Page 1 of 1

substraction of two 8bits signed values into a signed 16 bits

Posted: Wed Sep 30, 2020 6:10 pm
by jbperin
Hi all,

I'm trying to translate in assembly 6502 language of portion of code that I wrote in C and I'm blocking on dealing with overflow circumstance.

The code consist in computing the signed difference between two signed angle and use the result to index a look-up table.

If the difference is "small" (fits in one signed byte) I can directly use it to index an accurate table.
Otherwise, I divide the difference by two to index a less accurate table.

Code: Select all

signed char RayAlpha;
signed char RayBeta;
signed int RayDeltaAngle;

RayDeltaAngle = RayBeta - RayAlpha;

if (abs(RayDeltaAngle) < 127){
	RayDivisor = tab_divisor_acc[(unsigned char)RayDeltaAngle];
} else {
	RayDeltaAngle = RayDeltaAngle>>1;
	RayDivisor = tab_divisor[(unsigned char)RayDeltaAngle];
}
NB: tables are built so that tab_divisor [-1] == tab_divisor [255]

I only managed to translate some easy parts but I don't know to solve the FIXME and code the DUNNO in the following code:

Code: Select all

;; RayDeltaAngle = RayBeta - RayAlpha;
lda _RayBeta
sec
sbc _RayAlpha
sta _RayDeltaAngle
sbc #0                   // FIXME : won't work if signed angle difference overflows .. 
sta _RayDeltaAngle+1

// if (abs(RayDeltaAngle) < 127){			// DUNNO how to code this overflow condition

	;; RayDivisor = tab_divisor_acc[(unsigned char)RayDeltaAngle];
	ldy _RayDeltaAngle
	lda _tab_divisor_acc, y
	sta _RayDivisor

// } else {

	;; RayDeltaAngle = RayDeltaAngle>>1;
	;; RayDivisor = tab_divisor[(unsigned char)RayDeltaAngle];
	lda _RayDeltaAngle
	cmp #$80
	ror
	tay
	lda _tab_divisor, y
	sta _RayDivisor
Can anyone help please ?
It's breaking my head

Re: substraction of two 8bits signed values into a signed 16 bits

Posted: Wed Sep 30, 2020 8:03 pm
by iss
Why not to simply use 'signed int' for RayAlpha and RayBeta too, keeping the allowed values in the same range -127..128 ? :?
IMHO, this will not slowdown significantly the calculation. Then the translation to ASM will be easier and you can continue to use only 8 bits to index both tab_divisor arrays.
And when we talk about angles - is it not possible to use more limited ranges i.e. -90..+90 or even better -45..+45 just to avoid the overflow ... (pure guess - without knowing the whole idea it can be completely wrong).

Re: substraction of two 8bits signed values into a signed 16 bits

Posted: Wed Sep 30, 2020 9:24 pm
by jbperin
Hey Iss !! So glad to see you back here :-)
iss wrote: Wed Sep 30, 2020 8:03 pm Why not to simply use 'signed int' for RayAlpha and RayBeta too, keeping the allowed values in the same range -127..128 ? :?
IMHO, this will not slowdown significantly the calculation. Then the translation to ASM will be easier and you can continue to use only 8 bits to index both tab_divisor arrays.
Yes that's the solution I'll use if I find no way to work with 8 bits values.
working with 16 bits means : initialize MSB, propagate carry and sign at each operation, it's loosing cycles.
I'm sure there's a trick with the V flag of the processor which can be used at this specific point in calculation.
The V flag of the processor is typically made for that.

http://www.righto.com/2012/12/the-6502- ... ained.html

In the C code I use 16 bits, but in fact, I only need one more bit for the result of the substraction of the two 8 bits operands.
And this bit is the overflow bit which can be used to determine if abs(...)> 127.
I can feel there's a trick but I can't find it.
iss wrote: Wed Sep 30, 2020 8:03 pm And when we talk about angles - is it not possible to use more limited ranges i.e. -90..+90 or even better -45..+45 just to avoid the overflow ... (pure guess - without knowing the whole idea it can be completely wrong).
I use angle coded that way:
-128 = -Pi
0 = 0
127 = Pi

Because, in most operations, the rollover correspond to a modulo in angle. That's hyper mega convenient because I can add and/or substract angles without having to care of overflow or rollover.

look for example if I want to add two angles PI/2 and Pi :
Pi/2 + Pi = 64 + 127 = 191 (3*PI/2) = $BF = -65 = -PI/2 => So the angle value can be read as a signed as wall as an unsigned value .. IT WORKS IN BOTH CASE !! :-) So i can use a signed interpretation of the value for angular operations and an unsigned interpretation pour indexing lookup tables :-)
even better .. if i want to add two angles which sum overflows the 2*pi circle:
3 PI/2 + PI = 191 + 127 = 62 (we can ignore the overflow) = PI/2 => The overflows performs a modulo on the angle !!

So this way to code angle provides full range accuracy and it allows to get rid of rollover and overflow checking .. that's marvellous !!

Re: substraction of two 8bits signed values into a signed 16 bits

Posted: Wed Sep 30, 2020 11:48 pm
by iss
jbperin wrote: Wed Sep 30, 2020 9:24 pm Hey Iss !! So glad to see you back here :-)
Yep, I'm back from a long vacation without Orics, Internet etc., ... just 'underwater void' ! :D
uwv.jpg
Anyway..., attached you will find your sources as one main C file and one ASM file.
The idea is to redirect 'printf' to the printer output and to dump the results of the calculations in file 'printer_output.txt' generated by Oricutron. So you can compare the output from C and from ASM routines ;). In the attached file are also the results from your C calculations (it runs looong, just wait 'Ready' to appear). The ASM routine is only marked and has to be written. Hope this will help somehow.

Re: substraction of two 8bits signed values into a signed 16 bits

Posted: Thu Oct 01, 2020 8:21 pm
by jbperin
iss wrote: Wed Sep 30, 2020 11:48 pm just 'underwater void' ! :D
uwv.jpg
Wow .. looks greats !!
iss wrote: Wed Sep 30, 2020 11:48 pm Anyway..., attached you will find your sources as one main C file and one ASM file.
The idea is to redirect 'printf' to the printer output and to dump the results of the calculations in file 'printer_output.txt' generated by Oricutron. So you can compare the output from C and from ASM routines ;). In the attached file are also the results from your C calculations (it runs looong, just wait 'Ready' to appear). The ASM routine is only marked and has to be written. Hope this will help somehow.
Thank you for the trick .. I knew that we could write on the printer.out by using lprintf(...) instead fo fprintf(...) . Thks Dbug .
But i didn't know this method.

As for the routine, I managed to find a very nice translation of my C code. I saved 800 cycles with this little optim !! Can you believe that ? 800 cycles !!

Substract8bits.JPG

Re: substraction of two 8bits signed values into a signed 16 bits

Posted: Thu Oct 01, 2020 9:25 pm
by iss
Cool! Now let's save 3 bytes space too 8) :

Code: Select all

	sec
	lda _RayBeta
	sbc _RayAlpha
	bvc axmb_noOverflow
		ror
		tay
		lda _tab_divisor,y
		jmp axmb_done 
		
axmb_noOverflow
		tay
		lda _tab_divisor_acc,y
		
axmb_done
		sta _RayDivisor

Re: substraction of two 8bits signed values into a signed 16 bits

Posted: Fri Oct 02, 2020 6:00 am
by jbperin
Hey!! Yep. I had missed that. 😀Thank you for your review.

Re: substraction of two 8bits signed values into a signed 16 bits

Posted: Fri Oct 02, 2020 12:55 pm
by Chema
Ah, I'm too late to this thread, and iss has already answered perfectly :)

If you want to save 1 more byte you may change your jmp for a bvs. Be careful, though, as if there is a page crossing you will lose 1 machine cycle.