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