]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/msp430/msp430.md
Update copyright years.
[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
DD
185(define_insn "movqi_topbyte"
186 [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=r")
187 (subreg:QI (match_operand:PSI 1 "msp_general_operand" "r") 2))]
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"
a3b50977
DD
193 [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=rYs,rm")
194 (match_operand:QI 1 "msp_general_operand" "riYs,rmi"))]
f6a83b4a
DD
195 ""
196 "@
197 MOV.B\t%1, %0
198 MOV%X0.B\t%1, %0"
199)
200
201(define_insn "movhi"
3f02735b
DD
202 [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=r,rYs,rm")
203 (match_operand:HI 1 "msp_general_operand" "N,riYs,rmi"))]
f6a83b4a
DD
204 ""
205 "@
3f02735b 206 MOV.B\t%1, %0
f6a83b4a
DD
207 MOV.W\t%1, %0
208 MOV%X0.W\t%1, %0"
209)
210
211(define_expand "movsi"
40ada30a
NC
212 [(set (match_operand:SI 0 "nonimmediate_operand")
213 (match_operand:SI 1 "general_operand"))]
f6a83b4a
DD
214 ""
215 ""
216 )
d7edde11 217
14ae1d88
DD
218(define_insn_and_split "movsi_s"
219 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
220 (subreg:SI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))]
221 ""
222 ""
223 "reload_completed"
224 [(set (match_operand:HI 2 "nonimmediate_operand")
225 (match_operand:HI 4 "general_operand"))
226 (set (match_operand:HI 3 "nonimmediate_operand")
227 (match_operand:HI 5 "general_operand"))]
228 "msp430_split_movsi (operands);"
229 )
230
f6a83b4a
DD
231(define_insn_and_split "movsi_x"
232 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
233 (match_operand:SI 1 "general_operand" "rmi"))]
234 ""
235 "#"
236 "reload_completed"
237 [(set (match_operand:HI 2 "nonimmediate_operand")
238 (match_operand:HI 4 "general_operand"))
239 (set (match_operand:HI 3 "nonimmediate_operand")
240 (match_operand:HI 5 "general_operand"))]
241 "msp430_split_movsi (operands);"
242)
243
244;; Some MOVX.A cases can be done with MOVA, this is only a few of them.
245(define_insn "movpsi"
3f02735b
DD
246 [(set (match_operand:PSI 0 "msp_nonimmediate_operand" "=r,r,r,Ya,rm")
247 (match_operand:PSI 1 "msp_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"
a3b50977
DD
282 [(set (match_operand:PSI 0 "msp_nonimmediate_operand" "=r,rm")
283 (plus:PSI (match_operand:PSI 1 "msp_nonimmediate_operand" "%0,0")
284 (match_operand:PSI 2 "msp_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"
a3b50977
DD
292 [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=rYs,rm")
293 (plus:QI (match_operand:QI 1 "msp_nonimmediate_operand" "%0,0")
294 (match_operand:QI 2 "msp_general_operand" "riYs,rmi")))]
f6a83b4a
DD
295 ""
296 "@
297 ADD.B\t%2, %0
298 ADD%X0.B\t%2, %0"
299)
300
301(define_insn "addhi3"
a3b50977
DD
302 [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rYs,rm")
303 (plus:HI (match_operand:HI 1 "msp_nonimmediate_operand" "%0,0")
304 (match_operand:HI 2 "msp_general_operand" "riYs,rmi")))]
f6a83b4a
DD
305 ""
306 "@
307 ADD.W\t%2, %0
308 ADD%X0.W\t%2, %0"
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 ""
d4f283a1 320 "ADD.W\t%L2, %L0 { ADDC.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"
324 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,rm")
325 (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
326 (match_operand:SI 2 "general_operand" "r,mi")))]
327 ""
328 "@
329 ADD\t%L2, %L0 { ADDC\t%H2, %H0
330 ADD%X0\t%L2, %L0 { ADDC%X0\t%H2, %H0"
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
360(define_insn "addhi3_cy"
51ac3042 361 [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=r,rm")
a3b50977 362 (plus:HI (match_operand:HI 1 "msp_nonimmediate_operand" "%0,0")
d4f283a1 363 (match_operand:HI 2 "msp_nonimmediate_operand" "r,rm")))
f6a83b4a
DD
364 (set (reg:BI CARRY)
365 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
366 (zero_extend:SI (match_dup 2)))
367 (const_int 16))))
368 ]
369 ""
370 "@
40ada30a
NC
371 ADD\t%2, %1 ; cy
372 ADD%X0\t%2, %1 ; cy"
f6a83b4a
DD
373 )
374
375(define_insn "addhi3_cy_i"
d4f283a1 376 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,rm")
f6a83b4a 377 (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
d4f283a1 378 (match_operand:HI 2 "immediate_operand" "i,i")))
f6a83b4a
DD
379 (set (reg:BI CARRY)
380 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
381 (match_operand 3 "immediate_operand" "i,i"))
382 (const_int 16))))
383 ]
384 ""
385 "@
40ada30a
NC
386 ADD\t%2, %1 ; cy
387 ADD%X0\t%2, %1 ; cy"
f6a83b4a
DD
388 )
389
390; Version of addhi that adds the carry, for SImode adds.
391(define_insn "addchi4_cy"
51ac3042 392 [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=r,rm")
a3b50977 393 (plus:HI (plus:HI (match_operand:HI 1 "msp_nonimmediate_operand" "%0,0")
d4f283a1 394 (match_operand:HI 2 "msp_general_operand" "ri,rmi"))
f6a83b4a
DD
395 (zero_extend:HI (reg:BI CARRY))))
396 ]
397 ""
398 "@
40ada30a
NC
399 ADDC\t%2, %1
400 ADDC%X0\t%2, %1"
f6a83b4a
DD
401 )
402
403; Split an SImode add into two HImode adds, keeping track of the carry
404; so that gcc knows when it can and can't optimize away the two
405; halves.
406(define_split
51ac3042 407 [(set (match_operand:SI 0 "msp430_nonsubreg_operand")
9c5f6203
DD
408 (plus:SI (match_operand:SI 1 "msp430_nonsubreg_operand")
409 (match_operand:SI 2 "msp430_nonsubreg_or_imm_operand")))
f6a83b4a
DD
410 ]
411 ""
412 [(parallel [(set (match_operand:HI 3 "nonimmediate_operand" "=&rm")
413 (plus:HI (match_dup 4)
414 (match_dup 5)))
415 (set (reg:BI CARRY)
416 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 4))
417 (match_dup 9))
418 (const_int 16))))
419 ])
420 (set (match_operand:HI 6 "nonimmediate_operand" "=&rm")
421 (plus:HI (plus:HI (match_dup 7)
422 (match_dup 8))
423 (zero_extend:HI (reg:BI CARRY))))
424 ]
425 "
426 operands[3] = msp430_subreg (HImode, operands[0], SImode, 0);
427 operands[4] = msp430_subreg (HImode, operands[1], SImode, 0);
428 operands[5] = msp430_subreg (HImode, operands[2], SImode, 0);
429 operands[6] = msp430_subreg (HImode, operands[0], SImode, 2);
430 operands[7] = msp430_subreg (HImode, operands[1], SImode, 2);
431 operands[8] = msp430_subreg (HImode, operands[2], SImode, 2);
5704db33
NC
432
433 /* BZ 64160: Do not use this splitter when the dest partially overlaps the source. */
434 if (reg_overlap_mentioned_p (operands[3], operands[7])
435 || reg_overlap_mentioned_p (operands[3], operands[8]))
436 FAIL;
437
f6a83b4a 438 if (GET_CODE (operands[5]) == CONST_INT)
5704db33 439 operands[9] = GEN_INT (INTVAL (operands[5]) & 0xffff);
f6a83b4a 440 else
5704db33 441 operands[9] = gen_rtx_ZERO_EXTEND (SImode, operands[5]);
f6a83b4a
DD
442 "
443 )
444
445
446;; Alternatives 2 and 3 are to handle cases generated by reload.
447(define_insn "subpsi3"
448 [(set (match_operand:PSI 0 "nonimmediate_operand" "=r, rm, &?r, ?&r")
449 (minus:PSI (match_operand:PSI 1 "general_operand" "0, 0, !r, !i")
450 (match_operand:PSI 2 "general_operand" "rLs, rmi, rmi, r")))]
451 ""
452 "@
453 SUBA\t%2, %0
454 SUBX.A\t%2, %0
455 MOVX.A\t%1, %0 { SUBX.A\t%2, %0
456 MOVX.A\t%1, %0 { SUBA\t%2, %0"
457)
458
459;; Alternatives 2 and 3 are to handle cases generated by reload.
460(define_insn "subqi3"
461 [(set (match_operand:QI 0 "nonimmediate_operand" "=rYs, rm, &?r, ?&r")
462 (minus:QI (match_operand:QI 1 "general_operand" "0, 0, !r, !i")
463 (match_operand:QI 2 "general_operand" " riYs, rmi, rmi, r")))]
464 ""
465 "@
466 SUB.B\t%2, %0
467 SUB%X0.B\t%2, %0
468 MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0
469 MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0"
470)
471
472;; Alternatives 2 and 3 are to handle cases generated by reload.
473(define_insn "subhi3"
474 [(set (match_operand:HI 0 "nonimmediate_operand" "=rYs, rm, &?r, ?&r")
475 (minus:HI (match_operand:HI 1 "general_operand" "0, 0, !r, !i")
476 (match_operand:HI 2 "general_operand" " riYs, rmi, rmi, r")))]
477 ""
478 "@
479 SUB.W\t%2, %0
480 SUB%X0.W\t%2, %0
481 MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0
482 MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0"
483)
484
485(define_insn "subsi3"
486 [(set (match_operand:SI 0 "nonimmediate_operand" "=&rm")
487 (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0")
488 (match_operand:SI 2 "general_operand" "rmi")))]
489 ""
490 "SUB%X0\t%L2, %L0 { SUBC%X0\t%H2, %H0"
491)
492
493(define_insn "*bic<mode>_cg"
494 [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,m")
495 (and:QHI (match_operand:QHI 1 "msp_general_operand" "0,0")
496 (match_operand 2 "msp430_inv_constgen_operator" "n,n")))]
497 ""
498 "@
51ac3042
NC
499 BIC%x0%b0\t#%I2, %0
500 BIC%X0%b0\t#%I2, %0"
f6a83b4a
DD
501)
502
503(define_insn "bic<mode>3"
504 [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,rm")
505 (and:QHI (not:QHI (match_operand:QHI 1 "msp_general_operand" "rYs,rmn"))
506 (match_operand:QHI 2 "msp_nonimmediate_operand" "0,0")))]
507 ""
508 "@
51ac3042
NC
509 BIC%x0%b0\t%1, %0
510 BIC%X0%b0\t%1, %0"
f6a83b4a
DD
511)
512
513(define_insn "and<mode>3"
3f02735b
DD
514 [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=r,rYs,rm")
515 (and:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "%0,0,0")
516 (match_operand:QHI 2 "msp_general_operand" "N,riYs,rmi")))]
f6a83b4a
DD
517 ""
518 "@
3f02735b 519 AND%x0.B\t%2, %0
51ac3042
NC
520 AND%x0%b0\t%2, %0
521 AND%X0%b0\t%2, %0"
f6a83b4a
DD
522)
523
524(define_insn "ior<mode>3"
51ac3042 525 [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,rm")
f6a83b4a
DD
526 (ior:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "%0,0")
527 (match_operand:QHI 2 "msp_general_operand" "riYs,rmi")))]
528 ""
529 "@
51ac3042
NC
530 BIS%x0%b0\t%2, %0
531 BIS%X0%b0\t%2, %0"
f6a83b4a
DD
532)
533
534(define_insn "xor<mode>3"
51ac3042 535 [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,rm")
a3b50977
DD
536 (xor:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "%0,0")
537 (match_operand:QHI 2 "msp_general_operand" "riYs,rmi")))]
f6a83b4a
DD
538 ""
539 "@
51ac3042
NC
540 XOR%x0%b0\t%2, %0
541 XOR%X0%b0\t%2, %0"
f6a83b4a
DD
542)
543
544;; Macro : XOR #~0, %0
545(define_insn "one_cmpl<mode>2"
51ac3042 546 [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,m")
a3b50977 547 (not:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "0,0")))]
f6a83b4a
DD
548 ""
549 "@
51ac3042
NC
550 INV%x0%b0\t%0
551 INV%X0%b0\t%0"
f6a83b4a
DD
552)
553
554(define_insn "extendqihi2"
51ac3042 555 [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rYs,m")
a3b50977 556 (sign_extend:HI (match_operand:QI 1 "msp_nonimmediate_operand" "0,0")))]
f6a83b4a
DD
557 ""
558 "@
559 SXT%X0\t%0
560 SXT%X0\t%0"
561)
562
563(define_insn "zero_extendqihi2"
3f02735b
DD
564 [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rYs,r,r,m")
565 (zero_extend:HI (match_operand:QI 1 "msp_nonimmediate_operand" "0,rYs,m,0")))]
f6a83b4a
DD
566 ""
567 "@
568 AND\t#0xff, %0
3f02735b
DD
569 MOV.B\t%1, %0
570 MOV%X0.B\t%1, %0
f6a83b4a
DD
571 AND%X0\t#0xff, %0"
572)
573
574;; Eliminate extraneous zero-extends mysteriously created by gcc.
575(define_peephole2
576 [(set (match_operand:HI 0 "register_operand")
577 (zero_extend:HI (match_operand:QI 1 "general_operand")))
578 (set (match_operand:HI 2 "register_operand")
579 (zero_extend:HI (match_operand:QI 3 "register_operand")))]
580 "REGNO (operands[0]) == REGNO (operands[2]) && REGNO (operands[2]) == REGNO (operands[3])"
581 [(set (match_dup 0)
582 (zero_extend:HI (match_dup 1)))]
583)
d7edde11 584
f6a83b4a 585(define_insn "zero_extendhipsi2"
d4f283a1 586 [(set (match_operand:PSI 0 "msp_nonimmediate_operand" "=r,m")
a3b50977 587 (zero_extend:PSI (match_operand:HI 1 "msp_nonimmediate_operand" "rm,r")))]
f6a83b4a 588 ""
85bd3c01
NC
589 "@
590 MOVX\t%1, %0
591 MOVX.A\t%1, %0"
f6a83b4a
DD
592)
593
594(define_insn "truncpsihi2"
a3b50977 595 [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rm")
f6a83b4a
DD
596 (truncate:HI (match_operand:PSI 1 "register_operand" "r")))]
597 ""
598 "MOVX\t%1, %0"
599)
600
601(define_insn "extendhisi2"
602 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
603 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))]
604 ""
605 { return msp430x_extendhisi (operands); }
606)
607
608(define_insn "extendhipsi2"
609 [(set (match_operand:PSI 0 "nonimmediate_operand" "=r")
610 (subreg:PSI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) 0))]
c32ab325 611 "msp430x"
862edcd1 612 "RLAM.A #4, %0 { RRAM.A #4, %0"
f6a83b4a
DD
613)
614
615;; Look for cases where integer/pointer conversions are suboptimal due
616;; to missing patterns, despite us not having opcodes for these
617;; patterns. Doing these manually allows for alternate optimization
618;; paths.
3f02735b
DD
619
620(define_insn "zero_extendqisi2"
621 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
525213a5
JL
622 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
623 ""
3f02735b
DD
624 "MOV.B\t%1,%L0 { CLR\t%H0"
625)
626
f6a83b4a 627(define_insn "zero_extendhisi2"
bdafd679
NC
628 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
629 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r")))]
525213a5 630 ""
bdafd679
NC
631 "@
632 MOV.W\t#0,%H0
633 MOV.W\t%1,%L0 { MOV.W\t#0,%H0"
f6a83b4a
DD
634)
635
636(define_insn "zero_extendhisipsi2"
637 [(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r")
638 (subreg:PSI (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r")) 0))]
c32ab325 639 "msp430x"
f6a83b4a
DD
640 "@
641 AND.W\t#-1,%0
642 MOV.W\t%1,%0"
643)
644
645(define_insn "extend_and_shift1_hipsi2"
646 [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0)
647 (ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0"))
648 (const_int 1)))]
c32ab325 649 "msp430x"
862edcd1 650 "RLAM.A #4, %0 { RRAM.A #3, %0"
f6a83b4a
DD
651)
652
653(define_insn "extend_and_shift2_hipsi2"
654 [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0)
655 (ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0"))
656 (const_int 2)))]
c32ab325 657 "msp430x"
862edcd1 658 "RLAM.A #4, %0 { RRAM.A #2, %0"
f6a83b4a
DD
659)
660
661; Nasty - we are sign-extending a 20-bit PSI value in one register into
662; two adjacent 16-bit registers to make an SI value. There is no MSP430X
663; instruction that will do this, so we push the 20-bit value onto the stack
664; and then pop it off as two 16-bit values.
665;
666; FIXME: The MSP430X documentation does not specify if zero-extension or
667; sign-extension happens when the 20-bit value is pushed onto the stack.
668; It is probably zero-extension, but if not this pattern will not work
669; when the PSI value is negative..
670;
671; Note: using PUSHM.A #1 is two bytes smaller than using PUSHX.A....
8f0e7f6f
NC
672;
673; Note: We use a + constraint on operand 0 as otherwise GCC gets confused
674; about extending a single PSI mode register into a pair of SImode registers
675; with the same starting register. It thinks that the upper register of
676; the pair is unused and so it can clobber it. Try compiling 20050826-2.c
677; at -O2 to see this.
f6a83b4a
DD
678
679(define_insn "zero_extendpsisi2"
8f0e7f6f 680 [(set (match_operand:SI 0 "register_operand" "+r")
f6a83b4a
DD
681 (zero_extend:SI (match_operand:PSI 1 "register_operand" "r")))]
682 ""
683 "*
684 if (REGNO (operands[1]) == SP_REGNO)
685 /* If the source register is the stack pointer, the value
686 stored in the stack slot will be the value *after* the
687 stack pointer has been decremented. So allow for that
688 here. */
d4f283a1 689 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 690 else
d4f283a1 691 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
692 "
693)
694
695;; We also need to be able to sign-extend pointer types (eg ptrdiff_t).
696;; Since (we assume) pushing a 20-bit value onto the stack zero-extends
697;; it, we use a different method here.
698
699(define_insn "extendpsisi2"
700 [(set (match_operand:SI 0 "register_operand" "=r")
701 (sign_extend:SI (match_operand:PSI 1 "register_operand" "r")))]
c32ab325 702 "msp430x"
40ada30a
NC
703 "*
704 /* The intention here is that we copy the bottom 16-bits of
705 %1 into %L0 (zeroing the top four bits). Then we copy the
706 entire 20-bits of %1 into %H0 and then arithmetically shift
707 it right by 16 bits, to get the top four bits of the pointer
708 sign-extended in %H0. */
709 if (REGNO (operands[0]) == REGNO (operands[1]))
d4f283a1 710 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 711 else
d4f283a1 712 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
713 "
714)
715
716; See the movsipsi2 pattern above for another way that GCC performs this
717; conversion.
718(define_insn "truncsipsi2"
719 [(set (match_operand:PSI 0 "register_operand" "=r")
720 (truncate:PSI (match_operand:SI 1 "register_operand" "r")))]
721 ""
d4f283a1 722 "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A\t#1, %L0"
f6a83b4a
DD
723)
724
725;;------------------------------------------------------------
726;; Shift Functions
727
728;; Note: We do not use the RPT ... SHIFT instruction sequence
729;; when the repeat count is in a register, because even though RPT
730;; accepts counts in registers, it does not work if the count is
731;; zero, and the actual count in the register has to be one less
732;; than the required number of iterations. We could encode a
733;; seqeunce like this:
734;;
735;; bit #0xf, Rn
736;; bz 1f
737;; dec Rn
738;; rpt Rn
739;; <shift> Rm
740;; inc Rn
741;; 1:
742;;
743;; But is longer than calling a helper function, and we are mostly
744;; concerned with code size. FIXME: Maybe enable a sequence like
745;; this at -O3 and above ?
746;;
747;; Note - we ignore shift counts of less than one or more than 15.
748;; This is permitted by the ISO C99 standard as such shifts result
9c582551 749;; in "undefined" behavior. [6.5.7 (3)]
f6a83b4a
DD
750
751;; signed A << C
752
753(define_expand "ashlhi3"
754 [(set (match_operand:HI 0 "nonimmediate_operand")
755 (ashift:HI (match_operand:HI 1 "general_operand")
756 (match_operand:HI 2 "general_operand")))]
757 ""
758 {
3f02735b
DD
759 if (GET_CODE (operands[1]) == SUBREG
760 && REG_P (XEXP (operands[1], 0)))
761 operands[1] = force_reg (HImode, operands[1]);
f6a83b4a
DD
762 if (msp430x
763 && REG_P (operands[0])
764 && REG_P (operands[1])
765 && CONST_INT_P (operands[2]))
766 emit_insn (gen_430x_shift_left (operands[0], operands[1], operands[2]));
9c8a71e6
DD
767 else if (CONST_INT_P (operands[2])
768 && INTVAL (operands[2]) == 1)
769 emit_insn (gen_slli_1 (operands[0], operands[1]));
f6a83b4a
DD
770 else
771 msp430_expand_helper (operands, \"__mspabi_slli\", true);
772 DONE;
773 }
774)
775
776(define_insn "slli_1"
777 [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
778 (ashift:HI (match_operand:HI 1 "general_operand" "0")
779 (const_int 1)))]
780 ""
781 "RLA.W\t%0" ;; Note - this is a macro for ADD
782)
783
784(define_insn "430x_shift_left"
785 [(set (match_operand:HI 0 "register_operand" "=r")
786 (ashift:HI (match_operand:HI 1 "register_operand" "0")
787 (match_operand 2 "immediate_operand" "n")))]
788 "msp430x"
789 "*
790 if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 16)
791 return \"rpt\t%2 { rlax.w\t%0\";
792 return \"# nop left shift\";
793 "
794)
795
796(define_insn "slll_1"
797 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
798 (ashift:SI (match_operand:SI 1 "general_operand" "0")
799 (const_int 1)))]
800 ""
801 "RLA.W\t%L0 { RLC.W\t%H0"
802)
803
804(define_insn "slll_2"
805 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
806 (ashift:SI (match_operand:SI 1 "general_operand" "0")
807 (const_int 2)))]
808 ""
809 "RLA.W\t%L0 { RLC.W\t%H0 { RLA.W\t%L0 { RLC.W\t%H0"
810)
811
812(define_expand "ashlsi3"
813 [(set (match_operand:SI 0 "nonimmediate_operand")
814 (ashift:SI (match_operand:SI 1 "general_operand")
815 (match_operand:SI 2 "general_operand")))]
816 ""
817 "msp430_expand_helper (operands, \"__mspabi_slll\", true);
818 DONE;"
819)
820
821;;----------
822
823;; signed A >> C
824
825(define_expand "ashrhi3"
826 [(set (match_operand:HI 0 "nonimmediate_operand")
827 (ashiftrt:HI (match_operand:HI 1 "general_operand")
828 (match_operand:HI 2 "general_operand")))]
829 ""
830 {
3f02735b
DD
831 if (GET_CODE (operands[1]) == SUBREG
832 && REG_P (XEXP (operands[1], 0)))
833 operands[1] = force_reg (HImode, operands[1]);
f6a83b4a
DD
834 if (msp430x
835 && REG_P (operands[0])
836 && REG_P (operands[1])
837 && CONST_INT_P (operands[2]))
838 emit_insn (gen_430x_arithmetic_shift_right (operands[0], operands[1], operands[2]));
9c8a71e6
DD
839 else if (CONST_INT_P (operands[2])
840 && INTVAL (operands[2]) == 1)
841 emit_insn (gen_srai_1 (operands[0], operands[1]));
f6a83b4a
DD
842 else
843 msp430_expand_helper (operands, \"__mspabi_srai\", true);
844 DONE;
845 }
846)
847
848(define_insn "srai_1"
a3b50977
DD
849 [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rm")
850 (ashiftrt:HI (match_operand:HI 1 "msp_general_operand" "0")
f6a83b4a
DD
851 (const_int 1)))]
852 ""
853 "RRA.W\t%0"
854)
855
856(define_insn "430x_arithmetic_shift_right"
857 [(set (match_operand:HI 0 "register_operand" "=r")
858 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
859 (match_operand 2 "immediate_operand" "n")))]
860 "msp430x"
861 "*
862 if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 16)
863 return \"rpt\t%2 { rrax.w\t%0\";
864 return \"# nop arith right shift\";
865 "
866)
867
868(define_insn "srap_1"
869 [(set (match_operand:PSI 0 "register_operand" "=r")
870 (ashiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
871 (const_int 1)))]
872 "msp430x"
873 "RRAM.A #1,%0"
874)
875
876(define_insn "srap_2"
877 [(set (match_operand:PSI 0 "register_operand" "=r")
878 (ashiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
879 (const_int 2)))]
880 "msp430x"
881 "RRAM.A #2,%0"
882)
883
884(define_insn "sral_1"
885 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
886 (ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
887 (const_int 1)))]
888 ""
889 "RRA.W\t%H0 { RRC.W\t%L0"
890)
891
892(define_insn "sral_2"
893 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
894 (ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
895 (const_int 2)))]
896 ""
897 "RRA.W\t%H0 { RRC.W\t%L0 { RRA.W\t%H0 { RRC.W\t%L0"
898)
899
900(define_expand "ashrsi3"
901 [(set (match_operand:SI 0 "nonimmediate_operand")
902 (ashiftrt:SI (match_operand:SI 1 "general_operand")
903 (match_operand:SI 2 "general_operand")))]
904 ""
905 "msp430_expand_helper (operands, \"__mspabi_sral\", true);
906 DONE;"
907)
908
909;;----------
910
911;; unsigned A >> C
912
913(define_expand "lshrhi3"
914 [(set (match_operand:HI 0 "nonimmediate_operand")
915 (lshiftrt:HI (match_operand:HI 1 "general_operand")
916 (match_operand:HI 2 "general_operand")))]
917 ""
918 {
3f02735b
DD
919 if (GET_CODE (operands[1]) == SUBREG
920 && REG_P (XEXP (operands[1], 0)))
921 operands[1] = force_reg (HImode, operands[1]);
f6a83b4a
DD
922 if (msp430x
923 && REG_P (operands[0])
924 && REG_P (operands[1])
925 && CONST_INT_P (operands[2]))
926 emit_insn (gen_430x_logical_shift_right (operands[0], operands[1], operands[2]));
9c8a71e6
DD
927 else if (CONST_INT_P (operands[2])
928 && INTVAL (operands[2]) == 1)
929 emit_insn (gen_srli_1 (operands[0], operands[1]));
f6a83b4a
DD
930 else
931 msp430_expand_helper (operands, \"__mspabi_srli\", true);
932 DONE;
933 }
934)
935
936(define_insn "srli_1"
937 [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
938 (lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
939 (const_int 1)))]
940 ""
941 "CLRC { RRC.W\t%0"
942)
943
944(define_insn "430x_logical_shift_right"
945 [(set (match_operand:HI 0 "register_operand" "=r")
946 (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
947 (match_operand 2 "immediate_operand" "n")))]
948 "msp430x"
949 {
950 return msp430x_logical_shift_right (operands[2]);
951 }
952)
953
954(define_insn "srlp_1"
955 [(set (match_operand:PSI 0 "register_operand" "=r")
956 (lshiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
957 (const_int 1)))]
958 ""
959 "RRUM.A #1,%0"
960)
961
962(define_insn "srll_1"
963 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
964 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
965 (const_int 1)))]
966 ""
967 "CLRC { RRC.W\t%H0 { RRC.W\t%L0"
968)
969
970(define_insn "srll_2x"
971 [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
972 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
973 (const_int 2)))]
974 "msp430x"
975 "RRUX.W\t%H0 { RRC.W\t%L0 { RRUX.W\t%H0 { RRC.W\t%L0"
976)
977
978(define_expand "lshrsi3"
979 [(set (match_operand:SI 0 "nonimmediate_operand")
980 (lshiftrt:SI (match_operand:SI 1 "general_operand")
981 (match_operand:SI 2 "general_operand")))]
982 ""
983 "msp430_expand_helper (operands, \"__mspabi_srll\", true);
984 DONE;"
985)
986
987;;------------------------------------------------------------
988;; Function Entry/Exit
989
990(define_expand "prologue"
991 [(const_int 0)]
992 ""
993 "msp430_expand_prologue (); DONE;"
994 )
995
996(define_expand "epilogue"
997 [(const_int 0)]
998 ""
999 "msp430_expand_epilogue (0); DONE;"
1000 )
1001
f6a83b4a
DD
1002(define_insn "epilogue_helper"
1003 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_EPILOGUE_HELPER)]
1004 ""
fb28dac0 1005 "BR%Q0\t#__mspabi_func_epilog_%J0"
f6a83b4a
DD
1006 )
1007
f6a83b4a
DD
1008(define_insn "prologue_start_marker"
1009 [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_START_MARKER)]
1010 ""
1011 "; start of prologue"
1012 )
1013
1014(define_insn "prologue_end_marker"
1015 [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_END_MARKER)]
1016 ""
1017 "; end of prologue"
1018 )
1019
1020(define_insn "epilogue_start_marker"
1021 [(unspec_volatile [(const_int 0)] UNS_EPILOGUE_START_MARKER)]
1022 ""
1023 "; start of epilogue"
1024 )
1025
4f50b9ff
DD
1026;; This makes the linker add a call to exit() after the call to main()
1027;; in crt0
1028(define_insn "msp430_refsym_need_exit"
1029 [(unspec_volatile [(const_int 0)] UNS_REFSYM_NEED_EXIT)]
1030 ""
1031 ".refsym\t__crt0_call_exit"
1032 )
1033
f6a83b4a
DD
1034;;------------------------------------------------------------
1035;; Jumps
1036
1037(define_expand "call"
1038 [(call:HI (match_operand 0 "")
40ada30a 1039 (match_operand 1 ""))]
f6a83b4a
DD
1040 ""
1041 ""
1042)
1043
1044(define_insn "call_internal"
fb28dac0 1045 [(call (mem:HI (match_operand 0 "general_operand" "rYci"))
f6a83b4a
DD
1046 (match_operand 1 ""))]
1047 ""
51ac3042 1048 "CALL%Q0\t%0"
f6a83b4a
DD
1049)
1050
1051(define_expand "call_value"
1052 [(set (match_operand 0 "register_operand")
1053 (call:HI (match_operand 1 "general_operand")
1054 (match_operand 2 "")))]
1055 ""
1056 ""
1057)
1058
1059(define_insn "call_value_internal"
1060 [(set (match_operand 0 "register_operand" "=r")
fb28dac0 1061 (call (mem:HI (match_operand 1 "general_operand" "rYci"))
f6a83b4a
DD
1062 (match_operand 2 "")))]
1063 ""
51ac3042 1064 "CALL%Q0\t%1"
f6a83b4a
DD
1065)
1066
1067(define_insn "msp_return"
1068 [(return)]
1069 ""
cad055a4 1070 { return msp430_is_interrupt_func () ? "RETI" : (TARGET_LARGE ? "RETA" : "RET"); }
f6a83b4a
DD
1071)
1072
1073;; This pattern is NOT, as expected, a return pattern. It's called
1074;; before reload and must only store its operands, and emit a
1075;; placeholder where the epilog needs to be. AFTER reload, the
1076;; placeholder should get expanded into a regular-type epilogue that
1077;; also does the EH return.
1078(define_expand "eh_return"
40ada30a 1079 [(match_operand:HI 0 "")]
f6a83b4a
DD
1080 ""
1081 "msp430_expand_eh_return (operands[0]);
1082 emit_jump_insn (gen_msp430_eh_epilogue ());
1083 emit_barrier ();
1084 DONE;"
1085)
1086
1087;; This is the actual EH epilogue. We emit it in the pattern above,
1088;; before reload, and convert it to a real epilogue after reload.
1089(define_insn_and_split "msp430_eh_epilogue"
1090 [(eh_return)]
1091 ""
1092 "#"
1093 "reload_completed"
1094 [(const_int 0)]
1095 "msp430_expand_epilogue (1); DONE;"
1096 )
1097
1098(define_insn "jump"
1099 [(set (pc)
1100 (label_ref (match_operand 0 "" "")))]
1101 ""
51ac3042 1102 "BR%Q0\t#%l0"
f6a83b4a
DD
1103)
1104
1105;; FIXME: GCC currently (8/feb/2013) cannot handle symbol_refs
1106;; in indirect jumps (cf gcc.c-torture/compile/991213-3.c).
1107(define_insn "indirect_jump"
1108 [(set (pc)
1109 (match_operand 0 "nonimmediate_operand" "rYl"))]
1110 ""
51ac3042 1111 "BR%Q0\t%0"
f6a83b4a
DD
1112)
1113
1114;;------------------------------------------------------------
1115;; Various Conditionals
1116
1117(define_expand "cbranch<mode>4"
1118 [(parallel [(set (pc) (if_then_else
1119 (match_operator 0 ""
1120 [(match_operand:QHI 1 "nonimmediate_operand")
1121 (match_operand:QHI 2 "general_operand")])
1122 (label_ref (match_operand 3 "" ""))
1123 (pc)))
1124 (clobber (reg:BI CARRY))]
1125 )]
1126 ""
1127 "msp430_fixup_compare_operands (<MODE>mode, operands);"
1128 )
1129
1130(define_insn "cbranchpsi4_real"
1131 [(set (pc) (if_then_else
1132 (match_operator 0 "msp430_cmp_operator"
1133 [(match_operand:PSI 1 "nonimmediate_operand" "r,rYs,rm")
1134 (match_operand:PSI 2 "general_operand" "rLs,rYsi,rmi")])
1135 (label_ref (match_operand 3 "" ""))
1136 (pc)))
1137 (clobber (reg:BI CARRY))
1138 ]
1139 ""
1140 "@
51ac3042 1141 CMP%Q0\t%2, %1 { J%0\t%l3
f6a83b4a
DD
1142 CMPX.A\t%2, %1 { J%0\t%l3
1143 CMPX.A\t%2, %1 { J%0\t%l3"
1144 )
1145
1146(define_insn "cbranchqi4_real"
1147 [(set (pc) (if_then_else
1148 (match_operator 0 "msp430_cmp_operator"
1149 [(match_operand:QI 1 "nonimmediate_operand" "rYs,rm")
1150 (match_operand:QI 2 "general_operand" "rYsi,rmi")])
1151 (label_ref (match_operand 3 "" ""))
1152 (pc)))
1153 (clobber (reg:BI CARRY))
1154 ]
1155 ""
1156 "@
1157 CMP.B\t%2, %1 { J%0\t%l3
1158 CMP%X0.B\t%2, %1 { J%0\t%l3"
1159 )
1160
1161(define_insn "cbranchhi4_real"
1162 [(set (pc) (if_then_else
1163 (match_operator 0 "msp430_cmp_operator"
1164 [(match_operand:HI 1 "nonimmediate_operand" "rYs,rm")
1165 (match_operand:HI 2 "general_operand" "rYsi,rmi")])
1166 (label_ref (match_operand 3 "" ""))
1167 (pc)))
1168 (clobber (reg:BI CARRY))
1169 ]
1170 ""
d7edde11
NC
1171 "*
1172 /* This is nasty. If we are splitting code between low and high memory
1173 then we do not want the linker to increase the size of sections by
1174 relaxing out of range jump instructions. (Since relaxation occurs
1175 after section placement). So we have to generate pessimal branches
1176 here. But we only want to do this when really necessary.
1177
1178 FIXME: Do we need code in the other cbranch patterns ? */
1179 if (msp430_do_not_relax_short_jumps () && get_attr_length (insn) > 6)
1180 {
1181 return which_alternative == 0 ?
1182 \"CMP.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\" :
1183 \"CMP%X0.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\";
1184 }
1185
1186 return which_alternative == 0 ?
1187 \"CMP.W\t%2, %1 { J%0\t%l3\" :
1188 \"CMP%X0.W\t%2, %1 { J%0\t%l3\";
1189 "
1190 [(set (attr "length")
1191 (if_then_else
1192 (and (ge (minus (match_dup 3) (pc)) (const_int -510))
1193 (le (minus (match_dup 3) (pc)) (const_int 510)))
1194 (const_int 6)
1195 (const_int 10))
1196 )]
f6a83b4a
DD
1197 )
1198
1199(define_insn "cbranchpsi4_reversed"
1200 [(set (pc) (if_then_else
1201 (match_operator 0 "msp430_reversible_cmp_operator"
1202 [(match_operand:PSI 1 "general_operand" "rLs,rYsi,rmi")
1203 (match_operand:PSI 2 "general_operand" "r,rYs,rm")])
1204 (label_ref (match_operand 3 "" ""))
1205 (pc)))
1206 (clobber (reg:BI CARRY))
1207 ]
1208 ""
1209 "@
51ac3042 1210 CMP%Q0\t%1, %2 { J%R0\t%l3
f6a83b4a
DD
1211 CMPX.A\t%1, %2 { J%R0\t%l3
1212 CMPX.A\t%1, %2 { J%R0\t%l3"
1213 )
1214
1215(define_insn "cbranchqi4_reversed"
1216 [(set (pc) (if_then_else
1217 (match_operator 0 "msp430_reversible_cmp_operator"
1218 [(match_operand:QI 1 "general_operand" "rYsi,rmi")
1219 (match_operand:QI 2 "general_operand" "rYs,rm")])
1220 (label_ref (match_operand 3 "" ""))
1221 (pc)))
1222 (clobber (reg:BI CARRY))
1223 ]
1224 ""
1225 "@
1226 CMP.B\t%1, %2 { J%R0\t%l3
1227 CMP%X0.B\t%1, %2 { J%R0\t%l3"
1228 )
1229
1230(define_insn "cbranchhi4_reversed"
1231 [(set (pc) (if_then_else
1232 (match_operator 0 "msp430_reversible_cmp_operator"
1233 [(match_operand:HI 1 "general_operand" "rYsi,rmi")
1234 (match_operand:HI 2 "general_operand" "rYs,rm")])
1235 (label_ref (match_operand 3 "" ""))
1236 (pc)))
1237 (clobber (reg:BI CARRY))
1238 ]
1239 ""
1240 "@
1241 CMP.W\t%1, %2 { J%R0\t%l3
1242 CMP%X0.W\t%1, %2 { J%R0\t%l3"
1243 )
1244
f6a83b4a
DD
1245(define_insn "*bitbranch<mode>4"
1246 [(set (pc) (if_then_else
1247 (ne (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rYs,rm")
1248 (match_operand:QHI 1 "msp_general_operand" "rYsi,rmi"))
1249 (const_int 0))
1250 (label_ref (match_operand 2 "" ""))
1251 (pc)))
1252 (clobber (reg:BI CARRY))
1253 ]
1254 ""
1255 "@
51ac3042
NC
1256 BIT%x0%b0\t%1, %0 { JNE\t%l2
1257 BIT%X0%b0\t%1, %0 { JNE\t%l2"
f6a83b4a
DD
1258 )
1259
1260(define_insn "*bitbranch<mode>4"
1261 [(set (pc) (if_then_else
1262 (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1263 (match_operand:QHI 1 "msp_general_operand" "rmi"))
1264 (const_int 0))
1265 (label_ref (match_operand 2 "" ""))
1266 (pc)))
1267 (clobber (reg:BI CARRY))
1268 ]
1269 ""
c32ab325 1270 "BIT%x0%b0\t%1, %0 { JEQ\t%l2"
f6a83b4a
DD
1271 )
1272
1273(define_insn "*bitbranch<mode>4"
1274 [(set (pc) (if_then_else
1275 (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1276 (match_operand:QHI 1 "msp_general_operand" "rmi"))
1277 (const_int 0))
1278 (pc)
1279 (label_ref (match_operand 2 "" ""))))
1280 (clobber (reg:BI CARRY))
1281 ]
1282 ""
51ac3042 1283 "BIT%X0%b0\t%1, %0 { JNE\t%l2"
f6a83b4a
DD
1284 )
1285
1286(define_insn "*bitbranch<mode>4"
1287 [(set (pc) (if_then_else
1288 (ne (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1289 (match_operand:QHI 1 "msp_general_operand" "rmi"))
1290 (const_int 0))
1291 (pc)
1292 (label_ref (match_operand 2 "" ""))))
1293 (clobber (reg:BI CARRY))
1294 ]
1295 ""
51ac3042 1296 "BIT%X0%b0\t%1, %0 { JEQ\t%l2"
f6a83b4a
DD
1297 )
1298
1299;;------------------------------------------------------------
cad055a4 1300;; zero-extract versions of the above
f6a83b4a
DD
1301
1302(define_insn "*bitbranch<mode>4_z"
1303 [(set (pc) (if_then_else
1304 (ne (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rYs,rm")
1305 (const_int 1)
1306 (match_operand 1 "msp430_bitpos" "i,i"))
1307 (const_int 0))
1308 (label_ref (match_operand 2 "" ""))
1309 (pc)))
1310 (clobber (reg:BI CARRY))
1311 ]
1312 ""
1313 "@
51ac3042
NC
1314 BIT%x0%b0\t%p1, %0 { JNE\t%l2
1315 BIT%X0%b0\t%p1, %0 { JNE\t%l2"
f6a83b4a
DD
1316 )
1317
1318(define_insn "*bitbranch<mode>4_z"
1319 [(set (pc) (if_then_else
1320 (eq (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1321 (const_int 1)
1322 (match_operand 1 "msp430_bitpos" "i"))
1323 (const_int 0))
1324 (label_ref (match_operand 2 "" ""))
1325 (pc)))
1326 (clobber (reg:BI CARRY))
1327 ]
1328 ""
51ac3042 1329 "BIT%x0%X0%b0\t%p1, %0 { JEQ\t%l2"
f6a83b4a
DD
1330 )
1331
1332(define_insn "*bitbranch<mode>4_z"
1333 [(set (pc) (if_then_else
1334 (eq (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1335 (const_int 1)
1336 (match_operand 1 "msp430_bitpos" "i"))
1337 (const_int 0))
1338 (pc)
1339 (label_ref (match_operand 2 "" ""))))
1340 (clobber (reg:BI CARRY))
1341 ]
1342 ""
51ac3042 1343 "BIT%X0%b0\t%p1, %0 { JNE\t%l2"
f6a83b4a
DD
1344 )
1345
1346(define_insn "*bitbranch<mode>4_z"
1347 [(set (pc) (if_then_else
1348 (ne (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1349 (const_int 1)
1350 (match_operand 1 "msp430_bitpos" "i"))
1351 (const_int 0))
1352 (pc)
1353 (label_ref (match_operand 2 "" ""))))
1354 (clobber (reg:BI CARRY))
1355 ]
1356 ""
51ac3042 1357 "BIT%X0%b0\t%p1, %0 { JEQ\t%l2"
f6a83b4a
DD
1358 )
1359
1360;;------------------------------------------------------------
1361;; Misc
1362
1363(define_insn "nop"
1364 [(const_int 0)]
1365 "1"
1366 "NOP"
1367)
a005b5be 1368
cad055a4
NC
1369(define_insn "disable_interrupts"
1370 [(unspec_volatile [(const_int 0)] UNS_DINT)]
1371 ""
a005b5be 1372 "DINT \; NOP"
cad055a4
NC
1373 )
1374
1375(define_insn "enable_interrupts"
1376 [(unspec_volatile [(const_int 0)] UNS_EINT)]
1377 ""
1378 "EINT"
1379 )
1380
1381(define_insn "push_intr_state"
1382 [(unspec_volatile [(const_int 0)] UNS_PUSH_INTR)]
1383 ""
1384 "PUSH\tSR"
1385 )
1386
1387(define_insn "pop_intr_state"
1388 [(unspec_volatile [(const_int 0)] UNS_POP_INTR)]
1389 ""
1390 "POP\tSR"
1391 )
1392
1393;; Clear bits in the copy of the status register that is currently
1394;; saved on the stack at the top of the interrupt handler.
1395(define_insn "bic_SR"
1396 [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIC_SR)]
1397 ""
1398 "BIC.W\t%0, %O0(SP)"
1399 )
1400
1401;; Set bits in the copy of the status register that is currently
1402;; saved on the stack at the top of the interrupt handler.
1403(define_insn "bis_SR"
1404 [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIS_SR)]
1405 ""
1406 "BIS.W\t%0, %O0(SP)"
1407 )
40ada30a
NC
1408
1409;; For some reason GCC is generating (set (reg) (and (neg (reg)) (int)))
1410;; very late on in the compilation and not splitting it into separate
1411;; instructions, so we provide a pattern to support it here.
1412(define_insn "andneghi3"
1413 [(set (match_operand:HI 0 "register_operand" "=r")
1414 (and:HI (neg:HI (match_operand:HI 1 "register_operand" "r"))
1415 (match_operand 2 "immediate_operand" "n")))]
1416 ""
1417 "*
1418 if (REGNO (operands[0]) != REGNO (operands[1]))
9c5f6203 1419 return \"MOV.W\t%1, %0 { INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0\";
40ada30a 1420 else
9c5f6203 1421 return \"INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0\";
40ada30a
NC
1422 "
1423 )
c6f709ec 1424
5f35dde5
DD
1425(define_insn "delay_cycles_start"
1426 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
1427 UNS_DELAY_START)]
1428 ""
1429 "; Begin %J0 cycle delay"
1430 )
1431
1432(define_insn "delay_cycles_end"
1433 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
1434 UNS_DELAY_END)]
1435 ""
1436 "; End %J0 cycle delay"
1437 )
1438
1439(define_insn "delay_cycles_32"
1440 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1441 (match_operand 1 "immediate_operand" "i")
1442 ] UNS_DELAY_32)]
1443 ""
1444 "PUSH r13
1445 PUSH r14
1446 MOV.W %A0, r13
1447 MOV.W %B0, r14
14481: SUB.W #1, r13
1449 SUBC.W #0, r14
1450 JNE 1b
1451 TST.W r13
1452 JNE 1b
1453 POP r14
1454 POP r13"
1455 )
1456
1457(define_insn "delay_cycles_32x"
1458 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1459 (match_operand 1 "immediate_operand" "i")
1460 ] UNS_DELAY_32X)]
1461 ""
47f138d1 1462 "PUSHM.A #2,r14
5f35dde5
DD
1463 MOV.W %A0, r13
1464 MOV.W %B0, r14
14651: SUB.W #1, r13
1466 SUBC.W #0, r14
1467 JNE 1b
1468 TST.W r13
1469 JNE 1b
47f138d1 1470 POPM.A #2,r14"
5f35dde5
DD
1471 )
1472
1473(define_insn "delay_cycles_16"
1474 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1475 (match_operand 1 "immediate_operand" "i")
1476 ] UNS_DELAY_16)]
1477 ""
1478 "PUSH r13
1479 MOV.W %0, r13
14801: SUB.W #1, r13
1481 JNE 1b
1482 POP r13"
1483 )
1484
1485(define_insn "delay_cycles_16x"
1486 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1487 (match_operand 1 "immediate_operand" "i")
1488 ] UNS_DELAY_16X)]
1489 ""
1490 "PUSHM.A #1,r13
1491 MOV.W %0, r13
14921: SUB.W #1, r13
1493 JNE 1b
1494 POPM.A #1,r13"
1495 )
1496
1497(define_insn "delay_cycles_2"
1498 [(unspec_volatile [(const_int 0) ] UNS_DELAY_2)]
1499 ""
1500 "JMP .+2"
1501 )
1502
1503(define_insn "delay_cycles_1"
1504 [(unspec_volatile [(const_int 0) ] UNS_DELAY_1)]
1505 ""
1506 "NOP"
1507 )
1508
c6f709ec
NC
1509(define_insn "mulhisi3"
1510 [(set (match_operand:SI 0 "register_operand" "=r")
1511 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1512 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
b07447ba 1513 "optimize > 2 && msp430_hwmult_type != MSP430_HWMULT_NONE"
c6f709ec 1514 "*
f7961364 1515 if (msp430_use_f5_series_hwmult ())
ba3cf9f1 1516 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 1517 else
ba3cf9f1 1518 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
1519 "
1520)
1521
1522(define_insn "umulhisi3"
1523 [(set (match_operand:SI 0 "register_operand" "=r")
1524 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1525 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
b07447ba 1526 "optimize > 2 && msp430_hwmult_type != MSP430_HWMULT_NONE"
c6f709ec 1527 "*
f7961364 1528 if (msp430_use_f5_series_hwmult ())
ba3cf9f1 1529 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 1530 else
ba3cf9f1 1531 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
1532 "
1533)
1534
1535(define_insn "mulsidi3"
1536 [(set (match_operand:DI 0 "register_operand" "=r")
1537 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
1538 (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
b07447ba 1539 "optimize > 2 && msp430_hwmult_type != MSP430_HWMULT_NONE"
c6f709ec 1540 "*
f7961364 1541 if (msp430_use_f5_series_hwmult ())
ba3cf9f1 1542 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 1543 else
ba3cf9f1 1544 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
1545 "
1546)
1547
1548(define_insn "umulsidi3"
1549 [(set (match_operand:DI 0 "register_operand" "=r")
1550 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
1551 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
b07447ba 1552 "optimize > 2 && msp430_hwmult_type != MSP430_HWMULT_NONE"
c6f709ec 1553 "*
f7961364 1554 if (msp430_use_f5_series_hwmult ())
ba3cf9f1 1555 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 1556 else
ba3cf9f1 1557 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
1558 "
1559)