69 lines
		
	
	
	
		
			1.6 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			69 lines
		
	
	
	
		
			1.6 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| #
 | |
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | |
| 
 | |
| /* Multiplies two double-precision floats, then splits the product into
 | |
|  *  fraction and integer, both as floats, like modf(3) in C,
 | |
|  *  http://en.cppreference.com/w/c/numeric/math/modf
 | |
|  *
 | |
|  * Stack: ( a b -- fraction integer )
 | |
|  */
 | |
| 
 | |
| .sect .text
 | |
| .define .fif8
 | |
| .fif8:
 | |
| 	ldc1 f0, 8(sp)          ! f0 = a
 | |
| 	ldc1 f2, 0(sp)          ! f2 = b
 | |
| 	mul.d f0, f0, f2        ! f0 = a * b
 | |
| 	abs.d f2, f0            ! f2 = abs(f0)
 | |
| 
 | |
| 	lui at, ha16[max_power_of_two]
 | |
| 	ldc1 f4, lo16[max_power_of_two] (at) ! f4 = max power of two
 | |
| 
 | |
| 	mov.d f6, f2            ! we're going to assemble the integer part in f6
 | |
| 	c.lt.d 0, f4, f2        ! if absolute value too big, it must be integral
 | |
| 	bc1t 0, return
 | |
| 	nop
 | |
| 
 | |
| 	! Crudely strip off the fractional part.
 | |
| 
 | |
| 	add.d f6, f2, f4        ! f6 = absolute value + max power of two
 | |
| 	sub.d f6, f6, f4        ! f6 -= max_power_of_two
 | |
| 
 | |
| 	! The above might round, so correct that.
 | |
| 
 | |
| 	lui at, ha16[one]
 | |
| 	ldc1 f8, lo16[one] (at)   ! f8 = 1.0
 | |
| 1:
 | |
| 	c.le.d 0, f6, f2        ! if result <= absolute value, stop
 | |
| 	bc1t 0, 2f
 | |
| 	nop
 | |
| 
 | |
| 	sub.d f6, f6, f8        ! result -= 1.0
 | |
| 	b 1b
 | |
| 	nop
 | |
| 2:
 | |
| 
 | |
| 	! Correct the sign of the result.
 | |
| 
 | |
| 	mtc1 zero, f8
 | |
| 	mthc1 zero, f8          ! f8 = 0.0
 | |
| 	c.lt.d 0, f0, f8        ! if original value was negative
 | |
| 	bc1f 0, 1f
 | |
| 	nop
 | |
| 	neg.d f6, f6            ! negate the result
 | |
| 1:
 | |
| 
 | |
| return:
 | |
| 	sdc1 f6, 0(sp)          ! store integer part
 | |
| 	sub.d f6, f0, f6        ! calculate fractional part
 | |
| 	sdc1 f6, 8(sp)          ! store fractional part
 | |
| 	jr ra
 | |
| 	nop
 | |
| 
 | |
| ! doubles >= MAXPOWTWO are already integers
 | |
| .sect .rom
 | |
| max_power_of_two:
 | |
| 	.dataf8 4.503599627370496000E+15
 | |
| 
 | |
| one:
 | |
| 	.dataf8 1.0
 |