From: Michael Hayes Date: Sun, 24 Jan 1999 01:52:01 +0000 (+0000) Subject: Convert all direct memory references to use LO_SUM and remove machdep hack that used... X-Git-Tag: prereleases/libgcj-0.1~1190 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=50c3308739f502960f3c39ce00fcaac47cd6d391;p=thirdparty%2Fgcc.git Convert all direct memory references to use LO_SUM and remove machdep hack that used to do this. Convert all direct memory references to use LO_SUM and remove machdep hack that used to do this. Sun Jan 24 21:24:43 1999 Michael Hayes * config/c4x/c4x.c (c4x_emit_move_sequence, c4x_encode_section_info): New functions. (c4x_check_legit_addr): Remove USE and PLUS, allow LO_SUM, and disable SYMBOL_REF, LABEL_REF, and CONST cases. (c4x_legitimize_address): Penalise SYMBOL_REF, LABEL_REF, and CONST cases. Add LO_SUM. (c4x_print_operand): Modified 'C' and 'R' cases for calls. Added 'U' case. Remove dependence on SYMBOL_REF_FLAG. (c4x_print_operand_address): Handle LO_SUM. (c4x_scan_for_ldp): Delete. Hooray! (c4x_process_after_reload): Remove call to c4x_scan_for_ldp. Split all insns. (c4x_immed_int_constant): Renamed from c4x_int_constant. All callers changed. (c4x_immed_float_constant): Renamed from c4x_float_constant. All callers changed. (c4x_T_constraint): Allow LO_SUM, disable SYMBOL_REF, LABEL_REF, and CONST. (c4x_U_constraint, symbolic_operand): New functions. (src_operand): Allow 'I' constants in HImode. Allow LO_SUM, disable SYMBOL_REF, LABEL_REF, and CONST. (lsrc_operand, tsrc_operand): Call src_operand instead of general_operand. (c4x_operand_subword): Update comments. * config/c4x/c4x.c (TARGET_LOAD_ADDRESS): New macro. (LEGITIMATE_CONSTANT_P): Allow SYMBOL_REF, LABEL_REF, CONST, plus HIGH and LO_SUM for the C40. (ENCODE_SECTION_INFO): Define macro. (symbolic_operand, c4x_U_constraint, c4x_emit_move_sequence): New prototypes. (PREDICATE_CODES): Add symbolic_operand. * config/c4x/c4x.md (movqi, movgqf, movhi, movhi): Call c4x_emit_move_sequence. (floatunsqiqf2, fixuns_truncqfqi2): Rework emitted RTL to avoid symbol references. (all patterns with g constraint): Replace 'g' constraint with 'rIm'. (set_high): Renamed from set_high_use. (set_lo_sum): Renamed from set_ior_lo_use. (all call patterns): Make MEM explicit in call address operands. Modified output templates to use 'U' modifier. From-SVN: r24842 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 694d804e80a2..776dcdb0742a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,48 @@ +Sun Jan 24 21:24:43 1999 Michael Hayes + + * config/c4x/c4x.c (c4x_emit_move_sequence, c4x_encode_section_info): + New functions. + (c4x_check_legit_addr): Remove USE and PLUS, allow + LO_SUM, and disable SYMBOL_REF, LABEL_REF, and CONST cases. + (c4x_legitimize_address): Penalise SYMBOL_REF, LABEL_REF, and + CONST cases. Add LO_SUM. + (c4x_print_operand): Modified 'C' and 'R' cases for calls. + Added 'U' case. Remove dependence on SYMBOL_REF_FLAG. + (c4x_print_operand_address): Handle LO_SUM. + (c4x_scan_for_ldp): Delete. Hooray! + (c4x_process_after_reload): Remove call to c4x_scan_for_ldp. + Split all insns. + (c4x_immed_int_constant): Renamed from c4x_int_constant. All callers + changed. + (c4x_immed_float_constant): Renamed from c4x_float_constant. All + callers changed. + (c4x_T_constraint): Allow LO_SUM, disable SYMBOL_REF, LABEL_REF, + and CONST. + (c4x_U_constraint, symbolic_operand): New functions. + (src_operand): Allow 'I' constants in HImode. Allow LO_SUM, + disable SYMBOL_REF, LABEL_REF, and CONST. + (lsrc_operand, tsrc_operand): Call src_operand instead of + general_operand. + (c4x_operand_subword): Update comments. + + * config/c4x/c4x.c (TARGET_LOAD_ADDRESS): New macro. + (LEGITIMATE_CONSTANT_P): Allow SYMBOL_REF, LABEL_REF, CONST, + plus HIGH and LO_SUM for the C40. + (ENCODE_SECTION_INFO): Define macro. + (symbolic_operand, c4x_U_constraint, c4x_emit_move_sequence): New + prototypes. + (PREDICATE_CODES): Add symbolic_operand. + + * config/c4x/c4x.md (movqi, movgqf, movhi, movhi): Call + c4x_emit_move_sequence. + (floatunsqiqf2, fixuns_truncqfqi2): Rework emitted RTL + to avoid symbol references. + (all patterns with g constraint): Replace 'g' constraint with 'rIm'. + (set_high): Renamed from set_high_use. + (set_lo_sum): Renamed from set_ior_lo_use. + (all call patterns): Make MEM explicit in call address operands. + Modified output templates to use 'U' modifier. + Sun Jan 24 01:15:05 PST 1999 Jeff Law (law@cygnus.com) * version.c: Bump for snapshot. diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c index f5c6fc2aad14..2e4b941136eb 100644 --- a/gcc/config/c4x/c4x.c +++ b/gcc/config/c4x/c4x.c @@ -1016,6 +1016,84 @@ c4x_null_epilogue_p () } +int +c4x_emit_move_sequence (operands, mode) + rtx *operands; + enum machine_mode mode; +{ + rtx op0 = operands[0]; + rtx op1 = operands[1]; + + if (! reload_in_progress + && ! REG_P (op0) + && ! REG_P (op1) + && ! (stik_const_operand (op1, mode) && ! push_operand (op0, mode))) + op1 = force_reg (mode, op1); + + if (symbolic_operand (op1, mode)) + { + if (TARGET_LOAD_ADDRESS) + { + /* Alias analysis seems to do a better job if we force + constant addresses to memory after reload. */ + emit_insn (gen_load_immed_address (op0, op1)); + return 1; + } + else + { + /* Stick symbol or label address into the constant pool. */ + op1 = force_const_mem (Pmode, op1); + } + } + else if (mode == HFmode && CONSTANT_P (op1) && ! LEGITIMATE_CONSTANT_P (op1)) + { + /* We could be a lot smarter about loading some of these + constants... */ + op1 = force_const_mem (mode, op1); + } + else if (mode == HImode && CONSTANT_P (op1) && ! LEGITIMATE_CONSTANT_P (op1)) + { + /* We could load all sorts of constants in two goes by pulling all + sorts of tricks... The tricky thing is that we cannot clobber CC + so that stifles most of the obvious methods. */ + op1 = force_const_mem (mode, op1); + } + + /* Convert (MEM (SYMREF)) to a (MEM (LO_SUM (REG) (SYMREF))) + and emit associated (HIGH (SYMREF)) if large memory model. + c4x_legitimize_address could be used to do this, + perhaps by calling validize_address. */ + if (! (reload_in_progress || reload_completed) + && GET_CODE (op1) == MEM + && symbolic_operand (XEXP (op1, 0), Pmode)) + { + rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); + if (! TARGET_SMALL) + emit_insn (gen_set_ldp (dp_reg, XEXP (op1, 0))); + op1 = change_address (op1, mode, + gen_rtx_LO_SUM (Pmode, dp_reg, XEXP (op1, 0))); + } + + if (! (reload_in_progress || reload_completed) + && GET_CODE (op0) == MEM + && symbolic_operand (XEXP (op0, 0), Pmode)) + { + rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); + if (! TARGET_SMALL) + emit_insn (gen_set_ldp (dp_reg, XEXP (op0, 0))); + op0 = change_address (op0, mode, + gen_rtx_LO_SUM (Pmode, dp_reg, XEXP (op0, 0))); + } + + /* Adjust operands in case we have modified them. */ + operands[0] = op0; + operands[1] = op1; + + /* Emit normal pattern. */ + return 0; +} + + void c4x_emit_libcall (name, code, dmode, smode, noperands, operands) char *name; @@ -1066,6 +1144,7 @@ c4x_emit_libcall3 (name, code, mode, operands) return c4x_emit_libcall (name, code, mode, mode, 3, operands); } + void c4x_emit_libcall_mulhi (name, code, mode, operands) char *name; @@ -1096,7 +1175,7 @@ c4x_emit_libcall_mulhi (name, code, mode, operands) enum reg_class c4x_preferred_reload_class (x, class) - rtx x; + rtx x ATTRIBUTE_UNUSED; enum reg_class class; { return class; @@ -1122,6 +1201,22 @@ c4x_secondary_memory_needed (class1, class2, mode) } +/* Set the SYMBOL_REF_FLAG for a function decl. However, wo do not + yet use this info. */ +void +c4x_encode_section_info (decl) + tree decl; +{ +#if 0 + if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE) + SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1; +#else + if (TREE_CODE (decl) == FUNCTION_DECL) + SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1; +#endif +} + + int c4x_check_legit_addr (mode, addr, strict) enum machine_mode mode; @@ -1187,19 +1282,6 @@ c4x_check_legit_addr (mode, addr, strict) switch (code0) { - case USE: - /* The uses are put in to avoid problems - with referenced things disappearing. */ - return c4x_check_legit_addr (mode, op1, strict); - - case PLUS: - /* This is another reference to keep things - from disappearing, but it contains a plus - of a use and DP. */ - if (GET_CODE (XEXP (op0, 0)) == USE) - return c4x_check_legit_addr (mode, op1, strict); - return 0; - case REG: if (REG_P (op1)) { @@ -1224,18 +1306,47 @@ c4x_check_legit_addr (mode, addr, strict) } break; + /* Direct addressing with DP register. */ + case LO_SUM: + { + rtx op0 = XEXP (addr, 0); + rtx op1 = XEXP (addr, 1); + + /* HImode and HFmode direct memory references aren't truly + offsettable (consider case at end of data page). We + probably get better code by loading a pointer and using an + indirect memory reference. */ + if (mode == HImode || mode == HFmode) + return 0; + + if (!REG_P (op0) || REGNO (op0) != DP_REGNO) + return 0; + + if ((GET_CODE (op1) == SYMBOL_REF || GET_CODE (op1) == LABEL_REF)) + return 1; + + if (GET_CODE (op1) == CONST) + { + addr = XEXP (op1, 0); + + if (GET_CODE (addr) == PLUS + && (GET_CODE (XEXP (addr, 0)) == SYMBOL_REF + || GET_CODE (XEXP (addr, 0)) == LABEL_REF) + && GET_CODE (XEXP (addr, 1)) == CONST_INT) + return 1; + } + return 0; + } + break; + /* Direct addressing with some work for the assembler... */ case CONST: - if (GET_CODE (XEXP (addr, 0)) == PLUS - && (GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF - || GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF) - && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT) - return 1; - /* Direct addressing. */ - case SYMBOL_REF: case LABEL_REF: - return 1; + case SYMBOL_REF: + /* These need to be converted to a LO_SUM (...). + c4x_legitimize_address will fix them up. */ + return 0; /* Do not allow direct memory access to absolute addresses. This is more pain than its worth, especially for the @@ -1313,6 +1424,16 @@ c4x_legitimize_address (orig, mode) rtx orig ATTRIBUTE_UNUSED; enum machine_mode mode ATTRIBUTE_UNUSED; { + if (GET_CODE (orig) == SYMBOL_REF) + { + rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); + + if (! TARGET_SMALL) + emit_insn (gen_set_ldp (dp_reg, orig)); + + return gen_rtx_LO_SUM (Pmode, dp_reg, orig); + } + return NULL_RTX; } @@ -1332,32 +1453,46 @@ rtx addr; case REG: return 1; - case CONST: - { - rtx offset = const0_rtx; - addr = eliminate_constant_term (addr, &offset); - - if (GET_CODE (addr) == LABEL_REF) - return 3; - - if (GET_CODE (addr) != SYMBOL_REF) - return 4; - - if (INTVAL (offset) == 0) - return 3; - } - - /* fall through */ - case POST_INC: case POST_DEC: case PRE_INC: case PRE_DEC: return 1; + /* These shouldn't be directly generated. */ case SYMBOL_REF: case LABEL_REF: - return TARGET_SMALL ? 3 : 4; + case CONST: + return 10; + + case LO_SUM: + { + rtx op1 = XEXP (addr, 1); + + if (GET_CODE (op1) == LABEL_REF || GET_CODE (op1) == SYMBOL_REF) + return TARGET_SMALL ? 3 : 4; + + if (GET_CODE (op1) == CONST) + { + rtx offset = const0_rtx; + + op1 = eliminate_constant_term (op1, &offset); + + /* ??? These costs need rethinking... */ + if (GET_CODE (op1) == LABEL_REF) + return 3; + + if (GET_CODE (op1) != SYMBOL_REF) + return 4; + + if (INTVAL (offset) == 0) + return 3; + + return 4; + } + fatal_insn ("c4x_address_cost: Invalid addressing mode", addr); + } + break; case PLUS: { @@ -1479,18 +1614,9 @@ c4x_print_operand (file, op, letter) asm_fprintf (file, "@"); break; - case 'C': /* call */ - if (code != MEM) - fatal_insn ("c4x_print_operand: %%C inconsistency", op); - op1 = XEXP (op, 0); - SYMBOL_REF_FLAG (op1) = 1; - output_addr_const (file, op1); - return; - case 'H': /* sethi */ - if (code == SYMBOL_REF) - SYMBOL_REF_FLAG (op) = 1; - break; + output_addr_const (file, op); + return; case 'I': /* reversed condition */ code = reverse_condition (code); @@ -1511,9 +1637,9 @@ c4x_print_operand (file, op, letter) case 'K': /* generate ldp(k) if direct address */ if (! TARGET_SMALL && code == MEM - && GET_CODE (XEXP (op, 0)) == PLUS - && GET_CODE(XEXP (XEXP (op, 0), 0)) == REG - && REGNO(XEXP (XEXP (op, 0), 0)) == DP_REGNO) + && GET_CODE (XEXP (op, 0)) == LO_SUM + && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG + && REGNO (XEXP (XEXP (op, 0), 0)) == DP_REGNO) { op1 = XEXP (XEXP (op, 0), 1); if (GET_CODE(op1) == CONST_INT || GET_CODE(op1) == SYMBOL_REF) @@ -1548,12 +1674,18 @@ c4x_print_operand (file, op, letter) fatal_insn ("c4x_print_operand: %%O inconsistency", op); return; - case 'R': /* call register */ - op1 = XEXP (op, 0); - if (code != MEM || GET_CODE (op1) != REG) - fatal_insn ("c4x_print_operand: %%R inconsistency", op); - else - fprintf (file, "%s", reg_names[REGNO (op1)]); + case 'C': /* call */ + if (code != MEM) + fatal_insn ("c4x_print_operand: %%C inconsistency", op); + op = XEXP (op, 0); + code = GET_CODE (op); + break; + + case 'U': /* call/callu */ + if (code != MEM) + fatal_insn ("c4x_print_operand: %%U inconsistency", op); + if (GET_CODE (XEXP (op, 0)) != SYMBOL_REF) + asm_fprintf (file, "u"); return; default: @@ -1721,20 +1853,10 @@ c4x_print_operand_address (file, addr) { rtx op0 = XEXP (addr, 0); rtx op1 = XEXP (addr, 1); - enum rtx_code code0 = GET_CODE (op0); - if (code0 == USE || code0 == PLUS) - { - asm_fprintf (file, "@"); - output_addr_const (file, op1); - } - else if (REG_P (op0)) + if (REG_P (op0)) { - if (REGNO (op0) == DP_REGNO) - { - c4x_print_operand_address (file, op1); - } - else if (REG_P (op1)) + if (REG_P (op1)) { if (IS_INDEX_REGNO (op0)) { @@ -1762,16 +1884,28 @@ c4x_print_operand_address (file, addr) INTVAL (op1)); /* base + displacement */ } } + else + fatal_insn ("c4x_print_operand_address: Bad operand case", addr); + } + break; + + case LO_SUM: + { + rtx op0 = XEXP (addr, 0); + rtx op1 = XEXP (addr, 1); + + if (REG_P (op0) && REGNO (op0) == DP_REGNO) + c4x_print_operand_address (file, op1); + else + fatal_insn ("c4x_print_operand_address: Bad operand case", addr); } break; case CONST: case SYMBOL_REF: case LABEL_REF: - if (! SYMBOL_REF_FLAG (addr)) - fprintf (file, "@"); + fprintf (file, "@"); output_addr_const (file, addr); - SYMBOL_REF_FLAG (addr) = 0; break; /* We shouldn't access CONST_INT addresses. */ @@ -1783,17 +1917,18 @@ c4x_print_operand_address (file, addr) } } - +/* Return nonzero if the floating point operand will fit + in the immediate field. */ static int -c4x_immed_float_p (operand) - rtx operand; +c4x_immed_float_p (op) + rtx op; { long convval[2]; int exponent; REAL_VALUE_TYPE r; - REAL_VALUE_FROM_CONST_DOUBLE (r, operand); - if (GET_MODE (operand) == HFmode) + REAL_VALUE_FROM_CONST_DOUBLE (r, op); + if (GET_MODE (op) == HFmode) REAL_VALUE_TO_TARGET_DOUBLE (r, convval); else { @@ -1811,157 +1946,6 @@ c4x_immed_float_p (operand) && (exponent >= -7); /* Negative exp */ } - -/* This function checks for an insn operand that requires direct - addressing and inserts a load of the DP register prior to the - insn if the big memory model is being compiled for. Immediate - operands that do not fit within the opcode field get changed - into memory references using direct addressing. At this point - all pseudos have been converted to hard registers. */ - -int -c4x_scan_for_ldp (newop, insn, operand0) - rtx *newop; - rtx insn; - rtx operand0; -{ - int i; - char *format_ptr; - rtx op0, op1, op2, addr; - rtx operand = *newop; - - switch (GET_CODE (operand)) - { - case MEM: - op0 = XEXP (operand, 0); - - /* We have something we need to emit a load dp insn for. - The first operand should hold the rtx for the instruction - required. */ - - switch (GET_CODE (op0)) - { - case CONST_INT: - fatal_insn ("c4x_scan_for_ldp: Direct memory access to const_int", - op0); - break; - - case CONST: - case SYMBOL_REF: - if (! TARGET_C3X && ! TARGET_SMALL - && recog_memoized (insn) == CODE_FOR_movqi_noclobber - && ((addr = find_reg_note (insn, REG_EQUAL, NULL_RTX)) - || (addr = find_reg_note (insn, REG_EQUIV, NULL_RTX))) - && (IS_STD_OR_PSEUDO_REGNO (operand0))) - { - addr = XEXP (addr, 0); - if (GET_CODE (addr) == CONST_INT) - { - op1 = GEN_INT (INTVAL (addr) & ~0xffff); - emit_insn_before (gen_movqi (operand0, op1), insn); - op1 = GEN_INT (INTVAL (addr) & 0xffff); - emit_insn_before (gen_iorqi3_noclobber (operand0, - operand0, op1), insn); - delete_insn (insn); - return 1; - } - else if (GET_CODE (addr) == SYMBOL_REF) - { - emit_insn_before (gen_set_high_use (operand0, addr, addr), - insn); - emit_insn_before (gen_set_ior_lo_use (operand0, addr, addr), - insn); - delete_insn (insn); - return 1; - } - else if (GET_CODE (addr) == CONST - && GET_CODE (op1 = XEXP (addr, 0)) == PLUS - && GET_CODE (op2 = XEXP (op1, 0)) == SYMBOL_REF - && GET_CODE (XEXP (op1, 1)) == CONST_INT) - { - emit_insn_before (gen_set_high_use (operand0, addr, op2), - insn); - emit_insn_before (gen_set_ior_lo_use (operand0, addr, op2), - insn); - delete_insn (insn); - return 1; - } - } - if (! TARGET_SMALL) - emit_insn_before (gen_set_ldp (gen_rtx_REG (Pmode, DP_REGNO), - operand), insn); - - /* Replace old memory reference with direct reference. */ - *newop = gen_rtx_MEM (GET_MODE (operand), - gen_rtx_PLUS (Pmode, - gen_rtx_REG (Pmode, DP_REGNO), - op0)); - - /* Use change_address? */ - RTX_UNCHANGING_P (*newop) = RTX_UNCHANGING_P (operand); - MEM_COPY_ATTRIBUTES (*newop, operand); - break; - - default: - break; - } - - return 0; - - case CONST_INT: - if (SMALL_CONST (INTVAL (operand), insn)) - break; - fatal_insn ("Immediate integer too large", insn); - - case CONST_DOUBLE: - if (c4x_immed_float_p (operand)) - break; - - /* We'll come here if a CONST_DOUBLE integer has slipped - though the net... */ - fatal_insn ("Immediate CONST_DOUBLE integer too large", insn); - - case CONST: - fatal_insn ("Immediate integer not known", insn); - - /* Symbol and label immediate addresses cannot be stored - within a C[34]x instruction, so we store them in memory - and use direct addressing instead. */ - case LABEL_REF: - case SYMBOL_REF: - if (GET_CODE (operand0) != REG) - break; - - op0 = XEXP (force_const_mem (Pmode, operand), 0); - *newop = gen_rtx_MEM (GET_MODE (operand), - gen_rtx_PLUS (Pmode, - gen_rtx_PLUS (Pmode, - gen_rtx_USE (VOIDmode, operand), - gen_rtx_REG (Pmode, DP_REGNO)), - op0)); - - if (! TARGET_SMALL) - emit_insn_before (gen_set_ldp_use (gen_rtx_REG (Pmode, DP_REGNO), - *newop, operand), insn); - return 0; - - default: - break; - } - - format_ptr = GET_RTX_FORMAT (GET_CODE (operand)); - - /* Recursively hunt for required loads of DP. */ - for (i = 0; i < GET_RTX_LENGTH (GET_CODE (operand)); i++) - { - if (*format_ptr++ == 'e') /* rtx expression */ - if (c4x_scan_for_ldp (&XEXP (operand, i), insn, operand0)) - break; - } - return 0; -} - - /* The last instruction in a repeat block cannot be a Bcond, DBcound, CALL, CALLCond, TRAPcond, RETIcond, RETScond, IDLE, RPTB or RPTS. @@ -1993,7 +1977,11 @@ c4x_rptb_nop_p (insn) /* If there is a label at the end of the loop we must insert a NOP. */ - insn = prev_nonnote_insn (insn); + do { + insn = previous_insn (insn); + } while (GET_CODE (insn) == NOTE + || GET_CODE (insn) == USE + || GET_CODE (insn) == CLOBBER); if (GET_CODE (insn) == CODE_LABEL) return 1; @@ -2006,7 +1994,7 @@ c4x_rptb_nop_p (insn) if (insn == start_label) return i == 0; - insn = PREV_INSN (insn); + insn = previous_insn (insn); }; /* If we have a jump instruction we should insert a NOP. If we @@ -2014,7 +2002,7 @@ c4x_rptb_nop_p (insn) is empty. */ if (GET_CODE (insn) == JUMP_INSN) return 1; - insn = PREV_INSN (insn); + insn = previous_insn (insn); } return 0; } @@ -2053,20 +2041,16 @@ c4x_rptb_insert (insn) emit_insn_before (gen_rptb_top (start_label, end_label), insn); } -/* This function is a C4x special. It scans through all the insn - operands looking for places where the DP register needs to be - reloaded and for large immediate operands that need to be converted - to memory references. The latter should be avoidable with proper - definition of patterns in machine description. We come here right - near the end of things, immediately before delayed branch - scheduling. */ + +/* This function is a C4x special called immediately before delayed + branch scheduling. We fix up RTPB style loops that didn't get RC + allocated as the loop counter. */ void c4x_process_after_reload (first) rtx first; { rtx insn; - int i; for (insn = first; insn; insn = NEXT_INSN (insn)) { @@ -2086,11 +2070,9 @@ c4x_process_after_reload (first) c4x_rptb_insert(insn); /* We split all insns here if they have a # for the output - template if we are using the big memory model since there - is a chance that we might be accessing memory across a - page boundary. */ + template. */ - if (! TARGET_SMALL) + if (1) { char *template; @@ -2106,30 +2088,9 @@ c4x_process_after_reload (first) PUT_CODE (insn, NOTE); NOTE_SOURCE_FILE (insn) = 0; NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; - - /* Do we have to update the basic block info here? - Maybe reorg wants it sorted out... */ - - /* Continue with the first of the new insns generated - by the split. */ insn = new; - - insn_code_number = recog_memoized (insn); - - if (insn_code_number < 0) - continue; } } - - /* Ignore jumps and calls. */ - if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN) - continue; - - insn_extract (insn); - for (i = 0; i < insn_n_operands[insn_code_number]; i++) - if (c4x_scan_for_ldp (recog_operand_loc[i], insn, - recog_operand[0])) - break; } } } @@ -2152,11 +2113,12 @@ c4x_x_register (op) static int -c4x_int_constant (op) +c4x_immed_int_constant (op) rtx op; { if (GET_CODE (op) != CONST_INT) return 0; + return GET_MODE (op) == VOIDmode || GET_MODE_CLASS (op) == MODE_INT || GET_MODE_CLASS (op) == MODE_PARTIAL_INT; @@ -2164,11 +2126,15 @@ c4x_int_constant (op) static int -c4x_float_constant (op) +c4x_immed_float_constant (op) rtx op; { if (GET_CODE (op) != CONST_DOUBLE) return 0; + + if (GET_CODE (XEXP (op, 0)) == MEM) + return 0; + return GET_MODE (op) == QFmode || GET_MODE (op) == HFmode; } @@ -2177,7 +2143,7 @@ int c4x_H_constant (op) rtx op; { - return c4x_float_constant (op) && c4x_immed_float_p (op); + return c4x_immed_float_constant (op) && c4x_immed_float_p (op); } @@ -2185,7 +2151,7 @@ int c4x_I_constant (op) rtx op; { - return c4x_int_constant (op) && IS_INT16_CONST (INTVAL (op)); + return c4x_immed_int_constant (op) && IS_INT16_CONST (INTVAL (op)); } @@ -2195,7 +2161,7 @@ c4x_J_constant (op) { if (TARGET_C3X) return 0; - return c4x_int_constant (op) && IS_INT8_CONST (INTVAL (op)); + return c4x_immed_int_constant (op) && IS_INT8_CONST (INTVAL (op)); } @@ -2205,7 +2171,7 @@ c4x_K_constant (op) { if (TARGET_C3X) return 0; - return c4x_int_constant (op) && IS_INT5_CONST (INTVAL (op)); + return c4x_immed_int_constant (op) && IS_INT5_CONST (INTVAL (op)); } @@ -2213,7 +2179,7 @@ int c4x_L_constant (op) rtx op; { - return c4x_int_constant (op) && IS_UINT16_CONST (INTVAL (op)); + return c4x_immed_int_constant (op) && IS_UINT16_CONST (INTVAL (op)); } @@ -2221,7 +2187,7 @@ static int c4x_N_constant (op) rtx op; { - return c4x_int_constant (op) && IS_NOT_UINT16_CONST (INTVAL (op)); + return c4x_immed_int_constant (op) && IS_NOT_UINT16_CONST (INTVAL (op)); } @@ -2229,7 +2195,7 @@ static int c4x_O_constant (op) rtx op; { - return c4x_int_constant (op) && IS_HIGH_CONST (INTVAL (op)); + return c4x_immed_int_constant (op) && IS_HIGH_CONST (INTVAL (op)); } @@ -2277,6 +2243,7 @@ c4x_Q_constraint (op) return IS_DISP8_CONST (INTVAL (op1)); } break; + default: break; } @@ -2508,7 +2475,7 @@ c4x_S_indirect (op) } -/* Symbol ref. */ +/* Direct memory operand. */ int c4x_T_constraint (op) @@ -2518,27 +2485,37 @@ c4x_T_constraint (op) return 0; op = XEXP (op, 0); - if ((GET_CODE (op) == PLUS) - && (GET_CODE (XEXP (op, 0)) == REG) - && (REGNO (XEXP (op, 0)) == DP_REGNO)) + if (GET_CODE (op) != LO_SUM) { - op = XEXP (op, 1); - } - else if ((GET_CODE (op) == PLUS) - && (GET_CODE (XEXP (op, 0)) == PLUS) - && (GET_CODE (XEXP (XEXP (op, 0), 0)) == USE)) - { - op = XEXP (op, 1); - } - else if ((GET_CODE (op) == PLUS) && (GET_CODE (XEXP (op, 0)) == USE)) - { - op = XEXP (op, 1); + /* Allow call operands. */ + return GET_CODE (op) == SYMBOL_REF + && GET_MODE (op) == Pmode + && SYMBOL_REF_FLAG (op); } + /* HImode and HFmode are not offsettable. */ + if (GET_MODE (op) == HImode || GET_CODE (op) == HFmode) + return 0; + + if ((GET_CODE (XEXP (op, 0)) == REG) + && (REGNO (XEXP (op, 0)) == DP_REGNO)) + return c4x_U_constraint (XEXP (op, 1)); + + return 0; +} + + +/* Symbolic operand. */ + +int +c4x_U_constraint (op) + rtx op; +{ /* Don't allow direct addressing to an arbitrary constant. */ if (GET_CODE (op) == CONST && GET_CODE (XEXP (op, 0)) == PLUS - && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF + && (GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF + || GET_CODE (XEXP (XEXP (op, 0), 0)) == LABEL_REF) && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT) return 1; @@ -2657,6 +2634,7 @@ reg_operand (op, mode) return register_operand (op, mode); } + int reg_imm_operand (op, mode) rtx op; @@ -2667,6 +2645,7 @@ reg_imm_operand (op, mode) return 0; } + int not_modify_reg (op, mode) rtx op; @@ -2693,6 +2672,16 @@ not_modify_reg (op, mode) if (REG_P (op1) || GET_CODE (op1) == CONST_INT) return 1; } + + case LO_SUM: + { + rtx op0 = XEXP (op, 0); + + if (REG_P (op0) && REGNO (op0) == DP_REGNO) + return 1; + } + break; + case CONST: case SYMBOL_REF: case LABEL_REF: @@ -2703,6 +2692,7 @@ not_modify_reg (op, mode) return 0; } + int not_rc_reg (op, mode) rtx op; @@ -2713,6 +2703,7 @@ not_rc_reg (op, mode) return 1; } + /* Extended precision register R0-R1. */ int @@ -2867,8 +2858,6 @@ call_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED; { - if (GET_CODE (op) != MEM) - return 0; op = XEXP (op, 0); switch (GET_CODE (op)) { @@ -2881,6 +2870,29 @@ call_operand (op, mode) } +/* Symbolic operand. */ + +int +symbolic_operand (op, mode) + register rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + switch (GET_CODE (op)) + { + case SYMBOL_REF: + case LABEL_REF: + return 1; + case CONST: + op = XEXP (op, 0); + return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF + || GET_CODE (XEXP (op, 0)) == LABEL_REF) + && GET_CODE (XEXP (op, 1)) == CONST_INT); + default: + return 0; + } +} + + /* Check src operand of two operand arithmetic instructions. */ int @@ -2894,14 +2906,29 @@ src_operand (op, mode) if (mode == VOIDmode) mode = GET_MODE (op); - /* We could allow certain CONST_INT values for HImode... */ if (GET_CODE (op) == CONST_INT) - return (mode == QImode || mode == Pmode) && c4x_I_constant (op); + return (mode == QImode || mode == Pmode || mode == HImode) + && c4x_I_constant (op); /* We don't like CONST_DOUBLE integers. */ if (GET_CODE (op) == CONST_DOUBLE) return c4x_H_constant (op); + /* Disallow symbolic addresses. */ + if (GET_CODE (op) == SYMBOL_REF + || GET_CODE (op) == LABEL_REF + || GET_CODE (op) == CONST) + return 0; + + /* Disallow direct memory access symbolic addresses. + These are usually caught by the movqi expander and + converted to a LO_SUM. */ + if (GET_CODE (op) == MEM + && ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF + || GET_CODE (XEXP (op, 0)) == LABEL_REF + || GET_CODE (XEXP (op, 0)) == CONST))) + return 0; + return general_operand (op, mode); } @@ -2930,13 +2957,10 @@ lsrc_operand (op, mode) if (mode != QImode && mode != Pmode) fatal_insn ("Mode not QImode", op); - if (REG_P (op)) - return reg_operand (op, mode); - if (GET_CODE (op) == CONST_INT) return c4x_L_constant (op) || c4x_J_constant (op); - return general_operand (op, mode); + return src_operand (op, mode); } @@ -2953,13 +2977,10 @@ tsrc_operand (op, mode) if (mode != QImode && mode != Pmode) fatal_insn ("Mode not QImode", op); - if (REG_P (op)) - return reg_operand (op, mode); - if (GET_CODE (op) == CONST_INT) return c4x_L_constant (op) || c4x_N_constant (op) || c4x_J_constant (op); - return general_operand (op, mode); + return src_operand (op, mode); } @@ -3441,7 +3462,7 @@ c4x_valid_operands (code, operands, mode, force) break; default: - fatal ("c4x_valid_operands: Internal error"); + fatal_insn ("c4x_valid_operands: Internal error", op2); break; } @@ -3922,16 +3943,19 @@ c4x_operand_subword (op, i, validate_address, mode) { enum rtx_code code = GET_CODE (XEXP (op, 0)); enum machine_mode mode = GET_MODE (XEXP (op, 0)); + enum machine_mode submode; + + submode = mode; + if (mode == HImode) + submode = QImode; + else if (mode == HFmode) + submode = QFmode; switch (code) { case POST_INC: case PRE_INC: - if (mode == HImode) - mode = QImode; - else if (mode == HFmode) - mode = QFmode; - return gen_rtx_MEM (mode, XEXP (op, 0)); + return gen_rtx_MEM (submode, XEXP (op, 0)); case POST_DEC: case PRE_DEC: @@ -3941,6 +3965,23 @@ c4x_operand_subword (op, i, validate_address, mode) e.g., *p-- => *(p-=2); *(p+1). */ fatal_insn ("c4x_operand_subword: invalid autoincrement", op); + case SYMBOL_REF: + case LABEL_REF: + case CONST: + case CONST_INT: + fatal_insn ("c4x_operand_subword: invalid address", op); + + /* Even though offsettable_address_p considers (MEM + (LO_SUM)) to be offsettable, it is not safe if the + address is at the end of the data page since we also have + to fix up the associated high PART. In this case where + we are trying to split a HImode or HFmode memory + reference, we would have to emit another insn to reload a + new HIGH value. It's easier to disable LO_SUM memory references + in HImode or HFmode and we probably get better code. */ + case LO_SUM: + fatal_insn ("c4x_operand_subword: address not offsettable", op); + default: break; } @@ -4233,7 +4274,6 @@ c4x_adjust_cost (insn, link, dep_insn, cost) /* Data dependency; DEP_INSN writes a register that INSN reads some cycles later. */ - if (TARGET_C3X) { if (get_attr_setgroup1 (dep_insn) && get_attr_usegroup1 (insn)) @@ -4248,7 +4288,6 @@ c4x_adjust_cost (insn, link, dep_insn, cost) insn uses ar0-ar7. We then test if the same register is used. The tricky bit is that some operands will use several registers... */ - if (get_attr_setar0 (dep_insn) && get_attr_usear0 (insn)) max = SET_USE_COST > max ? SET_USE_COST : max; if (get_attr_setlda_ar0 (dep_insn) && get_attr_usear0 (insn)) @@ -4342,3 +4381,4 @@ c4x_adjust_cost (insn, link, dep_insn, cost) else abort (); } + diff --git a/gcc/config/c4x/c4x.h b/gcc/config/c4x/c4x.h index 2a0a7c045d48..c001712c8944 100644 --- a/gcc/config/c4x/c4x.h +++ b/gcc/config/c4x/c4x.h @@ -258,12 +258,16 @@ extern int target_flags; #define TARGET_C40 (target_flags & C40_FLAG) #define TARGET_C44 (target_flags & C44_FLAG) +#define TARGET_LOAD_ADDRESS (1 || (! TARGET_C3X && ! TARGET_SMALL)) + /* -mrpts allows the use of the RPTS instruction irregardless. -mrpts=max-cycles will use RPTS if the number of cycles is constant and less than max-cycles. */ #define TARGET_RPTS_CYCLES(CYCLES) (TARGET_RPTS || (CYCLES) < c4x_rpts_cycles) +#define BCT_CHECK_LOOP_ITERATIONS !(TARGET_LOOP_UNSIGNED) + /* -mcpu=XX with XX = target DSP version number */ /* This macro is similar to `TARGET_SWITCHES' but defines names of @@ -836,16 +840,17 @@ c4x_secondary_memory_needed(CLASS1, CLASS2, MODE) : ((C) == 'O') ? (IS_HIGH_CONST (VAL)) \ : 0 ) -#define CONST_DOUBLE_OK_FOR_LETTER_P(VAL, C) \ - ( ((C) == 'G') ? (fp_zero_operand (VAL)) \ - : ((C) == 'H') ? (c4x_H_constant (VAL)) \ +#define CONST_DOUBLE_OK_FOR_LETTER_P(OP, C) \ + ( ((C) == 'G') ? (fp_zero_operand (OP)) \ + : ((C) == 'H') ? (c4x_H_constant (OP)) \ : 0 ) -#define EXTRA_CONSTRAINT(VAL, C) \ - ( ((C) == 'Q') ? (c4x_Q_constraint (VAL)) \ - : ((C) == 'R') ? (c4x_R_constraint (VAL)) \ - : ((C) == 'S') ? (c4x_S_constraint (VAL)) \ - : ((C) == 'T') ? (c4x_T_constraint (VAL)) \ +#define EXTRA_CONSTRAINT(OP, C) \ + ( ((C) == 'Q') ? (c4x_Q_constraint (OP)) \ + : ((C) == 'R') ? (c4x_R_constraint (OP)) \ + : ((C) == 'S') ? (c4x_S_constraint (OP)) \ + : ((C) == 'T') ? (c4x_T_constraint (OP)) \ + : ((C) == 'U') ? (c4x_U_constraint (OP)) \ : 0 ) #define SMALL_CONST(VAL, insn) \ @@ -1613,17 +1618,44 @@ extern struct rtx_def *c4x_legitimize_address (); /* Nonzero if the constant value X is a legitimate general operand. It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. - The C4x can only load 16-bit immediate values, so we only allow - a restricted subset of CONST_INT and CONST_DOUBLE and reject - LABEL_REF, SYMBOL_REF, CONST, and HIGH codes. */ + The C4x can only load 16-bit immediate values, so we only allow a + restricted subset of CONST_INT and CONST_DOUBLE. Disallow + LABEL_REF and SYMBOL_REF (except on the C40 with the big memory + model) so that the symbols will be forced into the constant pool. + On second thoughts, lets do this with the move expanders. +*/ #define LEGITIMATE_CONSTANT_P(X) \ ((GET_CODE (X) == CONST_DOUBLE && c4x_H_constant (X)) \ - || (GET_CODE (X) == CONST_INT && c4x_I_constant (X))) - + || (GET_CODE (X) == CONST_INT && c4x_I_constant (X)) \ + || (GET_CODE (X) == SYMBOL_REF) \ + || (GET_CODE (X) == LABEL_REF) \ + || (GET_CODE (X) == CONST) \ + || (GET_CODE (X) == HIGH && ! TARGET_C3X) \ + || (GET_CODE (X) == LO_SUM && ! TARGET_C3X)) #define LEGITIMATE_DISPLACEMENT_P(X) IS_DISP8_CONST (INTVAL (X)) +/* Define this macro if references to a symbol must be treated + differently depending on something about the variable or + function named by the symbol (such as what section it is in). + + The macro definition, if any, is executed immediately after the + rtl for DECL or other node is created. + The value of the rtl will be a `mem' whose address is a + `symbol_ref'. + + The usual thing for this macro to do is to a flag in the + `symbol_ref' (such as `SYMBOL_REF_FLAG') or to store a modified + name string in the `symbol_ref' (if one bit is not enough + information). + + On the C4x we use this to indicate if a symbol is in text or + data space. */ + +extern void c4x_encode_section_info (); +#define ENCODE_SECTION_INFO(DECL) c4x_encode_section_info (DECL); + /* Descripting Relative Cost of Operations */ /* Provide the costs of a rtl expression. This is in the body of a @@ -1912,7 +1944,7 @@ dtors_section () \ || ! TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \ || ! DECL_INITIAL (DECL) \ || (DECL_INITIAL (DECL) != error_mark_node \ - && ! TREE_CONSTANT (DECL_INITIAL (DECL)))) \ + && ! TREE_CONSTANT (DECL_INITIAL (DECL)))) \ data_section (); \ else \ const_section (); \ @@ -2440,8 +2472,6 @@ do { fprintf (asm_out_file, "\t.sdef\t"); \ #define MACHINE_DEPENDENT_REORG(INSNS) c4x_process_after_reload(INSNS) -#define MACHINE_DEPENDENT_COMBINE(INSNS) c4x_combine_parallel(INSNS) - #define DBR_OUTPUT_SEQEND(FILE) \ if (final_sequence != NULL_RTX) \ { \ @@ -2492,7 +2522,8 @@ if (final_sequence != NULL_RTX) \ {"any_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \ {"par_ind_operand", {MEM}}, \ {"parallel_operand", {SUBREG, REG, MEM}}, \ - {"mem_operand", {MEM}}, \ + {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}}, \ + {"mem_operand", {MEM}}, /* Variables in c4x.c */ @@ -2582,6 +2613,8 @@ extern int rc_reg_operand (); extern int st_reg_operand (); +extern int symbolic_operand (); + extern int ar0_reg_operand (); extern int ar0_mem_operand (); @@ -2652,12 +2685,16 @@ extern int c4x_S_constraint (); extern int c4x_T_constraint (); +extern int c4x_U_constraint (); + extern void c4x_emit_libcall (); extern void c4x_emit_libcall3 (); extern void c4x_emit_libcall_mulhi (); +extern int c4x_emit_move_sequence (); + extern int legitimize_operands (); extern int valid_operands (); diff --git a/gcc/config/c4x/c4x.md b/gcc/config/c4x/c4x.md index 7d858547a790..60bc43fd99f1 100644 --- a/gcc/config/c4x/c4x.md +++ b/gcc/config/c4x/c4x.md @@ -23,7 +23,6 @@ ; ; TODO : -; Set up addressing macros to handle direct memory references properly. ; Try using PQImode again for addresses since C30 only uses ; 24-bit addresses. Ideally GCC would emit different insns ; for QImode and Pmode, whether Pmode was QImode or PQImode. @@ -66,7 +65,7 @@ ; st_reg_operand ST [y] ; dp_reg_operand DP [z] ; stik_const_operand 5-bit const [K] -; src_operand general operand [rfmHI] +; src_operand general operand [rfHmI] ; par_ind_operand indirect S mode (ARx + 0, 1, IRx) [S<>] ; parallel_operand par_ind_operand or ext_low_reg_operand @@ -125,7 +124,7 @@ ; Q ARx + 9-bit signed disp ; R ARx + 5-bit unsigned disp (C4x only) ; S ARx + 0, 1, IRx disp -; T symbol ref (direct) +; T direct memory operand ; V non offsettable memory ; X any operand ; < memory operand with autodecrement addressing @@ -133,8 +132,12 @@ ; { memory operand with pre-modify addressing ; } memory operand with post-modify addressing -; Note that the d, f, and h constraints are equivalent. -; The m constraint is equivalent to QT<>{} +; Note that the 'd', 'f', and 'h' constraints are equivalent. +; The m constraint is equivalent to 'QT<>{}' + +; Note we cannot use the 'g' constraint with Pmode (i.e, QImode) +; operations since LEGITIMATE_CONSTANT_P accepts SYMBOL_REF. +; So instead we use 'rIm' for signed operands or 'rLm' for unsigned operands. ; Note that the constraints are used to select the operands ; for a chosen pattern. The constraint that requires the fewest @@ -1099,37 +1102,79 @@ "* return (TARGET_C3X) ? \"ldp\\t%A1\" : \"ldpk\\t%A1\";" [(set_attr "type" "ldp")]) - -; Used when moving a constant label reference to an external -; location, this will make sure the original label is still -; used so the optimizer will not optimize it away. -; -(define_insn "set_ldp_use" - [(parallel [(set (match_operand:QI 0 "dp_reg_operand" "=z") - (high:QI (match_operand:QI 1 "" ""))) - (use (match_operand 2 "" ""))])] - "! TARGET_SMALL" - "* return (TARGET_C3X) ? \"ldp\\t%A1\" : \"ldpk\\t%A1\";" - [(set_attr "type" "ldp")]) - -(define_insn "set_high_use" - [(parallel [(set (match_operand:QI 0 "std_reg_operand" "=c") - (high:QI (match_operand:QI 1 "" ""))) - (use (match_operand 2 "" ""))])] - "! TARGET_C3X && ! TARGET_SMALL" +(define_insn "set_high" + [(set (match_operand:QI 0 "std_reg_operand" "=c") + (high:QI (match_operand:QI 1 "symbolic_operand" "")))] + "! TARGET_C3X " "ldhi\\t^%H1,%0" [(set_attr "type" "unary")]) -(define_insn "set_ior_lo_use" - [(parallel [(set (match_operand:QI 0 "std_reg_operand" "=c") - (ior:QI (match_dup 0) - (and:QI (match_operand:QI 1 "" "") - (const_int 65535)))) - (use (match_operand 2 "" ""))])] - "! TARGET_C3X && ! TARGET_SMALL" +(define_insn "set_lo_sum" + [(set (match_operand:QI 0 "std_reg_operand" "=c") + (lo_sum:QI (match_dup 0) + (match_operand:QI 1 "symbolic_operand" "")))] + "" "or\\t#%H1,%0" [(set_attr "type" "unary")]) +(define_split + [(set (match_operand:QI 0 "std_reg_operand" "") + (match_operand:QI 1 "symbolic_operand" ""))] + "! TARGET_C3X" + [(set (match_dup 0) (high:QI (match_dup 1))) + (set (match_dup 0) (lo_sum:QI (match_dup 0) (match_dup 1)))] + "") + +; This pattern is required to handle the case where a register that clobbers +; CC has been selected to load a symbolic address. We force the address +; into memory and then generate LDP and LDIU insns. +; This is also required for the C30 if we pretend that we can +; easily load symbolic addresses into a register. +(define_split + [(set (match_operand:QI 0 "reg_operand" "") + (match_operand:QI 1 "symbolic_operand" ""))] + "! TARGET_SMALL + && (TARGET_C3X || (reload_completed + && ! std_reg_operand (operands[0], QImode)))" + [(set (match_dup 2) (high:QI (match_dup 3))) + (set (match_dup 0) (match_dup 4)) + (use (match_dup 1))] + " +{ + rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); + operands[2] = dp_reg; + operands[3] = force_const_mem (Pmode, operands[1]); + operands[4] = change_address (operands[3], QImode, + gen_rtx_LO_SUM (Pmode, dp_reg, + XEXP (operands[3], 0))); + operands[3] = XEXP (operands[3], 0); +}") + +; This pattern is similar to the above but does not emit a LDP +; for the small memory model. +(define_split + [(set (match_operand:QI 0 "reg_operand" "") + (match_operand:QI 1 "symbolic_operand" ""))] + "TARGET_SMALL + && (TARGET_C3X || (reload_completed + && ! std_reg_operand (operands[0], QImode)))" + [(set (match_dup 0) (match_dup 1))] + " +{ + rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); + operands[1] = force_const_mem (Pmode, operands[1]); + operands[1] = change_address (operands[1], QImode, + gen_rtx_LO_SUM (Pmode, dp_reg, + XEXP (operands[1], 0))); +}") + +(define_insn "load_immed_address" + [(set (match_operand:QI 0 "reg_operand" "=a?x?c*r") + (match_operand:QI 1 "symbolic_operand" ""))] + "TARGET_LOAD_ADDRESS" + "#" + [(set_attr "type" "multi")]) + ; ; LDIU/LDA/STI/STIK ; @@ -1148,9 +1193,11 @@ ; spill a register. (define_insn "movqi_noclobber" [(set (match_operand:QI 0 "src_operand" "=d,*c,m,r") - (match_operand:QI 1 "src_hi_operand" "rmI,rmI,r,O"))] - "reg_operand (operands[0], QImode) - || reg_operand (operands[1], QImode)" + (match_operand:QI 1 "src_hi_operand" "rIm,rIm,r,O"))] + "(REG_P (operands[0]) || REG_P (operands[1]) + || GET_CODE (operands[0]) == SUBREG + || GET_CODE (operands[1]) == SUBREG) + && ! symbolic_operand (operands[1], QImode)" "* if (which_alternative == 2) return \"sti\\t%1,%0\"; @@ -1181,7 +1228,7 @@ ; We shouldn't need these peepholes, but the combiner seems to miss them... (define_peephole [(set (match_operand:QI 0 "ext_reg_operand" "=d") - (match_operand:QI 1 "src_operand" "g")) + (match_operand:QI 1 "src_operand" "rIm")) (set (reg:CC 21) (compare:CC (match_dup 0) (const_int 0)))] "" @@ -1192,7 +1239,7 @@ (define_insn "*movqi_set" [(set (reg:CC 21) - (compare:CC (match_operand:QI 1 "src_operand" "g") + (compare:CC (match_operand:QI 1 "src_operand" "rIm") (const_int 0))) (set (match_operand:QI 0 "ext_reg_operand" "=d") (match_dup 1))] @@ -1206,7 +1253,7 @@ ; when a simple compare with zero will suffice. ;(define_insn "*movqi_test" ; [(set (reg:CC 21) -; (compare:CC (match_operand:QI 1 "src_operand" "g") +; (compare:CC (match_operand:QI 1 "src_operand" "rIm") ; (const_int 0))) ; (clobber (match_scratch:QI 0 "=d"))] ; "" @@ -1226,28 +1273,14 @@ ; the compiler, have memoized the insn number already. (define_expand "movqi" - [(set (match_operand:QI 0 "src_operand" "") - (match_operand:QI 1 "src_operand" ""))] + [(set (match_operand:QI 0 "general_operand" "") + (match_operand:QI 1 "general_operand" ""))] "" " - /* We shouldn't have to do this, since reload is supposed to - be able to do this if we have a memory constraint. */ - if (CONSTANT_P (operands[1]) - && ! const_operand (operands[1], QImode)) - { - operands[1] = force_const_mem (QImode, operands[1]); - if (! memory_address_p (QImode, XEXP (operands[1], 0)) - && ! reload_in_progress) - operands[1] = change_address (operands[1], QImode, - XEXP (operands[1], 0)); - } - - if (! reload_in_progress - && ! reg_operand (operands[0], QImode) - && ! reg_operand (operands[1], QImode) - && ! (stik_const_operand (operands[1], QImode) - && ! push_operand (operands[0], QImode))) - operands[1] = force_reg (QImode, operands[1]);") +{ + if (c4x_emit_move_sequence (operands, QImode)) + DONE; +}") (define_insn "*movqi_update" [(set (match_operand:QI 0 "reg_operand" "=r") @@ -1303,7 +1336,7 @@ (define_insn "*absqi2_clobber" [(set (match_operand:QI 0 "reg_operand" "=d,c") - (abs:QI (match_operand:QI 1 "src_operand" "g,g"))) + (abs:QI (match_operand:QI 1 "src_operand" "rIm,rIm"))) (clobber (reg:CC_NOOV 21))] "" "absi\\t%1,%0" @@ -1312,7 +1345,7 @@ (define_insn "*absqi2_test" [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:QI (match_operand:QI 1 "src_operand" "g")) + (compare:CC_NOOV (abs:QI (match_operand:QI 1 "src_operand" "rIm")) (const_int 0))) (clobber (match_scratch:QI 0 "=d"))] "" @@ -1322,7 +1355,7 @@ (define_insn "*absqi2_set" [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:QI (match_operand:QI 1 "src_operand" "g")) + (compare:CC_NOOV (abs:QI (match_operand:QI 1 "src_operand" "rIm")) (const_int 0))) (set (match_operand:QI 0 "ext_reg_operand" "=d") (abs:QI (match_dup 1)))] @@ -1343,7 +1376,7 @@ (define_insn "*negqi2_clobber" [(set (match_operand:QI 0 "reg_operand" "=d,c") - (neg:QI (match_operand:QI 1 "src_operand" "g,g"))) + (neg:QI (match_operand:QI 1 "src_operand" "rIm,rIm"))) (clobber (reg:CC_NOOV 21))] "" "negi\\t%1,%0" @@ -1352,7 +1385,7 @@ (define_insn "*negqi2_test" [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QI (match_operand:QI 1 "src_operand" "g")) + (compare:CC_NOOV (neg:QI (match_operand:QI 1 "src_operand" "rIm")) (const_int 0))) (clobber (match_scratch:QI 0 "=d"))] "" @@ -1362,7 +1395,7 @@ (define_insn "*negqi2_set" [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QI (match_operand:QI 1 "src_operand" "g")) + (compare:CC_NOOV (neg:QI (match_operand:QI 1 "src_operand" "rIm")) (const_int 0))) (set (match_operand:QI 0 "ext_reg_operand" "=d") (neg:QI (match_dup 1)))] @@ -1373,7 +1406,7 @@ (define_insn "*negbqi2_clobber" [(set (match_operand:QI 0 "ext_reg_operand" "=d") - (neg:QI (match_operand:QI 1 "src_operand" "g"))) + (neg:QI (match_operand:QI 1 "src_operand" "rIm"))) (use (reg:CC_NOOV 21)) (clobber (reg:CC_NOOV 21))] "" @@ -1393,7 +1426,7 @@ (define_insn "*one_cmplqi2_clobber" [(set (match_operand:QI 0 "reg_operand" "=d,c") - (not:QI (match_operand:QI 1 "lsrc_operand" "g,g"))) + (not:QI (match_operand:QI 1 "lsrc_operand" "rLm,rLm"))) (clobber (reg:CC 21))] "" "not\\t%1,%0" @@ -1402,7 +1435,7 @@ (define_insn "*one_cmplqi2_test" [(set (reg:CC 21) - (compare:CC (not:QI (match_operand:QI 1 "lsrc_operand" "g")) + (compare:CC (not:QI (match_operand:QI 1 "lsrc_operand" "rLm")) (const_int 0))) (clobber (match_scratch:QI 0 "=d"))] "" @@ -1412,7 +1445,7 @@ (define_insn "*one_cmplqi2_set" [(set (reg:CC 21) - (compare:CC (not:QI (match_operand:QI 1 "lsrc_operand" "g")) + (compare:CC (not:QI (match_operand:QI 1 "lsrc_operand" "rLm")) (const_int 0))) (set (match_operand:QI 0 "ext_reg_operand" "=d") (not:QI (match_dup 1)))] @@ -1565,7 +1598,7 @@ (define_insn "*addqi3_clobber" [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g"))) + (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,JR,rS<>,rIm"))) (clobber (reg:CC_NOOV 21))] "valid_operands (PLUS, operands, QImode)" "@ @@ -1581,7 +1614,7 @@ (define_insn "*addqi3_test" [(set (reg:CC_NOOV 21) (compare:CC_NOOV (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g")) + (match_operand:QI 2 "src_operand" "JR,rS<>,rIm")) (const_int 0))) (clobber (match_scratch:QI 0 "=d,?d,d"))] "valid_operands (PLUS, operands, QImode)" @@ -1622,7 +1655,7 @@ (define_insn "*addqi3_set" [(set (reg:CC_NOOV 21) (compare:CC_NOOV (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g")) + (match_operand:QI 2 "src_operand" "JR,rS<>,rIm")) (const_int 0))) (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d") (plus:QI (match_dup 1) (match_dup 2)))] @@ -1640,7 +1673,7 @@ (define_insn "addqi3_noclobber" [(set (match_operand:QI 0 "std_reg_operand" "=c,?c,c") (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g")))] + (match_operand:QI 2 "src_operand" "JR,rS<>,rIm")))] "valid_operands (PLUS, operands, QImode)" "@ addi3\\t%2,%1,%0 @@ -1669,7 +1702,7 @@ (define_insn "*addqi3_noclobber_reload" [(set (match_operand:QI 0 "general_operand" "=c,?c,c") (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g")))] + (match_operand:QI 2 "src_operand" "JR,rS<>,rIm")))] "reload_in_progress" "@ addi3\\t%2,%1,%0 @@ -1682,7 +1715,7 @@ (define_insn "*addqi3_carry_clobber" [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g"))) + (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,JR,rS<>,rIm"))) (use (reg:CC_NOOV 21)) (clobber (reg:CC_NOOV 21))] "valid_operands (PLUS, operands, QImode)" @@ -1710,8 +1743,8 @@ (define_insn "*subqi3_clobber" [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,d,c,?c,c,c") - (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g,rR,rS<>,0,g") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,0,JR,rS<>,g,0"))) + (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rIm,rR,rS<>,0,rIm") + (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,0,JR,rS<>,rIm,0"))) (clobber (reg:CC_NOOV 21))] "valid_operands (MINUS, operands, QImode)" "@ @@ -1728,8 +1761,8 @@ (define_insn "*subqi3_test" [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,0")) + (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rIm") + (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,0")) (const_int 0))) (clobber (match_scratch:QI 0 "=d,?d,d,d"))] "valid_operands (MINUS, operands, QImode)" @@ -1743,8 +1776,8 @@ (define_peephole [(parallel [(set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d,d") - (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,0"))) + (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rIm") + (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,0"))) (clobber (reg:CC_NOOV 21))]) (set (reg:CC_NOOV 21) (compare:CC_NOOV (match_dup 0) (const_int 0)))] @@ -1758,8 +1791,8 @@ (define_insn "*subqi3_set" [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,0")) + (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rIm") + (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,0")) (const_int 0))) (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d,d") (minus:QI (match_dup 1) @@ -1775,8 +1808,8 @@ (define_insn "*subqi3_carry_clobber" [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,d,c,?c,c,c") - (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g,rR,rS<>,0,g") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,0,JR,rS<>,g,0"))) + (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rIm,rR,rS<>,0,rIm") + (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,0,JR,rS<>,rIm,0"))) (use (reg:CC_NOOV 21)) (clobber (reg:CC_NOOV 21))] "valid_operands (MINUS, operands, QImode)" @@ -1794,8 +1827,8 @@ (define_insn "*subqi3_carry_set" [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,0")) + (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rIm") + (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,0")) (const_int 0))) (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d,d") (minus:QI (match_dup 1) @@ -1851,7 +1884,7 @@ (define_insn "*mulqi3_clobber" [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") (mult:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g"))) + (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,JR,rS<>,rIm"))) (clobber (reg:CC_NOOV 21))] "valid_operands (MULT, operands, QImode)" "* @@ -1872,7 +1905,7 @@ (define_insn "*mulqi3_test" [(set (reg:CC_NOOV 21) (compare:CC_NOOV (mult:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g")) + (match_operand:QI 2 "src_operand" "JR,rS<>,rIm")) (const_int 0))) (clobber (match_scratch:QI 0 "=d,?d,d"))] "valid_operands (MULT, operands, QImode)" @@ -1894,7 +1927,7 @@ (define_insn "*mulqi3_set" [(set (reg:CC_NOOV 21) (compare:CC_NOOV (mult:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g")) + (match_operand:QI 2 "src_operand" "JR,rS<>,rIm")) (const_int 0))) (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d") (mult:QI (match_dup 1) @@ -1924,7 +1957,7 @@ (and:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0") (const_int 16777215))) (sign_extend:QI - (and:QI (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g") + (and:QI (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,JR,rS<>,rIm") (const_int 16777215))))) (clobber (reg:CC_NOOV 21))] "TARGET_C3X && valid_operands (MULT, operands, QImode)" @@ -2065,7 +2098,7 @@ (lshiftrt:HI (mult:HI (sign_extend:HI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0")) - (sign_extend:HI (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g"))) + (sign_extend:HI (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,JR,rS<>,rIm"))) (const_int 32)))) (clobber (reg:CC_NOOV 21))] "! TARGET_C3X && valid_operands (MULT, operands, QImode)" @@ -2106,7 +2139,7 @@ (lshiftrt:HI (mult:HI (zero_extend:HI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0")) - (zero_extend:HI (match_operand:QI 2 "lsrc_operand" "JR,rS<>,g,JR,rS<>,g"))) + (zero_extend:HI (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm,JR,rS<>,rLm"))) (const_int 32)))) (clobber (reg:CC_NOOV 21))] "! TARGET_C3X && valid_operands (MULT, operands, QImode)" @@ -2414,7 +2447,7 @@ (define_insn "*ashlqi3_clobber" [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") (ashift:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g"))) + (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,JR,rS<>,rIm"))) (clobber (reg:CC 21))] "valid_operands (ASHIFT, operands, QImode)" "@ @@ -2431,7 +2464,7 @@ [(set (reg:CC 21) (compare:CC (ashift:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g")) + (match_operand:QI 2 "src_operand" "JR,rS<>,rIm")) (const_int 0))) (set (match_operand:QI 0 "reg_operand" "=d,?d,d") (ashift:QI (match_dup 1) @@ -2449,7 +2482,7 @@ (define_insn "*lshlqi3_clobber" [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") (ashift:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rR,rS<>,0") - (unspec [(match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g")] 3))) + (unspec [(match_operand:QI 2 "src_operand" "JR,rS<>,rIm,JR,rS<>,rIm")] 3))) (clobber (reg:CC 21))] "valid_operands (ASHIFT, operands, QImode)" "@ @@ -2614,7 +2647,7 @@ (define_insn "*cmpqi_test" [(set (reg:CC 21) (compare:CC (match_operand:QI 0 "src_operand" "rR,?rS<>,r") - (match_operand:QI 1 "src_operand" "JR,rS<>,g")))] + (match_operand:QI 1 "src_operand" "JR,rS<>,rIm")))] "valid_operands (COMPARE, operands, QImode)" "@ cmpi3\\t%1,%0 @@ -2625,7 +2658,7 @@ (define_insn "*cmpqi_test_noov" [(set (reg:CC_NOOV 21) (compare:CC_NOOV (match_operand:QI 0 "src_operand" "rR,?rS<>,r") - (match_operand:QI 1 "src_operand" "JR,rS<>,g")))] + (match_operand:QI 1 "src_operand" "JR,rS<>,rIm")))] "valid_operands (COMPARE, operands, QImode)" "@ cmpi3\\t%1,%0 @@ -2698,7 +2731,7 @@ (define_insn "*extv_clobber" [(set (match_operand:QI 0 "reg_operand" "=d,c") - (sign_extract:QI (match_operand:QI 1 "src_operand" "g,g") + (sign_extract:QI (match_operand:QI 1 "src_operand" "rLm,rLm") (match_operand:QI 2 "const_int_operand" "n,n") (match_operand:QI 3 "const_int_operand" "n,n"))) (clobber (reg:CC 21))] @@ -2719,7 +2752,7 @@ (define_insn "*extv_clobber_test" [(set (reg:CC 21) - (compare:CC (sign_extract:QI (match_operand:QI 1 "src_operand" "g") + (compare:CC (sign_extract:QI (match_operand:QI 1 "src_operand" "rLm") (match_operand:QI 2 "const_int_operand" "n") (match_operand:QI 3 "const_int_operand" "n")) (const_int 0))) @@ -2741,7 +2774,7 @@ (define_insn "*extv_clobber_set" [(set (reg:CC 21) - (compare:CC (sign_extract:QI (match_operand:QI 1 "src_operand" "g") + (compare:CC (sign_extract:QI (match_operand:QI 1 "src_operand" "rLm") (match_operand:QI 2 "const_int_operand" "n") (match_operand:QI 3 "const_int_operand" "n")) (const_int 0))) @@ -2781,7 +2814,7 @@ (define_insn "*extzv_clobber" [(set (match_operand:QI 0 "reg_operand" "=d,c") - (zero_extract:QI (match_operand:QI 1 "src_operand" "g,g") + (zero_extract:QI (match_operand:QI 1 "src_operand" "rLm,rLm") (match_operand:QI 2 "const_int_operand" "n,n") (match_operand:QI 3 "const_int_operand" "n,n"))) (clobber (reg:CC 21))] @@ -2802,7 +2835,7 @@ (define_insn "*extzv_test" [(set (reg:CC 21) - (compare:CC (zero_extract:QI (match_operand:QI 1 "src_operand" "g") + (compare:CC (zero_extract:QI (match_operand:QI 1 "src_operand" "rLm") (match_operand:QI 2 "const_int_operand" "n") (match_operand:QI 3 "const_int_operand" "n")) (const_int 0))) @@ -2824,11 +2857,11 @@ (define_insn "*extzv_set" [(set (reg:CC 21) - (compare:CC (zero_extract:QI (match_operand:QI 1 "src_operand" "g") + (compare:CC (zero_extract:QI (match_operand:QI 1 "src_operand" "rLm") (match_operand:QI 2 "const_int_operand" "n") (match_operand:QI 3 "const_int_operand" "n")) (const_int 0))) - (set (match_operand:QI 0 "reg_operand" "=d") + (set (match_operand:QI 0 "ext_reg_operand" "=d") (zero_extract:QI (match_dup 1) (match_dup 2) (match_dup 3)))] @@ -2867,7 +2900,7 @@ [(set (zero_extract:QI (match_operand:QI 0 "reg_operand" "=d,c") (match_operand:QI 1 "const_int_operand" "n,n") (match_operand:QI 2 "const_int_operand" "n,n")) - (match_operand:QI 3 "src_operand" "g,g")) + (match_operand:QI 3 "src_operand" "rLm,rLm")) (clobber (reg:CC 21))] "! TARGET_C3X && (((INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16) @@ -2890,10 +2923,10 @@ (set_attr "data" "uint16,uint16")]) (define_peephole - [(parallel [(set (zero_extract:QI (match_operand:QI 0 "reg_operand" "=d") + [(parallel [(set (zero_extract:QI (match_operand:QI 0 "ext_reg_operand" "=d") (match_operand:QI 1 "const_int_operand" "n") (match_operand:QI 2 "const_int_operand" "n")) - (match_operand:QI 3 "src_operand" "g")) + (match_operand:QI 3 "src_operand" "rLm")) (clobber (reg:CC 21))]) (set (reg:CC 21) (compare:CC (match_dup 0) (const_int 0)))] @@ -2929,28 +2962,17 @@ (match_operand:QF 1 "src_operand" ""))] "" " - if (CONSTANT_P (operands[1]) && ! const_operand (operands[1], QFmode)) - { - operands[1] = force_const_mem (QFmode, operands[1]); - if (! memory_address_p (QFmode, XEXP (operands[1], 0)) - && ! reload_in_progress) - operands[1] = change_address (operands[1], QFmode, - XEXP (operands[1], 0)); - } - - if (! reload_in_progress - && ! reg_operand (operands[0], QFmode) - && ! reg_operand (operands[1], QFmode)) - operands[1] = force_reg (QFmode, operands[1]); - ") +{ + if (c4x_emit_move_sequence (operands, QFmode)) + DONE; +}") ; We must provide an alternative to store to memory in case we have to ; spill a register. -(define_insn "*movqf_noclobber" +(define_insn "movqf_noclobber" [(set (match_operand:QF 0 "src_operand" "=f,m") - (match_operand:QF 1 "src_operand" "fmH,f"))] - "reg_operand (operands[0], QFmode) - || reg_operand (operands[1], QFmode)" + (match_operand:QF 1 "src_operand" "fHm,f"))] + "REG_P (operands[0]) || REG_P (operands[1])" "@ ldfu\\t%1,%0 stf\\t%1,%0" @@ -2958,7 +2980,7 @@ ;(define_insn "*movqf_clobber" ; [(set (match_operand:QF 0 "reg_operand" "=f") -; (match_operand:QF 1 "src_operand" "fmH")) +; (match_operand:QF 1 "src_operand" "fHm")) ; (clobber (reg:CC 21))] ; "0" ; "ldf\\t%1,%0" @@ -2966,7 +2988,7 @@ (define_insn "*movqf_test" [(set (reg:CC 21) - (compare:CC (match_operand:QF 1 "src_operand" "fmH") + (compare:CC (match_operand:QF 1 "src_operand" "fHm") (const_int 0))) (clobber (match_scratch:QF 0 "=f"))] "" @@ -2975,7 +2997,7 @@ (define_insn "*movqf_set" [(set (reg:CC 21) - (compare:CC (match_operand:QF 1 "src_operand" "fmH") + (compare:CC (match_operand:QF 1 "src_operand" "fHm") (match_operand:QF 2 "fp_zero_operand" "G"))) (set (match_operand:QF 0 "reg_operand" "=f") (match_dup 1))] @@ -3038,7 +3060,7 @@ (define_insn "*absqf2_clobber" [(set (match_operand:QF 0 "reg_operand" "=f") - (abs:QF (match_operand:QF 1 "src_operand" "fmH"))) + (abs:QF (match_operand:QF 1 "src_operand" "fHm"))) (clobber (reg:CC_NOOV 21))] "" "absf\\t%1,%0" @@ -3046,7 +3068,7 @@ (define_insn "*absqf2_test" [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:QF (match_operand:QF 1 "src_operand" "fmH")) + (compare:CC_NOOV (abs:QF (match_operand:QF 1 "src_operand" "fHm")) (match_operand:QF 2 "fp_zero_operand" "G"))) (clobber (match_scratch:QF 0 "=f"))] "" @@ -3055,7 +3077,7 @@ (define_insn "*absqf2_set" [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:QF (match_operand:QF 1 "src_operand" "fmH")) + (compare:CC_NOOV (abs:QF (match_operand:QF 1 "src_operand" "fHm")) (match_operand:QF 2 "fp_zero_operand" "G"))) (set (match_operand:QF 0 "reg_operand" "=f") (abs:QF (match_dup 1)))] @@ -3076,7 +3098,7 @@ (define_insn "*negqf2_clobber" [(set (match_operand:QF 0 "reg_operand" "=f") - (neg:QF (match_operand:QF 1 "src_operand" "fmH"))) + (neg:QF (match_operand:QF 1 "src_operand" "fHm"))) (clobber (reg:CC_NOOV 21))] "" "negf\\t%1,%0" @@ -3084,7 +3106,7 @@ (define_insn "*negqf2_test" [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QF (match_operand:QF 1 "src_operand" "fmH")) + (compare:CC_NOOV (neg:QF (match_operand:QF 1 "src_operand" "fHm")) (match_operand:QF 2 "fp_zero_operand" "G"))) (clobber (match_scratch:QF 0 "=f"))] "" @@ -3093,7 +3115,7 @@ (define_insn "*negqf2_set" [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QF (match_operand:QF 1 "src_operand" "fmH")) + (compare:CC_NOOV (neg:QF (match_operand:QF 1 "src_operand" "fHm")) (match_operand:QF 2 "fp_zero_operand" "G"))) (set (match_operand:QF 0 "reg_operand" "=f") (neg:QF (match_dup 1)))] @@ -3106,7 +3128,7 @@ ; (define_insn "floatqiqf2" [(set (match_operand:QF 0 "reg_operand" "=f") - (float:QF (match_operand:QI 1 "src_operand" "g"))) + (float:QF (match_operand:QI 1 "src_operand" "rIm"))) (clobber (reg:CC 21))] "" "float\\t%1,%0" @@ -3114,17 +3136,17 @@ (define_insn "*floatqiqf2_set" [(set (reg:CC 21) - (compare:CC (float:QF (match_operand:QI 1 "src_operand" "g")) + (compare:CC (float:QF (match_operand:QI 1 "src_operand" "rIm")) (match_operand:QF 2 "fp_zero_operand" "G"))) (set (match_operand:QF 0 "reg_operand" "=f") (float:QF (match_dup 1)))] - "" "float\\t%1,%0" [(set_attr "type" "unarycc")]) ; Unsigned conversions are a little tricky because we need to ; add the value for the high bit if necessary. +; ; (define_expand "floatunsqiqf2" [(set (match_dup 2) (match_dup 3)) @@ -3133,22 +3155,25 @@ (match_dup 3))) (set (match_dup 4) (float:QF (match_dup 1)))]) - (set (match_dup 2) + (set (match_dup 6) (if_then_else:QF (lt (reg:CC 21) (const_int 0)) - (mem:QF (symbol_ref:QF "*___unsfltconst")) + (match_dup 5) (match_dup 2))) (parallel [(set (match_operand:QF 0 "reg_operand" "") - (plus:QF (match_dup 2) (match_dup 4))) + (plus:QF (match_dup 6) (match_dup 4))) (clobber (reg:CC_NOOV 21))])] "" "operands[2] = gen_reg_rtx (QFmode); operands[3] = CONST0_RTX (QFmode); operands[4] = gen_reg_rtx (QFmode); - ") + operands[5] = gen_reg_rtx (QFmode); + operands[6] = gen_reg_rtx (QFmode); + emit_move_insn (operands[5], + immed_real_const_1 (REAL_VALUE_ATOF (\"4294967296.0\", QFmode), QFmode));") (define_insn "floatqihf2" [(set (match_operand:HF 0 "reg_operand" "=h") - (float:HF (match_operand:QI 1 "src_operand" "g"))) + (float:HF (match_operand:QI 1 "src_operand" "rIm"))) (clobber (reg:CC 21))] "" "float\\t%1,%0" @@ -3159,7 +3184,7 @@ ; (define_insn "fixqfqi_clobber" [(set (match_operand:QI 0 "reg_operand" "=d,c") - (fix:QI (match_operand:QF 1 "src_operand" "fmH,fmH"))) + (fix:QI (match_operand:QF 1 "src_operand" "fHm,fHm"))) (clobber (reg:CC 21))] "" "fix\\t%1,%0" @@ -3167,9 +3192,9 @@ (define_insn "*fixqfqi_set" [(set (reg:CC 21) - (compare:CC (fix:QI (match_operand:QF 1 "src_operand" "fmH")) + (compare:CC (fix:QI (match_operand:QF 1 "src_operand" "fHm")) (const_int 0))) - (set (match_operand:QI 0 "reg_operand" "=d") + (set (match_operand:QI 0 "ext_reg_operand" "=d") (fix:QI (match_dup 1)))] "" "fix\\t%1,%0" @@ -3215,26 +3240,20 @@ "c4x_emit_libcall (FIX_TRUNCQFHI2_LIBCALL, FIX, HImode, QFmode, 2, operands); DONE;") +; Is this allowed to be implementation dependent? If so, we can +; omit the conditional load. Otherwise we should emit a split. (define_expand "fixuns_truncqfqi2" - [(set (match_dup 2) (match_dup 4)) - (set (reg:CC 21) - (compare:CC (match_operand:QF 1 "reg_operand" "") - (mem:QF (symbol_ref "*___unsfltcompare")))) - (set (match_dup 2) - (if_then_else:QF (ge (reg:CC 21) (const_int 0)) - (mem:QF (symbol_ref "*___unsfltconst")) - (match_dup 2))) - (parallel [(set (match_dup 3) - (minus:QF (match_dup 1) (match_dup 2))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_operand:QI 0 "reg_operand" "") - (fix:QI (match_dup 3))) - (clobber (reg:CC 21))])] + [(parallel [(set (reg:CC 21) + (compare:CC (fix:QI (match_operand:QF 1 "src_operand" "fHm")) + (const_int 0))) + (set (match_dup 2) + (fix:QI (match_dup 1)))]) + (set (match_operand:QI 0 "reg_operand" "=r") + (if_then_else:QI (lt (reg:CC 21) (const_int 0)) + (const_int 0) + (match_dup 2)))] "" - "operands[2] = gen_reg_rtx (QFmode); - operands[3] = gen_reg_rtx (QFmode); - operands[4] = CONST0_RTX (QFmode); - ") + "operands[2] = gen_reg_rtx (QImode);") (define_expand "fixuns_truncqfhi2" [(parallel [(set (match_operand:HI 0 "reg_operand" "") @@ -3250,7 +3269,7 @@ ; (define_insn "*rcpfqf_clobber" [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec [(match_operand:QF 1 "src_operand" "fmH")] 5)) + (unspec [(match_operand:QF 1 "src_operand" "fHm")] 5)) (clobber (reg:CC_NOOV 21))] "! TARGET_C3X" "rcpf\\t%1,%0" @@ -3261,7 +3280,7 @@ ; (define_insn "*rsqrfqf_clobber" [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec [(match_operand:QF 1 "src_operand" "fmH")] 10)) + (unspec [(match_operand:QF 1 "src_operand" "fHm")] 10)) (clobber (reg:CC_NOOV 21))] "! TARGET_C3X" "rsqrf\\t%1,%0" @@ -3272,7 +3291,7 @@ ; (define_insn "*rndqf_clobber" [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec [(match_operand:QF 1 "src_operand" "fmH")] 6)) + (unspec [(match_operand:QF 1 "src_operand" "fHm")] 6)) (clobber (reg:CC_NOOV 21))] "! TARGET_C3X" "rnd\\t%1,%0" @@ -3351,7 +3370,7 @@ (define_insn "*addqf3_clobber" [(set (match_operand:QF 0 "reg_operand" "=f,?f,f") (plus:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH"))) + (match_operand:QF 2 "src_operand" "R,fS<>,fHm"))) (clobber (reg:CC_NOOV 21))] "valid_operands (PLUS, operands, QFmode)" "@ @@ -3363,7 +3382,7 @@ (define_insn "*addqf3_test" [(set (reg:CC_NOOV 21) (compare:CC_NOOV (plus:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH")) + (match_operand:QF 2 "src_operand" "R,fS<>,fHm")) (match_operand:QF 3 "fp_zero_operand" "G,G,G"))) (clobber (match_scratch:QF 0 "=f,?f,f"))] "valid_operands (PLUS, operands, QFmode)" @@ -3376,7 +3395,7 @@ (define_insn "*addqf3_set" [(set (reg:CC_NOOV 21) (compare:CC_NOOV (plus:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH")) + (match_operand:QF 2 "src_operand" "R,fS<>,fHm")) (match_operand:QF 3 "fp_zero_operand" "G,G,G"))) (set (match_operand:QF 0 "reg_operand" "=f,?f,f") (plus:QF (match_dup 1) @@ -3401,8 +3420,8 @@ (define_insn "*subqf3_clobber" [(set (match_operand:QF 0 "reg_operand" "=f,?f,f,f") - (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fmH") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH,0"))) + (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fHm") + (match_operand:QF 2 "src_operand" "R,fS<>,fHm,0"))) (clobber (reg:CC_NOOV 21))] "valid_operands (MINUS, operands, QFmode)" "@ @@ -3414,8 +3433,8 @@ (define_insn "*subqf3_test" [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fmH") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH,0")) + (compare:CC_NOOV (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fHm") + (match_operand:QF 2 "src_operand" "R,fS<>,fHm,0")) (match_operand:QF 3 "fp_zero_operand" "G,G,G,G"))) (clobber (match_scratch:QF 0 "=f,?f,f,f"))] "valid_operands (MINUS, operands, QFmode)" @@ -3428,8 +3447,8 @@ (define_insn "*subqf3_set" [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fmH") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH,0")) + (compare:CC_NOOV (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fHm") + (match_operand:QF 2 "src_operand" "R,fS<>,fHm,0")) (match_operand:QF 3 "fp_zero_operand" "G,G,G,G"))) (set (match_operand:QF 0 "reg_operand" "=f,?f,f,f") (minus:QF (match_dup 1) @@ -3456,7 +3475,7 @@ (define_insn "*mulqf3_clobber" [(set (match_operand:QF 0 "reg_operand" "=f,?f,f") (mult:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH"))) + (match_operand:QF 2 "src_operand" "R,fS<>,fHm"))) (clobber (reg:CC_NOOV 21))] "valid_operands (MULT, operands, QFmode)" "@ @@ -3468,7 +3487,7 @@ (define_insn "*mulqf3_test" [(set (reg:CC_NOOV 21) (compare:CC_NOOV (mult:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH")) + (match_operand:QF 2 "src_operand" "R,fS<>,fHm")) (match_operand:QF 3 "fp_zero_operand" "G,G,G"))) (clobber (match_scratch:QF 0 "=f,?f,f"))] "valid_operands (MULT, operands, QFmode)" @@ -3481,7 +3500,7 @@ (define_insn "*mulqf3_set" [(set (reg:CC_NOOV 21) (compare:CC_NOOV (mult:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH")) + (match_operand:QF 2 "src_operand" "R,fS<>,fHm")) (match_operand:QF 3 "fp_zero_operand" "G,G,G"))) (set (match_operand:QF 0 "reg_operand" "=f,?f,f") (mult:QF (match_dup 1) @@ -3509,7 +3528,7 @@ (define_insn "*cmpqf" [(set (reg:CC 21) (compare:CC (match_operand:QF 0 "src_operand" "fR,?fS<>,f") - (match_operand:QF 1 "src_operand" "R,fS<>,fmH")))] + (match_operand:QF 1 "src_operand" "R,fS<>,fHm")))] "valid_operands (COMPARE, operands, QFmode)" "@ cmpf3\\t%1,%0 @@ -3520,7 +3539,7 @@ (define_insn "*cmpqf_noov" [(set (reg:CC_NOOV 21) (compare:CC_NOOV (match_operand:QF 0 "src_operand" "fR,?fS<>,f") - (match_operand:QF 1 "src_operand" "R,fS<>,fmH")))] + (match_operand:QF 1 "src_operand" "R,fS<>,fHm")))] "valid_operands (COMPARE, operands, QFmode)" "@ cmpf3\\t%1,%0 @@ -3586,8 +3605,8 @@ [(set (match_operand:QI 0 "reg_operand" "=r,r") (if_then_else:QI (match_operator 1 "comparison_operator" [(reg:CC 21) (const_int 0)]) - (match_operand:QI 2 "src_operand" "g,0") - (match_operand:QI 3 "src_operand" "0,g")))] + (match_operand:QI 2 "src_operand" "rIm,0") + (match_operand:QI 3 "src_operand" "0,rIm")))] "" "@ ldi%1\\t%2,%0 @@ -3598,8 +3617,8 @@ [(set (match_operand:QI 0 "reg_operand" "=r,r") (if_then_else:QI (match_operator 1 "comparison_operator" [(reg:CC_NOOV 21) (const_int 0)]) - (match_operand:QI 2 "src_operand" "g,0") - (match_operand:QI 3 "src_operand" "0,g")))] + (match_operand:QI 2 "src_operand" "rIm,0") + (match_operand:QI 3 "src_operand" "0,rIm")))] "GET_CODE (operands[1]) != LE && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != LT @@ -3634,8 +3653,8 @@ [(set (match_operand:QF 0 "reg_operand" "=f,f") (if_then_else:QF (match_operator 1 "comparison_operator" [(reg:CC 21) (const_int 0)]) - (match_operand:QF 2 "src_operand" "fmH,0") - (match_operand:QF 3 "src_operand" "0,fmH")))] + (match_operand:QF 2 "src_operand" "fHm,0") + (match_operand:QF 3 "src_operand" "0,fHm")))] "" "@ ldf%1\\t%2,%0 @@ -3646,8 +3665,8 @@ [(set (match_operand:QF 0 "reg_operand" "=f,f") (if_then_else:QF (match_operator 1 "comparison_operator" [(reg:CC_NOOV 21) (const_int 0)]) - (match_operand:QF 2 "src_operand" "fmH,0") - (match_operand:QF 3 "src_operand" "0,fmH")))] + (match_operand:QF 2 "src_operand" "fHm,0") + (match_operand:QF 3 "src_operand" "0,fHm")))] "GET_CODE (operands[1]) != LE && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != LT @@ -4336,92 +4355,68 @@ ; CALL ; (define_insn "*call_c3x" - [(call (match_operand:QI 0 "call_operand" "T,!o") + [(call (mem:QI (match_operand:QI 0 "call_operand" "")) (match_operand:QI 1 "general_operand" "")) (clobber (reg:QI 31))] ;; Operand 1 not really used on the C4x. The C30 doesn't have reg 31. "TARGET_C3X" - "@ - call\\t%C0 - callu\\t%R0" - [(set_attr "type" "call,call")]) + "call%U0\\t%C0" + [(set_attr "type" "call")]) ; LAJ requires R11 (31) for the return address (define_insn "*laj" - [(call (match_operand:QI 0 "call_operand" "T,!o") + [(call (mem:QI (match_operand:QI 0 "call_operand" "")) (match_operand:QI 1 "general_operand" "")) (clobber (reg:QI 31))] ;; Operand 1 not really used on the C4x. "! TARGET_C3X" "* - if (which_alternative == 0) - { - if (final_sequence) - return \"laj\\t%C0\"; - else - return \"call\\t%C0\"; - } + if (final_sequence) + return \"laj%U0\\t%C0\"; else - { - if (final_sequence) - return \"laju\\t%R0\"; - else - return \"callu\\t%R0\"; - }" - [(set_attr "type" "laj,laj")]) + return \"call%U0\\t%C0\";" + [(set_attr "type" "laj")]) (define_expand "call" - [(parallel [(call (match_operand:QI 0 "call_operand" "") + [(parallel [(call (mem:QI (match_operand:QI 0 "call_operand" "")) (match_operand:QI 1 "general_operand" "")) (clobber (reg:QI 31))])] "" "") (define_insn "*callv_c3x" - [(set (match_operand 0 "" "=r,r") - (call (match_operand:QI 1 "call_operand" "T,!o") + [(set (match_operand 0 "" "=r") + (call (mem:QI (match_operand:QI 1 "call_operand" "")) (match_operand:QI 2 "general_operand" ""))) (clobber (reg:QI 31))] ;; Operand 0 and 2 not really used for the C4x. ;; The C30 doesn't have reg 31. "TARGET_C3X" - "@ - call\\t%C1 - callu\\t%R1" - [(set_attr "type" "call,call")]) + "call%U1\\t%C1" + [(set_attr "type" "call")]) ; LAJ requires R11 (31) for the return address (define_insn "*lajv" - [(set (match_operand 0 "" "=r,r") - (call (match_operand:QI 1 "call_operand" "T,!o") + [(set (match_operand 0 "" "=r") + (call (mem:QI (match_operand:QI 1 "call_operand" "")) (match_operand:QI 2 "general_operand" ""))) (clobber (reg:QI 31))] ;; Operand 0 and 2 not really used in the C30 instruction. "! TARGET_C3X" "* - if (which_alternative == 0) - { - if (final_sequence) - return \"laj\\t%C1\"; - else - return \"call\\t%C1\"; - } + if (final_sequence) + return \"laj%U1\\t%C1\"; else - { - if (final_sequence) - return \"laju\\t%R1\"; - else - return \"callu\\t%R1\"; - }" - [(set_attr "type" "laj,laj")]) + return \"call%U1\\t%C1\";" + [(set_attr "type" "laj")]) (define_expand "call_value" [(parallel [(set (match_operand 0 "" "") - (call (match_operand:QI 1 "call_operand" "") + (call (mem:QI (match_operand:QI 1 "call_operand" "")) (match_operand:QI 2 "general_operand" ""))) (clobber (reg:QI 31))])] "" @@ -4787,7 +4782,7 @@ (define_insn "*cmpstrqi" - [(set (match_operand:QI 0 "reg_operand" "=d") + [(set (match_operand:QI 0 "ext_reg_operand" "=d") (compare:QI (mem:BLK (match_operand:QI 1 "addr_reg_operand" "a")) (mem:BLK (match_operand:QI 2 "addr_reg_operand" "a")))) (use (match_operand:QI 3 "immediate_operand" "i")) @@ -4833,32 +4828,20 @@ [(set (match_operand:HF 0 "src_operand" "") (match_operand:HF 1 "src_operand" ""))] "" - "if (CONSTANT_P (operands[1])) - { - operands[1] = force_const_mem (HFmode, operands[1]); - if (! memory_address_p (HFmode, XEXP (operands[1], 0)) - && ! reload_in_progress) - operands[1] = change_address (operands[1], HFmode, - XEXP (operands[1], 0)); - } - - /* Memory to memory copies must go through a register. */ - if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[0]) == MEM - && ! reload_in_progress) - operands[1] = force_reg (HFmode, operands[1]); -") + "if (c4x_emit_move_sequence (operands, HFmode)) + DONE;") (define_insn "*movhf_noclobber_reg" [(set (match_operand:HF 0 "reg_operand" "=h") - (match_operand:HF 1 "reg_operand" "h"))] - "" + (match_operand:HF 1 "src_operand" "Hh"))] + "GET_CODE (operands[1]) != MEM" "ldfu\\t%1,%0" [(set_attr "type" "unary")]) ; The predicates could be tightened to disallow constants (define_insn "*movhf_noclobber" [(set (match_operand:HF 0 "src_operand" "=h,m") - (match_operand:HF 1 "src_operand" "m,h"))] + (match_operand:HF 1 "src_operand" "HQT>,h"))] "reg_operand (operands[0], HFmode) ^ reg_operand (operands[1], HFmode)" "#" [(set_attr "type" "multi,multi")]) @@ -4917,7 +4900,7 @@ (define_insn "*loadhf_float" [(set (match_operand:HF 0 "reg_operand" "=h") - (float_extend:HF (match_operand:QF 1 "src_operand" "fmH")))] + (float_extend:HF (match_operand:QF 1 "src_operand" "fHm")))] "" "@ ldfu\\t%1,%0" @@ -4926,7 +4909,7 @@ (define_insn "*loadhf_int" [(set (match_operand:HF 0 "reg_operand" "=h") (unspec[(subreg:QI (match_dup 0) 0) - (match_operand:QI 1 "src_operand" "g")] 8))] + (match_operand:QI 1 "src_operand" "rIm")] 8))] "" "@ ldiu\\t%1,%0" @@ -5372,22 +5355,8 @@ [(set (match_operand:HI 0 "src_operand" "") (match_operand:HI 1 "src_operand" ""))] "" - "if (CONSTANT_P (operands[1])) - { - /* We don't need to force all constants into memory. - This could be improved.... */ - operands[1] = force_const_mem (HImode, operands[1]); - if (! memory_address_p (HImode, XEXP (operands[1], 0)) - && ! reload_in_progress) - operands[1] = change_address (operands[1], HImode, - XEXP (operands[1], 0)); - } - - /* Memory to memory copies must go through a register. */ - if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[0]) == MEM - && ! reload_in_progress) - operands[1] = force_reg (HImode, operands[1]); -") + "if (c4x_emit_move_sequence (operands, HImode)) + DONE;") ; The constraints for movhi must include 'r' if we don't ; restrict HImode regnos to start on an even number, since @@ -5395,7 +5364,7 @@ ; votes for FP_REGS so we use dr as the constraints. (define_insn "*movhi_noclobber" [(set (match_operand:HI 0 "src_operand" "=dr,m") - (match_operand:HI 1 "src_operand" "drm,r"))] + (match_operand:HI 1 "src_operand" "drIQT>,r"))] "reg_operand (operands[0], HImode) || reg_operand (operands[1], HImode)" "#" @@ -5416,7 +5385,7 @@ (define_insn "extendqihi2" [(set (match_operand:HI 0 "reg_operand" "=dc") - (sign_extend:HI (match_operand:QI 1 "src_operand" "g"))) + (sign_extend:HI (match_operand:QI 1 "src_operand" "rIm"))) (clobber (reg:CC 21))] "" "#" @@ -5424,7 +5393,7 @@ (define_split [(set (match_operand:HI 0 "reg_operand" "=?dc") - (sign_extend:HI (match_operand:QI 1 "src_operand" "g"))) + (sign_extend:HI (match_operand:QI 1 "src_operand" "rIm"))) (clobber (reg:CC 21))] "reload_completed && TARGET_C3X" [(set (match_dup 2) (match_dup 1)) @@ -5436,7 +5405,7 @@ (define_split [(set (match_operand:HI 0 "reg_operand" "=?dc") - (sign_extend:HI (match_operand:QI 1 "src_operand" "g"))) + (sign_extend:HI (match_operand:QI 1 "src_operand" "rIm"))) (clobber (reg:CC 21))] "reload_completed && ! TARGET_C3X" [(set (match_dup 2) (match_dup 1)) @@ -5447,7 +5416,7 @@ (define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "reg_operand" "=?dc") - (zero_extend:HI (match_operand:QI 1 "src_operand" "g"))) + (zero_extend:HI (match_operand:QI 1 "src_operand" "rIm"))) (clobber (reg:CC 21))] "" "#" @@ -5457,7 +5426,7 @@ ; the first set. (define_split [(set (match_operand:HI 0 "reg_operand" "=?dc") - (zero_extend:HI (match_operand:QI 1 "src_operand" "g"))) + (zero_extend:HI (match_operand:QI 1 "src_operand" "rIm"))) (clobber (reg:CC 21))] "reload_completed" [(set (match_dup 2) (match_dup 1)) @@ -6209,12 +6178,12 @@ (parallel [(set (pc) (if_then_else - (ge (plus:QI (match_operand:QI 4 "addr_reg_operand" "0") + (ge (plus:QI (match_operand:QI 0 "addr_reg_operand" "+a") (const_int -1)) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc))) - (set (match_operand:QI 0 "addr_reg_operand" "+a") + (set (match_dup 0) (plus:QI (match_dup 0) (const_int -1))) (clobber (reg:CC_NOOV 21))])] @@ -6230,11 +6199,11 @@ (parallel [(set (pc) (if_then_else - (ne (match_operand:QI 4 "addr_reg_operand" "0") + (ne (match_operand:QI 0 "addr_reg_operand" "+a") (const_int 0)) (label_ref (match_operand 1 "" "")) (pc))) - (set (match_operand:QI 0 "addr_reg_operand" "+a") + (set (match_dup 0) (plus:QI (match_dup 0) (const_int -1))) (clobber (reg:CC_NOOV 21))])] @@ -6246,27 +6215,31 @@ ; Peepholes to convert 'call label; rets' into jump label ; (define_peephole - [(parallel [(call (match_operand:QI 0 "call_operand" "T,!o") + [(parallel [(call (mem:QI (match_operand:QI 0 "call_operand" "")) (match_operand:QI 1 "general_operand" "")) (clobber (reg:QI 31))]) (return)] "c4x_null_epilogue_p ()" - "@ - br%#\\t%C0 - bu%#\\t%R0" - [(set_attr "type" "jump,jump")]) + "* + if (GET_CODE (XEXP (operands[0], 0)) == REG) + return \"bu%#\\t%C0\"; + else + return \"br%#\\t%C0\";" + [(set_attr "type" "jump")]) (define_peephole [(parallel [(set (match_operand 0 "" "") - (call (match_operand:QI 1 "call_operand" "T,!o") + (call (mem:QI (match_operand:QI 1 "call_operand" "")) (match_operand:QI 2 "general_operand" ""))) (clobber (reg:QI 31))]) (return)] "c4x_null_epilogue_p ()" - "@ - br%#\\t%C1 - bu%#\\t%R1" - [(set_attr "type" "jump,jump")]) + "* + if (GET_CODE (XEXP (operands[1], 0)) == REG) + return \"bu%#\\t%C1\"; + else + return \"br%#\\t%C1\";" + [(set_attr "type" "jump")]) ; ; Peepholes for parallel instructions