Open zu2 opened 2 weeks ago
OMG, someone is actually using this. :-)
Huge thanks for that. I rushed the code while working on other things. It was a quick macro (subd).
Hmm, will need to figure this out.
;*****************************************************
;*
;* BASIC COMPARE INSTRUCTION SUBROUTINE
;* Compare the top of Stack to Register and set Condition codes
;*
;* Unsigned compare, Carry set if top of stack < A,B
;*
BCMP TSX
; ldd 2,X ;* GET TOP OF STACK
ldaa 2,X ;* GET TOP OF STACK
ldab 3,X ;* GET TOP OF STACK
; subd zREG ;* COMPARE
subb zREG+1 ;* COMPARE
sbca zREG ;* COMPARE
RTS
I need to RTS after the subb is it is F
BTW, I'm sure there are other issues like that in the code. I didn't give it a whole lot of thought for edge cases.
The relational operations Zxx require a little extra work to test AccB. Below we show ZEQ and ZNE. The other Zxx operations get more complicated.
diff -u run0.asm.orig run0.asm
--- run0.asm.orig 2024-06-19 09:54:03
+++ run0.asm 2024-06-19 09:57:46
@@ -598,14 +598,18 @@
;*-------------------------------
;* #33 TEST FOR EQUALITY
ZEQ BSR BCMP
- BEQ T
- BRA F
+ BNE F
+ TSTB
+ BNE F
+ BRA T
;*-------------------------------
;* #34 TEST FOR NOT-EQUAL
ZNE BSR BCMP
- BNE T
- BRA F
+ BEQ F
+ TSTB
+ BEQ F
+ BRA T
I'm thinking a different solution, make BCMP returned a combined 'CC'. I still need to work this out. Need to figure out the zxx and uxx. I really need to create a unit test. I haven't figured out a good way to do that.
Also note that I've reversed the A & B, I think I had them backwards (dyslexic). That drives me crazy.
BCMP tsx
ldab 3,X ;* GET TOP OF STACK (lo)
ldaa 2,X ;* GET TOP OF STACK (hi)
psha ;* doesn't affect CC
;
; The BCMP routine performs subtraction on SUBB and SBCA. Only the result of
; SBCA is reflected in the flags. If the result of the subtraction is AccA=0,
; ZEQ will be T regardless of the value of AccB. Similarly for the others.
;
; Therefore, the Zxx routine needs to be modified so that it also references the lower byte.
;
subb zREG+1 ;* COMPARE (lo)
tpa ;* doesn't affect CC
staa CC ;* Temp save CC
pula ;* Restore A (doesn't affect CC)
sbca zREG ;* COMPARE (hi)
tpa ;* doesn't affect CC
oraa CC ;* A <- A OR CC, combines CC and A
tap ;* Restore combined to PCR
rts
I'll need to check the results against the 6809 version.
I don't have this checked in yet.
Unfortunately, I don't think this strategy works well for anything other than ZNE/ZEQ. For example, if the V/N flag is set as a result of SUBB, BLT and BGE will be messed up. And if the C flag is affected by the result of SUBB, Uxx will also be messed up.
I was afraid of that. I'll need to sit down and make notes to get this right. Thanks for checking
BCMP needs to be rewritten, the 16 bit subtraction is all wrong. I haven't found any good examples of 16 bit subtraction but I am working on it.
I think will be interesting as I think Small C creates a -1 signed char as 0x8001. SUBA MEMORY will return a 2s complement result if negative (COMA, B-1 if ... gets messy).
Okay a bit more work but not fully tested, basically only tested with a few value. A & B return values are not correct when done. This is probably okay for Zxx, not sure of Uxx yet.
;*-------------------------------
BCMP TSX
; ldd 2,X ;* GET TOP OF STACK
nop ;* SWI
ldab 3,X ;* GET TOP OF STACK (lo)
ldaa 2,X ;* GET TOP OF STACK (hi)
; subd zREG ;* COMPARE
;
; The BCMP routine performs subtraction on SUBB and SBCA. Only the result of
; SBCA is reflected in the flags. If the result of the subtraction is AccA=0,
; ZEQ will be T regardless of the value of AccB. Similarly for the others.
;
; Therefore, the Zxx routine needs to be modified so that it also references the lower byte.
;
subb zREG+1 ;* COMPARE
bpl PLUS
comb ;* Turn the negative to a positive
incb
;; Hi -1
;; and correct for negative
;; @TODO: 16 bit sub
sec ;*
PLUS sbca zREG ;* COMPARE
;; Problem, Z gets set if A is 00 and B is not 0 (sometimes)
bne DONE
aba
DONE rts
Just found this on a Small C disk for the 6800:
BCMP TSX
LDAA 2,X ;* GET TOP OF STACK
LDAB 3,X
CMPA zREG ;* CHECK TOP BYTE
BNE BCMP1
CMPB zREG+1
BCMP1 RTS
I'll test this later
This method does not seem to work correctly for branches that refer to the N flag (BGE, BGT, BLE, BLT).
Let's look at the ZLT subroutine. Note that the comparison is done in two's complement.
BCMP TSX
LDAA 2,X ;* GET TOP OF STACK
LDAB 3,X
CMPA zREG ;* CHECK TOP BYTE
BNE BCMP1
CMPB zREG+1
BCMP1 RTS
ZLT BSR BCMP
BLT T
BRA F
The BCMP routine compares TOS and zREG starting from the upper byte.
As an example, we will use TOS:$0080 and zREG:$0000. In decimal, these are 128 and 0.
Since both upper byte are 0, BNE does not hold, so we compare the lower byte.
Subtract $00 from $80. The result is $80. The flags are N=1, C=V=Z=0.
Since N=1, V=0, the BLT is successful and the result is True.
Next, we use TOS:$007F and zREG:$0000. In decimal, these are 127 and 0.
This time the N flag is 0. Therefore, the BLT is not successful and the result is False.
The reason the results are different when the value is 128 and when the value is 127 is because the sign in the lower byte was looked at.
I'll have another set of changes to cover that. Found a Small C disk with ccint.txt that splits the signed (SBCMP) and everything else (BCMP) but has a few changes for the < <= == != >= > functions also.
Okay I've added an updated run0.asm . I've stolen ccint.txt from a Small C Flex Floppy. The ccint.asm has self modifying code and also looks a bit trimmer. I'm still reformatting it for use with the asl macro assembler (and to make it pretty). I'll add the rest of the code later but we now have a BCMP (unsigned) and SBCMP (signed) and changed <= == != >= > functions.
I also need to create a Small C program that I can toss into the sim6800 to test if all these changes really work as expected.
Relational operator processing does not seem to work correctly in run0.asm for the 6800.
The BCMP routine performs subtraction on SUBB and SBCA. Only the result of SBCA is reflected in the flags. If the result of the subtraction is AccA=0, ZEQ will be T regardless of the value of AccB. Similarly for the others.
Therefore, the Zxx routine needs to be modified so that it also references the lower byte.