gba-x3dtest
view 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 source
1 #include "fixed.h"
3 #if 0
4 /* fast 16.16 division ripped from http://me.henri.net/fp-div.html */
5 int32_t x16div(register int32_t numerator, register int32_t denominator)
6 {
7 register int32_t quotient;
8 asm("num .req %[numerator] @ Map Register Equates\n\t"
9 "den .req %[denominator]\n\t"
10 "mod .req r2\n\t"
11 "cnt .req r3\n\t"
12 "quo .req r4\n\t"
13 "sign .req r12\n\t"
14 /* set sign and ensure numerator and denominator are positive */
15 "cmp den, #0 @ exceptioin if den == zero\n\t"
16 "beq .div0\n\t"
17 "eor sign, num, den @ sign = num ^ den\n\t"
18 "rsbmi den, den, #0 @ den = -den if den < 0\n\t"
19 "subs mod, den, #1 @ mod = den - 1\n\t"
20 "beq .div1 @ return if den == 1\n\t"
21 "movs cnt, num @ num = -num if num < 0\n\t"
22 "rsbmi num, num, #0\n\t"
23 /* skip if deniminator >= numerator */
24 "movs cnt, num, lsr #16 @ return if den >= num << 16\n\t"
25 "bne .cont\n\t"
26 "cmp den, num, lsl #16\n\t"
27 "bhs .numLeDen\n\t"
28 "\n.cont:\n\t"
29 /* test if denominator is a power of two */
30 "tst den, mod @ if(den & (den - 1) == 0)\n\t"
31 "beq .powerOf2 @ den is power of 2\n\t"
32 /* count leading zeros */
33 "stmfd sp!, {r4} @ push r4 (quo) onto the stack\n\t"
34 "mov cnt, #28 @ count difference in leading zeros\n\t"
35 "mov mod, num, lsr #4 @ between num and den\n\t"
36 "cmp den, mod, lsr #12; subls cnt, cnt, #16; movls mod, mod, lsr #16\n\t"
37 "cmp den, mod, lsr #4 ; subls cnt, cnt, #8 ; movls mod, mod, lsr #8\n\t"
38 "cmp den, mod ; subls cnt, cnt, #4 ; movls mod, mod, lsr #4\n\t"
39 /* shift numerator left by cnt bits */
40 "mov num, num, lsl cnt @ mod:num = num << cnt\n\t"
41 "mov quo, #0\n\t"
42 "rsb den, den, #0 @ negate den for divide loop\n\t"
43 /* skip cnt iterations in the divide loop */
44 "adds num, num, num @ start: num = mod:num / den\n\t"
45 "add pc, pc, cnt, lsl #4 @ skip cnt x 4 x 4 iterations\n\t"
46 "nop @ nop instruction takes care of pipeline\n\t"
47 /* inner loop unrolled x 48 */
48 ".rept 47 @ inner loop x 48\n\t"
49 " adcs mod, den, mod, lsl #1\n\t"
50 " subcc mod, mod, den\n\t"
51 " adc quo, quo, quo\n\t"
52 " adds num, num, num\n\t"
53 ".endr\n\t"
54 "adcs mod, den, mod, lsl #1\n\t"
55 "subcc mod, mod, den\n\t"
56 "adc quo, quo, quo\n\t"
57 /* negate quotient if signed */
58 "cmp sign, #0 @ negate quotient if sign < 0\n\t"
59 "mov num, quo\n\t"
60 "rsbmi num, num, #0\n\t"
61 "ldmfd sp!, {r4} @ pop r4 (quo) off the stack\n\t"
62 "mov pc, lr @return\n\t"
63 /* divide by zero handler */
64 "\n.div0:\n\t"
65 "mov num, #0\n\t"
66 "mov pc, lr @return\n\t"
67 /* divide by one handler */
68 "\n.div1:\n\t"
69 "cmp sign, #0\n\t"
70 "mov num, num, asl #16\n\t"
71 "rsbmi num, num, #0\n\t"
72 "mov pc, lr @return\n\t"
73 /* numerator less than or equal to denominator handler */
74 "\n.numLeDen:\n\t"
75 "mov num, #0 @ quotient = 0 if num < den\n\t"
76 "moveq num, sign, asr #31 @ negate quotient if sign < 0\n\t"
77 "orreq num, num, #1 @ quotient = 1 if num == den\n\t"
78 "mov pc, lr @return\n\t"
79 /* power of two handler */
80 "\n.powerOf2:\n\t"
81 "mov cnt, #0\n\t"
82 "cmp den, #(1 << 16); movhs cnt, #16 ; movhs den, den, lsr #16\n\t"
83 "cmp den, #(1 << 8) ; addhs cnt, cnt, #8; movhs den, den, lsr #8\n\t"
84 "cmp den, #(1 << 4) ; addhs cnt, cnt, #4; movhs den, den, lsr #4\n\t"
85 "cmp den, #(1 << 2) ; addhi cnt, cnt, #3; addls cnt, cnt, den, lsr #1\n\t"
86 "rsb mod, cnt, #32\n\t"
87 "mov den, num, lsr #16 @ den:num = num << 16\n\t"
88 "mov num, num, lsl #16\n\t"
89 "mov num, num, lsr cnt @ num = num >> cnt | den << mod\n\t"
90 "orr num, num, den, lsl mod\n\t"
91 "cmp sign, #0\n\t"
92 "rsbmi num, num, #0 @ negate quotient if sign < 0"
93 /* output registers */
94 : [quotient] "=r" (quotient)
95 /* input registers */
96 : [numerator] "0" (numerator), [denominator] "r" (denominator)
97 /* clobbered registers */
98 : "r2" /* mod */, "r3" /* cnt */, "r12" /* sign */);
99 return quotient;
100 }
101 #endif