From: uweigand Date: Sat, 11 Aug 2001 20:56:12 +0000 (+0000) Subject: Bring s390 backend back in sync with branch. X-Git-Tag: upstream/4.9.2~92699 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0c0a8ea5779b4c9790babb851705f4ba0ffd96de;p=platform%2Fupstream%2Flinaro-gcc.git Bring s390 backend back in sync with branch. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@44810 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 77f37b0..18244a1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,51 @@ +2001-08-11 Ulrich Weigand + + * 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 * rtl.h (REG_EH_RETHROW): Remove. diff --git a/gcc/config/s390/fixdfdi.h b/gcc/config/s390/fixdfdi.h index 3e1ad49..4f1fb35 100644 --- a/gcc/config/s390/fixdfdi.h +++ b/gcc/config/s390/fixdfdi.h @@ -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 + diff --git a/gcc/config/s390/linux.h b/gcc/config/s390/linux.h index 36ae80d..0e5d179 100644 --- a/gcc/config/s390/linux.h +++ b/gcc/config/s390/linux.h @@ -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). diff --git a/gcc/config/s390/linux64.h b/gcc/config/s390/linux64.h index ab518c2..36fa1c7 100644 --- a/gcc/config/s390/linux64.h +++ b/gcc/config/s390/linux64.h @@ -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 diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index c80dc2a..33307a8 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -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; diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 8cb03e8..fb98ba8 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -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. diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 5c6b183..31a5097 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -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,53 +5182,79 @@ ; (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; +}") ;; @@ -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; }")