2008-01-25 Douglas Gregor <doug.gregor@gmail.com>
[official-gcc.git] / gcc / config / c4x / libgcc.S
blob8f801da6af76e3357f3e87793b8b7ab4b13d4523
1 /* libgcc routines for the Texas Instruments TMS320C[34]x
2    Copyright (C) 1997,98, 1999 Free Software Foundation, Inc.
4  Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)
5             and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl).
7         
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
13 later version.
15 In addition to the permissions in the GNU General Public License, the
16 Free Software Foundation gives you unlimited permission to link the
17 compiled version of this file into combinations with other programs,
18 and to distribute those combinations without any restriction coming
19 from the use of this file.  (The General Public License restrictions
20 do apply in other respects; for example, they cover modification of
21 the file, and distribution when not linked into a combine
22 executable.)
24 This file is distributed in the hope that it will be useful, but
25 WITHOUT ANY WARRANTY; without even the implied warranty of
26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
27 General Public License for more details.
29 You should have received a copy of the GNU General Public License
30 along with this program; see the file COPYING.  If not, write to
31 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
32 Boston, MA 02110-1301, USA.  */
34 ; These routines are called using the standard TI register argument
35 ; passing model.
36 ; The following registers do not have to be saved:
37 ; r0, r1, r2, r3, ar0, ar1, ar2, ir0, ir1, bk, rs, rc, re, (r9, r10, r11)
39 ; Perform floating point divqf3
41 ; This routine performs a reciprocal of the divisor using the method
42 ; described in the C30/C40 user manuals.  It then multiplies that
43 ; result by the dividend.
44
45 ; Let r be the reciprocal of the divisor v and let the ith estimate
46 ; of r be denoted by r[i].  An iterative approach can be used to
47 ; improve the estimate of r, given an initial estimate r[0], where
49 ; r[i + 1] = r[i] * (2.0 - v * r[i])
51 ; The normalized error e[i] at the ith iteration is
53 ; e[i] = (r - r[i]) / r = (1 / v - r[i]) * v = (1 - v * r[i])
55 ; Note that 
57 ; e[i + 1]  = (1 - v * r[i + 1]) = 1 - 2 * v * r[i] + v^2 + (r[i])^2
58 ;           = (1 - v * r[i])^2 = (e[i])^2
60 ; r2 dividend, r3 divisor, r0 quotient
61 ; clobbers r1, ar1
62 #ifdef L_divsf3
63         .text
64         .global ___divqf3
65 ___divqf3:
67 #ifdef _TMS320C4x
68         .if .REGPARM == 0
69         lda     sp,ar0
70         ldf     *-ar0(2), r3
71         .endif
73         pop     ar1             ; Pop return address
75 ; r0 = estimate of r, r1 = tmp, r2 = dividend, r3 = divisor
76         rcpf    r3, r0          ; Compute initial estimate r[0]
78         mpyf3   r0, r3, r1      ; r1 = r[0] * v
79         subrf   2.0, r1         ; r1 = 2.0 - r[0] * v
80         mpyf    r1, r0          ; r0 = r[0] * (2.0 - r[0] * v) = r[1]
81 ; End of 1st iteration (16 bits accuracy)
83         mpyf3   r0, r3, r1      ; r1 = r[1] * v
84         subrf   2.0, r1         ; r1 = 2.0 - r[1] * v
86         bud     ar1             ; Delayed branch
87         mpyf    r1, r0          ; r0 = r[1] * (2.0 - r[1] * v) = r[2]
88 ; End of 2nd iteration (32 bits accuracy)
89         .if .REGPARM == 0
90         mpyf    *-ar0(1), r0    ; Multiply by the dividend
91         .else
92         mpyf    r2, r0          ; Multiply by the dividend
93         .endif
94         rnd     r0
95         ; Branch occurs here
96 #else
97         .if .REGPARM == 0
98         ldiu    sp,ar0
99         ldf     *-ar0(2), r3
100         .endif
102         pop     ar1             ; Pop return address
104 ; Initial estimate       r[0] = 1.0 * 2^(-e - 1)
105 ; where                  v = m * 2^e
107 ; r0 = estimate of r, r1 = tmp, r2 = dividend, r3 = divisor
109 ; Calculate initial estimate r[0]
110         pushf   r3
111         pop     r0
112         not     r0              ; r0 = -e
113                                 ; complement exponent = -e -1
114                                 ; complement sign (side effect)
115                                 ; complement mantissa (almost 3 bit accurate)
116         push    r0
117         popf    r0              ; r0 = 1.0 * e^(-e - 1) + inverted mantissa
118         ldf     -1.0, r1        ; undo complement sign bit
119         xor     r1, r0
121         mpyf3   r0, r3, r1      ; r1 = r[0] * v
122         subrf   2.0, r1         ; r1 = 2.0 - r[0] * v
123         mpyf    r1, r0          ; r0 = r[0] * (2.0 - r[0] * v) = r[1]
124 ; End of 1st iteration
126         mpyf3   r0, r3, r1      ; r1 = r[1] * v
127         subrf   2.0, r1         ; r1 = 2.0 - r[1] * v
128         mpyf    r1, r0          ; r0 = r[1] * (2.0 - r[1] * v) = r[2]
129 ; End of 2nd iteration
131         mpyf3   r0, r3, r1      ; r1 = r[2] * v
132         subrf   2.0, r1         ; r1 = 2.0 - r[2] * v
133         mpyf    r1, r0          ; r0 = r[2] * (2.0 - r[2] * v) = r[3]
134 ; End of 3rd iteration
136         rnd     r0              ; Minimize error in x[3]'s LSBs
138 ; Use modified last iteration
139 ; r[4] = (r[3] * (1.0 - (v * r[3]))) + r[3]
140         mpyf3   r0, r3, r1      ; r1 = r[3] * v
141         subrf   1.0, r1         ; r1 = 1.0 - r[3] * v
142         mpyf    r0, r1          ; r1 = r[3] * (1.0 - r[3] * v)
143         addf    r1, r0          ; r0 = r[3] * (1.0 - r[3] * v) + r[3] = r[4]
145         rnd     r0              ; Minimize error in x[4]'s LSBs
147         bud     ar1             ; Delayed branch
149         .if .REGPARM == 0
150         ldfu    *-ar0(1), r2    ; Dividend in mem has only 24 bits significance
151         .else
152         rnd     r2              ; Minimize error in reg dividend's LSBs
153                                 ; since this may have 32 bit significance
154         .endif
156         mpyf    r2, r0          ; Multiply by the dividend
157         rnd     r0              ; Round result to 32 bits
159         ; Branch occurs here
160 #endif
162 #endif
164 ; Integer signed division
166 ; ar2 dividend, r2 divisor, r0 quotient
167 ; clobbers r1, r3, ar0, ar1, ir0, ir1, rc, rs, re
168 #ifdef L_divsi3
169         .text
170         .global ___divqi3
171         .ref    udivqi3n
172 ___divqi3:
173         .if .REGPARM == 0
174 #ifdef _TMS320C4x
175         lda     sp,ar0
176 #else
177         ldiu    sp,ar0
178 #endif
179         ldi     *-ar0(1), ar2
180         ldi     *-ar0(2), r2
181         .endif
183         xor3    ar2, r2, r3     ; Get the sign
184         absi    ar2, r0
185         bvd     divq32
186         ldi     r0, ar2
187         absi    r2, r2
188         cmpi    ar2, r2         ; Divisor > dividend?
190         pop     ir1
191         bhid    zero            ; If so, return 0
194 ; Normalize oeprands.  Use difference exponents as shift count
195 ; for divisor, and as repeat count for "subc"
197         float   ar2, r1         ; Normalize dividend
198         pushf   r1              ; Get as integer
199         pop     ar0
200         lsh     -24, ar0        ; Get exponent
201         
202         float   r2, r1          ; Normalize divisor
203         pushf   r1              ; Get as integer
204         pop     ir0
205         lsh     -24, ir0        ; Get exponent
207         subi    ir0, ar0        ; Get difference of exponents
208         lsh     ar0, r2         ; Align divisor with dividend
211 ; Do count + 1 subtracts and shifts
213         rpts    ar0
214                 subc    r2, ar2
217 ; Mask off the lower count+1 bits of ar2
219         subri   31, ar0         ; Shift count is (32 - (ar0 + 1))
220         lsh     ar0, ar2        ; Shift left
221         negi    ar0, ar0
222         lsh3    ar0, ar2, r0    ; Shift right and put result in r0
225 ; Check sign and negate result if necessary
227         bud     ir1             ; Delayed return
228         negi    r0, r1          ; Negate result
229         ash     -31, r3         ; Check sign
230         ldinz   r1, r0          ; If set, use negative result
231         ; Branch occurs here
233 zero:   bud     ir1             ; Delayed branch
234         ldi     0, r0
235         nop
236         nop
237         ; Branch occurs here
239 ; special case where ar2 = abs(ar2) = 0x80000000.  We handle this by
240 ; calling unsigned divide and negating the result if necessary.
242 divq32:
243         push    r3              ; Save sign
244         call    udivqi3n
245         pop     r3
246         pop     ir1
247         bd      ir1
248         negi    r0, r1          ; Negate result
249         ash     -31, r3         ; Check sign
250         ldinz   r1, r0          ; If set, use negative result
251         ; Branch occurs here
252 #endif
255 ; ar2 dividend, r2 divisor, r0 quotient, 
256 ; clobbers r1, r3, ar0, ar1, ir0, ir1, rc, rs, re
257 #ifdef L_udivsi3
258         .text
259         .global ___udivqi3
260         .global udivqi3n
261 ___udivqi3:
262         .if .REGPARM == 0
263 #ifdef _TMS320C4x
264         lda     sp,ar0
265 #else
266         ldiu    sp,ar0
267 #endif
268         ldi     *-ar0(1), ar2
269         ldi     *-ar0(2), r2
270         .endif
272 udivqi3n:
273         pop     ir1
275         cmpi    ar2, r2         ; If divisor > dividend
276         bhi     qzero           ; return zero
277         ldi     r2, ar1         ; Store divisor in ar1
279         tstb    ar2, ar2        ; Check top bit, jump if set to special handler
280         bld     div_32          ; Delayed branch
283 ; Get divisor exponent
285         float   ar1, r1         ; Normalize the divisor
286         pushf   r1              ; Get into int register
287         pop     rc
288         ; branch occurs here
290         bzd     qzero           ; if (float) divisor zero, return zero
292         float   ar2, r1         ; Normalize the dividend
293         pushf   r1              ; Get into int register
294         pop     ar0
295         lsh     -24, ar0        ; Get both the exponents
296         lsh     -24, rc
298         subi    rc, ar0         ; Get the difference between the exponents
299         lsh     ar0, ar1        ; Normalize the divisor with the dividend
302 ; Do count_1 subtracts and shifts
304         rpts    ar0
305                 subc    ar1, ar2
308 ; mask off the lower count+1 bits
310         subri   31, ar0         ; Shift count (31 - (ar0+1))
311         bud     ir1             ; Delayed return
312         lsh3    ar0, ar2, r0
313         negi    ar0, ar0
314         lsh     ar0, r0
315         ; Branch occurs here
318 ; Handle a full 32-bit dividend
320 div_32: tstb    ar1, ar1
321         bld     qone            ; if divisor high bit is one, the result is one
322         lsh     -24, rc
323         subri   31, rc
324         lsh     rc, ar1         ; Line up the divisor
327 ; Now divisor and dividend are aligned.  Do first SUBC by hand, save
328 ; of the forst quotient digit.  Then, shift divisor right rather
329 ; than shifting dividend left.  This leaves a zero in the top bit of
330 ; the dividend
332         ldi     1, ar0          ; Initizialize MSB of quotient
333         lsh     rc, ar0         ; create a mask for MSBs
334         subi    1, ar0          ; mask is (2 << count) - 1
336         subi3   ar1, ar2, r1
337         ldihs   r1, ar2
338         ldihs   1, r1
339         ldilo   0, r1
340         lsh     rc, r1
342         lsh     -1, ar1
343         subi    1, rc
345 ; do the rest of the shifts and subtracts
347         rpts    rc
348                 subc    ar1, ar2
350         bud     ir1
351         and     ar0, ar2
352         or3     r1, ar2, r0
353         nop
355 qone:
356         bud     ir1
357         ldi     1, r0
358         nop
359         nop
361 qzero:
362         bud     ir1
363         ldi     0, r0
364         nop
365         nop
366 #endif
368 #ifdef L_umodsi3
369         .text
370         .global ___umodqi3
371         .global umodqi3n
372 ___umodqi3:
373         .if .REGPARM == 0
374 #ifdef _TMS320C4x
375         lda     sp,ar0
376 #else
377         ldiu    sp,ar0
378 #endif
379         ldi     *-ar0(1), ar2
380         ldi     *-ar0(2), r2
381         .endif
383 umodqi3n:
384         pop     ir1             ; return address
385         cmpi    ar2, r2         ; divisor > dividend ? 
386         bhi     uzero           ;    if so, return dividend
387         ldi     r2, ar1         ; load divisor
389 ; If top bit of dividend is set, handle specially.
391         tstb    ar2, ar2        ; check top bit
392         bld     umod_32         ; get divisor exponent, then jump.
394 ; Get divisor exponent by converting to float.
396         float   ar1, r1         ; normalize divisor
397         pushf   r1              ; push as float
398         pop     rc              ; pop as int to get exponent
399         bzd     uzero           ; if (float)divisor was zero, return
401 ; 31 or less bits in dividend.  Get dividend exponent.
403         float   ar2, r1         ; normalize dividend
404         pushf   r1              ; push as float
405         pop     ar0             ; pop as int to get exponent
407 ; Use difference in exponents as shift count to line up MSBs.
409         lsh     -24, rc         ; divisor exponent
410         lsh     -24, ar0        ; dividend exponent
411         subi    rc, ar0         ; difference
412         lsh     ar0, ar1        ; shift divisor up
414 ; Do COUNT+1 subtract & shifts.
416         rpts    ar0
417                 subc    ar1, ar2  
419 ;  Remainder is in upper 31-COUNT bits.
421         bud     ir1             ; delayed branch to return
422         addi    1, ar0          ; shift count is COUNT+1
423         negi    ar0, ar0        ; negate for right shift
424         lsh3    ar0, ar2, r0    ; shift to get result
425         ; Return occurs here
428 ; The following code handles cases of a full 32-bit dividend.  Before
429 ; SUBC can be used, the top bit must be cleared (otherwise SUBC can
430 ; possibly shift a significant 1 out the top of the dividend).  This
431 ; is accomplished by first doing a normal subtraction, then proceeding
432 ; with SUBCs. 
434 umod_32:
436 ; If the top bit of the divisor is set too, the remainder is simply
437 ; the difference between the dividend and divisor.  Otherwise, shift 
438 ; the divisor up to line up the MSBs.
440         tstb    ar1, ar1        ; check divisor
441         bld     uone            ; if negative, remainder is diff
443         lsh     -24, rc         ; divisor exponent
444         subri   31, rc          ; shift count = 31 - exp
445         negi    rc, ar0         ; used later as shift count
446         lsh     rc, ar1         ; shift up to line up MSBs
448 ; Now MSBs are aligned.  Do first SUBC by hand using a plain subtraction.
449 ; Then, shift divisor right rather than shifting dividend left.  This leaves
450 ; a 0 in the top bit of the dividend.
452         subi3   ar1, ar2, r1    ; subtract 
453         ldihs   r1, ar2         ; if positive, replace dividend
454         subi    1, rc           ; first iteration is done
455         lsh     -1, ar1         ; shift divisor down
457 ; Do EXP subtract & shifts.
459         rpts    rc  
460                 subc    ar1, ar2   
462 ;  Quotient is in EXP+1 LSBs; shift remainder (in MSBs) down.
464         bud     ir1
465         lsh3    ar0, ar2, r0    ; COUNT contains -(EXP+1)
466         nop
467         nop
469 ;  Return (dividend - divisor).
471 uone:   bud     ir1
472         subi3   r2, ar2, r0  
473         nop
474         nop
476 ;  Return dividend.
478 uzero:  bud     ir1
479         ldi     ar2, r0         ; set status from result
480         nop
481         nop
482 #endif
484 #ifdef L_modsi3
485         .text
486         .global ___modqi3
487         .ref umodqi3n
488 ___modqi3:
489         .if .REGPARM == 0
490 #ifdef _TMS320C4x
491         lda     sp,ar0
492 #else
493         ldiu    sp,ar0
494 #endif
495         ldi     *-ar0(1), ar2
496         ldi     *-ar0(2), r2
497         .endif
500 ; Determine sign of result.  Get absolute value of operands.
502         ldi     ar2, ar0        ; sign of result same as dividend
503         absi    ar2, r0         ; make dividend positive
504         bvd     mod_32          ; if still negative, escape
505         absi    r2, r1          ; make divisor positive
506         ldi     r1, ar1         ; save in ar1       
507         cmpi    r0, ar1         ; divisor > dividend ? 
509         pop     ir1            ; return address
510         bhid    return          ;   if so, return dividend
512 ; Normalize operands.  Use difference in exponents as shift count
513 ; for divisor, and as repeat count for SUBC.
515         float   r1, r1          ; normalize divisor
516         pushf   r1              ; push as float 
517         pop     rc              ; pop as int
518         bzd     return          ; if (float)divisor was zero, return
520         float   r0, r1          ; normalize dividend
521         pushf   r1              ; push as float
522         pop     r1              ; pop as int 
524         lsh     -24, rc         ; get divisor exponent
525         lsh     -24, r1         ; get dividend exponent
526         subi    rc, r1          ; get difference in exponents
527         lsh     r1, ar1         ; align divisor with dividend
529 ; Do COUNT+1 subtract & shifts.
531         rpts    r1
532                 subc    ar1, r0
534 ;  Remainder is in upper bits of R0
536         addi    1, r1           ; shift count is -(r1+1)
537         negi    r1, r1 
538         lsh     r1, r0          ; shift right
540 ;  Check sign and negate result if necessary.
542 return:
543         bud     ir1             ; delayed branch to return
544         negi    r0, r1          ; negate result
545         cmpi    0, ar0          ; check sign
546         ldin    r1, r0          ; if set, use negative result
547         ; Return occurs here
549 ; The following code handles cases of a full 32-bit dividend.  This occurs
550 ; when R0 = abs(R0) = 080000000h.  Handle this by calling the unsigned mod
551 ; function, then negating the result if necessary.
553 mod_32:
554         push    ar0             ; remember sign
555         call    umodqi3n        ; do divide
557         brd     return          ; return
558         pop     ar0             ; restore sign
559         pop     ir1             ; return address
560         nop
561 #endif
563 #ifdef L_unsfltconst
564         .section .const
565         .global ___unsfltconst
566 ___unsfltconst:   .float 4294967296.0
567 #endif
569 #ifdef L_unsfltcompare
570         .section .const
571         .global ___unsfltcompare
572 ___unsfltcompare: .float 2147483648.0
573 #endif
575 ; Integer 32-bit signed multiplication
577 ; The TMS320C3x MPYI instruction takes two 24-bit signed integers
578 ; and produces a 48-bit signed result which is truncated to 32-bits.
580 ; A 32-bit by 32-bit multiplication thus requires a number of steps.
582 ; Consider the product of two 32-bit signed integers,
584 ;       z = x * y
586 ; where x = (b << 16) + a,  y = (d << 16) + c
588 ; This can be expressed as
590 ;       z = ((b << 16) + a) * ((d << 16) + c)
592 ;          = ((b * d) << 32) + ((b * c + a * d) << 16) + a * c
594 ; Let z = (f << 16) + e where f < (1 << 16).
596 ; Since we are only interested in a 32-bit result, we can ignore the 
597 ; (b * d) << 32 term, and thus
599 ;       f = b * c + a * d,  e = a * c
601 ; We can simplify things if we have some a priori knowledge of the
602 ; operands, for example, if -32768 <= y <= 32767, then y = c and d = 0 and thus
604 ;       f = b * c,  e = a * c
606 ; ar2 multiplier, r2 multiplicand, r0 product
607 ; clobbers r1, r2, r3
608 #ifdef L_mulsi3 
609         .text
610         .global ___mulqi3
611 ___mulqi3:
612         .if .REGPARM == 0
613 #ifdef _TMS320C4x
614         lda     sp,ar0
615 #else
616         ldiu    sp,ar0
617 #endif
618         ldi     *-ar0(1), ar2
619         ldi     *-ar0(2), r2
620         .endif
622         pop     ir1             ; return address
623         ldi     ar2, r0         ;
624         and     0ffffh, r0      ; a
625         lsh     -16, ar2        ; b
626         ldi     r2, r3          ; 
627         and     0ffffh, r3      ; c
628         mpyi    r3, ar2         ; c * b         
629         lsh     -16, r2         ; d
630         mpyi    r0, r2          ; a * d
631         addi    ar2, r2         ; c * b + a * d
632         bd      ir1             ; delayed branch to return
633         lsh     16, r2          ; (c * b + a * d) << 16
634         mpyi    r3, r0          ; a * c
635         addi    r2, r0          ; a * c + (c * b + a * d) << 16
636 ; branch occurs here
638 #endif  
641 ; Integer 64 by 64 multiply
642 ; long1 and long2 on stack
643 ; result in r0,r1
645 #ifdef L_muldi3
646         .text
647         .global ___mulhi3
648 #ifdef _TMS320C4x
649 ___mulhi3:
650         pop     ar0
651         ldi     sp,ar2
652         ldi     *-ar2(1),r2
653         ldi     *-ar2(3),r3
654         mpyi3   r2,r3,r0
655         mpyuhi3 r2,r3,r1
656         mpyi    *-ar2(2),r2
657         bd      ar0
658         mpyi    *-ar2(0),r3
659         addi    r2,r1
660         addi    r3,r1
661 #else
662 ___mulhi3:
663         ldi     sp,ar2
664         ldi     -16,rs
665         ldi     *-ar2(2),ar0
666         ldi     *-ar2(4),ar1
667         ldi     ar0,r2
668         and     0ffffh,r2
669         ldi     ar1,r3
670         and     0ffffh,r3
671         lsh     rs,ar0
672         lsh     rs,ar1
674         mpyi    r2,r3,r0
675         mpyi    ar0,ar1,r1
676         mpyi    r2,ar1,rc
677         lsh     rs,rc,re
678         addi    re,r1
679         lsh     16,rc
680         addi    rc,r0
681         addc    0,r1
682         mpyi    r3,ar0,rc
683         lsh     rs,rc,re
684         addi    re,r1
685         lsh     16,rc
686         addi    rc,r0
687         addc    0,r1
689         ldi     *-ar2(1),ar0
690         ldi     ar0,r2
691         and     0ffffh,r2
692         lsh     rs,ar0
693         mpyi    r2,r3,rc
694         addi    rc,r1
695         mpyi    r2,ar1,rc
696         mpyi    r3,ar0,re
697         addi    re,rc
698         lsh     16,rc
699         addi    rc,r1
701         ldi     *-ar2(2),ar0
702         ldi     *-ar2(3),ar1
703         ldi     ar0,r2
704         and     0ffffh,r2
705         ldi     ar1,r3
706         and     0ffffh,r3
707         lsh     rs,ar0
708         lsh     rs,ar1
709         mpyi    r2,r3,rc
710         addi    rc,r1
711         mpyi    r2,ar1,rc
712         mpyi    r3,ar0,re
713         pop     ar0
714         bd      ar0
715         addi    re,rc
716         lsh     16,rc
717         addi    rc,r1
718 #endif
719 #endif
722 ; Integer 32 by 32 multiply highpart unsigned
723 ; src1 in ar2
724 ; src2 in r2
725 ; result in r0
727 #ifdef L_umuldi3_high
728         .text
729         .global ___umulhi3_high
730 ___umulhi3_high:
731         .if .REGPARM == 0
732 #ifdef _TMS320C4x
733         lda     sp,ar0
734 #else
735         ldiu    sp,ar0
736 #endif
737         ldi     *-ar0(1), ar2
738         ldi     *-ar0(2), r2
739         .endif
741         ldi     -16,rs
742         ldi     r2,r3
743         and     0ffffh,r2
744         ldi     ar2,ar1
745         and     0ffffh,ar2
746         lsh     rs,r3
747         lsh     rs,ar1
749         mpyi    ar2,r2,r1
750         mpyi    ar1,r3,r0
751         mpyi    ar2,r3,rc
752         lsh     rs,rc,re
753         addi    re,r0
754         lsh     16,rc
755         addi    rc,r1
756         addc    0,r0
757         mpyi    r2,ar1,rc
758         lsh     rs,rc,re
759         addi    re,r0
760         pop     ar0
761         bd      ar0
762         lsh     16,rc
763         addi    rc,r1
764         addc    0,r0
765 #endif
768 ; Integer 32 by 32 multiply highpart signed
769 ; src1 in ar2
770 ; src2 in r2
771 ; result in r0
773 #ifdef L_smuldi3_high
774         .text
775         .global ___smulhi3_high
776 ___smulhi3_high:
777         .if .REGPARM == 0
778 #ifdef _TMS320C4x
779         lda     sp,ar0
780 #else
781         ldiu    sp,ar0
782 #endif
783         ldi     *-ar0(1), ar2
784         ldi     *-ar0(2), r2
785         .endif
787         ldi     -16,rs
788         ldi     0,rc
789         subi3   ar2,rc,r0
790         ldi     r2,r3
791         ldilt   r0,rc
792         subi3   r2,rc,r0
793         ldi     ar2,ar1
794         tstb    ar1,ar1
795         ldilt   r0,rc
796         and     0ffffh,r2
797         and     0ffffh,ar2
798         lsh     rs,r3
799         lsh     rs,ar1
801         mpyi    ar2,r2,r1
802         mpyi    ar1,r3,r0
803         addi    rc,r0
804         mpyi    ar2,r3,rc
805         lsh     rs,rc,re
806         addi    re,r0
807         lsh     16,rc
808         addi    rc,r1
809         addc    0,r0
810         mpyi    r2,ar1,rc
811         lsh     rs,rc,re
812         addi    re,r0
813         pop     ar0
814         bd      ar0
815         lsh     16,rc
816         addi    rc,r1
817         addc    0,r0
818 #endif
821 ; Integer 64 by 64 unsigned divide
822 ; long1 and long2 on stack
823 ; divide in r0,r1
824 ; modulo in r2,r3
825 ; routine takes a maximum of 64*8+23=535 cycles = 21.4 us @ 50Mhz
827 #ifdef L_udivdi3
828         .text
829         .global ___udivhi3
830         .global ___udivide
831         .global ___umodulo
832         .ref udivqi3n
833         .ref umodqi3n
834 ___udivhi3:
835         ldi     sp,ar2
836         ldi     *-ar2(4),ar0
837         ldi     *-ar2(3),ar1
838         ldi     *-ar2(2),r0
839         ldi     *-ar2(1),r1
841 ___udivide:
842         or      r1,ar1,r2
843         bne     udiv0
844         ldi     ar0,r2
845         ldi     r0,ar2
846         call    udivqi3n
847         ldiu    0,r1
848         rets
850 ___umodulo:
851         or      r1,ar1,r2
852         bne     udiv0
853         ldi     ar0,r2
854         ldi     r0,ar2
855         call    umodqi3n
856         ldi     r0,r2
857         ldiu    0,r3
858         rets
860 udiv0:
861         tstb    ar1,ar1
862         bne     udiv1
863         tstb    ar0,ar0
864         bn      udiv1
866         ldiu    63,rc
867 #ifdef _TMS320C4x
868         rptbd   udivend0
869         ldiu    0,r2
870         addi    r0,r0
871         rolc    r1
872 #else
873         ldiu    0,r2
874         addi    r0,r0
875         rolc    r1
876         rptb    udivend0
877 #endif
879         rolc    r2
880         subi3   ar0,r2,r3
881         ldinc   r3,r2
882         rolc    r0
883 udivend0:
884         rolc    r1
886         not     r0
887         not     r1
888         ldiu    0,r3
889         rets
890 udiv1:
891         push    r4
892         push    r5
893         ldiu    63,rc
894         ldiu    0,r2
895 #ifdef _TMS320C4x
896         rptbd   udivend1
897         ldiu    0,r3
898         addi    r0,r0
899         rolc    r1
900 #else
901         ldiu    0,r3
902         addi    r0,r0
903         rolc    r1
904         rptb    udivend1
905 #endif
907         rolc    r2
908         rolc    r3
909         subi3   ar0,r2,r4
910         subb3   ar1,r3,r5
911         ldinc   r4,r2
912         ldinc   r5,r3
913         rolc    r0
914 udivend1:
915         rolc    r1
917         not     r0
918         not     r1
919         pop     r5
920         pop     r4
921         rets
922 #endif
925 ; Integer 64 by 64 unsigned modulo
926 ; long1 and long2 on stack
927 ; result in r0,r1
929 #ifdef L_umoddi3
930         .text
931         .global ___umodhi3
932         .ref ___modulo
933 ___umodhi3:
934         ldi     sp,ar2
935         ldi     *-ar2(4),ar0
936         ldi     *-ar2(3),ar1
937         ldi     *-ar2(2),r0
938         ldi     *-ar2(1),r1
939         call    ___umodulo
940         pop     ar0
941         bd      ar0
942         ldi     r2,r0
943         ldi     r3,r1
944         nop
945 #endif
948 ; Integer 64 by 64 signed divide
949 ; long1 and long2 on stack
950 ; result in r0,r1
952 #ifdef L_divdi3
953         .text
954         .global ___divhi3
955         .ref ___udivide
956 ___divhi3:
957         ldi     0,ir0
958         ldi     sp,ar2
959         ldi     *-ar2(4),r0
960         ldi     *-ar2(3),r1
961         bge     div1
962         not     ir0
963         negi    r0
964         negb    r1
965 div1:
966         ldi     r0,ar0
967         ldi     r1,ar1
968         ldi     *-ar2(2),r0
969         ldi     *-ar2(1),r1
970         bge     div2
971         not     ir0
972         negi    r0
973         negb    r1
974 div2:
975         call    ___udivide
976         tstb    ir0,ir0
977         bge     div3
978         negi    r0
979         negb    r1
980 div3:   
981         rets
982 #endif
985 ; Integer 64 by 64 signed modulo
986 ; long1 and long2 on stack
987 ; result in r0,r1
989 #ifdef L_moddi3
990         .text
991         .global ___modhi3
992         .ref ___umodulo
993 ___modhi3:
994         ldi     0,ir0
995         ldi     sp,ar2
996         ldi     *-ar2(4),r0
997         ldi     *-ar2(3),r1
998         bge     mod1
999         not     ir0
1000         negi    r0
1001         negb    r1
1002 mod1:
1003         ldi     r0,ar0
1004         ldi     r1,ar1
1005         ldi     *-ar2(2),r0
1006         ldi     *-ar2(1),r1
1007         bge     mod2
1008         not     ir0
1009         negi    r0
1010         negb    r1
1011 mod2:
1012         call    ___umodulo
1013         ldi     r2,r0
1014         ldi     r3,r1
1015         tstb    ir0,ir0
1016         bge     mod3
1017         negi    r0
1018         negb    r1
1019 mod3:   
1020         rets
1021 #endif
1024 ; double to signed long long conversion
1025 ; input in r2
1026 ; result in r0,r1
1028 #ifdef L_fix_truncsfdi2
1029         .text
1030         .global ___fix_truncqfhi2
1031         .ref ufix_truncqfhi2n
1032 ___fix_truncqfhi2:
1033         .if .REGPARM == 0
1034 #ifdef _TMS320C4x
1035         lda     sp,ar0
1036 #else
1037         ldiu    sp,ar0
1038 #endif
1039         ldf     *-ar0(1), r2
1040         .endif
1042         cmpf    0.0,r2
1043         bge     ufix_truncqfhi2n
1044         negf    r2
1045         call    ufix_truncqfhi2n
1046         negi    r0
1047         negb    r1
1048         rets
1049 #endif
1052 ; double to unsigned long long conversion
1053 ; input in r2
1054 ; result in r0,r1
1056 #ifdef L_ufix_truncsfdi2
1057         .text
1058         .global ___ufix_truncqfhi2
1059         .global ufix_truncqfhi2n
1060 ___ufix_truncqfhi2:
1061         .if .REGPARM == 0
1062 #ifdef _TMS320C4x
1063         lda     sp,ar0
1064 #else
1065         ldiu    sp,ar0
1066 #endif
1067         ldf     *-ar0(1), r2
1068         .endif
1070 ufix_truncqfhi2n:
1071         cmpf    0.0,r2
1072         ble     ufix1
1073         pushf   r2
1074         pop     r3
1075         ash     -24,r3
1076         subi    31,r3
1077         cmpi    32,r3
1078         bgt     ufix1
1079         cmpi    -32,r3
1080         ble     ufix1
1081         ldi     1,r0
1082         ash     31,r0
1083         or3     r0,r2,r0
1084         ldi     r0,r1
1085         lsh3    r3,r0,r0
1086         subi    32,r3
1087         cmpi    -32,r3
1088         ldile   0,r1
1089         lsh3    r3,r1,r1
1090         rets
1091 ufix1:
1092         ldi     0,r0
1093         ldi     0,r1
1094         rets
1095 #endif
1098 ; signed long long to double conversion
1099 ; input on stack
1100 ; result in r0
1102 #ifdef L_floatdisf2
1103         .text
1104         .global ___floathiqf2
1105         .ref ufloathiqf2n
1106 ___floathiqf2:
1107         ldi     sp,ar2
1108         ldi     *-ar2(2),r0
1109         ldi     *-ar2(1),r1
1110         bge     ufloathiqf2n
1111         negi    r0
1112         negb    r1
1113         call    ufloathiqf2n
1114         negf    r0
1115         rets
1116 #endif
1119 ; unsigned long long to double conversion
1120 ; input on stack
1121 ; result in r0
1123 #ifdef L_ufloatdisf2
1124         .text
1125         .global ___ufloathiqf2
1126         .global ufloathiqf2n
1127         .ref ___unsfltconst
1128 ___ufloathiqf2:
1129         ldi     sp,ar2
1130         ldi     *-ar2(2),r0
1131         ldi     *-ar2(1),r1
1132 ufloathiqf2n:
1133         .if .BIGMODEL
1134 #ifdef _TMS320C4x
1135         ldpk    @___unsfltconst
1136 #else
1137         ldp     @___unsfltconst
1138 #endif
1139         .endif
1140         ldf     @___unsfltconst,r2
1141         float   r0
1142         bge     uflt1
1143         addf    r2,r0
1144 uflt1:
1145         float   r1
1146         bge     uflt2
1147         addf    r2,r1
1148 uflt2:
1149 #ifdef _TMS320C4x
1150         pop     r3
1151         bd      r3
1152         mpyf    r2,r1
1153         addf    r1,r0
1154         nop
1155 #else
1156         ldf     r1,r3
1157         and     0ffh,r3
1158         norm    r3,r3
1159         mpyf    r2,r3
1160         pop     ar2
1161         bd      ar2
1162         addf    r3,r0
1163         mpyf    r2,r1
1164         addf    r1,r0
1165 #endif
1166 #endif
1169 ; long double to signed long long conversion
1170 ; input in r2
1171 ; result in r0,r1
1173 #ifdef L_fix_truncdfdi2
1174         .text
1175         .global ___fix_trunchfhi2
1176         .ref ufix_trunchfhi2n
1177 ___fix_trunchfhi2:
1178         .if .REGPARM == 0
1179 #ifdef _TMS320C4x
1180         lda     sp,ar0
1181 #else
1182         ldiu    sp,ar0
1183 #endif
1184         ldf     *-ar0(2), r2
1185         ldi     *-ar0(1), r2
1186         .endif
1188         cmpf    0.0,r2
1189         bge     ufix_trunchfhi2n
1190         negf    r2
1191         call    ufix_trunchfhi2n
1192         negi    r0
1193         negb    r1
1194         rets
1195 #endif
1198 ; long double to unsigned long long conversion
1199 ; input in r2
1200 ; result in r0,r1
1202 #ifdef L_ufix_truncdfdi2
1203         .text
1204         .global ___ufix_trunchfhi2
1205         .global ufix_trunchfhi2n
1206 ___ufix_trunchfhi2:
1207         .if .REGPARM == 0
1208 #ifdef _TMS320C4x
1209         lda     sp,ar0
1210 #else
1211         ldiu    sp,ar0
1212 #endif
1213         ldf     *-ar0(2), r2
1214         ldi     *-ar0(1), r2
1215         .endif
1217 ufix_trunchfhi2n:
1218         cmpf    0.0,r2
1219         ble     ufixh1
1220         pushf   r2
1221         pop     r3
1222         ash     -24,r3
1223         subi    31,r3
1224         cmpi    32,r3
1225         bgt     ufixh1
1226         cmpi    -32,r3
1227         ble     ufixh1
1228         ldi     1,r0
1229         ash     31,r0
1230         or3     r0,r2,r0
1231         ldi     r0,r1
1232         lsh3    r3,r0,r0
1233         subi    32,r3
1234         cmpi    -32,r3
1235         ldile   0,r1
1236         lsh3    r3,r1,r1
1237         rets
1238 ufixh1:
1239         ldi     0,r0
1240         ldi     0,r1
1241         rets
1242 #endif
1245 ; signed long long to long double conversion
1246 ; input on stack
1247 ; result in r0
1249 #ifdef L_floatdidf2
1250         .text
1251         .global ___floathihf2
1252         .ref ufloathihf2n
1253 ___floathihf2:
1254         ldi     sp,ar2
1255         ldi     *-ar2(2),r0
1256         ldi     *-ar2(1),r1
1257         bge     ufloathihf2n
1258         negi    r0
1259         negb    r1
1260         call    ufloathihf2n
1261         negf    r0
1262         rets
1263 #endif
1266 ; unsigned long long to double conversion
1267 ; input on stack
1268 ; result in r0
1270 #ifdef L_ufloatdidf2
1271         .text
1272         .global ___ufloathihf2
1273         .global ufloathihf2n
1274         .ref ___unsfltconst
1275 ___ufloathihf2:
1276         ldi     sp,ar2
1277         ldi     *-ar2(2),r0
1278         ldi     *-ar2(1),r1
1279 ufloathihf2n
1280         .if .BIGMODEL
1281 #ifdef _TMS320C4x
1282         ldpk    @___unsfltconst
1283 #else
1284         ldp     @___unsfltconst
1285 #endif
1286         .endif
1287         ldf     @___unsfltconst,r2
1288         float   r0
1289         bge     uflth1
1290         addf    r2,r0
1291 uflth1:
1292         float   r1
1293         bge     uflth2
1294         addf    r2,r1
1295 uflth2:
1296 #ifdef _TMS320C4x
1297         pop     r3
1298         bd      r3
1299         mpyf    r2,r1
1300         addf    r1,r0
1301         nop
1302 #else
1303         ldf     r1,r3
1304         and     0ffh,r3
1305         norm    r3,r3
1306         mpyf    r2,r3
1307         pop     ar2
1308         bd      ar2
1309         addf    r3,r0
1310         mpyf    r2,r1
1311         addf    r1,r0
1312 #endif
1313 #endif
1316 ; calculate ffs
1317 ; input in ar2
1318 ; result in r0
1320 #ifdef L_ffs
1321         .global ___ffs
1322         .ref ___unsfltconst
1323         .text
1324 ___ffs:
1325         .if .REGPARM == 0
1326 #ifdef _TMS320C4x
1327         lda     sp,ar0
1328 #else
1329         ldiu    sp,ar0
1330 #endif
1331         ldi     *-ar0(1), ar2
1332         .endif
1334         negi    ar2,r0
1335         and     ar2,r0
1336         float   r0,r0
1337         ldfu    0.0,r1
1338         .if .BIGMODEL
1339 #ifdef _TMS320C4x
1340         ldpk    @___unsfltconst
1341 #else
1342         ldp     @___unsfltconst
1343 #endif
1344         .endif
1345         ldflt   @___unsfltconst,r1
1346         addf    r1,r0
1347         pushf   r0
1348         pop     r0
1349         pop     ar0
1350         bd      ar0
1351         ash     -24,r0
1352         ldilt   -1,r0
1353         addi    1,r0
1354 #endif
1357 ; calculate long double * long double
1358 ; input in r2, r3
1359 ; output in r0
1361 #ifdef L_muldf3
1362         .global ___mulhf3
1363         .text
1364 ___mulhf3:
1365         .if .REGPARM == 0
1366 #ifdef _TMS320C4x
1367         lda     sp,ar0
1368 #else
1369         ldiu    sp,ar0
1370 #endif
1371         ldf     *-ar0(2), r2
1372         ldi     *-ar0(1), r2
1373         ldf     *-ar0(4), r3
1374         ldi     *-ar0(3), r3
1375         .endif
1377         pop     ar2             ; return ad
1378         ldf     r2,r0           ; copy lsb0
1379         ldf     r3,r1           ; copy lsb1
1380         and     0ffh,r0         ; mask lsb0
1381         and     0ffh,r1         ; mask lsb1
1382         norm    r0,r0           ; correct lsb0
1383         norm    r1,r1           ; correct lsb1
1384         mpyf    r2,r1           ; arg0*lsb1
1385         mpyf    r3,r0           ; arg1*lsb0
1386         bd      ar2             ; return (delayed)
1387         addf    r0,r1           ; arg0*lsb1 + arg1*lsb0
1388         mpyf    r2,r3,r0        ; msb0*msb1
1389         addf    r1,r0           ; msb0*msb1 + arg0*lsb1 + arg1*lsb0
1390 #endif
1393 ; calculate long double / long double
1394 ; r2 dividend, r3 divisor, r0 quotient
1396 #ifdef L_divdf3
1397         .global ___divhf3
1398         .text
1399 ___divhf3:
1400         .if .REGPARM == 0
1401 #ifdef _TMS320C4x
1402         lda     sp,ar0
1403 #else
1404         ldiu    sp,ar0
1405 #endif
1406         ldf     *-ar0(2), r2
1407         ldi     *-ar0(1), r2
1408         ldf     *-ar0(4), r3
1409         ldi     *-ar0(3), r3
1410         .endif
1412 #ifdef _TMS320C4x
1413         pop     ar1
1414         rcpf    r3, r0
1415         mpyf3   r0, r3, r1
1416         subrf   2.0, r1         
1417         mpyf    r1, r0  
1418         mpyf3   r0, r3, r1
1419         bud     ar1
1420         subrf   2.0, r1 
1421         mpyf    r1, r0
1422         mpyf    r2, r0
1423 #else
1424         pop     ar1
1425         pushf   r3
1426         pop     r0
1427         not     r0      
1428         push    r0
1429         popf    r0
1430         ldf     -1.0, r1
1431         xor     r1, r0
1433         mpyf3   r0, r3, r1      ; r1 = r[0] * v
1434         subrf   2.0, r1         ; r1 = 2.0 - r[0] * v
1435         mpyf    r1, r0          ; r0 = r[0] * (2.0 - r[0] * v) = r[1]
1436 ; End of 1st iteration
1438         mpyf3   r0, r3, r1      ; r1 = r[1] * v
1439         subrf   2.0, r1         ; r1 = 2.0 - r[1] * v
1440         mpyf    r1, r0          ; r0 = r[1] * (2.0 - r[1] * v) = r[2]
1441 ; End of 2nd iteration
1443         mpyf3   r0, r3, r1      ; r1 = r[2] * v
1444         subrf   2.0, r1         ; r1 = 2.0 - r[2] * v
1445         mpyf    r1, r0          ; r0 = r[2] * (2.0 - r[2] * v) = r[3]
1446 ; End of 3rd iteration
1448         or      080h, r0
1449         rnd     r0
1451 ;       mpyf3   r0, r3, r1      ; r1 = r[3] * v
1452         push    r4
1453         pushf   r4
1454         mpyf    r0, r3, r1
1456         ldf     r0, r4
1457         and     0ffh, r4
1458         norm    r4, r4
1459         mpyf    r3, r4
1460         addf    r4, r1
1462         ldf     r3, r4
1463         and     0ffh, r4
1464         norm    r4, r4
1465         mpyf    r0, r4
1466         addf    r4, r1
1467         
1468         subrf   2.0, r1         ; r1 = 2.0 - r[3] * v
1470         mpyf    r1, r0, r3      ; r3 = r[3] * (2.0 - r[3] * v) = r[5]
1472         ldf     r1, r4
1473         and     0ffh, r4
1474         norm    r4, r4
1475         mpyf    r0, r4
1476         addf    r4, r3
1478         ldf     r0, r4
1479         and     0ffh, r4
1480         norm    r4, r4
1481         mpyf    r1, r4
1482         addf    r4, r3
1484         mpyf    r2, r3, r0      ; Multiply by the dividend
1486         ldf     r2, r4
1487         and     0ffh, r4
1488         norm    r4, r4
1489         mpyf    r3, r4
1490         addf    r4, r0
1492         ldf     r3, r4
1493         and     0ffh, r4
1494         norm    r4, r4
1495         mpyf    r2, r4
1496         bd      ar1
1497         addf    r4, r0
1499         popf    r4
1500         pop     r4
1501 #endif
1502 #endif