diff options
author | DJ Delorie <dj@redhat.com> | 2007-02-08 17:22:52 -0500 |
---|---|---|
committer | DJ Delorie <dj@gcc.gnu.org> | 2007-02-08 17:22:52 -0500 |
commit | f9b894388828f39c8cdcd7df1cf609c63a3275de (patch) | |
tree | ca63f21f6a9cf192f20b2fca82777f493a0bb2ec /gcc | |
parent | ff39b79b8fe48e0f47c2798b71732250264baaa7 (diff) | |
download | gcc-f9b894388828f39c8cdcd7df1cf609c63a3275de.zip gcc-f9b894388828f39c8cdcd7df1cf609c63a3275de.tar.gz gcc-f9b894388828f39c8cdcd7df1cf609c63a3275de.tar.bz2 |
m32c-protos.h (m32c_illegal_subreg_p): New.
* config/m32c/m32c-protos.h (m32c_illegal_subreg_p): New.
* config/m32c/m32c.c (legal_subregs): New.
(m32c_illegal_subreg_p): New.
* config/m32c/predicates.md (m32c_any_operand): Use it to reject
unsupported subregs of hard regs.
From-SVN: r121725
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/m32c/m32c-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/m32c/m32c.c | 75 | ||||
-rw-r--r-- | gcc/config/m32c/predicates.md | 6 |
4 files changed, 89 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3a51bb5..232a4a1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2007-02-08 DJ Delorie <dj@redhat.com> + + * config/m32c/m32c-protos.h (m32c_illegal_subreg_p): New. + * config/m32c/m32c.c (legal_subregs): New. + (m32c_illegal_subreg_p): New. + * config/m32c/predicates.md (m32c_any_operand): Use it to reject + unsupported subregs of hard regs. + 2007-02-08 Jan Hubicka <jh@suse.cz> * tree-cfg.c (bsi_replace): Shortcut when replacing the statement with diff --git a/gcc/config/m32c/m32c-protos.h b/gcc/config/m32c/m32c-protos.h index 4b3ead3..5735ee7 100644 --- a/gcc/config/m32c/m32c-protos.h +++ b/gcc/config/m32c/m32c-protos.h @@ -74,6 +74,7 @@ int m32c_extra_constraint_p (rtx, char, const char *); int m32c_extra_constraint_p2 (rtx, char, const char *); int m32c_hard_regno_nregs (int, MM); int m32c_hard_regno_ok (int, MM); +bool m32c_illegal_subreg_p (rtx); bool m32c_immd_dbl_mov (rtx *, MM); rtx m32c_incoming_return_addr_rtx (void); void m32c_initialize_trampoline (rtx, rtx, rtx); diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c index 98e59dd..65f0898 100644 --- a/gcc/config/m32c/m32c.c +++ b/gcc/config/m32c/m32c.c @@ -2749,6 +2749,81 @@ m32c_insert_attributes (tree node ATTRIBUTE_UNUSED, /* Predicates */ +/* This is a list of legal subregs of hard regs. */ +static struct { + enum machine_mode outer_mode_size; + enum machine_mode inner_mode_size; + unsigned int regno; + int byte_mask; + int legal_when; +} legal_subregs[] = { + {1, 2, R0_REGNO, 0x03, 1}, /* r0h r0l */ + {1, 2, R1_REGNO, 0x03, 1}, /* r1h r1l */ + {1, 2, A0_REGNO, 0x01, 1}, + {1, 2, A1_REGNO, 0x01, 1}, + + {1, 4, A0_REGNO, 0x01, 1}, + {1, 4, A1_REGNO, 0x01, 1}, + + {2, 4, R0_REGNO, 0x05, 1}, /* r2 r0 */ + {2, 4, R1_REGNO, 0x05, 1}, /* r3 r1 */ + {2, 4, A0_REGNO, 0x05, 16}, /* a1 a0 */ + {2, 4, A0_REGNO, 0x01, 24}, /* a1 a0 */ + {2, 4, A1_REGNO, 0x01, 24}, /* a1 a0 */ + + {4, 8, R0_REGNO, 0x55, 1}, /* r3 r1 r2 r0 */ +}; + +/* Returns TRUE if OP is a subreg of a hard reg which we don't + support. */ +bool +m32c_illegal_subreg_p (rtx op) +{ + rtx orig_op = op; + int offset; + unsigned int i; + int src_mode, dest_mode; + + if (GET_CODE (op) != SUBREG) + return false; + + dest_mode = GET_MODE (op); + offset = SUBREG_BYTE (op); + op = SUBREG_REG (op); + src_mode = GET_MODE (op); + + if (GET_MODE_SIZE (dest_mode) == GET_MODE_SIZE (src_mode)) + return false; + if (GET_CODE (op) != REG) + return false; + if (REGNO (op) >= MEM0_REGNO) + return false; + + offset = (1 << offset); + + for (i = 0; i < sizeof(legal_subregs)/sizeof(legal_subregs[0]); i ++) + if (legal_subregs[i].outer_mode_size == GET_MODE_SIZE (dest_mode) + && legal_subregs[i].regno == REGNO (op) + && legal_subregs[i].inner_mode_size == GET_MODE_SIZE (src_mode) + && legal_subregs[i].byte_mask & offset) + { + switch (legal_subregs[i].legal_when) + { + case 1: + return false; + case 16: + if (TARGET_A16) + return false; + break; + case 24: + if (TARGET_A24) + return false; + break; + } + } + return true; +} + /* Returns TRUE if we support a move between the first two operands. At the moment, we just want to discourage mem to mem moves until after reload, because reload has a hard time with our limited diff --git a/gcc/config/m32c/predicates.md b/gcc/config/m32c/predicates.md index b0fbc84..5ca881f 100644 --- a/gcc/config/m32c/predicates.md +++ b/gcc/config/m32c/predicates.md @@ -27,7 +27,11 @@ (define_predicate "m32c_any_operand" (ior (match_operand 0 "general_operand") - (match_operand 1 "memory_operand"))) + (match_operand 1 "memory_operand")) + { + return ! m32c_illegal_subreg_p (op); + } +) ; Likewise for nonimmediate_operand. |