1*6d3ceb1dSskrll; $NetBSD: milli_tiny.S,v 1.1 2014/02/24 07:23:43 skrll Exp $ 2*6d3ceb1dSskrll 3*6d3ceb1dSskrll; Copyright (c) 2003 ITOH Yasufumi. 4*6d3ceb1dSskrll; All rights reserved. 5*6d3ceb1dSskrll; 6*6d3ceb1dSskrll; Redistribution and use in source and binary forms, with or without 7*6d3ceb1dSskrll; modification, are permitted provided that the following conditions 8*6d3ceb1dSskrll; are met: 9*6d3ceb1dSskrll; 1. Redistributions of source code must retain the above copyright 10*6d3ceb1dSskrll; notice, this list of conditions and the following disclaimer. 11*6d3ceb1dSskrll; 2. Redistributions in binary forms are unlimited. 12*6d3ceb1dSskrll; 13*6d3ceb1dSskrll; THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' 14*6d3ceb1dSskrll; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15*6d3ceb1dSskrll; THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16*6d3ceb1dSskrll; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS 17*6d3ceb1dSskrll; BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18*6d3ceb1dSskrll; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19*6d3ceb1dSskrll; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20*6d3ceb1dSskrll; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21*6d3ceb1dSskrll; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22*6d3ceb1dSskrll; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23*6d3ceb1dSskrll; THE POSSIBILITY OF SUCH DAMAGE. 24*6d3ceb1dSskrll 25*6d3ceb1dSskrll; millicode library, optimized for size 26*6d3ceb1dSskrll 27*6d3ceb1dSskrll .level 1.0 28*6d3ceb1dSskrll .code 29*6d3ceb1dSskrll .align 4 30*6d3ceb1dSskrll 31*6d3ceb1dSskrll; $$divU unsigned division, return quotient 32*6d3ceb1dSskrll; 33*6d3ceb1dSskrll; inputs: 34*6d3ceb1dSskrll; %r26 dividend 35*6d3ceb1dSskrll; %r25 divisor 36*6d3ceb1dSskrll; %r31 return address 37*6d3ceb1dSskrll; outputs: 38*6d3ceb1dSskrll; %r29 quotient 39*6d3ceb1dSskrll; %r1, %r25, %r26 undefined 40*6d3ceb1dSskrll .export $$divU,millicode 41*6d3ceb1dSskrll$$divU: 42*6d3ceb1dSskrll .proc 43*6d3ceb1dSskrll .callinfo millicode,no_unwind 44*6d3ceb1dSskrll .entry 45*6d3ceb1dSskrll comb,<,n %r25,0,bigdivisor_divU ; special case (>=0x80000000) 46*6d3ceb1dSskrll bl sub_divU,%r29 47*6d3ceb1dSskrll subt,= %r0,%r25,%r1 ; trap divide by 0, negate 48*6d3ceb1dSskrll 49*6d3ceb1dSskrll bv %r0(%r31) ; return millicode 50*6d3ceb1dSskrll .exit 51*6d3ceb1dSskrll addc %r26,%r26,%r29 ; fix quotient 52*6d3ceb1dSskrllbigdivisor_divU: 53*6d3ceb1dSskrll comclr,<< %r26,%r25,%r29 ; if dividend >= divisor 54*6d3ceb1dSskrll ldi 1,%r29 ; quotient is 1 55*6d3ceb1dSskrll bv,n %r0(%r31) ; return millicode 56*6d3ceb1dSskrll .procend 57*6d3ceb1dSskrll 58*6d3ceb1dSskrll; Note this is not a normal subroutine 59*6d3ceb1dSskrll; r29: return address 60*6d3ceb1dSskrllsub_divU: 61*6d3ceb1dSskrll stwm %r19,64(%sp) 62*6d3ceb1dSskrll ldi 31,%r19 63*6d3ceb1dSskrll 64*6d3ceb1dSskrll ds %r0,%r1,%r0 65*6d3ceb1dSskrll addc %r26,%r26,%r26 66*6d3ceb1dSskrll ds %r0,%r25,%r1 67*6d3ceb1dSskrllloop_sub_divU: ; addc/ds 31 times 68*6d3ceb1dSskrll addc %r26,%r26,%r26 69*6d3ceb1dSskrll addib,<> -1,%r19,loop_sub_divU 70*6d3ceb1dSskrll ds %r1,%r25,%r1 71*6d3ceb1dSskrll 72*6d3ceb1dSskrll bv %r0(%r29) 73*6d3ceb1dSskrll ldwm -64(%sp),%r19 74*6d3ceb1dSskrll 75*6d3ceb1dSskrll; $$remU unsigned division, return remainder 76*6d3ceb1dSskrll; 77*6d3ceb1dSskrll; inputs: 78*6d3ceb1dSskrll; %r26 dividend 79*6d3ceb1dSskrll; %r25 divisor 80*6d3ceb1dSskrll; %r31 return address 81*6d3ceb1dSskrll; outputs: 82*6d3ceb1dSskrll; %r29 remainder 83*6d3ceb1dSskrll; %r1, %r25, %r26 undefined 84*6d3ceb1dSskrll .export $$remU,millicode 85*6d3ceb1dSskrll$$remU: 86*6d3ceb1dSskrll .proc 87*6d3ceb1dSskrll .callinfo millicode,no_unwind 88*6d3ceb1dSskrll .entry 89*6d3ceb1dSskrll comb,<,n %r25,0,bigdivisor_remU ; special case (>=0x80000000) 90*6d3ceb1dSskrll bl sub_divU,%r29 91*6d3ceb1dSskrll subt,= %r0,%r25,%r1 ; trap divide by 0, negate 92*6d3ceb1dSskrll 93*6d3ceb1dSskrll comclr,>= %r1,%r0,%r0 94*6d3ceb1dSskrll addl %r1,%r25,%r1 ; fix remainder 95*6d3ceb1dSskrll bv %r0(%r31) ; return millicode 96*6d3ceb1dSskrll .exit 97*6d3ceb1dSskrll copy %r1,%r29 ; the return value is remainder 98*6d3ceb1dSskrllbigdivisor_remU: 99*6d3ceb1dSskrll sub,>>= %r26,%r25,%r29 ; if dividend < divisor 100*6d3ceb1dSskrll copy %r26,%r29 ; the remainder is dividend 101*6d3ceb1dSskrll bv,n %r0(%r31) ; return millicode 102*6d3ceb1dSskrll .procend 103*6d3ceb1dSskrll 104*6d3ceb1dSskrll; $$mulU unsigned multiplication 105*6d3ceb1dSskrll; 106*6d3ceb1dSskrll; inputs: 107*6d3ceb1dSskrll; %r26 multiplicand 108*6d3ceb1dSskrll; %r25 multiplier 109*6d3ceb1dSskrll; %r31 return address 110*6d3ceb1dSskrll; outputs: 111*6d3ceb1dSskrll; %r29 product 112*6d3ceb1dSskrll; %r1, %r25, %r26 undefined 113*6d3ceb1dSskrll .export $$mulU,millicode 114*6d3ceb1dSskrll .export $$mulI,millicode 115*6d3ceb1dSskrll$$mulU: 116*6d3ceb1dSskrll$$mulI: ; XXX actually wrong (not signed) but works for small positive numbers 117*6d3ceb1dSskrll .proc 118*6d3ceb1dSskrll .callinfo frame=0,no_calls,millicode 119*6d3ceb1dSskrll .entry 120*6d3ceb1dSskrll copy %r0,%r29 121*6d3ceb1dSskrll ldi 32,%r1 ; loop counter 122*6d3ceb1dSskrll 123*6d3ceb1dSskrll add,nuv %r25,%r25,%r25 ; shift left, skip next if not C 124*6d3ceb1dSskrllloop_mul: 125*6d3ceb1dSskrll sh1add,tr %r29,%r26,%r29 ; shift left and add, skip next 126*6d3ceb1dSskrll sh1add %r29,%r0,%r29 ; shift left only 127*6d3ceb1dSskrll addib,<>,n -1,%r1,loop_mul ; check loop condition 128*6d3ceb1dSskrll add,nuv %r25,%r25,%r25 ; shift left, skip next if not C 129*6d3ceb1dSskrll .exit 130*6d3ceb1dSskrll bv,n %r0(%r31) ; return millicode 131*6d3ceb1dSskrll .procend 132