ABOUT Z80 - ABOUT NEW AND OLD
Register I contains the high byte of the table address
interrupt vectors. In IM2 mode on signals -IORQ & -M1 from
circuit that caused the interrupt, the low byte of the address is read (not
believe those who write about ignoring the least significant bit). Now by
the received address is read from memory two bytes of the address
transition to the interrupt handling routine (in Intel format:
LSB first, MSB next). On the computer
Spectrum theoretically should always read the lowest one from the bus
the vector byte is FFh. But in real life some ports
extensions (including proprietary ones) do not check the signal value
-RD and “respond” to such a request; as a result it may
any value is considered, which forces you to keep in full memory
table of transition vectors 257 bytes long, in which the most significant
bytes are equal to least significant.
And 257 identical bytes are set for the following reason. On ZX
Spectrum when reading the low byte of the interrupt vector address on
The data bus must be #FF. Then the interrupt vector itself will be
select at address (I*100h)+FF. But on some machines,
which the data bus is overloaded when fetching the low byte on
the bus is not #FF. Therefore, to transfer control
interrupt handler, it (the handler) is placed at the address
the low byte of whichis equal to the most significant one, and this byte is filled with
area from (I*100h)+00 to (I*100h)+100h inclusive. That is,
for example, if the handler starts from address #D9D9, and in the register
I - #F8, then the memory area from #F800 to #F900 inclusive
filled with code #D9. Then, if when reading the low byte
address of the vector, code XX will be read, then the vector is selected by
address (I*100h)+XX=#F8XX. And at address #F8XX lies the word #D9D9 then
there is a correct interrupt handler address.
The R register contains a full byte (8 bits), but is modified
when counting only the lowest 7 bits (this was enough for the issued
at that time dynamic RAM). And he counts regeneration cycles,
which follow one after each M1 cycle (prefix sampling
or operation code), confirmed by the signals -MRQ & -M1 & -RD.
It is worth noting that on some computers (including some
then from Spectrum+) M1 sampling cycles are delayed by one clock cycle (for
synchronization with video memory and more reliable reading).
Some “craftsmen” adapt the high bit to a flag
condition.
As for the R register - it is associated with regeneration
dynamic memory. On the Spectrum, regeneration is performed by the circuit
video controller when sampling from video memory. But in general the Z80 can
regenerate memory itself. To do this, during decoding and
execution of a command inside the processor on 7 lowbus bit
address, the contents of register R are supplied, the signal is activated
/RFSH and by the /RAS signal in a small-scale dynamic memory circuit
the memory elements of the line will be regenerated, address
which is installed on the address bus (7 low-order bits). Register R
is incremented after each M1 cycle, but not
The most significant bit is affected. So the Z80 itself, IMHO, can
perheputb memory up to 128*(number of memory elements in one line
small circuits of dynamic memory). For PYS this number is 256 (8
address legs), for RU7 - 512 (9 address legs). If the tires
it is controlled not by the processor, but by another device in the BUSRQ cycle, or
the processor is in wait clock cycles (WAIT), then the processor
does not perform regeneration.
If /WAIT is passive, then:
cycle M1 - 4 cycles;
reading/writing to memory - 3 cycles;
I/O - 4 cycles;
providing access to the bus - 3 cycles;
maskable interrupt confirmation - 6 clock cycles;
NMI confirmation - 5 cycles;
HALT - 4 beats.
The I/O cycle always contains 1 wait cycle, cycle
maskable interrupt confirmation - 2. This is done for
making it easier to work with external devices.
The Z80 processor has two flip-flops IFF1 and IFF2,used in interrupt processing logic. IFF1 value
used when determining the admissibility of a masked
interrupt, and IFF2 is read in place of the P/V flag by LD commands
A,I and LD A,R. The logic of their work is as follows:
situation │ IFF1 │ IFF2 │ note
────────────────┼──────┼──────┼─ ────────────────────────────────
-RESET signal │ 0 │ 0 │ IMO mode is set
────────────────┼──────┼──────┼─ ────────────────────────────────
DI command │ 0 │ 0 │ disables interrupts
────────────────┼──────┼──────┼─ ────────────────────────────────
command EI │ 1 │ 1 │ enables interrupts
────────────────┼──────┼──────┼─ ────────────────────────────────
signal -INT │ 0 │ 0 │ if IFF1 is reset - processing
│ │ │ maskable interrupt
────────────────┼──────┼──────┼─ ────────────────────────────────
command RETI │ IFF2 │ IFF2 │ return from masked
│ ? │ │ interrupts
────────────────┼──────┼──────┼─ ────────────────────────────────
signal -NMI │ 0 │ IFF1 │ non-maskable interrupt
────────────────┼──────┼──────┼─ ────────────────────────────────
command RETN │ IFF2 │ IFF2 │ return from non-maskable
│ │ │ interrupts
────────────────┼──────┼──────┼─ ────────────────────────────────
commands LD A,I │ IFF1 │ IFF2 │ P/V<= IFF2
LD A,R │ │ │
────────────────┴──────┴──────┴─ ────────────────────────────────
I'm not sure if IFF1 is restored by the RETI command,
but this does not really matter - the differences will only be when
processing a non-maskable interrupt, and there it is always at the output
RETI is used. In general, the RETI command differs from RET except
lengths only that are recognized by other circuits of the Z80 family
as a sign of the end of interrupt processing. Since in
there are no such chips on our computers - this command is not
use (set simple RET).
The interrupt analysis algorithm is quite simple, before
by sampling the first cycle of the next command, the state is checked
signal -RESET, then in priority order -NMI, and if
IFF1 and -INT are set with the appropriate response. HALT command
does not change this algorithm, but simply prohibits changing the counter
commands before exiting this state (with -RESET,
-NMI and with interrupts enabled and -INT).
The F flags byte contains the following bits:
7: S - sign
6: Z - zero
5:
4: H - auxiliary carry
3:
2: P/V - parity/overflow
1: N - subtraction
0: C - carry
Undocumented bits can also be used for
storing states or changing by separate commands, which
quite possiblyused in defenses. To get it right
setting this byte requires special research
the behavior of this register in all instructions (including
undocumented). Some of the documented commands are also
modifies the H or P/V and S flags in undescribed ways, and some
commands for working with ports: flags C, P/V, S and H. I
There have been claims that undescribed flags take
states of the corresponding bits of register A, options are possible...
Convenient for analyzing undocumented commands
use decoding tables of 16*16 cells. This will save
from the temptation to explore clearly invalid command mnemonics. Yes
there is a "hole" visible in the CBh prefix table (bit operations and shifts)
with codes 30h...37h. It contains variants of the SLI command,
which differs from SLA by setting the least significant bit of the operand to
unit. If you apply the index command prefixes at the same time
and bit operation, you can get commands like: DDh,CBh,nn,36h [
SLI (IX+nn) ].
In index command tables with prefixes DDh and FDh
operations with the lower or higher half of the index are possible
register (designated: LX, HX, LY and HY). Teams are built according to
analogies with operations on HL registers, for example:
codes │ assembly │ mnemonics
────────────┼────────── ─────────┼─────────────DDh,24h │ DEFB #DD │ INC HX
│ INC H │
────────────┼───────────────────┼─────────────
FDh,2Dh │ DEFB #FD │ DEC LY
│ DEC L │
────────────┼───────────────────┼─────────────
DDh,ЧCh │ DEFB #DD │ LD C,HX
│ LD C,H │
────────────┼───────────────────┼─────────────
DDh,26h,nn │ DEFB #DD │ LD HX,nn
│ LD H,nn │
────────────┼───────────────────┼─────────────
DDh,8Ch │ DEFB #DD │ ADC A,HX
│ ADC A,H │
────────────┴───────────────────┴─────────────
Ясно, что невозможна одновременная работа с разными
индексными регистрами [ LD HX,HY ] или с целым регистром и его
половиной [ LD LX,(IX+nn) ]. Что-то я слыхал о трудностях в
командах типа LD LX,HX, надо специально проверить.
Интересно применение префиксов DDh и FDh в командах
сдвига и сброса/установки бита, например:
коды │ мнемоника │ стандартные команды
────────────────┼───────────────────┼─────────────────────
DDh,CBh,nn,1Ah │ RR (IX+nn),D │ RR (IX+nn)
│ │ LD D,(IX+nn)
FDh,CBh,nn,EOh │ SET 4,(IY+nn),B │ SET4,(IY+nn)
│ │ LD B,(IY+nn)
────────────────┴──────────── ───────┴─────────────────────
It is clear that such short and fast commands could not
not to interest “all sorts of Gilberts from Gremlins.”
Ports make things easier: access to ALL ports on the Z80 processor
receives using 16-bit addresses. In 8080 sample commands
the high byte is set to the value from the accumulator,
other commands for working with ports are set as an address
port current contents of BC registers. In reality everything is simpler:
in 8080, with out 36, A was output to 3636;
for Z80A when out (36), and A is output to A*100h+36 when out
(c), and A is output to (BC).
When entering it is the same.
Share your thoughts about the article
No comments yet.