Unlike a normal Z80, the Game Boy has no
JP pe/po or
RET pe/po instructions. I've been trying to figure out how to detect integer overflow on the Game Boy. (It doesn't have those instructions for the sign flag either but that can be done with
This is what I've been trying to come up with but it's an absolute mess. After doing a few calculations on paper, such as
&81 - &02,
&7F-&01, etc. I came to the (possibly faulty) conclusion that overflow is equivalent to sign change xor Carry Flag. It almost works but there seems to be a problem. If A and B have opposite signs but they subtract to less than 7F the compare is wrong. The second picture shows an incorrect result.
Like I said, the source code is spaghetti, but I couldn't come up with a better way.
;compares A to B signed. bit 7,a ;returns nz if A is negative, z if positive. call GetZeroFlag ;stores this result sub b bit 7,a push af call TestForSignChange jr z,NoSignChange pop af ;at this point, if carry is clear, overflow occurred. jr c,NoOverflow jr OverflowOccurred NoSignChange: ;at this point, if carry is set, overflow occurred. pop af jr nc,NoOverflow OverflowOccurred: ;test bit 7 of A again. If A is positive, A < B. If A is negative, A >= B bit 7,a jr nz, GreaterThanSigned LessThanSigned: scf ;set carry if less than, just like an unsigned compare does. ret GreaterThanSigned: or a ;clear carry if greater than or equal, just like an unsigned compare does. ret NoOverflow: ;Test bit 7 of A again. If A is positive, A >= B. If A is negative, A < B. bit 7,a jr nz, GreaterThanSigned ;I don't understand why this isn't "JR Z, GreaterThanSigned" jr LessThanSigned GetZeroFlag: push af push bc push af pop bc ;get the flags into the C register ld a,c and %01000000 ;zero flag is where the 1 is. ld (tempflags),a ;store the result in ram pop bc pop af ret TestForSignChange: ;compares bit 7 of A before and after the subtraction. ;If the value of bit 7 of A changed, return nz, otherwise return z. push bc push af pop bc ld a,c and %01000000 ;ignore all but the zero flag ld c,a ;store the current state of the zero flag in C ld a,(tempflags) ;get the state of the zero flag before the subtraction in A cp c ;compare it to the state of the zero flag after the subtraction. pop bc ret