| ;; libgcc routines for the Renesas H8/300 CPU. |
| ;; Contributed by Steve Chamberlain <sac@cygnus.com> |
| ;; Optimizations by Toshiyasu Morita <toshiyasu.morita@renesas.com> |
| |
| /* Copyright (C) 1994-2025 Free Software Foundation, Inc. |
| |
| This file is free software; you can redistribute it and/or modify it |
| under the terms of the GNU General Public License as published by the |
| Free Software Foundation; either version 3, or (at your option) any |
| later version. |
| |
| This file is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| Under Section 7 of GPL version 3, you are granted additional |
| permissions described in the GCC Runtime Library Exception, version |
| 3.1, as published by the Free Software Foundation. |
| |
| You should have received a copy of the GNU General Public License and |
| a copy of the GCC Runtime Library Exception along with this program; |
| see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
| <http://www.gnu.org/licenses/>. */ |
| |
| /* Assembler register definitions. */ |
| |
| #define A0 r0 |
| #define A0L r0l |
| #define A0H r0h |
| |
| #define A1 r1 |
| #define A1L r1l |
| #define A1H r1h |
| |
| #define A2 r2 |
| #define A2L r2l |
| #define A2H r2h |
| |
| #define A3 r3 |
| #define A3L r3l |
| #define A3H r3h |
| |
| #define S0 r4 |
| #define S0L r4l |
| #define S0H r4h |
| |
| #define S1 r5 |
| #define S1L r5l |
| #define S1H r5h |
| |
| #define S2 r6 |
| #define S2L r6l |
| #define S2H r6h |
| |
| #ifdef __H8300__ |
| #define PUSHP push |
| #define POPP pop |
| |
| #define A0P r0 |
| #define A1P r1 |
| #define A2P r2 |
| #define A3P r3 |
| #define S0P r4 |
| #define S1P r5 |
| #define S2P r6 |
| #endif |
| |
| #if defined (__H8300H__) || defined (__H8300S__) || defined (__H8300SX__) |
| #define PUSHP push.l |
| #define POPP pop.l |
| |
| #define A0P er0 |
| #define A1P er1 |
| #define A2P er2 |
| #define A3P er3 |
| #define S0P er4 |
| #define S1P er5 |
| #define S2P er6 |
| |
| #define A0E e0 |
| #define A1E e1 |
| #define A2E e2 |
| #define A3E e3 |
| #endif |
| |
| #define CONCAT(A,B) A##B |
| #define LABEL0(U,X) CONCAT(U,__##X) |
| #define LABEL0_DEF(U,X) CONCAT(U,__##X##:) |
| #define LABEL_DEF(X) LABEL0_DEF(__USER_LABEL_PREFIX__,X) |
| #define LABEL(X) LABEL0(__USER_LABEL_PREFIX__,X) |
| |
| #ifdef __H8300H__ |
| #ifdef __NORMAL_MODE__ |
| .h8300hn |
| #else |
| .h8300h |
| #endif |
| #endif |
| |
| #ifdef __H8300S__ |
| #ifdef __NORMAL_MODE__ |
| .h8300sn |
| #else |
| .h8300s |
| #endif |
| #endif |
| #ifdef __H8300SX__ |
| #ifdef __NORMAL_MODE__ |
| .h8300sxn |
| #else |
| .h8300sx |
| #endif |
| #endif |
| |
| #ifdef L_cmpsi2 |
| #ifdef __H8300__ |
| .section .text |
| .align 2 |
| .global LABEL(cmpsi2) |
| LABEL_DEF(cmpsi2) |
| cmp.w A0,A2 |
| bne .L2 |
| cmp.w A1,A3 |
| bne .L4 |
| mov.w #1,A0 |
| rts |
| .L2: |
| bgt .L5 |
| .L3: |
| mov.w #2,A0 |
| rts |
| .L4: |
| bls .L3 |
| .L5: |
| sub.w A0,A0 |
| rts |
| .end |
| #endif |
| #endif /* L_cmpsi2 */ |
| |
| #ifdef L_ucmpsi2 |
| #ifdef __H8300__ |
| .section .text |
| .align 2 |
| .global LABEL(ucmpsi2) |
| LABEL_DEF(ucmpsi2) |
| cmp.w A0,A2 |
| bne .L2 |
| cmp.w A1,A3 |
| bne .L4 |
| mov.w #1,A0 |
| rts |
| .L2: |
| bhi .L5 |
| .L3: |
| mov.w #2,A0 |
| rts |
| .L4: |
| bls .L3 |
| .L5: |
| sub.w A0,A0 |
| rts |
| .end |
| #endif |
| #endif /* L_ucmpsi2 */ |
| |
| #ifdef L_divhi3 |
| |
| ;; HImode divides for the H8/300. |
| ;; We bunch all of this into one object file since there are several |
| ;; "supporting routines". |
| |
| ; general purpose normalize routine |
| ; |
| ; divisor in A0 |
| ; dividend in A1 |
| ; turns both into +ve numbers, and leaves what the answer sign |
| ; should be in A2L |
| |
| #ifdef __H8300__ |
| .section .text |
| .align 2 |
| divnorm: |
| or A0H,A0H ; is divisor > 0 |
| stc ccr,A2L |
| bge _lab1 |
| not A0H ; no - then make it +ve |
| not A0L |
| adds #1,A0 |
| _lab1: or A1H,A1H ; look at dividend |
| bge _lab2 |
| not A1H ; it is -ve, make it positive |
| not A1L |
| adds #1,A1 |
| xor #0x8,A2L; and toggle sign of result |
| _lab2: rts |
| ;; Basically the same, except that the sign of the divisor determines |
| ;; the sign. |
| modnorm: |
| or A0H,A0H ; is divisor > 0 |
| stc ccr,A2L |
| bge _lab7 |
| not A0H ; no - then make it +ve |
| not A0L |
| adds #1,A0 |
| _lab7: or A1H,A1H ; look at dividend |
| bge _lab8 |
| not A1H ; it is -ve, make it positive |
| not A1L |
| adds #1,A1 |
| _lab8: rts |
| |
| ; A0=A0/A1 signed |
| |
| .global LABEL(divhi3) |
| LABEL_DEF(divhi3) |
| bsr divnorm |
| bsr LABEL(udivhi3) |
| negans: btst #3,A2L ; should answer be negative ? |
| beq _lab4 |
| not A0H ; yes, so make it so |
| not A0L |
| adds #1,A0 |
| _lab4: rts |
| |
| ; A0=A0%A1 signed |
| |
| .global LABEL(modhi3) |
| LABEL_DEF(modhi3) |
| bsr modnorm |
| bsr LABEL(udivhi3) |
| mov A3,A0 |
| bra negans |
| |
| ; A0=A0%A1 unsigned |
| |
| .global LABEL(umodhi3) |
| LABEL_DEF(umodhi3) |
| bsr LABEL(udivhi3) |
| mov A3,A0 |
| rts |
| |
| ; A0=A0/A1 unsigned |
| ; A3=A0%A1 unsigned |
| ; A2H trashed |
| ; D high 8 bits of denom |
| ; d low 8 bits of denom |
| ; N high 8 bits of num |
| ; n low 8 bits of num |
| ; M high 8 bits of mod |
| ; m low 8 bits of mod |
| ; Q high 8 bits of quot |
| ; q low 8 bits of quot |
| ; P preserve |
| |
| ; The H8/300 only has a 16/8 bit divide, so we look at the incoming and |
| ; see how to partition up the expression. |
| |
| .global LABEL(udivhi3) |
| LABEL_DEF(udivhi3) |
| ; A0 A1 A2 A3 |
| ; Nn Dd P |
| sub.w A3,A3 ; Nn Dd xP 00 |
| or A1H,A1H |
| bne divlongway |
| or A0H,A0H |
| beq _lab6 |
| |
| ; we know that D == 0 and N is != 0 |
| mov.b A0H,A3L ; Nn Dd xP 0N |
| divxu A1L,A3 ; MQ |
| mov.b A3L,A0H ; Q |
| ; dealt with N, do n |
| _lab6: mov.b A0L,A3L ; n |
| divxu A1L,A3 ; mq |
| mov.b A3L,A0L ; Qq |
| mov.b A3H,A3L ; m |
| mov.b #0x0,A3H ; Qq 0m |
| rts |
| |
| ; D != 0 - which means the denominator is |
| ; loop around to get the result. |
| |
| divlongway: |
| mov.b A0H,A3L ; Nn Dd xP 0N |
| mov.b #0x0,A0H ; high byte of answer has to be zero |
| mov.b #0x8,A2H ; 8 |
| div8: add.b A0L,A0L ; n*=2 |
| rotxl A3L ; Make remainder bigger |
| rotxl A3H |
| sub.w A1,A3 ; Q-=N |
| bhs setbit ; set a bit ? |
| add.w A1,A3 ; no : too far , Q+=N |
| |
| dec A2H |
| bne div8 ; next bit |
| rts |
| |
| setbit: inc A0L ; do insert bit |
| dec A2H |
| bne div8 ; next bit |
| rts |
| |
| #endif /* __H8300__ */ |
| #endif /* L_divhi3 */ |
| |
| #ifdef L_divsi3 |
| |
| ;; 4 byte integer divides for the H8/300. |
| ;; |
| ;; We have one routine which does all the work and lots of |
| ;; little ones which prepare the args and massage the sign. |
| ;; We bunch all of this into one object file since there are several |
| ;; "supporting routines". |
| |
| .section .text |
| .align 2 |
| |
| ; Put abs SIs into r0/r1 and r2/r3, and leave a 1 in r6l with sign of rest. |
| ; This function is here to keep branch displacements small. |
| |
| #ifdef __H8300__ |
| |
| divnorm: |
| mov.b A0H,A0H ; is the numerator -ve |
| stc ccr,S2L ; keep the sign in bit 3 of S2L |
| bge postive |
| |
| ; negate arg |
| not A0H |
| not A1H |
| not A0L |
| not A1L |
| |
| add #1,A1L |
| addx #0,A1H |
| addx #0,A0L |
| addx #0,A0H |
| postive: |
| mov.b A2H,A2H ; is the denominator -ve |
| bge postive2 |
| not A2L |
| not A2H |
| not A3L |
| not A3H |
| add.b #1,A3L |
| addx #0,A3H |
| addx #0,A2L |
| addx #0,A2H |
| xor.b #0x08,S2L ; toggle the result sign |
| postive2: |
| rts |
| |
| ;; Basically the same, except that the sign of the divisor determines |
| ;; the sign. |
| modnorm: |
| mov.b A0H,A0H ; is the numerator -ve |
| stc ccr,S2L ; keep the sign in bit 3 of S2L |
| bge mpostive |
| |
| ; negate arg |
| not A0H |
| not A1H |
| not A0L |
| not A1L |
| |
| add #1,A1L |
| addx #0,A1H |
| addx #0,A0L |
| addx #0,A0H |
| mpostive: |
| mov.b A2H,A2H ; is the denominator -ve |
| bge mpostive2 |
| not A2L |
| not A2H |
| not A3L |
| not A3H |
| add.b #1,A3L |
| addx #0,A3H |
| addx #0,A2L |
| addx #0,A2H |
| mpostive2: |
| rts |
| |
| #else /* __H8300H__ */ |
| |
| divnorm: |
| mov.l A0P,A0P ; is the numerator -ve |
| stc ccr,S2L ; keep the sign in bit 3 of S2L |
| bge postive |
| |
| neg.l A0P ; negate arg |
| |
| postive: |
| mov.l A1P,A1P ; is the denominator -ve |
| bge postive2 |
| |
| neg.l A1P ; negate arg |
| xor.b #0x08,S2L ; toggle the result sign |
| |
| postive2: |
| rts |
| |
| ;; Basically the same, except that the sign of the divisor determines |
| ;; the sign. |
| modnorm: |
| mov.l A0P,A0P ; is the numerator -ve |
| stc ccr,S2L ; keep the sign in bit 3 of S2L |
| bge mpostive |
| |
| neg.l A0P ; negate arg |
| |
| mpostive: |
| mov.l A1P,A1P ; is the denominator -ve |
| bge mpostive2 |
| |
| neg.l A1P ; negate arg |
| |
| mpostive2: |
| rts |
| |
| #endif |
| |
| ; numerator in A0/A1 |
| ; denominator in A2/A3 |
| .global LABEL(modsi3) |
| LABEL_DEF(modsi3) |
| #ifdef __H8300__ |
| PUSHP S2P |
| PUSHP S0P |
| PUSHP S1P |
| bsr modnorm |
| bsr divmodsi4 |
| mov S0,A0 |
| mov S1,A1 |
| bra exitdiv |
| #else |
| PUSHP S2P |
| bsr modnorm |
| bsr LABEL(divsi3) |
| mov.l er3,er0 |
| bra exitdiv |
| #endif |
| |
| ;; H8/300H and H8S version of ___udivsi3 is defined later in |
| ;; the file. |
| #ifdef __H8300__ |
| .global LABEL(udivsi3) |
| LABEL_DEF(udivsi3) |
| PUSHP S2P |
| PUSHP S0P |
| PUSHP S1P |
| bsr divmodsi4 |
| bra reti |
| #endif |
| |
| .global LABEL(umodsi3) |
| LABEL_DEF(umodsi3) |
| #ifdef __H8300__ |
| PUSHP S2P |
| PUSHP S0P |
| PUSHP S1P |
| bsr divmodsi4 |
| mov S0,A0 |
| mov S1,A1 |
| bra reti |
| #else |
| bsr LABEL(udivsi3) |
| mov.l er3,er0 |
| rts |
| #endif |
| |
| .global LABEL(divsi3) |
| LABEL_DEF(divsi3) |
| #ifdef __H8300__ |
| PUSHP S2P |
| PUSHP S0P |
| PUSHP S1P |
| jsr divnorm |
| jsr divmodsi4 |
| #else |
| PUSHP S2P |
| jsr divnorm |
| bsr LABEL(udivsi3) |
| #endif |
| |
| ; examine what the sign should be |
| exitdiv: |
| btst #3,S2L |
| beq reti |
| |
| ; should be -ve |
| #ifdef __H8300__ |
| not A0H |
| not A1H |
| not A0L |
| not A1L |
| |
| add #1,A1L |
| addx #0,A1H |
| addx #0,A0L |
| addx #0,A0H |
| #else /* __H8300H__ */ |
| neg.l A0P |
| #endif |
| |
| reti: |
| #ifdef __H8300__ |
| POPP S1P |
| POPP S0P |
| #endif |
| POPP S2P |
| rts |
| |
| ; takes A0/A1 numerator (A0P for H8/300H) |
| ; A2/A3 denominator (A1P for H8/300H) |
| ; returns A0/A1 quotient (A0P for H8/300H) |
| ; S0/S1 remainder (S0P for H8/300H) |
| ; trashes S2H |
| |
| #ifdef __H8300__ |
| |
| divmodsi4: |
| sub.w S0,S0 ; zero play area |
| mov.w S0,S1 |
| mov.b A2H,S2H |
| or A2L,S2H |
| or A3H,S2H |
| bne DenHighNonZero |
| mov.b A0H,A0H |
| bne NumByte0Zero |
| mov.b A0L,A0L |
| bne NumByte1Zero |
| mov.b A1H,A1H |
| bne NumByte2Zero |
| bra NumByte3Zero |
| NumByte0Zero: |
| mov.b A0H,S1L |
| divxu A3L,S1 |
| mov.b S1L,A0H |
| NumByte1Zero: |
| mov.b A0L,S1L |
| divxu A3L,S1 |
| mov.b S1L,A0L |
| NumByte2Zero: |
| mov.b A1H,S1L |
| divxu A3L,S1 |
| mov.b S1L,A1H |
| NumByte3Zero: |
| mov.b A1L,S1L |
| divxu A3L,S1 |
| mov.b S1L,A1L |
| |
| mov.b S1H,S1L |
| mov.b #0x0,S1H |
| rts |
| |
| ; have to do the divide by shift and test |
| DenHighNonZero: |
| mov.b A0H,S1L |
| mov.b A0L,A0H |
| mov.b A1H,A0L |
| mov.b A1L,A1H |
| |
| mov.b #0,A1L |
| mov.b #24,S2H ; only do 24 iterations |
| |
| nextbit: |
| add.w A1,A1 ; double the answer guess |
| rotxl A0L |
| rotxl A0H |
| |
| rotxl S1L ; double remainder |
| rotxl S1H |
| rotxl S0L |
| rotxl S0H |
| sub.w A3,S1 ; does it all fit |
| subx A2L,S0L |
| subx A2H,S0H |
| bhs setone |
| |
| add.w A3,S1 ; no, restore mistake |
| addx A2L,S0L |
| addx A2H,S0H |
| |
| dec S2H |
| bne nextbit |
| rts |
| |
| setone: |
| inc A1L |
| dec S2H |
| bne nextbit |
| rts |
| |
| #else /* __H8300H__ */ |
| |
| ;; This function also computes the remainder and stores it in er3. |
| .global LABEL(udivsi3) |
| LABEL_DEF(udivsi3) |
| mov.w A1E,A1E ; denominator top word 0? |
| bne DenHighNonZero |
| |
| ; do it the easy way, see page 107 in manual |
| mov.w A0E,A2 |
| extu.l A2P |
| divxu.w A1,A2P |
| mov.w A2E,A0E |
| divxu.w A1,A0P |
| mov.w A0E,A3 |
| mov.w A2,A0E |
| extu.l A3P |
| rts |
| |
| ; er0 = er0 / er1 |
| ; er3 = er0 % er1 |
| ; trashes er1 er2 |
| ; expects er1 >= 2^16 |
| DenHighNonZero: |
| mov.l er0,er3 |
| mov.l er1,er2 |
| #ifdef __H8300H__ |
| divmod_L21: |
| shlr.l er0 |
| shlr.l er2 ; make divisor < 2^16 |
| mov.w e2,e2 |
| bne divmod_L21 |
| #else |
| shlr.l #2,er2 ; make divisor < 2^16 |
| mov.w e2,e2 |
| beq divmod_L22A |
| divmod_L21: |
| shlr.l #2,er0 |
| divmod_L22: |
| shlr.l #2,er2 ; make divisor < 2^16 |
| mov.w e2,e2 |
| bne divmod_L21 |
| divmod_L22A: |
| rotxl.w r2 |
| bcs divmod_L23 |
| shlr.l er0 |
| bra divmod_L24 |
| divmod_L23: |
| rotxr.w r2 |
| shlr.l #2,er0 |
| divmod_L24: |
| #endif |
| ;; At this point, |
| ;; er0 contains shifted dividend |
| ;; er1 contains divisor |
| ;; er2 contains shifted divisor |
| ;; er3 contains dividend, later remainder |
| divxu.w r2,er0 ; r0 now contains the approximate quotient (AQ) |
| extu.l er0 |
| beq divmod_L25 |
| subs #1,er0 ; er0 = AQ - 1 |
| mov.w e1,r2 |
| mulxu.w r0,er2 ; er2 = upper (AQ - 1) * divisor |
| sub.w r2,e3 ; dividend - 65536 * er2 |
| mov.w r1,r2 |
| mulxu.w r0,er2 ; compute er3 = remainder (tentative) |
| sub.l er2,er3 ; er3 = dividend - (AQ - 1) * divisor |
| divmod_L25: |
| cmp.l er1,er3 ; is divisor < remainder? |
| blo divmod_L26 |
| adds #1,er0 |
| sub.l er1,er3 ; correct the remainder |
| divmod_L26: |
| rts |
| |
| #endif |
| #endif /* L_divsi3 */ |
| |
| #ifdef L_mulhi3 |
| |
| ;; HImode multiply. |
| ; The H8/300 only has an 8*8->16 multiply. |
| ; The answer is the same as: |
| ; |
| ; product = (srca.l * srcb.l) + ((srca.h * srcb.l) + (srcb.h * srca.l)) * 256 |
| ; (we can ignore A1.h * A0.h cause that will all off the top) |
| ; A0 in |
| ; A1 in |
| ; A0 answer |
| |
| #ifdef __H8300__ |
| .section .text |
| .align 2 |
| .global LABEL(mulhi3) |
| LABEL_DEF(mulhi3) |
| mov.b A1L,A2L ; A2l gets srcb.l |
| mulxu A0L,A2 ; A2 gets first sub product |
| |
| mov.b A0H,A3L ; prepare for |
| mulxu A1L,A3 ; second sub product |
| |
| add.b A3L,A2H ; sum first two terms |
| |
| mov.b A1H,A3L ; third sub product |
| mulxu A0L,A3 |
| |
| add.b A3L,A2H ; almost there |
| mov.w A2,A0 ; that is |
| rts |
| |
| #endif |
| #endif /* L_mulhi3 */ |
| |
| #ifdef L_mulsi3 |
| |
| ;; SImode multiply. |
| ;; |
| ;; I think that shift and add may be sufficient for this. Using the |
| ;; supplied 8x8->16 would need 10 ops of 14 cycles each + overhead. This way |
| ;; the inner loop uses maybe 20 cycles + overhead, but terminates |
| ;; quickly on small args. |
| ;; |
| ;; A0/A1 src_a |
| ;; A2/A3 src_b |
| ;; |
| ;; while (a) |
| ;; { |
| ;; if (a & 1) |
| ;; r += b; |
| ;; a >>= 1; |
| ;; b <<= 1; |
| ;; } |
| |
| .section .text |
| .align 2 |
| |
| #ifdef __H8300__ |
| |
| .global LABEL(mulsi3) |
| LABEL_DEF(mulsi3) |
| PUSHP S0P |
| PUSHP S1P |
| |
| sub.w S0,S0 |
| sub.w S1,S1 |
| |
| ; while (a) |
| _top: mov.w A0,A0 |
| bne _more |
| mov.w A1,A1 |
| beq _done |
| _more: ; if (a & 1) |
| bld #0,A1L |
| bcc _nobit |
| ; r += b |
| add.w A3,S1 |
| addx A2L,S0L |
| addx A2H,S0H |
| _nobit: |
| ; a >>= 1 |
| shlr A0H |
| rotxr A0L |
| rotxr A1H |
| rotxr A1L |
| |
| ; b <<= 1 |
| add.w A3,A3 |
| addx A2L,A2L |
| addx A2H,A2H |
| bra _top |
| |
| _done: |
| mov.w S0,A0 |
| mov.w S1,A1 |
| POPP S1P |
| POPP S0P |
| rts |
| |
| #else /* __H8300H__ */ |
| |
| ; |
| ; mulsi3 for H8/300H - based on Renesas SH implementation |
| ; |
| ; by Toshiyasu Morita |
| ; |
| ; Old code: |
| ; |
| ; 16b * 16b = 372 states (worst case) |
| ; 32b * 32b = 724 states (worst case) |
| ; |
| ; New code: |
| ; |
| ; 16b * 16b = 48 states |
| ; 16b * 32b = 72 states |
| ; 32b * 32b = 92 states |
| ; |
| |
| .global LABEL(mulsi3) |
| LABEL_DEF(mulsi3) |
| mov.w r1,r2 ; ( 2 states) b * d |
| mulxu r0,er2 ; (22 states) |
| |
| mov.w e0,r3 ; ( 2 states) a * d |
| beq L_skip1 ; ( 4 states) |
| mulxu r1,er3 ; (22 states) |
| add.w r3,e2 ; ( 2 states) |
| |
| L_skip1: |
| mov.w e1,r3 ; ( 2 states) c * b |
| beq L_skip2 ; ( 4 states) |
| mulxu r0,er3 ; (22 states) |
| add.w r3,e2 ; ( 2 states) |
| |
| L_skip2: |
| mov.l er2,er0 ; ( 2 states) |
| rts ; (10 states) |
| |
| #endif |
| #endif /* L_mulsi3 */ |
| #ifdef L_fixunssfsi_asm |
| /* For the h8300 we use asm to save some bytes, to |
| allow more programs to fit into the tiny address |
| space. For the H8/300H and H8S, the C version is good enough. */ |
| #ifdef __H8300__ |
| /* We still treat NANs different than libgcc2.c, but then, the |
| behavior is undefined anyways. */ |
| .global LABEL(fixunssfsi) |
| LABEL_DEF(fixunssfsi) |
| cmp.b #0x4f,r0h |
| bge Large_num |
| jmp @LABEL(fixsfsi) |
| Large_num: |
| bhi L_huge_num |
| xor.b #0x80,A0L |
| bmi L_shift8 |
| L_huge_num: |
| mov.w #65535,A0 |
| mov.w A0,A1 |
| rts |
| L_shift8: |
| mov.b A0L,A0H |
| mov.b A1H,A0L |
| mov.b A1L,A1H |
| mov.b #0,A1L |
| rts |
| #endif |
| #endif /* L_fixunssfsi_asm */ |