1 ;; Machine Description for TI MSP43* processors
2 ;; Copyright (C) 2013-2020 Free Software Foundation, Inc.
3 ;; Contributed by Red Hat.
5 ;; This file is part of GCC.
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)
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.
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/>.
29 (define_c_enum "unspec"
31 UNS_PROLOGUE_START_MARKER
32 UNS_PROLOGUE_END_MARKER
33 UNS_EPILOGUE_START_MARKER
61 ;; This is an approximation.
62 (define_attr "length" "" (const_int 4))
64 (include "predicates.md")
65 (include "constraints.md")
67 (define_mode_iterator QHI [QI HI PSI])
69 ;; There are two basic "family" tests we do here:
71 ;; msp430x - true if 430X instructions are available.
72 ;; TARGET_LARGE - true if pointers are 20-bits
74 ;; Note that there are three supported cases, since the base 430
75 ;; doesn't have 20-bit pointers:
77 ;; 1. MSP430 cpu, small model
78 ;; 2. MSP430X cpu, small model.
79 ;; 3. MSP430X cpu, large model.
81 ;;------------------------------------------------------------
84 ;; Push/Pop must be before the generic move patterns
87 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNO)))
88 (match_operand:HI 0 "register_operand" "r"))]
94 [(set (mem:PSI (pre_dec:PSI (reg:PSI SP_REGNO)))
95 (match_operand:PSI 0 "register_operand" "r"))]
101 [(unspec_volatile [(match_operand 0 "register_operand" "r")
102 (match_operand 1 "immediate_operand" "n")] UNS_PUSHM)]
108 [(set (match_operand:HI 0 "register_operand" "=r")
109 (mem:HI (post_inc:HI (reg:HI SP_REGNO))))]
115 [(set (match_operand:PSI 0 "register_operand" "=r")
116 (mem:PSI (post_inc:PSI (reg:PSI SP_REGNO))))]
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
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.
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.
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)]
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).
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.
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.
156 (define_insn "grow_and_swap"
157 [(unspec_volatile [(const_int 0)] UNS_GROW_AND_SWAP)]
161 return \"SUBA\t#2, r1 { MOVX.A\t2(r1), 0(r1)\";
162 return \"SUB\t#2, r1 { MOV.W\t2(r1), 0(r1)\";
166 (define_insn "swap_and_shrink"
167 [(unspec_volatile [(const_int 0)] UNS_SWAP_AND_SHRINK)]
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\";
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")))]
185 (define_insn "movqi_topbyte"
186 [(set (match_operand:QI 0 "msp430_general_dst_operand" "=r")
187 (subreg:QI (match_operand:PSI 1 "msp430_general_operand" "r") 2))]
189 "PUSHM.A\t#1,%1 { POPM.W\t#1,%0 { POPM.W\t#1,%0"
193 [(set (match_operand:QI 0 "msp430_general_dst_operand" "=rYsYx,rm")
194 (match_operand:QI 1 "msp430_general_operand" "riYsYx,rmi"))]
202 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=r,rYsYx,rm")
203 (match_operand:HI 1 "msp430_general_operand" "N,riYsYx,rmi"))]
211 (define_expand "movsi"
212 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand")
213 (match_operand:SI 1 "general_operand"))]
218 (define_insn_and_split "movsi_s"
219 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
220 (subreg:SI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))]
224 [(set (match_operand:HI 2 "msp430_general_dst_nonv_operand")
225 (match_operand:HI 4 "general_operand"))
226 (set (match_operand:HI 3 "msp430_general_dst_nonv_operand")
227 (match_operand:HI 5 "general_operand"))]
228 "msp430_split_movsi (operands);"
231 (define_insn_and_split "movsi_x"
232 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
233 (match_operand:SI 1 "general_operand" "rmi"))]
237 [(set (match_operand:HI 2 "msp430_general_dst_nonv_operand")
238 (match_operand:HI 4 "general_operand"))
239 (set (match_operand:HI 3 "msp430_general_dst_nonv_operand")
240 (match_operand:HI 5 "general_operand"))]
241 "msp430_split_movsi (operands);"
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 "msp430_general_dst_operand" "=r,r,r,Ya,rm")
247 (match_operand:PSI 1 "msp430_general_operand" "N,O,riYa,r,rmi"))]
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)).
261 ; Note: using POPM.A #1 is two bytes smaller than using POPX.A....
263 (define_insn "movsipsi2"
264 [(set (match_operand:PSI 0 "register_operand" "=r")
265 (subreg:PSI (match_operand:SI 1 "register_operand" "r") 0))]
267 "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A #1, %0 ; Move reg-pair %L1:%H1 into pointer %0"
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))]
278 ;;------------------------------------------------------------
281 (define_insn "addpsi3"
282 [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,rm")
283 (plus:PSI (match_operand:PSI 1 "msp430_general_operand" "%0,0")
284 (match_operand:PSI 2 "msp430_general_operand" "rLs,rmi")))]
291 (define_insn "addqi3"
292 [(set (match_operand:QI 0 "msp430_general_dst_operand" "=rYsYx,rm")
293 (plus:QI (match_operand:QI 1 "msp430_general_operand" "%0,0")
294 (match_operand:QI 2 "msp430_general_operand" "riYsYx,rmi")))]
301 (define_insn "addhi3"
302 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYsYx,rm")
303 (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0")
304 (match_operand:HI 2 "msp430_general_operand" "riYsYx,rmi")))]
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.
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")))]
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"
323 (define_insn "addsi3"
324 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=&rYsYx,rm")
325 (plus:SI (match_operand:SI 1 "general_operand" "%0,0")
326 (match_operand:SI 2 "general_operand" "rYsYxi,mi")))]
329 ADD\t%L2, %L0 { ADDC\t%H2, %H0
330 ADDX\t%L2, %L0 { ADDCX\t%H2, %H0"
333 ; Version of addhi that exposes the carry operations, for SImode adds.
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
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
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.
360 ; match_operand 3 is likely to be the same as op2 most of the time - except
361 ; when op2 is a post_inc and we have stripped the post_inc from match_operand 3
363 (define_insn "addhi3_cy"
364 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYsYx,rm")
365 (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0")
366 (match_operand:HI 2 "msp430_nonimmediate_operand" "rYsYxi,rm")))
368 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
369 (zero_extend:SI (match_operand:HI 3 "msp430_nonimmediate_operand" "rYsYxi,rm")))
378 (define_insn "addhi3_cy_i"
379 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=r,rm")
380 (plus:HI (match_operand:HI 1 "general_operand" "%0,0")
381 (match_operand:HI 2 "immediate_operand" "i,i")))
383 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
384 (match_operand 3 "immediate_operand" "i,i"))
393 ; Version of addhi that adds the carry, for SImode adds.
394 (define_insn "addchi4_cy"
395 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYsYx,rm")
396 (plus:HI (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0")
397 (match_operand:HI 2 "msp430_general_operand" "riYsYx,rmi"))
398 (zero_extend:HI (reg:BI CARRY))))
406 ; Split an SImode add into two HImode adds, keeping track of the carry
407 ; so that gcc knows when it can and can't optimize away the two
409 ; We use the ugly predicate "msp430_nonsubregnonpostinc_or_imm_operand" to
410 ; enforce the position of a post_inc into op2 if present
412 [(set (match_operand:SI 0 "msp430_nonsubreg_dst_operand")
413 (plus:SI (match_operand:SI 1 "msp430_nonsubregnonpostinc_or_imm_operand")
414 (match_operand:SI 2 "msp430_nonsubreg_or_imm_operand")))
417 [(parallel [(set (match_operand:HI 3 "msp430_general_dst_nonv_operand" "=&rm")
418 (plus:HI (match_dup 4)
421 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 4))
425 (set (match_operand:HI 6 "msp430_general_dst_nonv_operand" "=&rm")
426 (plus:HI (plus:HI (match_dup 7)
428 (zero_extend:HI (reg:BI CARRY))))
431 if (msp430_split_addsi (operands))
437 ;; Alternatives 2 and 3 are to handle cases generated by reload.
438 (define_insn "subpsi3"
439 [(set (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r, rm, &?r, ?&r")
440 (minus:PSI (match_operand:PSI 1 "general_operand" "0, 0, !r, !i")
441 (match_operand:PSI 2 "general_operand" "rLs, rmi, rmi, r")))]
446 MOVX.A\t%1, %0 { SUBX.A\t%2, %0
447 MOVX.A\t%1, %0 { SUBA\t%2, %0"
450 ;; Alternatives 2 and 3 are to handle cases generated by reload.
451 (define_insn "subqi3"
452 [(set (match_operand:QI 0 "msp430_general_dst_nonv_operand" "=rYsYx, rm, &?r, ?&r")
453 (minus:QI (match_operand:QI 1 "general_operand" "0, 0, !r, !i")
454 (match_operand:QI 2 "general_operand" " riYsYx, rmi, rmi, r")))]
459 MOV%X2.B\t%1, %0 { SUB%X2.B\t%2, %0
460 MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0"
463 ;; Alternatives 2 and 3 are to handle cases generated by reload.
464 (define_insn "subhi3"
465 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=rYsYx, rm, &?r, ?&r")
466 (minus:HI (match_operand:HI 1 "general_operand" "0, 0, !r, !i")
467 (match_operand:HI 2 "general_operand" " riYsYx, rmi, rmi, r")))]
472 MOV%X2.W\t%1, %0 { SUB%X2.W\t%2, %0
473 MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0"
476 (define_insn "subsi3"
477 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=&rYsYx,m")
478 (minus:SI (match_operand:SI 1 "general_operand" "0,0")
479 (match_operand:SI 2 "general_operand" "riYsYx,mi")))]
482 SUB\t%L2, %L0 { SUBC\t%H2, %H0
483 SUBX\t%L2, %L0 { SUBCX\t%H2, %H0"
486 (define_insn "*bic<mode>_cg"
487 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYs,m")
488 (and:QHI (match_operand:QHI 1 "msp430_general_operand" "0,0")
489 (match_operand 2 "msp430_inv_constgen_operator" "n,n")))]
496 (define_insn "bic<mode>3"
497 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYsYx,rm")
498 (and:QHI (not:QHI (match_operand:QHI 1 "msp430_general_operand" "rYsYx,rmn"))
499 (match_operand:QHI 2 "msp430_general_operand" "0,0")))]
506 (define_insn "and<mode>3"
507 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=r,rYsYx,rm")
508 (and:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0,0")
509 (match_operand:QHI 2 "msp430_general_operand" "N,riYsYx,rmi")))]
517 (define_insn "ior<mode>3"
518 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYsYx,rm")
519 (ior:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0")
520 (match_operand:QHI 2 "msp430_general_operand" "riYsYx,rmi")))]
527 (define_insn "xor<mode>3"
528 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYsYx,rm")
529 (xor:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0")
530 (match_operand:QHI 2 "msp430_general_operand" "riYsYx,rmi")))]
537 ;; Macro : XOR #~0, %0
538 (define_insn "one_cmpl<mode>2"
539 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYs,m")
540 (not:QHI (match_operand:QHI 1 "msp430_general_operand" "0,0")))]
547 (define_insn "extendqihi2"
548 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYs,m")
549 (sign_extend:HI (match_operand:QI 1 "msp430_general_operand" "0,0")))]
556 (define_insn "extendqipsi2"
557 [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,m")
558 (sign_extend:PSI (match_operand:QI 1 "msp430_general_operand" "0,0")))]
565 ;; ------------------------
566 ;; ZERO EXTEND INSTRUCTIONS
567 ;; Byte-writes to registers clear bits 19:8
568 ;; * Byte-writes to memory do not affect bits 15:8
569 ;; Word-writes to registers clear bits 19:16
570 ;; PSImode writes to memory clear bits 15:4 of the second memory word
571 ;; We define all possible insns since that results in better code than if
572 ;; they are inferred.
573 ;; ------------------------
575 (define_insn "zero_extendqihi2"
576 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYs,r,r,m")
577 (zero_extend:HI (match_operand:QI 1 "msp430_general_operand" "0,rYs,m,0")))]
586 (define_insn "zero_extendqipsi2"
587 [(set (match_operand:PSI 0 "register_operand" "=r,r")
588 (zero_extend:PSI (match_operand:QI 1 "general_operand" "rYs,m")))]
595 (define_insn "zero_extendqisi2"
596 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=r,r")
597 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,rm")))]
601 MOV%X1.B\t%1,%L0 { CLR\t%H0"
604 (define_insn "zero_extendhipsi2"
605 [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,r,m")
606 (zero_extend:PSI (match_operand:HI 1 "msp430_general_operand" "rYs,m,r")))]
614 (define_insn "zero_extendhisi2"
615 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm,r")
616 (zero_extend:SI (match_operand:HI 1 "general_operand" "0,r")))]
620 MOV.W\t%1,%L0 { MOV.W\t#0,%H0"
623 (define_insn "zero_extendhisipsi2"
624 [(set (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r,r")
625 (subreg:PSI (zero_extend:SI (match_operand:HI 1 "general_operand" "0,r")) 0))]
632 ; Nasty - we are sign-extending a 20-bit PSI value in one register into
633 ; two adjacent 16-bit registers to make an SI value. There is no MSP430X
634 ; instruction that will do this, so we push the 20-bit value onto the stack
635 ; and then pop it off as two 16-bit values.
637 ; FIXME: The MSP430X documentation does not specify if zero-extension or
638 ; sign-extension happens when the 20-bit value is pushed onto the stack.
639 ; It is probably zero-extension, but if not this pattern will not work
640 ; when the PSI value is negative..
642 ; Note: using PUSHM.A #1 is two bytes smaller than using PUSHX.A....
644 ; Note: We use a + constraint on operand 0 as otherwise GCC gets confused
645 ; about extending a single PSI mode register into a pair of SImode registers
646 ; with the same starting register. It thinks that the upper register of
647 ; the pair is unused and so it can clobber it. Try compiling 20050826-2.c
648 ; at -O2 to see this.
650 ; FIXME we can use MOVA for r->m if m is &abs20 or z16(rdst)
651 (define_insn "zero_extendpsisi2"
652 [(set (match_operand:SI 0 "register_operand" "+r,m")
653 (zero_extend:SI (match_operand:PSI 1 "register_operand" "r,r")))]
656 * if (REGNO (operands[1]) == SP_REGNO) \
657 /* If the source register is the stack pointer, the value \
658 stored in the stack slot will be the value *after* the \
659 stack pointer has been decremented. So allow for that \
661 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\"; \
663 return \"PUSHM.A\t#1, %1 { POPX.W\t%L0 { POPX.W\t%H0 ; move pointer in %1 into reg-pair %L0:%H0\";
667 ;; Below are unnamed insn patterns to catch pointer manipulation insns
668 ;; generated by combine.
669 ;; We get large code size bloat when a PSImode pointer is stored in
670 ;; memory, so we try to avoid that where possible and keep point manipulation
671 ;; between registers.
672 ; FIXME many of these should be unnnecessary once combine deals with
673 ; (sign_extend (zero_extend)) or (sign_extend (subreg)) BZ 91865.
675 ;; This is just another way of writing movqipsi/zero_extendqipsi
677 [(set (match_operand:PSI 0 "register_operand" "=r")
678 (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "rm") 0)))]
684 [(set (match_operand:PSI 0 "register_operand" "=r,r")
685 (sign_extend:PSI (zero_extend:HI (match_operand:QI 1 "general_operand" "rYs,m"))))]
693 [(set (match_operand:SI 0 "register_operand" "=r")
694 (ashift:SI (zero_extend:SI (match_operand:QI 1 "general_operand" "rm"))
695 (match_operand:HI 2 "immediate_operand" "M")))]
697 "MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0"
700 ;; We are taking a char and shifting it and putting the result in 2 registers.
701 ;; the high register will always be for 0 shift counts < 8.
703 [(set (match_operand:SI 0 "register_operand" "=r")
704 (ashift:SI (zero_extend:SI (subreg:HI (match_operand:QI 1 "general_operand" "rm") 0))
705 (match_operand:HI 2 "immediate_operand" "M")))]
707 "MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0"
710 ;; Same as above but with a NOP sign_extend round the subreg
712 [(set (match_operand:SI 0 "register_operand" "=r")
713 (ashift:SI (zero_extend:SI (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "rm") 0)))
714 (match_operand:HI 2 "immediate_operand" "M")))]
716 "MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0"
720 [(set (match_operand:SI 0 "register_operand" "=r")
721 (zero_extend:SI (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "rm") 0))))]
723 "MOV%X1.B %1, %L0 { CLR %H0"
727 [(set (match_operand:PSI 0 "register_operand" "=r")
728 (ashift:PSI (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "rm") 0))
729 (match_operand:HI 2 "immediate_operand" "M")))]
731 "MOV%X1.B %1, %0 { RLAM.W %2, %0"
733 ;; END msp430 pointer manipulation combine insn patterns
735 ;; Eliminate extraneous zero-extends mysteriously created by gcc.
737 [(set (match_operand:HI 0 "register_operand")
738 (zero_extend:HI (match_operand:QI 1 "general_operand")))
739 (set (match_operand:HI 2 "register_operand")
740 (zero_extend:HI (match_operand:QI 3 "register_operand")))]
741 "REGNO (operands[0]) == REGNO (operands[2]) && REGNO (operands[2]) == REGNO (operands[3])"
743 (zero_extend:HI (match_dup 1)))]
746 (define_insn "truncpsihi2"
747 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rm")
748 (truncate:HI (match_operand:PSI 1 "register_operand" "r")))]
753 (define_insn "extendhisi2"
754 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=r")
755 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))]
757 { return msp430x_extendhisi (operands); }
760 (define_insn "extendhipsi2"
761 [(set (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r")
762 (subreg:PSI (sign_extend:SI (match_operand:HI 1 "general_operand" "0")) 0))]
764 "RLAM.A #4, %0 { RRAM.A #4, %0"
767 ;; Look for cases where integer/pointer conversions are suboptimal due
768 ;; to missing patterns, despite us not having opcodes for these
769 ;; patterns. Doing these manually allows for alternate optimization
772 (define_insn "extend_and_shift1_hipsi2"
773 [(set (subreg:SI (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r") 0)
774 (ashift:SI (sign_extend:SI (match_operand:HI 1 "general_operand" "0"))
777 "RLAM.A #4, %0 { RRAM.A #3, %0"
780 (define_insn "extend_and_shift2_hipsi2"
781 [(set (subreg:SI (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r") 0)
782 (ashift:SI (sign_extend:SI (match_operand:HI 1 "general_operand" "0"))
785 "RLAM.A #4, %0 { RRAM.A #2, %0"
788 ;; We also need to be able to sign-extend pointer types (eg ptrdiff_t).
789 ;; Since (we assume) pushing a 20-bit value onto the stack zero-extends
790 ;; it, we use a different method here.
792 (define_insn "extendpsisi2"
793 [(set (match_operand:SI 0 "register_operand" "=r")
794 (sign_extend:SI (match_operand:PSI 1 "register_operand" "r")))]
797 /* The intention here is that we copy the bottom 16-bits of
798 %1 into %L0 (zeroing the top four bits). Then we copy the
799 entire 20-bits of %1 into %H0 and then arithmetically shift
800 it right by 16 bits, to get the top four bits of the pointer
801 sign-extended in %H0. */
802 if (REGNO (operands[0]) == REGNO (operands[1]))
803 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\";
805 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\";
809 ; See the movsipsi2 pattern above for another way that GCC performs this
811 (define_insn "truncsipsi2"
812 [(set (match_operand:PSI 0 "register_operand" "=r")
813 (truncate:PSI (match_operand:SI 1 "register_operand" "r")))]
815 "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A\t#1, %L0"
818 ;;------------------------------------------------------------
821 ;; Note: We do not use the RPT ... SHIFT instruction sequence
822 ;; when the repeat count is in a register, because even though RPT
823 ;; accepts counts in registers, it does not work if the count is
824 ;; zero, and the actual count in the register has to be one less
825 ;; than the required number of iterations. We could encode a
826 ;; seqeunce like this:
836 ;; But is longer than calling a helper function, and we are mostly
837 ;; concerned with code size. FIXME: Maybe enable a sequence like
838 ;; this at -O3 and above ?
840 ;; Note - we ignore shift counts of less than one or more than 15.
841 ;; This is permitted by the ISO C99 standard as such shifts result
842 ;; in "undefined" behavior. [6.5.7 (3)]
846 (define_expand "ashlhi3"
847 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand")
848 (ashift:HI (match_operand:HI 1 "general_operand")
849 (match_operand:HI 2 "general_operand")))]
852 if ((GET_CODE (operands[1]) == SUBREG
853 && REG_P (XEXP (operands[1], 0)))
854 || MEM_P (operands[1]))
855 operands[1] = force_reg (HImode, operands[1]);
857 && REG_P (operands[0])
858 && REG_P (operands[1])
859 && CONST_INT_P (operands[2]))
860 emit_insn (gen_430x_shift_left (operands[0], operands[1], operands[2]));
861 else if (CONST_INT_P (operands[2])
862 && INTVAL (operands[2]) == 1)
863 emit_insn (gen_slli_1 (operands[0], operands[1]));
865 /* The const variants of mspabi shifts have larger code size than the
866 generic version, so use the generic version if optimizing for
868 msp430_expand_helper (operands, \"__mspabi_slli\", !optimize_size);
873 (define_insn "slli_1"
874 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=rm")
875 (ashift:HI (match_operand:HI 1 "general_operand" "0")
878 "RLA%X0.W\t%0" ;; Note - this is a macro for ADD
881 (define_insn "430x_shift_left"
882 [(set (match_operand:HI 0 "register_operand" "=r")
883 (ashift:HI (match_operand:HI 1 "register_operand" "0")
884 (match_operand 2 "immediate_operand" "n")))]
887 if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 5)
888 return \"RLAM.W\t%2, %0\";
889 else if (INTVAL (operands[2]) >= 5 && INTVAL (operands[2]) < 16)
890 return \"RPT\t%2 { RLAX.W\t%0\";
891 return \"# nop left shift\";
895 (define_insn "slll_1"
896 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
897 (ashift:SI (match_operand:SI 1 "general_operand" "0")
900 "RLA%X0.W\t%L0 { RLC%X0.W\t%H0"
903 (define_insn "slll_2"
904 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
905 (ashift:SI (match_operand:SI 1 "general_operand" "0")
908 "RLA%X0.W\t%L0 { RLC%X0.W\t%H0 { RLA%X0.W\t%L0 { RLC%X0.W\t%H0"
911 (define_expand "ashlsi3"
912 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand")
913 (ashift:SI (match_operand:SI 1 "general_operand")
914 (match_operand:SI 2 "general_operand")))]
916 "msp430_expand_helper (operands, \"__mspabi_slll\", !optimize_size);
920 (define_expand "ashldi3"
921 [(set (match_operand:DI 0 "msp430_general_dst_nonv_operand")
922 (ashift:DI (match_operand:DI 1 "general_operand")
923 (match_operand:DI 2 "general_operand")))]
926 /* No const_variant for 64-bit shifts. */
927 msp430_expand_helper (operands, \"__mspabi_sllll\", false);
936 (define_expand "ashrhi3"
937 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand")
938 (ashiftrt:HI (match_operand:HI 1 "general_operand")
939 (match_operand:HI 2 "general_operand")))]
942 if ((GET_CODE (operands[1]) == SUBREG
943 && REG_P (XEXP (operands[1], 0)))
944 || MEM_P (operands[1]))
945 operands[1] = force_reg (HImode, operands[1]);
947 && REG_P (operands[0])
948 && REG_P (operands[1])
949 && CONST_INT_P (operands[2]))
950 emit_insn (gen_430x_arithmetic_shift_right (operands[0], operands[1], operands[2]));
951 else if (CONST_INT_P (operands[2])
952 && INTVAL (operands[2]) == 1)
953 emit_insn (gen_srai_1 (operands[0], operands[1]));
955 msp430_expand_helper (operands, \"__mspabi_srai\", !optimize_size);
960 (define_insn "srai_1"
961 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rm")
962 (ashiftrt:HI (match_operand:HI 1 "msp430_general_operand" "0")
968 (define_insn "430x_arithmetic_shift_right"
969 [(set (match_operand:HI 0 "register_operand" "=r")
970 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
971 (match_operand 2 "immediate_operand" "n")))]
974 if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 5)
975 return \"RRAM.W\t%2, %0\";
976 else if (INTVAL (operands[2]) >= 5 && INTVAL (operands[2]) < 16)
977 return \"RPT\t%2 { RRAX.W\t%0\";
978 return \"# nop arith right shift\";
982 (define_insn "srap_1"
983 [(set (match_operand:PSI 0 "register_operand" "=r")
984 (ashiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
990 (define_insn "srap_2"
991 [(set (match_operand:PSI 0 "register_operand" "=r")
992 (ashiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
998 (define_insn "sral_1"
999 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
1000 (ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
1003 "RRA%X0.W\t%H0 { RRC%X0.W\t%L0"
1006 (define_insn "sral_2"
1007 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
1008 (ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
1011 "RRA%X0.W\t%H0 { RRC%X0.W\t%L0 { RRA%X0.W\t%H0 { RRC%X0.W\t%L0"
1014 (define_expand "ashrsi3"
1015 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand")
1016 (ashiftrt:SI (match_operand:SI 1 "general_operand")
1017 (match_operand:SI 2 "general_operand")))]
1019 "msp430_expand_helper (operands, \"__mspabi_sral\", !optimize_size);
1023 (define_expand "ashrdi3"
1024 [(set (match_operand:DI 0 "msp430_general_dst_nonv_operand")
1025 (ashift:DI (match_operand:DI 1 "general_operand")
1026 (match_operand:DI 2 "general_operand")))]
1029 /* No const_variant for 64-bit shifts. */
1030 msp430_expand_helper (operands, \"__mspabi_srall\", false);
1039 (define_expand "lshrhi3"
1040 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand")
1041 (lshiftrt:HI (match_operand:HI 1 "general_operand")
1042 (match_operand:HI 2 "general_operand")))]
1045 if ((GET_CODE (operands[1]) == SUBREG
1046 && REG_P (XEXP (operands[1], 0)))
1047 || MEM_P (operands[1]))
1048 operands[1] = force_reg (HImode, operands[1]);
1050 && REG_P (operands[0])
1051 && REG_P (operands[1])
1052 && CONST_INT_P (operands[2]))
1053 emit_insn (gen_430x_logical_shift_right (operands[0], operands[1], operands[2]));
1054 else if (CONST_INT_P (operands[2])
1055 && INTVAL (operands[2]) == 1)
1056 emit_insn (gen_srli_1 (operands[0], operands[1]));
1058 msp430_expand_helper (operands, \"__mspabi_srli\", !optimize_size);
1063 (define_insn "srli_1"
1064 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=rm")
1065 (lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
1068 "CLRC { RRC%X0.W\t%0"
1071 (define_insn "430x_logical_shift_right"
1072 [(set (match_operand:HI 0 "register_operand" "=r")
1073 (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
1074 (match_operand 2 "immediate_operand" "n")))]
1077 return msp430x_logical_shift_right (operands[2]);
1081 (define_insn "srlp_1"
1082 [(set (match_operand:PSI 0 "register_operand" "=r")
1083 (lshiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
1089 (define_insn "srll_1"
1090 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
1091 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
1094 "CLRC { RRC%X0.W\t%H0 { RRC%X0.W\t%L0"
1097 (define_insn "srll_2x"
1098 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=r")
1099 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
1102 "RRUX.W\t%H0 { RRC.W\t%L0 { RRUX.W\t%H0 { RRC.W\t%L0"
1105 (define_expand "lshrsi3"
1106 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand")
1107 (lshiftrt:SI (match_operand:SI 1 "general_operand")
1108 (match_operand:SI 2 "general_operand")))]
1110 "msp430_expand_helper (operands, \"__mspabi_srll\", !optimize_size);
1114 (define_expand "lshrdi3"
1115 [(set (match_operand:DI 0 "msp430_general_dst_nonv_operand")
1116 (ashift:DI (match_operand:DI 1 "general_operand")
1117 (match_operand:DI 2 "general_operand")))]
1120 /* No const_variant for 64-bit shifts. */
1121 msp430_expand_helper (operands, \"__mspabi_srlll\", false);
1126 ;;------------------------------------------------------------
1127 ;; Function Entry/Exit
1129 (define_expand "prologue"
1132 "msp430_expand_prologue (); DONE;"
1135 (define_expand "epilogue"
1138 "msp430_expand_epilogue (0); DONE;"
1141 (define_insn "epilogue_helper"
1143 (unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_EPILOGUE_HELPER))
1146 "BR%Q0\t#__mspabi_func_epilog_%J0"
1149 (define_insn "prologue_start_marker"
1150 [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_START_MARKER)]
1152 "; start of prologue"
1155 (define_insn "prologue_end_marker"
1156 [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_END_MARKER)]
1161 (define_insn "epilogue_start_marker"
1162 [(unspec_volatile [(const_int 0)] UNS_EPILOGUE_START_MARKER)]
1164 "; start of epilogue"
1167 ;; This makes the linker add a call to exit() after the call to main()
1169 (define_insn "msp430_refsym_need_exit"
1170 [(unspec_volatile [(const_int 0)] UNS_REFSYM_NEED_EXIT)]
1172 ".refsym\t__crt0_call_exit"
1175 ;;------------------------------------------------------------
1178 (define_expand "call"
1179 [(call:HI (match_operand 0 "")
1180 (match_operand 1 ""))]
1185 (define_insn "call_internal"
1186 [(call (mem:HI (match_operand 0 "general_operand" "rYci"))
1187 (match_operand 1 ""))]
1192 (define_expand "call_value"
1193 [(set (match_operand 0 "register_operand")
1194 (call:HI (match_operand 1 "general_operand")
1195 (match_operand 2 "")))]
1200 (define_insn "call_value_internal"
1201 [(set (match_operand 0 "register_operand" "=r")
1202 (call (mem:HI (match_operand 1 "general_operand" "rYci"))
1203 (match_operand 2 "")))]
1208 (define_insn "msp430_return"
1211 { return msp430_is_interrupt_func () ? "RETI" : (TARGET_LARGE ? "RETA" : "RET"); }
1214 ;; This pattern is NOT, as expected, a return pattern. It's called
1215 ;; before reload and must only store its operands, and emit a
1216 ;; placeholder where the epilog needs to be. AFTER reload, the
1217 ;; placeholder should get expanded into a regular-type epilogue that
1218 ;; also does the EH return.
1219 (define_expand "eh_return"
1220 [(match_operand:HI 0 "")]
1222 "msp430_expand_eh_return (operands[0]);
1223 emit_jump_insn (gen_msp430_eh_epilogue ());
1228 ;; This is the actual EH epilogue. We emit it in the pattern above,
1229 ;; before reload, and convert it to a real epilogue after reload.
1230 (define_insn_and_split "msp430_eh_epilogue"
1236 "msp430_expand_epilogue (1); DONE;"
1241 (label_ref (match_operand 0 "" "")))]
1246 ;; FIXME: GCC currently (8/feb/2013) cannot handle symbol_refs
1247 ;; in indirect jumps (cf gcc.c-torture/compile/991213-3.c).
1248 (define_insn "indirect_jump"
1250 (match_operand 0 "nonimmediate_operand" "rYl"))]
1255 ;;------------------------------------------------------------
1256 ;; Various Conditionals
1258 (define_expand "cbranch<mode>4"
1259 [(parallel [(set (pc) (if_then_else
1260 (match_operator 0 ""
1261 [(match_operand:QHI 1 "msp430_general_dst_nonv_operand")
1262 (match_operand:QHI 2 "general_operand")])
1263 (label_ref (match_operand 3 "" ""))
1265 (clobber (reg:BI CARRY))]
1268 "msp430_fixup_compare_operands (<MODE>mode, operands);"
1271 (define_insn "cbranchpsi4_real"
1272 [(set (pc) (if_then_else
1273 (match_operator 0 "msp430_cmp_operator"
1274 [(match_operand:PSI 1 "msp430_general_dst_nonv_operand" "r,rYs,rm")
1275 (match_operand:PSI 2 "general_operand" "rLs,rYsi,rmi")])
1276 (label_ref (match_operand 3 "" ""))
1278 (clobber (reg:BI CARRY))
1282 CMP%Q0\t%2, %1 { J%0\t%l3
1283 CMPX.A\t%2, %1 { J%0\t%l3
1284 CMPX.A\t%2, %1 { J%0\t%l3"
1287 (define_insn "cbranchqi4_real"
1288 [(set (pc) (if_then_else
1289 (match_operator 0 "msp430_cmp_operator"
1290 [(match_operand:QI 1 "msp430_general_dst_nonv_operand" "rYsYx,rm")
1291 (match_operand:QI 2 "general_operand" "rYsYxi,rmi")])
1292 (label_ref (match_operand 3 "" ""))
1294 (clobber (reg:BI CARRY))
1298 CMP.B\t%2, %1 { J%0\t%l3
1299 CMPX.B\t%2, %1 { J%0\t%l3"
1302 (define_insn "cbranchhi4_real"
1303 [(set (pc) (if_then_else
1304 (match_operator 0 "msp430_cmp_operator"
1305 [(match_operand:HI 1 "msp430_general_dst_nonv_operand" "rYsYx,rm")
1306 (match_operand:HI 2 "general_operand" "rYsYxi,rmi")])
1307 (label_ref (match_operand 3 "" ""))
1309 (clobber (reg:BI CARRY))
1313 /* This is nasty. If we are splitting code between low and high memory
1314 then we do not want the linker to increase the size of sections by
1315 relaxing out of range jump instructions. (Since relaxation occurs
1316 after section placement). So we have to generate pessimal branches
1317 here. But we only want to do this when really necessary.
1319 FIXME: Do we need code in the other cbranch patterns ? */
1320 if (msp430_do_not_relax_short_jumps () && get_attr_length (insn) > 6)
1322 return which_alternative == 0 ?
1323 \"CMP.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\" :
1324 \"CMPX.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\";
1327 return which_alternative == 0 ?
1328 \"CMP.W\t%2, %1 { J%0\t%l3\" :
1329 \"CMPX.W\t%2, %1 { J%0\t%l3\";
1331 [(set (attr "length")
1333 (and (ge (minus (match_dup 3) (pc)) (const_int -510))
1334 (le (minus (match_dup 3) (pc)) (const_int 510)))
1340 (define_insn "cbranchpsi4_reversed"
1341 [(set (pc) (if_then_else
1342 (match_operator 0 "msp430_reversible_cmp_operator"
1343 [(match_operand:PSI 1 "general_operand" "rLs,rYsi,rmi")
1344 (match_operand:PSI 2 "msp430_general_dst_nonv_operand" "r,rYs,rm")])
1345 (label_ref (match_operand 3 "" ""))
1347 (clobber (reg:BI CARRY))
1351 CMP%Q0\t%1, %2 { J%R0\t%l3
1352 CMPX.A\t%1, %2 { J%R0\t%l3
1353 CMPX.A\t%1, %2 { J%R0\t%l3"
1356 (define_insn "cbranchqi4_reversed"
1357 [(set (pc) (if_then_else
1358 (match_operator 0 "msp430_reversible_cmp_operator"
1359 [(match_operand:QI 1 "general_operand" "rYsYxi,rmi")
1360 (match_operand:QI 2 "msp430_general_dst_nonv_operand" "rYsYx,rm")])
1361 (label_ref (match_operand 3 "" ""))
1363 (clobber (reg:BI CARRY))
1367 CMP.B\t%1, %2 { J%R0\t%l3
1368 CMPX.B\t%1, %2 { J%R0\t%l3"
1371 (define_insn "cbranchhi4_reversed"
1372 [(set (pc) (if_then_else
1373 (match_operator 0 "msp430_reversible_cmp_operator"
1374 [(match_operand:HI 1 "general_operand" "rYsYxi,rmi")
1375 (match_operand:HI 2 "msp430_general_dst_nonv_operand" "rYsYx,rm")])
1376 (label_ref (match_operand 3 "" ""))
1378 (clobber (reg:BI CARRY))
1382 CMP.W\t%1, %2 { J%R0\t%l3
1383 CMPX.W\t%1, %2 { J%R0\t%l3"
1386 (define_insn "*bitbranch<mode>4"
1387 [(set (pc) (if_then_else
1388 (ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
1389 (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
1391 (label_ref (match_operand 2 "" ""))
1393 (clobber (reg:BI CARRY))
1397 BIT%x0%b0\t%1, %0 { JNE\t%l2
1398 BITX%b0\t%1, %0 { JNE\t%l2"
1401 (define_insn "*bitbranch<mode>4"
1402 [(set (pc) (if_then_else
1403 (eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
1404 (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
1406 (label_ref (match_operand 2 "" ""))
1408 (clobber (reg:BI CARRY))
1412 BIT%x0%b0\t%1, %0 { JEQ\t%l2
1413 BITX%b0\t%1, %0 { JEQ\t%l2"
1416 (define_insn "*bitbranch<mode>4"
1417 [(set (pc) (if_then_else
1418 (eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
1419 (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
1422 (label_ref (match_operand 2 "" ""))))
1423 (clobber (reg:BI CARRY))
1427 BIT%x0%b0\t%1, %0 { JNE\t%l2
1428 BITX%b0\t%1, %0 { JNE\t%l2"
1431 (define_insn "*bitbranch<mode>4"
1432 [(set (pc) (if_then_else
1433 (ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
1434 (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
1437 (label_ref (match_operand 2 "" ""))))
1438 (clobber (reg:BI CARRY))
1442 BIT%x0%b0\t%1, %0 { JEQ\t%l2
1443 BITX%b0\t%1, %0 { JEQ\t%l2"
1446 ;;------------------------------------------------------------
1447 ;; zero-extract versions of the above
1449 (define_insn "*bitbranch<mode>4_z"
1450 [(set (pc) (if_then_else
1451 (ne (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rYs,rm")
1453 (match_operand 1 "msp430_bitpos" "i,i"))
1455 (label_ref (match_operand 2 "" ""))
1457 (clobber (reg:BI CARRY))
1461 BIT%x0%b0\t%p1, %0 { JNE\t%l2
1462 BIT%X0%b0\t%p1, %0 { JNE\t%l2"
1465 (define_insn "*bitbranch<mode>4_z"
1466 [(set (pc) (if_then_else
1467 (eq (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm")
1469 (match_operand 1 "msp430_bitpos" "i"))
1471 (label_ref (match_operand 2 "" ""))
1473 (clobber (reg:BI CARRY))
1476 "BIT%X0%b0\t%p1, %0 { JEQ\t%l2"
1479 (define_insn "*bitbranch<mode>4_z"
1480 [(set (pc) (if_then_else
1481 (eq (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm")
1483 (match_operand 1 "msp430_bitpos" "i"))
1486 (label_ref (match_operand 2 "" ""))))
1487 (clobber (reg:BI CARRY))
1490 "BIT%X0%b0\t%p1, %0 { JNE\t%l2"
1493 (define_insn "*bitbranch<mode>4_z"
1494 [(set (pc) (if_then_else
1495 (ne (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm")
1497 (match_operand 1 "msp430_bitpos" "i"))
1500 (label_ref (match_operand 2 "" ""))))
1501 (clobber (reg:BI CARRY))
1504 "BIT%X0%b0\t%p1, %0 { JEQ\t%l2"
1507 ;;------------------------------------------------------------
1516 (define_insn "disable_interrupts"
1517 [(unspec_volatile [(const_int 0)] UNS_DINT)]
1522 (define_insn "enable_interrupts"
1523 [(unspec_volatile [(const_int 0)] UNS_EINT)]
1528 (define_insn "push_intr_state"
1529 [(unspec_volatile [(const_int 0)] UNS_PUSH_INTR)]
1534 (define_insn "pop_intr_state"
1535 [(unspec_volatile [(const_int 0)] UNS_POP_INTR)]
1540 ;; Clear bits in the copy of the status register that is currently
1541 ;; saved on the stack at the top of the interrupt handler.
1542 (define_insn "bic_SR"
1543 [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIC_SR)]
1545 "BIC.W\t%0, %O0(SP)"
1548 ;; Set bits in the copy of the status register that is currently
1549 ;; saved on the stack at the top of the interrupt handler.
1550 (define_insn "bis_SR"
1551 [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIS_SR)]
1553 "BIS.W\t%0, %O0(SP)"
1556 ;; For some reason GCC is generating (set (reg) (and (neg (reg)) (int)))
1557 ;; very late on in the compilation and not splitting it into separate
1558 ;; instructions, so we provide a pattern to support it here.
1559 (define_insn "andneghi3"
1560 [(set (match_operand:HI 0 "register_operand" "=r")
1561 (and:HI (neg:HI (match_operand:HI 1 "register_operand" "r"))
1562 (match_operand 2 "immediate_operand" "n")))]
1565 if (REGNO (operands[0]) != REGNO (operands[1]))
1566 return \"MOV.W\t%1, %0 { INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0\";
1568 return \"INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0\";
1572 (define_insn "delay_cycles_start"
1573 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
1576 "; Begin %J0 cycle delay"
1579 (define_insn "delay_cycles_end"
1580 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
1583 "; End %J0 cycle delay"
1586 (define_insn "delay_cycles_32"
1587 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1588 (match_operand 1 "immediate_operand" "i")
1604 (define_insn "delay_cycles_32x"
1605 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1606 (match_operand 1 "immediate_operand" "i")
1620 (define_insn "delay_cycles_16"
1621 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1622 (match_operand 1 "immediate_operand" "i")
1632 (define_insn "delay_cycles_16x"
1633 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1634 (match_operand 1 "immediate_operand" "i")
1644 (define_insn "delay_cycles_2"
1645 [(unspec_volatile [(const_int 0) ] UNS_DELAY_2)]
1650 (define_insn "delay_cycles_1"
1651 [(unspec_volatile [(const_int 0) ] UNS_DELAY_1)]
1656 ; libgcc helper functions for widening multiplication aren't currently
1657 ; generated by gcc, so we can't catch them later and map them to the mspabi
1659 ; We catch the patterns here and either generate a call to the helper function,
1660 ; or emit the hardware multiply instruction sequence inline.
1662 ; If we don't have hardware multiply support, it will generally be slower and
1663 ; result in larger code to call the mspabi library function to perform the
1664 ; widening multiplication than just leaving GCC to widen the arguments itself.
1666 ; We don't use library functions for SImode->DImode widening since its always
1667 ; larger and slower than letting GCC widen the arguments inline.
1668 (define_expand "mulhisi3"
1669 [(set (match_operand:SI 0 "register_operand" "=r")
1670 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1671 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
1672 "msp430_has_hwmult ()"
1674 /* Leave the other case for the inline insn. */
1675 if (!(optimize > 2 && msp430_has_hwmult ()))
1677 msp430_expand_helper (operands, "__mspabi_mpysl", false);
1683 (define_expand "umulhisi3"
1684 [(set (match_operand:SI 0 "register_operand" "=r")
1685 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1686 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
1687 "msp430_has_hwmult ()"
1689 /* Leave the other case for the inline insn. */
1690 if (!(optimize > 2 && msp430_has_hwmult ()))
1692 msp430_expand_helper (operands, "__mspabi_mpyul", false);
1698 (define_insn "*mulhisi3_inline"
1699 [(set (match_operand:SI 0 "register_operand" "=r")
1700 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1701 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
1702 "optimize > 2 && msp430_has_hwmult ()"
1704 if (msp430_use_f5_series_hwmult ())
1705 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\";
1707 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\";
1711 (define_insn "*umulhisi3_inline"
1712 [(set (match_operand:SI 0 "register_operand" "=r")
1713 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1714 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
1715 "optimize > 2 && msp430_has_hwmult ()"
1717 if (msp430_use_f5_series_hwmult ())
1718 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\";
1720 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\";
1724 (define_insn "mulsidi3"
1725 [(set (match_operand:DI 0 "register_operand" "=r")
1726 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
1727 (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
1728 "optimize > 2 && msp430_has_hwmult ()"
1730 if (msp430_use_f5_series_hwmult ())
1731 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\";
1733 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\";
1737 (define_insn "umulsidi3"
1738 [(set (match_operand:DI 0 "register_operand" "=r")
1739 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
1740 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
1741 "optimize > 2 && msp430_has_hwmult ()"
1743 if (msp430_use_f5_series_hwmult ())
1744 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\";
1746 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\";