mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
237 lines
4.9 KiB
237 lines
4.9 KiB
/*
|
|
* |-----------------------------------------------------------|
|
|
* | Copyright (c) 1991 MIPS Computer Systems, Inc. |
|
|
* | All Rights Reserved |
|
|
* |-----------------------------------------------------------|
|
|
* | Restricted Rights Legend |
|
|
* | Use, duplication, or disclosure by the Government is |
|
|
* | subject to restrictions as set forth in |
|
|
* | subparagraph (c)(1)(ii) of the Rights in Technical |
|
|
* | Data and Computer Software Clause of DFARS 52.227-7013. |
|
|
* | MIPS Computer Systems, Inc. |
|
|
* | 950 DeGuigne Drive |
|
|
* | Sunnyvale, CA 94086 |
|
|
* |-----------------------------------------------------------|
|
|
*/
|
|
/* $Header: lldivrem.s,v 3010.3 92/01/29 15:27:35 murphy Exp $ */
|
|
|
|
#include <ksmips.h>
|
|
|
|
/* __ull_divrem (unsigned long long *quotient, *remainder, dividend, divisor) */
|
|
|
|
#ifdef _MIPSEL
|
|
# define LSH 0
|
|
# define MSH 2
|
|
# define LQUO 0(a0)
|
|
# define MQUO 4(a0)
|
|
# define LREM 0(a1)
|
|
# define MREM 4(a1)
|
|
# define LDEN a2
|
|
# define MDEN a3
|
|
# define LSOR 16(sp)
|
|
# define MSOR 20(sp)
|
|
#endif
|
|
#ifdef _MIPSEB
|
|
# 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)
|
|
#endif
|
|
|
|
.text
|
|
|
|
/* 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
|