1 2 3/* $OpenBSD: __remqu.S,v 1.1 2007/11/25 18:25:34 deraadt Exp $ */ 4/* $NetBSD: divrem.m4,v 1.5 1996/10/17 04:26:25 cgd Exp $ */ 5 6/* 7 * Copyright (c) 1994, 1995 Carnegie-Mellon University. 8 * All rights reserved. 9 * 10 * Author: Chris G. Demetriou 11 * 12 * Permission to use, copy, modify and distribute this software and 13 * its documentation is hereby granted, provided that both the copyright 14 * notice and this permission notice appear in all copies of the 15 * software, derivative works or modified versions, and any portions 16 * thereof, and that both notices appear in supporting documentation. 17 * 18 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 19 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 20 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 21 * 22 * Carnegie Mellon requests users of this software to return to 23 * 24 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 25 * School of Computer Science 26 * Carnegie Mellon University 27 * Pittsburgh PA 15213-3890 28 * 29 * any improvements or extensions that they make and grant Carnegie the 30 * rights to redistribute these changes. 31 */ 32 33/* 34 * Division and remainder. 35 * 36 * The use of m4 is modeled after the sparc code, but the algorithm is 37 * simple binary long division. 38 * 39 * Note that the loops could probably benefit from unrolling. 40 */ 41 42/* 43 * M4 Parameters 44 * __remqu name of function to generate 45 * rem rem=div: t10 / t11 -> t12; rem=rem: t10 % t11 -> t12 46 * false false=true: signed; false=false: unsigned 47 * 64 total number of bits 48 */ 49 50 51 52 53 54 55 56 57 58 59 60#include <machine/asm.h> 61 62LEAF(__remqu, 0) /* XXX */ 63 lda sp, -64(sp) 64 stq t0, 0(sp) 65 stq t1, 8(sp) 66 stq t2, 16(sp) 67 stq t3, 24(sp) 68 69 stq t10, 40(sp) 70 stq t11, 48(sp) 71 mov zero, t12 /* Initialize result to zero */ 72 73 74 75 76 /* kill the special cases. */ 77 beq t11, Ldotrap /* division by zero! */ 78 79 cmpult t10, t11, t2 /* t10 < t11? */ 80 /* t12 is already zero, from above. t10 is untouched. */ 81 bne t2, Lret_result 82 83 cmpeq t10, t11, t2 /* t10 == t11? */ 84 cmovne t2, 1, t12 85 cmovne t2, zero, t10 86 bne t2, Lret_result 87 88 /* 89 * Find out how many bits of zeros are at the beginning of the divisor. 90 */ 91LBbits: 92 ldiq t3, 1 /* t1 = 0; t0 = 1<<64-1 */ 93 mov zero, t1 94 sll t3, 64-1, t0 95LBloop: 96 and t11, t0, t2 /* if bit in t11 is set, done. */ 97 bne t2, LAbits 98 addq t1, 1, t1 /* increment t1, bit */ 99 srl t0, 1, t0 100 cmplt t1, 64-1, t2 /* if t1 leaves one bit, done. */ 101 bne t2, LBloop 102 103LAbits: 104 beq t1, Ldodiv /* If t1 = 0, divide now. */ 105 ldiq t3, 1 /* t0 = 1<<64-1 */ 106 sll t3, 64-1, t0 107 108LAloop: 109 and t10, t0, t2 /* if bit in t10 is set, done. */ 110 bne t2, Ldodiv 111 subq t1, 1, t1 /* decrement t1, bit */ 112 srl t0, 1, t0 113 bne t1, LAloop /* If t1 != 0, loop again */ 114 115Ldodiv: 116 sll t11, t1, t11 /* t11 <<= i */ 117 ldiq t3, 1 118 sll t3, t1, t0 119 120Ldivloop: 121 cmpult t10, t11, t2 122 or t12, t0, t3 123 cmoveq t2, t3, t12 124 subq t10, t11, t3 125 cmoveq t2, t3, t10 126 srl t0, 1, t0 127 srl t11, 1, t11 128 beq t10, Lret_result 129 bne t0, Ldivloop 130 131Lret_result: 132 mov t10, t12 133 134 135 136 ldq t0, 0(sp) 137 ldq t1, 8(sp) 138 ldq t2, 16(sp) 139 ldq t3, 24(sp) 140 141 ldq t10, 40(sp) 142 ldq t11, 48(sp) 143 lda sp, 64(sp) 144 ret zero, (t9), 1 145 146Ldotrap: 147 ldiq a0, -2 /* This is the signal to SIGFPE! */ 148 call_pal PAL_gentrap 149 mov zero, t10 /* so that zero will be returned */ 150 151 br zero, Lret_result 152 153END(__remqu) 154