summaryrefslogtreecommitdiff
path: root/nss/lib/freebl/mpi/mpi_mips.s
blob: 455792bbba2783fd1f8809dcf494ea24a9813fa1 (plain)
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
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <regdef.h>
        .set    noreorder
        .set    noat

        .section        .text, 1, 0x00000006, 4, 4
.text:
        .section        .text

        .ent    s_mpv_mul_d_add
        .globl  s_mpv_mul_d_add

s_mpv_mul_d_add: 
 #/* c += a * b */
 #void s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, 
 #			      mp_digit *c)
 #{
 #  mp_digit   a0, a1;	regs a4, a5
 #  mp_digit   c0, c1;  regs a6, a7
 #  mp_digit   cy = 0;  reg t2
 #  mp_word    w0, w1;  regs t0, t1
 #
 #  if (a_len) {
	beq	a1,zero,.L.1
	move	t2,zero		# cy = 0
	dsll32	a2,a2,0		# "b" is sometimes negative (?!?!)
	dsrl32	a2,a2,0		# This clears the upper 32 bits.
 #    a0 = a[0];
	lwu	a4,0(a0)
 #    w0 = ((mp_word)b * a0);
	dmultu	a2,a4
 #    if (--a_len) {
	addiu	a1,a1,-1
	beq	a1,zero,.L.2
 #      while (a_len >= 2) {
	sltiu	t3,a1,2
	bne	t3,zero,.L.3
 #	  a1     = a[1];
	lwu	a5,4(a0)
.L.4:
 #	  a_len -= 2;
        addiu	a1,a1,-2
 #	  c0     = c[0];
	lwu	a6,0(a3)
 #	  w0    += cy;
	mflo	t0
	daddu	t0,t0,t2
 #	  w0    += c0;
	daddu	t0,t0,a6
 #	  w1     = (mp_word)b * a1; 
	dmultu	a2,a5			#
 #	  cy     = CARRYOUT(w0);
	dsrl32	t2,t0,0
 #	  c[0]   = ACCUM(w0);
	sw	t0,0(a3)
 #	  a0     = a[2];
	lwu	a4,8(a0)
 #	  a     += 2;
	addiu	a0,a0,8
 #	  c1     = c[1];
	lwu	a7,4(a3)
 #	  w1    += cy;
	mflo	t1
	daddu	t1,t1,t2
 #	  w1    += c1;
	daddu	t1,t1,a7
 #	  w0     = (mp_word)b * a0;
	dmultu	a2,a4			#
 #	  cy     = CARRYOUT(w1);
	dsrl32	t2,t1,0
 #	  c[1]   = ACCUM(w1);
	sw	t1,4(a3)
 #	  c     += 2;
	addiu	a3,a3,8
	sltiu	t3,a1,2
	beq	t3,zero,.L.4
 #	  a1     = a[1];
	lwu	a5,4(a0)
 #      }
.L.3:
 #      c0       = c[0];
	lwu	a6,0(a3)
 #      w0      += cy;
 #      if (a_len) {
	mflo	t0
	beq	a1,zero,.L.5
	daddu	t0,t0,t2
 #	  w1     = (mp_word)b * a1; 
	dmultu	a2,a5
 #	  w0    += c0;
	daddu	t0,t0,a6		#
 #	  cy     = CARRYOUT(w0);
	dsrl32	t2,t0,0
 #	  c[0]   = ACCUM(w0);
	sw	t0,0(a3)
 #	  c1     = c[1];
	lwu	a7,4(a3)
 #	  w1    += cy;
	mflo	t1
	daddu	t1,t1,t2
 #	  w1    += c1;
	daddu	t1,t1,a7
 #	  c[1]   = ACCUM(w1);
	sw	t1,4(a3)
 #	  cy     = CARRYOUT(w1);
	dsrl32	t2,t1,0
 #	  c     += 1;
	b	.L.6
	addiu	a3,a3,4
 #      } else {
.L.5:
 #	  w0    += c0;
	daddu	t0,t0,a6
 #	  c[0]   = ACCUM(w0);
	sw	t0,0(a3)
 #	  cy     = CARRYOUT(w0);
	b	.L.6
	dsrl32	t2,t0,0
 #      }
 #    } else {
.L.2:
 #      c0     = c[0];
	lwu	a6,0(a3)
 #      w0    += c0;
	mflo	t0
	daddu	t0,t0,a6
 #      c[0]   = ACCUM(w0);
	sw	t0,0(a3)
 #      cy     = CARRYOUT(w0);
	dsrl32	t2,t0,0
 #    }
.L.6:
 #    c[1] = cy;
	jr	ra
	sw	t2,4(a3)
 #  }
.L.1:
	jr	ra
	nop
 #}
 #
        .end    s_mpv_mul_d_add

        .ent    s_mpv_mul_d_add_prop
        .globl  s_mpv_mul_d_add_prop

s_mpv_mul_d_add_prop: 
 #/* c += a * b */
 #void s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, 
 #			      mp_digit *c)
 #{
 #  mp_digit   a0, a1;	regs a4, a5
 #  mp_digit   c0, c1;  regs a6, a7
 #  mp_digit   cy = 0;  reg t2
 #  mp_word    w0, w1;  regs t0, t1
 #
 #  if (a_len) {
	beq	a1,zero,.M.1
	move	t2,zero		# cy = 0
	dsll32	a2,a2,0		# "b" is sometimes negative (?!?!)
	dsrl32	a2,a2,0		# This clears the upper 32 bits.
 #    a0 = a[0];
	lwu	a4,0(a0)
 #    w0 = ((mp_word)b * a0);
	dmultu	a2,a4
 #    if (--a_len) {
	addiu	a1,a1,-1
	beq	a1,zero,.M.2
 #      while (a_len >= 2) {
	sltiu	t3,a1,2
	bne	t3,zero,.M.3
 #	  a1     = a[1];
	lwu	a5,4(a0)
.M.4:
 #	  a_len -= 2;
        addiu	a1,a1,-2
 #	  c0     = c[0];
	lwu	a6,0(a3)
 #	  w0    += cy;
	mflo	t0
	daddu	t0,t0,t2
 #	  w0    += c0;
	daddu	t0,t0,a6
 #	  w1     = (mp_word)b * a1; 
	dmultu	a2,a5			#
 #	  cy     = CARRYOUT(w0);
	dsrl32	t2,t0,0
 #	  c[0]   = ACCUM(w0);
	sw	t0,0(a3)
 #	  a0     = a[2];
	lwu	a4,8(a0)
 #	  a     += 2;
	addiu	a0,a0,8
 #	  c1     = c[1];
	lwu	a7,4(a3)
 #	  w1    += cy;
	mflo	t1
	daddu	t1,t1,t2
 #	  w1    += c1;
	daddu	t1,t1,a7
 #	  w0     = (mp_word)b * a0;
	dmultu	a2,a4			#
 #	  cy     = CARRYOUT(w1);
	dsrl32	t2,t1,0
 #	  c[1]   = ACCUM(w1);
	sw	t1,4(a3)
 #	  c     += 2;
	addiu	a3,a3,8
	sltiu	t3,a1,2
	beq	t3,zero,.M.4
 #	  a1     = a[1];
	lwu	a5,4(a0)
 #      }
.M.3:
 #      c0       = c[0];
	lwu	a6,0(a3)
 #      w0      += cy;
 #      if (a_len) {
	mflo	t0
	beq	a1,zero,.M.5
	daddu	t0,t0,t2
 #	  w1     = (mp_word)b * a1; 
	dmultu	a2,a5
 #	  w0    += c0;
	daddu	t0,t0,a6		#
 #	  cy     = CARRYOUT(w0);
	dsrl32	t2,t0,0
 #	  c[0]   = ACCUM(w0);
	sw	t0,0(a3)
 #	  c1     = c[1];
	lwu	a7,4(a3)
 #	  w1    += cy;
	mflo	t1
	daddu	t1,t1,t2
 #	  w1    += c1;
	daddu	t1,t1,a7
 #	  c[1]   = ACCUM(w1);
	sw	t1,4(a3)
 #	  cy     = CARRYOUT(w1);
	dsrl32	t2,t1,0
 #	  c     += 1;
	b	.M.6
	addiu	a3,a3,8
 #      } else {
.M.5:
 #	  w0    += c0;
	daddu	t0,t0,a6
 #	  c[0]   = ACCUM(w0);
	sw	t0,0(a3)
 #	  cy     = CARRYOUT(w0);
	dsrl32	t2,t0,0
	b	.M.6
	addiu	a3,a3,4
 #      }
 #    } else {
.M.2:
 #      c0     = c[0];
	lwu	a6,0(a3)
 #      w0    += c0;
	mflo	t0
	daddu	t0,t0,a6
 #      c[0]   = ACCUM(w0);
	sw	t0,0(a3)
 #      cy     = CARRYOUT(w0);
	dsrl32	t2,t0,0
	addiu	a3,a3,4
 #    }
.M.6:

 #    while (cy) {
	beq	t2,zero,.M.1
	nop
.M.7:
 #      mp_word w = (mp_word)*c + cy;
	lwu	a6,0(a3)
	daddu	t2,t2,a6
 #      *c++ = ACCUM(w);
	sw	t2,0(a3)
 #      cy = CARRYOUT(w);
	dsrl32	t2,t2,0
	bne	t2,zero,.M.7
	addiu	a3,a3,4

 #  }
.M.1:
	jr	ra
	nop
 #}
 #
        .end    s_mpv_mul_d_add_prop

        .ent    s_mpv_mul_d
        .globl  s_mpv_mul_d

s_mpv_mul_d: 
 #/* c = a * b */
 #void s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, 
 #			      mp_digit *c)
 #{
 #  mp_digit   a0, a1;	regs a4, a5
 #  mp_digit   cy = 0;  reg t2
 #  mp_word    w0, w1;  regs t0, t1
 #
 #  if (a_len) {
	beq	a1,zero,.N.1
	move	t2,zero		# cy = 0
	dsll32	a2,a2,0		# "b" is sometimes negative (?!?!)
	dsrl32	a2,a2,0		# This clears the upper 32 bits.
 #    a0 = a[0];
	lwu	a4,0(a0)
 #    w0 = ((mp_word)b * a0);
	dmultu	a2,a4
 #    if (--a_len) {
	addiu	a1,a1,-1
	beq	a1,zero,.N.2
 #      while (a_len >= 2) {
	sltiu	t3,a1,2
	bne	t3,zero,.N.3
 #	  a1     = a[1];
	lwu	a5,4(a0)
.N.4:
 #	  a_len -= 2;
        addiu	a1,a1,-2
 #	  w0    += cy;
	mflo	t0
	daddu	t0,t0,t2
 #	  cy     = CARRYOUT(w0);
	dsrl32	t2,t0,0
 #	  w1     = (mp_word)b * a1; 
	dmultu	a2,a5	
 #	  c[0]   = ACCUM(w0);
	sw	t0,0(a3)
 #	  a0     = a[2];
	lwu	a4,8(a0)
 #	  a     += 2;
	addiu	a0,a0,8
 #	  w1    += cy;
	mflo	t1
	daddu	t1,t1,t2
 #	  cy     = CARRYOUT(w1);
	dsrl32	t2,t1,0
 #	  w0     = (mp_word)b * a0;
	dmultu	a2,a4	
 #	  c[1]   = ACCUM(w1);
	sw	t1,4(a3)
 #	  c     += 2;
	addiu	a3,a3,8
	sltiu	t3,a1,2
	beq	t3,zero,.N.4
 #	  a1     = a[1];
	lwu	a5,4(a0)
 #      }
.N.3:
 #      w0      += cy;
 #      if (a_len) {
	mflo	t0
	beq	a1,zero,.N.5
	daddu	t0,t0,t2
 #	  w1     = (mp_word)b * a1; 
	dmultu	a2,a5			#
 #	  cy     = CARRYOUT(w0);
	dsrl32	t2,t0,0
 #	  c[0]   = ACCUM(w0);
	sw	t0,0(a3)
 #	  w1    += cy;
	mflo	t1
	daddu	t1,t1,t2
 #	  c[1]   = ACCUM(w1);
	sw	t1,4(a3)
 #	  cy     = CARRYOUT(w1);
	dsrl32	t2,t1,0
 #	  c     += 1;
	b	.N.6
	addiu	a3,a3,4
 #      } else {
.N.5:
 #	  c[0]   = ACCUM(w0);
	sw	t0,0(a3)
 #	  cy     = CARRYOUT(w0);
	b	.N.6
	dsrl32	t2,t0,0
 #      }
 #    } else {
.N.2:
	mflo	t0
 #      c[0]   = ACCUM(w0);
	sw	t0,0(a3)
 #      cy     = CARRYOUT(w0);
	dsrl32	t2,t0,0
 #    }
.N.6:
 #    c[1] = cy;
	jr	ra
	sw	t2,4(a3)
 #  }
.N.1:
	jr	ra
	nop
 #}
 #
        .end    s_mpv_mul_d


        .ent    s_mpv_sqr_add_prop
        .globl  s_mpv_sqr_add_prop
 #void   s_mpv_sqr_add_prop(const mp_digit *a, mp_size a_len, mp_digit *sqrs);
 #	registers
 #	a0		*a
 #	a1		a_len
 #	a2		*sqr
 #	a3		digit from *a, a_i
 #	a4		square of digit from a
 #	a5,a6		next 2 digits in sqr
 #	a7,t0		carry 
s_mpv_sqr_add_prop:
	move	a7,zero
	move	t0,zero
	lwu	a3,0(a0)
	addiu	a1,a1,-1	# --a_len
	dmultu	a3,a3
	beq	a1,zero,.P.3	# jump if we've already done the only sqr
	addiu	a0,a0,4		# ++a
.P.2:
        lwu	a5,0(a2)
        lwu	a6,4(a2)
	addiu	a2,a2,8		# sqrs += 2;
	dsll32	a6,a6,0
	daddu	a5,a5,a6
	lwu	a3,0(a0)
	addiu	a0,a0,4		# ++a
	mflo	a4
	daddu	a6,a5,a4
	sltu	a7,a6,a5	# a7 = a6 < a5	detect overflow
	dmultu	a3,a3
	daddu	a4,a6,t0
	sltu	t0,a4,a6
	add	t0,t0,a7
	sw	a4,-8(a2)
	addiu	a1,a1,-1	# --a_len
	dsrl32	a4,a4,0
	bne	a1,zero,.P.2	# loop if a_len > 0
	sw	a4,-4(a2)
.P.3:
        lwu	a5,0(a2)
        lwu	a6,4(a2)
	addiu	a2,a2,8		# sqrs += 2;
	dsll32	a6,a6,0
	daddu	a5,a5,a6
	mflo	a4
	daddu	a6,a5,a4
	sltu	a7,a6,a5	# a7 = a6 < a5	detect overflow
	daddu	a4,a6,t0
	sltu	t0,a4,a6
	add	t0,t0,a7
	sw	a4,-8(a2)
	beq	t0,zero,.P.9	# jump if no carry
	dsrl32	a4,a4,0
.P.8:
	sw	a4,-4(a2)
	/* propagate final carry */
	lwu	a5,0(a2)
	daddu	a6,a5,t0
	sltu	t0,a6,a5
	bne	t0,zero,.P.8	# loop if carry persists
	addiu	a2,a2,4		# sqrs++
.P.9:
	jr	ra
	sw	a4,-4(a2)

        .end    s_mpv_sqr_add_prop