Re[3]: [stella] signed 8-bit comparisons?

Subject: Re[3]: [stella] signed 8-bit comparisons?
From: zu03776 <zu03776@xxxxxxxxxxxxxxxxxx>
Date: Fri, 5 Mar 2004 02:14:40 -0600
I did some experiments, conclusion in the last three to six
paragraphs.  :)

I included my thought process so that others could double-check.

>> Hi there,
>>
>> > I think what you want is:
>> >     LDA    var
>> >     CMP    #MAX
>> >     BMI    ltMAX
>> >     LDA    #MAX
>> > ltMAX
>> >     CMP    #MIN
>> >     BPL    gtMIN
>> >     LDA    #MIN
>> > gtMIN
>> >     STA    var
>>
>> Wouldn't it be better to use bcc and bcs instead of bmi and bpl?

Kac> If I'm reading
Kac> http://www.6502.org/tutorials/compare_instructions.html
Kac> correctly, bcc/bcs vs bmi/bpl is the whole point of my
Kac> question and Eric's response: bcc/bcs work if you're
Kac> treating your 8-bits as an unsigned byte, but if you
Kac> want your %11111111 to come across as LESS than your
Kac> %00000001, (ala 2's complement) then the code above is
Kac> correct.

For a full treatment of the 6502 flags, may I suggest Chapter 3 of the
wonderful book "Machine Language for the Commodore 64 and other
Commodore Computers", written by Jim Butterfield.

Original site: http://www.devili.iki.fi/library/publication/51.en.html
ZIP Archive Mirror: http://tripoint.org/wizard/ml4c64.zip

Search the text for "Z Flag" and you're in the right place.

A quick flag summary:  when used in comparisons: the Z flag should
be called the E flag (for "equals"), the C flag should be called the
GE flag ("greater than or equal"), the N flag should be called the HB
flag ("high bit"), and the V flag should be called the SAO flag
("signed arithmetic overflow").

It's real hard to set the V flag: the only instructions that do so are
ADC, SBC, and BIT.  Note the lack of CMP, CPX, and CPY.

To test how the flags get set, I assumed worst case signed scenarios.
The desired limits are -64 to +64; the current value is -128 or +127.
(That's limits of $c1 to $3f, values of $80 or $7f.)

                                     N Unsigned  Signed Intrepretation
LDA #$80 CMP #$C1 Flags B0 (N v z c) 128 < 197  -128 < -63 (OK)
LDA #$80 CMP #$3F Flags 31 (n v z C) 128 >  63  -128 >  63 (??)
LDA #$FF CMP #$C1 Flags 31 (n v z C) 255 > 197    -1 > -63 (OK)
LDA #$FF CMP #$3F Flags B1 (N v z C) 255 <  63 ?  -1 <  63 (OK)
LDA #$01 CMP #$C1 Flags 30 (n v z c)   1 > 197 ?   1 > -63 (OK)
LDA #$01 CMP #$3F Flags B0 (N v z c)   1 <  63     1 <  63 (OK)
LDA #$7F CMP #$C1 Flags B0 (N v z c) 127 < 197   127 < -63 (??)
LDA #$7F CMP #$3F Flags 31 (n v z C) 127 >  63   127 >  63 (OK)

The N flag for unsigned numbers isn't correct in two cases -- comparing
the small negative value (#$ff) to the positive value (#$3f) should be
positive; comparing the small positive value (#$01) to the negative
value (#$c1) should be negative.  When comparing unsigned numbers, the
carry flag is the correct flag to use (BCC, BCS).

By similar reasoning, the N flag for signed numbers isn't correct in
two cases -- comparing the large negative value (#$80) to the positive
value (#$3f) should be negative; comparing the large positive value
(#$7f) to the negative value (#$c1) should be positive.  However, the
carry flag is a worse candidate for correct flag, as it is wrong half
the cases.  Hmm...

Let's try subtraction... (with SEC first)
                                     Signed Intrepretation
LDA #$80 SBC #$C1 Flags B0 (N v z c) -128 < -63 (out)
LDA #$80 SBC #$3F Flags 71 (n V z C) signed overflow (in)
LDA #$FF SBC #$C1 Flags 31 (n v z C)   -1 > -63 (in)
LDA #$FF SBC #$3F Flags B1 (N v z C)   -1 <  63 (in)
LDA #$01 SBC #$C1 Flags 30 (n v z c)    1 > -63 (in)
LDA #$01 SBC #$3F Flags B0 (N v z c)    1 <  63 (in)
LDA #$7F SBC #$C1 Flags F0 (N V z c) signed overflow (in)
LDA #$7F SBC #$3F Flags 31 (n v z C)  127 >  63 (out)

This looks more promising....  In the cases where a signed overflow
occurs, the N flag is incorrect.  Where A is a large negative,
subtracting the positive maximum value and overflowing indicates A is
less than the maximum.  Where A is a large positive, subtracting the
negative minimum value and overflowing indicates A is greater than the
minimum.  Therefore, on an overflow comparing the numeric values, the
value need not be modified.

A similar set of overflow problems occurs when adding signed numbers.
Exercise left to the reader.  :)

How does this apply to your problem?  I'm working on that... :)

If A is -4, and the lower limit is -3, having a negative result when
subtracting the negative lower limit (adding a positive) from the
value indicates the value is out of range (N flag set).
However, if the A value is sufficiently positive (say, $7D),
subtracting -3 from the number (add 3) wraps A to the negative side
($80 or -128), and sets the negative flag and the overflow flag.
But, the original value was positive (way larger than the lower
limit), so a set overflow flag indicates to ignore the (set) negative
flag.

If A is 4, and the upper limit is 3, having a positive result when
subtracting the upper limit from the value is bad (N flag reset).
However, if A is sufficiently negative (say, $82), subtracting 3 makes
the result positive ($7F or 127), resets the N flag and sets the
overflow flag.  However, the original value was way below the upper
limit specified, so a set overflow flag indicates to ignore the reset
negative flag.

So, if you're sure that your _signed negative current value_ minus
your _signed negative limit value_ will never be less than -128, just
checking sign results (N) will work.  Otherwise, you will need to add
an overflow branch check to ignore the negative branch check.

Same thing for _signed positive current value_ plus your _signed
positive limit value_ never exceeding 127.  If it could, add an
overflow branch to ignore the positive branch check.

value .byte

chkrg LDA value
      SEC
      SBC #$MIN
      BVS skpmn
      BPL skpmn
      LDA #$MIN
      STA value
skpmn LDA value
      SEC
      SBC #$MAX
      BVS skpmx
      BMI skpmx
      LDA #$MAX
skpmx STA value

Too too long to sort though that one.  It still reads somewhat
somewhat confusingly.

So, where is this wrong?  I hope it's not at first premise.  :>

----------------------------------------------------------------------------------------------
Archives (includes files) at http://www.biglist.com/lists/stella/archives/
Unsub & more at http://www.biglist.com/lists/stella/


Current Thread