Home | History | Annotate | Line # | Download | only in sh
      1  1.10  mrg /* Copyright (C) 2006-2022 Free Software Foundation, Inc.
      2   1.1  mrg 
      3   1.1  mrg This file is free software; you can redistribute it and/or modify it
      4   1.1  mrg under the terms of the GNU General Public License as published by the
      5   1.1  mrg Free Software Foundation; either version 3, or (at your option) any
      6   1.1  mrg later version.
      7   1.1  mrg 
      8   1.1  mrg This file is distributed in the hope that it will be useful, but
      9   1.1  mrg WITHOUT ANY WARRANTY; without even the implied warranty of
     10   1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     11   1.1  mrg General Public License for more details.
     12   1.1  mrg 
     13   1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     14   1.1  mrg permissions described in the GCC Runtime Library Exception, version
     15   1.1  mrg 3.1, as published by the Free Software Foundation.
     16   1.1  mrg 
     17   1.1  mrg You should have received a copy of the GNU General Public License and
     18   1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     19   1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     20   1.1  mrg <http://www.gnu.org/licenses/>.  */
     21   1.1  mrg 
     22   1.1  mrg /* Moderately Space-optimized libgcc routines for the Renesas SH /
     23   1.1  mrg    STMicroelectronics ST40 CPUs.
     24   1.1  mrg    Contributed by J"orn Rennecke joern.rennecke (at) st.com.  */
     25   1.1  mrg 
     26   1.1  mrg #include "lib1funcs.h"
     27   1.1  mrg 
     28   1.1  mrg #ifdef L_udivsi3_i4i
     29   1.1  mrg 
     30   1.1  mrg /* 88 bytes; sh4-200 cycle counts:
     31   1.1  mrg    divisor  >= 2G: 11 cycles
     32   1.1  mrg    dividend <  2G: 48 cycles
     33   1.1  mrg    dividend >= 2G: divisor != 1: 54 cycles
     34   1.1  mrg    dividend >= 2G, divisor == 1: 22 cycles */
     35   1.1  mrg #if defined (__SH_FPU_DOUBLE__) || defined (__SH4_SINGLE_ONLY__)
     36   1.1  mrg !! args in r4 and r5, result in r0, clobber r1
     37   1.1  mrg 
     38   1.1  mrg 	.global GLOBAL(udivsi3_i4i)
     39   1.1  mrg 	FUNC(GLOBAL(udivsi3_i4i))
     40   1.1  mrg GLOBAL(udivsi3_i4i):
     41   1.1  mrg 	mova L1,r0
     42   1.1  mrg 	cmp/pz r5
     43   1.1  mrg 	sts fpscr,r1
     44   1.1  mrg 	lds.l @r0+,fpscr
     45   1.1  mrg 	sts.l fpul,@-r15
     46   1.1  mrg 	bf LOCAL(huge_divisor)
     47   1.1  mrg 	mov.l r1,@-r15
     48   1.1  mrg 	lds r4,fpul
     49   1.1  mrg 	cmp/pz r4
     50   1.1  mrg #ifdef FMOVD_WORKS
     51   1.1  mrg 	fmov.d dr0,@-r15
     52   1.1  mrg 	float fpul,dr0
     53   1.1  mrg 	fmov.d dr2,@-r15
     54   1.1  mrg 	bt LOCAL(dividend_adjusted)
     55   1.1  mrg 	mov #1,r1
     56   1.1  mrg 	fmov.d @r0,dr2
     57   1.1  mrg 	cmp/eq r1,r5
     58   1.1  mrg 	bt LOCAL(div_by_1)
     59   1.1  mrg 	fadd dr2,dr0
     60   1.1  mrg LOCAL(dividend_adjusted):
     61   1.1  mrg 	lds r5,fpul
     62   1.1  mrg 	float fpul,dr2
     63   1.1  mrg 	fdiv dr2,dr0
     64   1.1  mrg LOCAL(div_by_1):
     65   1.1  mrg 	fmov.d @r15+,dr2
     66   1.1  mrg 	ftrc dr0,fpul
     67   1.1  mrg 	fmov.d @r15+,dr0
     68   1.1  mrg #else /* !FMOVD_WORKS */
     69   1.1  mrg 	fmov.s DR01,@-r15
     70   1.1  mrg 	mov #1,r1
     71   1.1  mrg 	fmov.s DR00,@-r15
     72   1.1  mrg 	float fpul,dr0
     73   1.1  mrg 	fmov.s DR21,@-r15
     74   1.1  mrg 	bt/s LOCAL(dividend_adjusted)
     75   1.1  mrg 	fmov.s DR20,@-r15
     76   1.1  mrg 	cmp/eq r1,r5
     77   1.1  mrg 	bt LOCAL(div_by_1)
     78   1.1  mrg 	fmov.s @r0+,DR20
     79   1.1  mrg 	fmov.s @r0,DR21
     80   1.1  mrg 	fadd dr2,dr0
     81   1.1  mrg LOCAL(dividend_adjusted):
     82   1.1  mrg 	lds r5,fpul
     83   1.1  mrg 	float fpul,dr2
     84   1.1  mrg 	fdiv dr2,dr0
     85   1.1  mrg LOCAL(div_by_1):
     86   1.1  mrg 	fmov.s @r15+,DR20
     87   1.1  mrg 	fmov.s @r15+,DR21
     88   1.1  mrg 	ftrc dr0,fpul
     89   1.1  mrg 	fmov.s @r15+,DR00
     90   1.1  mrg 	fmov.s @r15+,DR01
     91   1.1  mrg #endif /* !FMOVD_WORKS */
     92   1.1  mrg 	lds.l @r15+,fpscr
     93   1.1  mrg 	sts fpul,r0
     94   1.1  mrg 	rts
     95   1.1  mrg 	lds.l @r15+,fpul
     96   1.1  mrg 
     97   1.1  mrg #ifdef FMOVD_WORKS
     98   1.1  mrg 	.p2align 3        ! make double below 8 byte aligned.
     99   1.1  mrg #endif
    100   1.1  mrg LOCAL(huge_divisor):
    101   1.1  mrg 	lds r1,fpscr
    102   1.1  mrg 	add #4,r15
    103   1.1  mrg 	cmp/hs r5,r4
    104   1.1  mrg 	rts
    105   1.1  mrg 	movt r0
    106   1.1  mrg 
    107   1.1  mrg 	.p2align 2
    108   1.1  mrg L1:
    109   1.1  mrg #ifndef FMOVD_WORKS
    110   1.1  mrg 	.long 0x80000
    111   1.1  mrg #else
    112   1.1  mrg 	.long 0x180000
    113   1.1  mrg #endif
    114   1.1  mrg 	.double 4294967296
    115   1.1  mrg 
    116   1.1  mrg 	ENDFUNC(GLOBAL(udivsi3_i4i))
    117   1.1  mrg #elif !defined (__sh1__)  /* !__SH_FPU_DOUBLE__ */
    118   1.1  mrg 
    119   1.1  mrg #if 0
    120   1.1  mrg /* With 36 bytes, the following would probably be the most compact
    121   1.1  mrg    implementation, but with 139 cycles on an sh4-200, it is extremely slow.  */
    122   1.1  mrg GLOBAL(udivsi3_i4i):
    123   1.1  mrg 	mov.l r2,@-r15
    124   1.1  mrg 	mov #0,r1
    125   1.1  mrg 	div0u
    126   1.1  mrg 	mov r1,r2
    127   1.1  mrg 	mov.l r3,@-r15
    128   1.1  mrg 	mov r1,r3
    129   1.1  mrg 	sett
    130   1.1  mrg 	mov r4,r0
    131   1.1  mrg LOCAL(loop):
    132   1.1  mrg 	rotcr r2
    133   1.1  mrg 	;
    134   1.1  mrg 	bt/s LOCAL(end)
    135   1.1  mrg 	cmp/gt r2,r3
    136   1.1  mrg 	rotcl r0
    137   1.1  mrg 	bra LOCAL(loop)
    138   1.1  mrg 	div1 r5,r1
    139   1.1  mrg LOCAL(end):
    140   1.1  mrg 	rotcl r0
    141   1.1  mrg 	mov.l @r15+,r3
    142   1.1  mrg 	rts
    143   1.1  mrg 	mov.l @r15+,r2
    144   1.1  mrg #endif /* 0 */
    145   1.1  mrg 
    146   1.1  mrg /* Size: 186 bytes jointly for udivsi3_i4i and sdivsi3_i4i
    147   1.1  mrg    sh4-200 run times:
    148   1.1  mrg    udiv small divisor: 55 cycles
    149   1.1  mrg    udiv large divisor: 52 cycles
    150   1.1  mrg    sdiv small divisor, positive result: 59 cycles
    151   1.1  mrg    sdiv large divisor, positive result: 56 cycles
    152   1.1  mrg    sdiv small divisor, negative result: 65 cycles (*)
    153   1.1  mrg    sdiv large divisor, negative result: 62 cycles (*)
    154   1.1  mrg    (*): r2 is restored in the rts delay slot and has a lingering latency
    155   1.1  mrg         of two more cycles.  */
    156   1.1  mrg 	.balign 4
    157   1.1  mrg 	.global	GLOBAL(udivsi3_i4i)
    158   1.1  mrg 	FUNC(GLOBAL(udivsi3_i4i))
    159   1.1  mrg 	FUNC(GLOBAL(sdivsi3_i4i))
    160   1.1  mrg GLOBAL(udivsi3_i4i):
    161   1.1  mrg 	sts pr,r1
    162   1.1  mrg 	mov.l r4,@-r15
    163   1.1  mrg 	extu.w r5,r0
    164   1.1  mrg 	cmp/eq r5,r0
    165   1.1  mrg 	swap.w r4,r0
    166   1.1  mrg 	shlr16 r4
    167   1.1  mrg 	bf/s LOCAL(large_divisor)
    168   1.1  mrg 	div0u
    169   1.1  mrg 	mov.l r5,@-r15
    170   1.1  mrg 	shll16 r5
    171   1.1  mrg LOCAL(sdiv_small_divisor):
    172   1.1  mrg 	div1 r5,r4
    173   1.1  mrg 	bsr LOCAL(div6)
    174   1.1  mrg 	div1 r5,r4
    175   1.1  mrg 	div1 r5,r4
    176   1.1  mrg 	bsr LOCAL(div6)
    177   1.1  mrg 	div1 r5,r4
    178   1.1  mrg 	xtrct r4,r0
    179   1.1  mrg 	xtrct r0,r4
    180   1.1  mrg 	bsr LOCAL(div7)
    181   1.1  mrg 	swap.w r4,r4
    182   1.1  mrg 	div1 r5,r4
    183   1.1  mrg 	bsr LOCAL(div7)
    184   1.1  mrg 	div1 r5,r4
    185   1.1  mrg 	xtrct r4,r0
    186   1.1  mrg 	mov.l @r15+,r5
    187   1.1  mrg 	swap.w r0,r0
    188   1.1  mrg 	mov.l @r15+,r4
    189   1.1  mrg 	jmp @r1
    190   1.1  mrg 	rotcl r0
    191   1.1  mrg LOCAL(div7):
    192   1.1  mrg 	div1 r5,r4
    193   1.1  mrg LOCAL(div6):
    194   1.1  mrg 	            div1 r5,r4; div1 r5,r4; div1 r5,r4
    195   1.1  mrg 	div1 r5,r4; div1 r5,r4; rts;        div1 r5,r4
    196   1.1  mrg 
    197   1.1  mrg LOCAL(divx3):
    198   1.1  mrg 	rotcl r0
    199   1.1  mrg 	div1 r5,r4
    200   1.1  mrg 	rotcl r0
    201   1.1  mrg 	div1 r5,r4
    202   1.1  mrg 	rotcl r0
    203   1.1  mrg 	rts
    204   1.1  mrg 	div1 r5,r4
    205   1.1  mrg 
    206   1.1  mrg LOCAL(large_divisor):
    207   1.1  mrg 	mov.l r5,@-r15
    208   1.1  mrg LOCAL(sdiv_large_divisor):
    209   1.1  mrg 	xor r4,r0
    210   1.1  mrg 	.rept 4
    211   1.1  mrg 	rotcl r0
    212   1.1  mrg 	bsr LOCAL(divx3)
    213   1.1  mrg 	div1 r5,r4
    214   1.1  mrg 	.endr
    215   1.1  mrg 	mov.l @r15+,r5
    216   1.1  mrg 	mov.l @r15+,r4
    217   1.1  mrg 	jmp @r1
    218   1.1  mrg 	rotcl r0
    219   1.1  mrg 	ENDFUNC(GLOBAL(udivsi3_i4i))
    220   1.1  mrg 
    221   1.1  mrg 	.global	GLOBAL(sdivsi3_i4i)
    222   1.1  mrg GLOBAL(sdivsi3_i4i):
    223   1.1  mrg 	mov.l r4,@-r15
    224   1.1  mrg 	cmp/pz r5
    225   1.1  mrg 	mov.l r5,@-r15
    226   1.1  mrg 	bt/s LOCAL(pos_divisor)
    227   1.1  mrg 	cmp/pz r4
    228   1.1  mrg 	neg r5,r5
    229   1.1  mrg 	extu.w r5,r0
    230   1.1  mrg 	bt/s LOCAL(neg_result)
    231   1.1  mrg 	cmp/eq r5,r0
    232   1.1  mrg 	neg r4,r4
    233   1.1  mrg LOCAL(pos_result):
    234   1.1  mrg 	swap.w r4,r0
    235   1.1  mrg 	bra LOCAL(sdiv_check_divisor)
    236   1.1  mrg 	sts pr,r1
    237   1.1  mrg LOCAL(pos_divisor):
    238   1.1  mrg 	extu.w r5,r0
    239   1.1  mrg 	bt/s LOCAL(pos_result)
    240   1.1  mrg 	cmp/eq r5,r0
    241   1.1  mrg 	neg r4,r4
    242   1.1  mrg LOCAL(neg_result):
    243   1.1  mrg 	mova LOCAL(negate_result),r0
    244   1.1  mrg 	;
    245   1.1  mrg 	mov r0,r1
    246   1.1  mrg 	swap.w r4,r0
    247   1.1  mrg 	lds r2,macl
    248   1.1  mrg 	sts pr,r2
    249   1.1  mrg LOCAL(sdiv_check_divisor):
    250   1.1  mrg 	shlr16 r4
    251   1.1  mrg 	bf/s LOCAL(sdiv_large_divisor)
    252   1.1  mrg 	div0u
    253   1.1  mrg 	bra LOCAL(sdiv_small_divisor)
    254   1.1  mrg 	shll16 r5
    255   1.1  mrg 	.balign 4
    256   1.1  mrg LOCAL(negate_result):
    257   1.1  mrg 	neg r0,r0
    258   1.1  mrg 	jmp @r2
    259   1.1  mrg 	sts macl,r2
    260   1.1  mrg 	ENDFUNC(GLOBAL(sdivsi3_i4i))
    261   1.1  mrg #endif /* !__SH_FPU_DOUBLE__ */
    262   1.1  mrg #endif /* L_udivsi3_i4i */
    263   1.1  mrg 
    264   1.1  mrg #ifdef L_sdivsi3_i4i
    265   1.1  mrg #if defined (__SH_FPU_DOUBLE__) || defined (__SH4_SINGLE_ONLY__)
    266   1.1  mrg /* 48 bytes, 45 cycles on sh4-200  */
    267   1.1  mrg !! args in r4 and r5, result in r0, clobber r1
    268   1.1  mrg 
    269   1.1  mrg 	.global GLOBAL(sdivsi3_i4i)
    270   1.1  mrg 	FUNC(GLOBAL(sdivsi3_i4i))
    271   1.1  mrg GLOBAL(sdivsi3_i4i):
    272   1.1  mrg 	sts.l fpscr,@-r15
    273   1.1  mrg 	sts fpul,r1
    274   1.1  mrg 	mova L1,r0
    275   1.1  mrg 	lds.l @r0+,fpscr
    276   1.1  mrg 	lds r4,fpul
    277   1.1  mrg #ifdef FMOVD_WORKS
    278   1.1  mrg 	fmov.d dr0,@-r15
    279   1.1  mrg 	float fpul,dr0
    280   1.1  mrg 	lds r5,fpul
    281   1.1  mrg 	fmov.d dr2,@-r15
    282   1.1  mrg #else
    283   1.1  mrg 	fmov.s DR01,@-r15
    284   1.1  mrg 	fmov.s DR00,@-r15
    285   1.1  mrg 	float fpul,dr0
    286   1.1  mrg 	lds r5,fpul
    287   1.1  mrg 	fmov.s DR21,@-r15
    288   1.1  mrg 	fmov.s DR20,@-r15
    289   1.1  mrg #endif
    290   1.1  mrg 	float fpul,dr2
    291   1.1  mrg 	fdiv dr2,dr0
    292   1.1  mrg #ifdef FMOVD_WORKS
    293   1.1  mrg 	fmov.d @r15+,dr2
    294   1.1  mrg #else
    295   1.1  mrg 	fmov.s @r15+,DR20
    296   1.1  mrg 	fmov.s @r15+,DR21
    297   1.1  mrg #endif
    298   1.1  mrg 	ftrc dr0,fpul
    299   1.1  mrg #ifdef FMOVD_WORKS
    300   1.1  mrg 	fmov.d @r15+,dr0
    301   1.1  mrg #else
    302   1.1  mrg 	fmov.s @r15+,DR00
    303   1.1  mrg 	fmov.s @r15+,DR01
    304   1.1  mrg #endif
    305   1.1  mrg 	lds.l @r15+,fpscr
    306   1.1  mrg 	sts fpul,r0
    307   1.1  mrg 	rts
    308   1.1  mrg 	lds r1,fpul
    309   1.1  mrg 
    310   1.1  mrg 	.p2align 2
    311   1.1  mrg L1:
    312   1.1  mrg #ifndef FMOVD_WORKS
    313   1.1  mrg 	.long 0x80000
    314   1.1  mrg #else
    315   1.1  mrg 	.long 0x180000
    316   1.1  mrg #endif
    317   1.1  mrg 
    318   1.1  mrg 	ENDFUNC(GLOBAL(sdivsi3_i4i))
    319   1.1  mrg #endif /* __SH_FPU_DOUBLE__ */
    320   1.1  mrg #endif /* L_sdivsi3_i4i */
    321