+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.
+/* 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
#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;
#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;
#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
+
/* 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.
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)
/* 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)
#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).
/* 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
1, 1, 1, 1, \
0, 0, 0, 0, \
0, 0, 0, 0, \
- 1 }
+ 1, 1 }
#endif
/* 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.
#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;
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
};
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. */
abort();
new = force_const_mem (SImode, orig);
- if (reg != 0)
- {
- emit_move_insn (reg, new);
- new = reg;
- }
}
/* Otherwise, compute the sum. */
}
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;
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;
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;
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);
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);
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;
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;
/* 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
{ "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")}, \
/* 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). */
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
(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)
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
/* 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.
{ 0x0000fffe, 0x00000001 }, /* ADDR_REGS */ \
{ 0x0000ffff, 0x00000001 }, /* GENERAL_REGS */ \
{ 0xffff0000, 0x00000000 }, /* FP_REGS */ \
- { 0x00000000, 0x00000002 }, /* CC_REGS */ \
{ 0xffffffff, 0x00000003 }, /* ALL_REGS */ \
}
#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. */
/* 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.
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.
;;- 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
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)));
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)));
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)));
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)));
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]));
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]));
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);
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);
(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")])
;;
(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")])
;;
;
(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 (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]);
- }
-}")
+ 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_insn "*tablejump1"
- [(set (pc) (match_operand 0 "register_operand" "a"))
- (use (label_ref (match_operand 1 "" "")))]
+(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 "" ""))]
""
- "br\\t%0"
- [(set_attr "op_type" "RX")])
+ "
+{
+ 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)));
-(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")])
+ 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;
+}")
;;
""
"
{
- 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)]
""
{
/* 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;
}")