Writes on the z80 - Page 1
Forum section: electronics / general

author: fabiodl
author_rank: Frequent Contributor
timestamp: January 04, 2021, 03:51:04 am
content: In a Z80 based system I am trying to develop a debugger that interrupts the program flow by inserting rst instructions on the bus. I want to do it at the beginning of an instruction, i.e. I do not want to modify later parts of multi-byte opcodes / parameters of the opcodes. Unless I solder additional wires (which I'd like to avoid) I have no access to M1.My idea is to detect writes, and replace the data on the bus on the fist read after a write.This holds correct only if there is no instruction that performs a read after a write. If I am not mistaken such instruction does not exist, but I may have overlooked some atypical case.Is there any (possibly undocumented) instruction that performs a memory read after a memory write, or can I be sure that no such instruction exists?

author: m k
author_rank: Super Contributor
timestamp: January 06, 2021, 04:17:13 pm
content: Block transfer?

author: guenthert
author_rank: Frequent Contributor
timestamp: January 06, 2021, 06:25:37 pm
content: Quote from: m k on January 06, 2021, 04:17:13 pmCould you elaborate? It's been alongtime since I programmed a Z80, but I'm unaware of block transfers on those. Perhaps later upward compatible eZ80 implemented such? The original Z80 had some loop construct (DJNZ, iirc), but no DMA or "string" operations.

author: SiliconWizard
author_rank: Super Contributor
timestamp: January 06, 2021, 06:46:01 pm
content: Quote from: guenthert on January 06, 2021, 06:25:37 pmYes, it had LDI, LDIR, LDD and LDDR.

author: emece67
author_rank: Frequent Contributor
timestamp: January 06, 2021, 06:51:13 pm
content: .

author: guenthert
author_rank: Frequent Contributor
timestamp: January 06, 2021, 07:14:36 pm
content: Ah, I happily forgot those. Thanks (i guess) for reminding me.

author: fabiodl
author_rank: Frequent Contributor
timestamp: January 08, 2021, 08:27:15 am
content: nice point. I believe the practical way they are done is by keeping the PC fixed. I believe they re-read the opcode any loop (at least on emulators, I have to try it on the real hw!) This means that if you steal the bus after, a single cycle is done you do not input "garbage" into the system.

author: jmelson
author_rank: Super Contributor
timestamp: January 12, 2021, 03:33:52 am
content: Quote from: emece67 on January 06, 2021, 06:51:13 pmThere's also INIR oad OUTIR in which you put a memory address in a 16-bit register, a count in another 16-bit register, and then the IN or OUT instruction would be repeated at successive memory addresses. This could be used to rapidly read or write a series of bytes from/to an I/O device. (I think there were also decrement versions that would go through memory in reverse order, INDR and OUTDR.) I used these in a SASI disk adaptor and in some other special devices that needed a string of bytes transferred. You could get at least half a megabyte/second data transfer, I think.Jon

author: fabiodl
author_rank: Frequent Contributor
timestamp: January 12, 2021, 08:30:18 am
content: I tried out every single instruction on thehttps://github.com/EisernSchild/t80and there' s no such instruction.Next step, is checking the real hw.

author: emece67
author_rank: Frequent Contributor
timestamp: January 12, 2021, 09:18:57 am
content: .

author: SiliconWizard
author_rank: Super Contributor
timestamp: January 12, 2021, 05:25:52 pm
content: Quote from: emece67 on January 12, 2021, 09:18:57 amYeah. I dunno avout T80 and have never used it, but those instructions are definitely part of the Z80 instruction set and were available on all Z80's.Just check any Z80 reference manual.

author: jmelson
author_rank: Super Contributor
timestamp: January 13, 2021, 12:21:03 am
content: Quote from: fabiodl on January 12, 2021, 08:30:18 amYes, I used a hackified assembler, and the mnemonics were 8080-based, not the Zilog-approved ones. I think the op-codes were :ED B2 for INIR and ED B3 for OUTIR, I got this from pp 62-63 of the Z-80 manual from Zilog.Jon

author: gslick
author_rank: Frequent Contributor
timestamp: January 20, 2021, 03:13:00 am
content: Quote from: fabiodl on January 08, 2021, 08:27:15 amAt least in the case of OTIR the opcodes are repeatedly fetched with M1 cycles while the loop count is being decremented.Here is an actual example logic analyzer state trace of a real Z80 loading the B register with the value 0x0B and then executing an OTIR instruction 11 times in a loop, where the OTIR 0xED/0xB3 opcodes are fetched again every time.(Columns are logic analyzer state #, address bus value (hex), data bus value (hex), Inverse Assembler decode).Code:141 0146 7E LD A, OPCODE FETCH142 020F 0B 0B memory read MEM READ143 0147 47 LD B,A OPCODE FETCH144 0148 E6 AND FF OPCODE FETCH145 0149 FF FF memory read MEM READ146 014A 28 JR Z,0120 OPCODE FETCH147 014B D4 D4 memory read MEM READ148 014C 54 LD D,H OPCODE FETCH149 014D 5D LD E,L OPCODE FETCH150 014E 23 INC HL OPCODE FETCH151 014F 0E LD C,05 OPCODE FETCH152 0150 05 05 memory read MEM READ153 0151 ED OTIR OPCODE FETCH154 0152 B3 B3 opcode fetch OPCODE FETCH155 0210 02 02 memory read MEM READ156 0A05 02 02 i/o write I/O WRITE157 0151 ED OTIR OPCODE FETCH158 0152 B3 B3 opcode fetch OPCODE FETCH159 0211 10 10 memory read MEM READ160 0905 10 10 i/o write I/O WRITE161 0151 ED OTIR OPCODE FETCH162 0152 B3 B3 opcode fetch OPCODE FETCH163 0212 14 14 memory read MEM READ164 0805 14 14 i/o write I/O WRITE165 0151 ED OTIR OPCODE FETCH166 0152 B3 B3 opcode fetch OPCODE FETCH167 0213 4C 4C memory read MEM READ168 0705 4C 4C i/o write I/O WRITE169 0151 ED OTIR OPCODE FETCH170 0152 B3 B3 opcode fetch OPCODE FETCH171 0214 03 03 memory read MEM READ172 0605 03 03 i/o write I/O WRITE173 0151 ED OTIR OPCODE FETCH174 0152 B3 B3 opcode fetch OPCODE FETCH175 0215 C1 C1 memory read MEM READ176 0505 C1 C1 i/o write I/O WRITE177 0151 ED OTIR OPCODE FETCH178 0152 B3 B3 opcode fetch OPCODE FETCH179 0216 05 05 memory read MEM READ180 0405 05 05 i/o write I/O WRITE181 0151 ED OTIR OPCODE FETCH182 0152 B3 B3 opcode fetch OPCODE FETCH183 0217 80 80 memory read MEM READ184 0305 80 80 i/o write I/O WRITE185 0151 ED OTIR OPCODE FETCH186 0152 B3 B3 opcode fetch OPCODE FETCH187 0218 11 11 memory read MEM READ188 0205 11 11 i/o write I/O WRITE189 0151 ED OTIR OPCODE FETCH190 0152 B3 B3 opcode fetch OPCODE FETCH191 0219 15 15 memory read MEM READ192 0105 15 15 i/o write I/O WRITE193 0151 ED OTIR OPCODE FETCH194 0152 B3 B3 opcode fetch OPCODE FETCH195 021A 20 20 memory read MEM READ196 0005 20 20 i/o write I/O WRITE197 0153 62 LD H,D OPCODE FETCH198 0154 6B LD L,E OPCODE FETCH199 0155 46 LD B, OPCODE FETCH200 020F 0B 0B memory read MEM READ201 0156 23 INC HL OPCODE FETCH202 0157 0E LD C,07 OPCODE FETCH203 0158 07 07 memory read MEM READ204 0159 ED OTIR OPCODE FETCH205 015A B3 B3 opcode fetch OPCODE FETCH206 0210 02 02 memory read MEM READ207 0A07 02 02 i/o write I/O WRITE208 0159 ED OTIR OPCODE FETCH209 015A B3 B3 opcode fetch OPCODE FETCH210 0211 10 10 memory read MEM READ211 0907 10 10 i/o write I/O WRITE212 0159 ED OTIR OPCODE FETCH213 015A B3 B3 opcode fetch OPCODE FETCH214 0212 14 14 memory read MEM READ215 0807 14 14 i/o write I/O WRITE216 0159 ED OTIR OPCODE FETCH217 015A B3 B3 opcode fetch OPCODE FETCH218 0213 4C 4C memory read MEM READ219 0707 4C 4C i/o write I/O WRITE220 0159 ED OTIR OPCODE FETCH221 015A B3 B3 opcode fetch OPCODE FETCH222 0214 03 03 memory read MEM READ223 0607 03 03 i/o write I/O WRITE224 0159 ED OTIR OPCODE FETCH225 015A B3 B3 opcode fetch OPCODE FETCH226 0215 C1 C1 memory read MEM READ227 0507 C1 C1 i/o write I/O WRITE228 0159 ED OTIR OPCODE FETCH229 015A B3 B3 opcode fetch OPCODE FETCH230 0216 05 05 memory read MEM READ231 0407 05 05 i/o write I/O WRITE232 0159 ED OTIR OPCODE FETCH233 015A B3 B3 opcode fetch OPCODE FETCH234 0217 80 80 memory read MEM READ235 0307 80 80 i/o write I/O WRITE236 0159 ED OTIR OPCODE FETCH237 015A B3 B3 opcode fetch OPCODE FETCH238 0218 11 11 memory read MEM READ239 0207 11 11 i/o write I/O WRITE240 0159 ED OTIR OPCODE FETCH241 015A B3 B3 opcode fetch OPCODE FETCH242 0219 15 15 memory read MEM READ243 0107 15 15 i/o write I/O WRITE244 0159 ED OTIR OPCODE FETCH245 015A B3 B3 opcode fetch OPCODE FETCH246 021A 20 20 memory read MEM READ247 0007 20 20 i/o write I/O WRITE

author: fabiodl
author_rank: Frequent Contributor
timestamp: January 21, 2021, 10:20:15 am
content: Thank you very much.I wrote a program that tests all opcodes (including the undocumented ones) and record the execution on a ‎Z84C0010AEG‎All the observed patterns are the following[('rd',),('rd', 'rd'),('rd', 'rd', 'rd'),('rd', 'rd', 'rd', 'rd'),('rd', 'rd', 'rd', 'rd', 'rd'),('rd', 'rd', 'rd', 'rd', 'rd', 'rd'),('rd', 'rd', 'rd', 'rd', 'rd', 'wr'),('rd', 'rd', 'rd', 'rd', 'wr'),('rd', 'rd', 'rd', 'rd', 'wr', 'wr'),('rd', 'rd', 'rd', 'wr'),('rd', 'rd', 'rd', 'wr', 'wr'),('rd', 'rd', 'wr'),('rd', 'rd', 'wr', 'wr'),('rd', 'wr'),('rd', 'wr', 'wr')]I attach the list of the instructions associated to each pattern

author: bson
author_rank: Unknown
timestamp: April 13, 2021, 11:06:11 pm
content: Quote from: fabiodl on January 08, 2021, 08:27:15 amThis is what I recall, as well, and this is what makes them interruptible - or more specifically, restartable.Normally, for things like hardware debugging NMI is (was) commonly used. But this of course assumes it's not used for something else, and the firmware can be changed to handle it (and maybe also differentiate between sources of it if it's already used for something other than debugging).