English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old 16 June 2011, 08:46   #1
oRBIT
Zone Friend
 
Join Date: Apr 2006
Location: Gothenburg/Sweden
Age: 48
Posts: 339
Floating point without FPU

Are there any clever ideas on how to deal with (or simulate) floating point values in 68k asm? I've been coding 68k asm for many years but almost never worked with decimals.
My code would look something like this psuedocode below. I could perhaps do it with the FPU but last time I experimented with the FPU it was quite slow..

"Psuedocode:"
move.l #113.66,d0
....
sub.l #2,d0
blt minus
...
minus:
add.l #113.66,d0
...
oRBIT is offline  
Old 16 June 2011, 09:42   #2
phx
Natteravn
 
phx's Avatar
 
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
When 16-bit precision is enough, you could try 16+16 bits fixed point numbers:
Code:
        move.l  #(113<<16)|$a8f5,d0  ; $10000*0.66 = $a8f5
        ...
        sub.l   #(2<<16),d0
phx is offline  
Old 16 June 2011, 13:37   #3
r0ber7
it's all in your head
 
r0ber7's Avatar
 
Join Date: Feb 2011
Location: The Netherlands
Posts: 174
multiply by a thousand? :P (cheating perhaps)
r0ber7 is offline  
Old 16 June 2011, 14:00   #4
StingRay
move.l #$c0ff33,throat
 
StingRay's Avatar
 
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,863
Quote:
Originally Posted by r0ber7 View Post
multiply by a thousand? :P (cheating perhaps)
$10000 = 65536 = 1<<16 (i.e. not 1000)

No cheating there, it's just to maintain precision.
StingRay is offline  
Old 16 June 2011, 17:22   #5
Kalms
Registered User
 
Join Date: Nov 2006
Location: Stockholm, Sweden
Posts: 237
There are also a bunch of pages out there on the interwebs which describe how fixed point arithmetic works.
Kalms is offline  
Old 23 June 2011, 23:44   #6
Photon
Moderator
 
Photon's Avatar
 
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,602
What you do is you treat it like a unit vector with scale, except the scale is a shift and not a multiply.

Decimal example:
0.4356347*10^-1 is 0.04356347
0.4356347*10^7 is 4356347
(-1, 7 are exponent, 0.43... is mantissa or unit vector)

Binary example:
4356347>>9=8508 (.490234375)
4356347<<9=too big for a longword, if signed numbers are used
(9 is exponent in the form of an ASR or ASL, becoming -9 or 9, respectively)
(4356347 is the mantissa or unit vector, fitting in how many bits are left after you decide how many bits to reserve for the exponent)

You simply decide on a binary representation of a floating-point number in whatever word size is efficient. You could go with 64-bit where 1 longword is the exponent and the other the mantissa (%01111111 11111111 11111111 11111111 is the highest possible positive number corresponding to 0.9999999999999999999...)

Or you could go 32-bit, something like
%seeeeee Smmmmmmm mmmmmmmm mmmmmmmm
where you have a signed exponent and a Signed mantissa and separate them into two registers before each computation.

You will get overflow or NAN (not a number) when the result of a computation doesn't fit in the format you chose. To solve that, you normalize the results and keep factors separate, or factorize before computing. For high-precision calculations that are simple, you can usually modify the calculations instead, to just make sure it doesn't become a problem.

For both of these, you need 32-bit multiply and divide at least, if you want to support all 680x0 processors you need to write functions for that.

My favorite is a 5-bit word for exponent and a word for mantissa; this makes writing the macros trivial. You only have "4.5 decimals" but usually it's possible to combine calculations to keep things in range so this doesn't affect the (rounded) result.

To round a number you add half the value of its highest unsigned bit before shifting down, or shift 1 less, addq #1, then asr #1.
Photon is offline  
Old 17 July 2011, 20:28   #7
tom42
 
Posts: n/a
Fixed point is what you want, most of the time.

Earlier this year I tinkered around with a raytracer that ran on the GBA. I wrote it in C++: The whole thing was templatized, and I could use float and double as the basic data type or substitute my own fixed point data type which was a template too (two template args: the integer type to use and how many bits to use for the fractional part).
 
Old 05 February 2015, 16:50   #8
h0ffman
Registered User
 
Join Date: Aug 2008
Location: Salisbury
Posts: 744
Hey guys, thought I'd drag this thread up rather than starting another one.

I'm thinking of using a longword as fixed point, top half int, bottom half decimals. I'm doing a division calculation which gives me the int part and then a remainder in the top half. How do I recalculate the remainder into the required decimal value?
h0ffman is offline  
Old 05 February 2015, 17:34   #9
Samurai_Crow
Total Chaos forever!
 
Samurai_Crow's Avatar
 
Join Date: Aug 2007
Location: Waterville, MN, USA
Age: 49
Posts: 2,186
There is an implementation in c99 at https://code.google.com/p/libfixmath/ or use the 64 by 32 bit division routines on an 020+ or use Utility.library on Kickstart 2+ to get the same results.
Samurai_Crow is offline  
Old 05 February 2015, 17:42   #10
h0ffman
Registered User
 
Join Date: Aug 2008
Location: Salisbury
Posts: 744
Needs to be 68000 only sadly, also calling out to a library is going to greatly impede the speed of the code.

I'm using this to mix multiple sounds together, so the calculations are done thousands of times, one cycle per resulting sample. I'm just trying to shave some time off it at the moment.
h0ffman is offline  
Old 06 February 2015, 15:25   #11
h0ffman
Registered User
 
Join Date: Aug 2008
Location: Salisbury
Posts: 744
Got it working now, thought I'd post the code in case anyone wants to see it.

Code:
.loop		moveq	#0,d0
		moveq	#0,d1
		moveq	#0,d2
		move.w	osc_baseperiod,d1	; base period
		move.w	osc_period(a0),d2	; get this per

		divs	d2,d1    ; divide the periods
		swap	d1        ; swap the remainder to lower
		tst.w	d1        ; test is remainder exists
		beq.b	.norem		 ; no then no point doing the rest..
		move.w	d1,d0    ; copy remainder to safe reg
	
		muls	#$1000,d0    ; multiply remainder by 4096
		divs	d2,d0          ; divide it by original
		asl.w	#4,d0         ; shift fraction result up
		move.w	d0,d1   ; copy fraction to our delta result

.norem		move.l	d1,osc_posdelta(a0)   ; delta result

Last edited by h0ffman; 06 February 2015 at 15:41. Reason: better comments
h0ffman is offline  
Old 06 February 2015, 23:22   #12
Nekoniaow
Banned
 
Join Date: Dec 2014
Location: Montreal
Posts: 129
If you are short on time I would recommend using a 16 bit fraction, this allows you to just do a swap to obtain the integer value after rounding which I seem to recall is faster than a 4 bit shift.
Nekoniaow is offline  
Old 07 February 2015, 17:37   #13
Mrs Beanbag
Glastonbridge Software
 
Mrs Beanbag's Avatar
 
Join Date: Jan 2012
Location: Edinburgh/Scotland
Posts: 2,243
it is certainly faster than a multiply, indeed why multiply by 4096? this way you end up with bottom 4 bits zero, you've lost 4 bits of precision already.

you will need to account for the sign of the remainder (if the dividend might be negative. the sign of the remainder is the same as the sign of the dividend)
Mrs Beanbag is offline  
Old 18 March 2015, 23:11   #14
Photon
Moderator
 
Photon's Avatar
 
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,602
Didn't think of moving this to the Assembler forum when I replied. Bad me. Now corrected
Photon is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
What's the point? Mounty project.WHDLoad 7 24 January 2013 23:18
Any point upgrading to WB 3.9? nixxjsteve support.Apps 3 10 January 2011 14:12
Found -> Galactic (Was: Looks like Woody's World but with floating king(s) ) killergorilla Looking for a game name ? 12 24 March 2006 15:51
Floating menus? Mojo2000 New to Emulation or Amiga scene 6 30 January 2003 14:35
Is there any point????? backtoskooldaze support.Hardware 1 06 April 2002 06:27

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 01:06.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.13502 seconds with 13 queries