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