gba-x3dtest

annotate src/fixed.c @ 10:23f716fa7f10

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