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