summaryrefslogtreecommitdiff
path: root/libgcc/config/rl78
diff options
context:
space:
mode:
authorDJ Delorie <dj@redhat.com>2013-09-14 02:13:18 -0400
committerDJ Delorie <dj@gcc.gnu.org>2013-09-14 02:13:18 -0400
commitceb2fc49ce5049ecafd811ca8ba406eadbdba5f8 (patch)
tree6f028c72a0421ebf758b7e3a0b11fc485361a541 /libgcc/config/rl78
parent03112d9463c2d0888ac4b0689573e4ae3d5e5b75 (diff)
downloadgcc-ceb2fc49ce5049ecafd811ca8ba406eadbdba5f8.tar.gz
mulsi3.S: Remove a few unneeded moves and branches.
* config/rl78/mulsi3.S: Remove a few unneeded moves and branches. * config/rl78/vregs.h: New. * config/rl78/signbit.S: New file. Implements signbit function. * config/rl78/divmodsi.S: New. * config/rl78/divmodhi.S: New. * config/rl78/divmodqi.S: New. * config/rl78/t-rl78: Build them here... * config/rl78/lib2div.c: ...but not here. Co-Authored-By: Nick Clifton <nickc@redhat.com> From-SVN: r202588
Diffstat (limited to 'libgcc/config/rl78')
-rw-r--r--libgcc/config/rl78/divmodhi.S337
-rw-r--r--libgcc/config/rl78/divmodqi.S310
-rw-r--r--libgcc/config/rl78/divmodsi.S521
-rw-r--r--libgcc/config/rl78/lib2div.c4
-rw-r--r--libgcc/config/rl78/mulsi3.S42
-rw-r--r--libgcc/config/rl78/signbit.S67
-rw-r--r--libgcc/config/rl78/t-rl784
-rw-r--r--libgcc/config/rl78/vregs.h32
8 files changed, 1290 insertions, 27 deletions
diff --git a/libgcc/config/rl78/divmodhi.S b/libgcc/config/rl78/divmodhi.S
new file mode 100644
index 00000000000..4e0a1237b28
--- /dev/null
+++ b/libgcc/config/rl78/divmodhi.S
@@ -0,0 +1,337 @@
+/* HImode div/mod functions for the GCC support library for the Renesas RL78 processors.
+ Copyright (C) 2012,2013 Free Software Foundation, Inc.
+ Contributed by Red Hat.
+
+ This file is part of GCC.
+
+ GCC 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.
+
+ GCC 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/>. */
+
+#ifndef __RL78_G10__
+
+#include "vregs.h"
+
+ .macro make_generic which,need_result
+
+ .if \need_result
+ quot = r8
+ num = r10
+ den = r12
+ bit = r14
+ .else
+ num = r8
+ quot = r10
+ den = r12
+ bit = r14
+ .endif
+
+ quotB0 = quot
+ quotB1 = quot+1
+
+ numB0 = num
+ numB1 = num+1
+
+ denB0 = den
+ denB1 = den+1
+
+ bitB0 = bit
+ bitB1 = bit+1
+
+#if 1
+#define bit bc
+#define bitB0 c
+#define bitB1 b
+#endif
+
+num_lt_den\which:
+ .if \need_result
+ movw r8, #0
+ .else
+ movw ax, [sp+8]
+ movw r8, ax
+ .endif
+ ret
+
+ ;; These routines leave DE alone - the signed functions use DE
+ ;; to store sign information that must remain intact
+
+ .if \need_result
+
+generic_div:
+
+ .else
+
+generic_mod:
+
+ .endif
+
+ ;; (quot,rem) = 8[sp] /% 10[sp]
+
+ movw hl, sp
+ movw ax, [hl+10] ; denH
+ cmpw ax, [hl+8] ; numH
+ bh $num_lt_den\which
+
+ ;; (quot,rem) = 16[sp] /% 20[sp]
+
+ ;; copy numerator
+ movw ax, [hl+8]
+ movw num, ax
+
+ ;; copy denomonator
+ movw ax, [hl+10]
+ movw den, ax
+
+ movw ax, den
+ cmpw ax, #0
+ bnz $den_not_zero\which
+ movw num, #0
+ ret
+
+den_not_zero\which:
+ .if \need_result
+ ;; zero out quot
+ movw quot, #0
+ .endif
+
+ ;; initialize bit to 1
+ movw bit, #1
+
+; while (den < num && !(den & (1L << BITS_MINUS_1)))
+
+shift_den_bit\which:
+ movw ax, den
+ mov1 cy,a.7
+ bc $enter_main_loop\which
+ cmpw ax, num
+ bh $enter_main_loop\which
+
+ ;; den <<= 1
+; movw ax, den ; already has it from the cmpw above
+ shlw ax, 1
+ movw den, ax
+
+ ;; bit <<= 1
+ .if \need_result
+#ifdef bit
+ shlw bit, 1
+#else
+ movw ax, bit
+ shlw ax, 1
+ movw bit, ax
+#endif
+ .else
+ ;; if we don't need to compute the quotent, we don't need an
+ ;; actual bit *mask*, we just need to keep track of which bit
+ inc bitB0
+ .endif
+
+ br $shift_den_bit\which
+
+main_loop\which:
+
+ ;; if (num >= den) (cmp den > num)
+ movw ax, den
+ cmpw ax, num
+ bh $next_loop\which
+
+ ;; num -= den
+ movw ax, num
+ subw ax, den
+ movw num, ax
+
+ .if \need_result
+ ;; res |= bit
+ mov a, quotB0
+ or a, bitB0
+ mov quotB0, a
+ mov a, quotB1
+ or a, bitB1
+ mov quotB1, a
+ .endif
+
+next_loop\which:
+
+ ;; den >>= 1
+ movw ax, den
+ shrw ax, 1
+ movw den, ax
+
+ .if \need_result
+ ;; bit >>= 1
+ movw ax, bit
+ shrw ax, 1
+ movw bit, ax
+ .else
+ dec bitB0
+ .endif
+
+enter_main_loop\which:
+ .if \need_result
+ movw ax, bit
+ cmpw ax, #0
+ .else
+ cmp0 bitB0
+ .endif
+ bnz $main_loop\which
+
+main_loop_done\which:
+ ret
+ .endm
+
+ make_generic _d 1
+ make_generic _m 0
+
+;----------------------------------------------------------------------
+
+ .global ___udivhi3
+ .type ___udivhi3,@function
+___udivhi3:
+ ;; r8 = 4[sp] / 6[sp]
+ call $!generic_div
+ ret
+ .size ___udivhi3, . - ___udivhi3
+
+
+ .global ___umodhi3
+ .type ___umodhi3,@function
+___umodhi3:
+ ;; r8 = 4[sp] % 6[sp]
+ call $!generic_mod
+ ret
+ .size ___umodhi3, . - ___umodhi3
+
+;----------------------------------------------------------------------
+
+ .macro neg_ax
+ movw hl, ax
+ movw ax, #0
+ subw ax, [hl]
+ movw [hl], ax
+ .endm
+
+ .global ___divhi3
+ .type ___divhi3,@function
+___divhi3:
+ ;; r8 = 4[sp] / 6[sp]
+ movw de, #0
+ mov a, [sp+5]
+ mov1 cy, a.7
+ bc $div_signed_num
+ mov a, [sp+7]
+ mov1 cy, a.7
+ bc $div_signed_den
+ call $!generic_div
+ ret
+
+div_signed_num:
+ ;; neg [sp+4]
+ movw ax, sp
+ addw ax, #4
+ neg_ax
+ mov d, #1
+ mov a, [sp+7]
+ mov1 cy, a.7
+ bnc $div_unsigned_den
+div_signed_den:
+ ;; neg [sp+6]
+ movw ax, sp
+ addw ax, #6
+ neg_ax
+ mov e, #1
+div_unsigned_den:
+ call $!generic_div
+
+ mov a, d
+ cmp0 a
+ bz $div_skip_restore_num
+ ;; We have to restore the numerator [sp+4]
+ movw ax, sp
+ addw ax, #4
+ neg_ax
+ mov a, d
+div_skip_restore_num:
+ xor a, e
+ bz $div_no_neg
+ movw ax, #r8
+ neg_ax
+div_no_neg:
+ mov a, e
+ cmp0 a
+ bz $div_skip_restore_den
+ movw ax, sp
+ addw ax, #6
+ neg_ax
+div_skip_restore_den:
+ ret
+ .size ___divhi3, . - ___divhi3
+
+
+ .global ___modhi3
+ .type ___modhi3,@function
+___modhi3:
+ ;; r8 = 4[sp] % 6[sp]
+ movw de, #0
+ mov a, [sp+5]
+ mov1 cy, a.7
+ bc $mod_signed_num
+ mov a, [sp+7]
+ mov1 cy, a.7
+ bc $mod_signed_den
+ call $!generic_mod
+ ret
+
+mod_signed_num:
+ ;; neg [sp+4]
+ movw ax, sp
+ addw ax, #4
+ neg_ax
+ mov d, #1
+ mov a, [sp+7]
+ mov1 cy, a.7
+ bnc $mod_unsigned_den
+mod_signed_den:
+ ;; neg [sp+6]
+ movw ax, sp
+ addw ax, #6
+ neg_ax
+mod_unsigned_den:
+ call $!generic_mod
+
+ mov a, d
+ cmp0 a
+ bz $mod_no_neg
+ movw ax, #r8
+ neg_ax
+ ;; Also restore numerator
+ movw ax, sp
+ addw ax, #4
+ neg_ax
+mod_no_neg:
+ mov a, e
+ cmp0 a
+ bz $mod_skip_restore_den
+ movw ax, sp
+ addw ax, #6
+ neg_ax
+mod_skip_restore_den:
+ ret
+ .size ___modhi3, . - ___modhi3
+
+#endif
diff --git a/libgcc/config/rl78/divmodqi.S b/libgcc/config/rl78/divmodqi.S
new file mode 100644
index 00000000000..62d6f776143
--- /dev/null
+++ b/libgcc/config/rl78/divmodqi.S
@@ -0,0 +1,310 @@
+/* QImode div/mod functions for the GCC support library for the Renesas RL78 processors.
+ Copyright (C) 2012,2013 Free Software Foundation, Inc.
+ Contributed by Red Hat.
+
+ This file is part of GCC.
+
+ GCC 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.
+
+ GCC 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/>. */
+
+#ifndef __RL78_G10__
+
+#include "vregs.h"
+
+ .macro make_generic which,need_result
+
+ .if \need_result
+ quot = r8
+ num = r10
+ den = r12
+ bit = r14
+ .else
+ num = r8
+ quot = r10
+ den = r12
+ bit = r14
+ .endif
+
+#if 1
+#define bit b
+#define den c
+#define bitden bc
+#endif
+
+num_lt_den\which:
+ .if \need_result
+ mov r8, #0
+ .else
+ mov a, [hl+4]
+ mov r8, a
+ .endif
+ ret
+
+num_eq_den\which:
+ .if \need_result
+ mov r8, #1
+ .else
+ mov r8, #0
+ .endif
+ ret
+
+den_is_zero\which:
+ mov r8, #0xff
+ ret
+
+ ;; These routines leave DE alone - the signed functions use DE
+ ;; to store sign information that must remain intact
+
+ .if \need_result
+
+generic_div:
+
+ .else
+
+generic_mod:
+
+ .endif
+
+ ;; (quot,rem) = 4[hl] /% 6[hl]
+
+ mov a, [hl+4] ; num
+ cmp a, [hl+6] ; den
+ bz $num_eq_den\which
+ bnh $num_lt_den\which
+
+ ;; copy numerator
+; mov a, [hl+4] ; already there from above
+ mov num, a
+
+ ;; copy denomonator
+ mov a, [hl+6]
+ mov den, a
+
+ cmp0 den
+ bz $den_is_zero\which
+
+den_not_zero\which:
+ .if \need_result
+ ;; zero out quot
+ mov quot, #0
+ .endif
+
+ ;; initialize bit to 1
+ mov bit, #1
+
+; while (den < num && !(den & (1L << BITS_MINUS_1)))
+
+shift_den_bit\which:
+ .macro sdb_one\which
+ mov a, den
+ mov1 cy,a.7
+ bc $enter_main_loop\which
+ cmp a, num
+ bh $enter_main_loop\which
+
+ ;; den <<= 1
+; mov a, den ; already has it from the cmpw above
+ shl a, 1
+ mov den, a
+
+ ;; bit <<= 1
+ shl bit, 1
+ .endm
+
+ sdb_one\which
+ sdb_one\which
+
+ br $shift_den_bit\which
+
+main_loop\which:
+
+ ;; if (num >= den) (cmp den > num)
+ mov a, den
+ cmp a, num
+ bh $next_loop\which
+
+ ;; num -= den
+ mov a, num
+ sub a, den
+ mov num, a
+
+ .if \need_result
+ ;; res |= bit
+ mov a, quot
+ or a, bit
+ mov quot, a
+ .endif
+
+next_loop\which:
+
+ ;; den, bit >>= 1
+ movw ax, bitden
+ shrw ax, 1
+ movw bitden, ax
+
+enter_main_loop\which:
+ cmp0 bit
+ bnz $main_loop\which
+
+main_loop_done\which:
+ ret
+ .endm
+
+ make_generic _d 1
+ make_generic _m 0
+
+;----------------------------------------------------------------------
+
+ .global ___udivqi3
+ .type ___udivqi3,@function
+___udivqi3:
+ ;; r8 = 4[sp] / 6[sp]
+ movw hl, sp
+ br $!generic_div
+ .size ___udivqi3, . - ___udivqi3
+
+
+ .global ___umodqi3
+ .type ___umodqi3,@function
+___umodqi3:
+ ;; r8 = 4[sp] % 6[sp]
+ movw hl, sp
+ br $!generic_mod
+ .size ___umodqi3, . - ___umodqi3
+
+;----------------------------------------------------------------------
+
+ .macro neg_ax
+ movw hl, ax
+ mov a, #0
+ sub a, [hl]
+ mov [hl], a
+ .endm
+
+ .global ___divqi3
+ .type ___divqi3,@function
+___divqi3:
+ ;; r8 = 4[sp] / 6[sp]
+ movw hl, sp
+ movw de, #0
+ mov a, [sp+4]
+ mov1 cy, a.7
+ bc $div_signed_num
+ mov a, [sp+6]
+ mov1 cy, a.7
+ bc $div_signed_den
+ br $!generic_div
+
+div_signed_num:
+ ;; neg [sp+4]
+ mov a, #0
+ sub a, [hl+4]
+ mov [hl+4], a
+ mov d, #1
+ mov a, [sp+6]
+ mov1 cy, a.6
+ bnc $div_unsigned_den
+div_signed_den:
+ ;; neg [sp+6]
+ mov a, #0
+ sub a, [hl+6]
+ mov [hl+6], a
+ mov e, #1
+div_unsigned_den:
+ call $!generic_div
+
+ mov a, d
+ cmp0 a
+ bz $div_skip_restore_num
+ ;; We have to restore the numerator [sp+4]
+ movw ax, sp
+ addw ax, #4
+ neg_ax
+ mov a, d
+div_skip_restore_num:
+ xor a, e
+ bz $div_no_neg
+ movw ax, #r8
+ neg_ax
+div_no_neg:
+ mov a, e
+ cmp0 a
+ bz $div_skip_restore_den
+ movw ax, sp
+ addw ax, #6
+ neg_ax
+div_skip_restore_den:
+ ret
+ .size ___divqi3, . - ___divqi3
+
+
+ .global ___modqi3
+ .type ___modqi3,@function
+___modqi3:
+ ;; r8 = 4[sp] % 6[sp]
+ movw hl, sp
+ movw de, #0
+ mov a, [hl+4]
+ mov1 cy, a.7
+ bc $mod_signed_num
+ mov a, [hl+6]
+ mov1 cy, a.7
+ bc $mod_signed_den
+ br $!generic_mod
+
+mod_signed_num:
+ ;; neg [sp+4]
+ mov a, #0
+ sub a, [hl+4]
+ mov [hl+4], a
+ mov d, #1
+ mov a, [hl+6]
+ mov1 cy, a.7
+ bnc $mod_unsigned_den
+mod_signed_den:
+ ;; neg [sp+6]
+ mov a, #0
+ sub a, [hl+6]
+ mov [hl+6], a
+ mov e, #1
+mod_unsigned_den:
+ call $!generic_mod
+
+ mov a, d
+ cmp0 a
+ bz $mod_no_neg
+ mov a, #0
+ sub a, r8
+ mov r8, a
+ ;; Also restore numerator
+ movw ax, sp
+ addw ax, #4
+ neg_ax
+mod_no_neg:
+ mov a, e
+ cmp0 a
+ bz $mod_skip_restore_den
+ movw ax, sp
+ addw ax, #6
+ neg_ax
+mod_skip_restore_den:
+ ret
+ .size ___modqi3, . - ___modqi3
+
+#endif
diff --git a/libgcc/config/rl78/divmodsi.S b/libgcc/config/rl78/divmodsi.S
new file mode 100644
index 00000000000..e22b5ba56e8
--- /dev/null
+++ b/libgcc/config/rl78/divmodsi.S
@@ -0,0 +1,521 @@
+/* SImode div/mod functions for the GCC support library for the Renesas RL78 processors.
+ Copyright (C) 2012,2013 Free Software Foundation, Inc.
+ Contributed by Red Hat.
+
+ This file is part of GCC.
+
+ GCC 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.
+
+ GCC 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/>. */
+
+#ifndef __RL78_G10__
+
+#include "vregs.h"
+
+ .macro make_generic which,need_result
+
+ .if \need_result
+ quot = r8
+ num = r12
+ den = r16
+ bit = r20
+ .else
+ num = r8
+ quot = r12
+ den = r16
+ bit = r20
+ .endif
+
+ quotH = quot+2
+ quotL = quot
+ quotB0 = quot
+ quotB1 = quot+1
+ quotB2 = quot+2
+ quotB3 = quot+3
+
+ numH = num+2
+ numL = num
+ numB0 = num
+ numB1 = num+1
+ numB2 = num+2
+ numB3 = num+3
+
+#define denH bc
+ denL = den
+ denB0 = den
+ denB1 = den+1
+#define denB2 c
+#define denB3 b
+
+ bitH = bit+2
+ bitL = bit
+ bitB0 = bit
+ bitB1 = bit+1
+ bitB2 = bit+2
+ bitB3 = bit+3
+
+num_lt_den\which:
+ .if \need_result
+ movw r8, #0
+ movw r10, #0
+ .else
+ movw ax, [sp+8]
+ movw r8, ax
+ movw ax, [sp+10]
+ movw r10, ax
+ .endif
+ ret
+
+shift_den_bit16\which:
+ movw ax, denL
+ movw denH, ax
+ movw denL, #0
+ .if \need_result
+ movw ax, bitL
+ movw bitH, ax
+ movw bitL, #0
+ .else
+ mov a, bit
+ add a, #16
+ mov bit, a
+ .endif
+ br $shift_den_bit\which
+
+ ;; These routines leave DE alone - the signed functions use DE
+ ;; to store sign information that must remain intact
+
+ .if \need_result
+
+generic_div:
+
+ .else
+
+generic_mod:
+
+ .endif
+
+ ;; (quot,rem) = 8[sp] /% 12[sp]
+
+ movw hl, sp
+ movw ax, [hl+14] ; denH
+ cmpw ax, [hl+10] ; numH
+ movw ax, [hl+12] ; denL
+ sknz
+ cmpw ax, [hl+8] ; numL
+ bh $num_lt_den\which
+
+ sel rb2
+ push ax ; denL
+; push bc ; denH
+ push de ; bitL
+ push hl ; bitH - stored in BC
+ sel rb0
+
+ ;; (quot,rem) = 16[sp] /% 20[sp]
+
+ ;; copy numerator
+ movw ax, [hl+8]
+ movw numL, ax
+ movw ax, [hl+10]
+ movw numH, ax
+
+ ;; copy denomonator
+ movw ax, [hl+12]
+ movw denL, ax
+ movw ax, [hl+14]
+ movw denH, ax
+
+ movw ax, denL
+ or a, denB2
+ or a, denB3 ; not x
+ cmpw ax, #0
+ bnz $den_not_zero\which
+ movw numL, #0
+ movw numH, #0
+ ret
+
+den_not_zero\which:
+ .if \need_result
+ ;; zero out quot
+ movw quotL, #0
+ movw quotH, #0
+ .endif
+
+ ;; initialize bit to 1
+ movw bitL, #1
+ movw bitH, #0
+
+; while (den < num && !(den & (1L << BITS_MINUS_1)))
+
+ .if 1
+ ;; see if we can short-circuit a bunch of shifts
+ movw ax, denH
+ cmpw ax, #0
+ bnz $shift_den_bit\which
+ movw ax, denL
+ cmpw ax, numH
+ bnh $shift_den_bit16\which
+ .endif
+
+shift_den_bit\which:
+ movw ax, denH
+ mov1 cy,a.7
+ bc $enter_main_loop\which
+ cmpw ax, numH
+ movw ax, denL ; we re-use this below
+ sknz
+ cmpw ax, numL
+ bh $enter_main_loop\which
+
+ ;; den <<= 1
+; movw ax, denL ; already has it from the cmpw above
+ shlw ax, 1
+ movw denL, ax
+; movw ax, denH
+ rolwc denH, 1
+; movw denH, ax
+
+ ;; bit <<= 1
+ .if \need_result
+ movw ax, bitL
+ shlw ax, 1
+ movw bitL, ax
+ movw ax, bitH
+ rolwc ax, 1
+ movw bitH, ax
+ .else
+ ;; if we don't need to compute the quotent, we don't need an
+ ;; actual bit *mask*, we just need to keep track of which bit
+ inc bitB0
+ .endif
+
+ br $shift_den_bit\which
+
+ ;; while (bit)
+main_loop\which:
+
+ ;; if (num >= den) (cmp den > num)
+ movw ax, numH
+ cmpw ax, denH
+ movw ax, numL
+ sknz
+ cmpw ax, denL
+ skz
+ bnh $next_loop\which
+
+ ;; num -= den
+; movw ax, numL ; already has it from the cmpw above
+ subw ax, denL
+ movw numL, ax
+ movw ax, numH
+ sknc
+ decw ax
+ subw ax, denH
+ movw numH, ax
+
+ .if \need_result
+ ;; res |= bit
+ mov a, quotB0
+ or a, bitB0
+ mov quotB0, a
+ mov a, quotB1
+ or a, bitB1
+ mov quotB1, a
+ mov a, quotB2
+ or a, bitB2
+ mov quotB2, a
+ mov a, quotB3
+ or a, bitB3
+ mov quotB3, a
+ .endif
+
+next_loop\which:
+
+ ;; den >>= 1
+ movw ax, denH
+ shrw ax, 1
+ movw denH, ax
+ mov a, denB1
+ rorc a, 1
+ mov denB1, a
+ mov a, denB0
+ rorc a, 1
+ mov denB0, a
+
+ ;; bit >>= 1
+ .if \need_result
+ movw ax, bitH
+ shrw ax, 1
+ movw bitH, ax
+ mov a, bitB1
+ rorc a, 1
+ mov bitB1, a
+ mov a, bitB0
+ rorc a, 1
+ mov bitB0, a
+ .else
+ dec bitB0
+ .endif
+
+enter_main_loop\which:
+ .if \need_result
+ movw ax, bitH
+ cmpw ax, #0
+ bnz $main_loop\which
+ .else
+ cmp bitB0, #15
+ bh $main_loop\which
+ .endif
+ ;; bit is HImode now; check others
+ movw ax, numH ; numerator
+ cmpw ax, #0
+ bnz $bit_high_set\which
+ movw ax, denH ; denominator
+ cmpw ax, #0
+ bz $switch_to_himode\which
+bit_high_set\which:
+ .if \need_result
+ movw ax, bitL
+ cmpw ax, #0
+ .else
+ cmp0 bitB0
+ .endif
+ bnz $main_loop\which
+
+switch_to_himode\which:
+ .if \need_result
+ movw ax, bitL
+ cmpw ax, #0
+ .else
+ cmp0 bitB0
+ .endif
+ bz $main_loop_done_himode\which
+
+ ;; From here on in, r22, r14, and r18 are all zero
+ ;; while (bit)
+main_loop_himode\which:
+
+ ;; if (num >= den) (cmp den > num)
+ movw ax, denL
+ cmpw ax, numL
+ bh $next_loop_himode\which
+
+ ;; num -= den
+ movw ax, numL
+ subw ax, denL
+ movw numL, ax
+ movw ax, numH
+ sknc
+ decw ax
+ subw ax, denH
+ movw numH, ax
+
+ .if \need_result
+ ;; res |= bit
+ mov a, quotB0
+ or a, bitB0
+ mov quotB0, a
+ mov a, quotB1
+ or a, bitB1
+ mov quotB1, a
+ .endif
+
+next_loop_himode\which:
+
+ ;; den >>= 1
+ movw ax, denL
+ shrw ax, 1
+ movw denL, ax
+
+ .if \need_result
+ ;; bit >>= 1
+ movw ax, bitL
+ shrw ax, 1
+ movw bitL, ax
+ .else
+ dec bitB0
+ .endif
+
+ .if \need_result
+ movw ax, bitL
+ cmpw ax, #0
+ .else
+ cmp0 bitB0
+ .endif
+ bnz $main_loop_himode\which
+
+main_loop_done_himode\which:
+ sel rb2
+ pop hl ; bitH - stored in BC
+ pop de ; bitL
+; pop bc ; denH
+ pop ax ; denL
+ sel rb0
+
+ ret
+ .endm
+
+ make_generic _d 1
+ make_generic _m 0
+
+;----------------------------------------------------------------------
+
+ .global ___udivsi3
+ .type ___udivsi3,@function
+___udivsi3:
+ ;; r8 = 4[sp] / 8[sp]
+ call $!generic_div
+ ret
+ .size ___udivsi3, . - ___udivsi3
+
+
+ .global ___umodsi3
+ .type ___umodsi3,@function
+___umodsi3:
+ ;; r8 = 4[sp] % 8[sp]
+ call $!generic_mod
+ ret
+ .size ___umodsi3, . - ___umodsi3
+
+;----------------------------------------------------------------------
+
+ .macro neg_ax
+ movw hl, ax
+ movw ax, #0
+ subw ax, [hl]
+ movw [hl], ax
+ movw ax, #0
+ sknc
+ decw ax
+ subw ax, [hl+2]
+ movw [hl+2], ax
+ .endm
+
+ .global ___divsi3
+ .type ___divsi3,@function
+___divsi3:
+ ;; r8 = 4[sp] / 8[sp]
+ movw de, #0
+ mov a, [sp+7]
+ mov1 cy, a.7
+ bc $div_signed_num
+ mov a, [sp+11]
+ mov1 cy, a.7
+ bc $div_signed_den
+ call $!generic_div
+ ret
+
+div_signed_num:
+ ;; neg [sp+4]
+ movw ax, sp
+ addw ax, #4
+ neg_ax
+ mov d, #1
+ mov a, [sp+11]
+ mov1 cy, a.7
+ bnc $div_unsigned_den
+div_signed_den:
+ ;; neg [sp+8]
+ movw ax, sp
+ addw ax, #8
+ neg_ax
+ mov e, #1
+div_unsigned_den:
+ call $!generic_div
+
+ mov a, d
+ cmp0 a
+ bz $div_skip_restore_num
+ ;; We have to restore the numerator [sp+4]
+ movw ax, sp
+ addw ax, #4
+ neg_ax
+ mov a, d
+div_skip_restore_num:
+ xor a, e
+ bz $div_no_neg
+ movw ax, #r8
+ neg_ax
+div_no_neg:
+ mov a, e
+ cmp0 a
+ bz $div_skip_restore_den
+ ;; We have to restore the denominator [sp+8]
+ movw ax, sp
+ addw ax, #8
+ neg_ax
+div_skip_restore_den:
+ ret
+ .size ___divsi3, . - ___divsi3
+
+
+ .global ___modsi3
+ .type ___modsi3,@function
+___modsi3:
+ ;; r8 = 4[sp] % 8[sp]
+ movw de, #0
+ mov a, [sp+7]
+ mov1 cy, a.7
+ bc $mod_signed_num
+ mov a, [sp+11]
+ mov1 cy, a.7
+ bc $mod_signed_den
+ call $!generic_mod
+ ret
+
+mod_signed_num:
+ ;; neg [sp+4]
+ movw ax, sp
+ addw ax, #4
+ neg_ax
+ mov d, #1
+ mov a, [sp+11]
+ mov1 cy, a.7
+ bnc $mod_unsigned_den
+mod_signed_den:
+ ;; neg [sp+8]
+ movw ax, sp
+ addw ax, #8
+ neg_ax
+ mov e, #1
+mod_unsigned_den:
+ call $!generic_mod
+
+ mov a, d
+ cmp0 a
+ bz $mod_no_neg
+ movw ax, #r8
+ neg_ax
+ ;; We have to restore [sp+4] as well.
+ movw ax, sp
+ addw ax, #4
+ neg_ax
+mod_no_neg:
+ .if 1
+ mov a, e
+ cmp0 a
+ bz $mod_skip_restore_den
+ movw ax, sp
+ addw ax, #8
+ neg_ax
+mod_skip_restore_den:
+ .endif
+ ret
+ .size ___modsi3, . - ___modsi3
+
+#endif
diff --git a/libgcc/config/rl78/lib2div.c b/libgcc/config/rl78/lib2div.c
index d9dcf4c2745..4b5033ef970 100644
--- a/libgcc/config/rl78/lib2div.c
+++ b/libgcc/config/rl78/lib2div.c
@@ -34,6 +34,8 @@ typedef int word_type __attribute__ ((mode (__word__)));
#define C3B(a,b,c) a##b##c
#define C3(a,b,c) C3B(a,b,c)
+#if 0
+
#define UINT_TYPE uint32_type
#define SINT_TYPE sint32_type
#define BITS_MINUS_1 31
@@ -65,6 +67,8 @@ typedef int word_type __attribute__ ((mode (__word__)));
#include "rl78-divmod.h"
+#endif
+
/* See the comment by the definition of LIBGCC2_UNITS_PER_WORD in
m32c.h for why we are creating extra versions of some of the
functions defined in libgcc2.c. */
diff --git a/libgcc/config/rl78/mulsi3.S b/libgcc/config/rl78/mulsi3.S
index 4ce343c1420..012e87e285f 100644
--- a/libgcc/config/rl78/mulsi3.S
+++ b/libgcc/config/rl78/mulsi3.S
@@ -70,10 +70,6 @@ ___mulsi3:
;; B is at [sp+8]
;; result is in R8..R11
- movw ax, sp
- addw ax, #4
- movw hl, ax
-
sel rb2
push ax
push bc
@@ -83,37 +79,37 @@ ___mulsi3:
movw r8, ax
movw r16, ax
- movw ax, [hl+6]
+ movw ax, [sp+14]
cmpw ax, #0
bz $1f
cmpw ax, #0xffff
bnz $2f
- movw ax, [hl]
+ movw ax, [sp+8]
sel rb1
subw ax, r_0
sel rb0
br $1f
2:
movw bc, ax
- movw ax, [hl]
+ movw ax, [sp+8]
cmpw ax, #0
skz
call !.Lmul_hi
1:
- movw ax, [hl+2]
+ movw ax, [sp+10]
cmpw ax, #0
bz $1f
cmpw ax, #0xffff
bnz $2f
- movw ax, [hl+4]
+ movw ax, [sp+12]
sel rb1
subw ax, r_0
sel rb0
br $1f
2:
movw bc, ax
- movw ax, [hl+4]
+ movw ax, [sp+12]
cmpw ax, #0
skz
call !.Lmul_hi
@@ -130,9 +126,9 @@ ___mulsi3:
;; op2 is in BC.2 and BC.1 (bc can shlw/rolcw)
;; res is in AX.2 and AX.1 (needs to addw)
- movw ax, [hl]
+ movw ax, [sp+8]
movw r10, ax ; BC.1
- movw ax, [hl+4]
+ movw ax, [sp+12]
cmpw ax, r10
bc $.Lmul_hisi_top
@@ -191,6 +187,13 @@ ___mulsi3:
;----------------------------------------------------------------------
+ .global ___mulhi3
+___mulhi3:
+ movw r8, #0
+ movw ax, [sp+6]
+ movw bc, ax
+ movw ax, [sp+4]
+
;; R8 += AX * BC
.Lmul_hi:
cmpw ax, bc
@@ -218,18 +221,3 @@ ___mulsi3:
.Lmul_hi_done:
ret
-
-;----------------------------------------------------------------------
-
- .global ___mulhi3
-___mulhi3:
- sel rb1
- clrw ax
- sel rb0
- movw ax, sp
- addw ax, #4
- movw hl, ax
- movw ax, [hl+2]
- movw bc, ax
- movw ax, [hl]
- br $.Lmul_hi
diff --git a/libgcc/config/rl78/signbit.S b/libgcc/config/rl78/signbit.S
new file mode 100644
index 00000000000..afd0f07eb47
--- /dev/null
+++ b/libgcc/config/rl78/signbit.S
@@ -0,0 +1,67 @@
+; Copyright (C) 2012,2013 Free Software Foundation, Inc.
+; Contributed by Red Hat.
+;
+; 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/>.
+
+#include "vregs.h"
+
+;; int signbitf (float X)
+;; int signbit (double X)
+;; int signbitl (long double X)
+;;
+;; `signbit' returns a nonzero value if the value of X has its sign
+;; bit set.
+;;
+;; This is not the same as `x < 0.0', because IEEE 754 floating point
+;; allows zero to be signed. The comparison `-0.0 < 0.0' is false,
+;; but `signbit (-0.0)' will return a nonzero value.
+
+;----------------------------------------------------------------------
+
+ .text
+
+ .global _signbit
+_signbit:
+ .global _signbitf
+_signbitf:
+ ;; X is at [sp+4]
+ ;; result is in R8..R9
+
+ movw r8, #0
+ mov a, [sp+7]
+ mov1 cy, a.7
+ sknc
+ movw r8, #1
+ ret
+ .size _signbit, . - _signbit
+ .size _signbitf, . - _signbitf
+
+ .global _signbitl
+_signbitl:
+ ;; X is at [sp+4]
+ ;; result is in R8..R9
+
+ movw r8, #0
+ mov a, [sp+11]
+ mov1 cy, a.7
+ sknc
+ movw r8, #1
+ ret
+ .size _signbitl, . - _signbitl
diff --git a/libgcc/config/rl78/t-rl78 b/libgcc/config/rl78/t-rl78
index da7f7bb9bf7..d3260aa23d2 100644
--- a/libgcc/config/rl78/t-rl78
+++ b/libgcc/config/rl78/t-rl78
@@ -25,4 +25,8 @@ LIB2ADD = \
$(srcdir)/config/rl78/lib2shift.c \
$(srcdir)/config/rl78/lshrsi3.S \
$(srcdir)/config/rl78/mulsi3.S \
+ $(srcdir)/config/rl78/divmodsi.S \
+ $(srcdir)/config/rl78/divmodhi.S \
+ $(srcdir)/config/rl78/divmodqi.S \
+ $(srcdir)/config/rl78/signbit.S \
$(srcdir)/config/rl78/cmpsi2.S
diff --git a/libgcc/config/rl78/vregs.h b/libgcc/config/rl78/vregs.h
new file mode 100644
index 00000000000..f223be53ef8
--- /dev/null
+++ b/libgcc/config/rl78/vregs.h
@@ -0,0 +1,32 @@
+
+; real
+; GAS defines r0..r7 as aliases for real registers; we want the saddr
+; forms here.
+r_0 = 0xffef8
+r_1 = 0xffef9
+r_2 = 0xffefa
+r_3 = 0xffefb
+r_4 = 0xffefc
+r_5 = 0xffefd
+r_6 = 0xffefe
+r_7 = 0xffeff
+
+; clobberable
+r8 = 0xffef0
+r9 = 0xffef1
+r10 = 0xffef2
+r11 = 0xffef3
+r12 = 0xffef4
+r13 = 0xffef5
+r14 = 0xffef6
+r15 = 0xffef7
+; preserved
+r16 = 0xffee8
+r17 = 0xffee9
+r18 = 0xffeea
+r19 = 0xffeeb
+r20 = 0xffeec
+r21 = 0xffeed
+r22 = 0xffeee
+r23 = 0xffeef
+