# Conversion of Z80 code to TMS9900

58 replies to this topic

### #26 AsmusrONLINE

Asmusr

River Patroller

• Topic Starter
• 2,361 posts
• Location:Denmark

Posted Fri Jun 30, 2017 10:16 AM

On the Z80, as far as I understand, if you subtract a bigger unsigned byte from a smaller one the carry bit is set:

ld a,#0xc0

sub #0xd0

jr C,label [this jump will be taken]

I don't think the carry flag works like that on the TMS9900. Is there an equivalent?

### #27 artragONLINE

artrag

Dragonstomper

• 676 posts

Posted Fri Jun 30, 2017 11:26 AM

Correct! sub a,n will set C if a<n
Be aware that some 16 instructions do not set the C flag

### #28 mizapfOFFLINE

mizapf

River Patroller

• 2,447 posts
• Location:Germany

Posted Fri Jun 30, 2017 11:26 AM

When you calculate 00c0 - 00d0, the ALU effectively adds the two's complement: 00c0 + ff30 = fff0. Since the result does not exceed ffff, carry is cleared. However, when you calculate 00d0 - 00c0, you have 00d0 + ff40 = 10010 = 0010, so this means carry is set.

### #29 artragONLINE

artrag

Dragonstomper

• 676 posts

Posted Fri Jun 30, 2017 1:26 PM

This is very different from z80

The z80 ALU has proper subtraction using the carry bit as 9th or 17th bit in the operation
Only pay attention that the 16 bit add does not affect carry for compatibility with intel 8080
If you need the carry bit on 16bit operations you can use adc and sbc, but they also add and sub the previous value of the carry before affecting it.
This is the reason why you often find

And a
Sbc hl,de

Because and a resets the carry before the execution of sbc

Edited by artrag, Sat Jul 1, 2017 5:35 AM.

### #30 mizapfOFFLINE

mizapf

River Patroller

• 2,447 posts
• Location:Germany

Posted Fri Jun 30, 2017 2:04 PM

I don't think the carry flag works like that on the TMS9900. Is there an equivalent?

If you subtract a bigger value from a smaller one, the result is negative, so a JLT should work.

### #31 AsmusrONLINE

Asmusr

River Patroller

• Topic Starter
• 2,361 posts
• Location:Denmark

Posted Fri Jun 30, 2017 2:28 PM

If you subtract a bigger value from a smaller one, the result is negative, so a JLT should work.

I don't think so because >C0 - >10  = >B0, this will trigger JLT but >10 is not unsigned bigger than >C0.

I think it works to use CB followed by JL, and perform the subtraction afterwards if it's not only needed for the comparison.

### #32 mizapfOFFLINE

mizapf

River Patroller

• 2,447 posts
• Location:Germany

Posted Fri Jun 30, 2017 2:38 PM

I actually did not say anything about the converse: If you subtract a bigger value from a smaller, the result is negative, but the result is also negative in other occasions, so you need something that behaves the same way in both directions (if and only if).

C0 - 10 = B0 will not trigger JLT if we understand this as 00C0 - 0010 (thinking by 16 bit). For our platform, it would have to read C000-1000 = B000, this would indeed be negative.

### #33 AsmusrONLINE

Asmusr

River Patroller

• Topic Starter
• 2,361 posts
• Location:Denmark

Posted Mon Jul 3, 2017 3:10 AM

Correct! sub a,n will set C if a<n
Be aware that some 16 instructions do not set the C flag

I'm still having troubles converting code that uses the C flag. Can you confirm that for sub the carry flag is set if and only if a<n and that this comparison is unsigned, i.e. 0xc0<0xd0?

### #34 artragONLINE

artrag

Dragonstomper

• 676 posts

Posted Mon Jul 3, 2017 5:12 AM

Carry is the 9th bit in the sub a,n instruction.
If the result (think it on infinite bits) is negative, the 9th bit is one. If the result is positive the 9th bit is zero.
Try
Msxpen.com
And see the 'hello word' program to have a guide

Edited by artrag, Mon Jul 3, 2017 5:16 AM.

### #35 AsmusrONLINE

Asmusr

River Patroller

• Topic Starter
• 2,361 posts
• Location:Denmark

Posted Mon Jul 3, 2017 9:12 AM

Carry is the 9th bit in the sub a,n instruction.
If the result (think it on infinite bits) is negative, the 9th bit is one. If the result is positive the 9th bit is zero.
Try
Msxpen.com
And see the 'hello word' program to have a guide

Thanks, I'm playing with msxpen.com and I have simple question: what's the different between ld a,200 and ld a,#200? The latter is used in the disassembly I'm converting. msxpen.com accepts both notations with different results.

### #36 artragONLINE

artrag

Dragonstomper

• 676 posts

Posted Mon Jul 3, 2017 9:21 AM

#200 is hex, same as 0x200
200 is decimal

### #37 JamesDONLINE

JamesD

• 7,363 posts

Posted Mon Jul 3, 2017 9:50 AM

Thanks, I'm playing with msxpen.com and I have simple question: what's the different between ld a,200 and ld a,#200? The latter is used in the disassembly I'm converting. msxpen.com accepts both notations with different results.

Motorola assembly is the same way.

#200 is hex, same as 0x200
200 is decimal

#200 is not hex, it is decimal.

Hex is represented by the prefix \$ on Motorola chips, and H postfix on the Z80, upper or lower case H h usually works depending on the assembler.
So when combined with my previous comment,  ld a,200h would be load a from address 200 hex, and ld a,#200h  would be load value 200 hex into a

Not only that, but a is 8 bit on the Z80 and loading a value larger than 8 bits into a should cause the assembler to generate an error

0x200 notation for hex is supported by most modern assemblers but I can't vouch for old ones.
Since this is about porting code, you just have to be aware of both forms as would a translator program.

Edited by JamesD, Mon Jul 3, 2017 9:54 AM.

### #38 artragONLINE

artrag

Dragonstomper

• 676 posts

Posted Mon Jul 3, 2017 9:54 AM

Z80 is from zilog
In msxpen #200 is hex

### #39 JamesDONLINE

JamesD

• 7,363 posts

Posted Mon Jul 3, 2017 9:59 AM

Z80 is from zilog
In msxpen #200 is hex

So how does it differentiate between hex and immediate addressing?

### #40 JamesDONLINE

JamesD

• 7,363 posts

Posted Mon Jul 3, 2017 10:11 AM

msxopen uses the pasmo assembler.
http://pasmo.speccy.org/pasmodoc.html

### #41 artragONLINE

artrag

Dragonstomper

• 676 posts

Posted Mon Jul 3, 2017 10:13 AM

Ld a,(200) will load in a the value stored in ram at 200 decimal

Edited by artrag, Mon Jul 3, 2017 10:43 AM.

### #42 JamesDONLINE

JamesD

• 7,363 posts

Posted Mon Jul 3, 2017 10:27 AM

Ld a,(200)

Which is indirect addressing on other processors.  Load a with the value located at the address pointed to by what is in memory address 200 and 201.

I've definitely never buying the guy that wrote Pasmo a beer.
If all you are writing is Z80 code it seems to have a lot of features., but if you spend much time going back and forth between different processors that it is likely to mess you up.

### #43 AsmusrONLINE

Asmusr

River Patroller

• Topic Starter
• 2,361 posts
• Location:Denmark

Posted Mon Jul 3, 2017 10:29 AM

#200 is hex, same as 0x200
200 is decimal

\$200 also seems to work in msxpen. But the code I'm converting must be using # to denote immediate addressing, because it uses things like ld hl,#table or ld a,#0xff.

### #44 artragONLINE

artrag

Dragonstomper

• 676 posts

Posted Mon Jul 3, 2017 10:45 AM

#table is a label, in some assemblers lables can start by #
Check if #0xff is a label too, it could be a quick and dirty way to name a label from a constant

Edited by artrag, Mon Jul 3, 2017 10:46 AM.

### #45 artragONLINE

artrag

Dragonstomper

• 676 posts

Posted Mon Jul 3, 2017 10:53 AM

Which is indirect addressing on other processors.  Load a with the value located at the address pointed to by what is in memory address 200 and 201.

I've definitely never buying the guy that wrote Pasmo a beer.
If all you are writing is Z80 code it seems to have a lot of features., but if you spend much time going back and forth between different processors that it is likely to mess you up.

The assembly has been defined by ziolg not by pasmo.

Look at this
www.zilog.com/docs/z80/um0080.pdf

### #46 AsmusrONLINE

Asmusr

River Patroller

• Topic Starter
• 2,361 posts
• Location:Denmark

Posted Mon Jul 3, 2017 10:59 AM

#table is a label, in some assemblers lables can start by #
Check if #0xff is a label too, it could be a quick and dirty way to name a label from a constant

No # is not part of the label, and #0xff is not a label either. I guess this has been produced using a non-standard disassembler.

### #47 JamesDONLINE

JamesD

• 7,363 posts

Posted Mon Jul 3, 2017 11:14 AM

The assembly has been defined by ziolg not by pasmo.

Look at this
www.zilog.com/docs/z80/um0080.pdf

Crap... and it's even in my own code like that.
Sorry

### #48 artragONLINE

artrag

Dragonstomper

• 676 posts

Posted Mon Jul 3, 2017 11:41 AM

No # is not part of the label, and #0xff is not a label either. I guess this has been produced using a non-standard disassembler.

Hardly I can imagine to find something useful in memory at 0xFF if the bios is paged in.

Maybe it is better if you send a larger except from the source if you want a more accurate evaluation of what is doing the code

Edited by artrag, Mon Jul 3, 2017 12:00 PM.

### #49 JamesDONLINE

JamesD

• 7,363 posts

Posted Mon Jul 3, 2017 2:07 PM

FWIW, someone has just completed a direct translation of the arcade version of Pacman to the Coco 3.
He used a tool to help convert from the Z80 code to the 6809.
If you follow the links to the blog and look for entries for July, you will find the C source code for his tool.
Maybe you could use it as a starting point for a Z80 to 9900 translator.
http://www.vintageis...-trs-80-coco-3/

### #50 WillsyOFFLINE

Willsy

River Patroller

• 2,996 posts
• Location:Uzbekistan (no, really!)

Posted Tue Jul 4, 2017 6:15 AM

So many late late nights under my blankets with a battery torch writing Z80 code into a notebook...

Into the wee hours I'd go, looking up op-codes and turning them into hex before POKEing into memory...

I'd awaken bleary eyed and naggy to shouting parents, rudely informing me that it's time for school...

Funny, the memories that a few Z80 op-codes can invoke.

Thanks for the memories.

I'll stick with the 9900 though

#### 1 user(s) are browsing this forum

0 members, 1 guests, 0 anonymous users