Speccy - наш выбор!

Speccy - наш выбор! (http://zx-pk.ru/index.php)
-   Unsorted (http://zx-pk.ru/forumdisplay.php?f=13)
-   -   ZX Spectrum: аппаратная реализация на восьми микросхемах (http://zx-pk.ru/showthread.php?t=13747)

RabidRabbit 7th March 2011 21:49

Quote:

Originally Posted by Lisitsin (Post 364218)
Да ... AVR при выполнении SBC не влияет на Z при нулевом результате, а при ненулевом сбрасывает. А я и не знал.

Таки грамотно сделано - не надо запоминать состояние после предыдущего SUB...

Lisitsin 8th March 2011 13:01

Всё. Центральный процессор засбоил. Завтра пойду феном выпаивать.

Lisitsin 8th March 2011 18:55

1 Attachment(s)
Перепаял вручную. Всё нормально.
ADC16 чуть по-больше:

Higgins 8th March 2011 19:30

Quote:

Originally Posted by Lisitsin (Post 364500)
TRACE_ADC16_2.zip

Здесь тоже все прошли. Нужно смотреть еще дальше.

Lisitsin 9th March 2011 08:18

2 Attachment(s)
Здесь сразу и ADC и SBC: (пришлось частями, всё не лезет)

Higgins 9th March 2011 12:24

Quote:

Originally Posted by Lisitsin (Post 364601)
TRACE_ADC16_SBC16_PART1.zip

Попались на строке 66048. Вместо

Quote:

87ac 80ff 8000 fe91
имеем

Quote:

87ac 80ff 8000 fe91
то есть ошибочно взведен PF.

PF в ADC16/SBC16 считается так. Считается значение PF как для всех прочих арифметических операций, но только для старших половин результата, прежнего значения HL и операнда.

Далее делается следующее. Если сумма второго операнда (то, что добавляется) и CF вызывает переполнение (то есть, CF взведен и операнд был равен #FFFF или стал равен #0000 после сложения с CF), тогда результирующее значение PF меняется на обратное, то есть взводится если сброшен и наоборот.

Мы уже знаем, что ADC8 считается верно, значит правильно работающее вычисление PF для арифметических инструкций есть, и нужно только правильно применить его к ADC16/SBC16.

Lisitsin 9th March 2011 18:24

То есть правильно я понимаю?
OPH:OPL - операнд. Сначала делаю ADD L,OPL, ADC H,OPH. Затем запоминаю PF. Затем если в начале C=0 - то выхожу, а если C=1 - инкрементирую HL и проверяю C, и если этот самый С=1 - значит инвертирую PF?
А флаг С я считаю как С1 or С2, где С1 - флаг переполнеия при первом сложении (старших байт), а С2 - при возможном втором (если в начале С=1).
Премного благодарен за консультацию !!!

Higgins 9th March 2011 19:14

Quote:

Originally Posted by Lisitsin (Post 364721)
OPH:OPL - операнд. Сначала делаю ADD L,OPL, ADC H,OPH. Затем запоминаю PF. Затем если в начале C=0 - то выхожу, а если C=1 - инкрементирую HL и проверяю C, и если этот самый С=1 - значит инвертирую PF?
А флаг С я считаю как С1 or С2, где С1 - флаг переполнеия при первом сложении (старших байт), а С2 - при возможном втором (если в начале С=1).

Не совсем. PF нужно инвертировать не тот, который получился при сложении HL и OP, а тот, который получился при сложении HL, OP и CF. Получив его, мы смотрим на то, дает ли переполнение сложение OP и CF. Переполнение будет только если CF был взведен и OP=#FFFF. Так вот если это переполнение случилось, следует проинвертировать PF.

Не забудьте также, про случаи "ADC HL, HL" и "SBC HL, HL" -- эти инструкции модифицируют свои вторые операнды, но во время их исполнения OP (то есть, эти самые вторые операнды) должны рассматриваться равными значению HL до исполнения инструкций, как бы HL ни изменялся во время их исполнения.

Lisitsin 9th March 2011 20:00

Есть идея сделать так:
1. Прибавить к операнду изначалое значение С.
2. Запомнить флаги P1, C1, S1, V1 - после первой операции.
2. Прибавить к HL текущее значение операнда используя компнда ADD, ADC.
3. Запомнить флаги P2, C2, S2, V2 после второго действия.
4. Вычислить флаги P, C, S результата как P=(P1ORP2)XORC1, C=C1ORC2, S=S1ORS2, V=V1ORV2, Z вычислить проверкой HL на ноль.

Higgins 9th March 2011 21:12

Quote:

Originally Posted by Lisitsin (Post 364745)
Есть идея сделать так:
1. Прибавить к операнду изначалое значение С.
2. Запомнить флаги P1, C1, S1 - после первой операции.
2. Прибавить к HL текущее значение операнда используя компнда ADD, ADC.
3. Запомнить флаги P2, C2, S2 после второго действия.
4. Вычислить флаги P, C, S результата как P=P2XORC1, C=C1ORC2, S=S1ORS2, Z вычислить проверкой HL на ноль.
Правильно я думаю на этот раз?

Почти. :)

В терминах Z80, и если перекладывать на восьмиразрядные инструкции, инструкция "ADC HL, OP" эквивалентно следующему.

1) Прибавляем CF к OP:
Code:

LD A, OPL
ADC A, 0
LD OPL, A
LD A, OPH
ADC A, 0
LD OPH, A

Здесь запоминаем флаги CF1 и PF1.

Имеем в виду, что OP -- это временная копия операнда, а не сам этот регистр в правой части инструкции. То есть, сам регистр не модифицируем.

2) Прибавляем OP к HL:
Code:

LD A, L
ADD A, OPL
LD L, A
LD A, H
ADD A, OPH
LD H, A

3) Считаем PF. Он равен текущему PF (после "ADD A, OPH") в ксорке с PF1, то есть
Code:

PF = PF XOR PF1
4) Считаем CF. Он равен текущему CF (после той же инструкции) в дизъюнкции с CF1 -- как вы и написали, то есть
Code:

CF = CF OR CF1
5) Считаем ZF. Это, действительно, просто проверка HL на 0.

6) SF считать не нужно. Последняя инструкция его выставит сама.

7) А вот HF посчитать придется. То, что дает последняя инструкция будет правильным значением для инкрементированного операнда (если CF на входе взведен), а нам нужен HF для исходных операндов, то есть до инкремента.

8) MEMPTR = значение HL до исполнения.

9) Во флаги 3 и 5 копируем соответствующие разряды старшей половины резлуьтата (то есть H).


All times are GMT +4. The time now is 16:59.

Powered by vBulletin® Version 3.8.3
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.