diff options
author | James Bowman <james.bowman@ftdichip.com> | 2015-05-16 23:49:08 +0000 |
---|---|---|
committer | James Bowman <jamesbowman@gcc.gnu.org> | 2015-05-16 23:49:08 +0000 |
commit | fef939d6a96bde0f924152e6b9e22701c28f8880 (patch) | |
tree | 5e4897f8e04c41bd78ca2cb6244476efaf07df39 /libgcc/config | |
parent | 9261aa4364af939b3fd91f20bf20c8e329434600 (diff) | |
download | gcc-fef939d6a96bde0f924152e6b9e22701c28f8880.zip gcc-fef939d6a96bde0f924152e6b9e22701c28f8880.tar.gz gcc-fef939d6a96bde0f924152e6b9e22701c28f8880.tar.bz2 |
FT32 target added. Approved by Jeff Law [law@redhat.com]
From-SVN: r223261
Diffstat (limited to 'libgcc/config')
-rw-r--r-- | libgcc/config/ft32/crti-hw.S | 193 | ||||
-rw-r--r-- | libgcc/config/ft32/crti.S | 40 | ||||
-rw-r--r-- | libgcc/config/ft32/crtn.S | 34 | ||||
-rw-r--r-- | libgcc/config/ft32/epilog.S | 52 | ||||
-rw-r--r-- | libgcc/config/ft32/lib1funcs.S | 919 | ||||
-rw-r--r-- | libgcc/config/ft32/prolog.S | 199 | ||||
-rw-r--r-- | libgcc/config/ft32/sfp-machine.h | 61 | ||||
-rw-r--r-- | libgcc/config/ft32/t-ft32 | 4 |
8 files changed, 1502 insertions, 0 deletions
diff --git a/libgcc/config/ft32/crti-hw.S b/libgcc/config/ft32/crti-hw.S new file mode 100644 index 0000000..1322dd6 --- /dev/null +++ b/libgcc/config/ft32/crti-hw.S @@ -0,0 +1,193 @@ +.equ SYS_REGMSC0CFG_B3 , 0x1001b +.equ SYS_REGIRQCTL_B3 , 0x100e3 + +.global _start +_start: +# START Interrupt Vector Table [[ + jmp 0x3fffc # RESET Vector + jmp _watchdog_isr # WATCHDOG Vector # TODO: Change me to reset the chip proper + jmp interrupt_0 + jmp interrupt_1 + jmp interrupt_2 + jmp interrupt_3 + jmp interrupt_4 + jmp interrupt_5 + jmp interrupt_6 + jmp interrupt_7 + jmp interrupt_8 + jmp interrupt_9 + jmp interrupt_10 + jmp interrupt_11 + jmp interrupt_12 + jmp interrupt_13 + jmp interrupt_14 + jmp interrupt_15 + jmp interrupt_16 + jmp interrupt_17 + jmp interrupt_18 + jmp interrupt_19 + jmp interrupt_20 + jmp interrupt_21 + jmp interrupt_22 + jmp interrupt_23 + jmp interrupt_24 + jmp interrupt_25 + jmp interrupt_26 + jmp interrupt_27 + jmp interrupt_28 + jmp interrupt_29 + jmp interrupt_30 + jmp interrupt_31 + jmp 0x3fff8 +# ]] END Interrupt Vector Table + +codestart: + jmp init + + +.global _exithook +_exithook: # Debugger uses '_exithook' at 0x90 to catch program exit + return + +init: + # Disable all interrupts + ldk $r0,0x80 + sta.b 0x100e3,$r0 + + # Reset all peripherals + # lda.l $r0, 0x10018 + # bins.l $r0, $r0, 0x23F # Set bit 31 + # sta.l 0x10018, $r0 + + # Initialize DATA by copying from program memory + ldk.l $r0,__data_load_start + ldk.l $r1,__data_load_end + ldk.l $r2,0 # Will use __data after binutils patch + + jmp .dscopy +.dsloop: + # Copy PM[$r0] to RAM $r2 + lpmi.l $r3,$r0,0 + sti.l $r2,0,$r3 + add.l $r0,$r0,4 + add.l $r2,$r2,4 +.dscopy: + cmp.l $r0,$r1 + jmpc lt,.dsloop + + # Zero BSS + ldk.l $r0,_bss_start + ldk.l $r2,_end + sub.l $r2,$r2,$r0 + ldk.l $r1,0 + memset.l $r0,$r1,$r2 + + sub.l $sp,$sp,24 # Space for the caller argument frame + call main + +.equ EXITEXIT , 0x1fffc + +.global _exit +_exit: + sta.l EXITEXIT,$r0 # simulator end of test + jmp _exithook + +_watchdog_isr: + ldk.l $sp, 0x80FFFF # Reset the stack pointer so it doesn't grow to a huge size + jmp 0 + +# Macro to construct the interrupt stub code. +# it just saves r0, loads r0 with the int vector +# and branches to interrupt_common. + +.macro inth i=0 +interrupt_\i: + push $r0 # { + lda $r0,(vector_table + 4 * \i) + jmp interrupt_common +.endm + + inth 0 + inth 1 + inth 2 + inth 3 + inth 4 + inth 5 + inth 6 + inth 7 + inth 8 + inth 9 + inth 10 + inth 11 + inth 12 + inth 13 + inth 14 + inth 15 + inth 16 + inth 17 + inth 18 + inth 19 + inth 20 + inth 21 + inth 22 + inth 23 + inth 24 + inth 25 + inth 26 + inth 27 + inth 28 + inth 29 + inth 30 + inth 31 + inth 32 + + # On entry: r0, already saved, holds the handler function +interrupt_common: + push $r1 # { + push $r2 # { + push $r3 # { + push $r4 # { + push $r5 # { + push $r6 # { + push $r7 # { + push $r8 # { + push $r9 # { + push $r10 # { + push $r11 # { + push $r12 # { + push $cc # { + + calli $r0 + + pop $cc # } + pop $r12 # } + pop $r11 # } + pop $r10 # } + pop $r9 # } + pop $r8 # } + pop $r7 # } + pop $r6 # } + pop $r5 # } + pop $r4 # } + pop $r3 # } + pop $r2 # } + pop $r1 # } + pop $r0 # } matching push in interrupt_0-31 above + reti + + # Null function for unassigned interrupt to point at +.global nullvector +nullvector: + return + +.section .data +.global vector_table +vector_table: + .rept 33 + .long nullvector + .endr + + +.section .text +.global __gxx_personality_sj0 +__gxx_personality_sj0: diff --git a/libgcc/config/ft32/crti.S b/libgcc/config/ft32/crti.S new file mode 100644 index 0000000..8fd8e39 --- /dev/null +++ b/libgcc/config/ft32/crti.S @@ -0,0 +1,40 @@ +# crti.S for FT32 +# +# Copyright (C) 2009-2013 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/>. + +# This file just make a stack frame for the contents of the .fini and +# .init sections. Users may put any desired instructions in those +# sections. + + .file "crti.S" + + .section ".init" + .global _init + .type _init, @function + .p2align 2 +_init: + + .section ".fini" + .global _fini + .type _fini,@function + .p2align 2 +_fini: diff --git a/libgcc/config/ft32/crtn.S b/libgcc/config/ft32/crtn.S new file mode 100644 index 0000000..322a0c9 --- /dev/null +++ b/libgcc/config/ft32/crtn.S @@ -0,0 +1,34 @@ +# crtn.S for FT32 +# +# Copyright (C) 2009-2013 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/>. + +# This file just makes sure that the .fini and .init sections do in +# fact return. Users may put any desired instructions in those sections. +# This file is the last thing linked into any executable. + + .file "crtn.S" + + .section ".init" + return + + .section ".fini" + return diff --git a/libgcc/config/ft32/epilog.S b/libgcc/config/ft32/epilog.S new file mode 100644 index 0000000..e40b548 --- /dev/null +++ b/libgcc/config/ft32/epilog.S @@ -0,0 +1,52 @@ + .macro e r=0 + .global __epilog_$r\r +__epilog_$r\r: + pop $r\r + .endm + + e 28 + e 27 + e 26 + e 25 + e 24 + e 23 + e 22 + e 21 + e 20 + e 19 + e 18 + e 17 + e 16 + e 15 + e 14 + e 13 + return + + .global __epilog24 +__epilog24: + add $sp,$sp,24 + return + + .macro f r=0 + .global __epilog24_$r\r +__epilog24_$r\r: + add $sp,$sp,24 + jmp __epilog_$r\r + .endm + + f 13 + f 14 + f 15 + f 16 + f 17 + f 18 + f 19 + f 20 + f 21 + f 22 + f 23 + f 24 + f 25 + f 26 + f 27 + f 28 diff --git a/libgcc/config/ft32/lib1funcs.S b/libgcc/config/ft32/lib1funcs.S new file mode 100644 index 0000000..36e4088 --- /dev/null +++ b/libgcc/config/ft32/lib1funcs.S @@ -0,0 +1,919 @@ +# ieee754 sf routines for FT32 + +/* Copyright (C) 1995-2014 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/>. */ + +# See http://www.ens-lyon.fr/LIP/Pub/Rapports/PhD/PhD2006/PhD2006-02.pdf +# for implementation details of all except division which is detailed below +# + +// .global __cmpsf2_ + +nan: .long 0x7FFFFFFF # also abs mask +inf: .long 0x7F800000 +sign_mask: .long 0x80000000 +m_mask: .long 0x007FFFFF +exp_bias: .long 127 +edge_case: .long 0x00FFFFFF +smallest_norm: .long 0x00800000 # implicit bit +high_FF: .long 0xFF000000 +high_uint: .long 0xFFFFFFFF + +# Supply a few 'missing' instructions + +# not +.macro not rd,r1 + xor \rd,\r1,-1 +.endm + +# negate +.macro neg x + not \x, \x + add \x, \x, 1 +.endm + +# set $cc from the result of "ashl reg,dist" +.macro ashlcc reg,dist + .long 0x5de04008 | (\reg << 15) | (\dist << 4) +.endm + + +# converts an unsigned number x to a signed rep based on the bits in sign +# sign should be 0x00000000 or 0xffffffff. +.macro to_signed x, sign + add \x,\x,\sign # conditionally decrement x + xor \x,\x,\sign # conditionally complement x +.endm + + +.macro ld32 r,v + ldk \r,(\v>>10) + ldl \r,\r,(\v & 1023) +.endm + +# calculate trailing zero count in x, also uses scr. +# Using Seal's algorithm +.macro ntz x, scr + not \scr, \x + add \scr, \scr, 1 + and \x, \x, \scr + ashl \scr, \x, 4 + add \x, \scr, \x + ashl \scr, \x, 6 + add \x, \scr, \x + ashl \scr, \x, 16 + sub \x, \scr, \x + lshr \x, \x, 26 + ldk \scr, ntz_table + add \x, \x, \scr + lpmi.b \x, \x, 0 +.endm + +ntz_table: + .byte 32,0,1,12,2,6,0,13,3,0,7,0,0,0,0,14 + .byte 10,4,0,0,8,0,0,25,0,0,0,0,0,21,27,15 + .byte 31,11,5,0,0,0,0,0,9,0,0,24,0,0,20,26 + .byte 30,0,0,0,0,23,0,19,29,0,22,18,28,17,16,0 + +# calculate leading zero count +.macro nlz x, scr + flip \x, \x, 31 + ntz \x, \scr +.endm + + +# Round 26 bit mantissa to nearest +# | 23 bits frac | G | R | S | +.macro round m, s1, s2 + ldk \s1,0xc8 + and \s2,\m,7 + lshr \s1,\s1,\s2 + and \s1,\s1,1 + lshr \m,\m,2 + add \m,\m,\s1 +.endm + +# If NZ, set the LSB of reg +.macro sticky reg + jmpc z,1f + or \reg,\reg,1 # set the sticky bit to 1 +1: +.endm + +########################################################################## +########################################################################## +## addition & subtraction + +#if defined(L_subsf3) || defined(L_addsub_sf) +.global __subsf3 +__subsf3: + # this is subtraction, so we just change the sign of r1 + lpm $r2,sign_mask + xor $r1,$r1,$r2 + jmp __addsf3 +#endif + +#if defined(L_addsf3) || defined(L_addsub_sf) +.global __addsf3 +__addsf3: + # x in $r0, y in $r1, result z in $r0 --||| 100 instructions +/- |||-- + # unpack e, calc d + bextu $r2,$r0,(8<<5)|23 # ex in r2 + bextu $r3,$r1,(8<<5)|23 # ey in r3 + sub $r5,$r2,$r3 # d = ex - ey + + # Special values are 0x00 and 0xff in ex and ey. + # If (ex&ey) != 0 or (xy|ey)=255 then there may be + # a special value. + tst $r2,$r3 + jmpc nz,1f + jmp slow +1: or $r4,$r2,$r3 + cmp $r4,255 + jmpc nz,no_special_vals +slow: + # Check for early exit + cmp $r2,0 + jmpc z,test_if_not_255 + cmp $r3,0 + jmpc nz,no_early_exit +test_if_not_255: + cmp $r2,255 + jmpc z,no_early_exit + cmp $r3,255 + jmpc z,no_early_exit + or $r6,$r2,$r3 + cmp $r6,0 + jmpc nz,was_not_zero + and $r0,$r0,$r1 + lpm $r1,sign_mask + and $r0,$r0,$r1 + return +was_not_zero: + cmp $r2,0 + jmpc nz,ret_x + move $r0,$r1 + return +ret_x: + return +no_early_exit: + # setup to test for special values + sub $r6,$r2,1 + and $r6,$r6,0xFE + sub $r7,$r3,1 + and $r7,$r7,0xFE + # test for special values + cmp $r6,$r7 + jmpc gte,ex_spec_is_gte + move $r6,$r7 +ex_spec_is_gte: + cmp $r6,0xFE + jmpc nz,no_special_vals + cmp $r5,0 + jmpc ns,d_gte_0 + cmp $r3,0xFF + jmpc z,ret_y + cmp $r2,0 + jmpc z,ret_y +ret_y: + move $r0,$r1 + return +d_gte_0: + cmp $r5,0 + jmpc z,d_is_0 + cmp $r2,0xFF + jmpc z,ret_x + cmp $r3,0 + jmpc z,ret_x +d_is_0: + cmp $r2,0xFF + jmpc nz,no_special_vals + ashl $r6,$r0,9 # clear all except x frac + ashl $r7,$r1,9 # clear all except y frac + or $r6,$r6,$r7 + cmp $r6,0 + jmpc nz,ret_nan + lshr $r4,$r0,31 # sx in r4 + lshr $r5,$r1,31 # sy in r4 + cmp $r4,$r5 + jmpc nz,ret_nan + return +ret_nan: + lpm $r0,nan + return +no_special_vals: + ldk $r8,(1<<10)|(9<<5)|26 # setup implicit bit and mask for e + #---------------------- + ashr $r4,$r0,31 # sx in r4 + ashl $r0,$r0,3 # shift mx 3 for GRS bits + bins $r0,$r0,$r8 # clear sx, ex and add implicit bit mx + # change mx to signed mantissa + to_signed $r0,$r4 + #---------------------- + ashr $r4,$r1,31 # sy in r4 + ashl $r1,$r1,3 # shift my 3 for GRS bits + bins $r1,$r1,$r8 # clear sy, ey and add implicit bit my + # change my to signed mantissa + to_signed $r1,$r4 + #---------------------- + # test if we swap ms based on d sign + cmp $r5,0 + jmpc gte,noswap + # swap mx & my + xor $r0,$r0,$r1 + xor $r1,$r0,$r1 + xor $r0,$r0,$r1 + # d positive means that ex>=ey, so ez = ex + # d negative means that ey>ex, so ez = ey + move $r2,$r3 + # |d| + neg $r5 +noswap: + # now $r2 = ez = max(ex,ey) + cmp $r5,26 # max necessary alignment shift is 26 + jmpc lt,under_26 + ldk $r5,26 +under_26: + ldk $r7,-1 + ashl $r7,$r7,$r5 # create inverse of mask for test of S bit value in discarded my + not $r7,$r7 + tst $r1,$r7 # determine value of sticky bit + # shift my >> |d| + ashr $r1,$r1,$r5 + sticky $r1 + + # add ms + add $r0,$r0,$r1 + + # $r4 = sign(mx), mx = |mx| + ashr $r4,$r0,31 + xor $r0,$r0,$r4 + sub $r0,$r0,$r4 + + # realign mantissa using leading zero count + flip $r7,$r0,31 + ntz $r7,$r8 + ashl $r0,$r0,$r7 + btst $r0,(6<<5)|0 # test low bits for sticky again + lshr $r0,$r0,6 + sticky $r0 + + # update exponent + add $r2,$r2,5 + sub $r2,$r2,$r7 + + # Round to nearest + round $r0,$r7,$r6 + + # detect_exp_update + lshr $r6,$r0,24 + add $r2,$r2,$r6 + + # final tests + # mz == 0? if so, we just bail with a +0 + cmp $r0,0 + jmpc nz,msum_not_zero + ldk $r0,0 + return +msum_not_zero: + # Combined check that (1 <= ez <= 254) + sub $r3,$r2,1 + cmp $r3,254 + jmpc b,no_special_ret + # underflow? + cmp $r2,0 + jmpc gt,no_under + ldk $r0,0 + jmp pack_sz +no_under: + # overflow? + cmp $r2,255 + jmpc lt,no_special_ret + ldk $r0,0x7F8 + ashl $r0,$r0,20 + jmp pack_sz +no_special_ret: + # Pack ez + ldl $r2,$r2,(8<<5)|23 + bins $r0,$r0,$r2 # width = 8, pos = 23 pack ez + # Pack sz +pack_sz: + ldl $r4,$r4,(1<<5)|31 + bins $r0,$r0,$r4 # width = 1, pos = 31 set sz to sy + return +#endif + +########################################################################## +########################################################################## +## multiplication + +#ifdef L_mulsf3 +.global __mulsf3 +__mulsf3: + # x in $r0, y in $r1, result z in $r0 --||| 61 instructions +/- |||-- + + # unpack e + bextu $r2,$r0,(8<<5)|23 # ex in r2 + bextu $r3,$r1,(8<<5)|23 # ey in r3 + # calc result sign + xor $r4,$r0,$r1 + lpm $r5,sign_mask + and $r4,$r4,$r5 # sz in r4 + + # unpack m add implicit bit + ldk $r5,(1<<10)|(9<<5)|23 # setup implicit bit and mask for e + #---------------------- + bins $r0,$r0,$r5 # clear sx, ex and add implicit bit mx + + sub $r6,$r2,1 + cmp $r6,254 + jmpc b,1f + jmp slow_mul +1: sub $r6,$r3,1 + cmp $r6,254 + jmpc b,no_special_vals_mul + +slow_mul: + # Check for early exit + cmp $r2,0 + jmpc z,op_is_zero + cmp $r3,0 + jmpc nz,no_early_exit_mul +op_is_zero: + cmp $r2,255 + jmpc z,no_early_exit_mul + cmp $r3,255 + jmpc z,no_early_exit_mul + move $r0,$r4 + return +no_early_exit_mul: + # setup to test for special values + sub $r6,$r2,1 + and $r6,$r6,0xFE + sub $r7,$r3,1 + and $r7,$r7,0xFE + # test for special values + cmp $r6,$r7 + jmpc gte,ex_spec_is_gte_ey_mul + move $r6,$r7 +ex_spec_is_gte_ey_mul: + cmp $r6,0xFE + jmpc nz,no_special_vals_mul + cmp $r2,0xFF + jmpc nz,ex_not_FF_mul + ashl $r6,$r0,9 + cmp $r6,0 + jmpc nz,ret_nan + cmp $r3,0 + jmpc z,ret_nan + ashl $r6,$r1,1 + lpm $r7,high_FF + cmp $r6,$r7 + jmpc a,ret_nan + cmp $r6,0 + jmpc z,ret_nan + # infinity + lpm $r0,inf + or $r0,$r0,$r4 + return +ex_not_FF_mul: + cmp $r2,0 + jmpc nz,no_nan_mul + cmp $r3,0xFF + jmpc nz,no_nan_mul + jmp ret_nan +no_nan_mul: + lpm $r0,nan + and $r0,$r0,$r1 + or $r0,$r0,$r4 + return + +ret_nan: + lpm $r0,nan + return + +no_special_vals_mul: + bins $r1,$r1,$r5 # clear sy, ey and add implicit bit my + # calc ez + add $r3,$r2,$r3 + sub $r3,$r3,127 # ez in r3 + + # (r1,r2) = R0 * R1 + mul $r2,$r0,$r1 + muluh $r1,$r0,$r1 + + btst $r1,(1<<5)|15 # XXX use jmpx + jmpc z,mul_z0 + + # mz is 1X.XX...X + # 48-bit product is in (r1,r2). The low 22 bits of r2 + # are discarded. + lshr $r0,$r2,22 + ashl $r1,$r1,10 + or $r0,$r0,$r1 # r0 = (r1,r2) >> 22 + ashlcc 2,10 + sticky $r0 + add $r3,$r3,1 # bump exponent + + # Round to nearest + round $r0, $r1, $r2 + lshr $r6,$r0,24 + add $r3,$r3,$r6 + + sub $r6,$r3,1 + cmp $r6,254 + jmpc b,no_special_ret_mul + +special_ret_mul: + # When the final exponent <= 0, result is flushed to 0 except + # for the border case 0x00FFFFFF which is promoted to next higher + # FP no., that is, the smallest "normalized" number. + cmp $r3,0 + jmpc gt,exp_normal + # Pack ez + ldl $r3,$r3,(8<<5)|23 + bins $r0,$r0,$r3 # width = 8, pos = 23 pack ez + lpm $r2,edge_case + cmp $r0,$r2 + jmpc nz,no_edge_case + lpm $r0,smallest_norm + jmp pack_sz_mul +no_edge_case: + ldk $r0,0 + jmp pack_sz_mul +exp_normal: + # overflow? + cmp $r3,255 + jmpc lt,no_special_ret_mul + ldk $r0,0x7F8 + ashl $r0,$r0,20 + jmp pack_sz_mul +no_special_ret_mul: + # Pack ez + ldl $r3,$r3,(8<<5)|23 + bins $r0,$r0,$r3 # width = 8, pos = 23 pack ez + # Pack sz +pack_sz_mul: + or $r0,$r0,$r4 + return + +mul_z0: + # mz is 0X.XX...X + # 48-bit product is in (r1,r2). The low 21 bits of r2 + # are discarded. + lshr $r0,$r2,21 + ashl $r1,$r1,11 + or $r0,$r0,$r1 # r0 = (r1,r2) >> 22 + ashlcc 2,11 + sticky $r0 + # Round to nearest + round $r0, $r1, $r2 + lshr $r6,$r0,24 + add $r3,$r3,$r6 + + sub $r6,$r3,1 + cmp $r6,254 + jmpc b,no_special_ret_mul + jmp special_ret_mul +#endif + +########################################################################## +########################################################################## +## division + +## See http://perso.ens-lyon.fr/gilles.villard/BIBLIOGRAPHIE/PDF/arith19.pdf +## for implementation details + + +dc_1: .long 0xffffe7d7 +dc_2: .long 0xffffffe8 +dc_3: .long 0xffbad86f +dc_4: .long 0xfffbece7 +dc_5: .long 0xf3672b51 +dc_6: .long 0xfd9d3a3e +dc_7: .long 0x9a3c4390 +dc_8: .long 0xd4d2ce9b +dc_9: .long 0x1bba92b3 +dc_10: .long 0x525a1a8b +dc_11: .long 0x0452b1bf +dc_12: .long 0xFFFFFFC0 +spec_val_test: .long 0x7F7FFFFF + + + +#ifdef L_divsf3 +.global __divsf3 +__divsf3: + push $r13 + # x in $r0, y in $r1, result z in $r0 --||| 73 instructions +/- |||- + bextu $r10,$r0,(8<<5)|23 # ex in r2 + bextu $r11,$r1,(8<<5)|23 # ey in r3 + lpm $r6, m_mask + and $r2, $r0, $r6 # mx + and $r3, $r1, $r6 # my + cmp $r2,$r3 + bextu $r2,$r30,(1<<5)|4 # c = Tx >= T; + ashl $r3,$r3,9 # T = X << 9; + lpm $r13, sign_mask + ashl $r4,$r0,8 # X8 = X << 8; + or $r4,$r4,$r13 # Mx = X8 | 0x80000000; + lshr $r5,$r4,$r2 # S = Mx >> c; + # calc D + sub $r2, $r11, $r2 + add $r12, $r10, 125 + sub $r2, $r12, $r2 # int D = (Ex + 125) - (Ey - c); + # calc result sign + xor $r12,$r0,$r1 + and $r12,$r12,$r13 # Sr = ( X ˆ Y ) & 0x80000000; + # check early exit + cmp $r10, 0 + jmpc nz, no_early_ret_dev + cmp $r11, 0 + jmpc z, no_early_ret_dev + cmp $r11, 255 + jmpc z, no_early_ret_dev + move $r0, $r12 + pop $r13 + return +no_early_ret_dev: + # setup to test for special values + sub $r8,$r10,1 + and $r8,$r8,0xFE + sub $r9,$r11,1 + and $r9,$r9,0xFE + # test for special values + cmp $r8, $r9 + jmpc gte, absXm1_gte_absYm1 + move $r8, $r9 +absXm1_gte_absYm1: + cmp $r8, 0xFE + jmpc nz, no_spec_ret_div + cmp $r10, 0xFF + jmpc nz, ex_not_FF_div + lpm $r6, m_mask + and $r2, $r0, $r6 # mx + cmp $r2, 0 + jmpc nz, ret_nan_div + cmp $r11, 0xFF + jmpc z, ret_nan_div + jmp ret_inf_div +ex_not_FF_div: + cmp $r11, 0xFF + jmpc nz, ey_not_FF_div + ashl $r13, $r1, 9 + cmp $r13, 0 + jmpc nz, ret_nan_div + move $r0, $r12 + pop $r13 + return +ey_not_FF_div: + or $r10, $r10, $r11 + cmp $r10, 0 + jmpc z, ret_nan_div +ret_inf_div: + lpm $r6, inf + move $r0, $r6 + or $r0, $r0, $r12 + pop $r13 + return +ret_nan_div: + lpm $r0, nan + pop $r13 + return + +no_spec_ret_div: +# check for overflow + ldk $r6, 0xFE + cmp $r2, $r6 + jmpc lt, no_overflow_div + lpm $r6, inf + or $r0, $r12, $r6 + pop $r13 + return +no_overflow_div: +# check for underflow + cmp $r2, 0 + jmpc ns, no_underflow_div + xnor $r6, $r6, $r6 # -1 + cmp $r2, $r6 + jmpc nz, ret_sr_div + ldk $r7, 0xFF + xor $r6, $r6, $r7 # 0xFF ^ -1 = 0xFFFFFF00 + cmp $r4, $r6 + jmpc nz, ret_sr_div + lpm $r6, sign_mask + cmp $r4, $r6 + jmpc nz, ret_sr_div + lshr $r0, $r6, 8 + or $r0, $r0, $r12 + pop $r13 + return +ret_sr_div: + move $r0, $r12 + pop $r13 + return +no_underflow_div: + lpm $r6, dc_1 + muluh $r7, $r3, $r6 # i0 = mul( T , 0xffffe7d7 ); + lpm $r6, dc_2 + sub $r7, $r6, $r7 # i1 = 0xffffffe8 - i0; + muluh $r7, $r5, $r7 # i2 = mul( S , i1 ); + add $r7, $r7, 0x20 # i3 = 0x00000020 + i2; + muluh $r8, $r3, $r3 # i4 = mul( T , T ); + muluh $r9, $r5, $r8 # i5 = mul( S , i4 ); + lpm $r6, dc_3 + muluh $r10, $r3, $r6 # i6 = mul( T , 0xffbad86f ); + lpm $r6, dc_4 + sub $r10, $r6, $r10 # i7 = 0xfffbece7 - i6; + muluh $r10, $r9, $r10 # i8 = mul( i5 , i7 ); + add $r7, $r7, $r10 # i9 = i3 + i8; + muluh $r9, $r8, $r9 # i10 = mul( i4 , i5 ); + lpm $r6, dc_5 + muluh $r10, $r3, $r6 # i11 = mul( T , 0xf3672b51 ); + lpm $r6, dc_6 + sub $r10, $r6, $r10 # i12 = 0xfd9d3a3e - i11; + lpm $r6, dc_7 + muluh $r11, $r3, $r6 # i13 = mul( T , 0x9a3c4390 ); + lpm $r6, dc_8 + sub $r11, $r6, $r11 # i14 = 0xd4d2ce9b - i13 + muluh $r11, $r8, $r11 # i15 = mul( i4 , i14 ); + add $r10, $r10, $r11 # i16 = i12 + i15; + muluh $r10, $r9, $r10 # i17 = mul( i10 , i16 ) + add $r7, $r7, $r10 # i18 = i9 + i17; + muluh $r10, $r8, $r8 # i19 = mul( i4 , i4 ); + lpm $r6, dc_9 + muluh $r11, $r3, $r6 # i20 = mul( T , 0x1bba92b3 ); + lpm $r6, dc_10 + sub $r11, $r6, $r11 # i21 = 0x525a1a8b - i20; + lpm $r6, dc_11 + muluh $r8, $r8, $r6 # i22 = mul( i4 , 0x0452b1bf ); + add $r8, $r11, $r8 # i23 = i21 + i22; + muluh $r8, $r10, $r8 # i24 = mul( i19 , i23 ); + muluh $r8, $r9, $r8 # i25 = mul( i10 , i24 ); + add $r3, $r7, $r8 # V = i18 + i25; +# W = V & 0xFFFFFFC0; + lpm $r6, dc_12 + and $r3, $r3, $r6 # W +# round and pack final values + ashl $r0, $r2, 23 # pack D + or $r0, $r0, $r12 # pack Sr + ashl $r12, $r1, 8 + or $r12, $r12, $r13 # My + muluh $r10, $r3, $r12 + lshr $r11, $r5, 1 + cmp $r10, $r11 + jmpc gte, div_ret_1 + add $r3, $r3, 0x40 +div_ret_1: + lshr $r3, $r3, 7 + add $r0, $r0, $r3 + pop $r13 + return +#endif + +########################################################################## +########################################################################## +## Negate + +#ifdef L_negsf +.global __negsf +__negsf: + lpm $r1, sign_mask + xor $r0, $r0, $r1 + return +#endif + +########################################################################## +########################################################################## +## float to int & unsigned int + +#ifdef L_fixsfsi +.global __fixsfsi +__fixsfsi: # 20 instructions + bextu $r1,$r0,(8<<5)|23 # e in r1 + lshr $r2,$r0,31 # s in r2 + lpm $r3, m_mask + and $r0,$r0,$r3 # m in r0 + # test nan + cmp $r1,0xFF + jmpc nz, int_not_nan + cmp $r0,0 + jmpc z, int_not_nan + ldk $r0,0 + return +int_not_nan: + # test edges + cmp $r1, 127 + jmpc gte, int_not_zero # lower limit + ldk $r0,0 + return +int_not_zero: + cmp $r1, 158 + jmpc lt, int_not_max # upper limit + lpm $r0, nan + cmp $r2, 0 + jmpc z, int_positive + xnor $r0, $r0, 0 + return +int_not_max: + lpm $r3, smallest_norm + or $r0, $r0, $r3 # set implicit bit + sub $r1, $r1, 150 + cmp $r1, 0 + jmpc s, shift_right + ashl $r0, $r0, $r1 + jmp set_int_sign +shift_right: + xnor $r1, $r1, 0 + add $r1, $r1, 1 + lshr $r0, $r0, $r1 +set_int_sign: + cmp $r2, 0 + jmpc z, int_positive + xnor $r0, $r0, 0 + add $r0, $r0, 1 +int_positive: + return +#endif + +#ifdef L_fixunssfsi +.global __fixunssfsi +__fixunssfsi: # 19 instructions + lshr $r2, $r0, 31 # s in r2 + cmp $r2, 0 + jmpc z, uint_not_neg + ldk $r0, 0 + return +uint_not_neg: + bextu $r1, $r0, (8<<5)|23 # e in r1 + sub $r1, $r1, 127 + lpm $r3, m_mask + and $r0, $r0, $r3 # m in r0 + # test nan + cmp $r1, 0xFF + jmpc nz, uint_not_nan + cmp $r0, 0 + jmpc z, uint_not_nan + ldk $r0, 0 + return +uint_not_nan: + # test edges + cmp $r1, 0 + jmpc ns, uint_not_zero # lower limit + ldk $r0, 0 + return +uint_not_zero: + lpm $r3, smallest_norm + or $r0, $r0, $r3 # set implicit bit + cmp $r1, 23 + jmpc lt, shift_uint_right + sub $r1, $r1, 23 + ashl $r0, $r0, $r1 + return +shift_uint_right: + ldk $r3, 23 + sub $r1, $r3, $r1 + lshr $r0, $r0, $r1 + return +#endif + +########################################################################## +########################################################################## +## int & unsigned int to float + + +.macro i2f x, s1, s2, s3, lbl + move \s1, \x + nlz \s1, \s2 + cmp \s1, 8 + jmpc s, float_round\lbl + sub \s2, \s1, 8 + ashl \x, \x, \s2 + jmp float_no_round\lbl +float_round\lbl: + cmp \s1, 6 + jmpc s, float_shift_right\lbl + sub \s2, \s1, 6 + ashl \x, \x, \s2 + jmp float_round_and_pack\lbl +float_shift_right\lbl: + ldk \s2, 6 + sub \s2, \s2, \s1 + xnor \s3, \s3 ,\s3 # 0xFFFFFFFF + ashl \s3, \s3 ,\s2 # create inverse of mask for test of S bit value in discarded my + xnor \s3, \s3 ,0 # NOT + tst \x, \s3 # determine value of sticky bit + lshr \x, \x, \s2 + jmpc z,float_round_and_pack\lbl + or \x, \x, 1 # set the sticky bit to 1 +float_round_and_pack\lbl: + bextu \s2, \x, (1<<5)|2 # extract low bit of m + or \x, \x, \s2 # or p into r + add \x, \x, 1 + lshr \x, \x, 2 + btst \x, (1<<5)|24 # test for carry from round + jmpc z, float_no_round\lbl + sub \s1, \s1, 1 # inc e for carry (actually dec nlz) + lshr \x, \x, 1 +float_no_round\lbl: + ldk \s2, 158 + sub \s1, \s2, \s1 + # Pack e + ldl \s1, \s1, (8<<5)|23 + bins \x, \x, \s1 +.endm + + +#ifdef L_floatsisf +.global __floatsisf +__floatsisf: # 32 instructions + cmp $r0, 0 + jmpc nz, float_not_zero + return +float_not_zero: + ashr $r1, $r0, 31 # s in r1 + xor $r0, $r0, $r1 # cond neg + sub $r0, $r0, $r1 + i2f $r0, $r2, $r3, $r4, 1 + ldl $r1, $r1, (1<<5)|31 + bins $r0, $r0, $r1 + return +#endif + +#ifdef L_floatunsisf +.global __floatunsisf +__floatunsisf: # 26 instructions + cmp $r0, 0 + jmpc nz, float_not_zero2 + return +float_not_zero2: + i2f $r0, $r1, $r2, $r3, 2 + return +#endif + +########################################################################## +########################################################################## +## float compare + + +__cmpsf2_: + # calc abs vals + lpm $r3, nan # also abs mask + and $r2, $r0, $r3 + and $r3, $r1, $r3 + # test if either abs is nan + lpm $r4, inf + cmp $r2, $r4 + jmpc gt, cmp_is_gt + cmp $r3, $r4 + jmpc gt, cmp_is_gt + # test if both are 0 + or $r2, $r2, $r3 + cmp $r2, 0 + jmpc z, cmp_is_eq + # test if eq + cmp $r0, $r1 + jmpc z, cmp_is_eq + # -- if either is pos + and $r2, $r0, $r1 + cmp $r2, 0 + jmpc s, cmp_both_neg + cmp $r0, $r1 + jmpc gt, cmp_is_gt + # r0 < r1 + lpm $r0, high_uint + return +cmp_both_neg: + cmp $r0, $r1 + jmpc lt, cmp_is_gt + # r0 < r1 + lpm $r0, high_uint + return +cmp_is_gt: + ldk $r0, 1 + return +cmp_is_eq: + ldk $r0, 0 + return + + + + diff --git a/libgcc/config/ft32/prolog.S b/libgcc/config/ft32/prolog.S new file mode 100644 index 0000000..ca15be9 --- /dev/null +++ b/libgcc/config/ft32/prolog.S @@ -0,0 +1,199 @@ + .global __prolog_$r13 +__prolog_$r13: + exi $r13,$sp,0 + jmpi $r13 + + .global __prolog_$r14 +__prolog_$r14: + exi $r13,$sp,0 + push $r14 + jmpi $r13 + + .global __prolog_$r15 +__prolog_$r15: + exi $r13,$sp,0 + push $r14 + push $r15 + jmpi $r13 + + .global __prolog_$r16 +__prolog_$r16: + exi $r13,$sp,0 + push $r14 + push $r15 + push $r16 + jmpi $r13 + + .global __prolog_$r17 +__prolog_$r17: + exi $r13,$sp,0 + push $r14 + push $r15 + push $r16 + push $r17 + jmpi $r13 + + .global __prolog_$r18 +__prolog_$r18: + exi $r13,$sp,0 + push $r14 + push $r15 + push $r16 + push $r17 + push $r18 + jmpi $r13 + + .global __prolog_$r19 +__prolog_$r19: + exi $r13,$sp,0 + push $r14 + push $r15 + push $r16 + push $r17 + push $r18 + push $r19 + jmpi $r13 + + .global __prolog_$r20 +__prolog_$r20: + exi $r13,$sp,0 + push $r14 + push $r15 + push $r16 + push $r17 + push $r18 + push $r19 + push $r20 + jmpi $r13 + + .global __prolog_$r21 +__prolog_$r21: + exi $r13,$sp,0 + push $r14 + push $r15 + push $r16 + push $r17 + push $r18 + push $r19 + push $r20 + push $r21 + jmpi $r13 + + .global __prolog_$r22 +__prolog_$r22: + exi $r13,$sp,0 + push $r14 + push $r15 + push $r16 + push $r17 + push $r18 + push $r19 + push $r20 + push $r21 + push $r22 + jmpi $r13 + + .global __prolog_$r23 +__prolog_$r23: + exi $r13,$sp,0 + push $r14 + push $r15 + push $r16 + push $r17 + push $r18 + push $r19 + push $r20 + push $r21 + push $r22 + push $r23 + jmpi $r13 + + .global __prolog_$r24 +__prolog_$r24: + exi $r13,$sp,0 + push $r14 + push $r15 + push $r16 + push $r17 + push $r18 + push $r19 + push $r20 + push $r21 + push $r22 + push $r23 + push $r24 + jmpi $r13 + + .global __prolog_$r25 +__prolog_$r25: + exi $r13,$sp,0 + push $r14 + push $r15 + push $r16 + push $r17 + push $r18 + push $r19 + push $r20 + push $r21 + push $r22 + push $r23 + push $r24 + push $r25 + jmpi $r13 + + .global __prolog_$r26 +__prolog_$r26: + exi $r13,$sp,0 + push $r14 + push $r15 + push $r16 + push $r17 + push $r18 + push $r19 + push $r20 + push $r21 + push $r22 + push $r23 + push $r24 + push $r25 + push $r26 + jmpi $r13 + + .global __prolog_$r27 +__prolog_$r27: + exi $r13,$sp,0 + push $r14 + push $r15 + push $r16 + push $r17 + push $r18 + push $r19 + push $r20 + push $r21 + push $r22 + push $r23 + push $r24 + push $r25 + push $r26 + push $r27 + jmpi $r13 + + .global __prolog_$r28 +__prolog_$r28: + exi $r13,$sp,0 + push $r14 + push $r15 + push $r16 + push $r17 + push $r18 + push $r19 + push $r20 + push $r21 + push $r22 + push $r23 + push $r24 + push $r25 + push $r26 + push $r27 + push $r28 + jmpi $r13 diff --git a/libgcc/config/ft32/sfp-machine.h b/libgcc/config/ft32/sfp-machine.h new file mode 100644 index 0000000..080e323 --- /dev/null +++ b/libgcc/config/ft32/sfp-machine.h @@ -0,0 +1,61 @@ +#define _FP_W_TYPE_SIZE 32 +#define _FP_W_TYPE unsigned long +#define _FP_WS_TYPE signed long +#define _FP_I_TYPE long + +/* The type of the result of a floating point comparison. This must + match `__libgcc_cmp_return__' in GCC for the target. */ +typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__))); +#define CMPtype __gcc_CMPtype + +#define _FP_MUL_MEAT_S(R,X,Y) \ + _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_D(R,X,Y) \ + _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_Q(R,X,Y) \ + _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) + +#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_loop(S,R,X,Y) +#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y) +#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y) + +#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1) +#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1 +#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1 +#define _FP_NANSIGN_S 0 +#define _FP_NANSIGN_D 0 +#define _FP_NANSIGN_Q 0 + +#define _FP_KEEPNANFRACP 1 +#define _FP_QNANNEGATEDP 0 + +/* Someone please check this. */ +#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ + do { \ + if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs) \ + && !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)) \ + { \ + R##_s = Y##_s; \ + _FP_FRAC_COPY_##wc(R,Y); \ + } \ + else \ + { \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc(R,X); \ + } \ + R##_c = FP_CLS_NAN; \ + } while (0) + +/* Not checked. */ +#define _FP_TININESS_AFTER_ROUNDING 0 + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 + +# define __BYTE_ORDER __LITTLE_ENDIAN + +/* Define ALIASNAME as a strong alias for NAME. */ +# define strong_alias(name, aliasname) _strong_alias(name, aliasname) +# define _strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); + diff --git a/libgcc/config/ft32/t-ft32 b/libgcc/config/ft32/t-ft32 new file mode 100644 index 0000000..8360bbf --- /dev/null +++ b/libgcc/config/ft32/t-ft32 @@ -0,0 +1,4 @@ +LIB2ADD = $(srcdir)/config/ft32/epilog.S $(srcdir)/config/ft32/prolog.S + +crti-hw.o: $(srcdir)/config/ft32/crti-hw.S + $(crt_compile) -c -x assembler-with-cpp $< |