95 lines
2.1 KiB
ArmAsm
95 lines
2.1 KiB
ArmAsm
.syntax unified
|
|
|
|
/*
|
|
* Calculates rx / 10 and places the result in rd. Clobbers the value of
|
|
* temporary register rt. The value in rx is unmodified.
|
|
*
|
|
* 0xCCCCCCCD >> 35 approximately equals 0.1
|
|
* Performs a 64 bit multiply of 0xCCCCCCCD and rx, shifts the high 32 bits
|
|
* by 3, and discards the low bits. This results in a division by 10 that
|
|
* works for all unsigned values of rx. This satifies the constraints of
|
|
* the Granlund-Montgomery integer division algorithm.
|
|
*/
|
|
.macro udiv10 rd, rx, rt
|
|
ldr \rt, =0xCCCCCCCD
|
|
umull \rt, \rd, \rx, \rt
|
|
lsrs \rd, $3
|
|
.endm
|
|
|
|
.macro udiv100 rd, rx, rt
|
|
ldr \rt, =0x51EB851F
|
|
umull \rt, \rd, \rx, \rt
|
|
lsrs \rd, $5
|
|
.endm
|
|
|
|
.macro udiv1000 rd, rx, rt
|
|
ldr \rt, =0x10624DD3
|
|
umull \rt, \rd, \rx, \rt
|
|
lsrs \rd, $6
|
|
.endm
|
|
|
|
.macro udiv10000 rd, rx, rt
|
|
ldr \rt, =0xD1B71759
|
|
umull \rt, \rd, \rx, \rt
|
|
lsrs \rd, $13
|
|
.endm
|
|
|
|
/*
|
|
* When using the Granlund-Montgomery integer division algorithm, the magic
|
|
* number produced does not fit inside the int32 range. GM produces:
|
|
* m = 0x14F8B588F
|
|
* k = 17
|
|
*
|
|
* This division uses the output produces by clang for a division by 100000.
|
|
* I don't understand why it works, but it does. It also needs one extra
|
|
* temporary register to preserve the value of rx.
|
|
*/
|
|
.macro udiv100000 rd, rx, rt, rtt
|
|
lsr \rtt, \rx, $5
|
|
ldr \rt, =0xA7C5AC5
|
|
umull \rt, \rd, \rtt, \rt
|
|
lsrs \rd, $7
|
|
.endm
|
|
|
|
.macro udiv1000000 rd, rx, rt
|
|
ldr \rt, =0x431BDE83
|
|
umull \rt, \rd, \rx, \rt
|
|
lsrs \rd, $18
|
|
.endm
|
|
|
|
.macro udiv10000000 rd, rx, rt
|
|
ldr \rt, =0x6B5FCA6B
|
|
umull \rt, \rd, \rx, \rt
|
|
lsrs \rd, $22
|
|
.endm
|
|
|
|
.macro udiv100000000 rd, rx, rt
|
|
ldr \rt, =0x55E63B89
|
|
umull \rt, \rd, \rx, \rt
|
|
lsrs \rd, $25
|
|
.endm
|
|
|
|
/*
|
|
* Same situation as udiv100000
|
|
*/
|
|
.macro udiv1000000000 rd, rx, rt, rtt
|
|
lsr \rtt, \rx, $9
|
|
ldr \rt, =0x44B83
|
|
umull \rt, \rd, \rtt, \rt
|
|
lsrs \rd, $7
|
|
.endm
|
|
|
|
/*
|
|
* Calculates rx % 10 and places the result in rd. Clobbers the value of
|
|
* temporary register rt
|
|
*
|
|
* Calculates the modulo by calculating the truncated division by 10,
|
|
* multiplying by 10, and finding the difference between the original value.
|
|
*/
|
|
.macro umod10 rd, rx, rt
|
|
udiv10 \rd, \rx, \rt
|
|
mov \rt, $10
|
|
mul \rd, \rt
|
|
subs \rd, \rx, \rd
|
|
.endm
|