aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDJ Delorie <dj@redhat.com>2007-02-08 17:22:52 -0500
committerDJ Delorie <dj@gcc.gnu.org>2007-02-08 17:22:52 -0500
commitf9b894388828f39c8cdcd7df1cf609c63a3275de (patch)
treeca63f21f6a9cf192f20b2fca82777f493a0bb2ec /gcc
parentff39b79b8fe48e0f47c2798b71732250264baaa7 (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/config/m32c/m32c-protos.h1
-rw-r--r--gcc/config/m32c/m32c.c75
-rw-r--r--gcc/config/m32c/predicates.md6
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.