-
Notifications
You must be signed in to change notification settings - Fork 3
/
conv.s
162 lines (147 loc) · 2.57 KB
/
conv.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
@ Copyright (c) 2009, Gerard Lledo Vives <[email protected]>
@ This program is open source. For license terms, see the LICENSE file.
.include "regdefs.asi"
.include "flags.asi"
.include "syscalls.asi"
.include "lib.asi"
.align 2
.text
.global parse_num
.global print_num
.global get_base
.global set_base
@ r0 => (char *) r1 => length of string
@ Returns the number in r0.
@ Z is set if no valid number can be parsed
parse_num:
push {lr}
mov r5, r0
push {r1}
bl get_base
mov r3, r0
pop {r1}
mov r2, #0
@ Positive or negative number?
ldrb r0, [r5]
cmp r0, #0x2D @ '-'
addeq r5, #1
subeq r1, #1
moveq r4, #-1
movne r4, #1
.Lparse_num_repeat:
cmp r1, #0
beq .Lparse_num_end
sub r1, #1
ldrb r0, [r5, r1]
push {r1}
mov r1, r3
bl isdigit
pop {r1}
bne .Lparse_num_error
sub r0, #0x30
cmp r0, #10
subpl r0, #0x7
mla r2, r4, r0, r2
mul r4, r3
b .Lparse_num_repeat
.Lparse_num_error:
Z_CLEAR
.Lparse_num_end:
Z_REVERT
mov r0, r2
pop {lr}
bx lr
@ In:
@ * r0 (uint32_t) => Number to convert
@ Out:
@ * r0 (char *) => Addres to a 16 bytes buffer
@ * r1 (uint32_t) => Length of r0
print_num:
push {lr}
ldr r1, .Lbuffer_word
ldr r2, .Lbase
ldrb r4, [r2]
mov r3, #14
@ Handle negative numbers
tst r0, #0x80000000
beq .Lrestart
push {r0, r1}
putchar #0x2D
pop {r0, r1}
bic r0, #0x80000000
eor r0, #0x7F000000
eor r0, #0x00FF0000
eor r0, #0x0000FF00
eor r0, #0x000000FF
add r0, #1
.Lrestart:
push {r1, r3, r4}
mov r1, r4
cmp r1, #16
bleq div16
beq .Lprint_num_div_done
cmp r1, #10
bleq div10
beq .Lprint_num_div_done
exit #2
.Lprint_num_div_done:
mov r2, r1
pop {r1, r3, r4}
cmp r2, #10
addlt r2, #48 @ r0 + '0'
addge r2, #55 @ r0 + ('A' - 10)
sub r3, #1
strb r2, [r1, r3]
cmp r0, #0
bne .Lrestart
ldr r0, .Lbuffer_word
add r0, r0, r3
rsb r1, r3, #14
pop {lr}
bx lr
get_base:
ldr r1, .Lbase
ldrb r0, [r1]
bx lr
set_base:
ldr r1, .Lbase
strb r0, [r1]
bx lr
@ Based on formula: R0 = ((R0 - (R0 >> 30)) * 429496730) >> 32
@ http://www.sciencezero.org/index.php?title=ARM:_Division_by_10
div10:
mov r3, r0
mov r4, #10
ldr r1, =429496730
sub r0, r0, r0, lsr #30
umull r2, r0, r1, r0
umull r1, r2, r4, r0
sub r1, r3, r1
bx lr
div16:
and r1, r0, #0xf
lsr r0, #4
bx lr
@ Input: r0 (numerator)
@ r1 (denominator)
@ Output: r0 (quotient)
@ r1 (remainder)
div:
mov r2, #0
.Ldiv_restart:
subs r0, r1
addpl r2, #1
bpl .Ldiv_restart
.Ldiv_end:
add r0, r1
mov r1, r0
mov r0, r2
bx lr
.Lbuffer_word:
.local buffer_8b
.word buffer_8b
.comm buffer_8b, 32, 4
.Lbase:
.local buffer_1b
.word buffer_1b
.comm buffer_1b, 1, 1