Last active
October 13, 2024 15:09
-
-
Save drhelius/8497817 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MEMPTR, esoteric register of the ZiLOG Z80 CPU. | |
by Boo-boo (first and draft English translation by Vladimir Kladov) | |
As it is known, after the instruction BIT n,(HL) execution, bits 3 and 5 of the flag register become containing values that is not documented in the official documentation at all. Actually these bits are copied from the bits 11 and 13 of the internal register pair of Z80 CPU, which is used for 16-bit operations, and in most cases to handle addresses. This is usual practice for processors having 8-bits data bus working with 16-bits data. | |
It is not known why and how these bits of the internal buffer register are copied to the flags register though. At least Sean Young in the "Undocumented Z80 Documented" refers to that phenomenon (http://www.myquest.nl/z80undocumented/) and a bit more info can be found in the Z80 description of another "nocash" project (http://www.work.de/nocash/zxdocs.htm) where such register pair is called as MEMPTR. Unfortunately until now attemts to crack the algorithm setting the value of the MEMPTR by different processor instructions on base of knowning only two bits of those 16-bits register were not successful. | |
But miraculously in result of many experiments (based on the hyposesis that index addressing instructions initialize the MEMPTR always the same way) and also after the deep meditations under the results of these samples we have found that CPI instruction increments the MEMPTR by 1 whereas CPD instruction decrements it. Hence, decrementing the MEMPTR in the loop and monitoring borrow from the high bits having two known bits in the flag register, it is possible to determine unambigously 14 low bits of the MEMPTR and having these in our hands to say for sure on which rule MEMPTR is set after each instruction. | |
A list of instructions changing the MEMPTR is follow, together with the formula for new MEMPTR value. Here "rp" means register pair (16 bits register BC, DE, HL or SP - ?), and "INDEX" means register pair IX or IY. Instructions not listed below do not affect MEMPTR as it is found. All the CPU chips tested give the same results except KP1858BM1 and T34BM1 slices noted as "BM1" in the text. | |
==================================================================================== | |
LD A,(addr) | |
MEMPTR = addr + 1 | |
LD (addr),A | |
MEMPTR_low = (addr + 1) & #FF, MEMPTR_hi = A | |
Note for *BM1: MEMPTR_low = (addr + 1) & #FF, MEMPTR_hi = 0 | |
LD A,(rp) where rp -- BC or DE | |
MEMPTR = rp + 1 | |
LD (rp),A where rp -- BC or DE | |
MEMPTR_low = (rp + 1) & #FF, MEMPTR_hi = A | |
Note for *BM1: MEMPTR_low = (rp + 1) & #FF, MEMPTR_hi = 0 | |
LD (addr), rp | |
LD rp,(addr) | |
MEMPTR = addr + 1 | |
EX (SP),rp | |
MEMPTR = rp value after the operation | |
ADD/ADC/SBC rp1,rp2 | |
MEMPTR = rp1_before_operation + 1 | |
RLD/RRD | |
MEMPTR = HL + 1 | |
JR/DJNZ/RET/RETI/RST (jumping to addr) | |
MEMPTR = addr | |
JP(except JP rp)/CALL addr (even in case of conditional call/jp, independantly on condition satisfied or not) | |
MEMPTR = addr | |
IN A,(port) | |
MEMPTR = (A_before_operation << 8) + port + 1 | |
IN A,(C) | |
MEMPTR = BC + 1 | |
OUT (port),A | |
MEMPTR_low = (port + 1) & #FF, MEMPTR_hi = A | |
Note for *BM1: MEMPTR_low = (port + 1) & #FF, MEMPTR_hi = 0 | |
OUT (C),A | |
MEMPTR = BC + 1 | |
LDIR/LDDR | |
when BC == 1: MEMPTR is not changed | |
when BC <> 1: MEMPTR = PC + 1, where PC = instruction address | |
CPI | |
MEMPTR = MEMPTR + 1 | |
CPD | |
MEMPTR = MEMPTR - 1 | |
CPIR | |
when BC=1 or A=(HL): exactly as CPI | |
In other cases MEMPTR = PC + 1 on each step, where PC = instruction address. | |
Note* since at the last execution BC=1 or A=(HL), resulting MEMPTR = PC + 1 + 1 | |
(if there were not interrupts during the execution) | |
CPDR | |
when BC=1 or A=(HL): exactly as CPD | |
In other cases MEMPTR = PC + 1 on each step, where PC = instruction address. | |
Note* since at the last execution BC=1 or A=(HL), resulting MEMPTR = PC + 1 - 1 | |
(if there were not interrupts during the execution) | |
INI | |
MEMPTR = BC_before_decrementing_B + 1 | |
IND | |
MEMPTR = BC_before_decrementing_B - 1 | |
INIR | |
exactly as INI on each execution. | |
I.e. resulting MEMPTR = ((1 << 8) + C) + 1 | |
INDR | |
exactly as IND on each execution. | |
I.e. resulting MEMPTR = ((1 << 8) + C) - 1 | |
OUTI | |
MEMPTR = BC_after_decrementing_B + 1 | |
OUTD | |
MEMPTR = BC_after_decrementing_B - 1 | |
OTIR | |
exactly as OUTI on each execution. I.e. resulting MEMPTR = C + 1 | |
OTDR | |
exactly as OUTD on each execution. I.e. resulting MEMPTR = C - 1 | |
Any instruction with (INDEX+d): | |
MEMPTR = INDEX+d | |
Interrupt call to addr: | |
As usual CALL. I.e. MEMPTR = addr | |
==================================================================================== | |
What is the profit of which secret knowledge? First of all, it is possible now to program Z80 emulators supporting _all_ the undocumented pecularities of the CPU. In the second place the fact that on some Z80 clones MEMPTR register behaves a bit another adds a method of model checking. Seems very enough! | |
(c)2006, zx.pk.ru | |
Theoretical part: boo_boo, Vladimir Kladov | |
Testing real Z80 chips: Wlodek, CHRV, icebear, molodcov_alex, goodboy | |
This document is not mine, just posted it here for preservation and for my own reference.
I wasn't able to test this behavior in real hardware but is really interesting you cannot replicate the BM1 differences.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The BM1 specific behavior doesn't seem to work.
I tried testing two КР1858ВМ1 that I have along with other Z80 CPUs and clones, using following sequences of commands:
And as the result I get bits 5 and 3 set in the flags, just like on other Z80 CPUs. According to the document above, on these CPUs, MEMPTR_hi should be set to 0 after running LD (BC),A, and so if the documentation is correct, the flags register bits 5 and 3 would be 0 after running BIT 0,(HL)