2012-05-15 5 views
1

Я пишу простой эмулятор GB (ничего себе, теперь это что-то новое, не так ли), так как я действительно делаю первые шаги в эму.Эмуляция: безусловные переходы и увеличение ПК с помощью циклов процессора

Я, похоже, не понимаю, как правильно реализовать цикл процессора и безусловные переходы.

Рассмотрим команду JP Nn (безусловный переход к адресу памяти указал,), как JP 1000h, если у меня есть основной цикл:

increment PC 
read opcode 
execute command 

Тогда после того, как опкод JP считаны и команда выполняется (прочитайте 1000h из памяти и установите PC = 1000h), ПК получает прирост и становится 1001h, что приводит к плохой эмуляции.

tl; dr Как вы эмулируете прыжки в эмуляторах, так что значение ПК остается верным, если у процессора есть петли, которые увеличивают число ПК?

+0

Вы посмотрели другие эмуляторы, чтобы увидеть различные подходы? –

ответ

0

ПК должен быть увеличен как «атомная» операция каждый раз, когда используется для возврата байта. Это означает немедленные операнды, а также коды операций.

В вашем примере ПК будет использоваться три раза, один раз для кода операции и дважды для двух байтов операнда. К тому моменту, когда процессор загрузил три байта и сможет загрузить ПК, ПК уже указывает на следующий код операции инструкции после второго операнда, но, поскольку на самом деле реализация инструкции перезагружает ПК, это не имеет значения ,

+0

Да, это объясняет логику целого «поэтапного ПК в середине цикла». Спасибо, сэр. Очень признателен. – joncys

+0

@joncys На самом деле, это то, как микропроцессоры работали внутри. (Современные микропроцессоры делают всевозможные вещи в наши дни, но все равно должны выставлять оригинальное поведение как абстракцию.) – Neil

+0

@Neil был специально разработан в первых спецификациях для этих типов ситуаций, или это стало «побочным эффектом» «(очень слабо используемый термин) проводки (аппаратного обеспечения), который оказался очень полезным? – joncys

0

Переместить increment PC в конец цикла и выполнить его условно в зависимости от кода операции?

+0

Ничего себе, это довольно неловко. Я не могу сделать это так, как вы предлагали, потому что я пишу более сложный интерпретатор, чем просто оператор переключения всех кодов операций, и даже в этом случае два оператора switch-case будут избыточными (необходимо проверить, была ли это команда JP 2-й раз). То, что я могу сделать, это иметь прирост ПК в середине цикла, таким образом, код операции считывается до INC PC - это решает проблему с прыжками, не нарушая ничего в текущей реализации цикла. Пожалуйста, обновите свой ответ, чтобы отразить это, чтобы я мог его принять. Спасибо за вашу помощь! – joncys

0

Я почти ничего не знаю о эмуляции, но на ум приходят два очевидных подхода.

  1. Вместо жесткого кодирования PC += 1 в основной цикл, пусть оценку, если каждый опкод возвращает следующее значение PC (или смещение, или флаг, говорящий ли увеличивать его, или и т.д.). Тогда разница между прыжками и другими кодами операций (их влияние на счетчик программ) определяется вместе со всем остальным о них.

  2. Зная, что основной контур всегда будет увеличивать число ПК на 1, просто выполните выполнение прыжков, установите ПК на target - 1, а не на target.

+0

Я думал об этих двух подходах, я просто знал, что в моей кишке должен быть классный способ решения этого для всех случаев. Мне пришло в голову, что вы можете поставить inc PC в середину цикла, прочитав ответ Оли. Спасибо за понимание, оценили. – joncys

+0

Для меня 1. «стильный» способ решения проблемы, а 2 - немного менее классный, но прагматичный и экономичный подход к набору текста.Я хотел бы, чтобы все, что определяется, каким образом выполняется код операции, инкапсулируется в одном определении для каждого кода операции; «PC + = 1» действительно ** - это то, что характерно для каждого кода операции, что подтверждается тем, что вы столкнулись с этой проблемой. Выполнение этого условно на основе кода операции означает, что ваша реализация кодов прыжка распространяется по нескольким местам, и если вы когда-либо добавляете еще один прыжок и забываете обновлять основной цикл, все идет не так. – Ben

+0

подход 2 обычно (большинство процессоров) не требует какой-либо регулировки, относительная ветвь предполагает, что pc был увеличен. Бесконечный цикл, инструкция, которая относится к нему self, представляет собой команду pc = pc-1, если, как известно, pc, как известно, один впереди или pc = pc -2, если известно, что он впереди. 1) требует, чтобы инструкция EVERY имела модификатор pc, гораздо более типизированную. 2) только странные случаи, если у них есть модификатор pc в реализации. Вместо * pc. вместо одного * pC++ замените это на * pc и несколько сотен pC++; линии? 1) не менее печатает. –

Смежные вопросы