Turn SLOW_UNALIGNED_ACCESS into a target hook
[official-gcc.git] / gcc / config / msp430 / msp430.md
blob571f745f7bc9fd932306f8314be0b723c9a33396
1 ;;  Machine Description for TI MSP43* processors
2 ;;  Copyright (C) 2013-2017 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)
10 ;; any later version.
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/>.
22 (define_constants
23   [
24    (PC_REGNO 0)
25    (SP_REGNO 1)
26    (CARRY 2)
27   ])
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
36    UNS_PUSHM
37    UNS_POPM
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
49    UNS_REFSYM_NEED_EXIT
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   ])
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 ;;------------------------------------------------------------
82 ;; Moves
84 ;; Push/Pop must be before the generic move patterns
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   )
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   )
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   )
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   )
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   )
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.
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   )
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)]
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   "
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   ")
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"
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"
192 (define_insn "movqi"
193   [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=rYs,rm")
194         (match_operand:QI 1 "msp_general_operand" "riYs,rmi"))]
195   ""
196   "@
197   MOV.B\t%1, %0
198   MOV%X0.B\t%1, %0"
201 (define_insn "movhi"
202   [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=r,rYs,rm")
203         (match_operand:HI 1 "msp_general_operand" "N,riYs,rmi"))]
204   ""
205   "@
206   MOV.B\t%1, %0
207   MOV.W\t%1, %0
208   MOV%X0.W\t%1, %0"
211 (define_expand "movsi"
212   [(set (match_operand:SI 0 "nonimmediate_operand")
213         (match_operand:SI 1 "general_operand"))]
214   ""
215   ""
216   )
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   )
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);"
244 ;; 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")
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))]
266   "msp430x"
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))]
274   "msp430x"
275   "MOVA\t%1, %0"
278 ;;------------------------------------------------------------
279 ;; Math
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"
291 (define_insn "addqi3"
292   [(set (match_operand:QI          0 "msp_nonimmediate_operand" "=rYs,rm")
293         (plus:QI (match_operand:QI 1 "msp_nonimmediate_operand" "%0,0")
294                  (match_operand:QI 2 "msp_general_operand"      "riYs,rmi")))]
295   ""
296   "@
297    ADD.B\t%2, %0
298    ADD%X0.B\t%2, %0"
301 (define_insn "addhi3"
302   [(set (match_operand:HI           0 "msp_nonimmediate_operand" "=rYs,rm")
303         (plus:HI (match_operand:HI  1 "msp_nonimmediate_operand" "%0,0")
304                   (match_operand:HI 2 "msp_general_operand"      "riYs,rmi")))]
305   ""
306   "@
307    ADD.W\t%2, %0
308    ADD%X0.W\t%2, %0"
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")))]
319   ""
320   "ADD.W\t%L2, %L0 { ADDC.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 "nonimmediate_operand" "=&r,rm")
325         (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
326                  (match_operand:SI 2 "general_operand" "r,mi")))]
327   ""
328   "@
329    ADD\t%L2, %L0 { ADDC\t%H2, %H0
330    ADD%X0\t%L2, %L0 { ADDC%X0\t%H2, %H0"
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
344 ; and second adds.
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.
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 (define_insn "addhi3_cy"
361   [(set (match_operand:HI          0 "msp_nonimmediate_operand" "=r,rm")
362         (plus:HI (match_operand:HI 1 "msp_nonimmediate_operand" "%0,0")
363                  (match_operand:HI 2 "msp_nonimmediate_operand" "r,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    ADD%X0\t%2, %1 ; cy"
373   )
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   )
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" "=r,rm")
393         (plus:HI (plus:HI (match_operand:HI 1 "msp_nonimmediate_operand" "%0,0")
394                           (match_operand:HI 2 "msp_general_operand"      "ri,rmi"))
395                  (zero_extend:HI (reg:BI CARRY))))
396    ]
397   ""
398   "@
399    ADDC\t%2, %1
400    ADDC%X0\t%2, %1"
401   )
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    operands[3] = msp430_subreg (HImode, operands[0], SImode, 0);
427    operands[4] = msp430_subreg (HImode, operands[1], SImode, 0);
428    operands[5] = msp430_subreg (HImode, operands[2], SImode, 0);
429    operands[6] = msp430_subreg (HImode, operands[0], SImode, 2);
430    operands[7] = msp430_subreg (HImode, operands[1], SImode, 2);
431    operands[8] = msp430_subreg (HImode, operands[2], SImode, 2);
433    /* BZ 64160: Do not use this splitter when the dest partially overlaps the source.  */
434    if (reg_overlap_mentioned_p (operands[3], operands[7])
435        || reg_overlap_mentioned_p (operands[3], operands[8]))
436       FAIL;
438    if (GET_CODE (operands[5]) == CONST_INT)
439      operands[9] = GEN_INT (INTVAL (operands[5]) & 0xffff);
440    else
441      operands[9] = gen_rtx_ZERO_EXTEND (SImode, operands[5]);
442    "
443   )
446 ;; Alternatives 2 and 3 are to handle cases generated by reload.
447 (define_insn "subpsi3"
448   [(set (match_operand:PSI            0 "nonimmediate_operand" "=r,   rm, &?r, ?&r")
449         (minus:PSI (match_operand:PSI 1 "general_operand"       "0,   0,   !r,  !i")
450                    (match_operand:PSI 2 "general_operand"       "rLs, rmi, rmi,  r")))]
451   ""
452   "@
453   SUBA\t%2, %0
454   SUBX.A\t%2, %0
455   MOVX.A\t%1, %0 { SUBX.A\t%2, %0
456   MOVX.A\t%1, %0 { SUBA\t%2, %0"
459 ;; Alternatives 2 and 3 are to handle cases generated by reload.
460 (define_insn "subqi3"
461   [(set (match_operand:QI           0 "nonimmediate_operand" "=rYs,  rm,  &?r, ?&r")
462         (minus:QI (match_operand:QI 1 "general_operand"       "0,    0,    !r,  !i")
463                   (match_operand:QI 2 "general_operand"      " riYs, rmi, rmi,   r")))]
464   ""
465   "@
466   SUB.B\t%2, %0
467   SUB%X0.B\t%2, %0
468   MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0
469   MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0"
472 ;; Alternatives 2 and 3 are to handle cases generated by reload.
473 (define_insn "subhi3"
474   [(set (match_operand:HI           0 "nonimmediate_operand" "=rYs,  rm,  &?r, ?&r")
475         (minus:HI (match_operand:HI 1 "general_operand"       "0,    0,    !r,  !i")
476                   (match_operand:HI 2 "general_operand"      " riYs, rmi, rmi,   r")))]
477   ""
478   "@
479   SUB.W\t%2, %0
480   SUB%X0.W\t%2, %0
481   MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0
482   MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0"
485 (define_insn "subsi3"
486   [(set (match_operand:SI           0 "nonimmediate_operand" "=&rm")
487         (minus:SI (match_operand:SI 1 "nonimmediate_operand"   "0")
488                   (match_operand:SI 2 "general_operand"        "rmi")))]
489   ""
490   "SUB%X0\t%L2, %L0 { SUBC%X0\t%H2, %H0"
493 (define_insn "*bic<mode>_cg"
494   [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,m")
495         (and:QHI (match_operand:QHI 1 "msp_general_operand" "0,0")
496                  (match_operand 2 "msp430_inv_constgen_operator" "n,n")))]
497   ""
498   "@
499    BIC%x0%b0\t#%I2, %0
500    BIC%X0%b0\t#%I2, %0"
503 (define_insn "bic<mode>3"
504   [(set (match_operand:QHI                   0 "msp_nonimmediate_operand" "=rYs,rm")
505         (and:QHI (not:QHI (match_operand:QHI 1 "msp_general_operand"       "rYs,rmn"))
506                  (match_operand:QHI          2 "msp_nonimmediate_operand"  "0,0")))]
507   ""
508   "@
509    BIC%x0%b0\t%1, %0
510    BIC%X0%b0\t%1, %0"
513 (define_insn "and<mode>3"
514   [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=r,rYs,rm")
515         (and:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "%0,0,0")
516                  (match_operand:QHI 2 "msp_general_operand" "N,riYs,rmi")))]
517   ""
518   "@
519    AND%x0.B\t%2, %0
520    AND%x0%b0\t%2, %0
521    AND%X0%b0\t%2, %0"
524 (define_insn "ior<mode>3"
525   [(set (match_operand:QHI          0 "msp_nonimmediate_operand" "=rYs,rm")
526         (ior:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "%0,0")
527                  (match_operand:QHI 2 "msp_general_operand" "riYs,rmi")))]
528   ""
529   "@
530    BIS%x0%b0\t%2, %0
531    BIS%X0%b0\t%2, %0"
534 (define_insn "xor<mode>3"
535   [(set (match_operand:QHI          0 "msp_nonimmediate_operand" "=rYs,rm")
536         (xor:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "%0,0")
537                  (match_operand:QHI 2 "msp_general_operand" "riYs,rmi")))]
538   ""
539   "@
540    XOR%x0%b0\t%2, %0
541    XOR%X0%b0\t%2, %0"
544 ;; Macro : XOR #~0, %0
545 (define_insn "one_cmpl<mode>2"
546   [(set (match_operand:QHI          0 "msp_nonimmediate_operand" "=rYs,m")
547         (not:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "0,0")))]
548   ""
549   "@
550    INV%x0%b0\t%0
551    INV%X0%b0\t%0"
554 (define_insn "extendqihi2"
555   [(set (match_operand:HI                 0 "msp_nonimmediate_operand" "=rYs,m")
556         (sign_extend:HI (match_operand:QI 1 "msp_nonimmediate_operand" "0,0")))]
557   ""
558   "@
559    SXT%X0\t%0
560    SXT%X0\t%0"
563 (define_insn "zero_extendqihi2"
564   [(set (match_operand:HI                 0 "msp_nonimmediate_operand" "=rYs,r,r,m")
565         (zero_extend:HI (match_operand:QI 1 "msp_nonimmediate_operand" "0,rYs,m,0")))]
566   ""
567   "@
568    AND\t#0xff, %0
569    MOV.B\t%1, %0
570    MOV%X0.B\t%1, %0
571    AND%X0\t#0xff, %0"
574 ;; Eliminate extraneous zero-extends mysteriously created by gcc.
575 (define_peephole2
576   [(set (match_operand:HI 0 "register_operand")
577         (zero_extend:HI (match_operand:QI 1 "general_operand")))
578    (set (match_operand:HI 2 "register_operand")
579         (zero_extend:HI (match_operand:QI 3 "register_operand")))]
580   "REGNO (operands[0]) == REGNO (operands[2]) && REGNO (operands[2]) == REGNO (operands[3])"
581   [(set (match_dup 0)
582         (zero_extend:HI (match_dup 1)))]
585 (define_insn "zero_extendhipsi2"
586   [(set (match_operand:PSI                 0 "msp_nonimmediate_operand" "=r,m")
587         (zero_extend:PSI (match_operand:HI 1 "msp_nonimmediate_operand" "rm,r")))]
588   ""
589   "@
590   MOVX\t%1, %0
591   MOVX.A\t%1, %0"
594 (define_insn "truncpsihi2"
595   [(set (match_operand:HI               0 "msp_nonimmediate_operand" "=rm")
596         (truncate:HI (match_operand:PSI 1 "register_operand"      "r")))]
597   ""
598   "MOVX\t%1, %0"
601 (define_insn "extendhisi2"
602   [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
603         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))]
604   ""
605   { return msp430x_extendhisi (operands); }
608 (define_insn "extendhipsi2"
609   [(set (match_operand:PSI 0 "nonimmediate_operand" "=r")
610         (subreg:PSI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) 0))]
611   "msp430x"
612   "RLAM.A #4, %0 { RRAM.A #4, %0"
615 ;; Look for cases where integer/pointer conversions are suboptimal due
616 ;; to missing patterns, despite us not having opcodes for these
617 ;; patterns.  Doing these manually allows for alternate optimization
618 ;; paths.
620 (define_insn "zero_extendqisi2"
621   [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
622         (zero_extend:SI (subreg:HI (match_operand:QI 1 "nonimmediate_operand" "rm") 0)))]
623   "msp430x"
624   "MOV.B\t%1,%L0 { CLR\t%H0"
627 (define_insn "zero_extendhisi2"
628   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
629         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r")))]
630   "msp430x"
631   "@
632   MOV.W\t#0,%H0
633   MOV.W\t%1,%L0 { MOV.W\t#0,%H0"
636 (define_insn "zero_extendhisipsi2"
637   [(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r")
638         (subreg:PSI (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r")) 0))]
639   "msp430x"
640   "@
641    AND.W\t#-1,%0
642    MOV.W\t%1,%0"
645 (define_insn "extend_and_shift1_hipsi2"
646   [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0)
647         (ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0"))
648                    (const_int 1)))]
649   "msp430x"
650   "RLAM.A #4, %0 { RRAM.A #3, %0"
653 (define_insn "extend_and_shift2_hipsi2"
654   [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0)
655         (ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0"))
656                    (const_int 2)))]
657   "msp430x"
658   "RLAM.A #4, %0 { RRAM.A #2, %0"
661 ; Nasty - we are sign-extending a 20-bit PSI value in one register into
662 ; two adjacent 16-bit registers to make an SI value.  There is no MSP430X
663 ; instruction that will do this, so we push the 20-bit value onto the stack
664 ; and then pop it off as two 16-bit values.
666 ; FIXME: The MSP430X documentation does not specify if zero-extension or
667 ; sign-extension happens when the 20-bit value is pushed onto the stack.
668 ; It is probably zero-extension, but if not this pattern will not work
669 ; when the PSI value is negative..
671 ; Note: using PUSHM.A #1 is two bytes smaller than using PUSHX.A....
673 ; Note: We use a + constraint on operand 0 as otherwise GCC gets confused
674 ; about extending a single PSI mode register into a pair of SImode registers
675 ; with the same starting register.  It thinks that the upper register of
676 ; the pair is unused and so it can clobber it.  Try compiling 20050826-2.c
677 ; at -O2 to see this.
679 (define_insn "zero_extendpsisi2"
680   [(set (match_operand:SI                  0 "register_operand" "+r")
681         (zero_extend:SI (match_operand:PSI 1 "register_operand" "r")))]
682   ""
683   "*
684     if (REGNO (operands[1]) == SP_REGNO)
685       /* If the source register is the stack pointer, the value
686          stored in the stack slot will be the value *after* the
687          stack pointer has been decremented.  So allow for that
688          here.  */
689       return \"PUSHM.A\t#1, %1 { ADDX.W\t#4, @r1 { POPX.W\t%L0 { POPX.W\t%H0 ; get stack pointer into %L0:%H0\";
690     else
691       return \"PUSHM.A\t#1, %1 { POPX.W\t%L0 { POPX.W\t%H0 ; move pointer in %1 into reg-pair %L0:%H0\";
692   "
695 ;; We also need to be able to sign-extend pointer types (eg ptrdiff_t).
696 ;; Since (we assume) pushing a 20-bit value onto the stack zero-extends
697 ;; it, we use a different method here.
699 (define_insn "extendpsisi2"
700   [(set (match_operand:SI                  0 "register_operand" "=r")
701         (sign_extend:SI (match_operand:PSI 1 "register_operand" "r")))]
702   "msp430x"
703   "*
704     /* The intention here is that we copy the bottom 16-bits of
705        %1 into %L0 (zeroing the top four bits).  Then we copy the
706        entire 20-bits of %1 into %H0 and then arithmetically shift
707        it right by 16 bits, to get the top four bits of the pointer
708        sign-extended in %H0.  */
709     if (REGNO (operands[0]) == REGNO (operands[1]))
710       return \"MOVX.A\t%1, %H0 { MOV.W\t%1, %L0 { RPT\t#16 { RRAX.A\t%H0 ; sign extend pointer in %1 into %L0:%H0\";
711     else
712       return \"MOV.W\t%1, %L0 { MOVX.A\t%1, %H0 { RPT\t#16 { RRAX.A\t%H0 ; sign extend pointer in %1 into %L0:%H0\";
713   "
716 ; See the movsipsi2 pattern above for another way that GCC performs this
717 ; conversion.
718 (define_insn "truncsipsi2"
719   [(set (match_operand:PSI              0 "register_operand" "=r")
720         (truncate:PSI (match_operand:SI 1 "register_operand" "r")))]
721   ""
722   "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A\t#1, %L0"
725 ;;------------------------------------------------------------
726 ;; Shift Functions
728 ;; Note:  We do not use the RPT ... SHIFT instruction sequence
729 ;; when the repeat count is in a register, because even though RPT
730 ;; accepts counts in registers, it does not work if the count is
731 ;; zero, and the actual count in the register has to be one less
732 ;; than the required number of iterations.  We could encode a
733 ;; seqeunce like this:
735 ;;   bit #0xf, Rn
736 ;;   bz  1f
737 ;;   dec Rn
738 ;;   rpt Rn
739 ;;   <shift> Rm
740 ;;   inc Rn
741 ;; 1:
743 ;; But is longer than calling a helper function, and we are mostly
744 ;; concerned with code size.  FIXME: Maybe enable a sequence like
745 ;; this at -O3 and above ?
747 ;; Note - we ignore shift counts of less than one or more than 15.
748 ;; This is permitted by the ISO C99 standard as such shifts result
749 ;; in "undefined" behavior.  [6.5.7 (3)]
751 ;; signed A << C
753 (define_expand "ashlhi3"
754   [(set (match_operand:HI            0 "nonimmediate_operand")
755         (ashift:HI (match_operand:HI 1 "general_operand")
756                    (match_operand:HI 2 "general_operand")))]
757   ""
758   {
759     if (GET_CODE (operands[1]) == SUBREG
760         && REG_P (XEXP (operands[1], 0)))
761       operands[1] = force_reg (HImode, operands[1]);
762     if (msp430x
763         && REG_P (operands[0])
764         && REG_P (operands[1])
765         && CONST_INT_P (operands[2]))
766       emit_insn (gen_430x_shift_left (operands[0], operands[1], operands[2]));
767     else if (CONST_INT_P (operands[2])
768              && INTVAL (operands[2]) == 1)
769       emit_insn (gen_slli_1 (operands[0], operands[1]));
770     else                 
771       msp430_expand_helper (operands, \"__mspabi_slli\", true);
772     DONE;
773   }
776 (define_insn "slli_1"
777   [(set (match_operand:HI            0 "nonimmediate_operand" "=rm")
778         (ashift:HI (match_operand:HI 1 "general_operand"       "0")
779                    (const_int 1)))]
780   ""
781   "RLA.W\t%0" ;; Note - this is a macro for ADD
784 (define_insn "430x_shift_left"
785   [(set (match_operand:HI            0 "register_operand" "=r")
786         (ashift:HI (match_operand:HI 1 "register_operand"  "0")
787                    (match_operand    2 "immediate_operand" "n")))]
788   "msp430x"
789   "*
790   if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 16)
791     return \"rpt\t%2 { rlax.w\t%0\";
792   return \"# nop left shift\";
793   "
796 (define_insn "slll_1"
797   [(set (match_operand:SI            0 "nonimmediate_operand" "=rm")
798         (ashift:SI (match_operand:SI 1 "general_operand"       "0")
799                    (const_int 1)))]
800   ""
801   "RLA.W\t%L0 { RLC.W\t%H0"
804 (define_insn "slll_2"
805   [(set (match_operand:SI            0 "nonimmediate_operand" "=rm")
806         (ashift:SI (match_operand:SI 1 "general_operand"       "0")
807                    (const_int 2)))]
808   ""
809   "RLA.W\t%L0 { RLC.W\t%H0 { RLA.W\t%L0 { RLC.W\t%H0"
812 (define_expand "ashlsi3"
813   [(set (match_operand:SI            0 "nonimmediate_operand")
814         (ashift:SI (match_operand:SI 1 "general_operand")
815                    (match_operand:SI 2 "general_operand")))]
816   ""
817   "msp430_expand_helper (operands, \"__mspabi_slll\", true);
818    DONE;"
821 ;;----------
823 ;; signed A >> C
825 (define_expand "ashrhi3"
826   [(set (match_operand:HI              0 "nonimmediate_operand")
827         (ashiftrt:HI (match_operand:HI 1 "general_operand")
828                      (match_operand:HI 2 "general_operand")))]
829   ""
830   {
831     if (GET_CODE (operands[1]) == SUBREG
832         && REG_P (XEXP (operands[1], 0)))
833       operands[1] = force_reg (HImode, operands[1]);
834     if (msp430x
835         && REG_P (operands[0])
836         && REG_P (operands[1])
837         && CONST_INT_P (operands[2]))
838       emit_insn (gen_430x_arithmetic_shift_right (operands[0], operands[1], operands[2]));
839     else if (CONST_INT_P (operands[2])
840              && INTVAL (operands[2]) == 1)
841       emit_insn (gen_srai_1 (operands[0], operands[1]));
842     else                 
843        msp430_expand_helper (operands, \"__mspabi_srai\", true);
844    DONE;
845    }
848 (define_insn "srai_1"
849   [(set (match_operand:HI              0 "msp_nonimmediate_operand" "=rm")
850         (ashiftrt:HI (match_operand:HI 1 "msp_general_operand"      "0")
851                      (const_int 1)))]
852   ""
853   "RRA.W\t%0"
856 (define_insn "430x_arithmetic_shift_right"
857   [(set (match_operand:HI              0 "register_operand" "=r")
858         (ashiftrt:HI (match_operand:HI 1 "register_operand"  "0")
859                      (match_operand    2 "immediate_operand" "n")))]
860   "msp430x"
861   "*
862   if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 16)
863     return \"rpt\t%2 { rrax.w\t%0\";
864   return \"# nop arith right shift\";
865   "
868 (define_insn "srap_1"
869   [(set (match_operand:PSI              0 "register_operand" "=r")
870         (ashiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
871                       (const_int 1)))]
872   "msp430x"
873   "RRAM.A #1,%0"
876 (define_insn "srap_2"
877   [(set (match_operand:PSI              0 "register_operand" "=r")
878         (ashiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
879                       (const_int 2)))]
880   "msp430x"
881   "RRAM.A #2,%0"
884 (define_insn "sral_1"
885   [(set (match_operand:SI              0 "nonimmediate_operand" "=rm")
886         (ashiftrt:SI (match_operand:SI 1 "general_operand"       "0")
887                      (const_int 1)))]
888   ""
889   "RRA.W\t%H0 { RRC.W\t%L0"
892 (define_insn "sral_2"
893   [(set (match_operand:SI              0 "nonimmediate_operand" "=rm")
894         (ashiftrt:SI (match_operand:SI 1 "general_operand"       "0")
895                      (const_int 2)))]
896   ""
897   "RRA.W\t%H0 { RRC.W\t%L0 { RRA.W\t%H0 { RRC.W\t%L0"
900 (define_expand "ashrsi3"
901   [(set (match_operand:SI              0 "nonimmediate_operand")
902         (ashiftrt:SI (match_operand:SI 1 "general_operand")
903                      (match_operand:SI 2 "general_operand")))]
904   ""
905   "msp430_expand_helper (operands, \"__mspabi_sral\", true);
906    DONE;"
909 ;;----------
911 ;; unsigned A >> C
913 (define_expand "lshrhi3"
914   [(set (match_operand:HI              0 "nonimmediate_operand")
915         (lshiftrt:HI (match_operand:HI 1 "general_operand")
916                      (match_operand:HI 2 "general_operand")))]
917   ""
918   {
919     if (GET_CODE (operands[1]) == SUBREG
920         && REG_P (XEXP (operands[1], 0)))
921       operands[1] = force_reg (HImode, operands[1]);
922     if (msp430x
923         && REG_P (operands[0])
924         && REG_P (operands[1])
925         && CONST_INT_P (operands[2]))
926       emit_insn (gen_430x_logical_shift_right (operands[0], operands[1], operands[2]));
927     else if (CONST_INT_P (operands[2])
928              && INTVAL (operands[2]) == 1)
929       emit_insn (gen_srli_1 (operands[0], operands[1]));
930     else                 
931       msp430_expand_helper (operands, \"__mspabi_srli\", true);
932     DONE;
933   }
936 (define_insn "srli_1"
937   [(set (match_operand:HI              0 "nonimmediate_operand" "=rm")
938         (lshiftrt:HI (match_operand:HI 1 "general_operand"       "0")
939                      (const_int 1)))]
940   ""
941   "CLRC { RRC.W\t%0"
944 (define_insn "430x_logical_shift_right"
945   [(set (match_operand:HI              0 "register_operand" "=r")
946         (lshiftrt:HI (match_operand:HI 1 "register_operand"  "0")
947                      (match_operand    2 "immediate_operand" "n")))]
948   "msp430x"
949   {
950     return msp430x_logical_shift_right (operands[2]);
951   }
954 (define_insn "srlp_1"
955   [(set (match_operand:PSI              0 "register_operand" "=r")
956         (lshiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
957                       (const_int 1)))]
958   ""
959   "RRUM.A #1,%0"
962 (define_insn "srll_1"
963   [(set (match_operand:SI              0 "nonimmediate_operand" "=rm")
964         (lshiftrt:SI (match_operand:SI 1 "general_operand"       "0")
965                      (const_int 1)))]
966   ""
967   "CLRC { RRC.W\t%H0 { RRC.W\t%L0"
970 (define_insn "srll_2x"
971   [(set (match_operand:SI              0 "nonimmediate_operand" "=r")
972         (lshiftrt:SI (match_operand:SI 1 "general_operand"       "0")
973                      (const_int 2)))]
974   "msp430x"
975   "RRUX.W\t%H0 { RRC.W\t%L0 { RRUX.W\t%H0 { RRC.W\t%L0"
978 (define_expand "lshrsi3"
979   [(set (match_operand:SI              0 "nonimmediate_operand")
980         (lshiftrt:SI (match_operand:SI 1 "general_operand")
981                      (match_operand:SI 2 "general_operand")))]
982   ""
983   "msp430_expand_helper (operands, \"__mspabi_srll\", true);
984    DONE;"
987 ;;------------------------------------------------------------
988 ;; Function Entry/Exit
990 (define_expand "prologue"
991   [(const_int 0)]
992   ""
993   "msp430_expand_prologue (); DONE;"
994   )
996 (define_expand "epilogue"
997   [(const_int 0)]
998   ""
999   "msp430_expand_epilogue (0); DONE;"
1000   )
1002 (define_insn "epilogue_helper"
1003   [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_EPILOGUE_HELPER)]
1004   ""
1005   "BR%Q0\t#__mspabi_func_epilog_%J0"
1006   )
1008 (define_insn "prologue_start_marker"
1009   [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_START_MARKER)]
1010   ""
1011   "; start of prologue"
1012   )
1014 (define_insn "prologue_end_marker"
1015   [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_END_MARKER)]
1016   ""
1017   "; end of prologue"
1018   )
1020 (define_insn "epilogue_start_marker"
1021   [(unspec_volatile [(const_int 0)] UNS_EPILOGUE_START_MARKER)]
1022   ""
1023   "; start of epilogue"
1024   )
1026 ;; This makes the linker add a call to exit() after the call to main()
1027 ;; in crt0
1028 (define_insn "msp430_refsym_need_exit"
1029   [(unspec_volatile [(const_int 0)] UNS_REFSYM_NEED_EXIT)]
1030   ""
1031   ".refsym\t__crt0_call_exit"
1032   )
1034 ;;------------------------------------------------------------
1035 ;; Jumps
1037 (define_expand "call"
1038   [(call:HI (match_operand 0 "")
1039             (match_operand 1 ""))]
1040   ""
1041   ""
1044 (define_insn "call_internal"
1045   [(call (mem:HI (match_operand 0 "general_operand" "rYci"))
1046          (match_operand 1 ""))]
1047   ""
1048   "CALL%Q0\t%0"
1051 (define_expand "call_value"
1052   [(set (match_operand          0 "register_operand")
1053         (call:HI (match_operand 1 "general_operand")
1054                  (match_operand 2 "")))]
1055   ""
1056   ""
1059 (define_insn "call_value_internal"
1060   [(set (match_operand               0 "register_operand" "=r")
1061         (call (mem:HI (match_operand 1 "general_operand" "rYci"))
1062               (match_operand 2 "")))]
1063   ""
1064   "CALL%Q0\t%1"
1067 (define_insn "msp_return"
1068   [(return)]
1069   ""
1070   { return msp430_is_interrupt_func () ? "RETI" : (TARGET_LARGE ? "RETA" : "RET"); }
1073 ;; This pattern is NOT, as expected, a return pattern.  It's called
1074 ;; before reload and must only store its operands, and emit a
1075 ;; placeholder where the epilog needs to be.  AFTER reload, the
1076 ;; placeholder should get expanded into a regular-type epilogue that
1077 ;; also does the EH return.
1078 (define_expand "eh_return"
1079   [(match_operand:HI 0 "")]
1080   ""
1081   "msp430_expand_eh_return (operands[0]);
1082    emit_jump_insn (gen_msp430_eh_epilogue ());
1083    emit_barrier ();
1084    DONE;"
1087 ;; This is the actual EH epilogue.  We emit it in the pattern above,
1088 ;; before reload, and convert it to a real epilogue after reload.
1089 (define_insn_and_split "msp430_eh_epilogue"
1090   [(eh_return)]
1091   ""
1092   "#"
1093   "reload_completed"
1094   [(const_int 0)]
1095   "msp430_expand_epilogue (1); DONE;"
1096   )
1098 (define_insn "jump"
1099   [(set (pc)
1100         (label_ref (match_operand 0 "" "")))]
1101   ""
1102   "BR%Q0\t#%l0"
1105 ;; FIXME: GCC currently (8/feb/2013) cannot handle symbol_refs
1106 ;; in indirect jumps (cf gcc.c-torture/compile/991213-3.c).
1107 (define_insn "indirect_jump"
1108   [(set (pc)
1109         (match_operand 0 "nonimmediate_operand" "rYl"))]
1110   ""
1111   "BR%Q0\t%0"
1114 ;;------------------------------------------------------------
1115 ;; Various Conditionals
1117 (define_expand "cbranch<mode>4"
1118   [(parallel [(set (pc) (if_then_else
1119                          (match_operator 0 ""
1120                                          [(match_operand:QHI 1 "nonimmediate_operand")
1121                                           (match_operand:QHI 2 "general_operand")])
1122                          (label_ref (match_operand 3 "" ""))
1123                          (pc)))
1124               (clobber (reg:BI CARRY))]
1125   )]
1126   ""
1127   "msp430_fixup_compare_operands (<MODE>mode, operands);"
1128   )
1130 (define_insn "cbranchpsi4_real"
1131   [(set (pc) (if_then_else
1132               (match_operator                     0 "msp430_cmp_operator"
1133                               [(match_operand:PSI 1 "nonimmediate_operand" "r,rYs,rm")
1134                                (match_operand:PSI 2 "general_operand"      "rLs,rYsi,rmi")])
1135               (label_ref (match_operand           3 "" ""))
1136               (pc)))
1137    (clobber (reg:BI CARRY))
1138    ]
1139   ""
1140   "@
1141   CMP%Q0\t%2, %1 { J%0\t%l3
1142   CMPX.A\t%2, %1 { J%0\t%l3
1143   CMPX.A\t%2, %1 { J%0\t%l3"
1144   )
1146 (define_insn "cbranchqi4_real"
1147   [(set (pc) (if_then_else
1148               (match_operator                    0 "msp430_cmp_operator"
1149                               [(match_operand:QI 1 "nonimmediate_operand" "rYs,rm")
1150                                (match_operand:QI 2 "general_operand"      "rYsi,rmi")])
1151               (label_ref (match_operand          3 "" ""))
1152               (pc)))
1153    (clobber (reg:BI CARRY))
1154    ]
1155   ""
1156   "@
1157    CMP.B\t%2, %1 { J%0\t%l3
1158    CMP%X0.B\t%2, %1 { J%0\t%l3"
1159   )
1161 (define_insn "cbranchhi4_real"
1162   [(set (pc) (if_then_else
1163               (match_operator                    0 "msp430_cmp_operator"
1164                               [(match_operand:HI 1 "nonimmediate_operand" "rYs,rm")
1165                                (match_operand:HI 2 "general_operand"      "rYsi,rmi")])
1166               (label_ref (match_operand          3 "" ""))
1167               (pc)))
1168    (clobber (reg:BI CARRY))
1169    ]
1170   ""
1171   "*
1172     /* This is nasty.  If we are splitting code between low and high memory
1173        then we do not want the linker to increase the size of sections by
1174        relaxing out of range jump instructions.  (Since relaxation occurs
1175        after section placement).  So we have to generate pessimal branches
1176        here.  But we only want to do this when really necessary.
1178        FIXME: Do we need code in the other cbranch patterns ?  */
1179     if (msp430_do_not_relax_short_jumps () && get_attr_length (insn) > 6)
1180       {
1181         return which_alternative == 0 ?
1182             \"CMP.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\" :
1183          \"CMP%X0.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\";
1184       }
1186     return which_alternative == 0 ?
1187          \"CMP.W\t%2, %1 { J%0\t%l3\" :
1188       \"CMP%X0.W\t%2, %1 { J%0\t%l3\";
1189   "
1190   [(set (attr "length")
1191         (if_then_else
1192           (and (ge (minus (match_dup 3) (pc)) (const_int -510))
1193                (le (minus (match_dup 3) (pc)) (const_int 510)))
1194           (const_int 6)
1195           (const_int 10))
1196         )]
1197   )
1199 (define_insn "cbranchpsi4_reversed"
1200   [(set (pc) (if_then_else
1201               (match_operator                     0 "msp430_reversible_cmp_operator"
1202                               [(match_operand:PSI 1 "general_operand" "rLs,rYsi,rmi")
1203                                (match_operand:PSI 2 "general_operand" "r,rYs,rm")])
1204               (label_ref (match_operand           3 "" ""))
1205               (pc)))
1206    (clobber (reg:BI CARRY))
1207    ]
1208   ""
1209   "@
1210   CMP%Q0\t%1, %2 { J%R0\t%l3
1211   CMPX.A\t%1, %2 { J%R0\t%l3
1212   CMPX.A\t%1, %2 { J%R0\t%l3"
1213   )
1215 (define_insn "cbranchqi4_reversed"
1216   [(set (pc) (if_then_else
1217               (match_operator                    0 "msp430_reversible_cmp_operator"
1218                               [(match_operand:QI 1 "general_operand" "rYsi,rmi")
1219                                (match_operand:QI 2 "general_operand" "rYs,rm")])
1220               (label_ref (match_operand          3 "" ""))
1221               (pc)))
1222    (clobber (reg:BI CARRY))
1223    ]
1224   ""
1225   "@
1226    CMP.B\t%1, %2 { J%R0\t%l3
1227    CMP%X0.B\t%1, %2 { J%R0\t%l3"
1228   )
1230 (define_insn "cbranchhi4_reversed"
1231   [(set (pc) (if_then_else
1232               (match_operator                    0 "msp430_reversible_cmp_operator"
1233                               [(match_operand:HI 1 "general_operand" "rYsi,rmi")
1234                                (match_operand:HI 2 "general_operand" "rYs,rm")])
1235               (label_ref (match_operand          3 "" ""))
1236               (pc)))
1237    (clobber (reg:BI CARRY))
1238    ]
1239   ""
1240   "@
1241    CMP.W\t%1, %2 { J%R0\t%l3
1242    CMP%X0.W\t%1, %2 { J%R0\t%l3"
1243   )
1245 (define_insn "*bitbranch<mode>4"
1246   [(set (pc) (if_then_else
1247               (ne (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rYs,rm")
1248                            (match_operand:QHI 1 "msp_general_operand" "rYsi,rmi"))
1249                   (const_int 0))
1250               (label_ref (match_operand 2 "" ""))
1251               (pc)))
1252    (clobber (reg:BI CARRY))
1253    ]
1254   ""
1255   "@
1256    BIT%x0%b0\t%1, %0 { JNE\t%l2
1257    BIT%X0%b0\t%1, %0 { JNE\t%l2"
1258   )
1260 (define_insn "*bitbranch<mode>4"
1261   [(set (pc) (if_then_else
1262               (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1263                            (match_operand:QHI 1 "msp_general_operand" "rmi"))
1264                   (const_int 0))
1265               (label_ref (match_operand 2 "" ""))
1266               (pc)))
1267    (clobber (reg:BI CARRY))
1268    ]
1269   ""
1270   "BIT%x0%b0\t%1, %0 { JEQ\t%l2"
1271   )
1273 (define_insn "*bitbranch<mode>4"
1274   [(set (pc) (if_then_else
1275               (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1276                            (match_operand:QHI 1 "msp_general_operand" "rmi"))
1277                   (const_int 0))
1278               (pc)
1279               (label_ref (match_operand 2 "" ""))))
1280    (clobber (reg:BI CARRY))
1281    ]
1282   ""
1283   "BIT%X0%b0\t%1, %0 { JNE\t%l2"
1284   )
1286 (define_insn "*bitbranch<mode>4"
1287   [(set (pc) (if_then_else
1288               (ne (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1289                            (match_operand:QHI 1 "msp_general_operand" "rmi"))
1290                   (const_int 0))
1291               (pc)
1292               (label_ref (match_operand 2 "" ""))))
1293    (clobber (reg:BI CARRY))
1294    ]
1295   ""
1296   "BIT%X0%b0\t%1, %0 { JEQ\t%l2"
1297   )
1299 ;;------------------------------------------------------------
1300 ;; zero-extract versions of the above
1302 (define_insn "*bitbranch<mode>4_z"
1303   [(set (pc) (if_then_else
1304               (ne (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rYs,rm")
1305                                     (const_int 1)
1306                                     (match_operand 1 "msp430_bitpos" "i,i"))
1307                   (const_int 0))
1308               (label_ref (match_operand 2 "" ""))
1309               (pc)))
1310    (clobber (reg:BI CARRY))
1311    ]
1312   ""
1313   "@
1314    BIT%x0%b0\t%p1, %0 { JNE\t%l2
1315    BIT%X0%b0\t%p1, %0 { JNE\t%l2"
1316   )
1318 (define_insn "*bitbranch<mode>4_z"
1319   [(set (pc) (if_then_else
1320               (eq (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1321                                    (const_int 1)
1322                                    (match_operand 1 "msp430_bitpos" "i"))
1323                   (const_int 0))
1324               (label_ref (match_operand 2 "" ""))
1325               (pc)))
1326    (clobber (reg:BI CARRY))
1327    ]
1328   ""
1329   "BIT%x0%X0%b0\t%p1, %0 { JEQ\t%l2"
1330   )
1332 (define_insn "*bitbranch<mode>4_z"
1333   [(set (pc) (if_then_else
1334               (eq (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1335                                    (const_int 1)
1336                                    (match_operand 1 "msp430_bitpos" "i"))
1337                   (const_int 0))
1338               (pc)
1339               (label_ref (match_operand 2 "" ""))))
1340    (clobber (reg:BI CARRY))
1341    ]
1342   ""
1343   "BIT%X0%b0\t%p1, %0 { JNE\t%l2"
1344   )
1346 (define_insn "*bitbranch<mode>4_z"
1347   [(set (pc) (if_then_else
1348               (ne (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1349                                    (const_int 1)
1350                                    (match_operand 1 "msp430_bitpos" "i"))
1351                   (const_int 0))
1352               (pc)
1353               (label_ref (match_operand 2 "" ""))))
1354    (clobber (reg:BI CARRY))
1355    ]
1356   ""
1357   "BIT%X0%b0\t%p1, %0 { JEQ\t%l2"
1358   )
1360 ;;------------------------------------------------------------
1361 ;; Misc
1363 (define_insn "nop"
1364   [(const_int 0)]
1365   "1"
1366   "NOP"
1369 (define_insn "disable_interrupts"
1370   [(unspec_volatile [(const_int 0)] UNS_DINT)]
1371   ""
1372   "DINT \; NOP"
1373   )
1375 (define_insn "enable_interrupts"
1376   [(unspec_volatile [(const_int 0)] UNS_EINT)]
1377   ""
1378   "EINT"
1379   )
1381 (define_insn "push_intr_state"
1382   [(unspec_volatile [(const_int 0)] UNS_PUSH_INTR)]
1383   ""
1384   "PUSH\tSR"
1385   )
1387 (define_insn "pop_intr_state"
1388   [(unspec_volatile [(const_int 0)] UNS_POP_INTR)]
1389   ""
1390   "POP\tSR"
1391   )
1393 ;; Clear bits in the copy of the status register that is currently
1394 ;; saved on the stack at the top of the interrupt handler.
1395 (define_insn "bic_SR"
1396   [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIC_SR)]
1397   ""
1398   "BIC.W\t%0, %O0(SP)"
1399   )
1401 ;; Set bits in the copy of the status register that is currently
1402 ;; saved on the stack at the top of the interrupt handler.
1403 (define_insn "bis_SR"
1404   [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIS_SR)]
1405   ""
1406   "BIS.W\t%0, %O0(SP)"
1407   )
1409 ;; For some reason GCC is generating (set (reg) (and (neg (reg)) (int)))
1410 ;; very late on in the compilation and not splitting it into separate
1411 ;; instructions, so we provide a pattern to support it here.
1412 (define_insn "andneghi3"
1413   [(set (match_operand:HI                 0 "register_operand" "=r")
1414         (and:HI (neg:HI (match_operand:HI 1 "register_operand"  "r"))
1415                 (match_operand            2 "immediate_operand" "n")))]
1416   ""
1417   "*
1418     if (REGNO (operands[0]) != REGNO (operands[1]))
1419       return \"MOV.W\t%1, %0 { INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0\";
1420     else
1421       return \"INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0\";
1422   "
1423   )
1425 (define_insn "delay_cycles_start"
1426   [(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
1427                     UNS_DELAY_START)]
1428   ""
1429   "; Begin %J0 cycle delay"
1430   )
1432 (define_insn "delay_cycles_end"
1433   [(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
1434                     UNS_DELAY_END)]
1435   ""
1436   "; End %J0 cycle delay"
1437   )
1439 (define_insn "delay_cycles_32"
1440   [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1441                      (match_operand 1 "immediate_operand" "i")
1442                      ] UNS_DELAY_32)]
1443   ""
1444   "PUSH r13
1445         PUSH    r14
1446         MOV.W   %A0, r13
1447         MOV.W   %B0, r14
1448 1:      SUB.W   #1, r13
1449         SUBC.W  #0, r14
1450         JNE     1b
1451         TST.W   r13
1452         JNE     1b
1453         POP     r14
1454         POP     r13"
1455   )
1457 (define_insn "delay_cycles_32x"
1458   [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1459                      (match_operand 1 "immediate_operand" "i")
1460                      ] UNS_DELAY_32X)]
1461   ""
1462   "PUSHM.A      #2,r14
1463         MOV.W   %A0, r13
1464         MOV.W   %B0, r14
1465 1:      SUB.W   #1, r13
1466         SUBC.W  #0, r14
1467         JNE     1b
1468         TST.W   r13
1469         JNE     1b
1470         POPM.A  #2,r14"
1471   )
1473 (define_insn "delay_cycles_16"
1474   [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1475                      (match_operand 1 "immediate_operand" "i")
1476                      ] UNS_DELAY_16)]
1477   ""
1478   "PUSH r13
1479         MOV.W   %0, r13
1480 1:      SUB.W   #1, r13
1481         JNE     1b
1482         POP     r13"
1483   )
1485 (define_insn "delay_cycles_16x"
1486   [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1487                      (match_operand 1 "immediate_operand" "i")
1488                      ] UNS_DELAY_16X)]
1489   ""
1490   "PUSHM.A      #1,r13
1491         MOV.W   %0, r13
1492 1:      SUB.W   #1, r13
1493         JNE     1b
1494         POPM.A  #1,r13"
1495   )
1497 (define_insn "delay_cycles_2"
1498   [(unspec_volatile [(const_int 0) ] UNS_DELAY_2)]
1499   ""
1500   "JMP  .+2"
1501   )
1503 (define_insn "delay_cycles_1"
1504   [(unspec_volatile [(const_int 0) ] UNS_DELAY_1)]
1505   ""
1506   "NOP"
1507   )
1509 (define_insn "mulhisi3"
1510   [(set (match_operand:SI                          0 "register_operand" "=r")
1511         (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1512                  (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
1513   "optimize > 2 && msp430_hwmult_type != MSP430_HWMULT_NONE"
1514   "*
1515     if (msp430_use_f5_series_hwmult ())
1516       return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x04C2 { MOV.W %2, &0x04C8 { MOV.W &0x04CA, %L0 { MOV.W &0x04CC, %H0 { POP.W sr\";
1517     else
1518       return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x0132 { MOV.W %2, &0x0138 { MOV.W &0x013A, %L0 { MOV.W &0x013C, %H0 { POP.W sr\";
1519   "
1522 (define_insn "umulhisi3"
1523   [(set (match_operand:SI                          0 "register_operand" "=r")
1524         (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1525                  (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
1526   "optimize > 2 && msp430_hwmult_type != MSP430_HWMULT_NONE"
1527   "*
1528     if (msp430_use_f5_series_hwmult ())
1529       return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x04C0 { MOV.W %2, &0x04C8 { MOV.W &0x04CA, %L0 { MOV.W &0x04CC, %H0 { POP.W sr\";
1530     else
1531       return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x0130 { MOV.W %2, &0x0138 { MOV.W &0x013A, %L0 { MOV.W &0x013C, %H0 { POP.W sr\";
1532   "
1535 (define_insn "mulsidi3"
1536   [(set (match_operand:DI                          0 "register_operand" "=r")
1537         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
1538                  (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
1539   "optimize > 2 && msp430_hwmult_type != MSP430_HWMULT_NONE"
1540   "*
1541     if (msp430_use_f5_series_hwmult ())
1542       return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x04D4 { MOV.W %H1, &0x04D6 { MOV.W %L2, &0x04E0 { MOV.W %H2, &0x04E2 { MOV.W &0x04E4, %A0 { MOV.W &0x04E6, %B0 { MOV.W &0x04E8, %C0 { MOV.W &0x04EA, %D0 { POP.W sr\";
1543     else
1544       return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x0144 { MOV.W %H1, &0x0146 { MOV.W %L2, &0x0150 { MOV.W %H2, &0x0152 { MOV.W &0x0154, %A0 { MOV.W &0x0156, %B0 { MOV.W &0x0158, %C0 { MOV.W &0x015A, %D0 { POP.W sr\";
1545   "
1548 (define_insn "umulsidi3"
1549   [(set (match_operand:DI                          0 "register_operand" "=r")
1550         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
1551                  (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
1552   "optimize > 2 && msp430_hwmult_type != MSP430_HWMULT_NONE"
1553   "*
1554     if (msp430_use_f5_series_hwmult ())
1555       return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x04D0 { MOV.W %H1, &0x04D2 { MOV.W %L2, &0x04E0 { MOV.W %H2, &0x04E2 { MOV.W &0x04E4, %A0 { MOV.W &0x04E6, %B0 { MOV.W &0x04E8, %C0 { MOV.W &0x04EA, %D0 { POP.W sr\";
1556     else
1557       return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x0140 { MOV.W %H1, &0x0142 { MOV.W %L2, &0x0150 { MOV.W %H2, &0x0152 { MOV.W &0x0154, %A0 { MOV.W &0x0156, %B0 { MOV.W &0x0158, %C0 { MOV.W &0x015A, %D0 { POP.W sr\";
1558   "