xref: /netbsd-src/external/gpl3/gcc/dist/gcc/config/h8300/multiply.md (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1;; ----------------------------------------------------------------------
2;; MULTIPLY INSTRUCTIONS
3;; ----------------------------------------------------------------------
4
5;; Note that the H8/300 can only handle umulqihi3.
6
7(define_expand "mulqihi3"
8  [(set (match_operand:HI 0 "register_operand" "")
9	(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" ""))
10		 ;; intentionally-mismatched modes
11		 (match_operand:QI 2 "reg_or_nibble_operand" "")))]
12  ""
13  {
14    if (GET_MODE (operands[2]) != VOIDmode)
15      operands[2] = gen_rtx_SIGN_EXTEND (HImode, operands[2]);
16  })
17
18(define_insn_and_split "*mulqihi3_const"
19  [(set (match_operand:HI 0 "register_operand" "=r")
20	(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
21		 (match_operand:QI 2 "nibble_operand" "IP4>X")))]
22  "TARGET_H8300SX"
23  "#"
24  "&& reload_completed"
25  [(parallel [(set (match_dup 0)
26		   (mult:HI (sign_extend:HI (match_dup 1)) (match_dup 2)))
27	      (clobber (reg:CC CC_REG))])])
28
29(define_insn "*mulqihi3_const<cczn>"
30  [(set (match_operand:HI 0 "register_operand" "=r")
31	(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
32		 (match_operand:QI 2 "nibble_operand" "IP4>X")))
33   (clobber (reg:CC CC_REG))]
34  "TARGET_H8300SX"
35  "mulxs.b	%X2,%T0"
36  [(set_attr "length" "4")])
37
38(define_insn_and_split "*mulqihi3"
39  [(set (match_operand:HI 0 "register_operand" "=r")
40	(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
41		 (sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
42  ""
43  "#"
44  "&& reload_completed"
45  [(parallel [(set (match_dup 0)
46		   (mult:HI (sign_extend:HI (match_dup 1))
47			    (sign_extend:HI (match_dup 2))))
48	      (clobber (reg:CC CC_REG))])])
49
50(define_insn "*mulqihi3<cczn>"
51  [(set (match_operand:HI 0 "register_operand" "=r")
52	(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
53		 (sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))
54   (clobber (reg:CC CC_REG))]
55  ""
56  "mulxs.b	%X2,%T0"
57  [(set_attr "length" "4")])
58
59(define_expand "mulhisi3"
60  [(set (match_operand:SI 0 "register_operand" "")
61	(mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" ""))
62		 ;; intentionally-mismatched modes
63		 (match_operand:HI 2 "reg_or_nibble_operand" "")))]
64  ""
65  {
66    if (GET_MODE (operands[2]) != VOIDmode)
67      operands[2] = gen_rtx_SIGN_EXTEND (SImode, operands[2]);
68  })
69
70(define_insn_and_split "*mulhisi3_const"
71  [(set (match_operand:SI 0 "register_operand" "=r")
72	(mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
73		 (match_operand:SI 2 "nibble_operand" "IP4>X")))]
74  "TARGET_H8300SX"
75  "#"
76  "&& reload_completed"
77  [(parallel [(set (match_dup 0)
78		   (mult:SI (sign_extend:SI (match_dup 1)) (match_dup 2)))
79	      (clobber (reg:CC CC_REG))])])
80
81(define_insn "*mulhisi3_const<cczn>"
82  [(set (match_operand:SI 0 "register_operand" "=r")
83	(mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
84		 (match_operand:SI 2 "nibble_operand" "IP4>X")))
85   (clobber (reg:CC CC_REG))]
86  "TARGET_H8300SX"
87  "mulxs.w	%T2,%S0"
88  [(set_attr "length" "4")])
89
90(define_insn_and_split "*mulhisi3"
91  [(set (match_operand:SI 0 "register_operand" "=r")
92	(mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
93		 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
94  ""
95  "#"
96  "&& reload_completed"
97  [(parallel [(set (match_dup 0)
98		   (mult:SI (sign_extend:SI (match_dup 1))
99			    (sign_extend:SI (match_dup 2))))
100	      (clobber (reg:CC CC_REG))])])
101
102(define_insn "*mulhisi3<cczn>"
103  [(set (match_operand:SI 0 "register_operand" "=r")
104	(mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
105		 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))
106   (clobber (reg:CC CC_REG))]
107  ""
108  "mulxs.w	%T2,%S0"
109  [(set_attr "length" "4")])
110
111(define_expand "umulqihi3"
112  [(set (match_operand:HI 0 "register_operand" "")
113	(mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" ""))
114		 ;; intentionally-mismatched modes
115		 (match_operand:QI 2 "reg_or_nibble_operand" "")))]
116  ""
117  {
118    if (GET_MODE (operands[2]) != VOIDmode)
119      operands[2] = gen_rtx_ZERO_EXTEND (HImode, operands[2]);
120  })
121
122(define_insn "*umulqihi3_const"
123  [(set (match_operand:HI 0 "register_operand" "=r")
124	(mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%0"))
125		 (match_operand:QI 2 "nibble_operand" "IP4>X")))]
126  "TARGET_H8300SX"
127  "mulxu.b	%X2,%T0"
128  [(set_attr "length" "4")])
129
130(define_insn "*umulqihi3"
131  [(set (match_operand:HI 0 "register_operand" "=r")
132	(mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%0"))
133		 (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
134  ""
135  "mulxu.b	%X2,%T0"
136  [(set_attr "length" "2")])
137
138(define_expand "umulhisi3"
139  [(set (match_operand:SI 0 "register_operand" "")
140	(mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" ""))
141		 ;; intentionally-mismatched modes
142		 (match_operand:HI 2 "reg_or_nibble_operand" "")))]
143  ""
144  {
145    if (GET_MODE (operands[2]) != VOIDmode)
146      operands[2] = gen_rtx_ZERO_EXTEND (SImode, operands[2]);
147  })
148
149(define_insn "*umulhisi3_const"
150  [(set (match_operand:SI 0 "register_operand" "=r")
151	(mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0"))
152		 (match_operand:SI 2 "nibble_operand" "IP4>X")))]
153  "TARGET_H8300SX"
154  "mulxu.w	%T2,%S0"
155  [(set_attr "length" "4")])
156
157(define_insn "*umulhisi3"
158  [(set (match_operand:SI 0 "register_operand" "=r")
159	(mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0"))
160		 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
161  ""
162  "mulxu.w	%T2,%S0"
163  [(set_attr "length" "2")])
164
165;; We could have used mulu.[wl] here, but mulu.[lw] is only available
166;; on a H8SX with a multiplier, whereas muls.w seems to be available
167;; on all H8SX variants.
168
169(define_insn_and_split "mul<mode>3"
170  [(set (match_operand:HSI 0 "register_operand" "=r")
171        (mult:HSI (match_operand:HSI 1 "register_operand" "%0")
172		  (match_operand:HSI 2 "reg_or_nibble_operand" "r IP4>X")))]
173  "TARGET_H8300SX"
174  "#"
175  "&& reload_completed"
176  [(parallel [(set (match_dup 0) (mult:HSI (match_dup 1) (match_dup 2)))
177	      (clobber (reg:CC CC_REG))])])
178
179(define_insn "mul<mode>3_clobber_flags"
180  [(set (match_operand:HSI 0 "register_operand" "=r")
181        (mult:HSI (match_operand:HSI 1 "register_operand" "%0")
182		  (match_operand:HSI 2 "reg_or_nibble_operand" "r IP4>X")))
183   (clobber (reg:CC CC_REG))]
184  "TARGET_H8300SX"
185  { return <MODE>mode == HImode ? "muls.w\\t%T2,%T0" : "muls.l\\t%S2,%S0"; }
186  [(set_attr "length" "4")])
187
188(define_insn_and_split "smulsi3_highpart"
189  [(set (match_operand:SI 0 "register_operand" "=r")
190	(truncate:SI
191	 (lshiftrt:DI
192	  (mult:DI
193	   (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
194	   (sign_extend:DI (match_operand:SI 2 "reg_or_nibble_operand" "r IP4>X")))
195	  (const_int 32))))]
196  "TARGET_H8300SXMUL"
197  "#"
198  "&& reload_completed"
199  [(parallel [(set (match_dup 0)
200		   (truncate:SI (lshiftrt:DI (mult:DI
201					       (sign_extend:DI (match_dup 1))
202					       (sign_extend:DI (match_dup 2)))
203					     (const_int 32))))
204	      (clobber (reg:CC CC_REG))])])
205
206(define_insn "smulsi3_highpart_clobber_flags"
207  [(set (match_operand:SI 0 "register_operand" "=r")
208	(truncate:SI
209	 (lshiftrt:DI
210	  (mult:DI
211	   (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
212	   (sign_extend:DI (match_operand:SI 2 "reg_or_nibble_operand" "r IP4>X")))
213	  (const_int 32))))
214   (clobber (reg:CC CC_REG))]
215  "TARGET_H8300SXMUL"
216  "muls/u.l\\t%S2,%S0"
217  [(set_attr "length" "4")])
218
219(define_insn "umulsi3_highpart"
220  [(set (match_operand:SI 0 "register_operand" "=r")
221	(truncate:SI
222	  (ashiftrt:DI
223	    (mult:DI
224	      (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
225	      (zero_extend:DI (match_operand:SI 2 "reg_or_nibble_operand" "r IP4>X")))
226	    (const_int 32))))]
227  "TARGET_H8300SX"
228  "mulu/u.l\\t%S2,%S0"
229  [(set_attr "length" "4")])
230
231;; This is a "bridge" instruction.  Combine can't cram enough insns
232;; together to crate a MAC instruction directly, but it can create
233;; this instruction, which then allows combine to create the real
234;; MAC insn.
235;;
236;; Unfortunately, if combine doesn't create a MAC instruction, this
237;; insn must generate reasonably correct code.  Egad.
238
239(define_insn ""
240  [(set (match_operand:SI 0 "register_operand" "=a")
241	(mult:SI
242	  (sign_extend:SI
243	    (mem:HI (post_inc:SI (match_operand:SI 1 "register_operand" "r"))))
244	  (sign_extend:SI
245	    (mem:HI (post_inc:SI (match_operand:SI 2 "register_operand" "r"))))))]
246  "TARGET_MAC"
247  "clrmac\;mac	@%2+,@%1+"
248  [(set_attr "length" "6")])
249
250(define_insn ""
251  [(set (match_operand:SI 0 "register_operand" "=a")
252	(plus:SI (mult:SI
253	  (sign_extend:SI (mem:HI
254	    (post_inc:SI (match_operand:SI 1 "register_operand" "r"))))
255	  (sign_extend:SI (mem:HI
256	    (post_inc:SI (match_operand:SI 2 "register_operand" "r")))))
257	      (match_operand:SI 3 "register_operand" "0")))]
258  "TARGET_MAC"
259  "mac	@%2+,@%1+"
260  [(set_attr "length" "4")])
261
262