annotate gcc/config/msp430/msp430.md @ 131:84e7813d76e9

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