Add hppa*-*-hpux* to targets which do not support split DWARF
[official-gcc.git] / gcc / config / msp430 / msp430.md
blob375e231b661c71469901377ce954e868353477c0
1 ;;  Machine Description for TI MSP43* processors
2 ;;  Copyright (C) 2013-2024 Free Software Foundation, Inc.
3 ;;  Contributed by Red Hat.
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
12 ;; GCC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>.
22 (define_constants
23   [
24    (PC_REGNO 0)
25    (SP_REGNO 1)
26    (CARRY 2)
27   ])
29 (define_c_enum "unspec"
30   [
31    UNS_PROLOGUE_START_MARKER
32    UNS_PROLOGUE_END_MARKER
33    UNS_EPILOGUE_START_MARKER
34    UNS_EPILOGUE_HELPER
36    UNS_PUSHM
37    UNS_POPM
39    UNS_GROW_AND_SWAP
40    UNS_SWAP_AND_SHRINK
41    
42    UNS_DINT
43    UNS_EINT
44    UNS_PUSH_INTR
45    UNS_POP_INTR
46    UNS_BIC_SR
47    UNS_BIS_SR
49    UNS_REFSYM_NEED_EXIT
51    UNS_DELAY_32
52    UNS_DELAY_32X
53    UNS_DELAY_16
54    UNS_DELAY_16X
55    UNS_DELAY_2
56    UNS_DELAY_1
57    UNS_DELAY_START
58    UNS_DELAY_END
59   ])
61 ;; 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.
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"))
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")))
106 ;; Multiply the default length by this constant value.
107 (define_attr "length_multiplier" "" (const_int 1))
109 ;; Add an additional amount to the total length of the insn.
110 (define_attr "extra_length" "" (const_int 0))
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)))
156 (include "predicates.md")
157 (include "constraints.md")
159 (define_mode_iterator QHI [QI HI PSI])
160 (define_mode_iterator HPSI [HI PSI])
161 (define_mode_iterator HDI [HI PSI SI DI])
163 ;; Mapping of all shift operators
164 (define_code_iterator any_shift [ashift ashiftrt lshiftrt])
166 ;; Base name for define_insn
167 (define_code_attr shift_insn
168   [(ashift "ashl") (lshiftrt "lshr") (ashiftrt "ashr")])
170 ;; There are two basic "family" tests we do here:
172 ;; msp430x - true if 430X instructions are available.
173 ;; TARGET_LARGE - true if pointers are 20-bits
175 ;; Note that there are three supported cases, since the base 430
176 ;; doesn't have 20-bit pointers:
178 ;; 1. MSP430 cpu, small model
179 ;; 2. MSP430X cpu, small model.
180 ;; 3. MSP430X cpu, large model.
182 ;;------------------------------------------------------------
183 ;; Moves
185 ;; Push/Pop must be before the generic move patterns
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"
192   [(set_attr "type" "single")]
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"
200   [(set_attr "type" "single")
201    (set_attr "extension" "x")]
204 (define_insn "pushm"
205   [(unspec_volatile [(match_operand 0 "register_operand" "r")
206                      (match_operand 1 "immediate_operand" "n")] UNS_PUSHM)]
207   ""
208   "PUSHM%b0\t%1, %0"
209   [(set_attr "type" "single")
210    (set_attr "extension" "m")]
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"
218   [(set_attr "type" "single")]
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"
226   [(set_attr "type" "single")
227    (set_attr "extension" "x")]
230 ;; This is nasty.  Operand0 is bogus.  It is only there so that we can get a
231 ;; mode for the %b0 to work.  We should use operand1 for this, but that does
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
237 ;; fudge it to be a register name when we generate the assembler.
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   ""
246   "POPM%b0\t%2, r%J1"
247   [(set_attr "type" "single")
248    (set_attr "extension" "m")]
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).
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.
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.
267 (define_insn "grow_and_swap"
268   [(unspec_volatile [(const_int 0)] UNS_GROW_AND_SWAP)]
269   ""
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   "
275   [(set (attr "length")
276         (if_then_else (match_test "TARGET_LARGE")
277                       (const_int 8)
278                       (const_int 6)))]
281 (define_insn "swap_and_shrink"
282   [(unspec_volatile [(const_int 0)] UNS_SWAP_AND_SHRINK)]
283   ""
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\";
287   "
288   [(set (attr "length")
289         (if_then_else (match_test "TARGET_LARGE")
290                       (const_int 10)
291                       (const_int 8)))]
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"
303   [(set_attr "type" "double")]
306 (define_insn "movqi_topbyte"
307   [(set (match_operand:QI 0 "msp430_general_dst_operand" "=r")
308         (subreg:QI (match_operand:PSI 1 "msp430_general_operand" "r") 2))]
309   "msp430x"
310   "PUSHM.A\t#1,%1 { POPM.W\t#1,%0 { POPM.W\t#1,%0"
311   [(set_attr "length" "6")
312    (set_attr "type" "double")]
315 (define_insn "movqi"
316   [(set (match_operand:QI 0 "msp430_general_dst_operand" "=rYsYx,rm")
317         (match_operand:QI 1 "msp430_general_operand" "riYsYx,rmi"))]
318   ""
319   "@
320   MOV.B\t%1, %0
321   MOVX.B\t%1, %0"
322   [(set_attr "type" "double")]
325 (define_insn "movhi"
326   [(set (match_operand:HI 0 "msp430_general_dst_operand" "=r,rYsYx,rm")
327         (match_operand:HI 1 "msp430_general_operand" "N,riYsYx,rmi"))]
328   ""
329   "@
330   MOV.B\t%1, %0
331   MOV.W\t%1, %0
332   MOVX.W\t%1, %0"
333   [(set_attr "type" "double")]
336 (define_expand "movsi"
337   [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand")
338         (match_operand:SI 1 "general_operand"))]
339   ""
340   ""
343 (define_insn_and_split "movsi_s"
344   [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
345         (subreg:SI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))]
346   ""
347   ""
348   "reload_completed"
349   [(set (match_operand:HI 2 "msp430_general_dst_nonv_operand")
350         (match_operand:HI 4 "general_operand"))
351    (set (match_operand:HI 3 "msp430_general_dst_nonv_operand")
352         (match_operand:HI 5 "general_operand"))]
353   "msp430_split_movsi (operands);"
354   [(set_attr "type" "double")]
357 (define_insn_and_split "movsi_x"
358   [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm")
359         (match_operand:SI 1 "general_operand" "rmi"))]
360   ""
361   "#"
362   "reload_completed"
363   [(set (match_operand:HI 2 "msp430_general_dst_nonv_operand")
364         (match_operand:HI 4 "general_operand"))
365    (set (match_operand:HI 3 "msp430_general_dst_nonv_operand")
366         (match_operand:HI 5 "general_operand"))]
367   "msp430_split_movsi (operands);"
368   [(set_attr "type" "double")]
371 ;; FIXME: Some MOVX.A cases can be done with MOVA, this is only a few of them.
372 (define_insn "movpsi"
373   [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,r,r,Ya,rm")
374         (match_operand:PSI 1 "msp430_general_operand" "N,O,riYa,r,rmi"))]
375   ""
376   "@
377   MOV.B\t%1, %0
378   MOV.W\t%1, %0
379   MOVA\t%1, %0
380   MOVA\t%1, %0
381   MOVX.A\t%1, %0"
382   [(set_attr "extension" "none,none,a,a,x")
383    (set_attr "type" "double")]
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)).
391 ; Note: using POPM.A #1 is two bytes smaller than using POPX.A....
393 (define_insn "movsipsi2"
394   [(set (match_operand:PSI            0 "register_operand" "=r")
395         (subreg:PSI (match_operand:SI 1 "register_operand" "r") 0))]
396   "msp430x"
397   "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A #1, %0 ; Move reg-pair %L1:%H1 into pointer %0"
398   [(set_attr "length" "6")
399    (set_attr "type" "double")]
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"
408   [(set_attr "extension" "a")
409    (set_attr "type" "double")]
412 ;;------------------------------------------------------------
413 ;; Math
415 (define_insn "addpsi3"
416   [(set (match_operand:PSI           0 "msp430_general_dst_operand" "=r,rm")
417         (plus:PSI (match_operand:PSI 1 "msp430_general_operand" "%0,0")
418                   (match_operand:PSI 2 "msp430_general_operand"      "rLs,rmi")))]
419   ""
420   "@
421   ADDA\t%2, %0
422   ADDX.A\t%2, %0"
423   [(set_attr "extension" "a,x")
424    (set_attr "type" "triple")]
427 (define_insn "addqi3"
428   [(set (match_operand:QI          0 "msp430_general_dst_operand" "=rYsYx,rm")
429         (plus:QI (match_operand:QI 1 "msp430_general_operand" "%0,0")
430                  (match_operand:QI 2 "msp430_general_operand"      "riYsYx,rmi")))]
431   ""
432   "@
433    ADD.B\t%2, %0
434    ADDX.B\t%2, %0"
435   [(set_attr "type" "triple")]
438 (define_insn "addhi3"
439   [(set (match_operand:HI           0 "msp430_general_dst_operand" "=rYsYx,rm")
440         (plus:HI (match_operand:HI  1 "msp430_general_operand" "%0,0")
441                   (match_operand:HI 2 "msp430_general_operand"      "riYsYx,rmi")))]
442   ""
443   "@
444    ADD.W\t%2, %0
445    ADDX.W\t%2, %0"
446   [(set_attr "type" "triple")]
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.
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   ""
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"
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")]
468 (define_insn "addsi3"
469   [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=&rYsYx,rm")
470         (plus:SI (match_operand:SI 1 "general_operand" "%0,0")
471                  (match_operand:SI 2 "general_operand" "rYsYxi,mi")))]
472   ""
473   "@
474    ADD\t%L2, %L0 { ADDC\t%H2, %H0
475    ADDX\t%L2, %L0 { ADDCX\t%H2, %H0"
476   [(set_attr "length_multiplier" "2")
477    (set_attr "type" "triple")]
480 ; Version of addhi that exposes the carry operations, for SImode adds.
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.
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.
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.
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
510 (define_insn "addhi3_cy"
511   [(set (match_operand:HI          0 "msp430_general_dst_operand" "=rYsYx,rm")
512         (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0")
513                  (match_operand:HI 2 "msp430_nonimmediate_operand" "rYsYxi,rm")))
514    (set (reg:BI CARRY)
515         (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
516                                            (zero_extend:SI (match_operand:HI 3 "msp430_nonimmediate_operand" "rYsYxi,rm")))
517                                   (const_int 16))))
518    ]
519   ""
520   "@
521    ADD\t%2, %1 ; cy
522    ADDX\t%2, %1 ; cy"
523   [(set_attr "type" "triple")]
526 (define_insn "addhi3_cy_i"
527   [(set (match_operand:HI          0 "msp430_general_dst_nonv_operand" "=r,rm")
528         (plus:HI (match_operand:HI 1 "general_operand" "%0,0")
529                  (match_operand:HI 2 "immediate_operand"     "i,i")))
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   "@
537    ADD\t%2, %1 ; cy
538    ADD%X0\t%2, %1 ; cy"
539   [(set_attr "type" "triple")]
542 ; Version of addhi that adds the carry, for SImode adds.
543 (define_insn "addchi4_cy"
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")
546                           (match_operand:HI 2 "msp430_general_operand"      "riYsYx,rmi"))
547                  (zero_extend:HI (reg:BI CARRY))))
548    ]
549   ""
550   "@
551    ADDC\t%2, %1
552    ADDCX\t%2, %1"
553   [(set_attr "type" "triple")]
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.
559 ; We use the ugly predicate "msp430_nonsubregnonpostinc_or_imm_operand" to
560 ; enforce the position of a post_inc into op2 if present
561 (define_split
562   [(set (match_operand:SI          0 "msp430_nonsubreg_dst_operand")
563         (plus:SI (match_operand:SI 1 "msp430_nonsubregnonpostinc_or_imm_operand")
564                  (match_operand:SI 2 "msp430_nonsubreg_or_imm_operand")))
565    ]
566   ""
567   [(parallel [(set (match_operand:HI 3 "msp430_general_dst_nonv_operand" "=&rm")
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               ])
575    (set (match_operand:HI 6 "msp430_general_dst_nonv_operand" "=&rm")
576         (plus:HI (plus:HI (match_dup 7)
577                           (match_dup 8))
578                  (zero_extend:HI (reg:BI CARRY))))
579    ]
580   "
581   if (msp430_split_addsi (operands))
582     FAIL;
583   "
587 ;; Alternatives 2 and 3 are to handle cases generated by reload.
588 (define_insn "subpsi3"
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")))]
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"
598   [(set_attr "type" "triple")
599    (set_attr "extension" "a,x,x,x")
600    (set_attr "length_multiplier" "1,1,2,2")]
603 ;; Alternatives 2 and 3 are to handle cases generated by reload.
604 (define_insn "subqi3"
605   [(set (match_operand:QI           0 "msp430_general_dst_nonv_operand" "=rYsYx,  rm,  &?r, ?&r")
606         (minus:QI (match_operand:QI 1 "general_operand"       "0,    0,    !r,  !i")
607                   (match_operand:QI 2 "general_operand"      " riYsYx, rmi, rmi,   r")))]
608   ""
609   "@
610   SUB.B\t%2, %0
611   SUBX.B\t%2, %0
612   MOV%X2.B\t%1, %0 { SUB%X2.B\t%2, %0
613   MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0"
614   [(set_attr "length_multiplier" "1,1,2,2")
615    (set_attr "type" "triple")]
618 ;; Alternatives 2 and 3 are to handle cases generated by reload.
619 (define_insn "subhi3"
620   [(set (match_operand:HI           0 "msp430_general_dst_nonv_operand" "=rYsYx,  rm,  &?r, ?&r")
621         (minus:HI (match_operand:HI 1 "general_operand"       "0,    0,    !r,  !i")
622                   (match_operand:HI 2 "general_operand"      " riYsYx, rmi, rmi,   r")))]
623   ""
624   "@
625   SUB.W\t%2, %0
626   SUBX.W\t%2, %0
627   MOV%X2.W\t%1, %0 { SUB%X2.W\t%2, %0
628   MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0"
629   [(set_attr "length_multiplier" "1,1,2,2")
630    (set_attr "type" "triple")]
633 (define_insn "subsi3"
634   [(set (match_operand:SI           0 "msp430_general_dst_nonv_operand" "=&rYsYx,m")
635         (minus:SI (match_operand:SI 1 "general_operand"   "0,0")
636                   (match_operand:SI 2 "general_operand"        "riYsYx,mi")))]
637   ""
638   "@
639   SUB\t%L2, %L0 { SUBC\t%H2, %H0
640   SUBX\t%L2, %L0 { SUBCX\t%H2, %H0"
641   [(set_attr "length_multiplier" "2")
642    (set_attr "type" "triple")]
645 (define_insn "*bic<mode>_cg"
646   [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYs,m")
647         (and:QHI (match_operand:QHI 1 "msp430_general_operand" "0,0")
648                  (match_operand 2 "msp430_inv_constgen_operator" "n,n")))]
649   ""
650   "@
651    BIC%x0%b0\t#%I2, %0
652    BIC%X0%b0\t#%I2, %0"
653   [(set_attr "length" "2")      ; Smaller length achieved by using constant generator
654    (set_attr "type" "double")]
657 (define_insn "bic<mode>3"
658   [(set (match_operand:QHI                   0 "msp430_general_dst_operand" "=rYsYx,rm")
659         (and:QHI (not:QHI (match_operand:QHI 1 "msp430_general_operand"       "rYsYx,rmn"))
660                  (match_operand:QHI          2 "msp430_general_operand"  "0,0")))]
661   ""
662   "@
663    BIC%x0%b0\t%1, %0
664    BICX%b0\t%1, %0"
665   [(set_attr "type" "double")]
668 (define_insn "and<mode>3"
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")
671                  (match_operand:QHI 2 "msp430_general_operand" "N,riYsYx,rmi")))]
672   ""
673   "@
674    AND%x0.B\t%2, %0
675    AND%x0%b0\t%2, %0
676    ANDX%b0\t%2, %0"
677   [(set_attr "type" "triple")]
680 (define_insn "ior<mode>3"
681   [(set (match_operand:QHI          0 "msp430_general_dst_operand" "=rYsYx,rm")
682         (ior:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0")
683                  (match_operand:QHI 2 "msp430_general_operand" "riYsYx,rmi")))]
684   ""
685   "@
686    BIS%x0%b0\t%2, %0
687    BISX%b0\t%2, %0"
688   [(set_attr "type" "triple")]
691 (define_insn "xor<mode>3"
692   [(set (match_operand:QHI          0 "msp430_general_dst_operand" "=rYsYx,rm")
693         (xor:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0")
694                  (match_operand:QHI 2 "msp430_general_operand" "riYsYx,rmi")))]
695   ""
696   "@
697    XOR%x0%b0\t%2, %0
698    XORX%b0\t%2, %0"
699   [(set_attr "type" "triple")]
702 ;; Macro : XOR #~0, %0
703 (define_insn "one_cmpl<mode>2"
704   [(set (match_operand:QHI          0 "msp430_general_dst_operand" "=rYs,m")
705         (not:QHI (match_operand:QHI 1 "msp430_general_operand" "0,0")))]
706   ""
707   "@
708    INV%x0%b0\t%0
709    INV%X0%b0\t%0"
710   [(set_attr "type" "double")]
713 (define_insn "extendqihi2"
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")))]
716   ""
717   "@
718    SXT%X0\t%0
719    SXT%X0\t%0"
720   [(set_attr "type" "single")]
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"
730   [(set_attr "type" "single")
731    (set_attr "extension" "none,x")]
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 ;; ------------------------
744 (define_insn "zero_extendqihi2"
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")))]
747   ""
748   "@
749    AND\t#0xff, %0
750    MOV.B\t%1, %0
751    MOV%X1.B\t%1, %0
752    AND%X0\t#0xff, %0"
753   [(set_attr "type" "double")]
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"
763   [(set_attr "type" "double")]
766 (define_insn "zero_extendqisi2"
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")))]
769   ""
770   "@
771   CLR\t%H0
772   MOV%X1.B\t%1,%L0 { CLR\t%H0"
773   [(set_attr "extra_length" "2")
774    (set_attr "length_multiplier" "1,2")
775    (set_attr "type" "double")]
778 (define_insn "zero_extendhipsi2"
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"
782   "@
783   MOV.W\t%1, %0
784   MOV%X1\t%1, %0
785   MOVX.A\t%1, %0"
786   [(set_attr "type" "double")]
789 (define_insn "zero_extendhisi2"
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")))]
792   ""
793   "@
794   MOV%X0.W\t#0,%H0
795   MOV.W\t%1,%L0 { MOV.W\t#0,%H0"
796   [(set_attr "length_multiplier" "1,2")
797    (set_attr "type" "double")]
800 (define_insn "zero_extendhisipsi2"
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))]
803   "msp430x"
804   "@
805    AND.W\t#-1,%0
806    MOV.W\t%1,%0"
807   [(set_attr "length" "4,2")
808    (set_attr "type" "double")]
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.
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..
821 ; Note: using PUSHM.A #1 is two bytes smaller than using PUSHX.A....
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.
829 ; FIXME we can use MOVA for r->m if m is &abs20 or z16(rdst)
830 (define_insn "zero_extendpsisi2"
831   [(set (match_operand:SI                  0 "register_operand" "+r,m")
832         (zero_extend:SI (match_operand:PSI 1 "register_operand" "r,r")))]
833   ""
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 \
842       return \"PUSHM.A\t#1, %1 { POPX.W\t%L0 { POPX.W\t%H0 ; move pointer in %1 into reg-pair %L0:%H0\";
843   MOVX.A %1, %0"
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")]
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.
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"
867   [(set_attr "type" "double")]
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"
877   [(set_attr "type" "double")]
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.
884 (define_insn ""
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")))]
888   "msp430x"
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"
893   [(set_attr "length" "4,*,*")
894    (set_attr "extra_length" "0,4,6")
895    (set_attr "type" "double")]
898 (define_insn ""
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")))]
902   "msp430x"
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"
907   [(set_attr "length" "4,*,*")
908    (set_attr "extra_length" "0,4,6")
909    (set_attr "type" "double")]
912 ;; Same as above but with a NOP sign_extend round the subreg
913 (define_insn ""
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")))]
917   "msp430x"
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"
922   [(set_attr "length" "4,*,*")
923    (set_attr "extra_length" "0,4,6")
924    (set_attr "type" "double")]
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"
932   [(set_attr "extra_length" "4")
933    (set_attr "type" "double")]
936 (define_insn ""
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")))]
940   "msp430x"
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"
945   [(set_attr "length" "2,*,*")
946    (set_attr "extra_length" "0,2,4")
947    (set_attr "type" "double")]
949 ;; END msp430 pointer manipulation combine insn patterns
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)))]
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"
967   [(set_attr "extension" "m")
968    (set_attr "type" "double")]
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   ""
975   { msp430x_extendhisi (operands, 0); return ""; }
976   [(set (attr "length")
977         (symbol_ref "msp430x_extendhisi (operands, 1)"))
978    (set_attr "type" "double")]
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"
986   [(set_attr "length_multiplier" "2")
987    (set_attr "extension" "m")
988    (set_attr "type" "double")]
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.
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"
1002   [(set_attr "length_multiplier" "2")
1003    (set_attr "extension" "m")
1004    (set_attr "type" "double")]
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"
1013   [(set_attr "length_multiplier" "2")
1014    (set_attr "extension" "m")
1015    (set_attr "type" "double")]
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.
1022 (define_insn "extendpsisi2"
1023   [(set (match_operand:SI                  0 "register_operand" "=r")
1024         (sign_extend:SI (match_operand:PSI 1 "register_operand" "r")))]
1025   "msp430x"
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]))
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\";
1034     else
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\";
1036   "
1037   [(set_attr "length" "10")
1038    (set_attr "type" "double")]
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   ""
1047   "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A\t#1, %L0"
1048   [(set_attr "length" "6")
1049    (set_attr "type" "single")]
1052 ;;------------------------------------------------------------
1053 ;; Shift Functions
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:
1062 ;;   bit #0xf, Rn
1063 ;;   bz  1f
1064 ;;   dec Rn
1065 ;;   rpt Rn
1066 ;;   <shift> Rm
1067 ;;   inc Rn
1068 ;; 1:
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 ?
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
1076 ;; in "undefined" behavior.  [6.5.7 (3)]
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.
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")))]
1086   ""
1087   {
1088     if (msp430_expand_shift (<CODE>, <MODE>mode, operands))
1089       DONE;
1090     /* Otherwise, fallthrough.  */
1091   }
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"
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")]
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")))]
1111   ""
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")]
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")))]
1122   "msp430x"
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"
1128   [(set_attr "length" "2,4,8,0")
1129    (set_attr "type" "single")]
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")))]
1136   "msp430x"
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"
1142   [(set_attr "length" "2,4,8,0")
1143    (set_attr "type" "single")]
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")))]
1150   "msp430x"
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"
1156   [(set_attr "length" "2,4,8,0")
1157    (set_attr "type" "single")]
1160 ;;------------------------------------------------------------
1161 ;; Function Entry/Exit
1163 (define_expand "prologue"
1164   [(const_int 0)]
1165   ""
1166   "msp430_expand_prologue (); DONE;"
1169 (define_expand "epilogue"
1170   [(const_int 0)]
1171   ""
1172   "msp430_expand_epilogue (0); DONE;"
1175 (define_insn "epilogue_helper"
1176   [(set (pc)
1177         (unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_EPILOGUE_HELPER))
1178    (return)]
1179   "!msp430x"
1180   "BR%Q0\t#__mspabi_func_epilog_%J0"
1181   [(set_attr "length" "2")]
1184 (define_insn "prologue_start_marker"
1185   [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_START_MARKER)]
1186   ""
1187   "; start of prologue"
1188   [(set_attr "length" "0")]
1191 (define_insn "prologue_end_marker"
1192   [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_END_MARKER)]
1193   ""
1194   "; end of prologue"
1195   [(set_attr "length" "0")]
1198 (define_insn "epilogue_start_marker"
1199   [(unspec_volatile [(const_int 0)] UNS_EPILOGUE_START_MARKER)]
1200   ""
1201   "; start of epilogue"
1202   [(set_attr "length" "0")]
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"
1211   [(set_attr "length" "0")]
1214 ;;------------------------------------------------------------
1215 ;; Jumps
1217 (define_expand "call"
1218   [(call:HI (match_operand 0 "")
1219             (match_operand 1 ""))]
1220   ""
1221   ""
1224 (define_insn "call_internal"
1225   [(call (mem:HI (match_operand 0 "general_operand" "rYci"))
1226          (match_operand 1 ""))]
1227   ""
1228   "CALL%Q0\t%0"
1229   [(set_attr "extension" "none")
1230    (set_attr "type" "single")]
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   ""
1241 (define_insn "call_value_internal"
1242   [(set (match_operand               0 "register_operand" "=r")
1243         (call (mem:HI (match_operand 1 "general_operand" "rYci"))
1244               (match_operand 2 "")))]
1245   ""
1246   "CALL%Q0\t%1"
1247   [(set_attr "extension" "none")
1248    (set_attr "type" "single")]
1251 (define_insn "msp430_return"
1252   [(return)]
1253   ""
1254   { return msp430_is_interrupt_func () ? "RETI" : (TARGET_LARGE ? "RETA" : "RET"); }
1255   [(set_attr "length" "2")]
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"
1264   [(match_operand:HI 0 "")]
1265   ""
1266   "msp430_expand_eh_return (operands[0]);
1267    emit_jump_insn (gen_msp430_eh_epilogue ());
1268    emit_barrier ();
1269    DONE;"
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;"
1281   [(set_attr "length" "40")]
1284 (define_insn "jump"
1285   [(set (pc)
1286         (label_ref (match_operand 0 "" "")))]
1287   ""
1288   "BR%Q0\t#%l0"
1289   [(set_attr "length" "4")]
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   ""
1298   "BR%Q0\t%0"
1299   [(set (attr "length")
1300         (if_then_else (match_operand 0 "register_operand" "")
1301                       (const_int 2)
1302                       (const_int 4)))]
1305 ;;------------------------------------------------------------
1306 ;; Various Conditionals
1308 (define_expand "cbranch<mode>4"
1309   [(parallel [(set (pc) (if_then_else
1310                          (match_operator 0 ""
1311                                          [(match_operand:QHI 1 "msp430_general_dst_nonv_operand")
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);"
1321 (define_insn "cbranchpsi4_real"
1322   [(set (pc) (if_then_else
1323               (match_operator                     0 "msp430_cmp_operator"
1324                               [(match_operand:PSI 1 "msp430_general_dst_nonv_operand" "r,rYs,rm")
1325                                (match_operand:PSI 2 "general_operand"      "rLs,rYsi,rmi")])
1326               (label_ref (match_operand           3 "" ""))
1327               (pc)))
1328    (clobber (reg:BI CARRY))
1329    ]
1330   ""
1331   "@
1332   CMP%Q0\t%2, %1 { J%0\t%l3
1333   CMPX.A\t%2, %1 { J%0\t%l3
1334   CMPX.A\t%2, %1 { J%0\t%l3"
1335   [(set_attr "extra_length" "2")
1336    (set_attr "type" "cmp")]
1339 (define_insn "cbranchqi4_real"
1340   [(set (pc) (if_then_else
1341               (match_operator                    0 "msp430_cmp_operator"
1342                               [(match_operand:QI 1 "msp430_general_dst_nonv_operand" "rYsYx,rm")
1343                                (match_operand:QI 2 "general_operand"      "rYsYxi,rmi")])
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
1351    CMPX.B\t%2, %1 { J%0\t%l3"
1352   [(set_attr "extra_length" "2")
1353    (set_attr "type" "cmp")]
1356 (define_insn "cbranchhi4_real"
1357   [(set (pc) (if_then_else
1358               (match_operator                    0 "msp430_cmp_operator"
1359                               [(match_operand:HI 1 "msp430_general_dst_nonv_operand" "rYsYx,rm")
1360                                (match_operand:HI 2 "general_operand"      "rYsYxi,rmi")])
1361               (label_ref (match_operand          3 "" ""))
1362               (pc)))
1363    (clobber (reg:BI CARRY))
1364    ]
1365   ""
1366   "@
1367    CMP.W\t%2, %1 { J%0\t%l3
1368    CMPX.W\t%2, %1 { J%0\t%l3"
1369   [(set_attr "extra_length" "2")
1370    (set_attr "type" "cmp")]
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")
1377                                (match_operand:PSI 2 "msp430_general_dst_nonv_operand" "r,rYs,rm")])
1378               (label_ref (match_operand           3 "" ""))
1379               (pc)))
1380    (clobber (reg:BI CARRY))
1381    ]
1382   ""
1383   "@
1384   CMP%Q0\t%1, %2 { J%R0\t%l3
1385   CMPX.A\t%1, %2 { J%R0\t%l3
1386   CMPX.A\t%1, %2 { J%R0\t%l3"
1387   [(set_attr "extra_length" "2")
1388    (set_attr "type" "cmp")]
1391 (define_insn "cbranchqi4_reversed"
1392   [(set (pc) (if_then_else
1393               (match_operator                    0 "msp430_reversible_cmp_operator"
1394                               [(match_operand:QI 1 "general_operand" "rYsYxi,rmi")
1395                                (match_operand:QI 2 "msp430_general_dst_nonv_operand" "rYsYx,rm")])
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
1403    CMPX.B\t%1, %2 { J%R0\t%l3"
1404   [(set_attr "extra_length" "2")
1405    (set_attr "type" "cmp")]
1408 (define_insn "cbranchhi4_reversed"
1409   [(set (pc) (if_then_else
1410               (match_operator                    0 "msp430_reversible_cmp_operator"
1411                               [(match_operand:HI 1 "general_operand" "rYsYxi,rmi")
1412                                (match_operand:HI 2 "msp430_general_dst_nonv_operand" "rYsYx,rm")])
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
1420    CMPX.W\t%1, %2 { J%R0\t%l3"
1421   [(set_attr "extra_length" "2")
1422    (set_attr "type" "cmp")]
1425 (define_insn "*bitbranch<mode>4"
1426   [(set (pc) (if_then_else
1427               (ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
1428                            (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
1429                   (const_int 0))
1430               (label_ref (match_operand 2 "" ""))
1431               (pc)))
1432    (clobber (reg:BI CARRY))
1433    ]
1434   ""
1435   "@
1436    BIT%x0%b0\t%1, %0 { JNE\t%l2
1437    BITX%b0\t%1, %0 { JNE\t%l2"
1438   [(set_attr "extra_length" "2")
1439    (set_attr "type" "double")]
1442 (define_insn "*bitbranch<mode>4"
1443   [(set (pc) (if_then_else
1444               (eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
1445                            (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
1446                   (const_int 0))
1447               (label_ref (match_operand 2 "" ""))
1448               (pc)))
1449    (clobber (reg:BI CARRY))
1450    ]
1451   ""
1452   "@
1453    BIT%x0%b0\t%1, %0 { JEQ\t%l2
1454    BITX%b0\t%1, %0 { JEQ\t%l2"
1455   [(set_attr "extra_length" "2")
1456    (set_attr "type" "double")]
1459 (define_insn "*bitbranch<mode>4"
1460   [(set (pc) (if_then_else
1461               (eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
1462                            (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
1463                   (const_int 0))
1464               (pc)
1465               (label_ref (match_operand 2 "" ""))))
1466    (clobber (reg:BI CARRY))
1467    ]
1468   ""
1469   "@
1470   BIT%x0%b0\t%1, %0 { JNE\t%l2
1471   BITX%b0\t%1, %0 { JNE\t%l2"
1472   [(set_attr "extra_length" "2")
1473    (set_attr "type" "double")]
1476 (define_insn "*bitbranch<mode>4"
1477   [(set (pc) (if_then_else
1478               (ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm")
1479                            (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
1480                   (const_int 0))
1481               (pc)
1482               (label_ref (match_operand 2 "" ""))))
1483    (clobber (reg:BI CARRY))
1484    ]
1485   ""
1486   "@
1487   BIT%x0%b0\t%1, %0 { JEQ\t%l2
1488   BITX%b0\t%1, %0 { JEQ\t%l2"
1489   [(set_attr "extra_length" "2")
1490    (set_attr "type" "double")]
1493 ;;------------------------------------------------------------
1494 ;; zero-extract versions of the above
1496 (define_insn "*bitbranch<mode>4_z"
1497   [(set (pc) (if_then_else
1498               (ne (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rYs,rm")
1499                                     (const_int 1)
1500                                     (match_operand 1 "const_0_to_15_operand" "i,i"))
1501                   (const_int 0))
1502               (label_ref (match_operand 2 "" ""))
1503               (pc)))
1504    (clobber (reg:BI CARRY))
1505    ]
1506   ""
1507   "@
1508    BIT%x0%b0\t%p1, %0 { JNE\t%l2
1509    BIT%X0%b0\t%p1, %0 { JNE\t%l2"
1510   [(set_attr "extra_length" "2")
1511    (set_attr "type" "double")]
1514 (define_insn "*bitbranch<mode>4_z"
1515   [(set (pc) (if_then_else
1516               (eq (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm")
1517                                    (const_int 1)
1518                                    (match_operand 1 "const_0_to_15_operand" "i"))
1519                   (const_int 0))
1520               (label_ref (match_operand 2 "" ""))
1521               (pc)))
1522    (clobber (reg:BI CARRY))
1523    ]
1524   ""
1525   "BIT%X0%b0\t%p1, %0 { JEQ\t%l2"
1526   [(set_attr "extra_length" "2")
1527    (set_attr "type" "double")]
1530 (define_insn "*bitbranch<mode>4_z"
1531   [(set (pc) (if_then_else
1532               (eq (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm")
1533                                    (const_int 1)
1534                                    (match_operand 1 "const_0_to_15_operand" "i"))
1535                   (const_int 0))
1536               (pc)
1537               (label_ref (match_operand 2 "" ""))))
1538    (clobber (reg:BI CARRY))
1539    ]
1540   ""
1541   "BIT%X0%b0\t%p1, %0 { JNE\t%l2"
1542   [(set_attr "extra_length" "2")
1543    (set_attr "type" "double")]
1546 (define_insn "*bitbranch<mode>4_z"
1547   [(set (pc) (if_then_else
1548               (ne (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm")
1549                                    (const_int 1)
1550                                    (match_operand 1 "const_0_to_15_operand" "i"))
1551                   (const_int 0))
1552               (pc)
1553               (label_ref (match_operand 2 "" ""))))
1554    (clobber (reg:BI CARRY))
1555    ]
1556   ""
1557   "BIT%X0%b0\t%p1, %0 { JEQ\t%l2"
1558   [(set_attr "extra_length" "2")
1559    (set_attr "type" "double")]
1562 ;;------------------------------------------------------------
1563 ;; Misc
1565 (define_insn "nop"
1566   [(const_int 0)]
1567   "1"
1568   "NOP"
1569   [(set_attr "length" "2")]
1572 (define_insn "disable_interrupts"
1573   [(unspec_volatile [(const_int 0)] UNS_DINT)]
1574   ""
1575   "DINT \; NOP"
1576   [(set_attr "length" "2")]
1579 (define_insn "enable_interrupts"
1580   [(unspec_volatile [(const_int 0)] UNS_EINT)]
1581   ""
1582   "EINT"
1583   [(set_attr "length" "2")]
1586 (define_insn "push_intr_state"
1587   [(unspec_volatile [(const_int 0)] UNS_PUSH_INTR)]
1588   ""
1589   "PUSH\tSR"
1590   [(set_attr "length" "2")]
1593 (define_insn "pop_intr_state"
1594   [(unspec_volatile [(const_int 0)] UNS_POP_INTR)]
1595   ""
1596   "POP\tSR"
1597   [(set_attr "length" "2")]
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)"
1606   [(set_attr "type" "single")
1607    (set_attr "extra_length" "2")]
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)"
1616   [(set_attr "type" "single")
1617    (set_attr "extra_length" "2")]
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"
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")))]
1627   ""
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")]
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"
1641   [(set_attr "length" "0")]
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   )
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
1660 1:      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"
1667   [(set_attr "length" "32")]
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   ""
1675   "PUSHM.A      #2,r14
1676         MOV.W   %A0, r13
1677         MOV.W   %B0, r14
1678 1:      SUB.W   #1, r13
1679         SUBC.W  #0, r14
1680         JNE     1b
1681         TST.W   r13
1682         JNE     1b
1683         POPM.A  #2,r14"
1684   [(set_attr "length" "28")]
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
1694 1:      SUB.W   #1, r13
1695         JNE     1b
1696         POP     r13"
1697   [(set_attr "length" "14")]
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
1707 1:      SUB.W   #1, r13
1708         JNE     1b
1709         POPM.A  #1,r13"
1710   [(set_attr "length" "14")]
1713 (define_insn "delay_cycles_2"
1714   [(unspec_volatile [(const_int 0) ] UNS_DELAY_2)]
1715   ""
1716   "JMP  .+2"
1717   [(set_attr "length" "2")]
1720 (define_insn "delay_cycles_1"
1721   [(unspec_volatile [(const_int 0) ] UNS_DELAY_1)]
1722   ""
1723   "NOP"
1724   [(set_attr "length" "2")]
1727 (define_expand "mulhi3"
1728   [(set (match_operand:HI                          0 "register_operand" "=r")
1729         (mult:HI (match_operand:HI 1 "register_operand" "%0")
1730                  (match_operand:HI 2 "register_operand" "r")))]
1731   "msp430_has_hwmult ()"
1732   {
1733     msp430_expand_helper (operands, "__mspabi_mpyi", false);
1734     DONE;
1735   }
1738 (define_expand "mulsi3"
1739   [(set (match_operand:SI                          0 "register_operand" "=r")
1740         (mult:SI (match_operand:SI 1 "register_operand" "%0")
1741                  (match_operand:SI 2 "register_operand" "r")))]
1742   "msp430_has_hwmult ()"
1743   {
1744     msp430_expand_helper (operands, "__mspabi_mpyl", false);
1745     DONE;
1746   }
1749 ; libgcc helper functions for widening multiplication aren't currently
1750 ; generated by gcc, so we can't catch them later and map them to the mspabi
1751 ; functions.
1752 ; We catch the patterns here and either generate a call to the helper function,
1753 ; or emit the hardware multiply instruction sequence inline.
1755 ; If we don't have hardware multiply support, it will generally be slower and
1756 ; result in larger code to call the mspabi library function to perform the
1757 ; widening multiplication than just leaving GCC to widen the arguments itself.
1759 (define_expand "mulhisi3"
1760   [(set (match_operand:SI                          0 "register_operand" "=r")
1761         (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1762                  (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
1763   "msp430_has_hwmult ()"
1764   {
1765     /* Leave the other case for the inline insn.  */
1766     if (!(optimize > 2 && msp430_has_hwmult ()))
1767     {
1768       msp430_expand_helper (operands, "__mspabi_mpysl", false);
1769       DONE;
1770     }
1771   }
1774 (define_expand "umulhisi3"
1775   [(set (match_operand:SI                          0 "register_operand" "=r")
1776         (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1777                  (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
1778   "msp430_has_hwmult ()"
1779   {
1780     /* Leave the other case for the inline insn.  */
1781     if (!(optimize > 2 && msp430_has_hwmult ()))
1782     {
1783       msp430_expand_helper (operands, "__mspabi_mpyul", false);
1784       DONE;
1785     }
1786   }
1789 (define_expand "mulsidi3"
1790   [(set (match_operand:DI                          0 "register_operand" "=r")
1791         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
1792                  (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
1793   "msp430_has_hwmult ()"
1794   {
1795     /* Leave the other case for the inline insn.  */
1796     if (!(optimize > 2 && msp430_has_hwmult ()))
1797     {
1798       msp430_expand_helper (operands, "__mspabi_mpysll", false);
1799       DONE;
1800     }
1801   }
1804 (define_expand "umulsidi3"
1805   [(set (match_operand:DI                          0 "register_operand" "=r")
1806         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
1807                  (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
1808   "msp430_has_hwmult ()"
1809   {
1810     /* Leave the other case for the inline insn.  */
1811     if (!(optimize > 2 && msp430_has_hwmult ()))
1812     {
1813       msp430_expand_helper (operands, "__mspabi_mpyull", false);
1814       DONE;
1815     }
1816   }
1820 (define_insn "*mulhisi3_inline"
1821   [(set (match_operand:SI                          0 "register_operand" "=r")
1822         (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1823                  (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
1824   "optimize > 2 && msp430_has_hwmult ()"
1825   "*
1826     if (msp430_use_f5_series_hwmult ())
1827       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\";
1828     else
1829       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\";
1830   "
1831   [(set_attr "length" "24")]
1834 (define_insn "*umulhisi3_inline"
1835   [(set (match_operand:SI                          0 "register_operand" "=r")
1836         (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0"))
1837                  (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
1838   "optimize > 2 && msp430_has_hwmult ()"
1839   "*
1840     if (msp430_use_f5_series_hwmult ())
1841       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\";
1842     else
1843       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\";
1844   "
1845   [(set_attr "length" "24")]
1848 (define_insn "*mulsidi3_inline"
1849   [(set (match_operand:DI                          0 "register_operand" "=r")
1850         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
1851                  (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
1852   "optimize > 2 && msp430_has_hwmult ()"
1853   "*
1854     if (msp430_use_f5_series_hwmult ())
1855       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\";
1856     else
1857       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\";
1858   "
1859   [(set_attr "length" "40")]
1862 (define_insn "*umulsidi3_inline"
1863   [(set (match_operand:DI                          0 "register_operand" "=r")
1864         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
1865                  (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
1866   "optimize > 2 && msp430_has_hwmult ()"
1867   "*
1868     if (msp430_use_f5_series_hwmult ())
1869       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\";
1870     else
1871       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\";
1872   "
1873   [(set_attr "length" "40")]