[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Lousy code generation (Re: MoriaGS 5.3.1 coming...)



nathan@cco.caltech.edu (Nathan Mates) writes:
[stuff]

Depending on the type of data that's in $F0, only one of the code samples is
correct. Isn't anyone teaching today's assembly programmers about signed
comparisons?

The minimal LDA/CMP/BCS sequence assumes that both operands are UNSIGNED or
have the same sign. If they are signed and have different signs, this sequence
fails to compare them correctly. Try 1 >= -1 ($FFFF).

We are up against an inherent flaw in the 65xxx series ALU's here; there is no
direct test for signed comparisons. You need to compute the term
	(N XOR V)
or (in explicit, C-ish notation)
	(N && !V) || (V && !N)
which is easier if you use SBC because it computes V for you. CMP does not.
Computing V manually is a royal pain, so it is better to accomodate SBC and
live with it.

In this particular example, however, the compiler could have taken advantage
of the fact that one of the numbers is known to be positive. We can correctly
do a signed comparison of ($F0 >= #3) with the following:

	lda	$F0
	bmi	less-than
	cmp	#3
	bcs	g-or-e
less-than:

If you are comparing two unknown signed numbers, though, then you are stuck
using something more like this (I altered it to match the explanation better):

	lda	$F0
	sec
	sbc	$F2
	bvc	okay
	eor	#$8000
okay	bpl	g-or-e
less-than:

Start with ($F0 >= $F2), and shuffle it to ($F0 - $F2) >= 0. The first three
instructions compute ($F0 - $F2), and if no overflow occurred (V is clear) we
got a mathematically correct result so we skip down to the bottom and use the
BPL ( >= 0 ) test to branch. If overflow _did_ occur, then the N bit is -wrong-
and we need to invert it first, so we do that by EOR-ing with $8000.

The code example Nathan disassembled does exactly the same thing, only it
reverses the sense of both branches -- they use a BMI to test the opposite
of the branch condition and flip the N bit in the non-overflow case, which
takes more time and seems to be the common path to me, so I saved two cycles
by changing it to branch over the EOR in the non-overflow case instead.

Todd Whitesel
toddpw @ cco.caltech.edu