4

I'm trying just for the fun to design a more complex Z80 CP/M system with a lot of peripheral devices. When reading the documentation I stumbled over an (undocumented?) behaviour of the Z80 CPU, when accepting an interrupt in IM0.

When an interrupt occurs, the Z80 activates M1 and IORQ to signal the external device: "Hey, give me an opcode". All is well if the opcode is rst 00 or something like this. Now the documentation tells, ANY opcode of any command can be given to the cpu, for instance a CALL.

But now comes the undocumented part: "The first byte of a multi-byte instruction is read during the interrupt acknowledge cycle. Subsequent bytes are read in by a normal memory read sequence."

A "normal memory read sequence". How can I determine, if the CPU wants to get a byte from memory or instead the next byte from the device?

EDIT: I think, I found a (good?) solution: I can dectect the start of the interrupt acknowlegde cycle by analyzing IORQ and M1. Also I can detect the next "normal" opcode fetch by analyzing MREQ and M1. This way I can install a flip-flop triggered by these two ANDed signals, i.e. the flip-flop is 1 as long as the CPU reads data from the io-device. This 1 I can use to inhibit the bus drivers to and from the memory.

My intentions? I'm designing an interrupt controller with 8 prioritized inputs in a CPLD. It's registers hold a 16 bit address for each interrupt pin. Just for the fun :-)

Hennes
  • 1,340
  • 1
  • 10
  • 26
  • Looking up `IM 0` in my old Rodnay Zaks *Programming the Z80*, all he says is: "In this condition, the interrupting device may insert one instruction onto the data bus for execution, the first byte of which must occur during the interrupt acknowledge cycle." Dat didn't help much :) – Jongware Dec 07 '14 at 00:11
  • I read that as being able to only take a single byte from the device during the ack cycle. The CPU, being unaware of where the op-code came from, then does what it always does on loading a multi-byte operand and reads the rest from memory. – Mike Dec 07 '14 at 00:15
  • 1
    @Mike it appears from the application note at least to be smart enough not to adjust the PC during such a sequence. – Tommy Dec 07 '14 at 00:17
  • I'm happily surprised at the quality answers for such an old CPU here on SO - especially since it's also a very arcane corner of that CPU (I wonder if anyone actually ever used a multibyte instruction in IM0?). – Michael Burr Dec 07 '14 at 01:06

2 Answers2

6

My understanding is that the peripheral device is required:

  • to know how many bytes it needs to feed;
  • to respond to normal read cycles following the IORQ cycle; and
  • to arrange that whatever would normally respond to memory read cycles does not do so for the duration.

Also the behaviour was documented by Zilog in an application note, from which your quote originates (presumably uncredited).

In practice I guess 99.99% of IM0 users just use an RST and 99.99% of the rest use a known-size instruction like CALL xxxx.

(also I'm aware of a few micros that effectively guaranteed not to put anything onto the bus during an interrupt cycle, thereby turning IM0 into a synonym of IM1 owing to open collector output).

Tommy
  • 99,986
  • 12
  • 185
  • 204
  • Where do these extra bytes come from? The diagram in Zaks, in his section on interrupt handling, says "the PC is not incremented", so that confirms "the PC" (of the Z80) is out of the picture, and the peripheral device should read the host memory. – Jongware Dec 07 '14 at 00:24
  • 4
    My reading was that the CPU will continue performing read cycles, and the peripheral is meant to count them off via its own counter. I couldn't find a clear documentation of which address will be supplied for the read cycle. If the history helps, `IM0` is the 8080-compatible mode and the 8080 was designed to be interrupt compatible with the 8008 (and source compatible, but not binary compatible). So we're talking really primitive stuff. `IM1` and `IM2` are Zilog's attempt to do something a little more intelligent. – Tommy Dec 07 '14 at 00:28
  • Nice find on the app note. The quote in the question is also in the Z80 User Manual, but without much other detail (hence the question presumably). It looks like the key detail that isn't mentioned explicitly even in the app note is that there must be some external circuitry to prevent the normal memory devices from interfering with the read cycles for the OP codes bytes after the first. – Michael Burr Dec 07 '14 at 01:01
0

The interrupt behavior is reasonably documented in the Z80 manual: Interupt modes, IM2 allows you to supply an 8-bit address to a 16-bit pointer. At least halfway to the desired 16-bit direct address.

How to set the interrupt modes

My understanding is that the M1 + IORQ combination is used since there was no pin left for a dedicated interrupt response. A fun detail is also that the Zilog I/O chips like PIO, SIO, CTC reads the RETI instruction (as the CPU fetches it) to learn that the CPU is ready to accept another interrupt.

jmn
  • 1,254
  • 1
  • 8
  • 7
  • Hi, thanks for your posting, although nothing new. The question is: "How can I determine, if the CPU wants to get a byte from memory or instead the next byte from the device?" – Hennes Feb 02 '15 at 09:40
  • No problem, I just added a few pieces. – jmn Feb 02 '15 at 14:46
  • I assume the information in the original answer + app note was complete enough to feed the address bytes? Otherwise I can elaborate a bit on that too. – jmn Feb 02 '15 at 14:55