# 2.11BSD#431 - /usr/src/lib/libc/pdp/crt/ldiv.s

##### Functions

    ldiv              X

##### Macros

    negl              X

       1: /*
       2:  * Copyright (c) 1987 Regents of the University of California.
       3:  * All rights reserved.  The Berkeley software License Agreement
       4:  * specifies the terms and conditions for redistribution.
       5:  */
       6:
       7: #ifdef LIBC_SCCS
       8:         <@(#)ldiv.s	2.4 (GTE) 12/26/92\0>
       9:         .even
      10: #endif LIBC_SCCS
      11:
      12: /*
      13:  * ldiv(lhs, rhs)
      14:  *	long	lhs, rhs;
      15:  *
      16:  * 32-bit "/" routine.  Calls to ldiv are generated automatically by the C
      17:  * compiler.
      18:  */
      19: #include "DEFS.h"
      20:
      21: #if !defined(KERNEL)
      22: /*
      23:  * Ldiv for floating point hardware.  Check for divide by zero.  Don't want
      24:  * floating divide trap in integer math.
      25:  */
      26: ASENTRY(ldiv)
      27:         tst     6(sp)           / divide by zero check
      28:         bne     1f
      29:         tst     8.(sp)
      30:         bne     1f
      31:         mov     2(sp),r0
      32:         mov     4(sp),r1        / return lhs
      33:         rts     pc
      34: 1:
      35:         setl
      36:         movif   2(sp),fr0       / fr0 = lhs
      37:         movif   6(sp),fr1       / fr1 = rhs
      38:         divf    fr1,fr0         / fr0 /= rhs
      39:         movfi   fr0,-(sp)
      40:         mov     (sp)+,r0        / return result
      41:         mov     (sp)+,r1
      42:         seti
      43:         rts     pc
      44: #else
      45: /*
      46:  * Ldiv for fixed point hardware.
      47:  */
      48: #define negl(high, low) neg     high; \
      49:                         neg     low; \
      50:                         sbc     high    / high -= (low != 0)
      51:
      52: ASENTRY(ldiv)
      53:         mov     r2,-(sp)        / faster than csv/cret ...
      54:         mov     r3,-(sp)
      55:         mov     r4,-(sp)
      56:         mov     14.(sp),r3      / r3 = loint(rhs)
      57:         sxt     r4              / r4 = sign(rhs)
      58:         bpl     1f              / if (int)loint(rhs) < 0
      59:         neg     r3              /   r3 = asb(loint(rhs))
      60: 1:
      61:         cmp     r4,12.(sp)      / hiint(rhs) all sign bits?
      62:         bne     hardldiv        /   no, rhs >= 2^15
      63:
      64:         mov     10.(sp),r2      / r2 = loint(lhs)
      65:         mov     8.(sp),r1       / r1 = hiint(lhs)
      66:         bge     2f              / if lhs < 0
      67:         negl(r1, r2)            /   r1:r2 = abs(lhs)
      68:         com     r4              /   invert sign of result
      69: 2:
      70:         /*
      71: 	 * At this point we know what the sign of the result is going to be
      72: 	 * (r4), abs(rhs) < 2^15, we have the absolute value of rhs in
      73: 	 * r3 as a single word integer and the absolute value of lhs in
      74: 	 * r1 (hiint) and r2 (loint).  References to hiint(rhs), loint(lhs)
      75: 	 * and hiint(lhs) in the following comments actually refer to the
      76: 	 * absolute value of rhs and lhs.
      77: 	 *
      78: 	 * We perform a long division the same way you learned in school:
      79: 	 *	hiint(quo) = hiint(lhs) / loint(rhs)
      80: 	 *	tmp        = (hiint(lhs) % loint(rhs))<<16 | loint(lhs)
      81: 	 *	loint(quo) = tmp / loint(rhs)
      82: 	 */
      83:         mov     r4,-(sp)        / save sign of result
      84:         clr     r0              / r0 = hiint(lhs) / loint(rhs)
      85:         div     r3,r0           / r1 = hiint(lhs) % loint(rhs)
      86:         mov     r0,r4           / save high quotient
      87:         mov     r1,-(sp)        / stash hiint(tmp)
      88:         mov     r1,r0           / tmp=(hiint(lhs)%loint(rhs))<<16 | loint(lhs)
      89:         mov     r2,r1           / (r0:r1 = tmp)
      90:         div     r3,r0           / r0 = tmp / loint(rhs)
      91:         bvc     3f              / done if tmp/loint(rhs) < 2^15
      92:         /*
      93: 	 * Our second division overflowed leaving undefined values in
      94: 	 * registers.  This can only happen when:
      95: 	 *	tmp/loint(rhs) >= 2^15
      96: 	 *	tmp >= 2^15 * loint(rhs)
      97: 	 *	tmp >= 2^16 * (loint(rhs)/2)
      98: 	 *
      99: 	 * If we subtract 2^16 * loint(rhs) from both sides however, we get:
     100: 	 *	tmp - (2^16 * loint(rhs)) >= -(2^16 * (loint(rhs)/2))
     101: 	 *
     102: 	 * and then divide both sides by loint(rhs):
     103: 	 *	tmp/loint(rhs) - 2^16 >= -(2^15)
     104: 	 *
     105: 	 * which is a division that won't generate an overflow.  Finally:
     106: 	 *	tmp = quo*loint(rhs) + rem
     107: 	 *	tmp - (2^16 * loint(rhs)) = (quo - 2^16) * loint(rhs) + rem
     108: 	 *
     109: 	 * which is fine since all we're going for is a 16 bit quotient so the
     110: 	 * subtraction of 2^16 won't have any effect.  However, since we're
     111: 	 * now dividing a negative number and since the div instruction
     112: 	 * always generates a remainder the same sign as the dividend, if we
     113: 	 * get a non-zero remainder, we'll actually get:
     114: 	 *	(quo+1 - 2^16) * loint(rhs) + rem-loint(rhs)
     115: 	 *
     116: 	 * which means we'll have to adjust the quotient returned by
     117: 	 * subtracting one ...
     118: 	 */
     119:         mov     (sp),r0         / reload r0:r1 with tmp (regs may be
     120:         mov     r2,r1           /   clobbered by failed div)
     121:         sub     r3,r0           / r0:r1 -= 2^16 * loint(rhs)
     122:         div     r3,r0
     123:         tst     r1              / if (negative) remainder, subtract one from
     124:         sxt     r1              /   quotient
     125:         add     r1,r0           / cannot overflow!
     126: 3:
     127:         tst     (sp)+           / pop hiint(tmp) off stack
     128:         mov     r0,r1           / r1 (loint(quo)) = tmp / loint(rhs)
     129:         mov     r4,r0           / r0 (hiint(quo)) = hiint(lhs) / loint(rhs)
     130:         tst     (sp)+
     131:         bpl     ret
     132: negret:                         / if result should be negative
     133:         negl(r0, r1)            /   quo = -quo
     134: ret:
     135:         mov     (sp)+,r4        / restore registers
     136:         mov     (sp)+,r3
     137:         mov     (sp)+,r2
     138:         rts     pc
     139:
     140: /*
     141:  * The divisor (rhs) is known to be >= 2^15 so we perform a bit shift
     142:  * algorithm as only 16 cycles are needed:
     143:  *	long
     144:  *	hardldiv(lhs, rhs)
     145:  *		long	lhs, rhs;
     146:  *	{
     147:  *		int		flag;
     148:  *		long		hi_sreg, lo_sreg;
     149:  * 		unsigned int	quo, cnt;
     150:  *
     151:  *		flag = 0;
     152:  *		if (lhs < 0) {
     153:  *			lhs = -lhs;
     154:  *			flag = !flag;
     155:  *		}
     156:  *		if (rhs < 0) {
     157:  *			rhs = -rhs;
     158:  *			flag = !flag;
     159:  *		}
     160:  *		hi_sreg = hiint(lhs);
     161:  *		lo_sreg = loint(lhs)<<16;
     162:  *		quo = 0;
     163:  *		for (cnt = 16; cnt; cnt--) {
     164:  *			quo <<= 1;
     165:  *			qshiftl(&hi_sreg, &lo_sreg);
     166:  *			if (hi_sreg >= rhs) {
     167:  *				hi_sreg -= rhs;
     168:  *				quo |= 1;
     169:  *			}
     170:  *		}
     171:  *		return((long)(flag ? -quo : quo));
     172:  *	}
     173:  * The assembly version of the above algorithm uses r2, r0 and r1 to implement
     174:  * hi_sreg, lo_sreg and quo by putting lhs into r0:r1 and zeroing r2 thereby
     175:  * creating a three word register r2:r0:r1 with hi_sreg = r2:r0, lo_sreg =
     176:  * r0:r1, and quo = r1 (using the unused bits in r1 as they become available
     177:  * after the shift in the loop) ...
     178:  */
     179: hardldiv:
     180:         mov     10.(sp),r1      / r1 = loint(lhs)
     181:         mov     8.(sp),r0       / r0 = hiint(lhs)
     182:         sxt     -(sp)           / flag = sign(lhs)
     183:         bpl     1f              / if lhs < 0
     184:         negl(r0, r1)            /   r0:r1 = abs(lhs)
     185: 1:
     186:         mov     14.(sp),r3      / r3 = hiint(rhs)
     187:         bge     2f              / if rhs < 0
     188:         negl(r3, 16.(sp))       /   rhs = -rhs (r3:loint(rhs))
     189:         com     (sp)            /   flag = !flag
     190: 2:
     191:         clr     r2              / clear top of shift register
     192:         mov     $16.,r4         / loop 16 times
     193: 3:
     194:         clc                     / shift combined shift register and quotient
     195:         rol     r1              /   left one place
     196:         rol     r0
     197:         rol     r2
     198:         cmp     r3,r2           / How do r2:r0 (hi_sreg) and rhs compare?
     199:         bgt     4f
     200:         blt     5f
     201:         cmp     16.(sp),r0
     202:         blos    5f
     203: 4:
     204:         sob     r4,3b           / r2:r0 (hi_sreg) < rhs:
     205:         br      6f              /   just loop
     206: 5:
     207:         sub     16.(sp),r0      / r2:r0 (hi_sreg) >= rhs
     208:         sbc     r2              /   subtract rhs from r2:r0 (hi_sreg)
     209:         sub     r3,r2
     210:         inc     r1              /   set bit in quotient
     211:         sob     r4,3b           /   and loop
     212: 6:
     213:         clr     r0              / clear upper word of quotient
     214:         tst     (sp)+           / test negative flag
     215:         bge     ret             /   and head off to the appropriate return
     216:         br      negret
     217: #endif

#### Defined functions

hardldiv defined in line 179; used 1 times

- in line 62

ldiv defined in line 52; never used
negret defined in line 132; used 1 times

- in line 216

ret defined in line 134; used 2 times

- in line 131, 215

#### Defined macros

negl defined in line 48; used 4 times

- in line 67, 133, 184-188(2)

Last modified: 1992-12-27 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 848 |