]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/msp430/msp430.md
msp430.md: Group zero_extend* insns together.
[thirdparty/gcc.git] / gcc / config / msp430 / msp430.md
CommitLineData
f6a83b4a 1;; Machine Description for TI MSP43* processors
a5544970 2;; Copyright (C) 2013-2019 Free Software Foundation, Inc.
f6a83b4a
DD
3;; Contributed by Red Hat.
4
5;; This file is part of GCC.
6
7;; GCC is free software; you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation; either version 3, or (at your option)
10;; any later version.
11
12;; GCC is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GCC; see the file COPYING3. If not see
19;; <http://www.gnu.org/licenses/>.
20\f
21
22(define_constants
23 [
24 (PC_REGNO 0)
25 (SP_REGNO 1)
26 (CARRY 2)
27 ])
28
29(define_c_enum "unspec"
30 [
31 UNS_PROLOGUE_START_MARKER
32 UNS_PROLOGUE_END_MARKER
33 UNS_EPILOGUE_START_MARKER
34 UNS_EPILOGUE_HELPER
35
36 UNS_PUSHM
37 UNS_POPM
38
39 UNS_GROW_AND_SWAP
40 UNS_SWAP_AND_SHRINK
cad055a4
NC
41
42 UNS_DINT
43 UNS_EINT
44 UNS_PUSH_INTR
45 UNS_POP_INTR
46 UNS_BIC_SR
47 UNS_BIS_SR
4f50b9ff
DD
48
49 UNS_REFSYM_NEED_EXIT
5f35dde5
DD
50
51 UNS_DELAY_32
52 UNS_DELAY_32X
53 UNS_DELAY_16
54 UNS_DELAY_16X
55 UNS_DELAY_2
56 UNS_DELAY_1
57 UNS_DELAY_START
58 UNS_DELAY_END
f6a83b4a 59 ])
c6f709ec 60
d7edde11
NC
61;; This is an approximation.
62(define_attr "length" "" (const_int 4))
63
f6a83b4a
DD
64(include "predicates.md")
65(include "constraints.md")
66
67(define_mode_iterator QHI [QI HI PSI])
68
69;; There are two basic "family" tests we do here:
70;;
71;; msp430x - true if 430X instructions are available.
72;; TARGET_LARGE - true if pointers are 20-bits
73;;
74;; Note that there are three supported cases, since the base 430
75;; doesn't have 20-bit pointers:
76;;
77;; 1. MSP430 cpu, small model
78;; 2. MSP430X cpu, small model.
79;; 3. MSP430X cpu, large model.
80
81;;------------------------------------------------------------
82;; Moves
83
84;; Push/Pop must be before the generic move patterns
85
86(define_insn "push"
87 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNO)))
88 (match_operand:HI 0 "register_operand" "r"))]
89 ""
90 "PUSH\t%0"
91 )
92
93(define_insn "pusha"
94 [(set (mem:PSI (pre_dec:PSI (reg:PSI SP_REGNO)))
95 (match_operand:PSI 0 "register_operand" "r"))]
96 "TARGET_LARGE"
97 "PUSHX.A\t%0"
98 )
99
100(define_insn "pushm"
101 [(unspec_volatile [(match_operand 0 "register_operand" "r")
cad055a4 102 (match_operand 1 "immediate_operand" "n")] UNS_PUSHM)]
f6a83b4a 103 ""
51ac3042 104 "PUSHM%b0\t%1, %0"
f6a83b4a
DD
105 )
106
107(define_insn "pop"
108 [(set (match_operand:HI 0 "register_operand" "=r")
109 (mem:HI (post_inc:HI (reg:HI SP_REGNO))))]
110 ""
111 "POP\t%0"
112 )
113
114(define_insn "popa"
115 [(set (match_operand:PSI 0 "register_operand" "=r")
116 (mem:PSI (post_inc:PSI (reg:PSI SP_REGNO))))]
117 "TARGET_LARGE"
118 "POPX.A\t%0"
119 )
120
121;; This is nasty. Operand0 is bogus. It is only there so that we can get a
51ac3042 122;; mode for the %b0 to work. We should use operand1 for this, but that does
f6a83b4a
DD
123;; not have a mode.
124;;
125;; Operand1 is actually a register, but we cannot accept (REG...) because the
126;; cprop_hardreg pass can and will renumber registers even inside
127;; unspec_volatiles. So we take an integer register number parameter and
d4f283a1 128;; fudge it to be a register name when we generate the assembler.
f6a83b4a
DD
129;;
130;; The pushm pattern does not have this problem because of all of the
131;; frame info cruft attached to it, so cprop_hardreg leaves it alone.
132(define_insn "popm"
133 [(unspec_volatile [(match_operand 0 "register_operand" "r")
134 (match_operand 1 "immediate_operand" "i")
135 (match_operand 2 "immediate_operand" "i")] UNS_POPM)]
136 ""
d4f283a1 137 "POPM%b0\t%2, r%J1"
f6a83b4a
DD
138 )
139
140;; The next two patterns are here to support a "feature" of how GCC implements
141;; varargs. When a function uses varargs and the *second* to last named
142;; argument is split between argument registers and the stack, gcc expects the
143;; callee to allocate space on the stack that can contain the register-based
144;; part of the argument. This space *has* to be just before the remaining
145;; arguments (ie the ones that are fully on the stack).
146;;
147;; The problem is that the MSP430 CALL instruction pushes the return address
148;; onto the stack in the exact place where the callee wants to allocate
149;; this extra space. So we need a sequence of instructions that can allocate
150;; the extra space and then move the return address down the stack, so that
151;; the extra space is now adjacent to the remaining arguments.
152;;
153;; This could be constructed through regular insns, but they might be split up
154;; by a misguided optimization, so an unspec volatile is used instead.
155
156(define_insn "grow_and_swap"
157 [(unspec_volatile [(const_int 0)] UNS_GROW_AND_SWAP)]
158 ""
c6f709ec
NC
159 "*
160 if (TARGET_LARGE)
161 return \"SUBA\t#2, r1 { MOVX.A\t2(r1), 0(r1)\";
162 return \"SUB\t#2, r1 { MOV.W\t2(r1), 0(r1)\";
163 "
164)
f6a83b4a
DD
165
166(define_insn "swap_and_shrink"
167 [(unspec_volatile [(const_int 0)] UNS_SWAP_AND_SHRINK)]
168 ""
c6f709ec
NC
169 "* return TARGET_LARGE
170 ? \"MOVX.A\t0(r1), 2(r1) { ADDA\t#2, SP\"
171 : \"MOV.W\t0(r1), 2(r1) { ADD\t#2, SP\";
172 ")
f6a83b4a
DD
173
174; I set LOAD_EXTEND_OP and WORD_REGISTER_OPERATIONS, but gcc puts in a
175; zero_extend anyway. Catch it here.
176(define_insn "movqihi"
177 [(set (match_operand:HI 0 "register_operand" "=r,r")
178 (zero_extend:HI (match_operand:QI 1 "memory_operand" "Ys,m")))]
179 ""
180 "@
181 MOV.B\t%1, %0
182 MOV%X1.B\t%1, %0"
183)
184
c32ab325 185(define_insn "movqi_topbyte"
28987d8b 186 [(set (match_operand:QI 0 "msp430_general_dst_operand" "=r")
8a896995 187 (subreg:QI (match_operand:PSI 1 "msp430_general_operand" "r") 2))]
c32ab325
DD
188 "msp430x"
189 "PUSHM.A\t#1,%1 { POPM.W\t#1,%0 { POPM.W\t#1,%0"
190)
191
f6a83b4a 192(define_insn "movqi"
28987d8b 193 [(set (match_operand:QI 0 "msp430_general_dst_operand" "=rYsYx,rm")
8a896995 194 (match_operand:QI 1 "msp430_general_operand" "riYsYx,rmi"))]
f6a83b4a
DD
195 ""
196 "@
197 MOV.B\t%1, %0
8682b1a5 198 MOVX.B\t%1, %0"
f6a83b4a
DD
199)
200
201(define_insn "movhi"
28987d8b 202 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=r,rYsYx,rm")
8a896995 203 (match_operand:HI 1 "msp430_general_operand" "N,riYsYx,rmi"))]
f6a83b4a
DD
204 ""
205 "@
3f02735b 206 MOV.B\t%1, %0
f6a83b4a 207 MOV.W\t%1, %0
8682b1a5 208 MOVX.W\t%1, %0"
f6a83b4a
DD
209)
210
211(define_expand "movsi"
28987d8b 212 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand")
40ada30a 213 (match_operand:SI 1 "general_operand"))]
f6a83b4a
DD
214 ""
215 ""
216 )
d7edde11 217
14ae1d88 218(define_insn_and_split "movsi_s"
28987d8b 219 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
14ae1d88
DD
220 (subreg:SI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))]
221 ""
222 ""
223 "reload_completed"
28987d8b 224 [(set (match_operand:HI 2 "msp430_general_dst_nonv_operand")
14ae1d88 225 (match_operand:HI 4 "general_operand"))
28987d8b 226 (set (match_operand:HI 3 "msp430_general_dst_nonv_operand")
14ae1d88
DD
227 (match_operand:HI 5 "general_operand"))]
228 "msp430_split_movsi (operands);"
229 )
230
f6a83b4a 231(define_insn_and_split "movsi_x"
28987d8b 232 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
f6a83b4a
DD
233 (match_operand:SI 1 "general_operand" "rmi"))]
234 ""
235 "#"
236 "reload_completed"
28987d8b 237 [(set (match_operand:HI 2 "msp430_general_dst_nonv_operand")
f6a83b4a 238 (match_operand:HI 4 "general_operand"))
28987d8b 239 (set (match_operand:HI 3 "msp430_general_dst_nonv_operand")
f6a83b4a
DD
240 (match_operand:HI 5 "general_operand"))]
241 "msp430_split_movsi (operands);"
242)
243
8682b1a5 244;; FIXME: Some MOVX.A cases can be done with MOVA, this is only a few of them.
f6a83b4a 245(define_insn "movpsi"
28987d8b 246 [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,r,r,Ya,rm")
8a896995 247 (match_operand:PSI 1 "msp430_general_operand" "N,O,riYa,r,rmi"))]
f6a83b4a
DD
248 ""
249 "@
3f02735b
DD
250 MOV.B\t%1, %0
251 MOV.W\t%1, %0
c32ab325
DD
252 MOVA\t%1, %0
253 MOVA\t%1, %0
254 MOVX.A\t%1, %0")
f6a83b4a
DD
255
256; This pattern is identical to the truncsipsi2 pattern except
257; that it uses a SUBREG instead of a TRUNC. It is needed in
258; order to prevent reload from converting (set:SI (SUBREG:PSI (SI)))
259; into (SET:PSI (PSI)).
260;
261; Note: using POPM.A #1 is two bytes smaller than using POPX.A....
262
263(define_insn "movsipsi2"
264 [(set (match_operand:PSI 0 "register_operand" "=r")
265 (subreg:PSI (match_operand:SI 1 "register_operand" "r") 0))]
c32ab325 266 "msp430x"
d4f283a1 267 "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A #1, %0 ; Move reg-pair %L1:%H1 into pointer %0"
f6a83b4a
DD
268)
269
e56989ff
NC
270;; Produced when converting a pointer to an integer via a union, eg gcc.dg/pr47201.c.
271(define_insn "*movpsihi2_lo"
272 [(set (match_operand:HI 0 "register_operand" "=r")
273 (subreg:HI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))]
274 "msp430x"
275 "MOVA\t%1, %0"
276)
277
f6a83b4a
DD
278;;------------------------------------------------------------
279;; Math
280
281(define_insn "addpsi3"
28987d8b
JL
282 [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,rm")
283 (plus:PSI (match_operand:PSI 1 "msp430_general_operand" "%0,0")
8a896995 284 (match_operand:PSI 2 "msp430_general_operand" "rLs,rmi")))]
f6a83b4a
DD
285 ""
286 "@
287 ADDA\t%2, %0
288 ADDX.A\t%2, %0"
289)
290
291(define_insn "addqi3"
28987d8b
JL
292 [(set (match_operand:QI 0 "msp430_general_dst_operand" "=rYsYx,rm")
293 (plus:QI (match_operand:QI 1 "msp430_general_operand" "%0,0")
8a896995 294 (match_operand:QI 2 "msp430_general_operand" "riYsYx,rmi")))]
f6a83b4a
DD
295 ""
296 "@
297 ADD.B\t%2, %0
8682b1a5 298 ADDX.B\t%2, %0"
f6a83b4a
DD
299)
300
301(define_insn "addhi3"
28987d8b
JL
302 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYsYx,rm")
303 (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0")
8a896995 304 (match_operand:HI 2 "msp430_general_operand" "riYsYx,rmi")))]
f6a83b4a
DD
305 ""
306 "@
307 ADD.W\t%2, %0
8682b1a5 308 ADDX.W\t%2, %0"
f6a83b4a
DD
309)
310
311; This pattern is needed in order to avoid reload problems.
312; It takes an SI pair of registers, adds a value to them, and
313; then converts them into a single PSI register.
314
315(define_insn "addsipsi3"
316 [(set (subreg:SI (match_operand:PSI 0 "register_operand" "=&r") 0)
317 (plus:SI (match_operand:SI 1 "register_operand" "0")
318 (match_operand 2 "general_operand" "rmi")))]
319 ""
8682b1a5 320 "ADD%X2.W\t%L2, %L0 { ADDC%X2.W\t%H2, %H0 { PUSH.W\t%H0 { PUSH.W\t%L0 { POPM.A\t#1, %0"
f6a83b4a
DD
321)
322
323(define_insn "addsi3"
28987d8b
JL
324 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=&rYsYx,rm")
325 (plus:SI (match_operand:SI 1 "general_operand" "%0,0")
8682b1a5 326 (match_operand:SI 2 "general_operand" "rYsYxi,mi")))]
f6a83b4a
DD
327 ""
328 "@
329 ADD\t%L2, %L0 { ADDC\t%H2, %H0
8682b1a5 330 ADDX\t%L2, %L0 { ADDCX\t%H2, %H0"
f6a83b4a
DD
331)
332
333; Version of addhi that exposes the carry operations, for SImode adds.
334;
335; NOTE - we are playing a dangerous game with GCC here. We have these two
336; add patterns and the splitter that follows because our tests have shown
337; that this results in a significant reduction in code size - because GCC is
338; able to discard any unused part of the addition. We have to annotate the
339; patterns with the set and use of the carry flag because otherwise GCC will
340; discard parts of the addition when they are actually needed. But we have
341; not annotated all the other patterns that set the CARRY flag as doing so
342; results in an overall increase in code size[1]. Instead we just *hope*
343; that GCC will not move a carry-setting instruction in between the first
344; and second adds.
345;
346; So far our experiments have shown that GCC is likely to move MOV and CMP
347; instructions in between the two adds, but not other instructions. MOV is
348; safe, CMP is not. So we have annotated the CMP patterns and left the
349; subtract, shift and other add patterns alone. At the moment this is
350; working, but with future changes to the generic parts of GCC that might
351; change.
352;
353; [1] It is not clear exactly why the code size increases. The cause appears
354; to be that reload is more prevelent to spilling a variable onto the stack
355; but why it does this is unknown. Possibly the additional CLOBBERs necessary
356; to correctly annotate the other patterns makes reload think that there is
357; increased register pressure. Or possibly reload does not handle ADD patterns
358; that are not single_set() very well.
359
28987d8b
JL
360; match_operand 3 is likely to be the same as op2 most of the time - except
361; when op2 is a post_inc and we have stripped the post_inc from match_operand 3
362
f6a83b4a 363(define_insn "addhi3_cy"
28987d8b
JL
364 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYsYx,rm")
365 (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0")
8a896995 366 (match_operand:HI 2 "msp430_nonimmediate_operand" "rYsYxi,rm")))
f6a83b4a
DD
367 (set (reg:BI CARRY)
368 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
28987d8b 369 (zero_extend:SI (match_operand:HI 3 "msp430_nonimmediate_operand" "rYsYxi,rm")))
f6a83b4a
DD
370 (const_int 16))))
371 ]
372 ""
373 "@
40ada30a 374 ADD\t%2, %1 ; cy
8682b1a5 375 ADDX\t%2, %1 ; cy"
f6a83b4a
DD
376 )
377
378(define_insn "addhi3_cy_i"
28987d8b
JL
379 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=r,rm")
380 (plus:HI (match_operand:HI 1 "general_operand" "%0,0")
d4f283a1 381 (match_operand:HI 2 "immediate_operand" "i,i")))
f6a83b4a
DD
382 (set (reg:BI CARRY)
383 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
384 (match_operand 3 "immediate_operand" "i,i"))
385 (const_int 16))))
386 ]
387 ""
388 "@
40ada30a
NC
389 ADD\t%2, %1 ; cy
390 ADD%X0\t%2, %1 ; cy"
f6a83b4a
DD
391 )
392
393; Version of addhi that adds the carry, for SImode adds.
394(define_insn "addchi4_cy"
28987d8b
JL
395 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYsYx,rm")
396 (plus:HI (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0")
8a896995 397 (match_operand:HI 2 "msp430_general_operand" "riYsYx,rmi"))
f6a83b4a
DD
398 (zero_extend:HI (reg:BI CARRY))))
399 ]
400 ""
401 "@
40ada30a 402 ADDC\t%2, %1
8682b1a5 403 ADDCX\t%2, %1"
f6a83b4a
DD
404 )
405
406; Split an SImode add into two HImode adds, keeping track of the carry
407; so that gcc knows when it can and can't optimize away the two
408; halves.
28987d8b
JL
409; We use the ugly predicate "msp430_nonsubregnonpostinc_or_imm_operand" to
410; enforce the position of a post_inc into op2 if present
f6a83b4a 411(define_split
28987d8b
JL
412 [(set (match_operand:SI 0 "msp430_nonsubreg_dst_operand")
413 (plus:SI (match_operand:SI 1 "msp430_nonsubregnonpostinc_or_imm_operand")
9c5f6203 414 (match_operand:SI 2 "msp430_nonsubreg_or_imm_operand")))
f6a83b4a
DD
415 ]
416 ""
28987d8b 417 [(parallel [(set (match_operand:HI 3 "msp430_general_dst_nonv_operand" "=&rm")
f6a83b4a
DD
418 (plus:HI (match_dup 4)
419 (match_dup 5)))
420 (set (reg:BI CARRY)
421 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 4))
422 (match_dup 9))
423 (const_int 16))))
424 ])
28987d8b 425 (set (match_operand:HI 6 "msp430_general_dst_nonv_operand" "=&rm")
f6a83b4a
DD
426 (plus:HI (plus:HI (match_dup 7)
427 (match_dup 8))
428 (zero_extend:HI (reg:BI CARRY))))
429 ]
430 "
53f45082
JL
431 if (msp430_split_addsi (operands))
432 FAIL;
433 "
f6a83b4a
DD
434 )
435
436
437;; Alternatives 2 and 3 are to handle cases generated by reload.
438(define_insn "subpsi3"
28987d8b
JL
439 [(set (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r, rm, &?r, ?&r")
440 (minus:PSI (match_operand:PSI 1 "general_operand" "0, 0, !r, !i")
441 (match_operand:PSI 2 "general_operand" "rLs, rmi, rmi, r")))]
f6a83b4a
DD
442 ""
443 "@
444 SUBA\t%2, %0
445 SUBX.A\t%2, %0
446 MOVX.A\t%1, %0 { SUBX.A\t%2, %0
447 MOVX.A\t%1, %0 { SUBA\t%2, %0"
448)
449
450;; Alternatives 2 and 3 are to handle cases generated by reload.
451(define_insn "subqi3"
28987d8b 452 [(set (match_operand:QI 0 "msp430_general_dst_nonv_operand" "=rYsYx, rm, &?r, ?&r")
f6a83b4a 453 (minus:QI (match_operand:QI 1 "general_operand" "0, 0, !r, !i")
8682b1a5 454 (match_operand:QI 2 "general_operand" " riYsYx, rmi, rmi, r")))]
f6a83b4a
DD
455 ""
456 "@
457 SUB.B\t%2, %0
8682b1a5
JL
458 SUBX.B\t%2, %0
459 MOV%X2.B\t%1, %0 { SUB%X2.B\t%2, %0
f6a83b4a
DD
460 MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0"
461)
462
463;; Alternatives 2 and 3 are to handle cases generated by reload.
464(define_insn "subhi3"
28987d8b 465 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=rYsYx, rm, &?r, ?&r")
f6a83b4a 466 (minus:HI (match_operand:HI 1 "general_operand" "0, 0, !r, !i")
8682b1a5 467 (match_operand:HI 2 "general_operand" " riYsYx, rmi, rmi, r")))]
f6a83b4a
DD
468 ""
469 "@
470 SUB.W\t%2, %0
8682b1a5
JL
471 SUBX.W\t%2, %0
472 MOV%X2.W\t%1, %0 { SUB%X2.W\t%2, %0
f6a83b4a
DD
473 MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0"
474)
475
476(define_insn "subsi3"
28987d8b
JL
477 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=&rYsYx,m")
478 (minus:SI (match_operand:SI 1 "general_operand" "0,0")
8682b1a5 479 (match_operand:SI 2 "general_operand" "riYsYx,mi")))]
f6a83b4a 480 ""
8682b1a5
JL
481 "@
482 SUB\t%L2, %L0 { SUBC\t%H2, %H0
483 SUBX\t%L2, %L0 { SUBCX\t%H2, %H0"
f6a83b4a
DD
484)
485
486(define_insn "*bic<mode>_cg"
28987d8b 487 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYs,m")
8a896995 488 (and:QHI (match_operand:QHI 1 "msp430_general_operand" "0,0")
f6a83b4a
DD
489 (match_operand 2 "msp430_inv_constgen_operator" "n,n")))]
490 ""
491 "@
51ac3042
NC
492 BIC%x0%b0\t#%I2, %0
493 BIC%X0%b0\t#%I2, %0"
f6a83b4a
DD
494)
495
496(define_insn "bic<mode>3"
28987d8b 497 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYsYx,rm")
8a896995 498 (and:QHI (not:QHI (match_operand:QHI 1 "msp430_general_operand" "rYsYx,rmn"))
28987d8b 499 (match_operand:QHI 2 "msp430_general_operand" "0,0")))]
f6a83b4a
DD
500 ""
501 "@
51ac3042 502 BIC%x0%b0\t%1, %0
8682b1a5 503 BICX%b0\t%1, %0"
f6a83b4a
DD
504)
505
506(define_insn "and<mode>3"
28987d8b
JL
507 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=r,rYsYx,rm")
508 (and:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0,0")
8a896995 509 (match_operand:QHI 2 "msp430_general_operand" "N,riYsYx,rmi")))]
f6a83b4a
DD
510 ""
511 "@
3f02735b 512 AND%x0.B\t%2, %0
51ac3042 513 AND%x0%b0\t%2, %0
8682b1a5 514 ANDX%b0\t%2, %0"
f6a83b4a
DD
515)
516
517(define_insn "ior<mode>3"
28987d8b
JL
518 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYsYx,rm")
519 (ior:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0")
8a896995 520 (match_operand:QHI 2 "msp430_general_operand" "riYsYx,rmi")))]
f6a83b4a
DD
521 ""
522 "@
51ac3042 523 BIS%x0%b0\t%2, %0
8682b1a5 524 BISX%b0\t%2, %0"
f6a83b4a
DD
525)
526
527(define_insn "xor<mode>3"
28987d8b
JL
528 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYsYx,rm")
529 (xor:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0")
8a896995 530 (match_operand:QHI 2 "msp430_general_operand" "riYsYx,rmi")))]
f6a83b4a
DD
531 ""
532 "@
51ac3042 533 XOR%x0%b0\t%2, %0
8682b1a5 534 XORX%b0\t%2, %0"
f6a83b4a
DD
535)
536
537;; Macro : XOR #~0, %0
538(define_insn "one_cmpl<mode>2"
28987d8b
JL
539 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYs,m")
540 (not:QHI (match_operand:QHI 1 "msp430_general_operand" "0,0")))]
f6a83b4a
DD
541 ""
542 "@
51ac3042
NC
543 INV%x0%b0\t%0
544 INV%X0%b0\t%0"
f6a83b4a
DD
545)
546
547(define_insn "extendqihi2"
28987d8b
JL
548 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYs,m")
549 (sign_extend:HI (match_operand:QI 1 "msp430_general_operand" "0,0")))]
f6a83b4a
DD
550 ""
551 "@
552 SXT%X0\t%0
553 SXT%X0\t%0"
554)
555
556(define_insn "zero_extendqihi2"
28987d8b
JL
557 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYs,r,r,m")
558 (zero_extend:HI (match_operand:QI 1 "msp430_general_operand" "0,rYs,m,0")))]
f6a83b4a
DD
559 ""
560 "@
561 AND\t#0xff, %0
3f02735b 562 MOV.B\t%1, %0
8682b1a5 563 MOV%X1.B\t%1, %0
f6a83b4a
DD
564 AND%X0\t#0xff, %0"
565)
566
582b4055
JL
567(define_insn "zero_extendqisi2"
568 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=r")
569 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
570 ""
571 "MOV%X1.B\t%1,%L0 { CLR\t%H0"
f6a83b4a 572)
d7edde11 573
f6a83b4a 574(define_insn "zero_extendhipsi2"
28987d8b
JL
575 [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,m")
576 (zero_extend:PSI (match_operand:HI 1 "msp430_general_operand" "rm,r")))]
f6a83b4a 577 ""
85bd3c01
NC
578 "@
579 MOVX\t%1, %0
580 MOVX.A\t%1, %0"
f6a83b4a 581)
cac52161 582
f6a83b4a 583(define_insn "zero_extendhisi2"
28987d8b
JL
584 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm,r")
585 (zero_extend:SI (match_operand:HI 1 "general_operand" "0,r")))]
525213a5 586 ""
bdafd679 587 "@
8682b1a5 588 MOV%X0.W\t#0,%H0
bdafd679 589 MOV.W\t%1,%L0 { MOV.W\t#0,%H0"
f6a83b4a
DD
590)
591
592(define_insn "zero_extendhisipsi2"
28987d8b
JL
593 [(set (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r,r")
594 (subreg:PSI (zero_extend:SI (match_operand:HI 1 "general_operand" "0,r")) 0))]
c32ab325 595 "msp430x"
f6a83b4a
DD
596 "@
597 AND.W\t#-1,%0
598 MOV.W\t%1,%0"
599)
600
f6a83b4a
DD
601; Nasty - we are sign-extending a 20-bit PSI value in one register into
602; two adjacent 16-bit registers to make an SI value. There is no MSP430X
603; instruction that will do this, so we push the 20-bit value onto the stack
604; and then pop it off as two 16-bit values.
605;
606; FIXME: The MSP430X documentation does not specify if zero-extension or
607; sign-extension happens when the 20-bit value is pushed onto the stack.
608; It is probably zero-extension, but if not this pattern will not work
609; when the PSI value is negative..
610;
611; Note: using PUSHM.A #1 is two bytes smaller than using PUSHX.A....
8f0e7f6f
NC
612;
613; Note: We use a + constraint on operand 0 as otherwise GCC gets confused
614; about extending a single PSI mode register into a pair of SImode registers
615; with the same starting register. It thinks that the upper register of
616; the pair is unused and so it can clobber it. Try compiling 20050826-2.c
617; at -O2 to see this.
f6a83b4a
DD
618
619(define_insn "zero_extendpsisi2"
8f0e7f6f 620 [(set (match_operand:SI 0 "register_operand" "+r")
f6a83b4a
DD
621 (zero_extend:SI (match_operand:PSI 1 "register_operand" "r")))]
622 ""
623 "*
624 if (REGNO (operands[1]) == SP_REGNO)
625 /* If the source register is the stack pointer, the value
626 stored in the stack slot will be the value *after* the
627 stack pointer has been decremented. So allow for that
628 here. */
d4f283a1 629 return \"PUSHM.A\t#1, %1 { ADDX.W\t#4, @r1 { POPX.W\t%L0 { POPX.W\t%H0 ; get stack pointer into %L0:%H0\";
40ada30a 630 else
d4f283a1 631 return \"PUSHM.A\t#1, %1 { POPX.W\t%L0 { POPX.W\t%H0 ; move pointer in %1 into reg-pair %L0:%H0\";
40ada30a
NC
632 "
633)
634
582b4055
JL
635
636;; Eliminate extraneous zero-extends mysteriously created by gcc.
637(define_peephole2
638 [(set (match_operand:HI 0 "register_operand")
639 (zero_extend:HI (match_operand:QI 1 "general_operand")))
640 (set (match_operand:HI 2 "register_operand")
641 (zero_extend:HI (match_operand:QI 3 "register_operand")))]
642 "REGNO (operands[0]) == REGNO (operands[2]) && REGNO (operands[2]) == REGNO (operands[3])"
643 [(set (match_dup 0)
644 (zero_extend:HI (match_dup 1)))]
645)
646
647(define_insn "truncpsihi2"
648 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rm")
649 (truncate:HI (match_operand:PSI 1 "register_operand" "r")))]
650 ""
651 "MOVX\t%1, %0"
652)
653
654(define_insn "extendhisi2"
655 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=r")
656 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))]
657 ""
658 { return msp430x_extendhisi (operands); }
659)
660
661(define_insn "extendhipsi2"
662 [(set (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r")
663 (subreg:PSI (sign_extend:SI (match_operand:HI 1 "general_operand" "0")) 0))]
664 "msp430x"
665 "RLAM.A #4, %0 { RRAM.A #4, %0"
666)
667
668;; Look for cases where integer/pointer conversions are suboptimal due
669;; to missing patterns, despite us not having opcodes for these
670;; patterns. Doing these manually allows for alternate optimization
671;; paths.
672
673(define_insn "extend_and_shift1_hipsi2"
674 [(set (subreg:SI (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r") 0)
675 (ashift:SI (sign_extend:SI (match_operand:HI 1 "general_operand" "0"))
676 (const_int 1)))]
677 "msp430x"
678 "RLAM.A #4, %0 { RRAM.A #3, %0"
679)
680
681(define_insn "extend_and_shift2_hipsi2"
682 [(set (subreg:SI (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r") 0)
683 (ashift:SI (sign_extend:SI (match_operand:HI 1 "general_operand" "0"))
684 (const_int 2)))]
685 "msp430x"
686 "RLAM.A #4, %0 { RRAM.A #2, %0"
687)
688
40ada30a
NC
689;; We also need to be able to sign-extend pointer types (eg ptrdiff_t).
690;; Since (we assume) pushing a 20-bit value onto the stack zero-extends
691;; it, we use a different method here.
692
693(define_insn "extendpsisi2"
694 [(set (match_operand:SI 0 "register_operand" "=r")
695 (sign_extend:SI (match_operand:PSI 1 "register_operand" "r")))]
c32ab325 696 "msp430x"
40ada30a
NC
697 "*
698 /* The intention here is that we copy the bottom 16-bits of
699 %1 into %L0 (zeroing the top four bits). Then we copy the
700 entire 20-bits of %1 into %H0 and then arithmetically shift
701 it right by 16 bits, to get the top four bits of the pointer
702 sign-extended in %H0. */
703 if (REGNO (operands[0]) == REGNO (operands[1]))
d4f283a1 704 return \"MOVX.A\t%1, %H0 { MOV.W\t%1, %L0 { RPT\t#16 { RRAX.A\t%H0 ; sign extend pointer in %1 into %L0:%H0\";
f6a83b4a 705 else
d4f283a1 706 return \"MOV.W\t%1, %L0 { MOVX.A\t%1, %H0 { RPT\t#16 { RRAX.A\t%H0 ; sign extend pointer in %1 into %L0:%H0\";
f6a83b4a
DD
707 "
708)
709
710; See the movsipsi2 pattern above for another way that GCC performs this
711; conversion.
712(define_insn "truncsipsi2"
713 [(set (match_operand:PSI 0 "register_operand" "=r")
714 (truncate:PSI (match_operand:SI 1 "register_operand" "r")))]
715 ""
d4f283a1 716 "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A\t#1, %L0"
f6a83b4a
DD
717)
718
719;;------------------------------------------------------------
720;; Shift Functions
721
722;; Note: We do not use the RPT ... SHIFT instruction sequence
723;; when the repeat count is in a register, because even though RPT
724;; accepts counts in registers, it does not work if the count is
725;; zero, and the actual count in the register has to be one less
726;; than the required number of iterations. We could encode a
727;; seqeunce like this:
728;;
729;; bit #0xf, Rn
730;; bz 1f
731;; dec Rn
732;; rpt Rn
733;; <shift> Rm
734;; inc Rn
735;; 1:
736;;
737;; But is longer than calling a helper function, and we are mostly
738;; concerned with code size. FIXME: Maybe enable a sequence like
739;; this at -O3 and above ?
740;;
741;; Note - we ignore shift counts of less than one or more than 15.
742;; This is permitted by the ISO C99 standard as such shifts result
9c582551 743;; in "undefined" behavior. [6.5.7 (3)]
f6a83b4a
DD
744
745;; signed A << C
746
747(define_expand "ashlhi3"
28987d8b 748 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand")
f6a83b4a
DD
749 (ashift:HI (match_operand:HI 1 "general_operand")
750 (match_operand:HI 2 "general_operand")))]
751 ""
752 {
e445e4b4
JL
753 if ((GET_CODE (operands[1]) == SUBREG
754 && REG_P (XEXP (operands[1], 0)))
755 || MEM_P (operands[1]))
3f02735b 756 operands[1] = force_reg (HImode, operands[1]);
f6a83b4a
DD
757 if (msp430x
758 && REG_P (operands[0])
759 && REG_P (operands[1])
760 && CONST_INT_P (operands[2]))
761 emit_insn (gen_430x_shift_left (operands[0], operands[1], operands[2]));
9c8a71e6
DD
762 else if (CONST_INT_P (operands[2])
763 && INTVAL (operands[2]) == 1)
764 emit_insn (gen_slli_1 (operands[0], operands[1]));
f6a83b4a 765 else
ec573765
JL
766 /* The const variants of mspabi shifts have larger code size than the
767 generic version, so use the generic version if optimizing for
768 size. */
769 msp430_expand_helper (operands, \"__mspabi_slli\", !optimize_size);
f6a83b4a
DD
770 DONE;
771 }
772)
773
774(define_insn "slli_1"
28987d8b 775 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=rm")
f6a83b4a
DD
776 (ashift:HI (match_operand:HI 1 "general_operand" "0")
777 (const_int 1)))]
778 ""
8682b1a5 779 "RLA%X0.W\t%0" ;; Note - this is a macro for ADD
f6a83b4a
DD
780)
781
782(define_insn "430x_shift_left"
783 [(set (match_operand:HI 0 "register_operand" "=r")
784 (ashift:HI (match_operand:HI 1 "register_operand" "0")
785 (match_operand 2 "immediate_operand" "n")))]
786 "msp430x"
787 "*
788 if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 16)
789 return \"rpt\t%2 { rlax.w\t%0\";
790 return \"# nop left shift\";
791 "
792)
793
794(define_insn "slll_1"
28987d8b 795 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
f6a83b4a
DD
796 (ashift:SI (match_operand:SI 1 "general_operand" "0")
797 (const_int 1)))]
798 ""
8682b1a5 799 "RLA%X0.W\t%L0 { RLC%X0.W\t%H0"
f6a83b4a
DD
800)
801
802(define_insn "slll_2"
28987d8b 803 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
f6a83b4a
DD
804 (ashift:SI (match_operand:SI 1 "general_operand" "0")
805 (const_int 2)))]
806 ""
8682b1a5 807 "RLA%X0.W\t%L0 { RLC%X0.W\t%H0 { RLA%X0.W\t%L0 { RLC%X0.W\t%H0"
f6a83b4a
DD
808)
809
810(define_expand "ashlsi3"
28987d8b 811 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand")
f6a83b4a
DD
812 (ashift:SI (match_operand:SI 1 "general_operand")
813 (match_operand:SI 2 "general_operand")))]
814 ""
ec573765 815 "msp430_expand_helper (operands, \"__mspabi_slll\", !optimize_size);
f6a83b4a
DD
816 DONE;"
817)
818
0fcc78f7 819(define_expand "ashldi3"
28987d8b 820 [(set (match_operand:DI 0 "msp430_general_dst_nonv_operand")
0fcc78f7
JL
821 (ashift:DI (match_operand:DI 1 "general_operand")
822 (match_operand:DI 2 "general_operand")))]
823 ""
824 {
825 /* No const_variant for 64-bit shifts. */
826 msp430_expand_helper (operands, \"__mspabi_sllll\", false);
827 DONE;
828 }
829)
830
f6a83b4a
DD
831;;----------
832
833;; signed A >> C
834
835(define_expand "ashrhi3"
28987d8b 836 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand")
f6a83b4a
DD
837 (ashiftrt:HI (match_operand:HI 1 "general_operand")
838 (match_operand:HI 2 "general_operand")))]
839 ""
840 {
e445e4b4
JL
841 if ((GET_CODE (operands[1]) == SUBREG
842 && REG_P (XEXP (operands[1], 0)))
843 || MEM_P (operands[1]))
3f02735b 844 operands[1] = force_reg (HImode, operands[1]);
f6a83b4a
DD
845 if (msp430x
846 && REG_P (operands[0])
847 && REG_P (operands[1])
848 && CONST_INT_P (operands[2]))
849 emit_insn (gen_430x_arithmetic_shift_right (operands[0], operands[1], operands[2]));
9c8a71e6
DD
850 else if (CONST_INT_P (operands[2])
851 && INTVAL (operands[2]) == 1)
852 emit_insn (gen_srai_1 (operands[0], operands[1]));
f6a83b4a 853 else
ec573765 854 msp430_expand_helper (operands, \"__mspabi_srai\", !optimize_size);
f6a83b4a
DD
855 DONE;
856 }
857)
858
859(define_insn "srai_1"
28987d8b 860 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rm")
8a896995 861 (ashiftrt:HI (match_operand:HI 1 "msp430_general_operand" "0")
f6a83b4a
DD
862 (const_int 1)))]
863 ""
8682b1a5 864 "RRA%X0.W\t%0"
f6a83b4a
DD
865)
866
867(define_insn "430x_arithmetic_shift_right"
868 [(set (match_operand:HI 0 "register_operand" "=r")
869 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
870 (match_operand 2 "immediate_operand" "n")))]
871 "msp430x"
872 "*
873 if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 16)
874 return \"rpt\t%2 { rrax.w\t%0\";
875 return \"# nop arith right shift\";
876 "
877)
878
879(define_insn "srap_1"
880 [(set (match_operand:PSI 0 "register_operand" "=r")
881 (ashiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
882 (const_int 1)))]
883 "msp430x"
884 "RRAM.A #1,%0"
885)
886
887(define_insn "srap_2"
888 [(set (match_operand:PSI 0 "register_operand" "=r")
889 (ashiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
890 (const_int 2)))]
891 "msp430x"
892 "RRAM.A #2,%0"
893)
894
895(define_insn "sral_1"
28987d8b 896 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
f6a83b4a
DD
897 (ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
898 (const_int 1)))]
899 ""
8682b1a5 900 "RRA%X0.W\t%H0 { RRC%X0.W\t%L0"
f6a83b4a
DD
901)
902
903(define_insn "sral_2"
28987d8b 904 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
f6a83b4a
DD
905 (ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
906 (const_int 2)))]
907 ""
8682b1a5 908 "RRA%X0.W\t%H0 { RRC%X0.W\t%L0 { RRA%X0.W\t%H0 { RRC%X0.W\t%L0"
f6a83b4a
DD
909)
910
911(define_expand "ashrsi3"
28987d8b 912 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand")
f6a83b4a
DD
913 (ashiftrt:SI (match_operand:SI 1 "general_operand")
914 (match_operand:SI 2 "general_operand")))]
915 ""
ec573765 916 "msp430_expand_helper (operands, \"__mspabi_sral\", !optimize_size);
f6a83b4a
DD
917 DONE;"
918)
919
0fcc78f7 920(define_expand "ashrdi3"
28987d8b 921 [(set (match_operand:DI 0 "msp430_general_dst_nonv_operand")
0fcc78f7
JL
922 (ashift:DI (match_operand:DI 1 "general_operand")
923 (match_operand:DI 2 "general_operand")))]
924 ""
925 {
926 /* No const_variant for 64-bit shifts. */
927 msp430_expand_helper (operands, \"__mspabi_srall\", false);
928 DONE;
929 }
930)
931
f6a83b4a
DD
932;;----------
933
934;; unsigned A >> C
935
936(define_expand "lshrhi3"
28987d8b 937 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand")
f6a83b4a
DD
938 (lshiftrt:HI (match_operand:HI 1 "general_operand")
939 (match_operand:HI 2 "general_operand")))]
940 ""
941 {
e445e4b4
JL
942 if ((GET_CODE (operands[1]) == SUBREG
943 && REG_P (XEXP (operands[1], 0)))
944 || MEM_P (operands[1]))
3f02735b 945 operands[1] = force_reg (HImode, operands[1]);
f6a83b4a
DD
946 if (msp430x
947 && REG_P (operands[0])
948 && REG_P (operands[1])
949 && CONST_INT_P (operands[2]))
950 emit_insn (gen_430x_logical_shift_right (operands[0], operands[1], operands[2]));
9c8a71e6
DD
951 else if (CONST_INT_P (operands[2])
952 && INTVAL (operands[2]) == 1)
953 emit_insn (gen_srli_1 (operands[0], operands[1]));
f6a83b4a 954 else
ec573765 955 msp430_expand_helper (operands, \"__mspabi_srli\", !optimize_size);
f6a83b4a
DD
956 DONE;
957 }
958)
959
960(define_insn "srli_1"
28987d8b 961 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=rm")
f6a83b4a
DD
962 (lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
963 (const_int 1)))]
964 ""
8682b1a5 965 "CLRC { RRC%X0.W\t%0"
f6a83b4a
DD
966)
967
968(define_insn "430x_logical_shift_right"
969 [(set (match_operand:HI 0 "register_operand" "=r")
970 (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
971 (match_operand 2 "immediate_operand" "n")))]
972 "msp430x"
973 {
974 return msp430x_logical_shift_right (operands[2]);
975 }
976)
977
978(define_insn "srlp_1"
979 [(set (match_operand:PSI 0 "register_operand" "=r")
980 (lshiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
981 (const_int 1)))]
982 ""
983 "RRUM.A #1,%0"
984)
985
986(define_insn "srll_1"
28987d8b 987 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
f6a83b4a
DD
988 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
989 (const_int 1)))]
990 ""
8682b1a5 991 "CLRC { RRC%X0.W\t%H0 { RRC%X0.W\t%L0"
f6a83b4a
DD
992)
993
994(define_insn "srll_2x"
28987d8b 995 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=r")
f6a83b4a
DD
996 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
997 (const_int 2)))]
998 "msp430x"
999 "RRUX.W\t%H0 { RRC.W\t%L0 { RRUX.W\t%H0 { RRC.W\t%L0"
1000)
1001
1002(define_expand "lshrsi3"
28987d8b 1003 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand")
f6a83b4a
DD
1004 (lshiftrt:SI (match_operand:SI 1 "general_operand")
1005 (match_operand:SI 2 "general_operand")))]
1006 ""
ec573765 1007 "msp430_expand_helper (operands, \"__mspabi_srll\", !optimize_size);
f6a83b4a
DD
1008 DONE;"
1009)
1010
0fcc78f7 1011(define_expand "lshrdi3"
28987d8b 1012 [(set (match_operand:DI 0 "msp430_general_dst_nonv_operand")
0fcc78f7
JL
1013 (ashift:DI (match_operand:DI 1 "general_operand")
1014 (match_operand:DI 2 "general_operand")))]
1015 ""
1016 {
1017 /* No const_variant for 64-bit shifts. */
1018 msp430_expand_helper (operands, \"__mspabi_srlll\", false);
1019 DONE;
1020 }
1021)
1022
f6a83b4a
DD
1023;;------------------------------------------------------------
1024;; Function Entry/Exit
1025
1026(define_expand "prologue"
1027 [(const_int 0)]
1028 ""
1029 "msp430_expand_prologue (); DONE;"
1030 )
1031
1032(define_expand "epilogue"
1033 [(const_int 0)]
1034 ""
1035 "msp430_expand_epilogue (0); DONE;"
1036 )
1037
f6a83b4a
DD
1038(define_insn "epilogue_helper"
1039 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_EPILOGUE_HELPER)]
1040 ""
fb28dac0 1041 "BR%Q0\t#__mspabi_func_epilog_%J0"
f6a83b4a
DD
1042 )
1043
f6a83b4a
DD
1044(define_insn "prologue_start_marker"
1045 [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_START_MARKER)]
1046 ""
1047 "; start of prologue"
1048 )
1049
1050(define_insn "prologue_end_marker"
1051 [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_END_MARKER)]
1052 ""
1053 "; end of prologue"
1054 )
1055
1056(define_insn "epilogue_start_marker"
1057 [(unspec_volatile [(const_int 0)] UNS_EPILOGUE_START_MARKER)]
1058 ""
1059 "; start of epilogue"
1060 )
1061
4f50b9ff
DD
1062;; This makes the linker add a call to exit() after the call to main()
1063;; in crt0
1064(define_insn "msp430_refsym_need_exit"
1065 [(unspec_volatile [(const_int 0)] UNS_REFSYM_NEED_EXIT)]
1066 ""
1067 ".refsym\t__crt0_call_exit"
1068 )
1069
f6a83b4a
DD
1070;;------------------------------------------------------------
1071;; Jumps
1072
1073(define_expand "call"
1074 [(call:HI (match_operand 0 "")
40ada30a 1075 (match_operand 1 ""))]
f6a83b4a
DD
1076 ""
1077 ""
1078)
1079
1080(define_insn "call_internal"
fb28dac0 1081 [(call (mem:HI (match_operand 0 "general_operand" "rYci"))
f6a83b4a
DD
1082 (match_operand 1 ""))]
1083 ""
51ac3042 1084 "CALL%Q0\t%0"
f6a83b4a
DD
1085)
1086
1087(define_expand "call_value"
1088 [(set (match_operand 0 "register_operand")
1089 (call:HI (match_operand 1 "general_operand")
1090 (match_operand 2 "")))]
1091 ""
1092 ""
1093)
1094
1095(define_insn "call_value_internal"
1096 [(set (match_operand 0 "register_operand" "=r")
fb28dac0 1097 (call (mem:HI (match_operand 1 "general_operand" "rYci"))
f6a83b4a
DD
1098 (match_operand 2 "")))]
1099 ""
51ac3042 1100 "CALL%Q0\t%1"
f6a83b4a
DD
1101)
1102
8a896995 1103(define_insn "msp430_return"
f6a83b4a
DD
1104 [(return)]
1105 ""
cad055a4 1106 { return msp430_is_interrupt_func () ? "RETI" : (TARGET_LARGE ? "RETA" : "RET"); }
f6a83b4a
DD
1107)
1108
1109;; This pattern is NOT, as expected, a return pattern. It's called
1110;; before reload and must only store its operands, and emit a
1111;; placeholder where the epilog needs to be. AFTER reload, the
1112;; placeholder should get expanded into a regular-type epilogue that
1113;; also does the EH return.
1114(define_expand "eh_return"
40ada30a 1115 [(match_operand:HI 0 "")]
f6a83b4a
DD
1116 ""
1117 "msp430_expand_eh_return (operands[0]);
1118 emit_jump_insn (gen_msp430_eh_epilogue ());
1119 emit_barrier ();
1120 DONE;"
1121)
1122
1123;; This is the actual EH epilogue. We emit it in the pattern above,
1124;; before reload, and convert it to a real epilogue after reload.
1125(define_insn_and_split "msp430_eh_epilogue"
1126 [(eh_return)]
1127 ""
1128 "#"
1129 "reload_completed"
1130 [(const_int 0)]
1131 "msp430_expand_epilogue (1); DONE;"
1132 )
1133
1134(define_insn "jump"
1135 [(set (pc)
1136 (label_ref (match_operand 0 "" "")))]
1137 ""
51ac3042 1138 "BR%Q0\t#%l0"
f6a83b4a
DD
1139)
1140
1141;; FIXME: GCC currently (8/feb/2013) cannot handle symbol_refs
1142;; in indirect jumps (cf gcc.c-torture/compile/991213-3.c).
1143(define_insn "indirect_jump"
1144 [(set (pc)
1145 (match_operand 0 "nonimmediate_operand" "rYl"))]
1146 ""
51ac3042 1147 "BR%Q0\t%0"
f6a83b4a
DD
1148)
1149
1150;;------------------------------------------------------------
1151;; Various Conditionals
1152
1153(define_expand "cbranch<mode>4"
1154 [(parallel [(set (pc) (if_then_else
1155 (match_operator 0 ""
1156 [(match_operand:QHI 1 "nonimmediate_operand")
1157 (match_operand:QHI 2 "general_operand")])
1158 (label_ref (match_operand 3 "" ""))
1159 (pc)))
1160 (clobber (reg:BI CARRY))]
1161 )]
1162 ""
1163 "msp430_fixup_compare_operands (<MODE>mode, operands);"
1164 )
1165
1166(define_insn "cbranchpsi4_real"
1167 [(set (pc) (if_then_else
1168 (match_operator 0 "msp430_cmp_operator"
1169 [(match_operand:PSI 1 "nonimmediate_operand" "r,rYs,rm")
1170 (match_operand:PSI 2 "general_operand" "rLs,rYsi,rmi")])
1171 (label_ref (match_operand 3 "" ""))
1172 (pc)))
1173 (clobber (reg:BI CARRY))
1174 ]
1175 ""
1176 "@
51ac3042 1177 CMP%Q0\t%2, %1 { J%0\t%l3
f6a83b4a
DD
1178 CMPX.A\t%2, %1 { J%0\t%l3
1179 CMPX.A\t%2, %1 { J%0\t%l3"
1180 )
1181
1182(define_insn "cbranchqi4_real"
1183 [(set (pc) (if_then_else
1184 (match_operator 0 "msp430_cmp_operator"
8682b1a5
JL
1185 [(match_operand:QI 1 "nonimmediate_operand" "rYsYx,rm")
1186 (match_operand:QI 2 "general_operand" "rYsYxi,rmi")])
f6a83b4a
DD
1187 (label_ref (match_operand 3 "" ""))
1188 (pc)))
1189 (clobber (reg:BI CARRY))
1190 ]
1191 ""
1192 "@
1193 CMP.B\t%2, %1 { J%0\t%l3
8682b1a5 1194 CMPX.B\t%2, %1 { J%0\t%l3"
f6a83b4a
DD
1195 )
1196
1197(define_insn "cbranchhi4_real"
1198 [(set (pc) (if_then_else
1199 (match_operator 0 "msp430_cmp_operator"
8682b1a5
JL
1200 [(match_operand:HI 1 "nonimmediate_operand" "rYsYx,rm")
1201 (match_operand:HI 2 "general_operand" "rYsYxi,rmi")])
f6a83b4a
DD
1202 (label_ref (match_operand 3 "" ""))
1203 (pc)))
1204 (clobber (reg:BI CARRY))
1205 ]
1206 ""
d7edde11
NC
1207 "*
1208 /* This is nasty. If we are splitting code between low and high memory
1209 then we do not want the linker to increase the size of sections by
1210 relaxing out of range jump instructions. (Since relaxation occurs
1211 after section placement). So we have to generate pessimal branches
1212 here. But we only want to do this when really necessary.
1213
1214 FIXME: Do we need code in the other cbranch patterns ? */
1215 if (msp430_do_not_relax_short_jumps () && get_attr_length (insn) > 6)
1216 {
1217 return which_alternative == 0 ?
1218 \"CMP.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\" :
8682b1a5 1219 \"CMPX.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\";
d7edde11
NC
1220 }
1221
1222 return which_alternative == 0 ?
1223 \"CMP.W\t%2, %1 { J%0\t%l3\" :
8682b1a5 1224 \"CMPX.W\t%2, %1 { J%0\t%l3\";
d7edde11
NC
1225 "
1226 [(set (attr "length")
1227 (if_then_else
1228 (and (ge (minus (match_dup 3) (pc)) (const_int -510))
1229 (le (minus (match_dup 3) (pc)) (const_int 510)))
1230 (const_int 6)
1231 (const_int 10))
1232 )]
f6a83b4a
DD
1233 )
1234
1235(define_insn "cbranchpsi4_reversed"
1236 [(set (pc) (if_then_else
1237 (match_operator 0 "msp430_reversible_cmp_operator"
1238 [(match_operand:PSI 1 "general_operand" "rLs,rYsi,rmi")
1239 (match_operand:PSI 2 "general_operand" "r,rYs,rm")])
1240 (label_ref (match_operand 3 "" ""))
1241 (pc)))
1242 (clobber (reg:BI CARRY))
1243 ]
1244 ""
1245 "@
51ac3042 1246 CMP%Q0\t%1, %2 { J%R0\t%l3
f6a83b4a
DD
1247 CMPX.A\t%1, %2 { J%R0\t%l3
1248 CMPX.A\t%1, %2 { J%R0\t%l3"
1249 )
1250
1251(define_insn "cbranchqi4_reversed"
1252 [(set (pc) (if_then_else
1253 (match_operator 0 "msp430_reversible_cmp_operator"
8682b1a5
JL
1254 [(match_operand:QI 1 "general_operand" "rYsYxi,rmi")
1255 (match_operand:QI 2 "general_operand" "rYsYx,rm")])
f6a83b4a
DD
1256 (label_ref (match_operand 3 "" ""))
1257 (pc)))
1258 (clobber (reg:BI CARRY))
1259 ]
1260 ""
1261 "@
1262 CMP.B\t%1, %2 { J%R0\t%l3
8682b1a5 1263 CMPX.B\t%1, %2 { J%R0\t%l3"
f6a83b4a
DD
1264 )
1265
1266(define_insn "cbranchhi4_reversed"
1267 [(set (pc) (if_then_else
1268 (match_operator 0 "msp430_reversible_cmp_operator"
8682b1a5
JL
1269 [(match_operand:HI 1 "general_operand" "rYsYxi,rmi")
1270 (match_operand:HI 2 "general_operand" "rYsYx,rm")])
f6a83b4a
DD
1271 (label_ref (match_operand 3 "" ""))
1272 (pc)))
1273 (clobber (reg:BI CARRY))
1274 ]
1275 ""
1276 "@
1277 CMP.W\t%1, %2 { J%R0\t%l3
8682b1a5 1278 CMPX.W\t%1, %2 { J%R0\t%l3"
f6a83b4a
DD
1279 )
1280
f6a83b4a
DD
1281(define_insn "*bitbranch<mode>4"
1282 [(set (pc) (if_then_else
28987d8b 1283 (ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
8a896995 1284 (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
f6a83b4a
DD
1285 (const_int 0))
1286 (label_ref (match_operand 2 "" ""))
1287 (pc)))
1288 (clobber (reg:BI CARRY))
1289 ]
1290 ""
1291 "@
51ac3042 1292 BIT%x0%b0\t%1, %0 { JNE\t%l2
8682b1a5 1293 BITX%b0\t%1, %0 { JNE\t%l2"
f6a83b4a
DD
1294 )
1295
1296(define_insn "*bitbranch<mode>4"
1297 [(set (pc) (if_then_else
28987d8b 1298 (eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
8a896995 1299 (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
f6a83b4a
DD
1300 (const_int 0))
1301 (label_ref (match_operand 2 "" ""))
1302 (pc)))
1303 (clobber (reg:BI CARRY))
1304 ]
1305 ""
8682b1a5
JL
1306 "@
1307 BIT%x0%b0\t%1, %0 { JEQ\t%l2
1308 BITX%b0\t%1, %0 { JEQ\t%l2"
f6a83b4a
DD
1309 )
1310
1311(define_insn "*bitbranch<mode>4"
1312 [(set (pc) (if_then_else
28987d8b 1313 (eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
8a896995 1314 (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
f6a83b4a
DD
1315 (const_int 0))
1316 (pc)
1317 (label_ref (match_operand 2 "" ""))))
1318 (clobber (reg:BI CARRY))
1319 ]
1320 ""
8682b1a5
JL
1321 "@
1322 BIT%x0%b0\t%1, %0 { JNE\t%l2
1323 BITX%b0\t%1, %0 { JNE\t%l2"
f6a83b4a
DD
1324 )
1325
1326(define_insn "*bitbranch<mode>4"
1327 [(set (pc) (if_then_else
28987d8b 1328 (ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
8a896995 1329 (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
f6a83b4a
DD
1330 (const_int 0))
1331 (pc)
1332 (label_ref (match_operand 2 "" ""))))
1333 (clobber (reg:BI CARRY))
1334 ]
1335 ""
8682b1a5
JL
1336 "@
1337 BIT%x0%b0\t%1, %0 { JEQ\t%l2
1338 BITX%b0\t%1, %0 { JEQ\t%l2"
f6a83b4a
DD
1339 )
1340
1341;;------------------------------------------------------------
cad055a4 1342;; zero-extract versions of the above
f6a83b4a
DD
1343
1344(define_insn "*bitbranch<mode>4_z"
1345 [(set (pc) (if_then_else
28987d8b 1346 (ne (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rYs,rm")
f6a83b4a
DD
1347 (const_int 1)
1348 (match_operand 1 "msp430_bitpos" "i,i"))
1349 (const_int 0))
1350 (label_ref (match_operand 2 "" ""))
1351 (pc)))
1352 (clobber (reg:BI CARRY))
1353 ]
1354 ""
1355 "@
51ac3042
NC
1356 BIT%x0%b0\t%p1, %0 { JNE\t%l2
1357 BIT%X0%b0\t%p1, %0 { JNE\t%l2"
f6a83b4a
DD
1358 )
1359
1360(define_insn "*bitbranch<mode>4_z"
1361 [(set (pc) (if_then_else
28987d8b 1362 (eq (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm")
f6a83b4a
DD
1363 (const_int 1)
1364 (match_operand 1 "msp430_bitpos" "i"))
1365 (const_int 0))
1366 (label_ref (match_operand 2 "" ""))
1367 (pc)))
1368 (clobber (reg:BI CARRY))
1369 ]
1370 ""
8682b1a5 1371 "BIT%X0%b0\t%p1, %0 { JEQ\t%l2"
f6a83b4a
DD
1372 )
1373
1374(define_insn "*bitbranch<mode>4_z"
1375 [(set (pc) (if_then_else
28987d8b 1376 (eq (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm")
f6a83b4a
DD
1377 (const_int 1)
1378 (match_operand 1 "msp430_bitpos" "i"))
1379 (const_int 0))
1380 (pc)
1381 (label_ref (match_operand 2 "" ""))))
1382 (clobber (reg:BI CARRY))
1383 ]
1384 ""
51ac3042 1385 "BIT%X0%b0\t%p1, %0 { JNE\t%l2"
f6a83b4a
DD
1386 )
1387
1388(define_insn "*bitbranch<mode>4_z"
1389 [(set (pc) (if_then_else
28987d8b 1390 (ne (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm")
f6a83b4a
DD
1391 (const_int 1)
1392 (match_operand 1 "msp430_bitpos" "i"))
1393 (const_int 0))
1394 (pc)
1395 (label_ref (match_operand 2 "" ""))))
1396 (clobber (reg:BI CARRY))
1397 ]
1398 ""
51ac3042 1399 "BIT%X0%b0\t%p1, %0 { JEQ\t%l2"
f6a83b4a
DD
1400 )
1401
1402;;------------------------------------------------------------
1403;; Misc
1404
1405(define_insn "nop"
1406 [(const_int 0)]
1407 "1"
1408 "NOP"
1409)
a005b5be 1410
cad055a4
NC
1411(define_insn "disable_interrupts"
1412 [(unspec_volatile [(const_int 0)] UNS_DINT)]
1413 ""
a005b5be 1414 "DINT \; NOP"
cad055a4
NC
1415 )
1416
1417(define_insn "enable_interrupts"
1418 [(unspec_volatile [(const_int 0)] UNS_EINT)]
1419 ""
1420 "EINT"
1421 )
1422
1423(define_insn "push_intr_state"
1424 [(unspec_volatile [(const_int 0)] UNS_PUSH_INTR)]
1425 ""
1426 "PUSH\tSR"
1427 )
1428
1429(define_insn "pop_intr_state"
1430 [(unspec_volatile [(const_int 0)] UNS_POP_INTR)]
1431 ""
1432 "POP\tSR"
1433 )
1434
1435;; Clear bits in the copy of the status register that is currently
1436;; saved on the stack at the top of the interrupt handler.
1437(define_insn "bic_SR"
1438 [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIC_SR)]
1439 ""
1440 "BIC.W\t%0, %O0(SP)"
1441 )
1442
1443;; Set bits in the copy of the status register that is currently
1444;; saved on the stack at the top of the interrupt handler.
1445(define_insn "bis_SR"
1446 [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIS_SR)]
1447 ""
1448 "BIS.W\t%0, %O0(SP)"
1449 )
40ada30a
NC
1450
1451;; For some reason GCC is generating (set (reg) (and (neg (reg)) (int)))
1452;; very late on in the compilation and not splitting it into separate
1453;; instructions, so we provide a pattern to support it here.
1454(define_insn "andneghi3"
1455 [(set (match_operand:HI 0 "register_operand" "=r")
1456 (and:HI (neg:HI (match_operand:HI 1 "register_operand" "r"))
1457 (match_operand 2 "immediate_operand" "n")))]
1458 ""
1459 "*
1460 if (REGNO (operands[0]) != REGNO (operands[1]))
9c5f6203 1461 return \"MOV.W\t%1, %0 { INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0\";
40ada30a 1462 else
9c5f6203 1463 return \"INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0\";
40ada30a
NC
1464 "
1465 )
c6f709ec 1466
5f35dde5
DD
1467(define_insn "delay_cycles_start"
1468 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
1469 UNS_DELAY_START)]
1470 ""
1471 "; Begin %J0 cycle delay"
1472 )
1473
1474(define_insn "delay_cycles_end"
1475 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
1476 UNS_DELAY_END)]
1477 ""
1478 "; End %J0 cycle delay"
1479 )
1480
1481(define_insn "delay_cycles_32"
1482 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1483 (match_operand 1 "immediate_operand" "i")
1484 ] UNS_DELAY_32)]
1485 ""
1486 "PUSH r13
1487 PUSH r14
1488 MOV.W %A0, r13
1489 MOV.W %B0, r14
14901: SUB.W #1, r13
1491 SUBC.W #0, r14
1492 JNE 1b
1493 TST.W r13
1494 JNE 1b
1495 POP r14
1496 POP r13"
1497 )
1498
1499(define_insn "delay_cycles_32x"
1500 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1501 (match_operand 1 "immediate_operand" "i")
1502 ] UNS_DELAY_32X)]
1503 ""
47f138d1 1504 "PUSHM.A #2,r14
5f35dde5
DD
1505 MOV.W %A0, r13
1506 MOV.W %B0, r14
15071: SUB.W #1, r13
1508 SUBC.W #0, r14
1509 JNE 1b
1510 TST.W r13
1511 JNE 1b
47f138d1 1512 POPM.A #2,r14"
5f35dde5
DD
1513 )
1514
1515(define_insn "delay_cycles_16"
1516 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1517 (match_operand 1 "immediate_operand" "i")
1518 ] UNS_DELAY_16)]
1519 ""
1520 "PUSH r13
1521 MOV.W %0, r13
15221: SUB.W #1, r13
1523 JNE 1b
1524 POP r13"
1525 )
1526
1527(define_insn "delay_cycles_16x"
1528 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1529 (match_operand 1 "immediate_operand" "i")
1530 ] UNS_DELAY_16X)]
1531 ""
1532 "PUSHM.A #1,r13
1533 MOV.W %0, r13
15341: SUB.W #1, r13
1535 JNE 1b
1536 POPM.A #1,r13"
1537 )
1538
1539(define_insn "delay_cycles_2"
1540 [(unspec_volatile [(const_int 0) ] UNS_DELAY_2)]
1541 ""
1542 "JMP .+2"
1543 )
1544
1545(define_insn "delay_cycles_1"
1546 [(unspec_volatile [(const_int 0) ] UNS_DELAY_1)]
1547 ""
1548 "NOP"
1549 )
1550
c6f709ec
NC
1551(define_insn "mulhisi3"
1552 [(set (match_operand:SI 0 "register_operand" "=r")
1553 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1554 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
b07447ba 1555 "optimize > 2 && msp430_hwmult_type != MSP430_HWMULT_NONE"
c6f709ec 1556 "*
f7961364 1557 if (msp430_use_f5_series_hwmult ())
ba3cf9f1 1558 return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x04C2 { MOV.W %2, &0x04C8 { MOV.W &0x04CA, %L0 { MOV.W &0x04CC, %H0 { POP.W sr\";
c6f709ec 1559 else
ba3cf9f1 1560 return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x0132 { MOV.W %2, &0x0138 { MOV.W &0x013A, %L0 { MOV.W &0x013C, %H0 { POP.W sr\";
c6f709ec
NC
1561 "
1562)
1563
1564(define_insn "umulhisi3"
1565 [(set (match_operand:SI 0 "register_operand" "=r")
1566 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1567 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
b07447ba 1568 "optimize > 2 && msp430_hwmult_type != MSP430_HWMULT_NONE"
c6f709ec 1569 "*
f7961364 1570 if (msp430_use_f5_series_hwmult ())
ba3cf9f1 1571 return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x04C0 { MOV.W %2, &0x04C8 { MOV.W &0x04CA, %L0 { MOV.W &0x04CC, %H0 { POP.W sr\";
c6f709ec 1572 else
ba3cf9f1 1573 return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x0130 { MOV.W %2, &0x0138 { MOV.W &0x013A, %L0 { MOV.W &0x013C, %H0 { POP.W sr\";
c6f709ec
NC
1574 "
1575)
1576
1577(define_insn "mulsidi3"
1578 [(set (match_operand:DI 0 "register_operand" "=r")
1579 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
1580 (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
b07447ba 1581 "optimize > 2 && msp430_hwmult_type != MSP430_HWMULT_NONE"
c6f709ec 1582 "*
f7961364 1583 if (msp430_use_f5_series_hwmult ())
ba3cf9f1 1584 return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x04D4 { MOV.W %H1, &0x04D6 { MOV.W %L2, &0x04E0 { MOV.W %H2, &0x04E2 { MOV.W &0x04E4, %A0 { MOV.W &0x04E6, %B0 { MOV.W &0x04E8, %C0 { MOV.W &0x04EA, %D0 { POP.W sr\";
c6f709ec 1585 else
ba3cf9f1 1586 return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x0144 { MOV.W %H1, &0x0146 { MOV.W %L2, &0x0150 { MOV.W %H2, &0x0152 { MOV.W &0x0154, %A0 { MOV.W &0x0156, %B0 { MOV.W &0x0158, %C0 { MOV.W &0x015A, %D0 { POP.W sr\";
c6f709ec
NC
1587 "
1588)
1589
1590(define_insn "umulsidi3"
1591 [(set (match_operand:DI 0 "register_operand" "=r")
1592 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
1593 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
b07447ba 1594 "optimize > 2 && msp430_hwmult_type != MSP430_HWMULT_NONE"
c6f709ec 1595 "*
f7961364 1596 if (msp430_use_f5_series_hwmult ())
ba3cf9f1 1597 return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x04D0 { MOV.W %H1, &0x04D2 { MOV.W %L2, &0x04E0 { MOV.W %H2, &0x04E2 { MOV.W &0x04E4, %A0 { MOV.W &0x04E6, %B0 { MOV.W &0x04E8, %C0 { MOV.W &0x04EA, %D0 { POP.W sr\";
c6f709ec 1598 else
ba3cf9f1 1599 return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x0140 { MOV.W %H1, &0x0142 { MOV.W %L2, &0x0150 { MOV.W %H2, &0x0152 { MOV.W &0x0154, %A0 { MOV.W &0x0156, %B0 { MOV.W &0x0158, %C0 { MOV.W &0x015A, %D0 { POP.W sr\";
c6f709ec
NC
1600 "
1601)