summaryrefslogtreecommitdiff
path: root/gcc/config/mn10300/mn10300.md
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2011-01-19 17:27:58 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2011-01-19 17:27:58 +0000
commit5babaf8133ca299d1e1fa537f6742704711c9a9b (patch)
tree19eff32a2b06c80a809819ea8346239153f15c00 /gcc/config/mn10300/mn10300.md
parent85a6eed4a699ef7dcb8e64f187ba5c6541aa1cf0 (diff)
downloadgcc-5babaf8133ca299d1e1fa537f6742704711c9a9b.tar.gz
mn10300: Explicitly represent MDR in multiply and divide.
Note that the mulsidi3_internal pattern is structured so as to let the lower-subregs pass fully split the result. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@169008 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/mn10300/mn10300.md')
-rw-r--r--gcc/config/mn10300/mn10300.md270
1 files changed, 154 insertions, 116 deletions
diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md
index 5f4f17a4e95..bc68ca5d8fd 100644
--- a/gcc/config/mn10300/mn10300.md
+++ b/gcc/config/mn10300/mn10300.md
@@ -38,6 +38,7 @@
(UNSPEC_PLT 4)
(UNSPEC_GOTSYM_OFF 5)
+ (UNSPEC_EXT 6)
(UNSPEC_BSCH 7)
])
@@ -167,6 +168,8 @@
(eq_attr "timings" "4040") "throughput*40")
(define_insn_reservation "throughput_41_latency_42" 42
(eq_attr "timings" "4142") "throughput*41,nothing")
+(define_insn_reservation "throughput_42_latency_43" 44
+ (eq_attr "timings" "4243") "throughput*42,nothing")
(define_insn_reservation "throughput_43_latency_44" 44
(eq_attr "timings" "4344") "throughput*43,nothing")
(define_insn_reservation "throughput_45_latency_46" 46
@@ -748,148 +751,183 @@
;; MULTIPLY INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn "mulsidi3"
- [(set (match_operand:DI 0 "register_operand" "=dax")
- (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "dax"))
- (sign_extend:DI (match_operand:SI 2 "register_operand" "dax"))))
- (clobber (reg:CC CC_REG))
- ]
- "TARGET_AM33"
- "mul %1,%2,%H0,%L0"
- [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
- (const_int 24) (const_int 23)))]
-)
+;; ??? Note that AM33 has a third multiply variant that puts the high part
+;; into the MDRQ register, however this variant also constrains the inputs
+;; to be in DATA_REGS and thus isn't as helpful as it might be considering
+;; the existance of the 4-operand multiply. Nor is there a set of divide
+;; insns that use MDRQ. Given that there is an IMM->MDRQ insn, this would
+;; have been very handy for starting udivmodsi4...
+
+(define_expand "mulsidi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
+ (sign_extend:DI (match_operand:SI 2 "register_operand" ""))))]
+ ""
+{
+ emit_insn (gen_mulsidi3_internal (gen_lowpart (SImode, operands[0]),
+ gen_highpart (SImode, operands[0]),
+ operands[1], operands[2]));
+ DONE;
+})
-(define_insn "umulsidi3"
- [(set (match_operand:DI 0 "register_operand" "=dax")
- (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "dax"))
- (zero_extend:DI (match_operand:SI 2 "register_operand" "dax"))))
- (clobber (reg:CC CC_REG))
- ]
- "TARGET_AM33"
- "mulu %1,%2,%H0,%L0"
- [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
- (const_int 24) (const_int 23)))]
+(define_insn "mulsidi3_internal"
+ [(set (match_operand:SI 0 "register_operand" "=D,r")
+ (mult:SI (match_operand:SI 2 "register_operand" "%0,r")
+ (match_operand:SI 3 "register_operand" " D,r")))
+ (set (match_operand:SI 1 "register_operand" "=z,r")
+ (truncate:SI
+ (ashiftrt:DI
+ (mult:DI (sign_extend:DI (match_dup 2))
+ (sign_extend:DI (match_dup 3)))
+ (const_int 32))))
+ (clobber (reg:CC CC_REG))]
+ ""
+{
+ if (which_alternative == 1)
+ return "mul %2,%3,%1,%0";
+ else if (TARGET_MULT_BUG)
+ return "nop\;nop\;mul %3,%0";
+ else
+ return "mul %3,%0";
+}
+ [(set_attr "isa" "*,am33")
+ (set (attr "timings")
+ (if_then_else (eq_attr "cpu" "am34") (const_int 24) (const_int 23)))]
)
-(define_expand "mulsi3"
- [(parallel [(set (match_operand:SI 0 "register_operand")
- (mult:SI (match_operand:SI 1 "register_operand")
- (match_operand:SI 2 "register_operand")))
- (clobber (reg:CC CC_REG))
- ])
- ]
+(define_expand "umulsidi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
+ (zero_extend:DI (match_operand:SI 2 "register_operand" ""))))
+ (clobber (reg:CC CC_REG))]
""
- "")
+{
+ emit_insn (gen_umulsidi3_internal (gen_lowpart (SImode, operands[0]),
+ gen_highpart (SImode, operands[0]),
+ operands[1], operands[2]));
+ DONE;
+})
-(define_insn "*am33_mulsi3"
- [(set (match_operand:SI 0 "register_operand" "=dx,!dax")
- (mult:SI (match_operand:SI 1 "register_operand" "%0,0")
- (match_operand:SI 2 "nonmemory_operand" "dx,daxi")))
- (clobber (reg:CC CC_REG))
- ]
- "TARGET_AM33"
- "*
+(define_insn "umulsidi3_internal"
+ [(set (match_operand:SI 0 "register_operand" "=D,r")
+ (mult:SI (match_operand:SI 2 "register_operand" "%0,r")
+ (match_operand:SI 3 "register_operand" " D,r")))
+ (set (match_operand:SI 1 "register_operand" "=z,r")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI (zero_extend:DI (match_dup 2))
+ (zero_extend:DI (match_dup 3)))
+ (const_int 32))))
+ (clobber (reg:CC CC_REG))]
+ ""
{
- if (TARGET_MULT_BUG)
- return \"nop\;nop\;mul %2,%0\";
+ if (which_alternative == 1)
+ return "mulu %2,%3,%1,%0";
+ else if (TARGET_MULT_BUG)
+ return "nop\;nop\;mulu %3,%0";
else
- return \"mul %2,%0\";
-}"
- [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34") (const_int 24) (const_int 23)))]
+ return "mulu %3,%0";
+}
+ [(set_attr "isa" "*,am33")
+ (set (attr "timings")
+ (if_then_else (eq_attr "cpu" "am34") (const_int 24) (const_int 23)))]
)
-(define_insn "*mn10300_mulsi3"
- [(set (match_operand:SI 0 "register_operand" "=dx")
- (mult:SI (match_operand:SI 1 "register_operand" "%0")
- (match_operand:SI 2 "register_operand" "dx")))
- (clobber (reg:CC CC_REG))
- ]
+(define_expand "mulsi3"
+ [(parallel [(set (match_operand:SI 0 "register_operand" "")
+ (mult:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))
+ (clobber (match_scratch:SI 3 ""))
+ (clobber (reg:CC CC_REG))])]
""
- "*
-{
- if (TARGET_MULT_BUG)
- return \"nop\;nop\;mul %2,%0\";
- else
- return \"mul %2,%0\";
-}"
- [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
- (const_int 24) (const_int 23)))]
)
-;; ??? This pattern causes too-high register pressure for MN103.
-;; ??? To be fixed by exposing the MDR register properly.
-(define_insn "udivmodsi4"
- [(set (match_operand:SI 0 "register_operand" "=D")
- (udiv:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "register_operand" "D")))
- (set (match_operand:SI 3 "register_operand" "=&d")
- (umod:SI (match_dup 1) (match_dup 2)))
+(define_insn "*mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "=D, r,r")
+ (mult:SI (match_operand:SI 2 "register_operand" "%0, 0,r")
+ (match_operand:SI 3 "nonmemory_operand" " D,ri,r")))
+ (clobber (match_scratch:SI 1 "=z, z,r"))
(clobber (reg:CC CC_REG))]
- "TARGET_AM33"
+ ""
{
- output_asm_insn ("clr %3\;ext %3", operands);
- if (find_reg_note (insn, REG_UNUSED, operands[3]))
- return "divu %2,%0";
+ if (which_alternative == 2)
+ return "mul %2,%3,%1,%0";
+ else if (TARGET_MULT_BUG)
+ return "nop\;nop\;mul %3,%0";
else
- return "divu %2,%0\;mov mdr,%3";
+ return "mul %3,%0";
}
- ;; Timings: AM33 AM34
- ;; SUB 1/1 1/1
- ;; MOV 1/1 1/1
- ;; DIVU 38/39 42/43
- ;; MOV 1/1 1/1
- ;; --------------------
- ;; total 41/42 45/46 (worst case sceanario)
- [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
- (const_int 4546) (const_int 4142)))]
+ [(set_attr "isa" "*,am33,am33")
+ (set (attr "timings")
+ (if_then_else (eq_attr "cpu" "am34") (const_int 24) (const_int 23)))]
)
-;; ??? In the meantime MN103 can use these two patterns,
-;; which reduce the register pressure by one.
-(define_insn "udivsi3"
- [(set (match_operand:SI 0 "register_operand" "=&d")
- (udiv:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "register_operand" "d")))
- (clobber (reg:CC CC_REG))]
- "!TARGET_AM33"
- "clr %0\;ext %0\;mov %1,%0\;divu %2,%0"
- [(set_attr "timings" "4142")]
+(define_expand "udivmodsi4"
+ [(parallel [(set (match_operand:SI 0 "register_operand")
+ (udiv:SI (match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "register_operand")))
+ (set (match_operand:SI 3 "register_operand")
+ (umod:SI (match_dup 1) (match_dup 2)))
+ (use (const_int 0))
+ (clobber (reg:CC CC_REG))])]
+ ""
)
-(define_insn "umodsi3"
- [(set (match_operand:SI 0 "register_operand" "=&d")
- (umod:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "register_operand" "d")))
+;; Note the trick to get reload to put the zero into the MDR register,
+;; rather than exposing the load early and letting CSE or someone try
+;; to share the zeros between division insns. Which tends to result
+;; in sequences like 0->r0->d0->mdr.
+
+(define_insn "*udivmodsi4"
+ [(set (match_operand:SI 0 "register_operand" "=D")
+ (udiv:SI (match_operand:SI 2 "register_operand" " 0")
+ (match_operand:SI 3 "register_operand" " D")))
+ (set (match_operand:SI 1 "register_operand" "=z")
+ (umod:SI (match_dup 2) (match_dup 3)))
+ (use (match_operand:SI 4 "nonmemory_operand" " 1"))
(clobber (reg:CC CC_REG))]
- "!TARGET_AM33"
- "clr %0\;ext %0\;mov %1,%0\;divu %2,%0\;mov mdr,%0"
- [(set_attr "timings" "4142")]
+ ""
+ "divu %3,%0"
+ [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
+ (const_int 3839) (const_int 4243)))]
)
-(define_insn "divmodsi4"
- [(set (match_operand:SI 0 "register_operand" "=dx")
- (div:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "register_operand" "dx")))
- (set (match_operand:SI 3 "register_operand" "=d")
- (mod:SI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC CC_REG))
- ]
+(define_expand "divmodsi4"
+ [(parallel [(set (match_operand:SI 0 "register_operand" "")
+ (div:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "register_operand" "")))
+ (set (match_operand:SI 3 "register_operand" "")
+ (mod:SI (match_dup 1) (match_dup 2)))
+ (use (match_dup 4))
+ (clobber (reg:CC CC_REG))])]
""
- "*
{
- if (find_reg_note (insn, REG_UNUSED, operands[3]))
- return \"ext %0\;div %2,%0\";
- else
- return \"ext %0\;div %2,%0\;mov mdr,%3\";
-}"
- ;; Timings: AM33 AM34
- ;; EXT 1/1 1/1
- ;; DIV 38/39 42/43
- ;; --------------------
- ;; total 39/40 43/44 (worst case sceanario)
+ operands[4] = gen_reg_rtx (SImode);
+ emit_insn (gen_ext_internal (operands[4], operands[1]));
+})
+
+;; ??? Ideally we'd represent this via shift, but it seems like adding a
+;; special-case pattern for (ashiftrt x 31) is just as likely to result
+;; in poor register allocation choices.
+(define_insn "ext_internal"
+ [(set (match_operand:SI 0 "register_operand" "=z")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "D")] UNSPEC_EXT))]
+ ""
+ "ext %1"
+)
+
+(define_insn "*divmodsi4"
+ [(set (match_operand:SI 0 "register_operand" "=D")
+ (div:SI (match_operand:SI 2 "register_operand" " 0")
+ (match_operand:SI 3 "register_operand" " D")))
+ (set (match_operand:SI 1 "register_operand" "=z")
+ (mod:SI (match_dup 2) (match_dup 3)))
+ (use (match_operand:SI 4 "register_operand" " 1"))
+ (clobber (reg:CC CC_REG))]
+ ""
+ "div %3,%0";
[(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
- (const_int 4344) (const_int 3940)))]
+ (const_int 3839) (const_int 4243)))]
)