re PR target/28014 (space-optimized divide used inconsistently)
PR target/28014: gcc: * config/sh/t-sh (LIB1ASMFUNCS): Add _udiv_qrnnd16 * config/sh/sh.c (print_operand): Add !SHMEDIA functionality to 'M'. * config/sh/lib1funcs.h (SL, SL1): Define. * config/sh/lib1funcs.asm (__udiv_qrnnd16): New hidden function. * longlong.h (__sh__): Define umul_ppmm, udiv_qrnnd and sub_ddmmss. * config/sh/t-sh ($(T)unwind-dw2-Os-4-200.o): New rule. (OBJS_Os_4_200): New variable. ($(T)libgcc-Os-4-200.a): Use it. * sh.md (udivsi3): For TARGET_DIVIDE_CALL_TABLE, avoid function call when dividing 1 and/or by 0. gcc/testsuite: * g++.dg/eh/div.C: New test. From-SVN: r114616
This commit is contained in:
parent
de4fb767a9
commit
31b6f0aee8
9 changed files with 175 additions and 13 deletions
|
@ -1,3 +1,17 @@
|
|||
2006-06-06 J"orn Rennecke <joern.rennecke@st.com>
|
||||
|
||||
PR target/28014:
|
||||
* config/sh/t-sh (LIB1ASMFUNCS): Add _udiv_qrnnd16
|
||||
* config/sh/sh.c (print_operand): Add !SHMEDIA functionality to 'M'.
|
||||
* config/sh/lib1funcs.h (SL, SL1): Define.
|
||||
* config/sh/lib1funcs.asm (__udiv_qrnnd16): New hidden function.
|
||||
* longlong.h (__sh__): Define umul_ppmm, udiv_qrnnd and sub_ddmmss.
|
||||
* config/sh/t-sh ($(T)unwind-dw2-Os-4-200.o): New rule.
|
||||
(OBJS_Os_4_200): New variable.
|
||||
($(T)libgcc-Os-4-200.a): Use it.
|
||||
* sh.md (udivsi3): For TARGET_DIVIDE_CALL_TABLE, avoid function call
|
||||
when dividing 1 and/or by 0.
|
||||
|
||||
2006-06-13 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* configure.ac (HAS_MCONTEXT_T_UNDERSCORES): Include <sys/signal.h>
|
||||
|
|
|
@ -3843,3 +3843,51 @@ LOCAL(div_table_inv):
|
|||
#endif /* SH3 / SH4 */
|
||||
|
||||
#endif /* L_div_table */
|
||||
|
||||
#ifdef L_udiv_qrnnd_16
|
||||
#if !__SHMEDIA__
|
||||
HIDDEN_FUNC(GLOBAL(udiv_qrnnd_16))
|
||||
/* r0: rn r1: qn */ /* r0: n1 r4: n0 r5: d r6: d1 */ /* r2: __m */
|
||||
/* n1 < d, but n1 might be larger than d1. */
|
||||
.global GLOBAL(udiv_qrnnd_16)
|
||||
.balign 8
|
||||
GLOBAL(udiv_qrnnd_16):
|
||||
div0u
|
||||
cmp/hi r6,r0
|
||||
bt .Lots
|
||||
.rept 16
|
||||
div1 r6,r0
|
||||
.endr
|
||||
extu.w r0,r1
|
||||
bt 0f
|
||||
add r6,r0
|
||||
0: rotcl r1
|
||||
mulu.w r1,r5
|
||||
xtrct r4,r0
|
||||
swap.w r0,r0
|
||||
sts macl,r2
|
||||
cmp/hs r2,r0
|
||||
sub r2,r0
|
||||
bt 0f
|
||||
addc r5,r0
|
||||
add #-1,r1
|
||||
bt 0f
|
||||
1: add #-1,r1
|
||||
rts
|
||||
add r5,r0
|
||||
.balign 8
|
||||
.Lots:
|
||||
sub r5,r0
|
||||
swap.w r4,r1
|
||||
xtrct r0,r1
|
||||
clrt
|
||||
mov r1,r0
|
||||
addc r5,r0
|
||||
mov #-1,r1
|
||||
SL1(bf, 1b,
|
||||
shlr16 r1)
|
||||
0: rts
|
||||
nop
|
||||
ENDFUNC(GLOBAL(udiv_qrnnd_16))
|
||||
#endif /* !__SHMEDIA__ */
|
||||
#endif /* L_udiv_qrnnd_16 */
|
||||
|
|
|
@ -67,3 +67,15 @@ Boston, MA 02110-1301, USA. */
|
|||
#define DR40 fr4
|
||||
#define DR41 fr5
|
||||
#endif /* !__LITTLE_ENDIAN__ */
|
||||
|
||||
#ifdef __sh1__
|
||||
#define SL(branch, dest, in_slot, in_slot_arg2) \
|
||||
in_slot, in_slot_arg2; branch dest
|
||||
#define SL1(branch, dest, in_slot) \
|
||||
in_slot; branch dest
|
||||
#else /* ! __sh1__ */
|
||||
#define SL(branch, dest, in_slot, in_slot_arg2) \
|
||||
branch##.s dest; in_slot, in_slot_arg2
|
||||
#define SL1(branch, dest, in_slot) \
|
||||
branch##/s dest; in_slot
|
||||
#endif /* !__sh1__ */
|
||||
|
|
|
@ -662,7 +662,8 @@ print_operand_address (FILE *stream, rtx x)
|
|||
'R' print the LSW of a dp value - changes if in little endian
|
||||
'S' print the MSW of a dp value - changes if in little endian
|
||||
'T' print the next word of a dp value - same as 'R' in big endian mode.
|
||||
'M' print an `x' if `m' will print `base,index'.
|
||||
'M' SHMEDIA: print an `x' if `m' will print `base,index'.
|
||||
otherwise: print .b / .w / .l / .s / .d suffix if operand is a MEM.
|
||||
'N' print 'r63' if the operand is (const_int 0).
|
||||
'd' print a V2SF reg as dN instead of fpN.
|
||||
'm' print a pair `base,offset' or `base,index', for LD and ST.
|
||||
|
@ -820,11 +821,29 @@ print_operand (FILE *stream, rtx x, int code)
|
|||
}
|
||||
break;
|
||||
case 'M':
|
||||
if (GET_CODE (x) == MEM
|
||||
&& GET_CODE (XEXP (x, 0)) == PLUS
|
||||
&& (GET_CODE (XEXP (XEXP (x, 0), 1)) == REG
|
||||
|| GET_CODE (XEXP (XEXP (x, 0), 1)) == SUBREG))
|
||||
fputc ('x', stream);
|
||||
if (TARGET_SHMEDIA)
|
||||
{
|
||||
if (GET_CODE (x) == MEM
|
||||
&& GET_CODE (XEXP (x, 0)) == PLUS
|
||||
&& (GET_CODE (XEXP (XEXP (x, 0), 1)) == REG
|
||||
|| GET_CODE (XEXP (XEXP (x, 0), 1)) == SUBREG))
|
||||
fputc ('x', stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GET_CODE (x) == MEM)
|
||||
{
|
||||
switch (GET_MODE (x))
|
||||
{
|
||||
case QImode: fputs (".b", stream); break;
|
||||
case HImode: fputs (".w", stream); break;
|
||||
case SImode: fputs (".l", stream); break;
|
||||
case SFmode: fputs (".s", stream); break;
|
||||
case DFmode: fputs (".d", stream); break;
|
||||
default: gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
|
|
|
@ -1829,6 +1829,21 @@
|
|||
/* Emit the move of the address to a pseudo outside of the libcall. */
|
||||
if (TARGET_DIVIDE_CALL_TABLE)
|
||||
{
|
||||
/* libgcc2:__udivmoddi4 is not supposed to use an actual division, since
|
||||
that causes problems when the divide code is supposed to come from a
|
||||
separate library. Division by zero is undefined, so dividing 1 can be
|
||||
implemented by comparing with the divisor. */
|
||||
if (operands[1] == const1_rtx && currently_expanding_to_rtl)
|
||||
{
|
||||
emit_insn (gen_cmpsi (operands[1], operands[2]));
|
||||
emit_insn (gen_sgeu (operands[0]));
|
||||
DONE;
|
||||
}
|
||||
else if (operands[2] == const0_rtx)
|
||||
{
|
||||
emit_move_insn (operands[0], operands[2]);
|
||||
DONE;
|
||||
}
|
||||
function_symbol (operands[3], \"__udivsi3_i4i\", SFUNC_GOT);
|
||||
last = gen_udivsi3_i4_int (operands[0], operands[3]);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ sh-c.o: $(srcdir)/config/sh/sh-c.c \
|
|||
LIB1ASMSRC = sh/lib1funcs.asm
|
||||
LIB1ASMFUNCS = _ashiftrt _ashiftrt_n _ashiftlt _lshiftrt _movmem \
|
||||
_movmem_i4 _mulsi3 _sdivsi3 _sdivsi3_i4 _udivsi3 _udivsi3_i4 _set_fpscr \
|
||||
_div_table \
|
||||
_div_table _udiv_qrnnd_16 \
|
||||
$(LIB1ASMFUNCS_CACHE)
|
||||
|
||||
# We want fine grained libraries, so use the new code to build the
|
||||
|
@ -98,8 +98,11 @@ $(T)sdivsi3_i4i-Os-4-200.o: $(srcdir)/config/sh/lib1funcs-Os-4-200.asm $(GCC_PAS
|
|||
$(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $@ -DL_sdivsi3_i4i -x assembler-with-cpp $<
|
||||
$(T)udivsi3_i4i-Os-4-200.o: $(srcdir)/config/sh/lib1funcs-Os-4-200.asm $(GCC_PASSES)
|
||||
$(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $@ -DL_udivsi3_i4i -x assembler-with-cpp $<
|
||||
$(T)libgcc-Os-4-200.a: $(T)sdivsi3_i4i-Os-4-200.o $(T)udivsi3_i4i-Os-4-200.o $(GCC_PASSES)
|
||||
$(AR_CREATE_FOR_TARGET) $@ $(T)sdivsi3_i4i-Os-4-200.o $(T)udivsi3_i4i-Os-4-200.o
|
||||
$(T)unwind-dw2-Os-4-200.o: $(srcdir)/unwind-dw2.c $(srcdir)/unwind-generic.h unwind-pe.h unwind.inc unwind-dw2-fde.h unwind-dw2.h $(CONFIG_H) coretypes.h $(TM_H) $(MACHMODE_H) longlong.h config.status stmp-int-hdrs tsystem.h $(GCC_PASSES)
|
||||
$(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) $(vis_hide) -fexceptions -Os -c -o $@ $<
|
||||
OBJS_Os_4_200=$(T)sdivsi3_i4i-Os-4-200.o $(T)udivsi3_i4i-Os-4-200.o $(T)unwind-dw2-Os-4-200.o
|
||||
$(T)libgcc-Os-4-200.a: $(OBJS_Os_4_200) $(GCC_PASSES)
|
||||
$(AR_CREATE_FOR_TARGET) $@ $(OBJS_Os_4_200)
|
||||
|
||||
# Local Variables:
|
||||
# mode: Makefile
|
||||
|
|
|
@ -831,18 +831,51 @@ UDItype __umulsidi3 (USItype, USItype);
|
|||
} while (0)
|
||||
#endif
|
||||
|
||||
#if defined (__sh2__) && W_TYPE_SIZE == 32
|
||||
#if defined(__sh__) && !__SHMEDIA__ && W_TYPE_SIZE == 32
|
||||
#ifndef __sh1__
|
||||
#define umul_ppmm(w1, w0, u, v) \
|
||||
__asm__ ( \
|
||||
"dmulu.l %2,%3\n\tsts macl,%1\n\tsts mach,%0" \
|
||||
: "=r" ((USItype)(w1)), \
|
||||
"=r" ((USItype)(w0)) \
|
||||
"dmulu.l %2,%3\n\tsts%M1 macl,%1\n\tsts%M0 mach,%0" \
|
||||
: "=r<" ((USItype)(w1)), \
|
||||
"=r<" ((USItype)(w0)) \
|
||||
: "r" ((USItype)(u)), \
|
||||
"r" ((USItype)(v)) \
|
||||
: "macl", "mach")
|
||||
#define UMUL_TIME 5
|
||||
#endif
|
||||
|
||||
/* This is the same algorithm as __udiv_qrnnd_c. */
|
||||
#define UDIV_NEEDS_NORMALIZATION 1
|
||||
|
||||
#define udiv_qrnnd(q, r, n1, n0, d) \
|
||||
do { \
|
||||
extern UWtype __udiv_qrnnd_16 (UWtype, UWtype) \
|
||||
__attribute__ ((visibility ("hidden"))); \
|
||||
/* r0: rn r1: qn */ /* r0: n1 r4: n0 r5: d r6: d1 */ /* r2: __m */ \
|
||||
__asm__ ( \
|
||||
"mov%M4 %4,r5\n" \
|
||||
" swap.w %3,r4\n" \
|
||||
" swap.w r5,r6\n" \
|
||||
" jsr @%5\n" \
|
||||
" shll16 r6\n" \
|
||||
" swap.w r4,r4\n" \
|
||||
" jsr @%5\n" \
|
||||
" swap.w r1,%0\n" \
|
||||
" or r1,%0" \
|
||||
: "=r" (q), "=&z" (r) \
|
||||
: "1" (n1), "r" (n0), "rm" (d), "r" (&__udiv_qrnnd_16) \
|
||||
: "r1", "r2", "r4", "r5", "r6", "pr"); \
|
||||
} while (0)
|
||||
|
||||
#define UDIV_TIME 80
|
||||
|
||||
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
|
||||
__asm__ ("clrt;subc %5,%1; subc %4,%0" \
|
||||
: "=r" (sh), "=r" (sl) \
|
||||
: "0" (ah), "1" (al), "r" (bh), "r" (bl))
|
||||
|
||||
#endif /* __sh__ */
|
||||
|
||||
#if defined (__SH5__) && __SHMEDIA__ && W_TYPE_SIZE == 32
|
||||
#define __umulsidi3(u,v) ((UDItype)(USItype)u*(USItype)v)
|
||||
#define count_leading_zeros(count, x) \
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2006-06-13 J"orn Rennecke <joern.rennecke@st.com>
|
||||
|
||||
PR target/28014:
|
||||
* g++.dg/eh/div.C: New test.
|
||||
|
||||
2006-06-13 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/27894
|
||||
|
|
13
gcc/testsuite/g++.dg/eh/div.C
Normal file
13
gcc/testsuite/g++.dg/eh/div.C
Normal file
|
@ -0,0 +1,13 @@
|
|||
// { dg-do link }
|
||||
// { dg-options "-Os" }
|
||||
/* PR target/28014: main references unsigned divide, and the unwinder
|
||||
references signed divide.
|
||||
If libgcc contains an object which defines both, and linking is done with
|
||||
a space-optimized library that defines these functions in separate objects,
|
||||
you end up with the function for unsigned divide defined twice. */
|
||||
int
|
||||
main (int c, char **argv)
|
||||
|
||||
{
|
||||
return 0xffffU/c;
|
||||
}
|
Loading…
Add table
Reference in a new issue