Можно ли процедурно определить количество циклов, которые выполняет конкретная инструкция на 6502?

Большинство эмуляторов хранят количество циклов, которое выполняет конкретная инструкция, в таблице поиска, а затем при необходимости добавляют любые условные циклы (например, при пересечении границ страницы).

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

Чтобы привести пример, я заметил, что все инструкции, использующие немедленную или относительную адресацию, занимают 2 цикла.

Все инструкции с нулевой страницей занимают 3 такта, плюс еще 2 такта при изменении памяти на месте.

Все индексированные инструкции с нулевой страницей занимают 4 такта плюс еще 2 такта при изменении памяти на месте.

...И так далее.

Итак, есть ли какой-нибудь полностью задокументированный процедурный способ определения количества циклов для инструкции, подобной приведенной выше? Существуют ли исключения, которые нарушили бы детерминизм в такой формуле?


person w.brian    schedule 21.12.2016    source источник
comment
Мне всегда приходилось использовать ссылку типа набор инструкций 6502, чтобы получить точное время для старые периферийные устройства Atari 8-битной серии, которые вручную отправляли или принимали по одному биту за раз через последовательный интерфейс со скоростью 52 или 19 циклов на бит (1 МГц 6502). (~19 200 бит/сек или ~52 600 бит/сек).   -  person rcgldr    schedule 21.12.2016


Ответы (1)


Да — так и пишутся почти все точные эмуляторы*; см. такие документы, как 64doc.txt. Однако это ненамного сложнее, чем простой подсчет доступа к памяти — 6502 будет выполнять доступ к памяти каждый отдельный цикл, обычно он может получить значимый результат в течение оставшейся части цикла после доступа (т. е. я немного махаю руками, чтобы избежать обсуждение того, что конвейерно, а что нет; см. документацию).

Так, например. для ADC #54 процессор должен (i) прочитать код операции; (ii) прочитать операнд. Это два цикла.

Для ADC ($32), Y это:

  1. прочитать код операции
  2. читать операнд
  3. читать от $32, чтобы получить младший байт адреса
  4. прочитайте от $33, чтобы получить старший байт адреса, добавьте Y к младшему байту адреса
  5. читать из (старший байт адреса): (младший байт адреса + Y), так как было время только для выполнения вычисления младшего байта
  6. о, подождите, если был перенос, то последний результат был неправильным, лучше перечитайте еще раз. Если нет то отлично, все нормально, не заморачивайтесь с этим циклом.

Так что это либо 5, либо 6 циклов.

Вы всегда можете эмулировать доступ к памяти как пошаговую синхронизированную вещь и выполнять фактическую операцию как ортогональный шаг. Также легко использовать одну и ту же логику для чтения, записи или чтения-изменения-записи: операции чтения и записи имеют одинаковое время, но в конце выполняют разный доступ к памяти, все операции Tead-Modify-Write записывают прочитанное значение обратно в течение цикла. пока отрабатываете реальный результат, то и напишите реальный результат.

*) потому что одновременное выполнение всех обращений к памяти, не включая избыточных, приводит к небольшому сдвигу времени вперед, что абсолютно не похоже на реальное оборудование. И это сбивает вас с толку, как только доступ к памяти будет осуществляться с независимой концепцией времени — таймером или чем-то, что может генерировать прерывания, или просто самой ОЗУ, если машина сканирует ОЗУ для вывода видео; не берите в голову, что это требует от вас добавления особых случаев вокруг таких инструкций, как CLI и SEI**. Эмуляторы больше не должны быть структурированы так, как они были в 1990-х годах.

**) Статус IRQ выбирается в предпоследнем цикле каждой операции. CLI и SEI настраивают бит во время последнего цикла. Таким образом, даже если ожидается прерывание, CLI не приведет к прерыванию до тех пор, пока не будет выполнена инструкция после CLI. Что само по себе может быть SEI. Таким образом, пара CLI/SEI во время ожидания прерывания должна привести к обращению к обработчику прерывания после выполнения SEI с установленным флагом прерывания. Это происходит естественным образом, если вы эмулируете цикл за циклом поведение 6502, и имеет тенденцию быть огромным взломом, если вы работаете с операцией за операцией и деформацией времени. Или, что более вероятно, такие эмуляторы просто неправильно себя ведут.

person Tommy    schedule 21.12.2016
comment
Отличным ресурсом для наблюдения за всеми операциями чтения/записи из памяти, включая избыточные, является visual6502.org/. JSSim/index.html - person Matt G; 24.01.2017
comment
Кстати, это SEI, а не STI. - person Eight-Bit Guru; 06.04.2017
comment
@Eight-BitGuru, вот почему ты гуру! Прерывание SEt, а не прерывание SeT; исправлено. - person Tommy; 06.04.2017