diff options
author | amylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-01-12 12:59:38 +0000 |
---|---|---|
committer | amylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-01-12 12:59:38 +0000 |
commit | 05e0956519aefe7929b081da944059e20a11a79f (patch) | |
tree | f09f63e49d892db0078f774f0763051f1cacb399 /gcc/config/sh | |
parent | b28a376c5ed3119834ffd0d50e5b883b82e271e3 (diff) | |
download | gcc-05e0956519aefe7929b081da944059e20a11a79f.tar.gz |
PR target/13585
* sh-protos.h (check_use_sfunc_addr): Declare.
* sh.c (extract_sfunc_addr, check_use_sfunc_addr): New functions.
* sh.md (use_sfunc_addr): Use check_use_sfunc_addr in insn predicate.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@75717 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/sh')
-rw-r--r-- | gcc/config/sh/sh-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 47 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 2 |
3 files changed, 49 insertions, 1 deletions
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index ec723bda127..fc96b193777 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -125,6 +125,7 @@ extern bool sh_cannot_change_mode_class extern void sh_mark_label (rtx, int); extern int sh_register_move_cost (enum machine_mode mode, enum reg_class, enum reg_class); +extern int check_use_sfunc_addr (rtx, rtx); #ifdef HARD_CONST extern void fpscr_set_from_mem (int, HARD_REG_SET); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 1c58712a00c..85f4aa6e639 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -9167,4 +9167,51 @@ sh_expand_t_scc (enum rtx_code code, rtx target) return 1; } +/* INSN is an sfunc; return the rtx that describes the address used. */ +static rtx +extract_sfunc_addr (rtx insn) +{ + rtx pattern, part = NULL_RTX; + int len, i; + + pattern = PATTERN (insn); + len = XVECLEN (pattern, 0); + for (i = 0; i < len; i++) + { + part = XVECEXP (pattern, 0, i); + if (GET_CODE (part) == USE && GET_MODE (XEXP (part, 0)) == Pmode + && GENERAL_REGISTER_P (true_regnum (XEXP (part, 0)))) + return XEXP (part, 0); + } + if (GET_CODE (XVECEXP (pattern, 0, 0)) == UNSPEC_VOLATILE) + return XVECEXP (XVECEXP (pattern, 0, 0), 0, 1); + abort (); +} + +/* Verify that the register in use_sfunc_addr still agrees with the address + used in the sfunc. This prevents fill_slots_from_thread from changing + use_sfunc_addr. + INSN is the use_sfunc_addr instruction, and REG is the register it + guards. */ +int +check_use_sfunc_addr (rtx insn, rtx reg) +{ + /* Search for the sfunc. It should really come right after INSN. */ + while ((insn = NEXT_INSN (insn))) + { + if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN) + break; + if (! INSN_P (insn)) + continue; + + if (GET_CODE (PATTERN (insn)) == SEQUENCE) + insn = XVECEXP (PATTERN (insn), 0, 0); + if (GET_CODE (PATTERN (insn)) != PARALLEL + || get_attr_type (insn) != TYPE_SFUNC) + continue; + return rtx_equal_p (extract_sfunc_addr (insn), reg); + } + abort (); +} + #include "gt-sh.h" diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index aa63209dbf6..099d930a6c2 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -1245,7 +1245,7 @@ (define_insn "use_sfunc_addr" [(set (reg:SI PR_REG) (unspec:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))] - "TARGET_SH1" + "TARGET_SH1 && check_use_sfunc_addr (insn, operands[0])" "" [(set_attr "length" "0")]) |