Author Topic: Writes on the z80  (Read 2887 times)

0 Members and 1 Guest are viewing this topic.

Offline fabiodlTopic starter

  • Frequent Contributor
  • **
  • Posts: 282
Writes on the z80
« on: January 04, 2021, 03:51:04 am »
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?
« Last Edit: January 04, 2021, 11:00:14 pm by fabiodl »
 

Offline m k

  • Super Contributor
  • ***
  • Posts: 1924
  • Country: fi
Re: Writes on the z80
« Reply #1 on: January 06, 2021, 04:17:13 pm »
Block transfer?
Advance-Aneng-Appa-AVO-Data Tech-Fluke-General Radio-H. W. Sullivan-Heathkit-HP-Kaise-Kyoritsu-Leeds & Northrup-Mastech-REO-Simpson-Sinclair-Tektronix-Triplett-YFE
(plus lesser brands from the work shop of the world)
 

Offline guenthert

  • Frequent Contributor
  • **
  • Posts: 706
  • Country: de
Re: Writes on the z80
« Reply #2 on: January 06, 2021, 06:25:37 pm »
Block transfer?
     Could you elaborate?   It's been a long time 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.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14297
  • Country: fr
Re: Writes on the z80
« Reply #3 on: January 06, 2021, 06:46:01 pm »
Block transfer?
     Could you elaborate?   It's been a long time 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.

Yes, it had LDI, LDIR, LDD and LDDR.

 

Offline emece67

  • Frequent Contributor
  • **
  • !
  • Posts: 614
  • Country: 00
Re: Writes on the z80
« Reply #4 on: January 06, 2021, 06:51:13 pm »
.
« Last Edit: August 19, 2022, 04:09:05 pm by emece67 »
 
The following users thanked this post: fabiodl

Offline guenthert

  • Frequent Contributor
  • **
  • Posts: 706
  • Country: de
Re: Writes on the z80
« Reply #5 on: January 06, 2021, 07:14:36 pm »
    Ah, I happily forgot those.  Thanks (i guess) for reminding me. :-DD
 

Offline fabiodlTopic starter

  • Frequent Contributor
  • **
  • Posts: 282
Re: Writes on the z80
« Reply #6 on: January 08, 2021, 08:27:15 am »
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.
« Last Edit: January 08, 2021, 08:29:56 am by fabiodl »
 

Offline jmelson

  • Super Contributor
  • ***
  • Posts: 2758
  • Country: us
Re: Writes on the z80
« Reply #7 on: January 12, 2021, 03:33:52 am »
LDDR and LDIR, if my memory serves me well, copy blocks of memory from a place to another. So they must perform write after read, after write...

EDIT: it is curious how the (brain) memory works. I haven't touched a Z80 since  ~30 years, but I still remember that the machine code for the LDIR instruction is 0xED, 0xB0.
There'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
 

Offline fabiodlTopic starter

  • Frequent Contributor
  • **
  • Posts: 282
Re: Writes on the z80
« Reply #8 on: January 12, 2021, 08:30:18 am »
I tried out every single instruction on the https://github.com/EisernSchild/t80 and there' s no such instruction.
Next step, is checking the real hw.
 

Offline emece67

  • Frequent Contributor
  • **
  • !
  • Posts: 614
  • Country: 00
Re: Writes on the z80
« Reply #9 on: January 12, 2021, 09:18:57 am »
.
« Last Edit: August 19, 2022, 04:09:16 pm by emece67 »
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14297
  • Country: fr
Re: Writes on the z80
« Reply #10 on: January 12, 2021, 05:25:52 pm »
I tried out every single instruction on the https://github.com/EisernSchild/t80 and there' s no such instruction.
Next step, is checking the real hw.

Not sure about what do you mean with this. All LDI/LDD/LDIR/LDDR and INIR/INDR/OTIR/OTDR do exist (as CPIR/CPDR & DJNZ). I've not used the t80 IP, but on its VHDL sources you can find all of them.

Yeah. 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.
 

Offline jmelson

  • Super Contributor
  • ***
  • Posts: 2758
  • Country: us
Re: Writes on the z80
« Reply #11 on: January 13, 2021, 12:21:03 am »
I tried out every single instruction on the https://github.com/EisernSchild/t80 and there' s no such instruction.
Next step, is checking the real hw.
Yes, 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
 

Offline gslick

  • Frequent Contributor
  • **
  • Posts: 579
  • Country: us
Re: Writes on the z80
« Reply #12 on: January 20, 2021, 03:13:00 am »
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.

At 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: [Select]
      141   0146   7E LD   A,[HL]            OPCODE FETCH     
      142   020F   0B   0B memory read       MEM READ         
      143   0147   47 LD   B,A               OPCODE FETCH     
      144   0148   E6 AND  FF                OPCODE FETCH     
      145   0149   FF   FF memory read       MEM READ         
      146   014A   28 JR   Z,0120            OPCODE FETCH     
      147   014B   D4   D4 memory read       MEM READ         
      148   014C   54 LD   D,H               OPCODE FETCH     
      149   014D   5D LD   E,L               OPCODE FETCH     
      150   014E   23 INC  HL                OPCODE FETCH     
      151   014F   0E LD   C,05              OPCODE FETCH     
      152   0150   05   05 memory read       MEM READ         
      153   0151   ED OTIR                   OPCODE FETCH     
      154   0152   B3   B3 opcode fetch      OPCODE FETCH     
      155   0210   02   02 memory read       MEM READ         
      156   0A05   02   02 i/o write         I/O WRITE       
      157   0151   ED OTIR                   OPCODE FETCH     
      158   0152   B3   B3 opcode fetch      OPCODE FETCH     
      159   0211   10   10 memory read       MEM READ         
      160   0905   10   10 i/o write         I/O WRITE       
      161   0151   ED OTIR                   OPCODE FETCH     
      162   0152   B3   B3 opcode fetch      OPCODE FETCH     
      163   0212   14   14 memory read       MEM READ         
      164   0805   14   14 i/o write         I/O WRITE       
      165   0151   ED OTIR                   OPCODE FETCH     
      166   0152   B3   B3 opcode fetch      OPCODE FETCH     
      167   0213   4C   4C memory read       MEM READ         
      168   0705   4C   4C i/o write         I/O WRITE       
      169   0151   ED OTIR                   OPCODE FETCH     
      170   0152   B3   B3 opcode fetch      OPCODE FETCH     
      171   0214   03   03 memory read       MEM READ         
      172   0605   03   03 i/o write         I/O WRITE       
      173   0151   ED OTIR                   OPCODE FETCH     
      174   0152   B3   B3 opcode fetch      OPCODE FETCH     
      175   0215   C1   C1 memory read       MEM READ         
      176   0505   C1   C1 i/o write         I/O WRITE       
      177   0151   ED OTIR                   OPCODE FETCH     
      178   0152   B3   B3 opcode fetch      OPCODE FETCH     
      179   0216   05   05 memory read       MEM READ         
      180   0405   05   05 i/o write         I/O WRITE       
      181   0151   ED OTIR                   OPCODE FETCH     
      182   0152   B3   B3 opcode fetch      OPCODE FETCH     
      183   0217   80   80 memory read       MEM READ         
      184   0305   80   80 i/o write         I/O WRITE       
      185   0151   ED OTIR                   OPCODE FETCH     
      186   0152   B3   B3 opcode fetch      OPCODE FETCH     
      187   0218   11   11 memory read       MEM READ         
      188   0205   11   11 i/o write         I/O WRITE       
      189   0151   ED OTIR                   OPCODE FETCH     
      190   0152   B3   B3 opcode fetch      OPCODE FETCH     
      191   0219   15   15 memory read       MEM READ         
      192   0105   15   15 i/o write         I/O WRITE       
      193   0151   ED OTIR                   OPCODE FETCH     
      194   0152   B3   B3 opcode fetch      OPCODE FETCH     
      195   021A   20   20 memory read       MEM READ         
      196   0005   20   20 i/o write         I/O WRITE       
      197   0153   62 LD   H,D               OPCODE FETCH     
      198   0154   6B LD   L,E               OPCODE FETCH     
      199   0155   46 LD   B,[HL]            OPCODE FETCH     
      200   020F   0B   0B memory read       MEM READ         
      201   0156   23 INC  HL                OPCODE FETCH     
      202   0157   0E LD   C,07              OPCODE FETCH     
      203   0158   07   07 memory read       MEM READ         
      204   0159   ED OTIR                   OPCODE FETCH     
      205   015A   B3   B3 opcode fetch      OPCODE FETCH     
      206   0210   02   02 memory read       MEM READ         
      207   0A07   02   02 i/o write         I/O WRITE       
      208   0159   ED OTIR                   OPCODE FETCH     
      209   015A   B3   B3 opcode fetch      OPCODE FETCH     
      210   0211   10   10 memory read       MEM READ         
      211   0907   10   10 i/o write         I/O WRITE       
      212   0159   ED OTIR                   OPCODE FETCH     
      213   015A   B3   B3 opcode fetch      OPCODE FETCH     
      214   0212   14   14 memory read       MEM READ         
      215   0807   14   14 i/o write         I/O WRITE       
      216   0159   ED OTIR                   OPCODE FETCH     
      217   015A   B3   B3 opcode fetch      OPCODE FETCH     
      218   0213   4C   4C memory read       MEM READ         
      219   0707   4C   4C i/o write         I/O WRITE       
      220   0159   ED OTIR                   OPCODE FETCH     
      221   015A   B3   B3 opcode fetch      OPCODE FETCH     
      222   0214   03   03 memory read       MEM READ         
      223   0607   03   03 i/o write         I/O WRITE       
      224   0159   ED OTIR                   OPCODE FETCH     
      225   015A   B3   B3 opcode fetch      OPCODE FETCH     
      226   0215   C1   C1 memory read       MEM READ         
      227   0507   C1   C1 i/o write         I/O WRITE       
      228   0159   ED OTIR                   OPCODE FETCH     
      229   015A   B3   B3 opcode fetch      OPCODE FETCH     
      230   0216   05   05 memory read       MEM READ         
      231   0407   05   05 i/o write         I/O WRITE       
      232   0159   ED OTIR                   OPCODE FETCH     
      233   015A   B3   B3 opcode fetch      OPCODE FETCH     
      234   0217   80   80 memory read       MEM READ         
      235   0307   80   80 i/o write         I/O WRITE       
      236   0159   ED OTIR                   OPCODE FETCH     
      237   015A   B3   B3 opcode fetch      OPCODE FETCH     
      238   0218   11   11 memory read       MEM READ         
      239   0207   11   11 i/o write         I/O WRITE       
      240   0159   ED OTIR                   OPCODE FETCH     
      241   015A   B3   B3 opcode fetch      OPCODE FETCH     
      242   0219   15   15 memory read       MEM READ         
      243   0107   15   15 i/o write         I/O WRITE       
      244   0159   ED OTIR                   OPCODE FETCH     
      245   015A   B3   B3 opcode fetch      OPCODE FETCH     
      246   021A   20   20 memory read       MEM READ         
      247   0007   20   20 i/o write         I/O WRITE       
 
The following users thanked this post: fabiodl

Offline fabiodlTopic starter

  • Frequent Contributor
  • **
  • Posts: 282
Re: Writes on the z80
« Reply #13 on: January 21, 2021, 10:20:15 am »
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
 

Offline bson

  • Supporter
  • ****
  • Posts: 2265
  • Country: us
Re: Writes on the z80
« Reply #14 on: April 13, 2021, 11:06:11 pm »
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.
This 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).
 
The following users thanked this post: fabiodl


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf