diff options
Diffstat (limited to 'gcc/config/m32r/m32r.c')
| -rw-r--r-- | gcc/config/m32r/m32r.c | 503 |
1 files changed, 405 insertions, 98 deletions
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c index 4b23157..f547332 100644 --- a/gcc/config/m32r/m32r.c +++ b/gcc/config/m32r/m32r.c @@ -35,6 +35,7 @@ Boston, MA 02111-1307, USA. */ #include "function.h" #include "recog.h" #include "toplev.h" +#include "m32r-protos.h" /* Save the operands last given to a compare for use when we generate a scc or bcc insn. */ @@ -44,16 +45,18 @@ rtx m32r_compare_op0, m32r_compare_op1; char m32r_punct_chars[256]; /* Selected code model. */ -char *m32r_model_string = M32R_MODEL_DEFAULT; +const char * m32r_model_string = M32R_MODEL_DEFAULT; enum m32r_model m32r_model; /* Selected SDA support. */ -char *m32r_sdata_string = M32R_SDATA_DEFAULT; +const char * m32r_sdata_string = M32R_SDATA_DEFAULT; enum m32r_sdata m32r_sdata; +/* Scheduler support */ +int m32r_sched_odd_word_p; /* Forward declaration. */ -static void init_reg_tables PROTO((void)); +static void init_reg_tables PROTO ((void)); /* Called by OVERRIDE_OPTIONS to initialize various things. */ @@ -88,7 +91,6 @@ m32r_init () m32r_sdata = M32R_SDATA_USE; else error ("bad value (%s) for -msdata switch", m32r_sdata_string); - } /* Vectors to keep interesting information about registers where it can easily @@ -104,7 +106,7 @@ enum m32r_mode_class { C_MODE, S_MODE, D_MODE, T_MODE, O_MODE, - SF_MODE, DF_MODE, TF_MODE, OF_MODE + SF_MODE, DF_MODE, TF_MODE, OF_MODE, A_MODE }; /* Modes for condition codes. */ @@ -119,6 +121,8 @@ enum m32r_mode_class /* Modes for quad-word and smaller quantities. */ #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE)) +/* Modes for accumulators. */ +#define A_MODES (1 << (int) A_MODE) /* Value is 1 if register/mode pair is acceptable on arc. */ @@ -126,7 +130,7 @@ unsigned int m32r_hard_regno_mode_ok[FIRST_PSEUDO_REGISTER] = { T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, S_MODES, S_MODES, S_MODES, - S_MODES, C_MODES + S_MODES, C_MODES, A_MODES }; unsigned int m32r_mode_class [NUM_MACHINE_MODES]; @@ -451,23 +455,21 @@ m32r_init_expanders () /* Acceptable arguments to the call insn. */ int -call_address_operand (op, int_mode) +call_address_operand (op, mode) rtx op; - int int_mode; + enum machine_mode mode; { - return symbolic_operand (op, int_mode); + return symbolic_operand (op, mode); /* Constants and values in registers are not OK, because the m32r BL instruction can only support PC relative branching. */ } int -call_operand (op, int_mode) +call_operand (op, mode) rtx op; - int int_mode; + enum machine_mode mode; { - enum machine_mode mode = (enum machine_mode)int_mode; - if (GET_CODE (op) != MEM) return 0; op = XEXP (op, 0); @@ -477,9 +479,9 @@ call_operand (op, int_mode) /* Returns 1 if OP is a symbol reference. */ int -symbolic_operand (op, int_mode) +symbolic_operand (op, mode) rtx op; - int int_mode ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; { switch (GET_CODE (op)) { @@ -496,9 +498,9 @@ symbolic_operand (op, int_mode) /* Return 1 if OP is a reference to an object in .sdata/.sbss. */ int -small_data_operand (op, int_mode) +small_data_operand (op, mode) rtx op; - int int_mode ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; { if (! TARGET_SDATA_USE) return 0; @@ -519,9 +521,9 @@ small_data_operand (op, int_mode) /* Return 1 if OP is a symbol that can use 24 bit addressing. */ int -addr24_operand (op, int_mode) +addr24_operand (op, mode) rtx op; - int int_mode ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; { if (GET_CODE (op) == LABEL_REF) return TARGET_ADDR24; @@ -551,24 +553,24 @@ addr24_operand (op, int_mode) /* Return 1 if OP is a symbol that needs 32 bit addressing. */ int -addr32_operand (op, int_mode) +addr32_operand (op, mode) rtx op; - int int_mode; + enum machine_mode mode; { if (GET_CODE (op) == LABEL_REF) return TARGET_ADDR32; if (GET_CODE (op) == SYMBOL_REF) - return (! addr24_operand (op, int_mode) - && ! small_data_operand (op, int_mode)); + return (! addr24_operand (op, mode) + && ! small_data_operand (op, mode)); 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), 1)) == CONST_INT) { - return (! addr24_operand (op, int_mode) - && ! small_data_operand (op, int_mode)); + return (! addr24_operand (op, mode) + && ! small_data_operand (op, mode)); } return 0; @@ -577,9 +579,9 @@ addr32_operand (op, int_mode) /* Return 1 if OP is a function that can be called with the `bl' insn. */ int -call26_operand (op, int_mode) +call26_operand (op, mode) rtx op; - int int_mode ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; { if (GET_CODE (op) == SYMBOL_REF) return ! LARGE_NAME_P (XSTR (op, 0)); @@ -590,9 +592,9 @@ call26_operand (op, int_mode) /* Returns 1 if OP is an acceptable operand for seth/add3. */ int -seth_add3_operand (op, int_mode) +seth_add3_operand (op, mode) rtx op; - int int_mode ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; { if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF) @@ -608,13 +610,25 @@ seth_add3_operand (op, int_mode) return 0; } +/* Return true if OP is a signed 8 bit immediate value. */ + +int +int8_operand (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + if (GET_CODE (op) != CONST_INT) + return 0; + return INT8_P (INTVAL (op)); +} + /* Return true if OP is a signed 16 bit immediate value useful in comparisons. */ int -cmp_int16_operand (op, int_mode) +cmp_int16_operand (op, mode) rtx op; - int int_mode ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; { if (GET_CODE (op) != CONST_INT) return 0; @@ -624,24 +638,22 @@ cmp_int16_operand (op, int_mode) /* Return true if OP is an unsigned 16 bit immediate value. */ int -uint16_operand (op, int_mode) +uint16_operand (op, mode) rtx op; - int int_mode ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; { if (GET_CODE (op) != CONST_INT) return 0; return UINT16_P (INTVAL (op)); } -/* Return true if OP is a register or signed 8 bit value. */ +/* Return true if OP is a register or signed 16 bit value. */ int -reg_or_int16_operand (op, int_mode) +reg_or_int16_operand (op, mode) rtx op; - int int_mode; + enum machine_mode mode; { - enum machine_mode mode = (enum machine_mode)int_mode; - if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG) return register_operand (op, mode); if (GET_CODE (op) != CONST_INT) @@ -652,12 +664,10 @@ reg_or_int16_operand (op, int_mode) /* Return true if OP is a register or an unsigned 16 bit value. */ int -reg_or_uint16_operand (op, int_mode) +reg_or_uint16_operand (op, mode) rtx op; - int int_mode; + enum machine_mode mode; { - enum machine_mode mode = (enum machine_mode)int_mode; - if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG) return register_operand (op, mode); if (GET_CODE (op) != CONST_INT) @@ -665,17 +675,37 @@ reg_or_uint16_operand (op, int_mode) return UINT16_P (INTVAL (op)); } -/* Return true if OP is a register or signed 16 bit value for compares. */ +/* Return true if OP is a register or an integer value that can be + used is SEQ/SNE. We can use either XOR of the value or ADD of + the negative of the value for the constant. Don't allow 0, + because that is special cased. */ int -reg_or_cmp_int16_operand (op, int_mode) +reg_or_eq_int16_operand (op, mode) rtx op; - int int_mode; + enum machine_mode mode; { - enum machine_mode mode = (enum machine_mode)int_mode; + HOST_WIDE_INT value; if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG) return register_operand (op, mode); + + if (GET_CODE (op) != CONST_INT) + return 0; + + value = INTVAL (op); + return (value != 0) && (UINT16_P (value) || CMP_INT16_P (-value)); +} + +/* Return true if OP is a register or signed 16 bit value for compares. */ + +int +reg_or_cmp_int16_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG) + return register_operand (op, mode); if (GET_CODE (op) != CONST_INT) return 0; return CMP_INT16_P (INTVAL (op)); @@ -684,9 +714,9 @@ reg_or_cmp_int16_operand (op, int_mode) /* Return true if OP is a const_int requiring two instructions to load. */ int -two_insn_const_operand (op, int_mode) +two_insn_const_operand (op, mode) rtx op; - int int_mode ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; { if (GET_CODE (op) != CONST_INT) return 0; @@ -701,16 +731,15 @@ two_insn_const_operand (op, int_mode) move source. */ int -move_src_operand (op, int_mode) +move_src_operand (op, mode) rtx op; - int int_mode; + enum machine_mode mode; { - enum machine_mode mode = (enum machine_mode)int_mode; switch (GET_CODE (op)) { case SYMBOL_REF : case CONST : - return addr24_operand (op, int_mode); + return addr24_operand (op, mode); case CONST_INT : /* ??? We allow more cse opportunities if we only allow constants loadable with one insn, and split the rest into two. The instances @@ -743,6 +772,9 @@ move_src_operand (op, int_mode) else return register_operand (op, mode); case MEM : + if (GET_CODE (XEXP (op, 0)) == PRE_INC + || GET_CODE (XEXP (op, 0)) == PRE_DEC) + return 0; /* loads can't do pre-{inc,dec} */ return address_operand (XEXP (op, 0), mode); default : return 0; @@ -753,11 +785,10 @@ move_src_operand (op, int_mode) move source. */ int -move_double_src_operand (op, int_mode) +move_double_src_operand (op, mode) rtx op; - int int_mode; + enum machine_mode mode; { - enum machine_mode mode = (enum machine_mode)int_mode; switch (GET_CODE (op)) { case CONST_INT : @@ -769,7 +800,7 @@ move_double_src_operand (op, int_mode) /* (subreg (mem ...) ...) can occur here if the inner part was once a pseudo-reg and is now a stack slot. */ if (GET_CODE (SUBREG_REG (op)) == MEM) - return move_double_src_operand (SUBREG_REG (op), int_mode); + return move_double_src_operand (SUBREG_REG (op), mode); else return register_operand (op, mode); case MEM : @@ -786,11 +817,10 @@ move_double_src_operand (op, int_mode) /* Return true if OP is an acceptable argument for a move destination. */ int -move_dest_operand (op, int_mode) +move_dest_operand (op, mode) rtx op; - int int_mode; + enum machine_mode mode; { - enum machine_mode mode = (enum machine_mode)int_mode; switch (GET_CODE (op)) { case REG : @@ -803,6 +833,8 @@ move_dest_operand (op, int_mode) else return register_operand (op, mode); case MEM : + if (GET_CODE (XEXP (op, 0)) == POST_INC) + return 0; /* stores can't do post inc */ return address_operand (XEXP (op, 0), mode); default : return 0; @@ -853,9 +885,9 @@ easy_df_const (op) /* Return 1 if OP is an EQ or NE comparison operator. */ int -eqne_comparison_operator (op, int_mode) +eqne_comparison_operator (op, mode) rtx op; - int int_mode ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; { enum rtx_code code = GET_CODE (op); @@ -867,9 +899,9 @@ eqne_comparison_operator (op, int_mode) /* Return 1 if OP is a signed comparison operator. */ int -signed_comparison_operator (op, int_mode) +signed_comparison_operator (op, mode) rtx op; - int int_mode ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; { enum rtx_code code = GET_CODE (op); @@ -883,20 +915,48 @@ signed_comparison_operator (op, int_mode) This is used in insn length calcs. */ int -memreg_operand (op, int_mode) +memreg_operand (op, mode) rtx op; - int int_mode ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; { return GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == REG; } +/* Return true if OP is an acceptable input argument for a zero/sign extend + operation. */ + +int +extend_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + rtx addr; + + switch (GET_CODE (op)) + { + case REG : + case SUBREG : + return register_operand (op, mode); + + case MEM : + addr = XEXP (op, 0); + if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC) + return 0; /* loads can't do pre inc/pre dec */ + + return address_operand (addr, mode); + + default : + return 0; + } +} + /* Return non-zero if the operand is an insn that is a small insn. Allow const_int 0 as well, which is a placeholder for NOP slots. */ int -small_insn_p (op, int_mode) +small_insn_p (op, mode) rtx op; - int int_mode ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; { if (GET_CODE (op) == CONST_INT && INTVAL (op) == 0) return 1; @@ -910,9 +970,9 @@ small_insn_p (op, int_mode) /* Return non-zero if the operand is an insn that is a large insn. */ int -large_insn_p (op, int_mode) +large_insn_p (op, mode) rtx op; - int int_mode ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; { if (GET_RTX_CLASS (GET_CODE (op)) != 'i') return 0; @@ -932,13 +992,13 @@ m32r_select_cc_mode (op, x, y) rtx x ATTRIBUTE_UNUSED; rtx y ATTRIBUTE_UNUSED; { - return (int)SImode; + return (int) CCmode; } /* X and Y are two things to compare using CODE. Emit the compare insn and return the rtx for compare [arg0 of the if_then_else]. If need_compare is true then the comparison insn must be generated, rather - than being susummed into the following branch instruction. */ + than being susummed into the following branch instruction. */ rtx gen_compare (code, x, y, need_compare) @@ -965,7 +1025,7 @@ gen_compare (code, x, y, need_compare) case GEU: compare_code = LTU; branch_code = EQ; break; default: - abort(); + abort (); } if (need_compare) @@ -992,7 +1052,7 @@ gen_compare (code, x, y, need_compare) if (register_operand (y, SImode) /* reg equal to reg. */ || y == const0_rtx) /* req equal to zero. */ { - emit_insn (gen_cmp_eqsi_insn (x, y)); + emit_insn (gen_cmp_eqsi_insn (x, y)); return gen_rtx (code, mode, cc_reg, const0_rtx); } @@ -1031,7 +1091,7 @@ gen_compare (code, x, y, need_compare) code = NE; break; default: - abort(); + abort (); } return gen_rtx (code, mode, cc_reg, const0_rtx); @@ -1083,7 +1143,6 @@ gen_compare (code, x, y, need_compare) } } else - if (! TARGET_OLD_COMPARE) { /* reg/reg equal comparison */ if (compare_code == EQ @@ -1280,13 +1339,12 @@ gen_split_move_double (operands) /* Implements the FUNCTION_ARG_PARTIAL_NREGS macro. */ int -function_arg_partial_nregs (cum, int_mode, type, named) +function_arg_partial_nregs (cum, mode, type, named) CUMULATIVE_ARGS *cum; - int int_mode; + enum machine_mode mode; tree type; int named ATTRIBUTE_UNUSED; { - enum machine_mode mode = (enum machine_mode)int_mode; int ret; int size = (((mode == BLKmode && type) ? int_size_in_bytes (type) @@ -1310,14 +1368,13 @@ function_arg_partial_nregs (cum, int_mode, type, named) and mode MODE, and we rely on this fact. */ void -m32r_setup_incoming_varargs (cum, int_mode, type, pretend_size, no_rtl) +m32r_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl) CUMULATIVE_ARGS *cum; - int int_mode; + enum machine_mode mode; tree type; int *pretend_size; int no_rtl; { - enum machine_mode mode = (enum machine_mode)int_mode; int first_anon_arg; if (no_rtl) @@ -1353,6 +1410,7 @@ m32r_setup_incoming_varargs (cum, int_mode, type, pretend_size, no_rtl) } } + /* Implement `va_arg'. */ rtx @@ -1415,6 +1473,218 @@ m32r_va_arg (valist, type) return addr_rtx; } +int +m32r_adjust_cost (insn, link, dep_insn, cost) + rtx insn ATTRIBUTE_UNUSED; + rtx link ATTRIBUTE_UNUSED; + rtx dep_insn ATTRIBUTE_UNUSED; + int cost; +{ + return cost; +} + + +/* A C statement (sans semicolon) to update the integer scheduling + priority `INSN_PRIORITY(INSN)'. Reduce the priority to execute + the INSN earlier, increase the priority to execute INSN later. + Do not define this macro if you do not need to adjust the + scheduling priorities of insns. + + On the m32r, increase the priority of long instructions so that + the short instructions are scheduled ahead of the long ones. */ + +int +m32r_adjust_priority (insn, priority) + rtx insn; + int priority; +{ + if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') + { + enum rtx_code code = GET_CODE (PATTERN (insn)); + if (code != USE && code != CLOBBER && code != ADDR_VEC + && get_attr_insn_size (insn) != INSN_SIZE_SHORT) + priority <<= 3; + } + + return priority; +} + + +/* Initialize for scheduling a group of instructions. */ + +void +m32r_sched_init (stream, verbose) + FILE * stream ATTRIBUTE_UNUSED; + int verbose ATTRIBUTE_UNUSED; +{ + m32r_sched_odd_word_p = FALSE; +} + + +/* Reorder the schedulers priority list if needed */ + +void +m32r_sched_reorder (stream, verbose, ready, n_ready) + FILE * stream; + int verbose; + rtx * ready; + int n_ready; +{ + if (TARGET_DEBUG) + return; + + if (verbose <= 7) + stream = (FILE *)0; + + if (stream) + fprintf (stream, + ";;\t\t::: Looking at %d insn(s) on ready list, boundary is %s word\n", + n_ready, + (m32r_sched_odd_word_p) ? "odd" : "even"); + + if (n_ready > 1) + { + rtx * long_head = (rtx *) alloca (sizeof (rtx) * n_ready); + rtx * long_tail = long_head; + rtx * short_head = (rtx *) alloca (sizeof (rtx) * n_ready); + rtx * short_tail = short_head; + rtx * new_head = (rtx *) alloca (sizeof (rtx) * n_ready); + rtx * new_tail = new_head + (n_ready - 1); + int i; + + /* Loop through the instructions, classifing them as short/long. Try + to keep 2 short together and/or 1 long. Note, the ready list is + actually ordered backwards, so keep it in that manner. */ + for (i = n_ready-1; i >= 0; i--) + { + rtx insn = ready[i]; + enum rtx_code code; + + if (GET_RTX_CLASS (GET_CODE (insn)) != 'i' + || (code = GET_CODE (PATTERN (insn))) == USE + || code == CLOBBER || code == ADDR_VEC) + { + /* Dump all current short/long insns just in case */ + while (long_head != long_tail) + *new_tail-- = *long_head++; + + while (short_head != short_tail) + *new_tail-- = *short_head++; + + *new_tail-- = insn; + if (stream) + fprintf (stream, + ";;\t\t::: Skipping non instruction %d\n", + INSN_UID (insn)); + + } + + else + { + if (get_attr_insn_size (insn) != INSN_SIZE_SHORT) + *long_tail++ = insn; + + else + *short_tail++ = insn; + } + } + + /* If we are on an odd word, emit a single short instruction if + we can */ + if (m32r_sched_odd_word_p && short_head != short_tail) + *new_tail-- = *short_head++; + + /* Now dump out all of the long instructions */ + while (long_head != long_tail) + *new_tail-- = *long_head++; + + /* Now dump out all of the short instructions */ + while (short_head != short_tail) + *new_tail-- = *short_head++; + + if (new_tail+1 != new_head) + abort (); + + bcopy ((char *) new_head, (char *) ready, sizeof (rtx) * n_ready); + if (stream) + { +#ifdef HAIFA + fprintf (stream, ";;\t\t::: New ready list: "); + debug_ready_list (ready, n_ready); +#else + int i; + for (i = 0; i < n_ready; i++) + { + rtx insn = ready[i]; + enum rtx_code code; + + fprintf (stream, " %d", INSN_UID (ready[i])); + if (GET_RTX_CLASS (GET_CODE (insn)) != 'i' + || (code = GET_CODE (PATTERN (insn))) == USE + || code == CLOBBER || code == ADDR_VEC) + fputs ("(?)", stream); + + else if (get_attr_insn_size (insn) != INSN_SIZE_SHORT) + fputs ("(l)", stream); + + else + fputs ("(s)", stream); + } + + fprintf (stream, "\n"); +#endif + } + } +} + + +/* If we have a machine that can issue a variable # of instructions + per cycle, indicate how many more instructions can be issued + after the current one. */ +int +m32r_sched_variable_issue (stream, verbose, insn, how_many) + FILE * stream; + int verbose; + rtx insn; + int how_many; +{ + int orig_odd_word_p = m32r_sched_odd_word_p; + int short_p = FALSE; + + how_many--; + if (how_many > 0 && !TARGET_DEBUG) + { + if (GET_RTX_CLASS (GET_CODE (insn)) != 'i') + how_many++; + + else if (GET_CODE (PATTERN (insn)) == USE + || GET_CODE (PATTERN (insn)) == CLOBBER + || GET_CODE (PATTERN (insn)) == ADDR_VEC) + how_many++; + + else if (get_attr_insn_size (insn) != INSN_SIZE_SHORT) + { + how_many = 0; + m32r_sched_odd_word_p = 0; + } + else + { + m32r_sched_odd_word_p = !m32r_sched_odd_word_p; + short_p = TRUE; + } + } + + if (verbose > 7 && stream) + fprintf (stream, + ";;\t\t::: %s insn %d starts on an %s word, can emit %d more instruction(s)\n", + short_p ? "short" : "long", + INSN_UID (insn), + orig_odd_word_p ? "odd" : "even", + how_many); + + return how_many; +} + /* Cost functions. */ /* Provide the costs of an addressing mode that contains ADDR. @@ -1638,7 +1908,7 @@ m32r_expand_prologue () { int regno; int frame_size; - unsigned int gmask = current_frame_info.gmask; + unsigned int gmask; if (! current_frame_info.initialized) m32r_compute_frame_size (get_frame_size ()); @@ -1849,6 +2119,22 @@ m32r_output_function_epilogue (file, size) m32r_compute_function_type (NULL_TREE); } +/* Return non-zero if this function is known to have a null or 1 instruction + epilogue. */ + +int +direct_return () +{ + if (!reload_completed) + return FALSE; + + if (! current_frame_info.initialized) + m32r_compute_frame_size (get_frame_size ()); + + return current_frame_info.total_size == 0; +} + + /* PIC */ /* Emit special PIC prologues and epilogues. */ @@ -1968,7 +2254,7 @@ m32r_print_operand (file, x, code) if (GET_CODE (x) != CONST_DOUBLE || GET_MODE_CLASS (GET_MODE (x)) != MODE_FLOAT) - abort (); + fatal_insn ("Bad insn for 'A'", x); REAL_VALUE_FROM_CONST_DOUBLE (d, x); REAL_VALUE_TO_DECIMAL (d, "%.20e", str); fprintf (file, "%s", str); @@ -2088,21 +2374,21 @@ m32r_print_operand (file, x, code) if (GET_CODE (addr) == PRE_INC) { if (GET_CODE (XEXP (addr, 0)) != REG) - abort (); + fatal_insn ("Pre-increment address is not a register", x); fprintf (file, "@+%s", reg_names[REGNO (XEXP (addr, 0))]); } else if (GET_CODE (addr) == PRE_DEC) { if (GET_CODE (XEXP (addr, 0)) != REG) - abort (); + fatal_insn ("Pre-decrement address is not a register", x); fprintf (file, "@-%s", reg_names[REGNO (XEXP (addr, 0))]); } else if (GET_CODE (addr) == POST_INC) { if (GET_CODE (XEXP (addr, 0)) != REG) - abort (); + fatal_insn ("Post-increment address is not a register", x); fprintf (file, "@%s+", reg_names[REGNO (XEXP (addr, 0))]); } @@ -2180,7 +2466,7 @@ m32r_print_operand_address (file, addr) fputs (reg_names[REGNO (base)], file); } else - abort (); + fatal_insn ("Bad address", addr); } else if (GET_CODE (base) == LO_SUM) { @@ -2196,12 +2482,12 @@ m32r_print_operand_address (file, addr) fputs (reg_names[REGNO (XEXP (base, 0))], file); } else - abort (); + fatal_insn ("Bad address", addr); break; case LO_SUM : if (GET_CODE (XEXP (addr, 0)) != REG) - abort (); + fatal_insn ("Lo_sum not of register", addr); if (small_data_operand (XEXP (addr, 1), VOIDmode)) fputs ("sda(", file); else @@ -2244,12 +2530,10 @@ zero_and_one (operand1, operand2) /* Return non-zero if the operand is suitable for use in a conditional move sequence. */ int -conditional_move_operand (operand, int_mode) +conditional_move_operand (operand, mode) rtx operand; - int int_mode; + enum machine_mode mode; { - enum machine_mode mode = (enum machine_mode)int_mode; - /* Only defined for simple integers so far... */ if (mode != SImode && mode != HImode && mode != QImode) return FALSE; @@ -2276,13 +2560,13 @@ conditional_move_operand (operand, int_mode) /* Return true if the code is a test of the carry bit */ int -carry_compare_operand (op, int_mode) +carry_compare_operand (op, mode) rtx op; - int int_mode ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; { rtx x; - if (GET_MODE (op) != SImode && GET_MODE (op) != VOIDmode) + if (GET_MODE (op) != CCmode && GET_MODE (op) != VOIDmode) return FALSE; if (GET_CODE (op) != NE && GET_CODE (op) != EQ) @@ -2299,7 +2583,6 @@ carry_compare_operand (op, int_mode) return TRUE; } - /* Generate the correct assembler code to handle the conditional loading of a value into a register. It is known that the operands satisfy the conditional_move_operand() function above. The destination is operand[0]. @@ -2341,6 +2624,30 @@ emit_cond_move (operands, insn) return buffer; } +/* Returns true if the registers contained in the two + rtl expressions are different. */ +int +m32r_not_same_reg (a, b) + rtx a; + rtx b; +{ + int reg_a = -1; + int reg_b = -2; + + while (GET_CODE (a) == SUBREG) + a = SUBREG_REG (a); + + if (GET_CODE (a) == REG) + reg_a = REGNO (a); + + while (GET_CODE (b) == SUBREG) + b = SUBREG_REG (b); + + if (GET_CODE (b) == REG) + reg_b = REGNO (b); + + return reg_a != reg_b; +} /* Use a library function to move some bytes. */ @@ -2600,7 +2907,7 @@ m32r_output_block_move (insn, operands) int m32r_block_immediate_operand (op, mode) rtx op; - int mode ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; { if (GET_CODE (op) != CONST_INT || INTVAL (op) > MAX_MOVE_BYTES |
