diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2fb37dce27b..d37980efa4a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +Wed Apr 5 23:17:10 2000 J"orn Rennecke + + * sh.c (sh_insn_length_adjustment): New function. + * sh-protos.h (sh_insn_length_adjustment): Declare. + * sh.h (ADJUST_INSN_LENGTH): Use it. + Wed Apr 5 12:35:18 2000 Hans-Peter Nilsson * optabs.c (emit_libcall_block): Remove spurious REG_EQUAL notes diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index a36e4c6fbb8..acc316ea376 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -90,6 +90,7 @@ extern void expand_sf_binop PARAMS ((rtx (*)(rtx, rtx, rtx, rtx), rtx *)); extern void expand_df_unop PARAMS ((rtx (*)(rtx, rtx, rtx), rtx *)); extern void expand_df_binop PARAMS ((rtx (*)(rtx, rtx, rtx, rtx), rtx *)); extern void expand_fp_branch PARAMS ((rtx (*)(void), rtx (*)(void))); +extern int sh_insn_length_adjustment PARAMS ((rtx)); #ifdef TREE_CODE extern void sh_va_start PARAMS ((int, tree, rtx)); extern rtx sh_va_arg PARAMS ((tree, tree)); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 28d199cebfc..d4d38d35922 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -5127,3 +5127,79 @@ fpscr_set_from_mem (mode, regs_live) REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_DEAD, addr_reg, REG_NOTES (i)); REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_INC, addr_reg, REG_NOTES (i)); } + +/* Is the given character a logical line separator for the assembler? */ +#ifndef IS_ASM_LOGICAL_LINE_SEPARATOR +#define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == ';') +#endif + +int +sh_insn_length_adjustment (insn) + rtx insn; +{ + /* Instructions with unfilled delay slots take up an extra two bytes for + the nop in the delay slot. */ + if (((GET_CODE (insn) == INSN + && GET_CODE (PATTERN (insn)) != USE + && GET_CODE (PATTERN (insn)) != CLOBBER) + || GET_CODE (insn) == CALL_INSN + || (GET_CODE (insn) == JUMP_INSN + && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC + && GET_CODE (PATTERN (insn)) != ADDR_VEC)) + && GET_CODE (PATTERN (NEXT_INSN (PREV_INSN (insn)))) != SEQUENCE + && get_attr_needs_delay_slot (insn) == NEEDS_DELAY_SLOT_YES) + return 2; + + /* sh-dsp parallel processing insn take four bytes instead of two. */ + + if (GET_CODE (insn) == INSN) + { + int sum = 0; + rtx body = PATTERN (insn); + char *template, c; + int maybe_label = 1; + + if (GET_CODE (body) == ASM_INPUT) + template = XSTR (body, 0); + else if (asm_noperands (body) >= 0) + template + = decode_asm_operands (body, NULL_PTR, NULL_PTR, NULL_PTR, NULL_PTR); + else + return 0; + do + { + int ppi_adjust = 0; + + do + c = *template++; + while (c == ' ' || c == '\t'); + /* all sh-dsp parallel-processing insns start with p. + The only non-ppi sh insn starting with p is pref. + The only ppi starting with pr is prnd. */ + if ((c == 'p' || c == 'P') && strncasecmp ("re", template, 2)) + ppi_adjust = 2; + /* The repeat pseudo-insn expands two three insns, a total of + six bytes in size. */ + else if ((c == 'r' || c == 'R') + && ! strncasecmp ("epeat", template, 5)) + ppi_adjust = 4; + while (c && c != '\n' && ! IS_ASM_LOGICAL_LINE_SEPARATOR (c)) + { + /* If this is a label, it is obviously not a ppi insn. */ + if (c == ':' && maybe_label) + { + ppi_adjust = 0; + break; + } + else if (c == '\'' || c == '"') + maybe_label = 0; + c = *template++; + } + sum += ppi_adjust; + maybe_label = c != ':'; + } + while (c); + return sum; + } + return 0; +} diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 6ae0deb6277..4df72bfecf3 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -2122,20 +2122,12 @@ extern int rtx_equal_function_value_matters; extern struct rtx_def *fpscr_rtx; -/* Instructions with unfilled delay slots take up an extra two bytes for - the nop in the delay slot. */ +/* Instructions with unfilled delay slots take up an + extra two bytes for the nop in the delay slot. + sh-dsp parallel processing insns are four bytes long. */ #define ADJUST_INSN_LENGTH(X, LENGTH) \ - if (((GET_CODE (X) == INSN \ - && GET_CODE (PATTERN (X)) != USE \ - && GET_CODE (PATTERN (X)) != CLOBBER) \ - || GET_CODE (X) == CALL_INSN \ - || (GET_CODE (X) == JUMP_INSN \ - && GET_CODE (PATTERN (X)) != ADDR_DIFF_VEC \ - && GET_CODE (PATTERN (X)) != ADDR_VEC)) \ - && GET_CODE (PATTERN (NEXT_INSN (PREV_INSN (X)))) != SEQUENCE \ - && get_attr_needs_delay_slot (X) == NEEDS_DELAY_SLOT_YES) \ - (LENGTH) += 2; + (LENGTH) += sh_insn_length_adjustment (X); /* Define the codes that are matched by predicates in sh.c. */ #define PREDICATE_CODES \