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