]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/msp430/msp430.md
MSP430: Add defaulting to the insn length attribute
[thirdparty/gcc.git] / gcc / config / msp430 / msp430.md
CommitLineData
f6a83b4a 1;; Machine Description for TI MSP43* processors
8d9254fc 2;; Copyright (C) 2013-2020 Free Software Foundation, Inc.
f6a83b4a
DD
3;; Contributed by Red Hat.
4
5;; This file is part of GCC.
6
7;; GCC is free software; you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation; either version 3, or (at your option)
10;; any later version.
11
12;; GCC is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GCC; see the file COPYING3. If not see
19;; <http://www.gnu.org/licenses/>.
20\f
21
22(define_constants
23 [
24 (PC_REGNO 0)
25 (SP_REGNO 1)
26 (CARRY 2)
27 ])
28
29(define_c_enum "unspec"
30 [
31 UNS_PROLOGUE_START_MARKER
32 UNS_PROLOGUE_END_MARKER
33 UNS_EPILOGUE_START_MARKER
34 UNS_EPILOGUE_HELPER
35
36 UNS_PUSHM
37 UNS_POPM
38
39 UNS_GROW_AND_SWAP
40 UNS_SWAP_AND_SHRINK
cad055a4
NC
41
42 UNS_DINT
43 UNS_EINT
44 UNS_PUSH_INTR
45 UNS_POP_INTR
46 UNS_BIC_SR
47 UNS_BIS_SR
4f50b9ff
DD
48
49 UNS_REFSYM_NEED_EXIT
5f35dde5
DD
50
51 UNS_DELAY_32
52 UNS_DELAY_32X
53 UNS_DELAY_16
54 UNS_DELAY_16X
55 UNS_DELAY_2
56 UNS_DELAY_1
57 UNS_DELAY_START
58 UNS_DELAY_END
f6a83b4a 59 ])
c6f709ec 60
546c8f95
JL
61;; Instruction length is calculated by examining the type and number of
62;; operands.
63;; Whether the insn uses the 430X extension word, or is a 430X address
64;; instruction also has an effect.
65;; "Cheap" source operands do not contribute to the overall length of the insn
66;; and are register (Rn), indirect post-increment (@Rn+) and indirect register
67;; (@Rn).
68;; The lengths of instructions in bytes are:
69;; Single-op 430: Cheap op == 2
70;; (also CALLA) Other op == 4
71;; Double-op 430: Source is not cheap == 2
72;; (also MOVA, Dest is register == 2
73;; CMPA, ADDA, Dest is not a register == 4
74;; SUBA) (sum the source and dest cost)
75;; Single-op 430X: For insn names ending in 'X' add 2 to single-op 430 cost.
76;; Double-op 430X: Insn name ends in 'M' == 2
77;; Others have the same cost as double-op 430 but add 2.
78;;
79;; The insn type describes whether it is a single or double operand MSP430
80;; instruction (some single-operand GCC instructions are actually
81;; double-operand on the target).
82;; "triple" and "cmp" types use the costs of a double operand type but
83;; instead assume that the src operand is in op2, and also cmp types assume the
84;; dst operand is in op1.
85;; This attribute also describes which operands are safe to examine
86;; when calculating the length or extension. GCC will segfault trying to
87;; examine a non-existant operand of an insn.
88(define_attr "type" "none,single,double,triple,cmp" (const_string "none"))
89
90;; The M extension is for instructions like RRAM - they always
91;; only, and the operand must be a register.
92(define_attr "extension" "none,x,a,m"
93 (cond [(eq_attr "type" "none")
94 (const_string "none")
95 (match_operand 0 "msp430_high_memory_operand" "")
96 (const_string "x")
97 (and (eq_attr "type" "double")
98 (match_operand 1 "msp430_high_memory_operand" ""))
99 (const_string "x")
100 (and (ior (eq_attr "type" "triple") (eq_attr "type" "cmp"))
101 (ior (match_operand 1 "msp430_high_memory_operand" "")
102 (match_operand 2 "msp430_high_memory_operand" "")))
103 (const_string "x")]
104 (const_string "none")))
105
106;; Multiply the default length by this constant value.
107(define_attr "length_multiplier" "" (const_int 1))
108
109;; Add an additional amount to the total length of the insn.
110(define_attr "extra_length" "" (const_int 0))
111
112;; FIXME for some reason if we move the addition of 2 for extension == x to
113;; ADJUST_INSN_LENGTH, codesize gets much worse.
114(define_attr "length" ""
115 (cond [(eq_attr "extension" "m")
116 (const_int 2)
117 (eq_attr "type" "single")
118 (plus (if_then_else (match_operand 0 "msp430_cheap_operand" "")
119 (const_int 2)
120 (const_int 4))
121 (if_then_else (eq_attr "extension" "x")
122 (const_int 2)
123 (const_int 0)))
124 (eq_attr "type" "double")
125 (plus (plus (if_then_else (match_operand 0 "register_operand" "")
126 (const_int 2)
127 (const_int 4))
128 (if_then_else (match_operand 1 "msp430_cheap_operand" "")
129 (const_int 0)
130 (const_int 2)))
131 (if_then_else (eq_attr "extension" "x")
132 (const_int 2)
133 (const_int 0)))
134 (eq_attr "type" "triple")
135 (plus (plus (if_then_else (match_operand 0 "register_operand" "")
136 (const_int 2)
137 (const_int 4))
138 (if_then_else (match_operand 2 "msp430_cheap_operand" "")
139 (const_int 0)
140 (const_int 2)))
141 (if_then_else (eq_attr "extension" "x")
142 (const_int 2)
143 (const_int 0)))
144 (eq_attr "type" "cmp")
145 (plus (plus (if_then_else (match_operand 1 "register_operand" "")
146 (const_int 2)
147 (const_int 4))
148 (if_then_else (match_operand 2 "msp430_cheap_operand" "")
149 (const_int 0)
150 (const_int 2)))
151 (if_then_else (eq_attr "extension" "x")
152 (const_int 2)
153 (const_int 0)))]
154 (const_int 2)))
d7edde11 155
f6a83b4a
DD
156(include "predicates.md")
157(include "constraints.md")
158
159(define_mode_iterator QHI [QI HI PSI])
703e049a
JL
160(define_mode_iterator HPSI [HI PSI])
161(define_mode_iterator HDI [HI PSI SI DI])
162
163;; Mapping of all shift operators
164(define_code_iterator any_shift [ashift ashiftrt lshiftrt])
165
166;; Base name for define_insn
167(define_code_attr shift_insn
168 [(ashift "ashl") (lshiftrt "lshr") (ashiftrt "ashr")])
f6a83b4a
DD
169
170;; There are two basic "family" tests we do here:
171;;
172;; msp430x - true if 430X instructions are available.
173;; TARGET_LARGE - true if pointers are 20-bits
174;;
175;; Note that there are three supported cases, since the base 430
176;; doesn't have 20-bit pointers:
177;;
178;; 1. MSP430 cpu, small model
179;; 2. MSP430X cpu, small model.
180;; 3. MSP430X cpu, large model.
181
182;;------------------------------------------------------------
183;; Moves
184
185;; Push/Pop must be before the generic move patterns
186
187(define_insn "push"
188 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNO)))
189 (match_operand:HI 0 "register_operand" "r"))]
190 ""
191 "PUSH\t%0"
546c8f95
JL
192 [(set_attr "type" "single")]
193)
f6a83b4a
DD
194
195(define_insn "pusha"
196 [(set (mem:PSI (pre_dec:PSI (reg:PSI SP_REGNO)))
197 (match_operand:PSI 0 "register_operand" "r"))]
198 "TARGET_LARGE"
199 "PUSHX.A\t%0"
546c8f95
JL
200 [(set_attr "type" "single")
201 (set_attr "extension" "x")]
202)
f6a83b4a
DD
203
204(define_insn "pushm"
205 [(unspec_volatile [(match_operand 0 "register_operand" "r")
cad055a4 206 (match_operand 1 "immediate_operand" "n")] UNS_PUSHM)]
f6a83b4a 207 ""
51ac3042 208 "PUSHM%b0\t%1, %0"
546c8f95
JL
209 [(set_attr "type" "single")
210 (set_attr "extension" "m")]
211)
f6a83b4a
DD
212
213(define_insn "pop"
214 [(set (match_operand:HI 0 "register_operand" "=r")
215 (mem:HI (post_inc:HI (reg:HI SP_REGNO))))]
216 ""
217 "POP\t%0"
546c8f95
JL
218 [(set_attr "type" "single")]
219)
f6a83b4a
DD
220
221(define_insn "popa"
222 [(set (match_operand:PSI 0 "register_operand" "=r")
223 (mem:PSI (post_inc:PSI (reg:PSI SP_REGNO))))]
224 "TARGET_LARGE"
225 "POPX.A\t%0"
546c8f95
JL
226 [(set_attr "type" "single")
227 (set_attr "extension" "x")]
228)
f6a83b4a
DD
229
230;; This is nasty. Operand0 is bogus. It is only there so that we can get a
51ac3042 231;; mode for the %b0 to work. We should use operand1 for this, but that does
f6a83b4a
DD
232;; not have a mode.
233;;
234;; Operand1 is actually a register, but we cannot accept (REG...) because the
235;; cprop_hardreg pass can and will renumber registers even inside
236;; unspec_volatiles. So we take an integer register number parameter and
d4f283a1 237;; fudge it to be a register name when we generate the assembler.
f6a83b4a
DD
238;;
239;; The pushm pattern does not have this problem because of all of the
240;; frame info cruft attached to it, so cprop_hardreg leaves it alone.
241(define_insn "popm"
242 [(unspec_volatile [(match_operand 0 "register_operand" "r")
243 (match_operand 1 "immediate_operand" "i")
244 (match_operand 2 "immediate_operand" "i")] UNS_POPM)]
245 ""
d4f283a1 246 "POPM%b0\t%2, r%J1"
546c8f95
JL
247 [(set_attr "type" "single")
248 (set_attr "extension" "m")]
249)
f6a83b4a
DD
250
251;; The next two patterns are here to support a "feature" of how GCC implements
252;; varargs. When a function uses varargs and the *second* to last named
253;; argument is split between argument registers and the stack, gcc expects the
254;; callee to allocate space on the stack that can contain the register-based
255;; part of the argument. This space *has* to be just before the remaining
256;; arguments (ie the ones that are fully on the stack).
257;;
258;; The problem is that the MSP430 CALL instruction pushes the return address
259;; onto the stack in the exact place where the callee wants to allocate
260;; this extra space. So we need a sequence of instructions that can allocate
261;; the extra space and then move the return address down the stack, so that
262;; the extra space is now adjacent to the remaining arguments.
263;;
264;; This could be constructed through regular insns, but they might be split up
265;; by a misguided optimization, so an unspec volatile is used instead.
266
267(define_insn "grow_and_swap"
268 [(unspec_volatile [(const_int 0)] UNS_GROW_AND_SWAP)]
269 ""
c6f709ec
NC
270 "*
271 if (TARGET_LARGE)
272 return \"SUBA\t#2, r1 { MOVX.A\t2(r1), 0(r1)\";
273 return \"SUB\t#2, r1 { MOV.W\t2(r1), 0(r1)\";
274 "
546c8f95
JL
275 [(set (attr "length")
276 (if_then_else (match_test "TARGET_LARGE")
277 (const_int 8)
278 (const_int 6)))]
c6f709ec 279)
f6a83b4a
DD
280
281(define_insn "swap_and_shrink"
282 [(unspec_volatile [(const_int 0)] UNS_SWAP_AND_SHRINK)]
283 ""
c6f709ec
NC
284 "* return TARGET_LARGE
285 ? \"MOVX.A\t0(r1), 2(r1) { ADDA\t#2, SP\"
286 : \"MOV.W\t0(r1), 2(r1) { ADD\t#2, SP\";
546c8f95
JL
287 "
288 [(set (attr "length")
289 (if_then_else (match_test "TARGET_LARGE")
290 (const_int 10)
291 (const_int 8)))]
292)
f6a83b4a
DD
293
294; I set LOAD_EXTEND_OP and WORD_REGISTER_OPERATIONS, but gcc puts in a
295; zero_extend anyway. Catch it here.
296(define_insn "movqihi"
297 [(set (match_operand:HI 0 "register_operand" "=r,r")
298 (zero_extend:HI (match_operand:QI 1 "memory_operand" "Ys,m")))]
299 ""
300 "@
301 MOV.B\t%1, %0
302 MOV%X1.B\t%1, %0"
546c8f95 303 [(set_attr "type" "double")]
f6a83b4a
DD
304)
305
c32ab325 306(define_insn "movqi_topbyte"
28987d8b 307 [(set (match_operand:QI 0 "msp430_general_dst_operand" "=r")
8a896995 308 (subreg:QI (match_operand:PSI 1 "msp430_general_operand" "r") 2))]
c32ab325
DD
309 "msp430x"
310 "PUSHM.A\t#1,%1 { POPM.W\t#1,%0 { POPM.W\t#1,%0"
546c8f95
JL
311 [(set_attr "length" "6")
312 (set_attr "type" "double")]
c32ab325
DD
313)
314
f6a83b4a 315(define_insn "movqi"
28987d8b 316 [(set (match_operand:QI 0 "msp430_general_dst_operand" "=rYsYx,rm")
8a896995 317 (match_operand:QI 1 "msp430_general_operand" "riYsYx,rmi"))]
f6a83b4a
DD
318 ""
319 "@
320 MOV.B\t%1, %0
8682b1a5 321 MOVX.B\t%1, %0"
546c8f95 322 [(set_attr "type" "double")]
f6a83b4a
DD
323)
324
325(define_insn "movhi"
28987d8b 326 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=r,rYsYx,rm")
8a896995 327 (match_operand:HI 1 "msp430_general_operand" "N,riYsYx,rmi"))]
f6a83b4a
DD
328 ""
329 "@
3f02735b 330 MOV.B\t%1, %0
f6a83b4a 331 MOV.W\t%1, %0
8682b1a5 332 MOVX.W\t%1, %0"
546c8f95 333 [(set_attr "type" "double")]
f6a83b4a
DD
334)
335
336(define_expand "movsi"
28987d8b 337 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand")
40ada30a 338 (match_operand:SI 1 "general_operand"))]
f6a83b4a
DD
339 ""
340 ""
546c8f95 341)
d7edde11 342
14ae1d88 343(define_insn_and_split "movsi_s"
28987d8b 344 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
14ae1d88
DD
345 (subreg:SI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))]
346 ""
347 ""
348 "reload_completed"
28987d8b 349 [(set (match_operand:HI 2 "msp430_general_dst_nonv_operand")
14ae1d88 350 (match_operand:HI 4 "general_operand"))
28987d8b 351 (set (match_operand:HI 3 "msp430_general_dst_nonv_operand")
14ae1d88
DD
352 (match_operand:HI 5 "general_operand"))]
353 "msp430_split_movsi (operands);"
546c8f95
JL
354 [(set_attr "type" "double")]
355)
14ae1d88 356
f6a83b4a 357(define_insn_and_split "movsi_x"
28987d8b 358 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
f6a83b4a
DD
359 (match_operand:SI 1 "general_operand" "rmi"))]
360 ""
361 "#"
362 "reload_completed"
28987d8b 363 [(set (match_operand:HI 2 "msp430_general_dst_nonv_operand")
f6a83b4a 364 (match_operand:HI 4 "general_operand"))
28987d8b 365 (set (match_operand:HI 3 "msp430_general_dst_nonv_operand")
f6a83b4a
DD
366 (match_operand:HI 5 "general_operand"))]
367 "msp430_split_movsi (operands);"
546c8f95 368 [(set_attr "type" "double")]
f6a83b4a
DD
369)
370
8682b1a5 371;; FIXME: Some MOVX.A cases can be done with MOVA, this is only a few of them.
f6a83b4a 372(define_insn "movpsi"
28987d8b 373 [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,r,r,Ya,rm")
8a896995 374 (match_operand:PSI 1 "msp430_general_operand" "N,O,riYa,r,rmi"))]
f6a83b4a
DD
375 ""
376 "@
3f02735b
DD
377 MOV.B\t%1, %0
378 MOV.W\t%1, %0
c32ab325
DD
379 MOVA\t%1, %0
380 MOVA\t%1, %0
546c8f95
JL
381 MOVX.A\t%1, %0"
382 [(set_attr "extension" "none,none,a,a,x")
383 (set_attr "type" "double")]
384)
f6a83b4a
DD
385
386; This pattern is identical to the truncsipsi2 pattern except
387; that it uses a SUBREG instead of a TRUNC. It is needed in
388; order to prevent reload from converting (set:SI (SUBREG:PSI (SI)))
389; into (SET:PSI (PSI)).
390;
391; Note: using POPM.A #1 is two bytes smaller than using POPX.A....
392
393(define_insn "movsipsi2"
394 [(set (match_operand:PSI 0 "register_operand" "=r")
395 (subreg:PSI (match_operand:SI 1 "register_operand" "r") 0))]
c32ab325 396 "msp430x"
d4f283a1 397 "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A #1, %0 ; Move reg-pair %L1:%H1 into pointer %0"
546c8f95
JL
398 [(set_attr "length" "6")
399 (set_attr "type" "double")]
f6a83b4a
DD
400)
401
e56989ff
NC
402;; Produced when converting a pointer to an integer via a union, eg gcc.dg/pr47201.c.
403(define_insn "*movpsihi2_lo"
404 [(set (match_operand:HI 0 "register_operand" "=r")
405 (subreg:HI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))]
406 "msp430x"
407 "MOVA\t%1, %0"
546c8f95
JL
408 [(set_attr "extension" "a")
409 (set_attr "type" "double")]
e56989ff
NC
410)
411
f6a83b4a
DD
412;;------------------------------------------------------------
413;; Math
414
415(define_insn "addpsi3"
28987d8b
JL
416 [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,rm")
417 (plus:PSI (match_operand:PSI 1 "msp430_general_operand" "%0,0")
8a896995 418 (match_operand:PSI 2 "msp430_general_operand" "rLs,rmi")))]
f6a83b4a
DD
419 ""
420 "@
421 ADDA\t%2, %0
422 ADDX.A\t%2, %0"
546c8f95
JL
423 [(set_attr "extension" "a,x")
424 (set_attr "type" "triple")]
f6a83b4a
DD
425)
426
427(define_insn "addqi3"
28987d8b
JL
428 [(set (match_operand:QI 0 "msp430_general_dst_operand" "=rYsYx,rm")
429 (plus:QI (match_operand:QI 1 "msp430_general_operand" "%0,0")
8a896995 430 (match_operand:QI 2 "msp430_general_operand" "riYsYx,rmi")))]
f6a83b4a
DD
431 ""
432 "@
433 ADD.B\t%2, %0
8682b1a5 434 ADDX.B\t%2, %0"
546c8f95 435 [(set_attr "type" "triple")]
f6a83b4a
DD
436)
437
438(define_insn "addhi3"
28987d8b
JL
439 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYsYx,rm")
440 (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0")
8a896995 441 (match_operand:HI 2 "msp430_general_operand" "riYsYx,rmi")))]
f6a83b4a
DD
442 ""
443 "@
444 ADD.W\t%2, %0
8682b1a5 445 ADDX.W\t%2, %0"
546c8f95 446 [(set_attr "type" "triple")]
f6a83b4a
DD
447)
448
449; This pattern is needed in order to avoid reload problems.
450; It takes an SI pair of registers, adds a value to them, and
451; then converts them into a single PSI register.
452
453(define_insn "addsipsi3"
454 [(set (subreg:SI (match_operand:PSI 0 "register_operand" "=&r") 0)
455 (plus:SI (match_operand:SI 1 "register_operand" "0")
456 (match_operand 2 "general_operand" "rmi")))]
457 ""
8682b1a5 458 "ADD%X2.W\t%L2, %L0 { ADDC%X2.W\t%H2, %H0 { PUSH.W\t%H0 { PUSH.W\t%L0 { POPM.A\t#1, %0"
546c8f95
JL
459 [(set (attr "length")
460 (if_then_else (match_operand 2 "register_operand" "")
461 (const_int 10)
462 (if_then_else (match_operand 2 "msp430_high_memory_operand" "")
463 (const_int 18)
464 (const_int 14))))
465 (set_attr "type" "triple")]
f6a83b4a
DD
466)
467
468(define_insn "addsi3"
28987d8b
JL
469 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=&rYsYx,rm")
470 (plus:SI (match_operand:SI 1 "general_operand" "%0,0")
8682b1a5 471 (match_operand:SI 2 "general_operand" "rYsYxi,mi")))]
f6a83b4a
DD
472 ""
473 "@
474 ADD\t%L2, %L0 { ADDC\t%H2, %H0
8682b1a5 475 ADDX\t%L2, %L0 { ADDCX\t%H2, %H0"
546c8f95
JL
476 [(set_attr "length_multiplier" "2")
477 (set_attr "type" "triple")]
f6a83b4a
DD
478)
479
480; Version of addhi that exposes the carry operations, for SImode adds.
481;
482; NOTE - we are playing a dangerous game with GCC here. We have these two
483; add patterns and the splitter that follows because our tests have shown
484; that this results in a significant reduction in code size - because GCC is
485; able to discard any unused part of the addition. We have to annotate the
486; patterns with the set and use of the carry flag because otherwise GCC will
487; discard parts of the addition when they are actually needed. But we have
488; not annotated all the other patterns that set the CARRY flag as doing so
489; results in an overall increase in code size[1]. Instead we just *hope*
490; that GCC will not move a carry-setting instruction in between the first
491; and second adds.
492;
493; So far our experiments have shown that GCC is likely to move MOV and CMP
494; instructions in between the two adds, but not other instructions. MOV is
495; safe, CMP is not. So we have annotated the CMP patterns and left the
496; subtract, shift and other add patterns alone. At the moment this is
497; working, but with future changes to the generic parts of GCC that might
498; change.
499;
500; [1] It is not clear exactly why the code size increases. The cause appears
501; to be that reload is more prevelent to spilling a variable onto the stack
502; but why it does this is unknown. Possibly the additional CLOBBERs necessary
503; to correctly annotate the other patterns makes reload think that there is
504; increased register pressure. Or possibly reload does not handle ADD patterns
505; that are not single_set() very well.
506
28987d8b
JL
507; match_operand 3 is likely to be the same as op2 most of the time - except
508; when op2 is a post_inc and we have stripped the post_inc from match_operand 3
509
f6a83b4a 510(define_insn "addhi3_cy"
28987d8b
JL
511 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYsYx,rm")
512 (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0")
8a896995 513 (match_operand:HI 2 "msp430_nonimmediate_operand" "rYsYxi,rm")))
f6a83b4a
DD
514 (set (reg:BI CARRY)
515 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
28987d8b 516 (zero_extend:SI (match_operand:HI 3 "msp430_nonimmediate_operand" "rYsYxi,rm")))
f6a83b4a
DD
517 (const_int 16))))
518 ]
519 ""
520 "@
40ada30a 521 ADD\t%2, %1 ; cy
8682b1a5 522 ADDX\t%2, %1 ; cy"
546c8f95
JL
523 [(set_attr "type" "triple")]
524)
f6a83b4a
DD
525
526(define_insn "addhi3_cy_i"
28987d8b
JL
527 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=r,rm")
528 (plus:HI (match_operand:HI 1 "general_operand" "%0,0")
d4f283a1 529 (match_operand:HI 2 "immediate_operand" "i,i")))
f6a83b4a
DD
530 (set (reg:BI CARRY)
531 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
532 (match_operand 3 "immediate_operand" "i,i"))
533 (const_int 16))))
534 ]
535 ""
536 "@
40ada30a
NC
537 ADD\t%2, %1 ; cy
538 ADD%X0\t%2, %1 ; cy"
546c8f95
JL
539 [(set_attr "type" "triple")]
540)
f6a83b4a
DD
541
542; Version of addhi that adds the carry, for SImode adds.
543(define_insn "addchi4_cy"
28987d8b
JL
544 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYsYx,rm")
545 (plus:HI (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0")
8a896995 546 (match_operand:HI 2 "msp430_general_operand" "riYsYx,rmi"))
f6a83b4a
DD
547 (zero_extend:HI (reg:BI CARRY))))
548 ]
549 ""
550 "@
40ada30a 551 ADDC\t%2, %1
8682b1a5 552 ADDCX\t%2, %1"
546c8f95
JL
553 [(set_attr "type" "triple")]
554)
f6a83b4a
DD
555
556; Split an SImode add into two HImode adds, keeping track of the carry
557; so that gcc knows when it can and can't optimize away the two
558; halves.
28987d8b
JL
559; We use the ugly predicate "msp430_nonsubregnonpostinc_or_imm_operand" to
560; enforce the position of a post_inc into op2 if present
f6a83b4a 561(define_split
28987d8b
JL
562 [(set (match_operand:SI 0 "msp430_nonsubreg_dst_operand")
563 (plus:SI (match_operand:SI 1 "msp430_nonsubregnonpostinc_or_imm_operand")
9c5f6203 564 (match_operand:SI 2 "msp430_nonsubreg_or_imm_operand")))
f6a83b4a
DD
565 ]
566 ""
28987d8b 567 [(parallel [(set (match_operand:HI 3 "msp430_general_dst_nonv_operand" "=&rm")
f6a83b4a
DD
568 (plus:HI (match_dup 4)
569 (match_dup 5)))
570 (set (reg:BI CARRY)
571 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 4))
572 (match_dup 9))
573 (const_int 16))))
574 ])
28987d8b 575 (set (match_operand:HI 6 "msp430_general_dst_nonv_operand" "=&rm")
f6a83b4a
DD
576 (plus:HI (plus:HI (match_dup 7)
577 (match_dup 8))
578 (zero_extend:HI (reg:BI CARRY))))
579 ]
580 "
53f45082
JL
581 if (msp430_split_addsi (operands))
582 FAIL;
583 "
546c8f95 584)
f6a83b4a
DD
585
586
587;; Alternatives 2 and 3 are to handle cases generated by reload.
588(define_insn "subpsi3"
28987d8b
JL
589 [(set (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r, rm, &?r, ?&r")
590 (minus:PSI (match_operand:PSI 1 "general_operand" "0, 0, !r, !i")
591 (match_operand:PSI 2 "general_operand" "rLs, rmi, rmi, r")))]
f6a83b4a
DD
592 ""
593 "@
594 SUBA\t%2, %0
595 SUBX.A\t%2, %0
596 MOVX.A\t%1, %0 { SUBX.A\t%2, %0
597 MOVX.A\t%1, %0 { SUBA\t%2, %0"
546c8f95
JL
598 [(set_attr "type" "triple")
599 (set_attr "extension" "a,x,x,x")
600 (set_attr "length_multiplier" "1,1,2,2")]
f6a83b4a
DD
601)
602
603;; Alternatives 2 and 3 are to handle cases generated by reload.
604(define_insn "subqi3"
28987d8b 605 [(set (match_operand:QI 0 "msp430_general_dst_nonv_operand" "=rYsYx, rm, &?r, ?&r")
f6a83b4a 606 (minus:QI (match_operand:QI 1 "general_operand" "0, 0, !r, !i")
8682b1a5 607 (match_operand:QI 2 "general_operand" " riYsYx, rmi, rmi, r")))]
f6a83b4a
DD
608 ""
609 "@
610 SUB.B\t%2, %0
8682b1a5
JL
611 SUBX.B\t%2, %0
612 MOV%X2.B\t%1, %0 { SUB%X2.B\t%2, %0
f6a83b4a 613 MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0"
546c8f95
JL
614 [(set_attr "length_multiplier" "1,1,2,2")
615 (set_attr "type" "triple")]
f6a83b4a
DD
616)
617
618;; Alternatives 2 and 3 are to handle cases generated by reload.
619(define_insn "subhi3"
28987d8b 620 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=rYsYx, rm, &?r, ?&r")
f6a83b4a 621 (minus:HI (match_operand:HI 1 "general_operand" "0, 0, !r, !i")
8682b1a5 622 (match_operand:HI 2 "general_operand" " riYsYx, rmi, rmi, r")))]
f6a83b4a
DD
623 ""
624 "@
625 SUB.W\t%2, %0
8682b1a5
JL
626 SUBX.W\t%2, %0
627 MOV%X2.W\t%1, %0 { SUB%X2.W\t%2, %0
f6a83b4a 628 MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0"
546c8f95
JL
629 [(set_attr "length_multiplier" "1,1,2,2")
630 (set_attr "type" "triple")]
f6a83b4a
DD
631)
632
633(define_insn "subsi3"
28987d8b
JL
634 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=&rYsYx,m")
635 (minus:SI (match_operand:SI 1 "general_operand" "0,0")
8682b1a5 636 (match_operand:SI 2 "general_operand" "riYsYx,mi")))]
f6a83b4a 637 ""
8682b1a5
JL
638 "@
639 SUB\t%L2, %L0 { SUBC\t%H2, %H0
640 SUBX\t%L2, %L0 { SUBCX\t%H2, %H0"
546c8f95
JL
641 [(set_attr "length_multiplier" "2")
642 (set_attr "type" "triple")]
f6a83b4a
DD
643)
644
645(define_insn "*bic<mode>_cg"
28987d8b 646 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYs,m")
8a896995 647 (and:QHI (match_operand:QHI 1 "msp430_general_operand" "0,0")
f6a83b4a
DD
648 (match_operand 2 "msp430_inv_constgen_operator" "n,n")))]
649 ""
650 "@
51ac3042
NC
651 BIC%x0%b0\t#%I2, %0
652 BIC%X0%b0\t#%I2, %0"
546c8f95
JL
653 [(set_attr "length" "2") ; Smaller length achieved by using constant generator
654 (set_attr "type" "double")]
f6a83b4a
DD
655)
656
657(define_insn "bic<mode>3"
28987d8b 658 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYsYx,rm")
8a896995 659 (and:QHI (not:QHI (match_operand:QHI 1 "msp430_general_operand" "rYsYx,rmn"))
28987d8b 660 (match_operand:QHI 2 "msp430_general_operand" "0,0")))]
f6a83b4a
DD
661 ""
662 "@
51ac3042 663 BIC%x0%b0\t%1, %0
8682b1a5 664 BICX%b0\t%1, %0"
546c8f95 665 [(set_attr "type" "double")]
f6a83b4a
DD
666)
667
668(define_insn "and<mode>3"
28987d8b
JL
669 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=r,rYsYx,rm")
670 (and:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0,0")
8a896995 671 (match_operand:QHI 2 "msp430_general_operand" "N,riYsYx,rmi")))]
f6a83b4a
DD
672 ""
673 "@
3f02735b 674 AND%x0.B\t%2, %0
51ac3042 675 AND%x0%b0\t%2, %0
8682b1a5 676 ANDX%b0\t%2, %0"
546c8f95 677 [(set_attr "type" "triple")]
f6a83b4a
DD
678)
679
680(define_insn "ior<mode>3"
28987d8b
JL
681 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYsYx,rm")
682 (ior:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0")
8a896995 683 (match_operand:QHI 2 "msp430_general_operand" "riYsYx,rmi")))]
f6a83b4a
DD
684 ""
685 "@
51ac3042 686 BIS%x0%b0\t%2, %0
8682b1a5 687 BISX%b0\t%2, %0"
546c8f95 688 [(set_attr "type" "triple")]
f6a83b4a
DD
689)
690
691(define_insn "xor<mode>3"
28987d8b
JL
692 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYsYx,rm")
693 (xor:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0")
8a896995 694 (match_operand:QHI 2 "msp430_general_operand" "riYsYx,rmi")))]
f6a83b4a
DD
695 ""
696 "@
51ac3042 697 XOR%x0%b0\t%2, %0
8682b1a5 698 XORX%b0\t%2, %0"
546c8f95 699 [(set_attr "type" "triple")]
f6a83b4a
DD
700)
701
702;; Macro : XOR #~0, %0
703(define_insn "one_cmpl<mode>2"
28987d8b
JL
704 [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYs,m")
705 (not:QHI (match_operand:QHI 1 "msp430_general_operand" "0,0")))]
f6a83b4a
DD
706 ""
707 "@
51ac3042
NC
708 INV%x0%b0\t%0
709 INV%X0%b0\t%0"
546c8f95 710 [(set_attr "type" "double")]
f6a83b4a
DD
711)
712
713(define_insn "extendqihi2"
28987d8b
JL
714 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYs,m")
715 (sign_extend:HI (match_operand:QI 1 "msp430_general_operand" "0,0")))]
f6a83b4a
DD
716 ""
717 "@
718 SXT%X0\t%0
719 SXT%X0\t%0"
546c8f95 720 [(set_attr "type" "single")]
f6a83b4a
DD
721)
722
aa360dd1
JL
723(define_insn "extendqipsi2"
724 [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,m")
725 (sign_extend:PSI (match_operand:QI 1 "msp430_general_operand" "0,0")))]
726 ""
727 "@
728 SXT\t%0
729 SXTX.A\t%0"
546c8f95
JL
730 [(set_attr "type" "single")
731 (set_attr "extension" "none,x")]
aa360dd1
JL
732)
733
a0a9a3fc
JL
734;; ------------------------
735;; ZERO EXTEND INSTRUCTIONS
736;; Byte-writes to registers clear bits 19:8
737;; * Byte-writes to memory do not affect bits 15:8
738;; Word-writes to registers clear bits 19:16
739;; PSImode writes to memory clear bits 15:4 of the second memory word
740;; We define all possible insns since that results in better code than if
741;; they are inferred.
742;; ------------------------
743
f6a83b4a 744(define_insn "zero_extendqihi2"
28987d8b
JL
745 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYs,r,r,m")
746 (zero_extend:HI (match_operand:QI 1 "msp430_general_operand" "0,rYs,m,0")))]
f6a83b4a
DD
747 ""
748 "@
749 AND\t#0xff, %0
3f02735b 750 MOV.B\t%1, %0
8682b1a5 751 MOV%X1.B\t%1, %0
f6a83b4a 752 AND%X0\t#0xff, %0"
546c8f95 753 [(set_attr "type" "double")]
f6a83b4a
DD
754)
755
a0a9a3fc
JL
756(define_insn "zero_extendqipsi2"
757 [(set (match_operand:PSI 0 "register_operand" "=r,r")
758 (zero_extend:PSI (match_operand:QI 1 "general_operand" "rYs,m")))]
759 "msp430x"
760 "@
761 MOV.B\t%1, %0
762 MOV%X1.B\t%1, %0"
546c8f95 763 [(set_attr "type" "double")]
a0a9a3fc
JL
764)
765
582b4055 766(define_insn "zero_extendqisi2"
a0a9a3fc
JL
767 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=r,r")
768 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,rm")))]
582b4055 769 ""
a0a9a3fc
JL
770 "@
771 CLR\t%H0
772 MOV%X1.B\t%1,%L0 { CLR\t%H0"
546c8f95
JL
773 [(set_attr "extra_length" "2")
774 (set_attr "length_multiplier" "1,2")
775 (set_attr "type" "double")]
f6a83b4a 776)
d7edde11 777
f6a83b4a 778(define_insn "zero_extendhipsi2"
a0a9a3fc
JL
779 [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,r,m")
780 (zero_extend:PSI (match_operand:HI 1 "msp430_general_operand" "rYs,m,r")))]
781 "msp430x"
85bd3c01 782 "@
a0a9a3fc
JL
783 MOV.W\t%1, %0
784 MOV%X1\t%1, %0
85bd3c01 785 MOVX.A\t%1, %0"
546c8f95 786 [(set_attr "type" "double")]
f6a83b4a 787)
cac52161 788
f6a83b4a 789(define_insn "zero_extendhisi2"
28987d8b
JL
790 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm,r")
791 (zero_extend:SI (match_operand:HI 1 "general_operand" "0,r")))]
525213a5 792 ""
bdafd679 793 "@
8682b1a5 794 MOV%X0.W\t#0,%H0
bdafd679 795 MOV.W\t%1,%L0 { MOV.W\t#0,%H0"
546c8f95
JL
796 [(set_attr "length_multiplier" "1,2")
797 (set_attr "type" "double")]
f6a83b4a
DD
798)
799
800(define_insn "zero_extendhisipsi2"
28987d8b
JL
801 [(set (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r,r")
802 (subreg:PSI (zero_extend:SI (match_operand:HI 1 "general_operand" "0,r")) 0))]
c32ab325 803 "msp430x"
f6a83b4a
DD
804 "@
805 AND.W\t#-1,%0
806 MOV.W\t%1,%0"
546c8f95
JL
807 [(set_attr "length" "4,2")
808 (set_attr "type" "double")]
f6a83b4a
DD
809)
810
f6a83b4a
DD
811; Nasty - we are sign-extending a 20-bit PSI value in one register into
812; two adjacent 16-bit registers to make an SI value. There is no MSP430X
813; instruction that will do this, so we push the 20-bit value onto the stack
814; and then pop it off as two 16-bit values.
815;
816; FIXME: The MSP430X documentation does not specify if zero-extension or
817; sign-extension happens when the 20-bit value is pushed onto the stack.
818; It is probably zero-extension, but if not this pattern will not work
819; when the PSI value is negative..
820;
821; Note: using PUSHM.A #1 is two bytes smaller than using PUSHX.A....
8f0e7f6f
NC
822;
823; Note: We use a + constraint on operand 0 as otherwise GCC gets confused
824; about extending a single PSI mode register into a pair of SImode registers
825; with the same starting register. It thinks that the upper register of
826; the pair is unused and so it can clobber it. Try compiling 20050826-2.c
827; at -O2 to see this.
f6a83b4a 828
a0a9a3fc 829; FIXME we can use MOVA for r->m if m is &abs20 or z16(rdst)
f6a83b4a 830(define_insn "zero_extendpsisi2"
a0a9a3fc
JL
831 [(set (match_operand:SI 0 "register_operand" "+r,m")
832 (zero_extend:SI (match_operand:PSI 1 "register_operand" "r,r")))]
f6a83b4a 833 ""
a0a9a3fc
JL
834 "@
835 * if (REGNO (operands[1]) == SP_REGNO) \
836 /* If the source register is the stack pointer, the value \
837 stored in the stack slot will be the value *after* the \
838 stack pointer has been decremented. So allow for that \
839 here. */ \
840 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\"; \
841 else \
d4f283a1 842 return \"PUSHM.A\t#1, %1 { POPX.W\t%L0 { POPX.W\t%H0 ; move pointer in %1 into reg-pair %L0:%H0\";
a0a9a3fc 843 MOVX.A %1, %0"
546c8f95
JL
844 [(set (attr "length")
845 (cond [(match_test "REGNO (operands[1]) == SP_REGNO")
846 (const_int 18)
847 (eq_attr "alternative" "1")
848 (const_int 6)]
849 (const_int 10)))
850 (set_attr "type" "double")]
a0a9a3fc
JL
851)
852
853;; Below are unnamed insn patterns to catch pointer manipulation insns
854;; generated by combine.
855;; We get large code size bloat when a PSImode pointer is stored in
856;; memory, so we try to avoid that where possible and keep point manipulation
857;; between registers.
858; FIXME many of these should be unnnecessary once combine deals with
859; (sign_extend (zero_extend)) or (sign_extend (subreg)) BZ 91865.
860
861;; This is just another way of writing movqipsi/zero_extendqipsi
862(define_insn ""
863 [(set (match_operand:PSI 0 "register_operand" "=r")
864 (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "rm") 0)))]
865 "msp430x"
866 "MOV%X1.B\t%1, %0"
546c8f95 867 [(set_attr "type" "double")]
40ada30a
NC
868)
869
a0a9a3fc
JL
870(define_insn ""
871 [(set (match_operand:PSI 0 "register_operand" "=r,r")
872 (sign_extend:PSI (zero_extend:HI (match_operand:QI 1 "general_operand" "rYs,m"))))]
873 "msp430x"
874 "@
875 MOV.B\t%1, %0
876 MOV%X1.B\t%1, %0"
546c8f95 877 [(set_attr "type" "double")]
a0a9a3fc
JL
878)
879
703e049a
JL
880;; The next three insns emit identical assembly code.
881;; They take a QImode and shift it in SImode. Only shift counts <= 8
882;; are handled since that is the simple case where the high 16-bits (i.e. the
883;; high register) are always 0.
a0a9a3fc 884(define_insn ""
703e049a
JL
885 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
886 (ashift:SI (zero_extend:SI (match_operand:QI 1 "general_operand" "0,rm,rm"))
887 (match_operand:HI 2 "const_1_to_8_operand" "M,M,i")))]
a0a9a3fc 888 "msp430x"
703e049a
JL
889 "@
890 RLAM.W %2, %L0 { CLR %H0
891 MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0
892 MOV%X1.B %1, %L0 { RPT %2 { RLAX.W %L0 { CLR %H0"
546c8f95
JL
893 [(set_attr "length" "4,*,*")
894 (set_attr "extra_length" "0,4,6")
895 (set_attr "type" "double")]
a0a9a3fc
JL
896)
897
a0a9a3fc 898(define_insn ""
703e049a
JL
899 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
900 (ashift:SI (zero_extend:SI (subreg:HI (match_operand:QI 1 "general_operand" "0,rm,rm") 0))
901 (match_operand:HI 2 "const_1_to_8_operand" "M,M,i")))]
a0a9a3fc 902 "msp430x"
703e049a
JL
903 "@
904 RLAM.W %2, %L0 { CLR %H0
905 MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0
906 MOV%X1.B %1, %L0 { RPT %2 { RLAX.W %L0 { CLR %H0"
546c8f95
JL
907 [(set_attr "length" "4,*,*")
908 (set_attr "extra_length" "0,4,6")
909 (set_attr "type" "double")]
a0a9a3fc
JL
910)
911
912;; Same as above but with a NOP sign_extend round the subreg
913(define_insn ""
703e049a
JL
914 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
915 (ashift:SI (zero_extend:SI (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "0,rm,rm") 0)))
916 (match_operand:HI 2 "const_1_to_8_operand" "M,M,i")))]
a0a9a3fc 917 "msp430x"
703e049a
JL
918 "@
919 RLAM.W %2, %L0 { CLR %H0
920 MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0
921 MOV%X1.B %1, %L0 { RPT %2 { RLAX.W %L0 { CLR %H0"
546c8f95
JL
922 [(set_attr "length" "4,*,*")
923 (set_attr "extra_length" "0,4,6")
924 (set_attr "type" "double")]
a0a9a3fc
JL
925)
926
927(define_insn ""
928 [(set (match_operand:SI 0 "register_operand" "=r")
929 (zero_extend:SI (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "rm") 0))))]
930 "msp430x"
931 "MOV%X1.B %1, %L0 { CLR %H0"
546c8f95
JL
932 [(set_attr "extra_length" "4")
933 (set_attr "type" "double")]
a0a9a3fc
JL
934)
935
936(define_insn ""
703e049a
JL
937 [(set (match_operand:PSI 0 "register_operand" "=r,r,r")
938 (ashift:PSI (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "0,rm,rm") 0))
939 (match_operand:HI 2 "const_1_to_19_operand" "M,M,i")))]
a0a9a3fc 940 "msp430x"
703e049a
JL
941 "@
942 RLAM.W %2, %0
943 MOV%X1.B %1, %0 { RLAM.W %2, %0
944 MOV%X1.B %1, %0 { RPT %2 { RLAX.A %0"
546c8f95
JL
945 [(set_attr "length" "2,*,*")
946 (set_attr "extra_length" "0,2,4")
947 (set_attr "type" "double")]
a0a9a3fc
JL
948)
949;; END msp430 pointer manipulation combine insn patterns
582b4055
JL
950
951;; Eliminate extraneous zero-extends mysteriously created by gcc.
952(define_peephole2
953 [(set (match_operand:HI 0 "register_operand")
954 (zero_extend:HI (match_operand:QI 1 "general_operand")))
955 (set (match_operand:HI 2 "register_operand")
956 (zero_extend:HI (match_operand:QI 3 "register_operand")))]
957 "REGNO (operands[0]) == REGNO (operands[2]) && REGNO (operands[2]) == REGNO (operands[3])"
958 [(set (match_dup 0)
959 (zero_extend:HI (match_dup 1)))]
960)
961
962(define_insn "truncpsihi2"
963 [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rm")
964 (truncate:HI (match_operand:PSI 1 "register_operand" "r")))]
965 ""
966 "MOVX\t%1, %0"
546c8f95
JL
967 [(set_attr "extension" "m")
968 (set_attr "type" "double")]
582b4055
JL
969)
970
971(define_insn "extendhisi2"
972 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=r")
973 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))]
974 ""
546c8f95
JL
975 { msp430x_extendhisi (operands, 0); return ""; }
976 [(set (attr "length")
977 (symbol_ref "msp430x_extendhisi (operands, 1)"))
978 (set_attr "type" "double")]
582b4055
JL
979)
980
981(define_insn "extendhipsi2"
982 [(set (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r")
983 (subreg:PSI (sign_extend:SI (match_operand:HI 1 "general_operand" "0")) 0))]
984 "msp430x"
985 "RLAM.A #4, %0 { RRAM.A #4, %0"
546c8f95
JL
986 [(set_attr "length_multiplier" "2")
987 (set_attr "extension" "m")
988 (set_attr "type" "double")]
582b4055
JL
989)
990
991;; Look for cases where integer/pointer conversions are suboptimal due
992;; to missing patterns, despite us not having opcodes for these
993;; patterns. Doing these manually allows for alternate optimization
994;; paths.
995
996(define_insn "extend_and_shift1_hipsi2"
997 [(set (subreg:SI (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r") 0)
998 (ashift:SI (sign_extend:SI (match_operand:HI 1 "general_operand" "0"))
999 (const_int 1)))]
1000 "msp430x"
1001 "RLAM.A #4, %0 { RRAM.A #3, %0"
546c8f95
JL
1002 [(set_attr "length_multiplier" "2")
1003 (set_attr "extension" "m")
1004 (set_attr "type" "double")]
582b4055
JL
1005)
1006
1007(define_insn "extend_and_shift2_hipsi2"
1008 [(set (subreg:SI (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r") 0)
1009 (ashift:SI (sign_extend:SI (match_operand:HI 1 "general_operand" "0"))
1010 (const_int 2)))]
1011 "msp430x"
1012 "RLAM.A #4, %0 { RRAM.A #2, %0"
546c8f95
JL
1013 [(set_attr "length_multiplier" "2")
1014 (set_attr "extension" "m")
1015 (set_attr "type" "double")]
582b4055
JL
1016)
1017
40ada30a
NC
1018;; We also need to be able to sign-extend pointer types (eg ptrdiff_t).
1019;; Since (we assume) pushing a 20-bit value onto the stack zero-extends
1020;; it, we use a different method here.
1021
1022(define_insn "extendpsisi2"
1023 [(set (match_operand:SI 0 "register_operand" "=r")
1024 (sign_extend:SI (match_operand:PSI 1 "register_operand" "r")))]
c32ab325 1025 "msp430x"
40ada30a
NC
1026 "*
1027 /* The intention here is that we copy the bottom 16-bits of
1028 %1 into %L0 (zeroing the top four bits). Then we copy the
1029 entire 20-bits of %1 into %H0 and then arithmetically shift
1030 it right by 16 bits, to get the top four bits of the pointer
1031 sign-extended in %H0. */
1032 if (REGNO (operands[0]) == REGNO (operands[1]))
d4f283a1 1033 return \"MOVX.A\t%1, %H0 { MOV.W\t%1, %L0 { RPT\t#16 { RRAX.A\t%H0 ; sign extend pointer in %1 into %L0:%H0\";
f6a83b4a 1034 else
d4f283a1 1035 return \"MOV.W\t%1, %L0 { MOVX.A\t%1, %H0 { RPT\t#16 { RRAX.A\t%H0 ; sign extend pointer in %1 into %L0:%H0\";
f6a83b4a 1036 "
546c8f95
JL
1037 [(set_attr "length" "10")
1038 (set_attr "type" "double")]
f6a83b4a
DD
1039)
1040
1041; See the movsipsi2 pattern above for another way that GCC performs this
1042; conversion.
1043(define_insn "truncsipsi2"
1044 [(set (match_operand:PSI 0 "register_operand" "=r")
1045 (truncate:PSI (match_operand:SI 1 "register_operand" "r")))]
1046 ""
d4f283a1 1047 "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A\t#1, %L0"
546c8f95
JL
1048 [(set_attr "length" "6")
1049 (set_attr "type" "single")]
f6a83b4a
DD
1050)
1051
1052;;------------------------------------------------------------
1053;; Shift Functions
1054
1055;; Note: We do not use the RPT ... SHIFT instruction sequence
1056;; when the repeat count is in a register, because even though RPT
1057;; accepts counts in registers, it does not work if the count is
1058;; zero, and the actual count in the register has to be one less
1059;; than the required number of iterations. We could encode a
1060;; seqeunce like this:
1061;;
1062;; bit #0xf, Rn
1063;; bz 1f
1064;; dec Rn
1065;; rpt Rn
1066;; <shift> Rm
1067;; inc Rn
1068;; 1:
1069;;
1070;; But is longer than calling a helper function, and we are mostly
1071;; concerned with code size. FIXME: Maybe enable a sequence like
1072;; this at -O3 and above ?
1073;;
1074;; Note - we ignore shift counts of less than one or more than 15.
1075;; This is permitted by the ISO C99 standard as such shifts result
9c582551 1076;; in "undefined" behavior. [6.5.7 (3)]
703e049a
JL
1077;;
1078;; We avoid emitting insns in msp430_expand_shift, since we would have to handle
1079;; many extra cases such as op0 != op1, or, op0 or op1 in memory. Instead we
1080;; let reload coerce op0 and op1 into the same register.
f6a83b4a 1081
703e049a
JL
1082(define_expand "<shift_insn><mode>3"
1083 [(set (match_operand:HDI 0 "msp430_general_dst_nonv_operand")
1084 (any_shift:HDI (match_operand:HDI 1 "general_operand")
1085 (match_operand:HDI 2 "general_operand")))]
0fcc78f7
JL
1086 ""
1087 {
703e049a
JL
1088 if (msp430_expand_shift (<CODE>, <MODE>mode, operands))
1089 DONE;
1090 /* Otherwise, fallthrough. */
0fcc78f7
JL
1091 }
1092)
1093
703e049a
JL
1094;; All 430 HImode constant shifts
1095(define_insn "<shift_insn>hi3_430"
1096 [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=rm")
1097 (any_shift:HI (match_operand:HI 1 "general_operand" "0")
1098 (match_operand:HI 2 "const_int_operand" "n")))]
1099 "!msp430x"
546c8f95
JL
1100 "* msp430_output_asm_shift_insns (<CODE>, HImode, operands, false); return \"\";"
1101 [(set (attr "length")
1102 (symbol_ref "msp430_output_asm_shift_insns (<CODE>, HImode, operands, true)"))
1103 (set_attr "type" "single")]
f6a83b4a
DD
1104)
1105
703e049a
JL
1106;; All 430 and 430X SImode constant shifts
1107(define_insn "<shift_insn>si3_const"
1108 [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
1109 (any_shift:SI (match_operand:SI 1 "general_operand" "0")
1110 (match_operand:SI 2 "const_int_operand" "n")))]
f6a83b4a 1111 ""
546c8f95
JL
1112 "* msp430_output_asm_shift_insns (<CODE>, SImode, operands, false); return \"\";"
1113 [(set (attr "length")
1114 (symbol_ref "msp430_output_asm_shift_insns (<CODE>, SImode, operands, true)"))
1115 (set_attr "type" "single")]
f6a83b4a
DD
1116)
1117
703e049a
JL
1118(define_insn "ashl<mode>3_430x"
1119 [(set (match_operand:HPSI 0 "msp430_general_dst_nonv_operand" "=r,r,r,r")
1120 (ashift:HPSI (match_operand:HPSI 1 "general_operand" "0 ,0,0,0")
1121 (match_operand:HPSI 2 "const_int_operand" "M ,P,K,i")))]
f6a83b4a 1122 "msp430x"
703e049a
JL
1123 "@
1124 RLAM%b0\t%2, %0
1125 RPT\t%2 { RLAX%b0\t%0
1126 RPT\t#16 { RLAX%b0\t%0 { RPT\t%W2 { RLAX%b0\t%0
1127 # undefined behavior left shift of %1 by %2"
546c8f95
JL
1128 [(set_attr "length" "2,4,8,0")
1129 (set_attr "type" "single")]
f6a83b4a
DD
1130)
1131
703e049a
JL
1132(define_insn "ashr<mode>3_430x"
1133 [(set (match_operand:HPSI 0 "msp430_general_dst_nonv_operand" "=r,r,r,r")
1134 (ashiftrt:HPSI (match_operand:HPSI 1 "general_operand" "0,0,0,0")
1135 (match_operand:HPSI 2 "const_int_operand" "M,P,K,i")))]
f6a83b4a 1136 "msp430x"
703e049a
JL
1137 "@
1138 RRAM%b0\t%2, %0
1139 RPT\t%2 { RRAX%b0\t%0
1140 RPT\t#16 { RRAX%b0\t%0 { RPT\t%W2 { RRAX%b0\t%0
1141 # undefined behavior arithmetic right shift of %1 by %2"
546c8f95
JL
1142 [(set_attr "length" "2,4,8,0")
1143 (set_attr "type" "single")]
f6a83b4a
DD
1144)
1145
703e049a
JL
1146(define_insn "lshr<mode>3_430x"
1147 [(set (match_operand:HPSI 0 "msp430_general_dst_nonv_operand" "=r,r,r,r")
1148 (lshiftrt:HPSI (match_operand:HPSI 1 "general_operand" "0,0,0,0")
1149 (match_operand:HPSI 2 "const_int_operand" "M,P,K,i")))]
f6a83b4a 1150 "msp430x"
703e049a
JL
1151 "@
1152 RRUM%b0\t%2, %0
1153 RPT\t%2 { RRUX%b0\t%0
1154 RPT\t#16 { RRUX%b0\t%0 { RPT\t%W2 { RRUX%b0\t%0
1155 # undefined behavior logical right shift of %1 by %2"
546c8f95
JL
1156 [(set_attr "length" "2,4,8,0")
1157 (set_attr "type" "single")]
0fcc78f7
JL
1158)
1159
f6a83b4a
DD
1160;;------------------------------------------------------------
1161;; Function Entry/Exit
1162
1163(define_expand "prologue"
1164 [(const_int 0)]
1165 ""
1166 "msp430_expand_prologue (); DONE;"
546c8f95 1167)
f6a83b4a
DD
1168
1169(define_expand "epilogue"
1170 [(const_int 0)]
1171 ""
1172 "msp430_expand_epilogue (0); DONE;"
546c8f95 1173)
f6a83b4a 1174
f6a83b4a 1175(define_insn "epilogue_helper"
07432a80 1176 [(set (pc)
546c8f95 1177 (unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_EPILOGUE_HELPER))
07432a80 1178 (return)]
546c8f95 1179 "!msp430x"
fb28dac0 1180 "BR%Q0\t#__mspabi_func_epilog_%J0"
546c8f95
JL
1181 [(set_attr "length" "2")]
1182)
f6a83b4a 1183
f6a83b4a
DD
1184(define_insn "prologue_start_marker"
1185 [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_START_MARKER)]
1186 ""
1187 "; start of prologue"
546c8f95
JL
1188 [(set_attr "length" "0")]
1189)
f6a83b4a
DD
1190
1191(define_insn "prologue_end_marker"
1192 [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_END_MARKER)]
1193 ""
1194 "; end of prologue"
546c8f95
JL
1195 [(set_attr "length" "0")]
1196)
f6a83b4a
DD
1197
1198(define_insn "epilogue_start_marker"
1199 [(unspec_volatile [(const_int 0)] UNS_EPILOGUE_START_MARKER)]
1200 ""
1201 "; start of epilogue"
546c8f95
JL
1202 [(set_attr "length" "0")]
1203)
f6a83b4a 1204
4f50b9ff
DD
1205;; This makes the linker add a call to exit() after the call to main()
1206;; in crt0
1207(define_insn "msp430_refsym_need_exit"
1208 [(unspec_volatile [(const_int 0)] UNS_REFSYM_NEED_EXIT)]
1209 ""
1210 ".refsym\t__crt0_call_exit"
546c8f95
JL
1211 [(set_attr "length" "0")]
1212)
4f50b9ff 1213
f6a83b4a
DD
1214;;------------------------------------------------------------
1215;; Jumps
1216
1217(define_expand "call"
1218 [(call:HI (match_operand 0 "")
40ada30a 1219 (match_operand 1 ""))]
f6a83b4a
DD
1220 ""
1221 ""
1222)
1223
1224(define_insn "call_internal"
fb28dac0 1225 [(call (mem:HI (match_operand 0 "general_operand" "rYci"))
f6a83b4a
DD
1226 (match_operand 1 ""))]
1227 ""
51ac3042 1228 "CALL%Q0\t%0"
546c8f95
JL
1229 [(set_attr "extension" "none")
1230 (set_attr "type" "single")]
f6a83b4a
DD
1231)
1232
1233(define_expand "call_value"
1234 [(set (match_operand 0 "register_operand")
1235 (call:HI (match_operand 1 "general_operand")
1236 (match_operand 2 "")))]
1237 ""
1238 ""
1239)
1240
1241(define_insn "call_value_internal"
1242 [(set (match_operand 0 "register_operand" "=r")
fb28dac0 1243 (call (mem:HI (match_operand 1 "general_operand" "rYci"))
f6a83b4a
DD
1244 (match_operand 2 "")))]
1245 ""
51ac3042 1246 "CALL%Q0\t%1"
546c8f95
JL
1247 [(set_attr "extension" "none")
1248 (set_attr "type" "single")]
f6a83b4a
DD
1249)
1250
8a896995 1251(define_insn "msp430_return"
f6a83b4a
DD
1252 [(return)]
1253 ""
cad055a4 1254 { return msp430_is_interrupt_func () ? "RETI" : (TARGET_LARGE ? "RETA" : "RET"); }
546c8f95 1255 [(set_attr "length" "2")]
f6a83b4a
DD
1256)
1257
1258;; This pattern is NOT, as expected, a return pattern. It's called
1259;; before reload and must only store its operands, and emit a
1260;; placeholder where the epilog needs to be. AFTER reload, the
1261;; placeholder should get expanded into a regular-type epilogue that
1262;; also does the EH return.
1263(define_expand "eh_return"
40ada30a 1264 [(match_operand:HI 0 "")]
f6a83b4a
DD
1265 ""
1266 "msp430_expand_eh_return (operands[0]);
1267 emit_jump_insn (gen_msp430_eh_epilogue ());
1268 emit_barrier ();
1269 DONE;"
1270)
1271
1272;; This is the actual EH epilogue. We emit it in the pattern above,
1273;; before reload, and convert it to a real epilogue after reload.
1274(define_insn_and_split "msp430_eh_epilogue"
1275 [(eh_return)]
1276 ""
1277 "#"
1278 "reload_completed"
1279 [(const_int 0)]
1280 "msp430_expand_epilogue (1); DONE;"
546c8f95
JL
1281 [(set_attr "length" "40")]
1282)
f6a83b4a
DD
1283
1284(define_insn "jump"
1285 [(set (pc)
1286 (label_ref (match_operand 0 "" "")))]
1287 ""
51ac3042 1288 "BR%Q0\t#%l0"
546c8f95 1289 [(set_attr "length" "4")]
f6a83b4a
DD
1290)
1291
1292;; FIXME: GCC currently (8/feb/2013) cannot handle symbol_refs
1293;; in indirect jumps (cf gcc.c-torture/compile/991213-3.c).
1294(define_insn "indirect_jump"
1295 [(set (pc)
1296 (match_operand 0 "nonimmediate_operand" "rYl"))]
1297 ""
51ac3042 1298 "BR%Q0\t%0"
546c8f95
JL
1299 [(set (attr "length")
1300 (if_then_else (match_operand 0 "register_operand" "")
1301 (const_int 2)
1302 (const_int 4)))]
f6a83b4a
DD
1303)
1304
1305;;------------------------------------------------------------
1306;; Various Conditionals
1307
1308(define_expand "cbranch<mode>4"
1309 [(parallel [(set (pc) (if_then_else
1310 (match_operator 0 ""
6ff8ab6a 1311 [(match_operand:QHI 1 "msp430_general_dst_nonv_operand")
f6a83b4a
DD
1312 (match_operand:QHI 2 "general_operand")])
1313 (label_ref (match_operand 3 "" ""))
1314 (pc)))
1315 (clobber (reg:BI CARRY))]
1316 )]
1317 ""
1318 "msp430_fixup_compare_operands (<MODE>mode, operands);"
546c8f95 1319)
f6a83b4a
DD
1320
1321(define_insn "cbranchpsi4_real"
1322 [(set (pc) (if_then_else
1323 (match_operator 0 "msp430_cmp_operator"
6ff8ab6a 1324 [(match_operand:PSI 1 "msp430_general_dst_nonv_operand" "r,rYs,rm")
f6a83b4a 1325 (match_operand:PSI 2 "general_operand" "rLs,rYsi,rmi")])
546c8f95 1326 (label_ref (match_operand 3 "" ""))
f6a83b4a
DD
1327 (pc)))
1328 (clobber (reg:BI CARRY))
1329 ]
1330 ""
1331 "@
51ac3042 1332 CMP%Q0\t%2, %1 { J%0\t%l3
f6a83b4a
DD
1333 CMPX.A\t%2, %1 { J%0\t%l3
1334 CMPX.A\t%2, %1 { J%0\t%l3"
546c8f95
JL
1335 [(set_attr "extra_length" "2")
1336 (set_attr "type" "cmp")]
1337)
f6a83b4a
DD
1338
1339(define_insn "cbranchqi4_real"
1340 [(set (pc) (if_then_else
1341 (match_operator 0 "msp430_cmp_operator"
6ff8ab6a 1342 [(match_operand:QI 1 "msp430_general_dst_nonv_operand" "rYsYx,rm")
8682b1a5 1343 (match_operand:QI 2 "general_operand" "rYsYxi,rmi")])
f6a83b4a
DD
1344 (label_ref (match_operand 3 "" ""))
1345 (pc)))
1346 (clobber (reg:BI CARRY))
1347 ]
1348 ""
1349 "@
1350 CMP.B\t%2, %1 { J%0\t%l3
8682b1a5 1351 CMPX.B\t%2, %1 { J%0\t%l3"
546c8f95
JL
1352 [(set_attr "extra_length" "2")
1353 (set_attr "type" "cmp")]
1354)
f6a83b4a
DD
1355
1356(define_insn "cbranchhi4_real"
1357 [(set (pc) (if_then_else
1358 (match_operator 0 "msp430_cmp_operator"
6ff8ab6a 1359 [(match_operand:HI 1 "msp430_general_dst_nonv_operand" "rYsYx,rm")
8682b1a5 1360 (match_operand:HI 2 "general_operand" "rYsYxi,rmi")])
f6a83b4a
DD
1361 (label_ref (match_operand 3 "" ""))
1362 (pc)))
1363 (clobber (reg:BI CARRY))
1364 ]
1365 ""
b4ca70a3
JL
1366 "@
1367 CMP.W\t%2, %1 { J%0\t%l3
1368 CMPX.W\t%2, %1 { J%0\t%l3"
546c8f95
JL
1369 [(set_attr "extra_length" "2")
1370 (set_attr "type" "cmp")]
b4ca70a3 1371)
f6a83b4a
DD
1372
1373(define_insn "cbranchpsi4_reversed"
1374 [(set (pc) (if_then_else
1375 (match_operator 0 "msp430_reversible_cmp_operator"
1376 [(match_operand:PSI 1 "general_operand" "rLs,rYsi,rmi")
6ff8ab6a 1377 (match_operand:PSI 2 "msp430_general_dst_nonv_operand" "r,rYs,rm")])
f6a83b4a
DD
1378 (label_ref (match_operand 3 "" ""))
1379 (pc)))
1380 (clobber (reg:BI CARRY))
1381 ]
1382 ""
1383 "@
51ac3042 1384 CMP%Q0\t%1, %2 { J%R0\t%l3
f6a83b4a
DD
1385 CMPX.A\t%1, %2 { J%R0\t%l3
1386 CMPX.A\t%1, %2 { J%R0\t%l3"
546c8f95
JL
1387 [(set_attr "extra_length" "2")
1388 (set_attr "type" "cmp")]
1389)
f6a83b4a
DD
1390
1391(define_insn "cbranchqi4_reversed"
1392 [(set (pc) (if_then_else
1393 (match_operator 0 "msp430_reversible_cmp_operator"
8682b1a5 1394 [(match_operand:QI 1 "general_operand" "rYsYxi,rmi")
6ff8ab6a 1395 (match_operand:QI 2 "msp430_general_dst_nonv_operand" "rYsYx,rm")])
f6a83b4a
DD
1396 (label_ref (match_operand 3 "" ""))
1397 (pc)))
1398 (clobber (reg:BI CARRY))
1399 ]
1400 ""
1401 "@
1402 CMP.B\t%1, %2 { J%R0\t%l3
8682b1a5 1403 CMPX.B\t%1, %2 { J%R0\t%l3"
546c8f95
JL
1404 [(set_attr "extra_length" "2")
1405 (set_attr "type" "cmp")]
1406)
f6a83b4a
DD
1407
1408(define_insn "cbranchhi4_reversed"
1409 [(set (pc) (if_then_else
1410 (match_operator 0 "msp430_reversible_cmp_operator"
8682b1a5 1411 [(match_operand:HI 1 "general_operand" "rYsYxi,rmi")
6ff8ab6a 1412 (match_operand:HI 2 "msp430_general_dst_nonv_operand" "rYsYx,rm")])
f6a83b4a
DD
1413 (label_ref (match_operand 3 "" ""))
1414 (pc)))
1415 (clobber (reg:BI CARRY))
1416 ]
1417 ""
1418 "@
1419 CMP.W\t%1, %2 { J%R0\t%l3
8682b1a5 1420 CMPX.W\t%1, %2 { J%R0\t%l3"
546c8f95
JL
1421 [(set_attr "extra_length" "2")
1422 (set_attr "type" "cmp")]
1423)
f6a83b4a 1424
f6a83b4a
DD
1425(define_insn "*bitbranch<mode>4"
1426 [(set (pc) (if_then_else
28987d8b 1427 (ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
8a896995 1428 (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
f6a83b4a 1429 (const_int 0))
546c8f95 1430 (label_ref (match_operand 2 "" ""))
f6a83b4a
DD
1431 (pc)))
1432 (clobber (reg:BI CARRY))
1433 ]
1434 ""
1435 "@
51ac3042 1436 BIT%x0%b0\t%1, %0 { JNE\t%l2
8682b1a5 1437 BITX%b0\t%1, %0 { JNE\t%l2"
546c8f95
JL
1438 [(set_attr "extra_length" "2")
1439 (set_attr "type" "double")]
1440)
f6a83b4a
DD
1441
1442(define_insn "*bitbranch<mode>4"
1443 [(set (pc) (if_then_else
28987d8b 1444 (eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
8a896995 1445 (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
f6a83b4a 1446 (const_int 0))
546c8f95 1447 (label_ref (match_operand 2 "" ""))
f6a83b4a
DD
1448 (pc)))
1449 (clobber (reg:BI CARRY))
1450 ]
1451 ""
8682b1a5
JL
1452 "@
1453 BIT%x0%b0\t%1, %0 { JEQ\t%l2
1454 BITX%b0\t%1, %0 { JEQ\t%l2"
546c8f95
JL
1455 [(set_attr "extra_length" "2")
1456 (set_attr "type" "double")]
1457)
f6a83b4a
DD
1458
1459(define_insn "*bitbranch<mode>4"
1460 [(set (pc) (if_then_else
28987d8b 1461 (eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
8a896995 1462 (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
f6a83b4a 1463 (const_int 0))
546c8f95 1464 (pc)
f6a83b4a
DD
1465 (label_ref (match_operand 2 "" ""))))
1466 (clobber (reg:BI CARRY))
1467 ]
1468 ""
8682b1a5
JL
1469 "@
1470 BIT%x0%b0\t%1, %0 { JNE\t%l2
1471 BITX%b0\t%1, %0 { JNE\t%l2"
546c8f95
JL
1472 [(set_attr "extra_length" "2")
1473 (set_attr "type" "double")]
1474)
f6a83b4a
DD
1475
1476(define_insn "*bitbranch<mode>4"
1477 [(set (pc) (if_then_else
28987d8b 1478 (ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
8a896995 1479 (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
f6a83b4a 1480 (const_int 0))
546c8f95 1481 (pc)
f6a83b4a
DD
1482 (label_ref (match_operand 2 "" ""))))
1483 (clobber (reg:BI CARRY))
1484 ]
1485 ""
8682b1a5
JL
1486 "@
1487 BIT%x0%b0\t%1, %0 { JEQ\t%l2
1488 BITX%b0\t%1, %0 { JEQ\t%l2"
546c8f95
JL
1489 [(set_attr "extra_length" "2")
1490 (set_attr "type" "double")]
1491)
f6a83b4a
DD
1492
1493;;------------------------------------------------------------
cad055a4 1494;; zero-extract versions of the above
f6a83b4a
DD
1495
1496(define_insn "*bitbranch<mode>4_z"
1497 [(set (pc) (if_then_else
28987d8b 1498 (ne (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rYs,rm")
f6a83b4a 1499 (const_int 1)
703e049a 1500 (match_operand 1 "const_0_to_15_operand" "i,i"))
f6a83b4a 1501 (const_int 0))
546c8f95 1502 (label_ref (match_operand 2 "" ""))
f6a83b4a
DD
1503 (pc)))
1504 (clobber (reg:BI CARRY))
1505 ]
1506 ""
1507 "@
51ac3042
NC
1508 BIT%x0%b0\t%p1, %0 { JNE\t%l2
1509 BIT%X0%b0\t%p1, %0 { JNE\t%l2"
546c8f95
JL
1510 [(set_attr "extra_length" "2")
1511 (set_attr "type" "double")]
1512)
f6a83b4a
DD
1513
1514(define_insn "*bitbranch<mode>4_z"
1515 [(set (pc) (if_then_else
28987d8b 1516 (eq (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm")
f6a83b4a 1517 (const_int 1)
703e049a 1518 (match_operand 1 "const_0_to_15_operand" "i"))
f6a83b4a 1519 (const_int 0))
546c8f95 1520 (label_ref (match_operand 2 "" ""))
f6a83b4a
DD
1521 (pc)))
1522 (clobber (reg:BI CARRY))
1523 ]
1524 ""
8682b1a5 1525 "BIT%X0%b0\t%p1, %0 { JEQ\t%l2"
546c8f95
JL
1526 [(set_attr "extra_length" "2")
1527 (set_attr "type" "double")]
1528)
f6a83b4a
DD
1529
1530(define_insn "*bitbranch<mode>4_z"
1531 [(set (pc) (if_then_else
28987d8b 1532 (eq (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm")
f6a83b4a 1533 (const_int 1)
703e049a 1534 (match_operand 1 "const_0_to_15_operand" "i"))
f6a83b4a 1535 (const_int 0))
546c8f95 1536 (pc)
f6a83b4a
DD
1537 (label_ref (match_operand 2 "" ""))))
1538 (clobber (reg:BI CARRY))
1539 ]
1540 ""
51ac3042 1541 "BIT%X0%b0\t%p1, %0 { JNE\t%l2"
546c8f95
JL
1542 [(set_attr "extra_length" "2")
1543 (set_attr "type" "double")]
1544)
f6a83b4a
DD
1545
1546(define_insn "*bitbranch<mode>4_z"
1547 [(set (pc) (if_then_else
28987d8b 1548 (ne (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm")
f6a83b4a 1549 (const_int 1)
703e049a 1550 (match_operand 1 "const_0_to_15_operand" "i"))
f6a83b4a 1551 (const_int 0))
546c8f95 1552 (pc)
f6a83b4a
DD
1553 (label_ref (match_operand 2 "" ""))))
1554 (clobber (reg:BI CARRY))
1555 ]
1556 ""
51ac3042 1557 "BIT%X0%b0\t%p1, %0 { JEQ\t%l2"
546c8f95
JL
1558 [(set_attr "extra_length" "2")
1559 (set_attr "type" "double")]
1560)
f6a83b4a
DD
1561
1562;;------------------------------------------------------------
1563;; Misc
1564
1565(define_insn "nop"
1566 [(const_int 0)]
1567 "1"
1568 "NOP"
546c8f95 1569 [(set_attr "length" "2")]
f6a83b4a 1570)
a005b5be 1571
cad055a4
NC
1572(define_insn "disable_interrupts"
1573 [(unspec_volatile [(const_int 0)] UNS_DINT)]
1574 ""
a005b5be 1575 "DINT \; NOP"
546c8f95
JL
1576 [(set_attr "length" "2")]
1577)
cad055a4
NC
1578
1579(define_insn "enable_interrupts"
1580 [(unspec_volatile [(const_int 0)] UNS_EINT)]
1581 ""
1582 "EINT"
546c8f95
JL
1583 [(set_attr "length" "2")]
1584)
cad055a4
NC
1585
1586(define_insn "push_intr_state"
1587 [(unspec_volatile [(const_int 0)] UNS_PUSH_INTR)]
1588 ""
1589 "PUSH\tSR"
546c8f95
JL
1590 [(set_attr "length" "2")]
1591)
cad055a4
NC
1592
1593(define_insn "pop_intr_state"
1594 [(unspec_volatile [(const_int 0)] UNS_POP_INTR)]
1595 ""
1596 "POP\tSR"
546c8f95
JL
1597 [(set_attr "length" "2")]
1598)
cad055a4
NC
1599
1600;; Clear bits in the copy of the status register that is currently
1601;; saved on the stack at the top of the interrupt handler.
1602(define_insn "bic_SR"
1603 [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIC_SR)]
1604 ""
1605 "BIC.W\t%0, %O0(SP)"
546c8f95
JL
1606 [(set_attr "type" "single")
1607 (set_attr "extra_length" "2")]
1608)
cad055a4
NC
1609
1610;; Set bits in the copy of the status register that is currently
1611;; saved on the stack at the top of the interrupt handler.
1612(define_insn "bis_SR"
1613 [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIS_SR)]
1614 ""
1615 "BIS.W\t%0, %O0(SP)"
546c8f95
JL
1616 [(set_attr "type" "single")
1617 (set_attr "extra_length" "2")]
1618)
40ada30a
NC
1619
1620;; For some reason GCC is generating (set (reg) (and (neg (reg)) (int)))
1621;; very late on in the compilation and not splitting it into separate
1622;; instructions, so we provide a pattern to support it here.
1623(define_insn "andneghi3"
546c8f95
JL
1624 [(set (match_operand:HI 0 "register_operand" "=r,r")
1625 (and:HI (neg:HI (match_operand:HI 1 "general_operand" "0,rm"))
1626 (match_operand 2 "immediate_operand" "n,n")))]
40ada30a 1627 ""
546c8f95
JL
1628 "@
1629 INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0
1630 MOV%X1.W\t%1, %0 { INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0"
1631 [(set_attr "length" "12,14")
1632 (set_attr "type" "double")]
1633)
1634
c6f709ec 1635
5f35dde5
DD
1636(define_insn "delay_cycles_start"
1637 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
1638 UNS_DELAY_START)]
1639 ""
1640 "; Begin %J0 cycle delay"
546c8f95
JL
1641 [(set_attr "length" "0")]
1642)
5f35dde5
DD
1643
1644(define_insn "delay_cycles_end"
1645 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
1646 UNS_DELAY_END)]
1647 ""
1648 "; End %J0 cycle delay"
1649 )
1650
1651(define_insn "delay_cycles_32"
1652 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1653 (match_operand 1 "immediate_operand" "i")
1654 ] UNS_DELAY_32)]
1655 ""
1656 "PUSH r13
1657 PUSH r14
1658 MOV.W %A0, r13
1659 MOV.W %B0, r14
16601: SUB.W #1, r13
1661 SUBC.W #0, r14
1662 JNE 1b
1663 TST.W r13
1664 JNE 1b
1665 POP r14
1666 POP r13"
546c8f95
JL
1667 [(set_attr "length" "32")]
1668)
5f35dde5
DD
1669
1670(define_insn "delay_cycles_32x"
1671 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1672 (match_operand 1 "immediate_operand" "i")
1673 ] UNS_DELAY_32X)]
1674 ""
47f138d1 1675 "PUSHM.A #2,r14
5f35dde5
DD
1676 MOV.W %A0, r13
1677 MOV.W %B0, r14
16781: SUB.W #1, r13
1679 SUBC.W #0, r14
1680 JNE 1b
1681 TST.W r13
1682 JNE 1b
47f138d1 1683 POPM.A #2,r14"
546c8f95
JL
1684 [(set_attr "length" "28")]
1685)
5f35dde5
DD
1686
1687(define_insn "delay_cycles_16"
1688 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1689 (match_operand 1 "immediate_operand" "i")
1690 ] UNS_DELAY_16)]
1691 ""
1692 "PUSH r13
1693 MOV.W %0, r13
16941: SUB.W #1, r13
1695 JNE 1b
1696 POP r13"
546c8f95
JL
1697 [(set_attr "length" "14")]
1698)
5f35dde5
DD
1699
1700(define_insn "delay_cycles_16x"
1701 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
1702 (match_operand 1 "immediate_operand" "i")
1703 ] UNS_DELAY_16X)]
1704 ""
1705 "PUSHM.A #1,r13
1706 MOV.W %0, r13
17071: SUB.W #1, r13
1708 JNE 1b
1709 POPM.A #1,r13"
546c8f95
JL
1710 [(set_attr "length" "14")]
1711)
5f35dde5
DD
1712
1713(define_insn "delay_cycles_2"
1714 [(unspec_volatile [(const_int 0) ] UNS_DELAY_2)]
1715 ""
1716 "JMP .+2"
546c8f95
JL
1717 [(set_attr "length" "2")]
1718)
5f35dde5
DD
1719
1720(define_insn "delay_cycles_1"
1721 [(unspec_volatile [(const_int 0) ] UNS_DELAY_1)]
1722 ""
1723 "NOP"
546c8f95
JL
1724 [(set_attr "length" "2")]
1725)
5f35dde5 1726
499a39af
JL
1727; libgcc helper functions for widening multiplication aren't currently
1728; generated by gcc, so we can't catch them later and map them to the mspabi
1729; functions.
1730; We catch the patterns here and either generate a call to the helper function,
1731; or emit the hardware multiply instruction sequence inline.
1732;
1733; If we don't have hardware multiply support, it will generally be slower and
1734; result in larger code to call the mspabi library function to perform the
1735; widening multiplication than just leaving GCC to widen the arguments itself.
1736;
1737; We don't use library functions for SImode->DImode widening since its always
1738; larger and slower than letting GCC widen the arguments inline.
1739(define_expand "mulhisi3"
1740 [(set (match_operand:SI 0 "register_operand" "=r")
1741 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1742 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
1743 "msp430_has_hwmult ()"
1744 {
1745 /* Leave the other case for the inline insn. */
1746 if (!(optimize > 2 && msp430_has_hwmult ()))
1747 {
1748 msp430_expand_helper (operands, "__mspabi_mpysl", false);
1749 DONE;
1750 }
1751 }
1752)
1753
1754(define_expand "umulhisi3"
1755 [(set (match_operand:SI 0 "register_operand" "=r")
1756 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1757 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
1758 "msp430_has_hwmult ()"
1759 {
1760 /* Leave the other case for the inline insn. */
1761 if (!(optimize > 2 && msp430_has_hwmult ()))
1762 {
1763 msp430_expand_helper (operands, "__mspabi_mpyul", false);
1764 DONE;
1765 }
1766 }
1767)
1768
1769(define_insn "*mulhisi3_inline"
c6f709ec
NC
1770 [(set (match_operand:SI 0 "register_operand" "=r")
1771 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1772 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
0744333e 1773 "optimize > 2 && msp430_has_hwmult ()"
c6f709ec 1774 "*
f7961364 1775 if (msp430_use_f5_series_hwmult ())
ba3cf9f1 1776 return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x04C2 { MOV.W %2, &0x04C8 { MOV.W &0x04CA, %L0 { MOV.W &0x04CC, %H0 { POP.W sr\";
c6f709ec 1777 else
ba3cf9f1 1778 return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x0132 { MOV.W %2, &0x0138 { MOV.W &0x013A, %L0 { MOV.W &0x013C, %H0 { POP.W sr\";
c6f709ec 1779 "
546c8f95 1780 [(set_attr "length" "24")]
c6f709ec
NC
1781)
1782
499a39af 1783(define_insn "*umulhisi3_inline"
c6f709ec
NC
1784 [(set (match_operand:SI 0 "register_operand" "=r")
1785 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1786 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
0744333e 1787 "optimize > 2 && msp430_has_hwmult ()"
c6f709ec 1788 "*
f7961364 1789 if (msp430_use_f5_series_hwmult ())
ba3cf9f1 1790 return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x04C0 { MOV.W %2, &0x04C8 { MOV.W &0x04CA, %L0 { MOV.W &0x04CC, %H0 { POP.W sr\";
c6f709ec 1791 else
ba3cf9f1 1792 return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x0130 { MOV.W %2, &0x0138 { MOV.W &0x013A, %L0 { MOV.W &0x013C, %H0 { POP.W sr\";
c6f709ec 1793 "
546c8f95 1794 [(set_attr "length" "24")]
c6f709ec
NC
1795)
1796
1797(define_insn "mulsidi3"
1798 [(set (match_operand:DI 0 "register_operand" "=r")
1799 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
1800 (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
0744333e 1801 "optimize > 2 && msp430_has_hwmult ()"
c6f709ec 1802 "*
f7961364 1803 if (msp430_use_f5_series_hwmult ())
ba3cf9f1 1804 return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x04D4 { MOV.W %H1, &0x04D6 { MOV.W %L2, &0x04E0 { MOV.W %H2, &0x04E2 { MOV.W &0x04E4, %A0 { MOV.W &0x04E6, %B0 { MOV.W &0x04E8, %C0 { MOV.W &0x04EA, %D0 { POP.W sr\";
c6f709ec 1805 else
ba3cf9f1 1806 return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x0144 { MOV.W %H1, &0x0146 { MOV.W %L2, &0x0150 { MOV.W %H2, &0x0152 { MOV.W &0x0154, %A0 { MOV.W &0x0156, %B0 { MOV.W &0x0158, %C0 { MOV.W &0x015A, %D0 { POP.W sr\";
c6f709ec 1807 "
546c8f95 1808 [(set_attr "length" "40")]
c6f709ec
NC
1809)
1810
1811(define_insn "umulsidi3"
1812 [(set (match_operand:DI 0 "register_operand" "=r")
1813 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
1814 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
0744333e 1815 "optimize > 2 && msp430_has_hwmult ()"
c6f709ec 1816 "*
f7961364 1817 if (msp430_use_f5_series_hwmult ())
ba3cf9f1 1818 return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x04D0 { MOV.W %H1, &0x04D2 { MOV.W %L2, &0x04E0 { MOV.W %H2, &0x04E2 { MOV.W &0x04E4, %A0 { MOV.W &0x04E6, %B0 { MOV.W &0x04E8, %C0 { MOV.W &0x04EA, %D0 { POP.W sr\";
c6f709ec 1819 else
ba3cf9f1 1820 return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x0140 { MOV.W %H1, &0x0142 { MOV.W %L2, &0x0150 { MOV.W %H2, &0x0152 { MOV.W &0x0154, %A0 { MOV.W &0x0156, %B0 { MOV.W &0x0158, %C0 { MOV.W &0x015A, %D0 { POP.W sr\";
c6f709ec 1821 "
546c8f95 1822 [(set_attr "length" "40")]
c6f709ec 1823)