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

Here you can ask questions or provide insights about how to use efficiently 6502 assembly code on the Oric.
User avatar
jbperin
Flight Lieutenant
Posts: 480
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

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

Post 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
User avatar
iss
Wing Commander
Posts: 1641
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

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

Post 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).
User avatar
jbperin
Flight Lieutenant
Posts: 480
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

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

Post 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 !!
User avatar
iss
Wing Commander
Posts: 1641
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

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

Post 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.
Attachments
calc_helper.zip
(278.37 KiB) Downloaded 238 times
User avatar
jbperin
Flight Lieutenant
Posts: 480
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

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

Post 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
User avatar
iss
Wing Commander
Posts: 1641
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

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

Post 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
User avatar
jbperin
Flight Lieutenant
Posts: 480
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

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

Post by jbperin »

Hey!! Yep. I had missed that. 😀Thank you for your review.
User avatar
Chema
Game master
Posts: 3014
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

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

Post 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.
Post Reply