Uncovering the R800

By Grauw

Enlighted (7525)

Grauw's picture

06-12-2018, 21:22

Very little is known about the turboR’s R800.

For the R800, it is said it is part of the Z800 and Z280 family, but what this means exactly is unclear. It’s known that there are differences in the instruction set, but there is very little actual information.

Additionally if one inspects the pinout of the R800 one can see DMA-related pins, as well as the MA13-MA23 pins which could suggest the presence of an MMU with 8K pages as well, and 8 interrupt signals. Even if not connected (like the DMA pins are in the turboR), how are these functions accessed?

In this thread I hope we can perhaps discover some new things. I did some research which I will post below, and hopefully it can spark some discussion and further investigation.

Login or register to post comments

By Grauw

Enlighted (7525)

Grauw's picture

07-12-2018, 00:53

The R800 instruction timing is pretty well-documented. However the processor’s capabilities leave much unknown. Let’s start off with the claims that it’s derived from the Z800.

Wikipedia mentions that the Z800 was rebranded Z280, and if we compare the Z280 technical manual with the Z800 information in Zilog’s 1983/84 components databook (p. 599 and onward) this seems to be correct. So here we have quite documentation. Maybe this can aid our understanding of the R800.

The Z280 has DMA functions, an MMU with 4K pages, and eight trap interrupts for amongst others stack overflow protection, breakpoints and memory protection. I see similarities to those R800 pins mentioned earlier.

The opcodes of MULUB and MULUW also match the Z280 opcodes for MULTU and MULTUW. So there is indeed upward compatibility, unlike the Z180 and eZ80.

Unfortunately I can break your dreams right now; I did some tests, and I was not able to execute any of the other Z280 instructions on the R800. Looks like if the R800 was based on the Z800, it was severely stripped.

I tested all the undocumented op-codes in the DD and ED ranges, results below.

CB range:

The undocumented opcodes for CB 30-37 seem to have the same function as SLA (CB 20-27). If these are considered as the logical complement of SRA & SRL, an undocumented instruction called SLL, this makes sense since a logical and arithmetic left shift are the same thing.

This is unlike the Z80, where these shift a 1 into the right bit. This undocumented Z80 instruction is often also referred to as SLL, but does not behave like a logical left shift.

This is also unlike the Z280, which uses this range for a “TSET” (test-and-set) instruction which tests a bit and then sets the value to FFH.

DD range:

All undocumented opcodes have a length of 2, with no visible effect on AF, BC, DE, HL, IX or IY, and thus likely are a no-op. Specifically these are:

00-08, 0A-18, 1A-20, 27-28, 2F-33, 37-38, 3A-43, 47-4B, 4F-53, 57-5B, 5F, 76, 78-7B, 7F-83, 87-8B, 8F-93, 97-9B, 9F-A3, A7-AB, AF-B3, B7-BB, BF-CA, CC-E0, E2, E4, E6-E8, EA-F8, FA-FF

This is unlike the Z80, where many of these behave like their un-prefixed counterparts (a slower version of it).

DD CB range:

All undocumented opcodes have a length of 4, with no visible effect on AF, BC, DE, HL, IX or IY, and thus likely are a no-op.

This is unlike the Z80 too, where the undocumented variants store the operated value in a register.

ED range:

Most undocumented opcodes have a length of 2, with no visible effect on AF, BC, DE, HL, IX or IY, and thus likely are a no-op. Specifically these are:

00-3F, 4C, 4E, 54-55, 5C-5D, 64-66, 6C, 74-77, 7C-81, 83-89, 8B-91, 93-99, 9B-9F, A4-A7, AC-AF, B4-B7, BC-C0, C2, C4-C8, CA, CC-D0, D2, D4-D8, DA, DC-E0, E2, E4-D8, EA, EC-F0, F2, F4-D8, FA, FC-FF

However this range has some interesting exceptions:

ED E1 (MULUB A,H)
ED E9 (MULUB A,L)
ED F9 (MULUB A,A)

Although the R800 instruction tables found in amongst others the R800 Technical Handbook state that MULUB only works for B, C, D and E, in my tests these also seem to work fine for H, L and A. I have not tested all possible input values though, so this should be verified. But LD A,11H / MULUB A,A yields 0121H as expected, and H=55H -> 05A5H / L=66H -> 06C6H for the other two.

ED F1

This one has the same output as ED F9 (MULUB A,A), so it does not read (hl) as the register bits of the opcode (bits 3-5) would suggest.

ED D3
ED E3

These correspond to the DE and HL variants of the MULUW instruction. The technical handbook says these do not work, and indeed this seems to be the case, since the output is not the multiplication of the values I input.

They both yield the same result, and it changes when the input values do; it would be interesting to try with many different values and derive what is happening here exactly, to see if it is somehow useful or at least to improve emulation.

ED CB
ED DB
ED EB
ED FB

These yield the same results as the above ED D3 and ED E3. Although they are not specified as part of the MULUW opcode range, since the 16-bit register bits are set in bits 4-5. However if the decoder of this instruction actually looks at bits 3-5, it could be that it’s processed by the multiplication unit as well.

ED 6B nn nn

This opcode has a length of 4 and changes HL to 6B6BH no matter what value I specify in nn nn.

On Z80 this is LD HL,(nn), a slower version of 2A nn nn, part of the LD rr,(nn) series.

I think maybe this is a broken instruction? Further investigation is needed.

ED 63 nn nn

This instruction has a length of 4 and does not modify any registers.

It may be the LD (nn),HL counterpart of ED 6B, in which case perhaps it writes HL to address 6363H? I haven’t tested this.

ED 82 xx
ED 8A xx
ED 92 xx
ED 9A xx

These instructions have a length of 3 and do not modify any registers. I don’t know what they do.

I did observe some strange behaviour; infrequently they seem to have a length of 2 and the opcode in the place of xx is executed. Maybe this is a problem with my test program, or maybe they do not like it if an interrupt or refresh occurs in the middle of the instruction? Just a theory.

Further investigation is needed.

ED 71 xx nn nn

This instruction has a length of 5 and modifies DE. The value of DE seems to be specified in the bytes nn nn. I don’t know what xx does.

Here too I have observed that strange behaviour where infrequently the opcode in the place of xx is executed. I think I recall if xx is a 2-opcode instruction like LD A,n, then the value of n is fetched from the byte after nn nn (I tried this yesterday so I’m not 100% sure now).

This is by the way where the undocumented “OUT (C),0” Z80 instruction is located.

Further investigation is needed.

Especially those last few op-codes are interesting. I’m wondering if perhaps they allow access to R800 on-chip functions like an MMU.

By Grauw

Enlighted (7525)

Grauw's picture

06-12-2018, 21:33

And here is my test program:

100 AF=&H11FF
110 BC=&H2208
120 DE=&H3344
130 HL=&H5566
140 IX=&H7788
150 IY=&H99AA
160 '
170 GOSUB 390:PRINT
180 '
190 POKE &HD000,AF AND 255:POKE &HD001,(AF AND &HFF00) \ 256 AND 255
200 POKE &HD002,BC AND 255:POKE &HD003,(BC AND &HFF00) \ 256 AND 255
210 POKE &HD004,DE AND 255:POKE &HD005,(DE AND &HFF00) \ 256 AND 255
220 POKE &HD006,HL AND 255:POKE &HD007,(HL AND &HFF00) \ 256 AND 255
230 POKE &HD008,IX AND 255:POKE &HD009,(IX AND &HFF00) \ 256 AND 255
240 POKE &HD00A,IY AND 255:POKE &HD00B,(IY AND &HFF00) \ 256 AND 255
250 '
260 AD=&HC000
270 READ B:IF B<>-1 THEN POKE AD,B:AD=AD+1:GOTO 270
280 DEFUSR=&HC000:U=USR(0)
290 '
300 AF=PEEK(&HD000) + PEEK(&HD001) * 256
310 BC=PEEK(&HD002) + PEEK(&HD003) * 256
320 DE=PEEK(&HD004) + PEEK(&HD005) * 256
330 HL=PEEK(&HD006) + PEEK(&HD007) * 256
340 IX=PEEK(&HD008) + PEEK(&HD009) * 256
350 IY=PEEK(&HD00A) + PEEK(&HD00B) * 256
360 '
370 GOSUB 390:END
380 '
390 PRINT "AF: ";RIGHT$("000"+HEX$(AF),4);" ";
400 PRINT "BC: ";RIGHT$("000"+HEX$(BC),4)
410 PRINT "DE: ";RIGHT$("000"+HEX$(DE),4);" ";
420 PRINT "HL: ";RIGHT$("000"+HEX$(HL),4)
430 PRINT "IX: ";RIGHT$("000"+HEX$(IX),4);" ";
440 PRINT "IY: ";RIGHT$("000"+HEX$(IY),4)
450 RETURN
460 '
470 DATA &h2A,&h00,&hD0,&hE5
480 DATA &h2A,&h02,&hD0,&hE5
490 DATA &h2A,&h04,&hD0,&hE5
500 DATA &h2A,&h06,&hD0,&hE5
510 DATA &h2A,&h08,&hD0,&hE5
520 DATA &h2A,&h0A,&hD0,&hE5
530 DATA &hFD,&hE1,&hDD,&hE1,&hE1,&HD1,&HC1,&HF1
540 '
550 DATA &hCB,&h37,&h0B,&h0B,&h0B,&h0B,&h0B,&h0B
560 '
570 DATA &hFD,&hE5,&hDD,&hE5,&hE5,&HD5,&HC5,&HF5
580 DATA &hE1,&h22,&h00,&hD0
590 DATA &hE1,&h22,&h02,&hD0
600 DATA &hE1,&h22,&h04,&hD0
610 DATA &hE1,&h22,&h06,&hD0
620 DATA &hE1,&h22,&h08,&hD0
630 DATA &hE1,&h22,&h0A,&hD0
640 DATA &hC9,-1

To use it I modify lines 100-150 and 550 and then run it. To do this handily, I type “LIST -150”, then “LIST 550” and then RUN, and move my cursor up to modify the test values. To know the opcode length I look at the value of register C, since line 550 ends with DEC BC instructions.

By ToriHino

Master (245)

ToriHino's picture

06-12-2018, 23:02

That's some interesting research you did. Too bad they stripped a lot from the Z800, but at least some more MULUB instructions are found.

In all ways, the turboR really feels like a rushed product which could have been so much more.

By lintweaker

Expert (99)

lintweaker's picture

07-12-2018, 08:55

This code can be used to 'detect' running on a Z280, does it work for R800?

    ld a,40h
    defb 0cbh, 037h
    jp m,cpu_z80
    ; or
    ; jp p,z280

Did you test Z280 LDCTL opcodes on R800? I use this for Z280 :

LDCTL   MACRO   @opcode
›       defw›   @opcode
        ENDM

OUTW›   MACRO›  @opcode
›       defw›   @opcode
›       ENDM

OTIRW›  MACRO
›       defw›   093edh› ›       ›       ; OTIRW
›       ENDM
PCACHE› MACRO
›       defw›   65edh›  ›       ›       ; PCACHE
›       ENDM

L_CHL›  equ›    06eedh› ›       ›       ; LDCTL (C),HL
O_CHL›  equ›    0bfedh› ›       ›       ; OUTW (C),HL

L_HLC   equ 066edh          ; LDCTL HL,(C)

By Grauw

Enlighted (7525)

Grauw's picture

07-12-2018, 09:59

lintweaker wrote:

This code can be used to 'detect' running on a Z280, does it work for R800?

    ld a,40h
    defb 0cbh, 037h
    jp m,cpu_z80
    ; or
    ; jp p,z280

Indeed I saw that in the Z280 manual. No, it won’t work, because it tests the TSET instruction behaviour and that acts as "SLL" (SLA) on R800. With this particular test, it will detect the R800 as Z80, because it shifts the high bit into bit 7 and thus flags the sign negative.

(Of course if the goal is to know if the R800 is active, on MSX you can simply call the BIOS, which inspects the F4H port. Possibly S1990 register 6 is also readable. If detecting by instruction, I would test MULUB.)

lintweaker wrote:

Did you test Z280 LDCTL opcodes on R800? I use this for Z280

I saw no observable effect from those opcodes (like most others). However it does not necessarily mean that there is no effect, e.g. LDCTL (C),HL could still be working. But at least its counterpart LDCTL HL,(C) did not modify HL.

By erpirao

Paladin (815)

erpirao's picture

07-12-2018, 14:40

The truth is that it is a thread that I have always wanted to open, the z280-R800 comparison.
Graw, the research you are developing is very interesting, this confirms my theory that the R800 is a much better processor than we thought in the 90s.
what level of similarity are these cpu, s? 80% .. 90% ?.
the truth is that the z280 are cpu, s VERY cheap (2.35 € by aliexpress the version of 10MHZ).
Sorry for my English "made by google"

My MSX profile