Zilog Z80/Система команд/INI

Материал из Emuverse
Этот документ создан для Emuverse и распространяется на условиях лицензии CC-BY-SA-3.0.

Найденная в Интернете информация сильно отличается от официальных данных (особенно, в отношении флагов N и CY). Все сказанное ниже относится к блочным командам ввода-вывода INI/INIR/OUTI/OTIR и IND/INDR/OUTD/OTDR.

Флаги устанавливаются следующим образом:

  • S, Z, F5, F3 из декремента B (официально — S неизвестен; информация по Z совпадает);
  • N — копия 7-го бита значения, полученного/переданного в порт (по официальным данным равен 1);

Далее для получения CY (официально — не меняется) и HC (официально — неизвестен):

  1. Прибавить к значению регистра C единицу, если инструкция увеличивала HL, иначе отнять единицу;
  2. Добавить к этому значению байт, полученный или переданный в порт;
  3. Скопировать признак переноса этой операции во флаги CY и HY (то есть они будут одинаковые).

PV (официально — неизвестен) зависит от значения регистров B, C и переданного байта (по информации Pedro Gimeno (pgimeno@geocities.com)):

Для INI/INIR/OUTI/OTIR

1. Вычисление первой промежуточной переменной Temp1(С.1 обозначает 1-й бит регистра и т. д., inp — переданный байт):

C.1 C.0 inp.1 inp.0 Temp1
0 0 0 0 0
0 0 0 1 0
0 0 1 0 1
0 0 1 1 0
0 1 0 0 0
0 1 0 1 1
0 1 1 0 0
0 1 1 1 1
1 0 0 0 1
1 0 0 1 0
1 0 1 0 1
1 0 1 1 1
1 1 0 0 0
1 1 0 1 1
1 1 1 0 1
1 1 1 1 0

2. Вычисление второй промежуточной переменной:

Если (B AND 0xF = 0) то
      Temp2 = Parity(B) XOR (B.4 OR (B.6 AND NOT B.5))
иначе
      Temp2 = Parity(B) XOR (B.0 OR (B.2 AND NOT B.1))

где Parity - обычная операция вычисления четности

Реально данную операцию проще выполнять по таблице:

    0123456789ABCDEF <- (нижний полубайт B)
00  0011010011001011
10  0100101100110100
20  1100101100110100
30  1011010011001011
40  0100101100110100
50  1011010011001011
60  0011010011001011
70  0100101100110100
80  1100101100110100
90  1011010011001011
A0  0011010011001011
B0  0100101100110100
C0  1011010011001011
D0  0100101100110100
E0  1100101100110100
F0  1011010011001011
^
(Верхний полубайт B)

Тогда PV = Temp1 XOR Temp2 XOR C.2 XOR inp.2

IND/INDR/OUTD/OTDR

Аналогично INI, только отличается первая таблица:

C.1 C.0 inp.1 inp.0 Temp1
0 0 0 0 0
0 0 0 1 1
0 0 1 0 0
0 0 1 1 0
0 1 0 0 1
0 1 0 1 0
0 1 1 0 0
0 1 1 1 1
1 0 0 0 0
1 0 0 1 0
1 0 1 0 1
1 0 1 1 0
1 1 0 0 0
1 1 0 1 1
1 1 1 0 0
1 1 1 1 1