Как правило, когда у вас есть инструкция, вам нужно ее декодировать.Например, из вашей таблицы кодов операций:
if ((inst&0xF000)==0x1000)
{
write_register(pc,(inst&0x0FFF)<<1);
}
И предположим, что, поскольку вы обращаетесь к двум байтам на инструкцию, адрес, вероятно, является адресом слова (16 бит), а не байтовым адресом, поэтому я переместил его влево на один(вам нужно изучить, как кодируются эти инструкции, предоставленная вами таблица кодов операций не подходит для этого, ну, конечно, не нужно делать предположений).
Должно произойти намного больше, и я не знаю, смогу ли янаписал что-нибудь об этом в моих образцах github.Я рекомендую вам создать функцию выборки для извлечения инструкций по адресу, функцию чтения из памяти, функцию записи в память, функцию чтения из регистра, функцию записи из регистра.Я рекомендую вашу функцию декодирования и выполнения, декодирует и выполняет только одну инструкцию за раз.Обычное выполнение - просто вызывать его в цикле, оно дает возможность делать прерывания и тому подобное без особой дополнительной работы.Это также модулирует ваше решение.Путем создания функций fetch () read_mem_byte () read_mem_word () и т. Д.Вы модулируете свой код (с небольшими затратами производительности), что значительно упрощает отладку, поскольку у вас есть единственное место, где вы можете наблюдать за регистрами или обращениями к памяти и выяснять, что происходит или что не происходит.
На основе вашихВопрос, а где вы находитесь в этом процессе, я думаю, что первое, что вам нужно сделать перед написанием эмулятора, это написать дизассемблер.Быть набором инструкций фиксированной длины (16 бит), что делает его намного проще.Вы можете начать с какого-то интересного пункта в роме или с самого начала, если хотите, и расшифровать все, что видите.Например:
if ((inst&0xF000)==0x1000)
{
printf("jmp 0x%04X\n",(inst&0x0FFF)<<1);
}
Только с 35 инструкциями, которые не должны занимать, кроме дня, может быть, целой субботы, будучи вашими первыми инструкциями по расшифровке (я полагаю, что это основано на вашем вопросе).Дизассемблер становится основным декодером для вашего эмулятора.Замените printf () на эмуляцию, еще лучше оставьте printfs и просто добавьте код, чтобы эмулировать выполнение инструкции, чтобы вы могли следить за выполнением.(в той же сделке разберите одну функцию инструкции, вызывайте ее для каждой инструкции, это становится основой для вашего эмулятора).
Ваше понимание должно быть более чем расплывчатым в отношении того, что делает эта строка кода выборки, чтобы выполнить эту задачу, вы должны хорошо разбираться в манипулировании битами.
Также я бы назвал эту строку кода, которую вы предоставили, ошибочной или, по крайней мере, рискованной.Если memory [] является массивом байтов, компилятор может очень хорошо выполнить сдвиг влево с использованием математики размером в байты, в результате чего получается ноль, а затем нулевое значение со вторым байтом дает только второй байт.
В основномкомпилятор имеет право превратить это:
opcode = memory[pc] << 8) | memory[pc + 1];
В это:
opcode = memory[pc + 1];
Что совсем не работает, очень быстрое исправление:
opcode = memory[pc + 0];
opcode <<= 8;
opcode |= memory[pc + 1];
Избавит вас от головной боли.Минимальная оптимизация избавит компилятор от сохранения промежуточных результатов в оперативной памяти для каждой операции, что приведет к одинаковым (желаемым) результатам / производительности.
Симуляторы набора команд, которые я написал и упомянул выше, предназначены не для повышения производительности, а для удобства чтения, наглядности и, надеюсь, для обучения.Я бы начал с чего-то подобного, тогда, если производительность, например, представляет интерес, вам придется ее переписать.Этот эмулятор chip8, когда-то испытанный, будет задачей дня с нуля, поэтому, как только вы справитесь с этим в первый раз, вы можете переписать его, может быть, три или четыре раза в выходные, а не монументальное задание (чтобы переписать).(Большая часть одного заняла у меня выходные, по большей части. msp430 один, вероятно, больше походил на вечер или два, стоит работы. Правильно раз и навсегда установить флаг переполнения было самой большой задачей, и это произошло позже.).В любом случае, обратите внимание на такие вещи, как исходные коды, большинство, если не все, эти имитаторы набора команд рассчитаны на скорость выполнения, многие из них едва читаемы без достаточного количества изучения.Часто в большой степени управляемый таблицами, иногда много хитростей программирования на C и т. Д. Начните с чего-то управляемого, настройте его правильно, затем подумайте об улучшении его для скорости, размера, переносимости или чего-то еще.Эта микросхема выглядит как основанная на графике, поэтому вам также придется иметь дело с большим количеством рисования линий и другими битовыми манипуляциями на растровом изображении / экране / где угодно.Или вы можете просто вызвать API или функции операционной системы.По сути, этот чип 8 не является вашим традиционным набором инструкций с регистрами и перечнем режимов адресации и операций alu.