149 lines
5.4 KiB
ArmAsm
149 lines
5.4 KiB
ArmAsm
/* 32 and 64-bit millicode, original author Hewlett-Packard
|
|
adapted for gcc by Paul Bame <bame@debian.org>
|
|
and Alan Modra <alan@linuxcare.com.au>.
|
|
|
|
Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
|
|
|
|
This file is part of GCC and is released under the terms of
|
|
of the GNU General Public License as published by the Free Software
|
|
Foundation; either version 2, or (at your option) any later version.
|
|
See the file COPYING in the top-level GCC source directory for a copy
|
|
of the license. */
|
|
|
|
#include "milli.h"
|
|
|
|
#ifdef L_remU
|
|
/* ROUTINE: $$remU
|
|
. Single precision divide for remainder with unsigned binary integers.
|
|
.
|
|
. The remainder must be dividend-(dividend/divisor)*divisor.
|
|
. Divide by zero is trapped.
|
|
|
|
INPUT REGISTERS:
|
|
. arg0 == dividend
|
|
. arg1 == divisor
|
|
. mrp == return pc
|
|
. sr0 == return space when called externally
|
|
|
|
OUTPUT REGISTERS:
|
|
. arg0 = undefined
|
|
. arg1 = undefined
|
|
. ret1 = remainder
|
|
|
|
OTHER REGISTERS AFFECTED:
|
|
. r1 = undefined
|
|
|
|
SIDE EFFECTS:
|
|
. Causes a trap under the following conditions: DIVIDE BY ZERO
|
|
. Changes memory at the following places: NONE
|
|
|
|
PERMISSIBLE CONTEXT:
|
|
. Unwindable.
|
|
. Does not create a stack frame.
|
|
. Suitable for internal or external millicode.
|
|
. Assumes the special millicode register conventions.
|
|
|
|
DISCUSSION:
|
|
. Calls other millicode routines using mrp: NONE
|
|
. Calls other millicode routines: NONE */
|
|
|
|
|
|
RDEFINE(temp,r1)
|
|
RDEFINE(rmndr,ret1) /* r29 */
|
|
SUBSPA_MILLI
|
|
ATTR_MILLI
|
|
.export $$remU,millicode
|
|
.proc
|
|
.callinfo millicode
|
|
.entry
|
|
GSYM($$remU)
|
|
ldo -1(arg1),temp /* is there at most one bit set ? */
|
|
and,= arg1,temp,r0 /* if not, don't use power of 2 */
|
|
b LREF(regular_seq)
|
|
addit,= 0,arg1,r0 /* trap on div by zero */
|
|
and arg0,temp,rmndr /* get the result for power of 2 */
|
|
MILLIRETN
|
|
LSYM(regular_seq)
|
|
comib,>=,n 0,arg1,LREF(special_case)
|
|
subi 0,arg1,rmndr /* clear carry, negate the divisor */
|
|
ds r0,rmndr,r0 /* set V-bit to 1 */
|
|
add arg0,arg0,temp /* shift msb bit into carry */
|
|
ds r0,arg1,rmndr /* 1st divide step, if no carry */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 2nd divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 3rd divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 4th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 5th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 6th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 7th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 8th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 9th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 10th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 11th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 12th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 13th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 14th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 15th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 16th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 17th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 18th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 19th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 20th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 21st divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 22nd divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 23rd divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 24th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 25th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 26th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 27th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 28th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 29th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 30th divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 31st divide step */
|
|
addc temp,temp,temp /* shift temp with/into carry */
|
|
ds rmndr,arg1,rmndr /* 32nd divide step, */
|
|
comiclr,<= 0,rmndr,r0
|
|
add rmndr,arg1,rmndr /* correction */
|
|
MILLIRETN
|
|
nop
|
|
|
|
/* Putting >= on the last DS and deleting COMICLR does not work! */
|
|
LSYM(special_case)
|
|
sub,>>= arg0,arg1,rmndr
|
|
copy arg0,rmndr
|
|
MILLIRETN
|
|
nop
|
|
.exit
|
|
.procend
|
|
.end
|
|
#endif
|