зря пылитсяСообщение от Shiru
а у меня нет никаких оснований полагать что он отличается от CMOS ядра Z84C00xx, которое конечно отличается от NMOS ядра, но не так же сильно
зря пылитсяСообщение от Shiru
а у меня нет никаких оснований полагать что он отличается от CMOS ядра Z84C00xx, которое конечно отличается от NMOS ядра, но не так же сильно
да, извините.Сообщение от Shiru
это я с защитой от отладки стсом попутал.
имхо отличается, там внутренние порты есть. надо шиты читать...Сообщение от Shiru
Про его порты я знаю, а вот 100%-ли там совместимость в плане команд и прочего - нет.Сообщение от jtn
насчет битов 5 и 3 не совсем верно. туда копируются не биты аккумулятора, а биты того регистра, над которым совершается операция. логическая или арифметическая. чаще всего (и по умолчанию, если регистр не определен) это именно аккумулятор.
вот что мне подсказали по этому поводу в конференции фидо.
2) Undocumented flag affection & operation [5][3]
-------------------------------------------------
2.1) Flag register bits [5][3]
The F (flag) register has the following bits:
F 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
-----------+-----+------+-----+-----+-----+-----+-----
flag S | Z | 5 | H | 3 | P/V | N | C
S flag:
set if the 2-complement value is negative. It's simply a copy of the most
significant bit.
Z flag:
Set if the value is zero.
5 flag:
A copy of bit 5 of the result.
H flag:
The half-carry of an addition/subtraction (from bit 3 to 4). Needed for
DAA correction.
3 flag:
A copy of bit 3 of the result.
P/V flag:
This flag can either be the parity of the result, or the 2-compliment
signed overflow (2-compliment value doesn't fit in the register).
N flag:
Shows whether the last operation was an addition (0) or an subtraction
(1).
This information is needed for DAA.
C flag:
The carry flag, set if there was a carry after the most significant bit.
In this part, the following notation is used for flag affection:
* indicates the effect is non-standard (see the notes).
0 indicates the flag is reset.
1 indicates the flag is set.
- indicates the flag is not affected.
S,Z,5,H,3,P,V,N,C indicate the flag is set as above.
Notice there's no ``unknown'' or ``undefined'' here.
2.2) All instructions that affect the flags [1][2][3]
This section lists all the instructions that affect the flags, and how they
do that.
2.2.1) 8 Bit arithmetic and logical
The 8 bit arithmetic group is straightforward:
ADD/ADC/SUB/SBC SZ5H3VNC
All standard flags ..
CP r SZ*H*VNC
A CP is simply a SUB with the result thrown away. Flag 5 and 3 are copied
from the operand, not the result (which is thrown away anyways).
INC/DEC r SZ5H3VN-
AND r SZ513P00
OR/XOR r SZ503P00
RLCA/RLA/RRCA/RRA --503-0C
RLC/RL/RRC/RR r SZ503P0C
SLA/SLL/SRA/SRL r SZ503P0C SLL is like SLA except bit 0 gets set
RRD/RLD SZ503P0- Flags set on result in A
2.2.2) 16 Bit arithmetic
The 16 bit additions are a bit more complicated. 16 bit additions are done
in
two stages: first the lower bytes are added, then the two higher bytes. The
S,5,H,3 flags are affected as by the second 8 bit addition. Z is set if the
whole 16 bit result is 0.
ADD s --***-0C
ADC/SBC s SZ***VNC
2.2.3) BIT instruction [5] [6]
BIT n,r *Z513*0- r is one of the 8 bit registers.
BIT behaves much AND r,2^n with the result throw away and the C flag is
unaffected. So in effect:
Z = set if the tested bit is reset.
S = set if n=7 and tested bit is set.
5 = set if n=5 and tested bit is set.
3 = set if n=3 and tested bit is set.
P/V = set like Z.
BIT n,(IX/IY+d) *Z*1**0-
Again, P/V is set like Z and S is if set n=7 and the tested bit is set. But
the 5 and 3 flags are different: they are a copy of bit 5 and 3 of the high
byte of IX/IY+d (the value after the addition of d to IX or IY).
BIT n,(HL) *Z*1**0-
P/V, Z, S set as the other BIT instructions, but the 5 and 3 flags are
different. Okay, brace yourself. They are a copy of an internal register of
the Z80, which is set as follows:
ADD HL,xx (use high byte of HL, i.e. H, before the addition)
LD r,(IX/IY+d) (use high byte of the resulting address IX/IY+d)
JR d (use high byte target address of the jump)
LD r,r' (not affected)
others not tested -- any additions welcome!
2.2.4) Other non-block instructions [2] [5]
CCF --***-0*
C=1-C, H as old C. 5, 3 from A register
SCF --*0*-01
CPL --*1*-1-
5, 3 from A register.
NEG SZ5H3V1C
DAA SZ5*3P-*
See below (2.3) for more information.
LD A,R/LD A,I SZ503*0-
P/V contains a copy of IFF2.
IN r,(C) SZ503P0-
Also true for IN F,(C) / IN (C).
2.2.5) Memory block instructions [2] [5]
LDI/LDIR/LDD/LDDR --*0**0- P/V set if BC not 0
5 is bit 1 of (transferred byte + A)
3 is bit 3 of (transferred byte + A)
So add A to the (last) transferred byte (from (HL)), and bit 1 of that
8 bit value is flag 5, and bit 3 is flag 3.
CPI/CPIR/CPD/CPDR SZ*H**1- P/V set if BC not 0
S,Z,H from (A - (HL) ) as in CP (HL)
3 is bit 3 of (A - (HL) - H)
5 is bit 1 of (A - (HL) - H)
CPI instructions are weird too. The test is simply like a CP (HL). Flag 3
and
5 are set like this: Take A, subtract the last (HL), and then decrease it
with 1 if the H flag was set (/after/ the CP). Bit 1 of this value is flag
5, bit 3 is flag 3.
2.2.6) I/O Block instructions [5] [6]
INI/INIR/IND/INDR SZ5*3*** Flags affected as in DEC B
OUTI/OTIR/OUTD/OTDR SZ5*3*** Flags affected as in DEC B
Another weird one. S,Z,5,3 are affected by the decrease of B, like in DEC B.
The N flag is a copy of bit 7 of the last value read from/written too the
I/O port. The C and H flag is set as follows: Take register C, add one to it
if the instruction increases HL otherwise decrease it by one. Now, add the
the value of the I/O port (read or written) to it, and the carry of this
last addition is copied to the C and H flag (so C and H flag are the same).
Beats me, but tests show it to be true.
Pedro Gimeno ({[email protected]}) has figured out how the P/V flag is
affected. The result depends on the B register, the lower 3 bits of the C
register and the lower 3 bits of the value from the I/O port. This next part
is written by him. Whatever he says about INI/INIR is true for OUTI/OTIR,
and what he says about IND/INDR is true for OUTD/OTDR.
I use the notation C.2 to mean bit 2 of C. "inp" is the byte being
input.
First, look at bits 1 and 0 of both C and inp and look up this table to
obtain a temporary result:
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
You'll need also an additional temporary result which depends on B (all
of its bits), according to the following pseudocode:
If B.3 = B.2 = B.1 = B.0 = 0 then [i.e. if B and 0Fh = 0 then]
let Temp2 = Parity(B) xor (B.4 or (B.6 and not B.5))
else
let Temp2 = Parity(B) xor (B.0 or (B.2 and not B.1))
where Parity(B) is defined as not (B.0 xor B.1 xor B.2 xor B.3 xor B.4
xor B.5 xor B.6 xor B.7), i.e. 1 if B has an even number of bits = 1,
and 0 otherwise (the usual parity function).
Note that I obtained the operation (B.0 or (B.2 and not B.1)) from the
next table using Karnaugh maps:
B.2 through B.0 000 001 010 011 100 101 110 111
Value 0 1 0 1 1 1 0 1
For completeness here's the full table of values of Temp2 according to
B:
0123456789ABCDEF <- (low nibble)
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
^
(high nibble)
And finally, the value of the P/V flag is:
P/V = Temp1 xor Temp2 xor C.2 xor inp.2
IND / INDR:
The operations to obtain the P/V flag are the same as for INI/INIR but
the table used to lookup Temp1 is different:
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
2.3) Undocumented operation [1][5]
2.3.1) DAA [4] [5]
This instruction is useful when you're using BCD values. After an addition
or subtraction, DAA makes the correction so the value is the correct BCD
value again.
The correction done is as in the following table [4]:
N | C | high | H | low | # added | C after
| | nibble | | nibble | to A | execution
--+---+--------+---+--------+---------+-----------
add, adc, inc operands:
0 0 0-9 0 0-9 00 0
0 0-8 0 a-f 06 0
0 0-9 1 0-3 06 0
0 a-f 0 0-9 60 1
0 9-f 0 a-f 66 1
0 a-f 1 0-3 66 1
1 0-2 0 0-9 60 1
1 0-2 0 a-f 66 1
1 0-3 1 0-3 66 1
-------------------------------------------------
sub, sbc, dec, neg operands:
1 0 0-9 0 0-9 00 0
0 0-8 1 6-f fa 0
1 7-f 0 0-9 a0 1
1 6-f 1 6-f 9a 1
This table is all I know about DAA operation.
Emulator builders: this instruction is hard to emulate. The Intel 80x86
equivalents are more or less the same, but differ for some input values
(not in the table?). If you're not using assembly, the best way IMHO is
to put all possible output values (for A and F registers) in a table. The
output depends on the following inputs: A register and H,N,C flags. That's
11 bits in total, so the table will have size: 2^11*2 = 4096 bytes, which
isn't too bad.
ну порты и ядро - большая разница. да и в шитах такие весчи (недокументированные) не пишут.Сообщение от jtn
ну да, результата. а то ту все про аккумулятор, а флаги-то в соответствии с результатом выставляются. даже проверил, ld h,#07:inc h - 3 бит устанавливается.Сообщение от Vitamin
Ого, сколько всего. Всем спасибо за подробную информацию
Всё зависит от того, на сколько ты хочешь сделать эмулятор точной копией Z80 !!! Вообще-то у половины команд на Z80 нет точной логики в установке флагов ... Я, конечно, не имею в виду команды простых логических операций, хотя и там есть приколы ...Сообщение от Shiru
У каждой комманды чуть-ли не трёхэтажная логика работы с битами ... Я предполагаю это сделано в качестве защиты от копирования процессоров, поскольку я не один раз убеждался что в аналогах Zilog'а просто по-другому работают многие биты не говоря уже о советских монстрах типа ВМ80 ...
Я делал свой эмулятор и у меня есть ооооочень точное описание каждого бита флага на каждую команду ... Хотя мой эмулятор не доделан и там где-то есть глючёк, но за-то флаги он эмулирует очень точно ... Самая мощная команда это была INI, я пока выявил зависимость флагов от значений регистров чуть не умер, кроме всего на флаги влияют значение на входе порта ... А с помощью комманды LDI можно, например, XOR'ить ...
Вообщем, если нужно могу помочь с отдельными командами ... Многие мои записи в бумажном виде, ну или в виде АСМА на ПиЦи, могу поделиться любой ...
AAA когда меня режут, я терплю, но когда дополняют, становится нестерпимо.
Ты что, значения undefined бит выявлял что-ли? 8)Сообщение от Robus
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)