1: /* 2: * Program: ulrem.s 3: * Copyright 1993, GTE Government Systems 4: * Author: Steven M. Schultz 5: * 6: * Version Date Modification 7: * 0.0 02Feb91 1. Initial inspiration struck. 8: * 1.0 05Jun93 2. Released into the Public Domain. 9: */ 10: 11: #include "DEFS.h" 12: 13: /* 14: * All routines have both a C interface and an assembly interface. Normally 15: * the two are the same. In the case of 'ulsh' the compiler has placed one 16: * of the operands in r0 and r1 so the assembly interface differs from the 17: * C interface. 18: */ 19: 20: #define one 040200 21: 22: /* 23: * u_long ulrem(lhs, rhs) 24: * u_long lhs, rhs; 25: * 26: * 32-bit "%" routine. Calls to ulrem are generated automatically by the C 27: * compiler. 28: */ 29: 30: #if !defined(KERNEL) 31: /* 32: * ulrem for applications (uses floating point). 33: */ 34: 35: .globl ulrem 36: .globl l2f, l6f 37: 38: ulrem: 39: ENTRY(ulrem) 40: jsr pc,l2f / 2(sp) -> fr0 41: movf fr0,fr2 / put in right place (fr2) 42: jsr pc,l6f / 6(sp) -> fr3 43: tstf fr3 / check for division by zero 44: cfcc / don't want FP trap during 45: beq 1f / integer arithmetic 46: divf fr3,fr0 / fr0 = lhs/rhs 47: modf $one,fr0 / fr0 = integer((lhs/rhs) * 1.0) 48: mulf fr3,fr1 / fr0 = integer(lhs/rhs) * rhs 49: subf fr1,fr2 / fr2 = lhs - (integer(*lhs/rhs) * rhs) 50: 1: 51: movfi fr2,-(sp) / (result) 52: mov (sp)+,r0 53: mov (sp)+,r1 54: seti 55: rts pc 56: #else 57: /* 58: * ulrem for the kernel (uses only fixed point - no FP) 59: */ 60: .globl ulrem 61: ulrem: 62: ENTRY(ulrem) 63: mov r2,-(sp) / faster than csv/cret ... 64: mov r3,-(sp) 65: mov r4,-(sp) 66: mov 8.(sp),r0 / r0 = hi(lhs) 67: mov 10.(sp),r1 / r1 = lo(lhs) 68: mov 12.(sp),r2 / r2 = hi(rhs) 69: mov 14.(sp),r3 / r3 = lo(rhs) 70: bne 3f 71: tst r2 72: beq 9f / check for divide by 0 73: 3: 74: clr r4 / init scale of lhs 75: 2: 76: ashc $1,r0 77: blos 1f / check for zero at same time 78: inc r4 79: br 2b 80: 1: 81: mov r4,-(sp) / save scale of lhs 82: clr r4 83: 2: 84: asl r3 85: rol r2 86: bcs 1f 87: inc r4 / bump rhs scale 88: br 2b 89: 1: 90: clr r0 91: mov $1,r1 92: sub (sp)+,r4 / difference in scale (rhs - lhs) 93: ashc r4,r0 / initial quotient adder 94: mov r1,-(sp) / quoadder lo 95: mov r0,-(sp) / quoadder hi 96: mov 12.(sp),r0 / r0 = hi(lhs) 97: mov 14.(sp),r1 / r1 = lo(lhs) 98: mov 16.(sp),r2 / r2 = hi(rhs) 99: mov 18.(sp),r3 / r3 = lo(rhs) 100: 101: ashc r4,r2 / scale rhs up for repetitive subtraction 102: clr r4 / quo lo 103: clr -(sp) / quo hi 104: docmp1: 105: cmp r2,r0 106: bhi noadd1 107: blo dosub1 108: cmp r3,r1 109: bhi noadd1 110: dosub1: 111: sub r3,r1 112: sbc r0 113: sub r2,r0 114: add 4(sp),r4 / quo lo += quoadder lo 115: adc (sp) / quo hi 116: add 2(sp),(sp) / quo hi += quoadder hi 117: br docmp1 118: noadd1: 119: clc / right shift rhs 120: ror r2 121: ror r3 122: clc / right shift quotient adder 123: ror 2(sp) 124: ror 4(sp) 125: bne docmp1 / quo adder not 0 means more to do 126: tst 2(sp) 127: bne docmp1 128: add $6,sp / remove quo adder and quo high 129: 9: 130: mov (sp)+,r4 / r0,r1 have remainder 131: mov (sp)+,r3 132: mov (sp)+,r2 133: rts pc 134: #endif KERNEL 135: 136: /* 137: * u_long ualrem(lhs, rhs) 138: * u_long *lhs, rhs; 139: * 140: * 32-bit "/=" routine. Calls to ualrem are generated automatically by the C 141: * compiler. 142: */ 143: 144: .globl ualrem 145: ualrem: 146: ENTRY(ualrem) 147: mov r2,-(sp) / need a register to point at the lhs 148: mov 8.(sp),-(sp) / The rem algorithm is long 149: mov 8.(sp),-(sp) / enough that it just doesn't make sense 150: mov 8.(sp),r2 / to bother repeating it. We just translate 151: mov 2(r2),-(sp) / the call for ulrem and let it do the work 152: mov (r2),-(sp) / and return its results (also stuffing it 153: jsr pc,ulrem / into *lhs) 154: add $8.,sp / clean up stack 155: mov r0,(r2)+ / store high word, 156: mov r1,(r2) / and low 157: mov (sp)+,r2 / restore r2 158: rts pc / and return