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