gba-x3dtest
diff src/fixed.c @ 4:78d1664c2443
- fixed sin_x16/cos_x16
- added fixed point header
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 14 Jun 2014 03:04:56 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/fixed.c Sat Jun 14 03:04:56 2014 +0300 1.3 @@ -0,0 +1,101 @@ 1.4 +#include "fixed.h" 1.5 + 1.6 +#if 0 1.7 +/* fast 16.16 division ripped from http://me.henri.net/fp-div.html */ 1.8 +int32_t x16div(register int32_t numerator, register int32_t denominator) 1.9 +{ 1.10 + register int32_t quotient; 1.11 + asm("num .req %[numerator] @ Map Register Equates\n\t" 1.12 + "den .req %[denominator]\n\t" 1.13 + "mod .req r2\n\t" 1.14 + "cnt .req r3\n\t" 1.15 + "quo .req r4\n\t" 1.16 + "sign .req r12\n\t" 1.17 + /* set sign and ensure numerator and denominator are positive */ 1.18 + "cmp den, #0 @ exceptioin if den == zero\n\t" 1.19 + "beq .div0\n\t" 1.20 + "eor sign, num, den @ sign = num ^ den\n\t" 1.21 + "rsbmi den, den, #0 @ den = -den if den < 0\n\t" 1.22 + "subs mod, den, #1 @ mod = den - 1\n\t" 1.23 + "beq .div1 @ return if den == 1\n\t" 1.24 + "movs cnt, num @ num = -num if num < 0\n\t" 1.25 + "rsbmi num, num, #0\n\t" 1.26 + /* skip if deniminator >= numerator */ 1.27 + "movs cnt, num, lsr #16 @ return if den >= num << 16\n\t" 1.28 + "bne .cont\n\t" 1.29 + "cmp den, num, lsl #16\n\t" 1.30 + "bhs .numLeDen\n\t" 1.31 + "\n.cont:\n\t" 1.32 + /* test if denominator is a power of two */ 1.33 + "tst den, mod @ if(den & (den - 1) == 0)\n\t" 1.34 + "beq .powerOf2 @ den is power of 2\n\t" 1.35 + /* count leading zeros */ 1.36 + "stmfd sp!, {r4} @ push r4 (quo) onto the stack\n\t" 1.37 + "mov cnt, #28 @ count difference in leading zeros\n\t" 1.38 + "mov mod, num, lsr #4 @ between num and den\n\t" 1.39 + "cmp den, mod, lsr #12; subls cnt, cnt, #16; movls mod, mod, lsr #16\n\t" 1.40 + "cmp den, mod, lsr #4 ; subls cnt, cnt, #8 ; movls mod, mod, lsr #8\n\t" 1.41 + "cmp den, mod ; subls cnt, cnt, #4 ; movls mod, mod, lsr #4\n\t" 1.42 + /* shift numerator left by cnt bits */ 1.43 + "mov num, num, lsl cnt @ mod:num = num << cnt\n\t" 1.44 + "mov quo, #0\n\t" 1.45 + "rsb den, den, #0 @ negate den for divide loop\n\t" 1.46 + /* skip cnt iterations in the divide loop */ 1.47 + "adds num, num, num @ start: num = mod:num / den\n\t" 1.48 + "add pc, pc, cnt, lsl #4 @ skip cnt x 4 x 4 iterations\n\t" 1.49 + "nop @ nop instruction takes care of pipeline\n\t" 1.50 + /* inner loop unrolled x 48 */ 1.51 + ".rept 47 @ inner loop x 48\n\t" 1.52 + " adcs mod, den, mod, lsl #1\n\t" 1.53 + " subcc mod, mod, den\n\t" 1.54 + " adc quo, quo, quo\n\t" 1.55 + " adds num, num, num\n\t" 1.56 + ".endr\n\t" 1.57 + "adcs mod, den, mod, lsl #1\n\t" 1.58 + "subcc mod, mod, den\n\t" 1.59 + "adc quo, quo, quo\n\t" 1.60 + /* negate quotient if signed */ 1.61 + "cmp sign, #0 @ negate quotient if sign < 0\n\t" 1.62 + "mov num, quo\n\t" 1.63 + "rsbmi num, num, #0\n\t" 1.64 + "ldmfd sp!, {r4} @ pop r4 (quo) off the stack\n\t" 1.65 + "mov pc, lr @return\n\t" 1.66 + /* divide by zero handler */ 1.67 + "\n.div0:\n\t" 1.68 + "mov num, #0\n\t" 1.69 + "mov pc, lr @return\n\t" 1.70 + /* divide by one handler */ 1.71 + "\n.div1:\n\t" 1.72 + "cmp sign, #0\n\t" 1.73 + "mov num, num, asl #16\n\t" 1.74 + "rsbmi num, num, #0\n\t" 1.75 + "mov pc, lr @return\n\t" 1.76 + /* numerator less than or equal to denominator handler */ 1.77 + "\n.numLeDen:\n\t" 1.78 + "mov num, #0 @ quotient = 0 if num < den\n\t" 1.79 + "moveq num, sign, asr #31 @ negate quotient if sign < 0\n\t" 1.80 + "orreq num, num, #1 @ quotient = 1 if num == den\n\t" 1.81 + "mov pc, lr @return\n\t" 1.82 + /* power of two handler */ 1.83 + "\n.powerOf2:\n\t" 1.84 + "mov cnt, #0\n\t" 1.85 + "cmp den, #(1 << 16); movhs cnt, #16 ; movhs den, den, lsr #16\n\t" 1.86 + "cmp den, #(1 << 8) ; addhs cnt, cnt, #8; movhs den, den, lsr #8\n\t" 1.87 + "cmp den, #(1 << 4) ; addhs cnt, cnt, #4; movhs den, den, lsr #4\n\t" 1.88 + "cmp den, #(1 << 2) ; addhi cnt, cnt, #3; addls cnt, cnt, den, lsr #1\n\t" 1.89 + "rsb mod, cnt, #32\n\t" 1.90 + "mov den, num, lsr #16 @ den:num = num << 16\n\t" 1.91 + "mov num, num, lsl #16\n\t" 1.92 + "mov num, num, lsr cnt @ num = num >> cnt | den << mod\n\t" 1.93 + "orr num, num, den, lsl mod\n\t" 1.94 + "cmp sign, #0\n\t" 1.95 + "rsbmi num, num, #0 @ negate quotient if sign < 0" 1.96 + /* output registers */ 1.97 + : [quotient] "=r" (quotient) 1.98 + /* input registers */ 1.99 + : [numerator] "0" (numerator), [denominator] "r" (denominator) 1.100 + /* clobbered registers */ 1.101 + : "r2" /* mod */, "r3" /* cnt */, "r12" /* sign */); 1.102 + return quotient; 1.103 +} 1.104 +#endif