1;;  Machine Description for TI MSP43* processors
2;;  Copyright (C) 2013-2018 Free Software Foundation, Inc.
3;;  Contributed by Red Hat.
4
5;; This file is part of GCC.
6
7;; GCC is free software; you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation; either version 3, or (at your option)
10;; any later version.
11
12;; GCC is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GCC; see the file COPYING3.  If not see
19;; <http://www.gnu.org/licenses/>.
20
21
22(define_constants
23  [
24   (PC_REGNO 0)
25   (SP_REGNO 1)
26   (CARRY 2)
27  ])
28
29(define_c_enum "unspec"
30  [
31   UNS_PROLOGUE_START_MARKER
32   UNS_PROLOGUE_END_MARKER
33   UNS_EPILOGUE_START_MARKER
34   UNS_EPILOGUE_HELPER
35
36   UNS_PUSHM
37   UNS_POPM
38
39   UNS_GROW_AND_SWAP
40   UNS_SWAP_AND_SHRINK
41
42   UNS_DINT
43   UNS_EINT
44   UNS_PUSH_INTR
45   UNS_POP_INTR
46   UNS_BIC_SR
47   UNS_BIS_SR
48
49   UNS_REFSYM_NEED_EXIT
50
51   UNS_DELAY_32
52   UNS_DELAY_32X
53   UNS_DELAY_16
54   UNS_DELAY_16X
55   UNS_DELAY_2
56   UNS_DELAY_1
57   UNS_DELAY_START
58   UNS_DELAY_END
59  ])
60
61;; This is an approximation.
62(define_attr "length" "" (const_int 4))
63
64(include "predicates.md")
65(include "constraints.md")
66
67(define_mode_iterator QHI [QI HI PSI])
68
69;; There are two basic "family" tests we do here:
70;;
71;; msp430x - true if 430X instructions are available.
72;; TARGET_LARGE - true if pointers are 20-bits
73;;
74;; Note that there are three supported cases, since the base 430
75;; doesn't have 20-bit pointers:
76;;
77;; 1. MSP430 cpu, small model
78;; 2. MSP430X cpu, small model.
79;; 3. MSP430X cpu, large model.
80
81;;------------------------------------------------------------
82;; Moves
83
84;; Push/Pop must be before the generic move patterns
85
86(define_insn "push"
87  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNO)))
88	(match_operand:HI 0 "register_operand" "r"))]
89  ""
90  "PUSH\t%0"
91  )
92
93(define_insn "pusha"
94  [(set (mem:PSI (pre_dec:PSI (reg:PSI SP_REGNO)))
95	(match_operand:PSI 0 "register_operand" "r"))]
96  "TARGET_LARGE"
97  "PUSHX.A\t%0"
98  )
99
100(define_insn "pushm"
101  [(unspec_volatile [(match_operand 0 "register_operand" "r")
102		     (match_operand 1 "immediate_operand" "n")] UNS_PUSHM)]
103  ""
104  "PUSHM%b0\t%1, %0"
105  )
106
107(define_insn "pop"
108  [(set (match_operand:HI 0 "register_operand" "=r")
109	(mem:HI (post_inc:HI (reg:HI SP_REGNO))))]
110  ""
111  "POP\t%0"
112  )
113
114(define_insn "popa"
115  [(set (match_operand:PSI 0 "register_operand" "=r")
116	(mem:PSI (post_inc:PSI (reg:PSI SP_REGNO))))]
117  "TARGET_LARGE"
118  "POPX.A\t%0"
119  )
120
121;; This is nasty.  Operand0 is bogus.  It is only there so that we can get a
122;; mode for the %b0 to work.  We should use operand1 for this, but that does
123;; not have a mode.
124;;
125;; Operand1 is actually a register, but we cannot accept (REG...) because the
126;; cprop_hardreg pass can and will renumber registers even inside
127;; unspec_volatiles.  So we take an integer register number parameter and
128;; fudge it to be a register name when we generate the assembler.
129;;
130;; The pushm pattern does not have this problem because of all of the
131;; frame info cruft attached to it, so cprop_hardreg leaves it alone.
132(define_insn "popm"
133  [(unspec_volatile [(match_operand 0 "register_operand" "r")
134		     (match_operand 1 "immediate_operand" "i")
135		     (match_operand 2 "immediate_operand" "i")] UNS_POPM)]
136  ""
137  "POPM%b0\t%2, r%J1"
138  )
139
140;; The next two patterns are here to support a "feature" of how GCC implements
141;; varargs.  When a function uses varargs and the *second* to last named
142;; argument is split between argument registers and the stack, gcc expects the
143;; callee to allocate space on the stack that can contain the register-based
144;; part of the argument.  This space *has* to be just before the remaining
145;; arguments (ie the ones that are fully on the stack).
146;;
147;; The problem is that the MSP430 CALL instruction pushes the return address
148;; onto the stack in the exact place where the callee wants to allocate
149;; this extra space.  So we need a sequence of instructions that can allocate
150;; the extra space and then move the return address down the stack, so that
151;; the extra space is now adjacent to the remaining arguments.
152;;
153;; This could be constructed through regular insns, but they might be split up
154;; by a misguided optimization, so an unspec volatile is used instead.
155
156(define_insn "grow_and_swap"
157  [(unspec_volatile [(const_int 0)] UNS_GROW_AND_SWAP)]
158  ""
159  "*
160    if (TARGET_LARGE)
161      return \"SUBA\t#2, r1 { MOVX.A\t2(r1), 0(r1)\";
162    return \"SUB\t#2, r1 { MOV.W\t2(r1), 0(r1)\";
163  "
164)
165
166(define_insn "swap_and_shrink"
167  [(unspec_volatile [(const_int 0)] UNS_SWAP_AND_SHRINK)]
168  ""
169  "* return TARGET_LARGE
170	   ? \"MOVX.A\t0(r1), 2(r1) { ADDA\t#2, SP\"
171	   : \"MOV.W\t0(r1), 2(r1) { ADD\t#2, SP\";
172  ")
173
174; I set LOAD_EXTEND_OP and WORD_REGISTER_OPERATIONS, but gcc puts in a
175; zero_extend anyway.  Catch it here.
176(define_insn "movqihi"
177  [(set (match_operand:HI                 0 "register_operand" "=r,r")
178	(zero_extend:HI (match_operand:QI 1 "memory_operand" "Ys,m")))]
179  ""
180  "@
181   MOV.B\t%1, %0
182   MOV%X1.B\t%1, %0"
183)
184
185(define_insn "movqi_topbyte"
186  [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=r")
187	(subreg:QI (match_operand:PSI 1 "msp_general_operand" "r") 2))]
188  "msp430x"
189  "PUSHM.A\t#1,%1 { POPM.W\t#1,%0 { POPM.W\t#1,%0"
190)
191
192(define_insn "movqi"
193  [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=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"
199)
200
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"
209)
210
211(define_expand "movsi"
212  [(set (match_operand:SI 0 "nonimmediate_operand")
213	(match_operand:SI 1 "general_operand"))]
214  ""
215  ""
216  )
217
218(define_insn_and_split "movsi_s"
219  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
220	(subreg:SI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))]
221  ""
222  ""
223  "reload_completed"
224  [(set (match_operand:HI 2 "nonimmediate_operand")
225	(match_operand:HI 4 "general_operand"))
226   (set (match_operand:HI 3 "nonimmediate_operand")
227	(match_operand:HI 5 "general_operand"))]
228  "msp430_split_movsi (operands);"
229  )
230
231(define_insn_and_split "movsi_x"
232  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
233	(match_operand:SI 1 "general_operand" "rmi"))]
234  ""
235  "#"
236  "reload_completed"
237  [(set (match_operand:HI 2 "nonimmediate_operand")
238	(match_operand:HI 4 "general_operand"))
239   (set (match_operand:HI 3 "nonimmediate_operand")
240	(match_operand:HI 5 "general_operand"))]
241  "msp430_split_movsi (operands);"
242)
243
244;; Some MOVX.A cases can be done with MOVA, this is only a few of them.
245(define_insn "movpsi"
246  [(set (match_operand:PSI 0 "msp_nonimmediate_operand" "=r,r,r,Ya,rm")
247	(match_operand:PSI 1 "msp_general_operand" "N,O,riYa,r,rmi"))]
248  ""
249  "@
250  MOV.B\t%1, %0
251  MOV.W\t%1, %0
252  MOVA\t%1, %0
253  MOVA\t%1, %0
254  MOVX.A\t%1, %0")
255
256; This pattern is identical to the truncsipsi2 pattern except
257; that it uses a SUBREG instead of a TRUNC.  It is needed in
258; order to prevent reload from converting (set:SI (SUBREG:PSI (SI)))
259; into (SET:PSI (PSI)).
260;
261; Note: using POPM.A #1 is two bytes smaller than using POPX.A....
262
263(define_insn "movsipsi2"
264  [(set (match_operand:PSI            0 "register_operand" "=r")
265	(subreg:PSI (match_operand:SI 1 "register_operand" "r") 0))]
266  "msp430x"
267  "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A #1, %0 ; Move reg-pair %L1:%H1 into pointer %0"
268)
269
270;; Produced when converting a pointer to an integer via a union, eg gcc.dg/pr47201.c.
271(define_insn "*movpsihi2_lo"
272  [(set (match_operand:HI             0 "register_operand" "=r")
273	(subreg:HI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))]
274  "msp430x"
275  "MOVA\t%1, %0"
276)
277
278;;------------------------------------------------------------
279;; Math
280
281(define_insn "addpsi3"
282  [(set (match_operand:PSI           0 "msp_nonimmediate_operand" "=r,rm")
283	(plus:PSI (match_operand:PSI 1 "msp_nonimmediate_operand" "%0,0")
284		  (match_operand:PSI 2 "msp_general_operand"      "rLs,rmi")))]
285  ""
286  "@
287  ADDA\t%2, %0
288  ADDX.A\t%2, %0"
289)
290
291(define_insn "addqi3"
292  [(set (match_operand:QI          0 "msp_nonimmediate_operand" "=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"
299)
300
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"
309)
310
311; This pattern is needed in order to avoid reload problems.
312; It takes an SI pair of registers, adds a value to them, and
313; then converts them into a single PSI register.
314
315(define_insn "addsipsi3"
316  [(set (subreg:SI (match_operand:PSI 0 "register_operand" "=&r") 0)
317	(plus:SI (match_operand:SI    1 "register_operand" "0")
318		 (match_operand       2 "general_operand" "rmi")))]
319  ""
320  "ADD.W\t%L2, %L0 { ADDC.W\t%H2, %H0 { PUSH.W\t%H0 { PUSH.W\t%L0 { POPM.A\t#1, %0"
321)
322
323(define_insn "addsi3"
324  [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,rm")
325	(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
326		 (match_operand:SI 2 "general_operand" "r,mi")))]
327  ""
328  "@
329   ADD\t%L2, %L0 { ADDC\t%H2, %H0
330   ADD%X0\t%L2, %L0 { ADDC%X0\t%H2, %H0"
331)
332
333; Version of addhi that exposes the carry operations, for SImode adds.
334;
335; NOTE - we are playing a dangerous game with GCC here.  We have these two
336; add patterns and the splitter that follows because our tests have shown
337; that this results in a significant reduction in code size - because GCC is
338; able to discard any unused part of the addition.  We have to annotate the
339; patterns with the set and use of the carry flag because otherwise GCC will
340; discard parts of the addition when they are actually needed.  But we have
341; not annotated all the other patterns that set the CARRY flag as doing so
342; results in an overall increase in code size[1].  Instead we just *hope*
343; that GCC will not move a carry-setting instruction in between the first
344; and second adds.
345;
346; So far our experiments have shown that GCC is likely to move MOV and CMP
347; instructions in between the two adds, but not other instructions.  MOV is
348; safe, CMP is not.  So we have annotated the CMP patterns and left the
349; subtract, shift and other add patterns alone.  At the moment this is
350; working, but with future changes to the generic parts of GCC that might
351; change.
352;
353; [1] It is not clear exactly why the code size increases.  The cause appears
354; to be that reload is more prevelent to spilling a variable onto the stack
355; but why it does this is unknown.  Possibly the additional CLOBBERs necessary
356; to correctly annotate the other patterns makes reload think that there is
357; increased register pressure.  Or possibly reload does not handle ADD patterns
358; that are not single_set() very well.
359
360(define_insn "addhi3_cy"
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  )
374
375(define_insn "addhi3_cy_i"
376  [(set (match_operand:HI          0 "nonimmediate_operand" "=r,rm")
377	(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
378		 (match_operand:HI 2 "immediate_operand"     "i,i")))
379   (set (reg:BI CARRY)
380	(truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
381					   (match_operand 3 "immediate_operand" "i,i"))
382				  (const_int 16))))
383   ]
384  ""
385  "@
386   ADD\t%2, %1 ; cy
387   ADD%X0\t%2, %1 ; cy"
388  )
389
390; Version of addhi that adds the carry, for SImode adds.
391(define_insn "addchi4_cy"
392  [(set (match_operand:HI                   0 "msp_nonimmediate_operand" "=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  )
402
403; Split an SImode add into two HImode adds, keeping track of the carry
404; so that gcc knows when it can and can't optimize away the two
405; halves.
406(define_split
407  [(set (match_operand:SI          0 "msp430_nonsubreg_operand")
408	(plus:SI (match_operand:SI 1 "msp430_nonsubreg_operand")
409		 (match_operand:SI 2 "msp430_nonsubreg_or_imm_operand")))
410   ]
411  ""
412  [(parallel [(set (match_operand:HI 3 "nonimmediate_operand" "=&rm")
413		   (plus:HI (match_dup 4)
414			    (match_dup 5)))
415	      (set (reg:BI CARRY)
416		   (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 4))
417						      (match_dup 9))
418					     (const_int 16))))
419	      ])
420   (set (match_operand:HI 6 "nonimmediate_operand" "=&rm")
421	(plus:HI (plus:HI (match_dup 7)
422			  (match_dup 8))
423		 (zero_extend:HI (reg:BI CARRY))))
424   ]
425  "
426   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);
432
433   /* BZ 64160: Do not use this splitter when the dest partially overlaps the source.  */
434   if (reg_overlap_mentioned_p (operands[3], operands[7])
435       || reg_overlap_mentioned_p (operands[3], operands[8]))
436      FAIL;
437
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  )
444
445
446;; Alternatives 2 and 3 are to handle cases generated by reload.
447(define_insn "subpsi3"
448  [(set (match_operand:PSI            0 "nonimmediate_operand" "=r,   rm, &?r, ?&r")
449	(minus:PSI (match_operand:PSI 1 "general_operand"       "0,   0,   !r,  !i")
450		   (match_operand:PSI 2 "general_operand"       "rLs, rmi, rmi,  r")))]
451  ""
452  "@
453  SUBA\t%2, %0
454  SUBX.A\t%2, %0
455  MOVX.A\t%1, %0 { SUBX.A\t%2, %0
456  MOVX.A\t%1, %0 { SUBA\t%2, %0"
457)
458
459;; Alternatives 2 and 3 are to handle cases generated by reload.
460(define_insn "subqi3"
461  [(set (match_operand:QI           0 "nonimmediate_operand" "=rYs,  rm,  &?r, ?&r")
462	(minus:QI (match_operand:QI 1 "general_operand"       "0,    0,    !r,  !i")
463		  (match_operand:QI 2 "general_operand"      " riYs, rmi, rmi,   r")))]
464  ""
465  "@
466  SUB.B\t%2, %0
467  SUB%X0.B\t%2, %0
468  MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0
469  MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0"
470)
471
472;; Alternatives 2 and 3 are to handle cases generated by reload.
473(define_insn "subhi3"
474  [(set (match_operand:HI           0 "nonimmediate_operand" "=rYs,  rm,  &?r, ?&r")
475	(minus:HI (match_operand:HI 1 "general_operand"       "0,    0,    !r,  !i")
476		  (match_operand:HI 2 "general_operand"      " riYs, rmi, rmi,   r")))]
477  ""
478  "@
479  SUB.W\t%2, %0
480  SUB%X0.W\t%2, %0
481  MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0
482  MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0"
483)
484
485(define_insn "subsi3"
486  [(set (match_operand:SI           0 "nonimmediate_operand" "=&rm")
487	(minus:SI (match_operand:SI 1 "nonimmediate_operand"   "0")
488		  (match_operand:SI 2 "general_operand"        "rmi")))]
489  ""
490  "SUB%X0\t%L2, %L0 { SUBC%X0\t%H2, %H0"
491)
492
493(define_insn "*bic<mode>_cg"
494  [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,m")
495	(and:QHI (match_operand:QHI 1 "msp_general_operand" "0,0")
496		 (match_operand 2 "msp430_inv_constgen_operator" "n,n")))]
497  ""
498  "@
499   BIC%x0%b0\t#%I2, %0
500   BIC%X0%b0\t#%I2, %0"
501)
502
503(define_insn "bic<mode>3"
504  [(set (match_operand:QHI                   0 "msp_nonimmediate_operand" "=rYs,rm")
505	(and:QHI (not:QHI (match_operand:QHI 1 "msp_general_operand"       "rYs,rmn"))
506		 (match_operand:QHI          2 "msp_nonimmediate_operand"  "0,0")))]
507  ""
508  "@
509   BIC%x0%b0\t%1, %0
510   BIC%X0%b0\t%1, %0"
511)
512
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"
522)
523
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"
532)
533
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"
542)
543
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"
552)
553
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"
561)
562
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"
572)
573
574;; Eliminate extraneous zero-extends mysteriously created by gcc.
575(define_peephole2
576  [(set (match_operand:HI 0 "register_operand")
577	(zero_extend:HI (match_operand:QI 1 "general_operand")))
578   (set (match_operand:HI 2 "register_operand")
579	(zero_extend:HI (match_operand:QI 3 "register_operand")))]
580  "REGNO (operands[0]) == REGNO (operands[2]) && REGNO (operands[2]) == REGNO (operands[3])"
581  [(set (match_dup 0)
582	(zero_extend:HI (match_dup 1)))]
583)
584
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"
592)
593
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"
599)
600
601(define_insn "extendhisi2"
602  [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
603	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))]
604  ""
605  { return msp430x_extendhisi (operands); }
606)
607
608(define_insn "extendhipsi2"
609  [(set (match_operand:PSI 0 "nonimmediate_operand" "=r")
610	(subreg:PSI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) 0))]
611  "msp430x"
612  "RLAM.A #4, %0 { RRAM.A #4, %0"
613)
614
615;; Look for cases where integer/pointer conversions are suboptimal due
616;; to missing patterns, despite us not having opcodes for these
617;; patterns.  Doing these manually allows for alternate optimization
618;; paths.
619
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"
625)
626
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"
634)
635
636(define_insn "zero_extendhisipsi2"
637  [(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r")
638	(subreg:PSI (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r")) 0))]
639  "msp430x"
640  "@
641   AND.W\t#-1,%0
642   MOV.W\t%1,%0"
643)
644
645(define_insn "extend_and_shift1_hipsi2"
646  [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0)
647	(ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0"))
648		   (const_int 1)))]
649  "msp430x"
650  "RLAM.A #4, %0 { RRAM.A #3, %0"
651)
652
653(define_insn "extend_and_shift2_hipsi2"
654  [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0)
655	(ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0"))
656		   (const_int 2)))]
657  "msp430x"
658  "RLAM.A #4, %0 { RRAM.A #2, %0"
659)
660
661; Nasty - we are sign-extending a 20-bit PSI value in one register into
662; two adjacent 16-bit registers to make an SI value.  There is no MSP430X
663; instruction that will do this, so we push the 20-bit value onto the stack
664; and then pop it off as two 16-bit values.
665;
666; FIXME: The MSP430X documentation does not specify if zero-extension or
667; sign-extension happens when the 20-bit value is pushed onto the stack.
668; It is probably zero-extension, but if not this pattern will not work
669; when the PSI value is negative..
670;
671; Note: using PUSHM.A #1 is two bytes smaller than using PUSHX.A....
672;
673; Note: We use a + constraint on operand 0 as otherwise GCC gets confused
674; about extending a single PSI mode register into a pair of SImode registers
675; with the same starting register.  It thinks that the upper register of
676; the pair is unused and so it can clobber it.  Try compiling 20050826-2.c
677; at -O2 to see this.
678
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  "
693)
694
695;; We also need to be able to sign-extend pointer types (eg ptrdiff_t).
696;; Since (we assume) pushing a 20-bit value onto the stack zero-extends
697;; it, we use a different method here.
698
699(define_insn "extendpsisi2"
700  [(set (match_operand:SI                  0 "register_operand" "=r")
701	(sign_extend:SI (match_operand:PSI 1 "register_operand" "r")))]
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  "
714)
715
716; See the movsipsi2 pattern above for another way that GCC performs this
717; conversion.
718(define_insn "truncsipsi2"
719  [(set (match_operand:PSI              0 "register_operand" "=r")
720	(truncate:PSI (match_operand:SI 1 "register_operand" "r")))]
721  ""
722  "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A\t#1, %L0"
723)
724
725;;------------------------------------------------------------
726;; Shift Functions
727
728;; Note:  We do not use the RPT ... SHIFT instruction sequence
729;; when the repeat count is in a register, because even though RPT
730;; accepts counts in registers, it does not work if the count is
731;; zero, and the actual count in the register has to be one less
732;; than the required number of iterations.  We could encode a
733;; seqeunce like this:
734;;
735;;   bit #0xf, Rn
736;;   bz  1f
737;;   dec Rn
738;;   rpt Rn
739;;   <shift> Rm
740;;   inc Rn
741;; 1:
742;;
743;; But is longer than calling a helper function, and we are mostly
744;; concerned with code size.  FIXME: Maybe enable a sequence like
745;; this at -O3 and above ?
746;;
747;; Note - we ignore shift counts of less than one or more than 15.
748;; This is permitted by the ISO C99 standard as such shifts result
749;; in "undefined" behavior.  [6.5.7 (3)]
750
751;; signed A << C
752
753(define_expand "ashlhi3"
754  [(set (match_operand:HI            0 "nonimmediate_operand")
755	(ashift:HI (match_operand:HI 1 "general_operand")
756		   (match_operand:HI 2 "general_operand")))]
757  ""
758  {
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  }
774)
775
776(define_insn "slli_1"
777  [(set (match_operand:HI            0 "nonimmediate_operand" "=rm")
778	(ashift:HI (match_operand:HI 1 "general_operand"       "0")
779		   (const_int 1)))]
780  ""
781  "RLA.W\t%0" ;; Note - this is a macro for ADD
782)
783
784(define_insn "430x_shift_left"
785  [(set (match_operand:HI            0 "register_operand" "=r")
786	(ashift:HI (match_operand:HI 1 "register_operand"  "0")
787		   (match_operand    2 "immediate_operand" "n")))]
788  "msp430x"
789  "*
790  if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 16)
791    return \"rpt\t%2 { rlax.w\t%0\";
792  return \"# nop left shift\";
793  "
794)
795
796(define_insn "slll_1"
797  [(set (match_operand:SI            0 "nonimmediate_operand" "=rm")
798	(ashift:SI (match_operand:SI 1 "general_operand"       "0")
799		   (const_int 1)))]
800  ""
801  "RLA.W\t%L0 { RLC.W\t%H0"
802)
803
804(define_insn "slll_2"
805  [(set (match_operand:SI            0 "nonimmediate_operand" "=rm")
806	(ashift:SI (match_operand:SI 1 "general_operand"       "0")
807		   (const_int 2)))]
808  ""
809  "RLA.W\t%L0 { RLC.W\t%H0 { RLA.W\t%L0 { RLC.W\t%H0"
810)
811
812(define_expand "ashlsi3"
813  [(set (match_operand:SI            0 "nonimmediate_operand")
814	(ashift:SI (match_operand:SI 1 "general_operand")
815		   (match_operand:SI 2 "general_operand")))]
816  ""
817  "msp430_expand_helper (operands, \"__mspabi_slll\", true);
818   DONE;"
819)
820
821;;----------
822
823;; signed A >> C
824
825(define_expand "ashrhi3"
826  [(set (match_operand:HI              0 "nonimmediate_operand")
827	(ashiftrt:HI (match_operand:HI 1 "general_operand")
828		     (match_operand:HI 2 "general_operand")))]
829  ""
830  {
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   }
846)
847
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"
854)
855
856(define_insn "430x_arithmetic_shift_right"
857  [(set (match_operand:HI              0 "register_operand" "=r")
858	(ashiftrt:HI (match_operand:HI 1 "register_operand"  "0")
859		     (match_operand    2 "immediate_operand" "n")))]
860  "msp430x"
861  "*
862  if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 16)
863    return \"rpt\t%2 { rrax.w\t%0\";
864  return \"# nop arith right shift\";
865  "
866)
867
868(define_insn "srap_1"
869  [(set (match_operand:PSI              0 "register_operand" "=r")
870	(ashiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
871		      (const_int 1)))]
872  "msp430x"
873  "RRAM.A #1,%0"
874)
875
876(define_insn "srap_2"
877  [(set (match_operand:PSI              0 "register_operand" "=r")
878	(ashiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
879		      (const_int 2)))]
880  "msp430x"
881  "RRAM.A #2,%0"
882)
883
884(define_insn "sral_1"
885  [(set (match_operand:SI              0 "nonimmediate_operand" "=rm")
886	(ashiftrt:SI (match_operand:SI 1 "general_operand"       "0")
887		     (const_int 1)))]
888  ""
889  "RRA.W\t%H0 { RRC.W\t%L0"
890)
891
892(define_insn "sral_2"
893  [(set (match_operand:SI              0 "nonimmediate_operand" "=rm")
894	(ashiftrt:SI (match_operand:SI 1 "general_operand"       "0")
895		     (const_int 2)))]
896  ""
897  "RRA.W\t%H0 { RRC.W\t%L0 { RRA.W\t%H0 { RRC.W\t%L0"
898)
899
900(define_expand "ashrsi3"
901  [(set (match_operand:SI              0 "nonimmediate_operand")
902	(ashiftrt:SI (match_operand:SI 1 "general_operand")
903		     (match_operand:SI 2 "general_operand")))]
904  ""
905  "msp430_expand_helper (operands, \"__mspabi_sral\", true);
906   DONE;"
907)
908
909;;----------
910
911;; unsigned A >> C
912
913(define_expand "lshrhi3"
914  [(set (match_operand:HI              0 "nonimmediate_operand")
915	(lshiftrt:HI (match_operand:HI 1 "general_operand")
916		     (match_operand:HI 2 "general_operand")))]
917  ""
918  {
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  }
934)
935
936(define_insn "srli_1"
937  [(set (match_operand:HI              0 "nonimmediate_operand" "=rm")
938	(lshiftrt:HI (match_operand:HI 1 "general_operand"       "0")
939		     (const_int 1)))]
940  ""
941  "CLRC { RRC.W\t%0"
942)
943
944(define_insn "430x_logical_shift_right"
945  [(set (match_operand:HI              0 "register_operand" "=r")
946	(lshiftrt:HI (match_operand:HI 1 "register_operand"  "0")
947		     (match_operand    2 "immediate_operand" "n")))]
948  "msp430x"
949  {
950    return msp430x_logical_shift_right (operands[2]);
951  }
952)
953
954(define_insn "srlp_1"
955  [(set (match_operand:PSI              0 "register_operand" "=r")
956	(lshiftrt:PSI (match_operand:PSI 1 "general_operand" "0")
957		      (const_int 1)))]
958  ""
959  "RRUM.A #1,%0"
960)
961
962(define_insn "srll_1"
963  [(set (match_operand:SI              0 "nonimmediate_operand" "=rm")
964	(lshiftrt:SI (match_operand:SI 1 "general_operand"       "0")
965		     (const_int 1)))]
966  ""
967  "CLRC { RRC.W\t%H0 { RRC.W\t%L0"
968)
969
970(define_insn "srll_2x"
971  [(set (match_operand:SI              0 "nonimmediate_operand" "=r")
972	(lshiftrt:SI (match_operand:SI 1 "general_operand"       "0")
973		     (const_int 2)))]
974  "msp430x"
975  "RRUX.W\t%H0 { RRC.W\t%L0 { RRUX.W\t%H0 { RRC.W\t%L0"
976)
977
978(define_expand "lshrsi3"
979  [(set (match_operand:SI              0 "nonimmediate_operand")
980	(lshiftrt:SI (match_operand:SI 1 "general_operand")
981		     (match_operand:SI 2 "general_operand")))]
982  ""
983  "msp430_expand_helper (operands, \"__mspabi_srll\", true);
984   DONE;"
985)
986
987;;------------------------------------------------------------
988;; Function Entry/Exit
989
990(define_expand "prologue"
991  [(const_int 0)]
992  ""
993  "msp430_expand_prologue (); DONE;"
994  )
995
996(define_expand "epilogue"
997  [(const_int 0)]
998  ""
999  "msp430_expand_epilogue (0); DONE;"
1000  )
1001
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  )
1007
1008(define_insn "prologue_start_marker"
1009  [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_START_MARKER)]
1010  ""
1011  "; start of prologue"
1012  )
1013
1014(define_insn "prologue_end_marker"
1015  [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_END_MARKER)]
1016  ""
1017  "; end of prologue"
1018  )
1019
1020(define_insn "epilogue_start_marker"
1021  [(unspec_volatile [(const_int 0)] UNS_EPILOGUE_START_MARKER)]
1022  ""
1023  "; start of epilogue"
1024  )
1025
1026;; This makes the linker add a call to exit() after the call to main()
1027;; in crt0
1028(define_insn "msp430_refsym_need_exit"
1029  [(unspec_volatile [(const_int 0)] UNS_REFSYM_NEED_EXIT)]
1030  ""
1031  ".refsym\t__crt0_call_exit"
1032  )
1033
1034;;------------------------------------------------------------
1035;; Jumps
1036
1037(define_expand "call"
1038  [(call:HI (match_operand 0 "")
1039	    (match_operand 1 ""))]
1040  ""
1041  ""
1042)
1043
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"
1049)
1050
1051(define_expand "call_value"
1052  [(set (match_operand          0 "register_operand")
1053	(call:HI (match_operand 1 "general_operand")
1054		 (match_operand 2 "")))]
1055  ""
1056  ""
1057)
1058
1059(define_insn "call_value_internal"
1060  [(set (match_operand               0 "register_operand" "=r")
1061	(call (mem:HI (match_operand 1 "general_operand" "rYci"))
1062	      (match_operand 2 "")))]
1063  ""
1064  "CALL%Q0\t%1"
1065)
1066
1067(define_insn "msp_return"
1068  [(return)]
1069  ""
1070  { return msp430_is_interrupt_func () ? "RETI" : (TARGET_LARGE ? "RETA" : "RET"); }
1071)
1072
1073;; This pattern is NOT, as expected, a return pattern.  It's called
1074;; before reload and must only store its operands, and emit a
1075;; placeholder where the epilog needs to be.  AFTER reload, the
1076;; placeholder should get expanded into a regular-type epilogue that
1077;; also does the EH return.
1078(define_expand "eh_return"
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;"
1085)
1086
1087;; This is the actual EH epilogue.  We emit it in the pattern above,
1088;; before reload, and convert it to a real epilogue after reload.
1089(define_insn_and_split "msp430_eh_epilogue"
1090  [(eh_return)]
1091  ""
1092  "#"
1093  "reload_completed"
1094  [(const_int 0)]
1095  "msp430_expand_epilogue (1); DONE;"
1096  )
1097
1098(define_insn "jump"
1099  [(set (pc)
1100	(label_ref (match_operand 0 "" "")))]
1101  ""
1102  "BR%Q0\t#%l0"
1103)
1104
1105;; FIXME: GCC currently (8/feb/2013) cannot handle symbol_refs
1106;; in indirect jumps (cf gcc.c-torture/compile/991213-3.c).
1107(define_insn "indirect_jump"
1108  [(set (pc)
1109	(match_operand 0 "nonimmediate_operand" "rYl"))]
1110  ""
1111  "BR%Q0\t%0"
1112)
1113
1114;;------------------------------------------------------------
1115;; Various Conditionals
1116
1117(define_expand "cbranch<mode>4"
1118  [(parallel [(set (pc) (if_then_else
1119			 (match_operator 0 ""
1120					 [(match_operand:QHI 1 "nonimmediate_operand")
1121					  (match_operand:QHI 2 "general_operand")])
1122			 (label_ref (match_operand 3 "" ""))
1123			 (pc)))
1124	      (clobber (reg:BI CARRY))]
1125  )]
1126  ""
1127  "msp430_fixup_compare_operands (<MODE>mode, operands);"
1128  )
1129
1130(define_insn "cbranchpsi4_real"
1131  [(set (pc) (if_then_else
1132	      (match_operator                     0 "msp430_cmp_operator"
1133			      [(match_operand:PSI 1 "nonimmediate_operand" "r,rYs,rm")
1134			       (match_operand:PSI 2 "general_operand"      "rLs,rYsi,rmi")])
1135              (label_ref (match_operand           3 "" ""))
1136	      (pc)))
1137   (clobber (reg:BI CARRY))
1138   ]
1139  ""
1140  "@
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  )
1145
1146(define_insn "cbranchqi4_real"
1147  [(set (pc) (if_then_else
1148	      (match_operator                    0 "msp430_cmp_operator"
1149			      [(match_operand:QI 1 "nonimmediate_operand" "rYs,rm")
1150			       (match_operand:QI 2 "general_operand"      "rYsi,rmi")])
1151              (label_ref (match_operand          3 "" ""))
1152	      (pc)))
1153   (clobber (reg:BI CARRY))
1154   ]
1155  ""
1156  "@
1157   CMP.B\t%2, %1 { J%0\t%l3
1158   CMP%X0.B\t%2, %1 { J%0\t%l3"
1159  )
1160
1161(define_insn "cbranchhi4_real"
1162  [(set (pc) (if_then_else
1163	      (match_operator                    0 "msp430_cmp_operator"
1164			      [(match_operand:HI 1 "nonimmediate_operand" "rYs,rm")
1165			       (match_operand:HI 2 "general_operand"      "rYsi,rmi")])
1166              (label_ref (match_operand          3 "" ""))
1167	      (pc)))
1168   (clobber (reg:BI CARRY))
1169   ]
1170  ""
1171  "*
1172    /* This is nasty.  If we are splitting code between low and high memory
1173       then we do not want the linker to increase the size of sections by
1174       relaxing out of range jump instructions.  (Since relaxation occurs
1175       after section placement).  So we have to generate pessimal branches
1176       here.  But we only want to do this when really necessary.
1177
1178       FIXME: Do we need code in the other cbranch patterns ?  */
1179    if (msp430_do_not_relax_short_jumps () && get_attr_length (insn) > 6)
1180      {
1181        return which_alternative == 0 ?
1182            \"CMP.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\" :
1183         \"CMP%X0.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\";
1184      }
1185
1186    return which_alternative == 0 ?
1187         \"CMP.W\t%2, %1 { J%0\t%l3\" :
1188      \"CMP%X0.W\t%2, %1 { J%0\t%l3\";
1189  "
1190  [(set (attr "length")
1191	(if_then_else
1192	  (and (ge (minus (match_dup 3) (pc)) (const_int -510))
1193	       (le (minus (match_dup 3) (pc)) (const_int 510)))
1194	  (const_int 6)
1195	  (const_int 10))
1196	)]
1197  )
1198
1199(define_insn "cbranchpsi4_reversed"
1200  [(set (pc) (if_then_else
1201	      (match_operator                     0 "msp430_reversible_cmp_operator"
1202			      [(match_operand:PSI 1 "general_operand" "rLs,rYsi,rmi")
1203			       (match_operand:PSI 2 "general_operand" "r,rYs,rm")])
1204              (label_ref (match_operand           3 "" ""))
1205	      (pc)))
1206   (clobber (reg:BI CARRY))
1207   ]
1208  ""
1209  "@
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  )
1214
1215(define_insn "cbranchqi4_reversed"
1216  [(set (pc) (if_then_else
1217	      (match_operator                    0 "msp430_reversible_cmp_operator"
1218			      [(match_operand:QI 1 "general_operand" "rYsi,rmi")
1219			       (match_operand:QI 2 "general_operand" "rYs,rm")])
1220              (label_ref (match_operand          3 "" ""))
1221	      (pc)))
1222   (clobber (reg:BI CARRY))
1223   ]
1224  ""
1225  "@
1226   CMP.B\t%1, %2 { J%R0\t%l3
1227   CMP%X0.B\t%1, %2 { J%R0\t%l3"
1228  )
1229
1230(define_insn "cbranchhi4_reversed"
1231  [(set (pc) (if_then_else
1232	      (match_operator                    0 "msp430_reversible_cmp_operator"
1233			      [(match_operand:HI 1 "general_operand" "rYsi,rmi")
1234			       (match_operand:HI 2 "general_operand" "rYs,rm")])
1235              (label_ref (match_operand          3 "" ""))
1236	      (pc)))
1237   (clobber (reg:BI CARRY))
1238   ]
1239  ""
1240  "@
1241   CMP.W\t%1, %2 { J%R0\t%l3
1242   CMP%X0.W\t%1, %2 { J%R0\t%l3"
1243  )
1244
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  )
1259
1260(define_insn "*bitbranch<mode>4"
1261  [(set (pc) (if_then_else
1262	      (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1263			   (match_operand:QHI 1 "msp_general_operand" "rmi"))
1264		  (const_int 0))
1265              (label_ref (match_operand 2 "" ""))
1266	      (pc)))
1267   (clobber (reg:BI CARRY))
1268   ]
1269  ""
1270  "BIT%x0%b0\t%1, %0 { JEQ\t%l2"
1271  )
1272
1273(define_insn "*bitbranch<mode>4"
1274  [(set (pc) (if_then_else
1275	      (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1276			   (match_operand:QHI 1 "msp_general_operand" "rmi"))
1277		  (const_int 0))
1278              (pc)
1279	      (label_ref (match_operand 2 "" ""))))
1280   (clobber (reg:BI CARRY))
1281   ]
1282  ""
1283  "BIT%X0%b0\t%1, %0 { JNE\t%l2"
1284  )
1285
1286(define_insn "*bitbranch<mode>4"
1287  [(set (pc) (if_then_else
1288	      (ne (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1289			   (match_operand:QHI 1 "msp_general_operand" "rmi"))
1290		  (const_int 0))
1291              (pc)
1292	      (label_ref (match_operand 2 "" ""))))
1293   (clobber (reg:BI CARRY))
1294   ]
1295  ""
1296  "BIT%X0%b0\t%1, %0 { JEQ\t%l2"
1297  )
1298
1299;;------------------------------------------------------------
1300;; zero-extract versions of the above
1301
1302(define_insn "*bitbranch<mode>4_z"
1303  [(set (pc) (if_then_else
1304	      (ne (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rYs,rm")
1305				    (const_int 1)
1306				    (match_operand 1 "msp430_bitpos" "i,i"))
1307		  (const_int 0))
1308              (label_ref (match_operand 2 "" ""))
1309	      (pc)))
1310   (clobber (reg:BI CARRY))
1311   ]
1312  ""
1313  "@
1314   BIT%x0%b0\t%p1, %0 { JNE\t%l2
1315   BIT%X0%b0\t%p1, %0 { JNE\t%l2"
1316  )
1317
1318(define_insn "*bitbranch<mode>4_z"
1319  [(set (pc) (if_then_else
1320	      (eq (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1321				   (const_int 1)
1322				   (match_operand 1 "msp430_bitpos" "i"))
1323		  (const_int 0))
1324              (label_ref (match_operand 2 "" ""))
1325	      (pc)))
1326   (clobber (reg:BI CARRY))
1327   ]
1328  ""
1329  "BIT%x0%X0%b0\t%p1, %0 { JEQ\t%l2"
1330  )
1331
1332(define_insn "*bitbranch<mode>4_z"
1333  [(set (pc) (if_then_else
1334	      (eq (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1335				   (const_int 1)
1336				   (match_operand 1 "msp430_bitpos" "i"))
1337		  (const_int 0))
1338              (pc)
1339	      (label_ref (match_operand 2 "" ""))))
1340   (clobber (reg:BI CARRY))
1341   ]
1342  ""
1343  "BIT%X0%b0\t%p1, %0 { JNE\t%l2"
1344  )
1345
1346(define_insn "*bitbranch<mode>4_z"
1347  [(set (pc) (if_then_else
1348	      (ne (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
1349				   (const_int 1)
1350				   (match_operand 1 "msp430_bitpos" "i"))
1351		  (const_int 0))
1352              (pc)
1353	      (label_ref (match_operand 2 "" ""))))
1354   (clobber (reg:BI CARRY))
1355   ]
1356  ""
1357  "BIT%X0%b0\t%p1, %0 { JEQ\t%l2"
1358  )
1359
1360;;------------------------------------------------------------
1361;; Misc
1362
1363(define_insn "nop"
1364  [(const_int 0)]
1365  "1"
1366  "NOP"
1367)
1368
1369(define_insn "disable_interrupts"
1370  [(unspec_volatile [(const_int 0)] UNS_DINT)]
1371  ""
1372  "DINT \; NOP"
1373  )
1374
1375(define_insn "enable_interrupts"
1376  [(unspec_volatile [(const_int 0)] UNS_EINT)]
1377  ""
1378  "EINT"
1379  )
1380
1381(define_insn "push_intr_state"
1382  [(unspec_volatile [(const_int 0)] UNS_PUSH_INTR)]
1383  ""
1384  "PUSH\tSR"
1385  )
1386
1387(define_insn "pop_intr_state"
1388  [(unspec_volatile [(const_int 0)] UNS_POP_INTR)]
1389  ""
1390  "POP\tSR"
1391  )
1392
1393;; Clear bits in the copy of the status register that is currently
1394;; saved on the stack at the top of the interrupt handler.
1395(define_insn "bic_SR"
1396  [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIC_SR)]
1397  ""
1398  "BIC.W\t%0, %O0(SP)"
1399  )
1400
1401;; Set bits in the copy of the status register that is currently
1402;; saved on the stack at the top of the interrupt handler.
1403(define_insn "bis_SR"
1404  [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIS_SR)]
1405  ""
1406  "BIS.W\t%0, %O0(SP)"
1407  )
1408
1409;; For some reason GCC is generating (set (reg) (and (neg (reg)) (int)))
1410;; very late on in the compilation and not splitting it into separate
1411;; instructions, so we provide a pattern to support it here.
1412(define_insn "andneghi3"
1413  [(set (match_operand:HI                 0 "register_operand" "=r")
1414	(and:HI (neg:HI (match_operand:HI 1 "register_operand"  "r"))
1415		(match_operand            2 "immediate_operand" "n")))]
1416  ""
1417  "*
1418    if (REGNO (operands[0]) != REGNO (operands[1]))
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  )
1424
1425(define_insn "delay_cycles_start"
1426  [(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
1427		    UNS_DELAY_START)]
1428  ""
1429  "; Begin %J0 cycle delay"
1430  )
1431
1432(define_insn "delay_cycles_end"
1433  [(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
1434		    UNS_DELAY_END)]
1435  ""
1436  "; End %J0 cycle delay"
1437  )
1438
1439(define_insn "delay_cycles_32"
1440  [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1441		     (match_operand 1 "immediate_operand" "i")
1442		     ] UNS_DELAY_32)]
1443  ""
1444  "PUSH	r13
1445	PUSH	r14
1446	MOV.W	%A0, r13
1447	MOV.W	%B0, r14
14481:	SUB.W	#1, r13
1449	SUBC.W	#0, r14
1450	JNE	1b
1451	TST.W	r13
1452	JNE	1b
1453	POP	r14
1454	POP	r13"
1455  )
1456
1457(define_insn "delay_cycles_32x"
1458  [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1459		     (match_operand 1 "immediate_operand" "i")
1460		     ] UNS_DELAY_32X)]
1461  ""
1462  "PUSHM.A	#2,r14
1463	MOV.W	%A0, r13
1464	MOV.W	%B0, r14
14651:	SUB.W	#1, r13
1466	SUBC.W	#0, r14
1467	JNE	1b
1468	TST.W	r13
1469	JNE	1b
1470	POPM.A	#2,r14"
1471  )
1472
1473(define_insn "delay_cycles_16"
1474  [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1475		     (match_operand 1 "immediate_operand" "i")
1476		     ] UNS_DELAY_16)]
1477  ""
1478  "PUSH	r13
1479	MOV.W	%0, r13
14801:	SUB.W	#1, r13
1481	JNE	1b
1482	POP	r13"
1483  )
1484
1485(define_insn "delay_cycles_16x"
1486  [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1487		     (match_operand 1 "immediate_operand" "i")
1488		     ] UNS_DELAY_16X)]
1489  ""
1490  "PUSHM.A	#1,r13
1491	MOV.W	%0, r13
14921:	SUB.W	#1, r13
1493	JNE	1b
1494	POPM.A	#1,r13"
1495  )
1496
1497(define_insn "delay_cycles_2"
1498  [(unspec_volatile [(const_int 0) ] UNS_DELAY_2)]
1499  ""
1500  "JMP	.+2"
1501  )
1502
1503(define_insn "delay_cycles_1"
1504  [(unspec_volatile [(const_int 0) ] UNS_DELAY_1)]
1505  ""
1506  "NOP"
1507  )
1508
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  "
1520)
1521
1522(define_insn "umulhisi3"
1523  [(set (match_operand:SI                          0 "register_operand" "=r")
1524	(mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1525		 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
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  "
1533)
1534
1535(define_insn "mulsidi3"
1536  [(set (match_operand:DI                          0 "register_operand" "=r")
1537	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
1538		 (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
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  "
1546)
1547
1548(define_insn "umulsidi3"
1549  [(set (match_operand:DI                          0 "register_operand" "=r")
1550	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
1551		 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
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  "
1559)
1560