llasm.s
4.31 KB
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#include "regdef.h"
/* long long __ll_mul (long long a, long long b) */
#ifdef _MIPSEL
# define RLSW v0
# define RMSW v1
# define ALSW a0
# define AMSW a1
# define BLSW a2
# define BMSW a3
#else /* _MIPSEB */
# define RMSW v0
# define RLSW v1
# define AMSW a0
# define ALSW a1
# define BMSW a2
# define BLSW a3
#endif
.text
/* note that result of AMSW * BMSW overflows 64bits, so it is ignored. */
.globl __ll_mul
.ent __ll_mul
__ll_mul:
.frame sp, 0, ra
multu ALSW, BLSW
mflo RLSW
mfhi RMSW
multu AMSW, BLSW
mflo t0
addu RMSW, t0
multu ALSW, BMSW
mflo t0
addu RMSW, t0
j ra
.end __ll_mul
/* __ull_divrem (unsigned long long *quotient, *remainder, dividend, divisor) */
# define MSH 0
# define LSH 2
# define MQUO 0(a0)
# define LQUO 4(a0)
# define MREM 0(a1)
# define LREM 4(a1)
# define MDEN a2
# define LDEN a3
# define MSOR 16(sp)
# define LSOR 20(sp)
/* ulldivrem (unsigned long long *quotient, unsigned long long *remainder,
* unsigned long long dividend, unsigned long long divisor); */
/* unsigned division */
/* assume that dividend is 64bit positive value;
* divisor is 16bit positive value. */
.globl __ull_divrem_6416
.ent __ull_divrem_6416
__ull_divrem_6416:
.frame sp, 0, ra
move t0, LDEN /* dividend */
move t1, MDEN
lw t2, LSOR /* divisor */
lw t3, MSOR
divu zero, t0, t2 /* early start for first case */
/* test if both dividend and divisor are 32-bit values */
sra t4, t0, 31
bnez t3, 3f /* divisor not 32-bit */
/* divisor is 32-bit */
bnez t1, 1f /* dividend not 32-bit */
/* simply use 32-bit divide instruction */
mflo v0
mfhi t4
sw v0, LQUO
sw zero, MQUO
sw t4, LREM
sw zero, MREM
j ra
/* divisor 32-bit, dividend not */
1: srl t4, t2, 16
bne t4, 0, 3f
/* dividing 64-bit positive value by 16-bit unsigned value */
#ifdef _MIPSEL
sll v0, MDEN, 16
#else
move v0, MDEN
#endif
srl v0, v0, 16 /* get 16-bit MSH value from MDEN */
divu zero, v0, t2
mflo v1
mfhi v0
sh v1, MSH+MQUO
sll v0, 16
#ifdef _MIPSEB
sll t0, MDEN, 16
#else
move t0, MDEN
#endif
srl t0, t0, 16 /* get 16-bit LSH value from MDEN */
or v0, t0
divu zero, v0, t2
mflo v1
mfhi v0
sh v1, LSH+MQUO
sll v0, 16
#ifdef _MIPSEL
sll t0, LDEN, 16
#else
move t0, LDEN
#endif
srl t0, t0, 16 /* get 16-bit MSH value from LDEN */
or v0, t0
divu zero, v0, t2
mflo v1
mfhi v0
sh v1, MSH+LQUO
sll v0, 16
#ifdef _MIPSEB
sll t0, LDEN, 16
#else
move t0, LDEN
#endif
srl t0, t0, 16 /* get 16-bit LSH value from LDEN */
or v0, t0
divu zero, v0, t2
mflo v1
mfhi v0
sh v1, LSH+LQUO
sw zero, MREM
sw v0, LREM
j ra
/* if dividend < divisor then quo = 0, rem = dividend */
3: lw t0, MSOR
bgtu MDEN, t0, 36f
bltu MDEN, t0, 32f
/* MDEN == MSOR */
lw t0, LSOR
bgeu LDEN, t0, 36f
32: sw zero, LQUO
sw zero, MQUO
sw LDEN, LREM
sw MDEN, MREM
j ra
/* dividend or divisor too big; have to do division the hard way */
36: break 0
.end __ull_divrem_6416
/* ulldivrem (unsigned long long *quotient, unsigned long long *remainder,
* unsigned long long dividend, unsigned long long divisor); */
/* unsigned division */
/* assume that dividend and divisor both fit in 53 bits,
* so do double fp divide. */
.globl __ull_divrem_5353
.ent __ull_divrem_5353
__ull_divrem_5353:
.frame sp, 0, ra
move t0, LDEN /* dividend */
move t1, MDEN
lw t2, LSOR /* divisor */
lw t3, MSOR
2: li.d $f8, 4294967296.0
cfc1 v1, $31
li t5, 1
ctc1 t5, $31
mtc1 t0, $f0
mtc1 t1, $f2
cvt.d.w $f0
cvt.d.w $f2
bgez t0, 22f
add.d $f0, $f8
22: mul.d $f2, $f8
add.d $f0, $f2
mtc1 t2, $f4
mtc1 t3, $f6
cvt.d.w $f4
cvt.d.w $f6
bgez t2, 24f
add.d $f4, $f8
24: mul.d $f6, $f8
add.d $f4, $f6
cfc1 t9, $31
and t9, 4
bne t9, 0, 3f
div.d $f2, $f0, $f4
li.d $f6, 4503599627370496.0
mfc1 t9, $f3
bgez t9, 26f
neg.d $f6
26: add.d $f2, $f6
mfc1 t4, $f2
mfc1 t5, $f3
and t5, 0x000fffff
multu t4, t2
mflo t6
mfhi t7
multu t4, t3
mflo t8
addu t7, t8
multu t5, t2
mflo t8
addu t7, t8
sltu t9, t0, t6
subu t6, t0, t6
subu t7, t1, t7
subu t7, t9
sw t4, LQUO
sw t5, MQUO
sw t6, LREM
sw t7, MREM
ctc1 v1, $31
j ra
/* if dividend < divisor then quo = 0, rem = dividend */
3: lw t0, MSOR
bgtu MDEN, t0, 36f
bltu MDEN, t0, 32f
/* MDEN == MSOR */
lw t0, LSOR
bgeu LDEN, t0, 36f
32: sw zero, LQUO
sw zero, MQUO
sw LDEN, LREM
sw MDEN, MREM
j ra
/* dividend or divisor too big; have to do division the hard way */
36: break 0
.end __ull_divrem_5353