То есть флаг H в конечном итоге это флаг от суммы HL и операнда (послее шага суммирования их старших байтов) без учёта изначального С?
А про MEMPTR у Янга я читал, что он равен (HL+1), где HL берётся до операции.
Вид для печати
То есть флаг H в конечном итоге это флаг от суммы HL и операнда (послее шага суммирования их старших байтов) без учёта изначального С?
А про MEMPTR у Янга я читал, что он равен (HL+1), где HL берётся до операции.
С учетом. В Higgins Emulator есть такой простой макрос:
Так вот для ADC16 вычислить HF можно с помощью HF_ARI(r, a, b), приняв r=(HL+OP+CF)/#100, a=HL/#100 и b=OP/#100. Во всех случаях HL, OP и CF -- значения до исполнения.Код:#define HF_ARI(r, a, b) (((r) ^ (a) ^ (b)) & Z80_HF)
Правильно. Я ошибся, действительно берется значение (HL + 1).
Ничего не понимаю. С H в последнем моём вопросе я немного ошибся. Исправляю:Код:#define HF_ARI(r, a, b) (((r) ^ (a) ^ (b)) & Z80_HF)
1. Прибавить к операнду изначалое значение С.
2. Запомнить флаги P1, C1, H1 - после первой операции.
2. Прибавить к HL текущее значение операнда используя компнда ADD, ADC.
3. Запомнить флаги P2, C2, H2 после второго действия.
4. Вычислить флаги P, C, H результата как P=(P1ORP2)XORC1, C=C1ORC2, H=H1ORH2, Z вычислить проверкой HL на ноль.
То есть H взводится если он взводился хотя бы один раз - после первой операции сложения (старших байт) или же после второй операции сложения (старших байт).
(надо мне как нибудь на досуге С++ выучить ... :-) )
ADC16 PASSED !!!
А вот SBC16 по этому алгоритму не хочет ...
Шлю в приложении:
Вот здесь:
В ADC16 вы суммируете HL и CF и запоминаете флаги, а затем прибавляете получившееся к операнду и снова получаете нужные флаги, и это правильно. Это работает потому, что сложение коммутативно, и не имеет значения прибавлять ли CF к правому операнду и получить первую порцию флагов или прибавлять CF к левому и получить порцию флагов -- в любом случае последующее вычисление флагов даст правильный результат.Код:BST F,CC ; копируем бит С
BLD BUF,0 ; в младший разряд BUF
SUB ZL,BUF ; вычитаем флаг С, хранящийся в BUF
SBC ZH,ZERO ; к операнду (регистр ZERO==0 – всегда)
Когда речь идет о SBC16 (то есть, о вычитании), то отнимая CF из HL вы получаете не те флаги, которые нужны. Здесь важна последовательность вычислений: сначала нужно добавить CF к правому операнду (а не к HL) и получить порцию флагов, а уже затем из HL вычесть получившееся и вычислить результирующие флаги.
Сделел как во вложении, но всё равно failed:
Ой !!! не взвожу N !!!
Исправляюсь ...
PASSED !
Всё до SLL/SRL проходит (RLA/RRA исправил):
Готовлю. А эмулирую так:
Начало трейсинга для SLL:
Вижу ! Читаю флаги раньше последнего действия - установки младшего бита в 1. Исправляюсь ...
PASSED !!!
Дальше регистры R и I. Но с R дело сложное: я его обрабатываю в цикле M1 и во время трейсинга комментирую его инкремент и вместо него ставлю команду обращения к подпрограмме обработки трейсигна. BIT n,(HL) - пока не до конца прописан MEMPTR. На BIT n, (IX+D) Z80TESTS виснет. Может там копнуть?
Нормально. Можно сделать.
Добрый вечер, Higgins. Имеется ли настроение поработать? Готов запустить трейсинг с инкрементом R.
Есть. Немножко. Если нужно - сделаю больше.
Чуть по-больше:
"LD A, I" по #8842. При I=#3F после исполнения ошибочно F=#00 вместо правильного F=#28.
Как выставлять флаги: CF не меняем. В SF и флаги 3 и 5 копируем соответствующие разряды регистра I. Взводим ZF если I=#00, иначе ZF сбрасываем. В PF кладем IFF2.
Для "LD A, R" делаем в точности то же, но вместо I берем регистр R (все восемь его разрядов).
Весело. А у меня и IFF1 не формируется.
Действительно весело. Как же вы прерывания обрабатываете? :)
Тогда так:
1) Вводим два флажка IFF1, IFF2.
2) "RETN" копирует IFF2 в IFF1.
3) Про "LD A, I" и "LD A, R" уже сказано.
4) В начале обрабтки прерывания сбрасываем IFF1 и IFF2.
5) Прерывание обрабатываем если прерывания не запрещены и текущий такт от начала фрейма в пределах длительности сигнала ~INT. У меня это 32 такта.
6) Запрещенное прерывание означает, что либо IFF1 сброшен, либо была выборка одного из оп-кодов, после которых прерывания не должно быть, либо и то, и другое вместе.
7) "DI" сбрасывает IFF1 и IFF2.
8) "EI" взводит IFF1 и IFF2.
9) Оп-коды, после которых не должно быть прерываний: #DD (префикс для IX), #FB (инструкция "EI") и #FD (префикс для IY).
Что-то вроде бы сляпал, но failed:
Кстати, поздравляю с новым статусом !!!
скоро - будет вполне возможно заменять мегой реальный Z80 осталось только недокументированные инструкции потом добавить. получится платка переходник с смдшной AVR. и кстати потреблять помоему будет меньше. только не знаю как с нагрузочной способностью.
Z исправил. Failed:
Вижу две проблемы:
1) Инкрементировать следует только младшие семь разрядов R. Старший разряд остается неизменным.
При этом инструкция "LD R, A" загружает в R все восемь разрядов.
2) Инкрементировать R следует только в циклах выборки (fetch). Непосредственные операнды инструкций извлекаются обычными циклами чтения, которые не являются циклами выборки. например, в инструкции "LD HL, #nn" будет цикл выборки и два цикла чтения, итого R инкрементируем один раз.
Но: префиксы #CB и #ED, а также префиксы для IX/IY #DD и #FD читаются тоже циклами выборки, и значит каждый такой префикс увеличивает R.
Теперь смотрим в трейсинг. Ищем строки для PC=#8849. Эти строки отражают состояние после инструкции "LD A, R". Перед циклом тестирования R сбрасывается в ноль с помощью "LD R, A".
В первой такой строке у вас получается R=#4C. А должен быть R=#2C.
Вторая такая строка у вас говорит, что R=#DB (сразу замечаем перемену старшего разряда R, чего быть не должно). А должен быть R=#7F.
Значит, между циклами у вас R увеличивается на #DB - #4C = #8F = 143. А должен увеличиваться на #7F - #2C = #53 = 83. Итого 143 - 83 = 60 лишних циклов выборки. Для такого короткого кода (одна итерация тестирования) это очень много. Из этого я делаю вывод, что R у вас инкрементируется не только для циклов выборки.
Еще раз, кратко. Первая строка для PC=#8849 должна быть:
Вторая:Цитата:
8849 2c28
Третья:Цитата:
8849 7f29
Цитата:
8849 5200
А как LD R,A влияет на флаги?