1*2fe8fb19SBen Gras/* $NetBSD: divrem.m4,v 1.9 2002/01/21 23:40:41 ross Exp $ */ 2*2fe8fb19SBen Gras 3*2fe8fb19SBen Gras/* 4*2fe8fb19SBen Gras * Copyright (c) 1994, 1995 Carnegie-Mellon University. 5*2fe8fb19SBen Gras * All rights reserved. 6*2fe8fb19SBen Gras * 7*2fe8fb19SBen Gras * Author: Chris G. Demetriou 8*2fe8fb19SBen Gras * 9*2fe8fb19SBen Gras * Permission to use, copy, modify and distribute this software and 10*2fe8fb19SBen Gras * its documentation is hereby granted, provided that both the copyright 11*2fe8fb19SBen Gras * notice and this permission notice appear in all copies of the 12*2fe8fb19SBen Gras * software, derivative works or modified versions, and any portions 13*2fe8fb19SBen Gras * thereof, and that both notices appear in supporting documentation. 14*2fe8fb19SBen Gras * 15*2fe8fb19SBen Gras * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16*2fe8fb19SBen Gras * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 17*2fe8fb19SBen Gras * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18*2fe8fb19SBen Gras * 19*2fe8fb19SBen Gras * Carnegie Mellon requests users of this software to return to 20*2fe8fb19SBen Gras * 21*2fe8fb19SBen Gras * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 22*2fe8fb19SBen Gras * School of Computer Science 23*2fe8fb19SBen Gras * Carnegie Mellon University 24*2fe8fb19SBen Gras * Pittsburgh PA 15213-3890 25*2fe8fb19SBen Gras * 26*2fe8fb19SBen Gras * any improvements or extensions that they make and grant Carnegie the 27*2fe8fb19SBen Gras * rights to redistribute these changes. 28*2fe8fb19SBen Gras */ 29*2fe8fb19SBen Gras 30*2fe8fb19SBen Gras/* 31*2fe8fb19SBen Gras * Division and remainder. 32*2fe8fb19SBen Gras * 33*2fe8fb19SBen Gras * The use of m4 is modeled after the sparc code, but the algorithm is 34*2fe8fb19SBen Gras * simple binary long division. 35*2fe8fb19SBen Gras * 36*2fe8fb19SBen Gras * Note that the loops could probably benefit from unrolling. 37*2fe8fb19SBen Gras */ 38*2fe8fb19SBen Gras 39*2fe8fb19SBen Gras/* 40*2fe8fb19SBen Gras * M4 Parameters 41*2fe8fb19SBen Gras * NAME name of function to generate 42*2fe8fb19SBen Gras * OP OP=div: t10 / t11 -> t12; OP=rem: t10 % t11 -> t12 43*2fe8fb19SBen Gras * S S=true: signed; S=false: unsigned 44*2fe8fb19SBen Gras * WORDSIZE total number of bits 45*2fe8fb19SBen Gras */ 46*2fe8fb19SBen Gras 47*2fe8fb19SBen Grasdefine(A, `t10') 48*2fe8fb19SBen Grasdefine(B, `t11') 49*2fe8fb19SBen Grasdefine(RESULT, `t12') 50*2fe8fb19SBen Gras 51*2fe8fb19SBen Grasdefine(BIT, `t0') 52*2fe8fb19SBen Grasdefine(I, `t1') 53*2fe8fb19SBen Grasdefine(CC, `t2') 54*2fe8fb19SBen Grasdefine(T_0, `t3') 55*2fe8fb19SBen Grasifelse(S, `true', `define(NEG, `t4')') 56*2fe8fb19SBen Gras 57*2fe8fb19SBen Gras#include <machine/asm.h> 58*2fe8fb19SBen Gras 59*2fe8fb19SBen GrasLEAF(NAME, 0) /* XXX */ 60*2fe8fb19SBen Gras lda sp, -64(sp) 61*2fe8fb19SBen Gras stq BIT, 0(sp) 62*2fe8fb19SBen Gras stq I, 8(sp) 63*2fe8fb19SBen Gras stq CC, 16(sp) 64*2fe8fb19SBen Gras stq T_0, 24(sp) 65*2fe8fb19SBen Grasifelse(S, `true', 66*2fe8fb19SBen Gras` stq NEG, 32(sp)') 67*2fe8fb19SBen Gras stq A, 40(sp) 68*2fe8fb19SBen Gras stq B, 48(sp) 69*2fe8fb19SBen Gras mov zero, RESULT /* Initialize result to zero */ 70*2fe8fb19SBen Gras 71*2fe8fb19SBen Grasifelse(S, `true', 72*2fe8fb19SBen Gras` 73*2fe8fb19SBen Gras /* Compute sign of result. If either is negative, this is easy. */ 74*2fe8fb19SBen Gras or A, B, NEG /* not the sign, but... */ 75*2fe8fb19SBen Gras srl NEG, WORDSIZE - 1, NEG /* rather, or of high bits */ 76*2fe8fb19SBen Gras blbc NEG, Ldoit /* neither negative? do it! */ 77*2fe8fb19SBen Gras 78*2fe8fb19SBen Grasifelse(OP, `div', 79*2fe8fb19SBen Gras` xor A, B, NEG /* THIS is the sign! */ 80*2fe8fb19SBen Gras', ` mov A, NEG /* sign follows A. */ 81*2fe8fb19SBen Gras') 82*2fe8fb19SBen Gras srl NEG, WORDSIZE - 1, NEG /* make negation the low bit. */ 83*2fe8fb19SBen Gras 84*2fe8fb19SBen Gras srl A, WORDSIZE - 1, I /* is A negative? */ 85*2fe8fb19SBen Gras blbc I, LnegB /* no. */ 86*2fe8fb19SBen Gras /* A is negative; flip it. */ 87*2fe8fb19SBen Grasifelse(WORDSIZE, `32', ` 88*2fe8fb19SBen Gras /* top 32 bits may be random junk */ 89*2fe8fb19SBen Gras zap A, 0xf0, A 90*2fe8fb19SBen Gras') 91*2fe8fb19SBen Gras subq zero, A, A 92*2fe8fb19SBen Gras srl B, WORDSIZE - 1, I /* is B negative? */ 93*2fe8fb19SBen Gras blbc I, Ldoit /* no. */ 94*2fe8fb19SBen GrasLnegB: 95*2fe8fb19SBen Gras /* B is definitely negative, no matter how we got here. */ 96*2fe8fb19SBen Grasifelse(WORDSIZE, `32', ` 97*2fe8fb19SBen Gras /* top 32 bits may be random junk */ 98*2fe8fb19SBen Gras zap B, 0xf0, B 99*2fe8fb19SBen Gras') 100*2fe8fb19SBen Gras subq zero, B, B 101*2fe8fb19SBen GrasLdoit: 102*2fe8fb19SBen Gras') 103*2fe8fb19SBen Grasifelse(WORDSIZE, `32', ` 104*2fe8fb19SBen Gras /* 105*2fe8fb19SBen Gras * Clear the top 32 bits of each operand, as they may 106*2fe8fb19SBen Gras * sign extension (if negated above), or random junk. 107*2fe8fb19SBen Gras */ 108*2fe8fb19SBen Gras zap A, 0xf0, A 109*2fe8fb19SBen Gras zap B, 0xf0, B 110*2fe8fb19SBen Gras') 111*2fe8fb19SBen Gras 112*2fe8fb19SBen Gras /* kill the special cases. */ 113*2fe8fb19SBen Gras beq B, Ldotrap /* division by zero! */ 114*2fe8fb19SBen Gras 115*2fe8fb19SBen Gras cmpult A, B, CC /* A < B? */ 116*2fe8fb19SBen Gras /* RESULT is already zero, from above. A is untouched. */ 117*2fe8fb19SBen Gras bne CC, Lret_result 118*2fe8fb19SBen Gras 119*2fe8fb19SBen Gras cmpeq A, B, CC /* A == B? */ 120*2fe8fb19SBen Gras cmovne CC, 1, RESULT 121*2fe8fb19SBen Gras cmovne CC, zero, A 122*2fe8fb19SBen Gras bne CC, Lret_result 123*2fe8fb19SBen Gras 124*2fe8fb19SBen Gras /* 125*2fe8fb19SBen Gras * Find out how many bits of zeros are at the beginning of the divisor. 126*2fe8fb19SBen Gras */ 127*2fe8fb19SBen GrasLBbits: 128*2fe8fb19SBen Gras ldiq T_0, 1 /* I = 0; BIT = 1<<WORDSIZE-1 */ 129*2fe8fb19SBen Gras mov zero, I 130*2fe8fb19SBen Gras sll T_0, WORDSIZE-1, BIT 131*2fe8fb19SBen GrasLBloop: 132*2fe8fb19SBen Gras and B, BIT, CC /* if bit in B is set, done. */ 133*2fe8fb19SBen Gras bne CC, LAbits 134*2fe8fb19SBen Gras addq I, 1, I /* increment I, shift bit */ 135*2fe8fb19SBen Gras srl BIT, 1, BIT 136*2fe8fb19SBen Gras cmplt I, WORDSIZE-1, CC /* if I leaves one bit, done. */ 137*2fe8fb19SBen Gras bne CC, LBloop 138*2fe8fb19SBen Gras 139*2fe8fb19SBen GrasLAbits: 140*2fe8fb19SBen Gras beq I, Ldodiv /* If I = 0, divide now. */ 141*2fe8fb19SBen Gras ldiq T_0, 1 /* BIT = 1<<WORDSIZE-1 */ 142*2fe8fb19SBen Gras sll T_0, WORDSIZE-1, BIT 143*2fe8fb19SBen Gras 144*2fe8fb19SBen GrasLAloop: 145*2fe8fb19SBen Gras and A, BIT, CC /* if bit in A is set, done. */ 146*2fe8fb19SBen Gras bne CC, Ldodiv 147*2fe8fb19SBen Gras subq I, 1, I /* decrement I, shift bit */ 148*2fe8fb19SBen Gras srl BIT, 1, BIT 149*2fe8fb19SBen Gras bne I, LAloop /* If I != 0, loop again */ 150*2fe8fb19SBen Gras 151*2fe8fb19SBen GrasLdodiv: 152*2fe8fb19SBen Gras sll B, I, B /* B <<= i */ 153*2fe8fb19SBen Gras ldiq T_0, 1 154*2fe8fb19SBen Gras sll T_0, I, BIT 155*2fe8fb19SBen Gras 156*2fe8fb19SBen GrasLdivloop: 157*2fe8fb19SBen Gras cmpult A, B, CC 158*2fe8fb19SBen Gras or RESULT, BIT, T_0 159*2fe8fb19SBen Gras cmoveq CC, T_0, RESULT 160*2fe8fb19SBen Gras subq A, B, T_0 161*2fe8fb19SBen Gras cmoveq CC, T_0, A 162*2fe8fb19SBen Gras srl BIT, 1, BIT 163*2fe8fb19SBen Gras srl B, 1, B 164*2fe8fb19SBen Gras beq A, Lret_result 165*2fe8fb19SBen Gras bne BIT, Ldivloop 166*2fe8fb19SBen Gras 167*2fe8fb19SBen GrasLret_result: 168*2fe8fb19SBen Grasifelse(OP, `div', 169*2fe8fb19SBen Gras`', ` mov A, RESULT 170*2fe8fb19SBen Gras') 171*2fe8fb19SBen Grasifelse(S, `true', 172*2fe8fb19SBen Gras` 173*2fe8fb19SBen Gras /* Check to see if we should negate it. */ 174*2fe8fb19SBen Gras subq zero, RESULT, T_0 175*2fe8fb19SBen Gras cmovlbs NEG, T_0, RESULT 176*2fe8fb19SBen Gras') 177*2fe8fb19SBen Gras 178*2fe8fb19SBen Gras ldq BIT, 0(sp) 179*2fe8fb19SBen Gras ldq I, 8(sp) 180*2fe8fb19SBen Gras ldq CC, 16(sp) 181*2fe8fb19SBen Gras ldq T_0, 24(sp) 182*2fe8fb19SBen Grasifelse(S, `true', 183*2fe8fb19SBen Gras` ldq NEG, 32(sp)') 184*2fe8fb19SBen Gras ldq A, 40(sp) 185*2fe8fb19SBen Gras ldq B, 48(sp) 186*2fe8fb19SBen Gras lda sp, 64(sp) 187*2fe8fb19SBen Gras ret zero, (t9), 1 188*2fe8fb19SBen Gras 189*2fe8fb19SBen GrasLdotrap: 190*2fe8fb19SBen Gras ldiq a0, -2 /* This is the signal to SIGFPE! */ 191*2fe8fb19SBen Gras call_pal PAL_gentrap 192*2fe8fb19SBen Grasifelse(OP, `div', 193*2fe8fb19SBen Gras`', ` mov zero, A /* so that zero will be returned */ 194*2fe8fb19SBen Gras') 195*2fe8fb19SBen Gras br zero, Lret_result 196*2fe8fb19SBen Gras 197*2fe8fb19SBen GrasEND(NAME) 198