Bring s390 backend back in sync with branch.

From-SVN: r44810
This commit is contained in:
Ulrich Weigand 2001-08-11 20:56:12 +00:00 committed by Ulrich Weigand
parent dddba20582
commit f314b9b168
7 changed files with 391 additions and 165 deletions

View File

@ -1,3 +1,51 @@
2001-08-11 Ulrich Weigand <uweigand@de.ibm.com>
* config/s390/s390.c (targetm): Define TARGET_ASM_OPEN_PAREN
and TARGET_ASM_CLOSE_PAREN.
(regclass_map): CC register belongs to class NO_REGS.
(legitimize_pic_address): Don't generate unnecessary moves
(to avoid confusing loop optimization).
(check_and_change_labels): Replace jump_long by indirect_jump.
(s390_final_chunkify): Don't start a new literal pool on section
switch in 64-bit code.
(s390_va_start, s390_va_arg): Fixed incorrect sizes for 64-bit.
* config/s390/s390.h (TARGET_SWITCHES): Renamed debug_arg to debug.
(MAX_BITS_PER_WORD, MAX_LONG_TYPE_SIZE): Set to 64 (for 64-bit).
(HARD_REGNO_MODE_OK, RETURN_IN_MEMORY): Support complex integer
modes correctly.
(reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS): Remove CC_REGS.
(EH_RETURN_HANDLER_RTX): Fixed incorrect offset for 64-bit.
(CONST_COSTS): Fixed incorrect costs.
* config/s390/s390.md (fixuns_trunc[sd]f[sd]i2, udivsi3, umodsi3):
Use emit_jump instead of emit_jump_insn (gen_jump).
(divsi3, modsi3): Clobber low word of divmoddisi3 before shifting
(to avoid confusing flow analysis).
(tablejump, tablejump1, tablejump2): Removed. Replaced by casesi.
(casesi, casesi_jump): New.
(jump_long): Removed. Functionality merged into indirect_jump.
(indirect_jump): Accept address_operand, not just register_operand.
(cjump_long, icjump_long): Use same logic as indirect_jump.
(builtin_setjmp_setup, builtin_setjmp_receiver, builtin_longjmp):
Fixed broken setjmp/longjmp handling.
(do_builtin_setjmp_setup): Removed.
* config/s390/linux.h (ASM_OUTPUT_DOUBLE_INT): Work around
broken GNU as versions that don't accept .quad with large
negative values. Use hexadecimal output instead.
(ASM_OUTPUT_ADDR_DIFF_ELT): Adapt to new casesi insn.
(ASM_OPEN_PAREN, ASM_CLOSE_PAREN, FUNCTION_PROLOGUE,
FUNCTION_EPILOGUE): Removed. Now in targetm.
* config/s390/linux64.h (CALL_USED_REGISTERS): Add CC register.
* config/s390/fixdfdi.h: Add missing copyright statement.
Fix type conflicts on 64-bit. Add missing SFmode routines.
* s390.c, s390.h, s390.md, linux.h, linux64.h: Fixed incorrect
email address.
2001-08-11 Richard Henderson <rth@redhat.com>
* rtl.h (REG_EH_RETHROW): Remove.

View File

@ -1,3 +1,25 @@
/* Definitions of target machine for GNU compiler, for IBM S/390
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com) and
Ulrich Weigand (uweigand@de.ibm.com).
This file is part of GNU CC.
GNU CC 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 2, or (at your option)
any later version.
GNU CC 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.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifdef L_fixunsdfdi
#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
#define EXCESSD 1022
@ -5,25 +27,30 @@
#define SIGND(fp) ((fp.l.upper) & SIGNBIT)
#define MANTD_LL(fp) ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL)
#define FRACD_LL(fp) (fp.ll & (HIDDEND_LL-1))
#define HIDDEND_LL ((long long)1 << 52)
#define HIDDEND_LL ((UDItype_x)1 << 52)
typedef int DItype_x __attribute__ ((mode (DI)));
typedef unsigned int UDItype_x __attribute__ ((mode (DI)));
typedef int SItype_x __attribute__ ((mode (SI)));
typedef unsigned int USItype_x __attribute__ ((mode (SI)));
union double_long {
double d;
struct {
long upper;
unsigned long lower;
SItype_x upper;
USItype_x lower;
} l;
long long ll;
UDItype_x ll;
};
/* convert double to unsigned int */
unsigned long long
UDItype_x
__fixunsdfdi (double a1)
{
register union double_long dl1;
register int exp;
register long long l;
register UDItype_x l;
dl1.d = a1;
@ -71,24 +98,29 @@ __fixunsdfdi (double a1)
#define SIGND(fp) ((fp.l.upper) & SIGNBIT)
#define MANTD_LL(fp) ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL)
#define FRACD_LL(fp) (fp.ll & (HIDDEND_LL-1))
#define HIDDEND_LL ((long long)1 << 52)
#define HIDDEND_LL ((UDItype_x)1 << 52)
typedef int DItype_x __attribute__ ((mode (DI)));
typedef unsigned int UDItype_x __attribute__ ((mode (DI)));
typedef int SItype_x __attribute__ ((mode (SI)));
typedef unsigned int USItype_x __attribute__ ((mode (SI)));
union double_long {
double d;
struct {
long upper;
unsigned long lower;
SItype_x upper;
USItype_x lower;
} l;
long long ll;
UDItype_x ll;
};
/* convert double to int */
long long
DItype_x
__fixdfdi (double a1)
{
register union double_long dl1;
register int exp;
register long long l;
register DItype_x l;
dl1.d = a1;
@ -132,3 +164,138 @@ __fixdfdi (double a1)
#endif
#undef L_fixdfdi
#ifdef L_fixunssfdi
#define EXP(fp) (((fp.l) >> 23) & 0xFF)
#define EXCESS 126
#define SIGNBIT 0x80000000
#define SIGN(fp) ((fp.l) & SIGNBIT)
#define HIDDEN (1 << 23)
#define MANT(fp) (((fp.l) & 0x7FFFFF) | HIDDEN)
#define FRAC(fp) ((fp.l) & 0x7FFFFF)
typedef int DItype_x __attribute__ ((mode (DI)));
typedef unsigned int UDItype_x __attribute__ ((mode (DI)));
typedef int SItype_x __attribute__ ((mode (SI)));
typedef unsigned int USItype_x __attribute__ ((mode (SI)));
union float_long
{
float f;
USItype_x l;
};
/* convert float to unsigned int */
UDItype_x
__fixunssfdi (float a1)
{
register union float_long fl1;
register int exp;
register UDItype_x l;
fl1.f = a1;
/* +/- 0, denormalized, negativ */
if (!EXP (fl1) || SIGN(fl1))
return 0;
exp = EXP (fl1) - EXCESS - 24;
/* number < 1 */
if (exp < -24)
return 0;
/* NaN */
if ((EXP(fl1) == 0xff) && (FRAC(fl1) != 0)) /* NaN */
return 0x0ULL;
/* Number big number & + inf */
if (exp >= 41) {
return 0xFFFFFFFFFFFFFFFFULL;
}
l = MANT(fl1);
if (exp > 0)
l <<= exp;
else
l >>= -exp;
return l;
}
#define __fixunssfdi ___fixunssfdi
#endif
#undef L_fixunssfdi
#ifdef L_fixsfdi
#define EXP(fp) (((fp.l) >> 23) & 0xFF)
#define EXCESS 126
#define SIGNBIT 0x80000000
#define SIGN(fp) ((fp.l) & SIGNBIT)
#define HIDDEN (1 << 23)
#define MANT(fp) (((fp.l) & 0x7FFFFF) | HIDDEN)
#define FRAC(fp) ((fp.l) & 0x7FFFFF)
typedef int DItype_x __attribute__ ((mode (DI)));
typedef unsigned int UDItype_x __attribute__ ((mode (DI)));
typedef int SItype_x __attribute__ ((mode (SI)));
typedef unsigned int USItype_x __attribute__ ((mode (SI)));
union float_long
{
float f;
USItype_x l;
};
/* convert double to int */
DItype_x
__fixsfdi (float a1)
{
register union float_long fl1;
register int exp;
register DItype_x l;
fl1.f = a1;
/* +/- 0, denormalized */
if (!EXP (fl1))
return 0;
exp = EXP (fl1) - EXCESS - 24;
/* number < 1 */
if (exp < -24)
return 0;
/* NaN */
if ((EXP(fl1) == 0xff) && (FRAC(fl1) != 0)) /* NaN */
return 0x8000000000000000ULL;
/* Number big number & +/- inf */
if (exp >= 40) {
l = (long long)1<<63;
if (!SIGN(fl1))
l--;
return l;
}
l = MANT(fl1);
if (exp > 0)
l <<= exp;
else
l >>= -exp;
return (SIGN (fl1) ? -l : l);
}
#define __fixsfdi ___fixsfdi
#endif
#undef L_fixsfdi

View File

@ -1,7 +1,7 @@
/* Definitions for Linux for S/390.
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com) and
Ulrich Weigand (weigand@de.ibm.com).
Ulrich Weigand (uweigand@de.ibm.com).
This file is part of GNU CC.
@ -138,10 +138,14 @@ Boston, MA 02111-1307, USA. */
sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
#define ASM_OUTPUT_DOUBLE_INT(FILE, VALUE) \
do { fprintf (FILE, "%s\t", ASM_QUAD); \
output_addr_const (FILE,(VALUE)); \
putc ('\n',FILE); \
#define ASM_OUTPUT_DOUBLE_INT(FILE, VALUE) \
do { fprintf ((FILE), "%s\t", ASM_QUAD); \
/* Work around bug in some GNU as versions */ \
if (GET_CODE (VALUE) == CONST_INT && INTVAL (VALUE) < INT_MIN) \
fprintf ((FILE), HOST_WIDE_INT_PRINT_HEX, INTVAL (x)); \
else \
output_addr_const ((FILE), (VALUE)); \
putc ('\n', (FILE)); \
} while (0)
@ -180,22 +184,14 @@ do { fprintf (FILE, "%s\t", ASM_LONG); \
/* This is how to output an element of a case-vector that is absolute. */
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
fprintf (FILE, "%s %s%d\n", TARGET_64BIT?ASM_QUAD:ASM_LONG, \
fprintf (FILE, "%s\t%s%d\n", TARGET_64BIT?ASM_QUAD:ASM_LONG, \
LPREFIX, VALUE)
/* This is how to output an element of a case-vector that is relative. */
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
fprintf (FILE, "%s %s%d-.LT%X_%X\n" ,TARGET_64BIT?ASM_QUAD:ASM_LONG, \
LPREFIX, VALUE, s390_function_count,s390_pool_count)
/* Define the parentheses used to group arithmetic operations
in assembler code. */
#undef ASM_OPEN_PAREN
#undef ASM_CLOSE_PAREN
#define ASM_OPEN_PAREN ""
#define ASM_CLOSE_PAREN ""
fprintf (FILE, "%s\t%s%d-%s%d\n", TARGET_64BIT?ASM_QUAD:ASM_LONG, \
LPREFIX, VALUE, LPREFIX, REL)
@ -293,24 +289,6 @@ do { \
#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
/*
* This macro generates the assembly code for function entry.
*/
#define FUNCTION_PROLOGUE(FILE, LSIZE) s390_function_prologue (FILE, LSIZE)
/* This macro generates the assembly code for function exit, on machines
that need it. If FUNCTION_EPILOGUE is not defined then individual
return instructions are generated for each return statement. Args are
same as for FUNCTION_PROLOGUE.
The function epilogue should not depend on the current stack pointer!
It should use the frame pointer only. This is mandatory because
of alloca; we also take advantage of it to omit stack adjustments
before returning. */
#define FUNCTION_EPILOGUE(FILE, LSIZE) s390_function_epilogue(FILE, LSIZE)
/* Select section for constant in constant pool.
We are in the right section.
undef for 64 bit mode (linux64.h).

View File

@ -1,7 +1,7 @@
/* Definitions for Linux for s/390 zSeries
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com) and
Ulrich Weigand (weigand@de.ibm.com).
Ulrich Weigand (uweigand@de.ibm.com).
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
@ -77,6 +77,6 @@ Boston, MA 02111-1307, USA. */
1, 1, 1, 1, \
0, 0, 0, 0, \
0, 0, 0, 0, \
1 }
1, 1 }
#endif

View File

@ -1,7 +1,7 @@
/* Subroutines used for code generation on IBM S/390 and zSeries
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com) and
Ulrich Weigand (weigand@de.ibm.com).
Ulrich Weigand (uweigand@de.ibm.com).
This file is part of GNU CC.
@ -53,6 +53,12 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE s390_function_epilogue
#undef TARGET_ASM_OPEN_PAREN
#define TARGET_ASM_OPEN_PAREN ""
#undef TARGET_ASM_CLOSE_PAREN
#define TARGET_ASM_CLOSE_PAREN ""
struct gcc_target targetm = TARGET_INITIALIZER;
extern int reload_completed;
@ -173,7 +179,7 @@ enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
ADDR_REGS, CC_REGS
ADDR_REGS, NO_REGS
};
@ -959,11 +965,6 @@ legitimize_pic_address (orig, reg)
case 112:
case 114:
new = force_const_mem (SImode, orig);
if (reg != 0)
{
emit_move_insn (reg, new);
new = reg;
}
break;
/* @GOTENT is OK as is. */
@ -1080,11 +1081,6 @@ legitimize_pic_address (orig, reg)
abort();
new = force_const_mem (SImode, orig);
if (reg != 0)
{
emit_move_insn (reg, new);
new = reg;
}
}
/* Otherwise, compute the sum. */
@ -1700,7 +1696,7 @@ check_and_change_labels (rtx insn, int *ltorg_uids)
}
emit_insn_before (gen_movsi (temp_reg, target), insn);
tmp = emit_jump_insn_before (gen_jump_long (jump), insn);
tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
remove_insn (insn);
INSN_ADDRESSES_NEW (tmp, -1);
return tmp;
@ -1736,7 +1732,7 @@ check_and_change_labels (rtx insn, int *ltorg_uids)
label1 = gen_label_rtx ();
emit_jump_insn_before (gen_icjump (label1, XEXP (body, 0)), insn);
emit_insn_before (gen_movsi (temp_reg, target), insn);
tmp = emit_jump_insn_before (gen_jump_long (jump), insn);
tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
INSN_ADDRESSES_NEW (emit_label_before (label1, insn), -1);
remove_insn (insn);
return tmp;
@ -1770,7 +1766,7 @@ check_and_change_labels (rtx insn, int *ltorg_uids)
label1 = gen_label_rtx ();
emit_jump_insn_before (gen_cjump (label1, XEXP (body, 0)), insn);
emit_insn_before (gen_movsi (temp_reg, target), insn);
tmp = emit_jump_insn_before (gen_jump_long (jump), insn);
tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
INSN_ADDRESSES_NEW (emit_label_before (label1, insn), -1);
remove_insn (insn);
return tmp;
@ -1862,7 +1858,7 @@ s390_final_chunkify (int chunkify)
warning ("no code label found");
}
}
else if (GET_CODE (PATTERN (insn)) == ASM_INPUT)
else if (GET_CODE (PATTERN (insn)) == ASM_INPUT && !TARGET_64BIT)
{
asms = XSTR (PATTERN (insn),0);
@ -2732,7 +2728,7 @@ s390_va_start (int stdarg_p, tree valist, rtx nextarg)
off = INTVAL (current_function_arg_offset_rtx);
off = off < 0 ? 0 : off;
if (! stdarg_p)
off = off > 0 ? off - 4 : off;
off = off > 0 ? off - UNITS_PER_WORD : off;
if (TARGET_DEBUG_ARG)
fprintf (stderr, "va_start: n_gpr = %d, n_fpr = %d off %d\n",
n_gpr, n_fpr, off);
@ -2809,7 +2805,7 @@ s390_va_arg (tree valist, tree type)
indirect_p = 1;
reg = gpr;
n_reg = 1;
sav_ofs = 8;
sav_ofs = 2 * UNITS_PER_WORD;
sav_scale = UNITS_PER_WORD;
size = UNITS_PER_WORD;
max_reg = 4;
@ -2826,7 +2822,7 @@ s390_va_arg (tree valist, tree type)
indirect_p = 0;
reg = fpr;
n_reg = 1;
sav_ofs = 16 * UNITS_PER_WORD;;
sav_ofs = 16 * UNITS_PER_WORD;
sav_scale = 8;
/* TARGET_64BIT has up to 4 parameter in fprs */
max_reg = TARGET_64BIT ? 3 : 1;

View File

@ -1,7 +1,7 @@
/* Definitions of target machine for GNU compiler, for IBM S/390
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com) and
Ulrich Weigand (weigand@de.ibm.com).
Ulrich Weigand (uweigand@de.ibm.com).
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
@ -54,8 +54,8 @@ extern int target_flags;
{ "no-backchain", -2,N_("Don't set backchain (faster, but debug harder")}, \
{ "small-exec", 4,N_("Use bras for execucable < 64k")}, \
{ "no-small-exec",-4,N_("Don't use bras")}, \
{ "debug_arg", 8,N_("Additional debug prints")}, \
{ "no-debug_arg", -8,N_("Don't print additional debug prints")}, \
{ "debug", 8,N_("Additional debug prints")}, \
{ "no-debug", -8,N_("Don't print additional debug prints")}, \
{ "64", 16,N_("64 bit mode")}, \
{ "31", -16,N_("31 bit mode")}, \
{ "mvcle", 32,N_("mvcle use")}, \
@ -95,7 +95,7 @@ extern int current_function_outgoing_args_size;
/* Width in bits of a "word", which is the contents of a machine register. */
#define BITS_PER_WORD (TARGET_64BIT ? 64 : 32)
#define MAX_BITS_PER_WORD 32
#define MAX_BITS_PER_WORD 64
/* Width of a word, in units (bytes). */
@ -121,7 +121,7 @@ extern int current_function_outgoing_args_size;
target machine. If you don't define this, the default is one
word. */
#define LONG_TYPE_SIZE (TARGET_64BIT ? 64 : 32)
#define MAX_LONG_TYPE_SIZE 32
#define MAX_LONG_TYPE_SIZE 64
/* A C expression for the size in bits of the type `long long' on the
target machine. If you don't define this, the default is two
@ -330,8 +330,7 @@ do \
(GET_MODE_CLASS(MODE) == MODE_FLOAT || \
GET_MODE_CLASS(MODE) == MODE_COMPLEX_FLOAT) : \
INT_REGNO_P(REGNO)? \
(!((TARGET_64BIT && (MODE) == TImode) || \
(!TARGET_64BIT && (MODE) == DImode)) || ((REGNO) & 1) == 0 ) : \
(HARD_REGNO_NREGS(REGNO, MODE) == 1 || !((REGNO) & 1)) : \
CC_REGNO_P(REGNO)? \
GET_MODE_CLASS (MODE) == MODE_CC : \
0)
@ -427,7 +426,7 @@ while (0)
enum reg_class
{
NO_REGS, ADDR_REGS, GENERAL_REGS,
FP_REGS, CC_REGS, ALL_REGS, LIM_REG_CLASSES
FP_REGS, ALL_REGS, LIM_REG_CLASSES
};
#define N_REG_CLASSES (int) LIM_REG_CLASSES
@ -435,7 +434,7 @@ enum reg_class
/* Give names of register classes as strings for dump file. */
#define REG_CLASS_NAMES \
{ "NO_REGS","ADDR_REGS", "GENERAL_REGS", "FP_REGS", "CC_REGS", "ALL_REGS" }
{ "NO_REGS","ADDR_REGS", "GENERAL_REGS", "FP_REGS", "ALL_REGS" }
/* Define which registers fit in which classes. This is an initializer for
a vector of HARD_REG_SET of length N_REG_CLASSES.
@ -447,7 +446,6 @@ enum reg_class
{ 0x0000fffe, 0x00000001 }, /* ADDR_REGS */ \
{ 0x0000ffff, 0x00000001 }, /* GENERAL_REGS */ \
{ 0xffff0000, 0x00000000 }, /* FP_REGS */ \
{ 0x00000000, 0x00000002 }, /* CC_REGS */ \
{ 0xffffffff, 0x00000003 }, /* ALL_REGS */ \
}
@ -591,7 +589,8 @@ extern enum reg_class regclass_map[]; /* smalled class containing REGNO */
#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 6 : INVALID_REGNUM)
#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, 10)
#define EH_RETURN_HANDLER_RTX \
gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, -40))
gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, \
TARGET_64BIT? -48 : -40))
/* Define this if pushing a word on the stack makes the stack pointer a
smaller address. */
@ -767,10 +766,10 @@ CUMULATIVE_ARGS;
/* The definition of this macro implies that there are cases where
a scalar value cannot be returned in registers. */
#define RETURN_IN_MEMORY(type) \
(TYPE_MODE (type) == BLKmode || \
TYPE_MODE (type) == DCmode || \
TYPE_MODE (type) == SCmode)
#define RETURN_IN_MEMORY(type) \
(TYPE_MODE (type) == BLKmode || \
GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_INT || \
GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_FLOAT)
/* Mode of stack savearea.
FUNCTION is VOIDmode because calling convention maintains SP.
@ -1569,11 +1568,11 @@ do { \
if ((OUTER_CODE == PLUS) && \
((INTVAL (RTX) > 32767) || \
(INTVAL (RTX) < -32768))) \
return 3; \
return COSTS_N_INSNS (3); \
case LABEL_REF: \
case SYMBOL_REF: \
case CONST_DOUBLE: \
return 1; \
return 0; \
/* Like `CONST_COSTS' but applies to nonconstant RTL expressions.

View File

@ -1,7 +1,7 @@
;;- Machine description for GNU compiler -- S/390 / zSeries version.
;; Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
;; Ulrich Weigand (weigand@de.ibm.com).
;; Ulrich Weigand (uweigand@de.ibm.com).
;; This file is part of GNU CC.
;; GNU CC is free software; you can redistribute it and/or modify
@ -2397,7 +2397,7 @@
emit_insn (gen_subdf3 (temp, operands[1], force_const_mem (DFmode,
CONST_DOUBLE_FROM_REAL_VALUE (0x10000000000000000ULL, DFmode))));
emit_insn (gen_fix_truncdfdi2_ieee (operands[0], temp, GEN_INT(7)));
emit_jump_insn (gen_jump (label2));
emit_jump (label2);
emit_label (label1);
emit_insn (gen_fix_truncdfdi2_ieee (operands[0], operands[1], GEN_INT(5)));
@ -2447,7 +2447,7 @@
emit_insn (gen_subdf3 (temp, operands[1], force_const_mem (DFmode,
CONST_DOUBLE_FROM_REAL_VALUE (0x100000000ULL, DFmode))));
emit_insn (gen_fix_truncdfsi2_ieee (operands[0], temp, GEN_INT (7)));
emit_jump_insn (gen_jump (label2));
emit_jump (label2);
emit_label (label1);
emit_insn (gen_fix_truncdfsi2_ieee (operands[0], operands[1], GEN_INT (5)));
@ -2538,7 +2538,7 @@
emit_insn (gen_subsf3 (temp, operands[1], force_const_mem (SFmode,
CONST_DOUBLE_FROM_REAL_VALUE (0x10000000000000000ULL, SFmode))));
emit_insn (gen_fix_truncsfdi2_ieee (operands[0], temp, GEN_INT(7)));
emit_jump_insn (gen_jump (label2));
emit_jump (label2);
emit_label (label1);
emit_insn (gen_fix_truncsfdi2_ieee (operands[0], operands[1], GEN_INT(5)));
@ -2588,7 +2588,7 @@
emit_insn (gen_subsf3 (temp, operands[1], force_const_mem (SFmode,
CONST_DOUBLE_FROM_REAL_VALUE (0x100000000ULL, SFmode))));
emit_insn (gen_fix_truncsfsi2_ieee (operands[0], temp, GEN_INT (7)));
emit_jump_insn (gen_jump (label2));
emit_jump (label2);
emit_label (label1);
emit_insn (gen_fix_truncsfsi2_ieee (operands[0], operands[1], GEN_INT (5)));
@ -3754,7 +3754,7 @@
else
operands[2] = force_reg (SImode, operands[2]);
emit_insn (gen_rtx_CLOBBER (DImode, tmp));
emit_insn (gen_rtx_CLOBBER (SImode, gen_rtx_SUBREG (SImode, tmp, 4)));
emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), operands[1]);
emit_insn (gen_ashrdi3 (tmp, tmp, GEN_INT (32)));
emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
@ -3776,7 +3776,7 @@
else
operands[2] = force_reg (SImode, operands[2]);
emit_insn (gen_rtx_CLOBBER (DImode, tmp));
emit_insn (gen_rtx_CLOBBER (SImode, gen_rtx_SUBREG (SImode, tmp, 4)));
emit_insn (gen_movsi (gen_rtx_SUBREG (SImode, tmp, 0), operands[1]));
emit_insn (gen_ashrdi3 (tmp, tmp, GEN_INT (32)));
emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
@ -3858,10 +3858,10 @@
emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), const0_rtx);
emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 4), operands[1]);
emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
emit_jump_insn (gen_jump (label3));
emit_jump (label3);
emit_label (label1);
emit_move_insn (dr_1, operands[1]);
emit_jump_insn (gen_jump (label3));
emit_jump (label3);
emit_label (label2);
emit_move_insn (dr_1, const1_rtx);
emit_label (label3);
@ -3924,10 +3924,10 @@
emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), const0_rtx);
emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 4), operands[1]);
emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
emit_jump_insn (gen_jump (label3));
emit_jump (label3);
emit_label (label1);
emit_move_insn (dr_0, const0_rtx);
emit_jump_insn (gen_jump (label3));
emit_jump (label3);
emit_label (label2);
emit_insn (gen_subsi3 (dr_0, dr_0, operands[2]));
emit_label (label3);
@ -5043,15 +5043,24 @@
(lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
(const_int 4) (const_int 6)))])
(define_insn "cjump_long"
(define_insn "*cjump_long"
[(set (pc)
(if_then_else
(match_operator 1 "comparison_operator" [(reg 33) (const_int 0)])
(match_operand 0 "memory_operand" "m")
(match_operand 0 "address_operand" "p")
(pc)))]
""
"b%C1\\t%0"
[(set_attr "op_type" "RX")])
"*
{
if (get_attr_op_type (insn) == OP_TYPE_RR)
return \"b%C1r\\t%0\";
else
return \"b%C1\\t%a0\";
}"
[(set (attr "op_type")
(if_then_else (match_operand 0 "register_operand" "")
(const_string "RR") (const_string "RX")))
(set_attr "atype" "mem")])
;;
@ -5077,15 +5086,24 @@
(lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
(const_int 4) (const_int 6)))])
(define_insn "icjump_long"
(define_insn "*icjump_long"
[(set (pc)
(if_then_else
(match_operator 1 "comparison_operator" [(reg 33) (const_int 0)])
(pc)
(match_operand 0 "memory_operand" "m")))]
(pc)
(match_operand 0 "address_operand" "p")))]
""
"b%D1\\t%0"
[(set_attr "op_type" "RX")])
"*
{
if (get_attr_op_type (insn) == OP_TYPE_RR)
return \"b%D1r\\t%0\";
else
return \"b%D1\\t%a0\";
}"
[(set (attr "op_type")
(if_then_else (match_operand 0 "register_operand" "")
(const_string "RR") (const_string "RX")))
(set_attr "atype" "mem")])
;;
@ -5164,54 +5182,80 @@
;
(define_insn "indirect_jump"
[(set (pc) (match_operand 0 "register_operand" "a"))]
[(set (pc) (match_operand 0 "address_operand" "p"))]
""
"br\\t%0"
[(set_attr "op_type" "RX")])
(define_insn "jump_long"
[(set (pc) (match_operand 0 "address_operand" "p"))]
""
"b\\t%a0"
[(set_attr "op_type" "RX")
(set_attr "atype" "mem")])
"*
{
if (get_attr_op_type (insn) == OP_TYPE_RR)
return \"br\\t%0\";
else
return \"b\\t%a0\";
}"
[(set (attr "op_type")
(if_then_else (match_operand 0 "register_operand" "")
(const_string "RR") (const_string "RX")))
(set_attr "atype" "mem")])
;
; tablejump instruction pattern(s).
; casesi instruction pattern(s).
;
(define_expand "tablejump"
[(parallel
[(set (pc) (match_operand 0 "register_operand" "a"))
(use (label_ref (match_operand 1 "" "")))])]
(define_insn "casesi_jump"
[(set (pc) (match_operand 0 "address_operand" "p"))
(use (label_ref (match_operand 1 "" "")))]
""
"*
{
if (get_attr_op_type (insn) == OP_TYPE_RR)
return \"br\\t%0\";
else
return \"b\\t%a0\";
}"
[(set (attr "op_type")
(if_then_else (match_operand 0 "register_operand" "")
(const_string "RR") (const_string "RX")))
(set_attr "atype" "mem")])
(define_expand "casesi"
[(match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")
(label_ref (match_operand 3 "" ""))
(label_ref (match_operand 4 "" ""))]
""
"
{
if (flag_pic)
{
rtx base;
base = gen_rtx_REG (Pmode, BASE_REGISTER);
base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), 101);
operands[0] = gen_rtx_PLUS (Pmode, base, operands[0]);
}
rtx index = gen_reg_rtx (SImode);
rtx base = gen_reg_rtx (Pmode);
rtx target = gen_reg_rtx (Pmode);
emit_move_insn (index, operands[0]);
emit_insn (gen_subsi3 (index, index, operands[1]));
emit_cmp_and_jump_insns (index, operands[2], GTU, NULL_RTX, SImode, 1,
0, operands[4]);
if (Pmode != SImode)
index = convert_to_mode (Pmode, index, 1);
if (GET_CODE (index) != REG)
index = copy_to_mode_reg (Pmode, index);
if (TARGET_64BIT)
emit_insn (gen_ashldi3 (index, index, GEN_INT (3)));
else
emit_insn (gen_ashlsi3 (index, index, GEN_INT (2)));
emit_move_insn (base, gen_rtx_LABEL_REF (Pmode, operands[3]));
index = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, base, index));
emit_move_insn (target, index);
if (flag_pic)
target = gen_rtx_PLUS (Pmode, base, target);
emit_jump_insn (gen_casesi_jump (target, operands[3]));
DONE;
}")
(define_insn "*tablejump1"
[(set (pc) (match_operand 0 "register_operand" "a"))
(use (label_ref (match_operand 1 "" "")))]
""
"br\\t%0"
[(set_attr "op_type" "RX")])
(define_insn "*tablejump2"
[(set (pc) (match_operand 0 "address_operand" "p"))
(use (label_ref (match_operand 1 "" "")))]
""
"b\\t%a0"
[(set_attr "op_type" "RX")
(set_attr "atype" "mem")])
;;
;;- Jump to subroutine.
@ -5518,29 +5562,27 @@
""
"
{
emit_insn (gen_do_builtin_setjmp_setup (operands[0]));
rtx base = gen_rtx_MEM (Pmode, plus_constant (operands[0], 4 * GET_MODE_SIZE (Pmode)));
rtx basereg = gen_rtx_REG (Pmode, BASE_REGISTER);
emit_move_insn (base, basereg);
DONE;
}")
(define_expand "builtin_setjmp_receiver"
[(unspec_volatile [(label_ref (match_operand 0 "" ""))] 2)]
""
"flag_pic"
"
{
emit_insn (gen_blockage ());
rtx gotreg = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
rtx got = gen_rtx_SYMBOL_REF (Pmode, \"_GLOBAL_OFFSET_TABLE_\");
SYMBOL_REF_FLAG (got) = 1;
emit_move_insn (gotreg, got);
emit_insn (gen_rtx_USE (VOIDmode, gotreg));
DONE;
}")
(define_expand "do_builtin_setjmp_setup"
[(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "a")
(const_int 12)))
(reg:SI 12))
(set (mem:SI (plus:SI (match_dup 0)
(const_int 16)))
(reg:SI 13)) ]
""
"")
(define_expand "builtin_longjmp"
[(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)]
""
@ -5548,24 +5590,20 @@
{
/* The elements of the buffer are, in order: */
rtx fp = gen_rtx_MEM (Pmode, operands[0]);
rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 4));
rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 8));
rtx gotv = gen_rtx_MEM (Pmode, plus_constant (operands[0], 12));
rtx basev = gen_rtx_MEM (Pmode, plus_constant (operands[0], 16));
rtx base = gen_rtx_REG (Pmode, 13);
rtx got = gen_rtx_REG (Pmode, 12);
rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], GET_MODE_SIZE (Pmode)));
rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 2 * GET_MODE_SIZE (Pmode)));
rtx base = gen_rtx_MEM (Pmode, plus_constant (operands[0], 4 * GET_MODE_SIZE (Pmode)));
rtx basereg = gen_rtx_REG (Pmode, BASE_REGISTER);
rtx jmp = gen_rtx_REG (Pmode, 14);
emit_move_insn (jmp, lab);
emit_move_insn (got, gotv);
emit_move_insn (base, basev);
emit_move_insn (basereg, base);
emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
emit_move_insn (hard_frame_pointer_rtx, fp);
emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
emit_insn (gen_rtx_USE (VOIDmode, got));
emit_insn (gen_rtx_USE (VOIDmode, base));
emit_insn (gen_rtx_USE (VOIDmode, basereg));
emit_indirect_jump (jmp);
DONE;
}")