diff options
author | Hans-Peter Nilsson <hp@axis.com> | 2005-03-03 03:53:29 +0000 |
---|---|---|
committer | Hans-Peter Nilsson <hp@gcc.gnu.org> | 2005-03-03 03:53:29 +0000 |
commit | f60c7155c144c7d4f6f321eeafe5773976f0528c (patch) | |
tree | 79941ea418e91490baa9e14c4e6d7c7af887ba8c /gcc/config/cris | |
parent | 768875a86fdf0a487ba662404e04f1898ce88c1e (diff) | |
download | gcc-f60c7155c144c7d4f6f321eeafe5773976f0528c.zip gcc-f60c7155c144c7d4f6f321eeafe5773976f0528c.tar.gz gcc-f60c7155c144c7d4f6f321eeafe5773976f0528c.tar.bz2 |
Describe special registers SRP and MOF as allocatable registers.
* config/cris/cris.c (cris_md_asm_clobbers): New function.
(TARGET_MD_ASM_CLOBBERS): Define to cris_md_asm_clobbers.
(cris_conditional_register_usage): Enable CRIS_MOF_REGNUM if
TARGET_HAS_MUL_INSNS.
(cris_print_operand) <case 'd'>: New case.
<case REG>: Allow CRIS_MOF_REGNUM and CRIS_SRP_REGNUM.
* config/cris/cris.h (CRIS_PC_REGNUM, CRIS_SRP_REGNUM): Don't
define.
(FIRST_PSEUDO_REGISTER, FIXED_REGISTERS, CALL_USED_REGISTERS)
(REG_ALLOC_ORDER): Update for MOF.
(enum reg_class): New members MOF_REGS, GENERAL_REGS and
SPECIAL_REGS.
(GENERAL_REGS): No longer a define of ALL_REGS.
(REGNO_REG_CLASS, REG_CLASS_CONTENTS, REG_CLASS_NAMES)
(PREFERRED_RELOAD_CLASS, REGISTER_NAMES, DBX_REGISTER_NUMBER):
Adjust accordingly.
(CRIS_SPECIAL_REGS_CONTENTS): New macro.
(REG_CLASS_FROM_LETTER): Allocate 'h' and 'x'.
(SECONDARY_RELOAD_CLASS): Define.
(STACK_POINTER_REGNUM): Define as CRIS_SP_REGNUM.
(FRAME_POINTER_REGNUM): Define as CRIS_FP_REGNUM.
(ARG_POINTER_REGNUM): Define as CRIS_AP_REGNUM.
(STATIC_CHAIN_REGNUM): Define as CRIS_STATIC_CHAIN_REGNUM.
(REGISTER_MOVE_COST): Define.
(PIC_OFFSET_TABLE_REGNUM): Define in terms of CRIS_GOT_REGNUM.
* config/cris/cris.md (CRIS_GOT_REGNUM, CRIS_STATIC_CHAIN_REGNUM)
(CRIS_FP_REGNUM, CRIS_SP_REGNUM, CRIS_SRP_REGNUM, CRIS_AP_REGNUM)
(CRIS_MOF_REGNUM): New define_constants.
("*movsi_internal", "movhi", "movqi", "movsf"): Add alternatives for
special registers.
("reload_inhi", "reload_outhi", "reload_inqi",
("umulhisi3", "umulqihi3", "mulsi3", "mulqihi3", "mulhisi3")
("mulsidi3", "umulsidi3", "smulsi3_highpart", "umulsi3_highpart"):
Adjust for MOF being properly described as a register.
(indir_to_reg_split): Name this split. Conditionalize on the
destination register being a general register.
(movei): Conditionalize on on operands 0 and 1 having the same
register class.
From-SVN: r95823
Diffstat (limited to 'gcc/config/cris')
-rw-r--r-- | gcc/config/cris/cris.c | 30 | ||||
-rw-r--r-- | gcc/config/cris/cris.h | 123 | ||||
-rw-r--r-- | gcc/config/cris/cris.md | 181 |
3 files changed, 251 insertions, 83 deletions
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c index e1b3a65..a4c61b4 100644 --- a/gcc/config/cris/cris.c +++ b/gcc/config/cris/cris.c @@ -125,6 +125,7 @@ static bool cris_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode, tree, bool); static int cris_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, tree, bool); +static tree cris_md_asm_clobbers (tree); /* This is the argument from the "-max-stack-stackframe=" option. */ const char *cris_max_stackframe_str; @@ -196,6 +197,8 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION; #define TARGET_PASS_BY_REFERENCE cris_pass_by_reference #undef TARGET_ARG_PARTIAL_BYTES #define TARGET_ARG_PARTIAL_BYTES cris_arg_partial_bytes +#undef TARGET_MD_ASM_CLOBBERS +#define TARGET_MD_ASM_CLOBBERS cris_md_asm_clobbers struct gcc_target targetm = TARGET_INITIALIZER; @@ -479,6 +482,9 @@ cris_conditional_register_usage (void) if (flag_pic) fixed_regs[PIC_OFFSET_TABLE_REGNUM] = call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; + + if (TARGET_HAS_MUL_INSNS) + fixed_regs[CRIS_MOF_REGNUM] = 0; } /* Return current_function_uses_pic_offset_table. For use in cris.md, @@ -1454,6 +1460,16 @@ cris_print_operand (FILE *file, rtx x, int code) fprintf (file, INTVAL (operand) < 0 ? "adds.w" : "addq"); return; + case 'd': + /* If this is a GOT symbol, print it as :GOT regardless of -fpic. */ + if (flag_pic && CONSTANT_P (operand) && cris_got_symbol (operand)) + { + cris_output_addr_const (file, operand); + fprintf (file, ":GOT"); + return; + } + break; + case 'D': /* When emitting an sub for the high part of a DImode constant, we want to use subq for 0 and subs.w for -1. */ @@ -1488,7 +1504,9 @@ cris_print_operand (FILE *file, rtx x, int code) switch (GET_CODE (operand)) { case REG: - if (REGNO (operand) > 15) + if (REGNO (operand) > 15 + && REGNO (operand) != CRIS_MOF_REGNUM + && REGNO (operand) != CRIS_SRP_REGNUM) internal_error ("internal error: bad register: %d", REGNO (operand)); fprintf (file, "$%s", reg_names[REGNO (operand)]); return; @@ -3039,6 +3057,16 @@ cris_arg_partial_bytes (CUMULATIVE_ARGS *ca, enum machine_mode mode, return 0; } +/* Worker function for TARGET_MD_ASM_CLOBBERS. */ + +static tree +cris_md_asm_clobbers (tree clobbers) +{ + return tree_cons (NULL_TREE, + build_string (strlen (reg_names[CRIS_MOF_REGNUM]), + reg_names[CRIS_MOF_REGNUM]), + clobbers); +} #if 0 /* Various small functions to replace macros. Only called from a diff --git a/gcc/config/cris/cris.h b/gcc/config/cris/cris.h index 50b81cf..f1dd5da 100644 --- a/gcc/config/cris/cris.h +++ b/gcc/config/cris/cris.h @@ -50,12 +50,10 @@ Boston, MA 02111-1307, USA. */ #define CRIS_FIRST_ARG_REG 10 #define CRIS_MAX_ARGS_IN_REGS 4 -/* Other convenience definitions. */ -#define CRIS_PC_REGNUM 15 -#define CRIS_SRP_REGNUM 16 +/* See also *_REGNUM constants in cris.md. */ /* Most of the time, we need the index into the register-names array. - When passing debug-info, we need the real register number. */ + When passing debug-info, we need the real hardware register number. */ #define CRIS_CANONICAL_SRP_REGNUM (16 + 11) #define CRIS_CANONICAL_MOF_REGNUM (16 + 7) @@ -602,9 +600,9 @@ extern int target_flags; /* Node: Register Basics */ -/* We count all 16 non-special registers, SRP and a faked argument - pointer register. */ -#define FIRST_PSEUDO_REGISTER (16 + 1 + 1) +/* We count all 16 non-special registers, SRP, a faked argument + pointer register and MOF. */ +#define FIRST_PSEUDO_REGISTER (16 + 1 + 1 + 1) /* For CRIS, these are r15 (pc) and r14 (sp). Register r8 is used as a frame-pointer, but is not fixed. SRP is not included in general @@ -612,12 +610,12 @@ extern int target_flags; registers are fixed at the moment. The faked argument pointer register is fixed too. */ #define FIXED_REGISTERS \ - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1} + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1} /* Register r9 is used for structure-address, r10-r13 for parameters, r10- for return values. */ #define CALL_USED_REGISTERS \ - {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1} + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1} #define CONDITIONAL_REGISTER_USAGE cris_conditional_register_usage () @@ -643,7 +641,7 @@ extern int target_flags; Use struct-return address first, since very few functions use structure return values so it is likely to be available. */ #define REG_ALLOC_ORDER \ - {9, 13, 12, 11, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17} + {9, 13, 12, 11, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15, 18, 16, 17} /* Node: Values in Registers */ @@ -674,27 +672,46 @@ extern int target_flags; class for special registers, and yet another class for the multiply-overflow register in v10; then a class for the return register also makes sense. */ -enum reg_class {NO_REGS, ALL_REGS, LIM_REG_CLASSES}; +enum reg_class + { + NO_REGS, + MOF_REGS, SPECIAL_REGS, GENERAL_REGS, ALL_REGS, + LIM_REG_CLASSES + }; #define N_REG_CLASSES (int) LIM_REG_CLASSES -#define REG_CLASS_NAMES {"NO_REGS", "ALL_REGS"} +#define REG_CLASS_NAMES \ + {"NO_REGS", "MOF_REGS", "SPECIAL_REGS", "GENERAL_REGS", "ALL_REGS"} -#define GENERAL_REGS ALL_REGS +#define CRIS_SPECIAL_REGS_CONTENTS \ + ((1 << CRIS_SRP_REGNUM) | (1 << CRIS_MOF_REGNUM)) /* Count in the faked argument register in GENERAL_REGS. Keep out SRP. */ -#define REG_CLASS_CONTENTS {{0}, {0x2ffff}} - -#define REGNO_REG_CLASS(REGNO) GENERAL_REGS +#define REG_CLASS_CONTENTS \ + { \ + {0}, \ + {1 << CRIS_MOF_REGNUM}, \ + {CRIS_SPECIAL_REGS_CONTENTS}, \ + {0x2ffff}, \ + {0x2ffff | CRIS_SPECIAL_REGS_CONTENTS} \ + } + +#define REGNO_REG_CLASS(REGNO) \ + ((REGNO) == CRIS_MOF_REGNUM ? MOF_REGS : \ + (REGNO) == CRIS_SRP_REGNUM ? SPECIAL_REGS : \ + GENERAL_REGS) #define BASE_REG_CLASS GENERAL_REGS #define INDEX_REG_CLASS GENERAL_REGS -/* Get reg_class from a letter such as appears in the machine - description. No letters are used, since 'r' is used for any - register. */ -#define REG_CLASS_FROM_LETTER(C) NO_REGS +#define REG_CLASS_FROM_LETTER(C) \ + ( \ + (C) == 'h' ? MOF_REGS : \ + (C) == 'x' ? SPECIAL_REGS : \ + NO_REGS \ + ) /* Since it uses reg_renumber, it is safe only once reg_renumber has been allocated, which happens in local-alloc.c. */ @@ -710,9 +727,23 @@ enum reg_class {NO_REGS, ALL_REGS, LIM_REG_CLASSES}; /* It seems like gcc (2.7.2 and 2.9x of 2000-03-22) may send "NO_REGS" as the class for a constant (testcase: __Mul in arit.c). To avoid forcing out a constant into the constant pool, we will trap this case and - return something a bit more sane. FIXME: Check if this is a bug. */ -#define PREFERRED_RELOAD_CLASS(X, CLASS) \ - ((CLASS) == NO_REGS ? GENERAL_REGS : (CLASS)) + return something a bit more sane. FIXME: Check if this is a bug. + Beware that we must not "override" classes that can be specified as + constraint letters, or else asm operands using them will fail when + they need to be reloaded. FIXME: Investigate whether that constitutes + a bug. */ +#define PREFERRED_RELOAD_CLASS(X, CLASS) \ + ((CLASS) != MOF_REGS \ + && (CLASS) != SPECIAL_REGS \ + ? GENERAL_REGS : (CLASS)) + +/* We can't move special registers to and from memory in smaller than + word_mode. */ +#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) \ + (((CLASS) != SPECIAL_REGS && (CLASS) != MOF_REGS) \ + || GET_MODE_SIZE (MODE) == 4 \ + || GET_CODE (X) != MEM \ + ? NO_REGS : GENERAL_REGS) /* For CRIS, this is always the size of MODE in words, since all registers are the same size. To use omitted modes in @@ -884,17 +915,17 @@ enum reg_class {NO_REGS, ALL_REGS, LIM_REG_CLASSES}; /* Node: Frame Registers */ -#define STACK_POINTER_REGNUM 14 +#define STACK_POINTER_REGNUM CRIS_SP_REGNUM /* Register used for frame pointer. This is also the last of the saved registers, when a frame pointer is not used. */ -#define FRAME_POINTER_REGNUM 8 +#define FRAME_POINTER_REGNUM CRIS_FP_REGNUM /* Faked register, is always eliminated. We need it to eliminate allocating stack slots for the return address and the frame pointer. */ -#define ARG_POINTER_REGNUM 17 +#define ARG_POINTER_REGNUM CRIS_AP_REGNUM -#define STATIC_CHAIN_REGNUM 7 +#define STATIC_CHAIN_REGNUM CRIS_STATIC_CHAIN_REGNUM /* Node: Elimination */ @@ -1288,8 +1319,32 @@ struct cum_args {int regs;}; /* Node: Costs */ -/* FIXME: Need to define REGISTER_MOVE_COST when more register classes are - introduced. */ +/* Can't move to and from a SPECIAL_REGS register, so we have to say + their move cost within that class is higher. How about 7? That's 3 + for a move to a GENERAL_REGS register, 3 for the move from the + GENERAL_REGS register, and 1 for the increased register pressure. + Also, it's higher than the memory move cost, which is in order. + We also do this for ALL_REGS, since we don't want that class to be + preferred (even to memory) at all where GENERAL_REGS doesn't fit. + Whenever it's about to be used, it's for SPECIAL_REGS. If we don't + present a higher cost for ALL_REGS than memory, a SPECIAL_REGS may be + used when a GENERAL_REGS should be used, even if there are call-saved + GENERAL_REGS left to allocate. This is because the fall-back when + the most preferred register class isn't available, isn't the next + (or next good) wider register class, but the *most widest* register + class. + Give the cost 3 between a special register and a general register, + because we want constraints verified. */ + +#define REGISTER_MOVE_COST(MODE, FROM, TO) \ + ((((FROM) == SPECIAL_REGS || (FROM) == MOF_REGS) \ + && ((TO) == SPECIAL_REGS || (TO) == MOF_REGS)) \ + || (FROM) == ALL_REGS \ + || (TO) == ALL_REGS \ + ? 7 : \ + ((FROM) == SPECIAL_REGS || (FROM) == MOF_REGS \ + || (TO) == SPECIAL_REGS || (TO) == MOF_REGS) \ + ? 3 : 2) /* This isn't strictly correct for v0..3 in buswidth-8bit mode, but should suffice. */ @@ -1323,7 +1378,7 @@ struct cum_args {int regs;}; /* Node: PIC */ -#define PIC_OFFSET_TABLE_REGNUM (flag_pic ? 0 : INVALID_REGNUM) +#define PIC_OFFSET_TABLE_REGNUM (flag_pic ? CRIS_GOT_REGNUM : INVALID_REGNUM) #define LEGITIMATE_PIC_OPERAND_P(X) cris_legitimate_pic_operand (X) @@ -1439,7 +1494,7 @@ struct cum_args {int regs;}; #define REGISTER_NAMES \ {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", \ - "r9", "r10", "r11", "r12", "r13", "sp", "pc", "srp", "faked_ap"} + "r9", "r10", "r11", "r12", "r13", "sp", "pc", "srp", "faked_ap", "mof"} #define ADDITIONAL_REGISTER_NAMES \ {{"r14", 14}, {"r15", 15}} @@ -1525,8 +1580,10 @@ struct cum_args {int regs;}; /* Node: All Debuggers */ -#define DBX_REGISTER_NUMBER(REGNO) \ - ((REGNO) == CRIS_SRP_REGNUM ? CRIS_CANONICAL_SRP_REGNUM : (REGNO)) +#define DBX_REGISTER_NUMBER(REGNO) \ + ((REGNO) == CRIS_SRP_REGNUM ? CRIS_CANONICAL_SRP_REGNUM : \ + (REGNO) == CRIS_MOF_REGNUM ? CRIS_CANONICAL_MOF_REGNUM : \ + (REGNO)) /* FIXME: Investigate DEBUGGER_AUTO_OFFSET, DEBUGGER_ARG_OFFSET. */ diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md index 11d0de4..0a9d419 100644 --- a/gcc/config/cris/cris.md +++ b/gcc/config/cris/cris.md @@ -59,6 +59,18 @@ ;; 0 PLT reference from call expansion: operand 0 is the address, ;; the mode is VOIDmode. Always wrapped in CONST. + +;; Register numbers. +(define_constants + [(CRIS_GOT_REGNUM 0) + (CRIS_STATIC_CHAIN_REGNUM 7) + (CRIS_FP_REGNUM 8) + (CRIS_SP_REGNUM 14) + (CRIS_SRP_REGNUM 16) + (CRIS_AP_REGNUM 17) + (CRIS_MOF_REGNUM 18)] +) + ;; We need an attribute to define whether an instruction can be put in ;; a branch-delay slot or not, and whether it has a delay slot. ;; @@ -994,11 +1006,11 @@ (define_insn "*movsi_internal" [(set - (match_operand:SI 0 "nonimmediate_operand" "=r,r, r,Q>,r,Q>,g,r,r,r,g") + (match_operand:SI 0 "nonimmediate_operand" "=r,r, r,Q>,r,Q>,g,r,r, r,g,rQ>,x, m,x") (match_operand:SI 1 ;; FIXME: We want to put S last, but apparently g matches S. ;; It's a bug: an S is not a general_operand and shouldn't match g. - "cris_general_operand_or_gotless_symbol" "r,Q>,M,M, I,r, M,n,!S,g,r"))] + "cris_general_operand_or_gotless_symbol" "r,Q>,M,M, I,r, M,n,!S,g,r,x, rQ>,x,gi"))] "" "* { @@ -1014,6 +1026,12 @@ case 10: return \"move.d %1,%0\"; + case 11: + case 12: + case 13: + case 14: + return \"move %d1,%0\"; + case 2: case 3: case 6: @@ -1059,7 +1077,8 @@ return \"BOGUS: %1 to %0\"; } }" - [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,no,no,no")]) + [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,no,no,no,yes,yes,no,no") + (set_attr "cc" "*,*,*,*,*,*,*,*,*,*,*,none,none,none,none")]) ;; Extend operations with side-effect from mem to register, using ;; MOVS/MOVU. These are from mem to register only. @@ -1207,8 +1226,8 @@ (define_insn "movhi" [(set - (match_operand:HI 0 "nonimmediate_operand" "=r,r, r,Q>,r,Q>,r,r,r,g,g,r") - (match_operand:HI 1 "general_operand" "r,Q>,M,M, I,r, L,O,n,M,r,g"))] + (match_operand:HI 0 "nonimmediate_operand" "=r,r, r,Q>,r,Q>,r,r,r,g,g,r,r,x") + (match_operand:HI 1 "general_operand" "r,Q>,M,M, I,r, L,O,n,M,r,g,x,r"))] "" "* { @@ -1220,6 +1239,9 @@ case 10: case 11: return \"move.w %1,%0\"; + case 12: + case 13: + return \"move %1,%0\"; case 2: case 3: case 9: @@ -1241,11 +1263,8 @@ return \"BOGUS: %1 to %0\"; } }" - [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,yes,no,no,no,no") - (set (attr "cc") - (if_then_else (eq_attr "alternative" "7") - (const_string "clobber") - (const_string "normal")))]) + [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,yes,no,no,no,no,yes,yes") + (set_attr "cc" "*,*,none,none,*,none,*,clobber,*,none,none,*,none,none")]) (define_insn "movstricthi" [(set @@ -1263,10 +1282,26 @@ move.w %1,%0 move.w %1,%0" [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no")]) + +(define_expand "reload_inhi" + [(set (match_operand:HI 2 "register_operand" "=r") + (match_operand:HI 1 "memory_operand" "m")) + (set (match_operand:HI 0 "register_operand" "=x") + (match_dup 2))] + "" + "") + +(define_expand "reload_outhi" + [(set (match_operand:HI 2 "register_operand" "=r") + (match_operand:HI 1 "register_operand" "x")) + (set (match_operand:HI 0 "memory_operand" "=m") + (match_dup 2))] + "" + "") (define_insn "movqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=r,Q>,r, r,Q>,r,g,g,r,r") - (match_operand:QI 1 "general_operand" "r,r, Q>,M,M, I,M,r,O,g"))] + [(set (match_operand:QI 0 "nonimmediate_operand" "=r,Q>,r, r,Q>,r,g,g,r,r,r,x") + (match_operand:QI 1 "general_operand" "r,r, Q>,M,M, I,M,r,O,g,x,r"))] "" "@ move.b %1,%0 @@ -1278,12 +1313,11 @@ clear.b %0 move.b %1,%0 moveq %b1,%0 - move.b %1,%0" - [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,yes,no") - (set (attr "cc") - (if_then_else (eq_attr "alternative" "8") - (const_string "clobber") - (const_string "normal")))]) + move.b %1,%0 + move %1,%0 + move %1,%0" + [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,yes,no,yes,yes") + (set_attr "cc" "*,*,*,*,*,*,*,*,clobber,*,none,none")]) (define_insn "movstrictqi" [(set (strict_low_part @@ -1301,14 +1335,30 @@ move.b %1,%0" [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no")]) +(define_expand "reload_inqi" + [(set (match_operand:QI 2 "register_operand" "=r") + (match_operand:QI 1 "memory_operand" "m")) + (set (match_operand:QI 0 "register_operand" "=x") + (match_dup 2))] + "" + "") + +(define_expand "reload_outqi" + [(set (match_operand:QI 2 "register_operand" "=r") + (match_operand:QI 1 "register_operand" "x")) + (set (match_operand:QI 0 "memory_operand" "=m") + (match_dup 2))] + "" + "") + ;; The valid "quick" bit-patterns are, except for 0.0, denormalized ;; values REALLY close to 0, and some NaN:s (I think; their exponent is ;; all ones); the worthwhile one is "0.0". ;; It will use clear, so we know ALL types of immediate 0 never change cc. (define_insn "movsf" - [(set (match_operand:SF 0 "nonimmediate_operand" "=r,Q>,r, r,Q>,g,g,r") - (match_operand:SF 1 "general_operand" "r,r, Q>,G,G, G,r,g"))] + [(set (match_operand:SF 0 "nonimmediate_operand" "=r,Q>,r, r,Q>,g,g,r,r,x,Q>,m,x, x") + (match_operand:SF 1 "general_operand" "r,r, Q>,G,G, G,r,g,x,r,x, x,Q>,g"))] "" "@ move.d %1,%0 @@ -1318,8 +1368,14 @@ clear.d %0 clear.d %0 move.d %1,%0 - move.d %1,%0" - [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no")]) + move.d %1,%0 + move %1,%0 + move %1,%0 + move %1,%0 + move %1,%0 + move %1,%0 + move %1,%0" + [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no,yes,yes,yes,no,yes,no")]) ;; Sign- and zero-extend insns with standard names. @@ -2472,7 +2528,8 @@ [(set (match_operand:SI 0 "register_operand" "=r") (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0")) - (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))] + (zero_extend:SI (match_operand:HI 2 "register_operand" "r")))) + (clobber (match_scratch:SI 3 "=h"))] "TARGET_HAS_MUL_INSNS" "%!mulu.w %2,%0" [(set (attr "slottable") @@ -2486,7 +2543,8 @@ [(set (match_operand:HI 0 "register_operand" "=r") (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%0")) - (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))] + (zero_extend:HI (match_operand:QI 2 "register_operand" "r")))) + (clobber (match_scratch:SI 3 "=h"))] "TARGET_HAS_MUL_INSNS" "%!mulu.b %2,%0" [(set (attr "slottable") @@ -2505,7 +2563,8 @@ (define_insn "mulsi3" [(set (match_operand:SI 0 "register_operand" "=r") (mult:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "register_operand" "r")))] + (match_operand:SI 2 "register_operand" "r"))) + (clobber (match_scratch:SI 3 "=h"))] "TARGET_HAS_MUL_INSNS" "%!muls.d %2,%0" [(set (attr "slottable") @@ -2523,7 +2582,8 @@ [(set (match_operand:HI 0 "register_operand" "=r") (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0")) - (sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))] + (sign_extend:HI (match_operand:QI 2 "register_operand" "r")))) + (clobber (match_scratch:SI 3 "=h"))] "TARGET_HAS_MUL_INSNS" "%!muls.b %2,%0" [(set (attr "slottable") @@ -2536,7 +2596,8 @@ [(set (match_operand:SI 0 "register_operand" "=r") (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0")) - (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))] + (sign_extend:SI (match_operand:HI 2 "register_operand" "r")))) + (clobber (match_scratch:SI 3 "=h"))] "TARGET_HAS_MUL_INSNS" "%!muls.w %2,%0" [(set (attr "slottable") @@ -2556,7 +2617,8 @@ [(set (match_operand:DI 0 "register_operand" "=r") (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0")) - (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))] + (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))) + (clobber (match_scratch:SI 3 "=h"))] "TARGET_HAS_MUL_INSNS" "%!muls.d %2,%M0\;move $mof,%H0") @@ -2564,42 +2626,60 @@ [(set (match_operand:DI 0 "register_operand" "=r") (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) - (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))] + (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))) + (clobber (match_scratch:SI 3 "=h"))] "TARGET_HAS_MUL_INSNS" "%!mulu.d %2,%M0\;move $mof,%H0") -;; This pattern would probably not be needed if we add "mof" in its own -;; register class (and open a can of worms about /not/ pairing it with a -;; "normal" register). Having multiple register classes here, and -;; applicable to the v10 variant only, seems worse than having these two -;; patterns with multi-insn contents for now (may change; having a free -;; call-clobbered register is worth some trouble). +;; These two patterns may be expressible by other means, perhaps by making +;; [u]?mulsidi3 a define_expand. + +;; Due to register allocation braindamage, the clobber 1,2 alternatives +;; cause a move into the clobbered register *before* the insn, then +;; after the insn, mof is moved too, rather than the clobber assigned +;; the last mof target. This became apparent when making MOF and SRP +;; visible registers, with the necessary tweak to smulsi3_highpart. +;; Because these patterns are used in division by constants, that damage +;; is visible (ipps regression tests). Therefore the last two +;; alternatives, "helping" reload to avoid an unnecessary move, but +;; punished by force of one "?". Check code from "int d (int a) {return +;; a / 1000;}" and unsigned. FIXME: Comment above was for 3.2, revisit. (define_insn "smulsi3_highpart" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m") + [(set (match_operand:SI 0 "nonimmediate_operand" "=h,h,?r,?r") (truncate:SI (lshiftrt:DI (mult:DI - (sign_extend:DI (match_operand:SI 1 "register_operand" "%0,r,r")) - (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r,r"))) + (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r,0,r")) + (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r,r,0"))) (const_int 32)))) - (clobber (match_scratch:SI 3 "=X,1,1"))] + (clobber (match_scratch:SI 3 "=1,2,h,h"))] "TARGET_HAS_MUL_INSNS" - "%!muls.d %2,%1\;move $mof,%0" - [(set_attr "cc" "clobber")]) + "@ + %!muls.d %2,%1 + .error 'untested assembly generated by GCC (smulsi3_highpart): muls.d %1,%2' + %!muls.d %2,%1\;move $mof,%0 + %!muls.d %1,%2\;move $mof,%0" + [(set_attr "slottable" "yes,yes,no,no") + (set_attr "cc" "clobber")]) (define_insn "umulsi3_highpart" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m") + [(set (match_operand:SI 0 "register_operand" "=h,h,?r,?r") (truncate:SI (lshiftrt:DI (mult:DI - (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,r,r")) - (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r,r"))) + (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r,0,r")) + (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r,r,0"))) (const_int 32)))) - (clobber (match_scratch:SI 3 "=X,1,1"))] + (clobber (match_scratch:SI 3 "=1,2,h,h"))] "TARGET_HAS_MUL_INSNS" - "%!mulu.d %2,%1\;move $mof,%0" - [(set_attr "cc" "clobber")]) + "@ + %!mulu.d %2,%1 + .error 'untested assembly generated by GCC (umulsi3_highpart): mulu.d %1,%2' + %!mulu.d %2,%1\;move $mof,%0 + %!mulu.d %1,%2\;move $mof,%0" + [(set_attr "slottable" "yes,yes,no,no") + (set_attr "cc" "clobber")]) ;; Divide and modulus instructions. CRIS only has a step instruction. @@ -4651,14 +4731,15 @@ ;; 2001-08-24, unwind-dw2-fde.c, _Unwind_Find_FDE ICE in ;; cselib_invalidate_regno. -(define_split +(define_split ; indir_to_reg_split [(set (match_operand 0 "register_operand" "") (match_operand 1 "indirect_operand" ""))] "reload_completed && REG_P (operands[0]) && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD && (GET_CODE (XEXP (operands[1], 0)) == MEM - || CONSTANT_P (XEXP (operands[1], 0)))" + || CONSTANT_P (XEXP (operands[1], 0))) + && REGNO (operands[0]) < CRIS_LAST_GENERAL_REGISTER" [(set (match_dup 2) (match_dup 4)) (set (match_dup 0) (match_dup 3))] "operands[2] = gen_rtx_REG (Pmode, REGNO (operands[0])); @@ -4993,6 +5074,8 @@ (set (match_operand 2 "register_operand" "") (match_operator 3 "cris_mem_op" [(match_dup 0)]))] "REGNO (operands[0]) == REGNO (operands[2]) + && (REGNO_REG_CLASS (REGNO (operands[0])) + == REGNO_REG_CLASS (REGNO (operands[1]))) && GET_MODE_SIZE (GET_MODE (operands[2])) <= UNITS_PER_WORD" [(set (match_dup 2) (match_dup 4))] "operands[4] = replace_equiv_address (operands[3], operands[1]);") |