145
|
1 ;; Machine description for OpenRISC
|
|
2 ;; Copyright (C) 2018-2020 Free Software Foundation, Inc.
|
|
3 ;; Contributed by Stafford Horne
|
|
4
|
|
5 ;; This file is part of GCC.
|
|
6
|
|
7 ;; GCC is free software; you can redistribute it and/or modify it
|
|
8 ;; under the terms of the GNU General Public License as published
|
|
9 ;; by the Free Software Foundation; either version 3, or (at your
|
|
10 ;; option) any later version.
|
|
11
|
|
12 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
|
|
13 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
14 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
15 ;; License for more details.
|
|
16
|
|
17 ;; You should have received a copy of the GNU General Public License
|
|
18 ;; along with GCC; see the file COPYING3. If not see
|
|
19 ;; <http://www.gnu.org/licenses/>.
|
|
20
|
|
21 ;; -------------------------------------------------------------------------
|
|
22 ;; OpenRISC specific constraints, predicates and attributes
|
|
23 ;; -------------------------------------------------------------------------
|
|
24
|
|
25 (include "constraints.md")
|
|
26 (include "predicates.md")
|
|
27
|
|
28 ;; Register numbers
|
|
29 (define_constants
|
|
30 [(SP_REGNUM 1)
|
|
31 (HFP_REGNUM 2)
|
|
32 (LR_REGNUM 9)
|
|
33 (TLS_REGNUM 10)
|
|
34 (RV_REGNUM 11)
|
|
35 (PE_TMP_REGNUM 13)
|
|
36 (AP_REGNUM 32)
|
|
37 (SFP_REGNUM 33)
|
|
38 (SR_F_REGNUM 34)]
|
|
39 )
|
|
40
|
|
41 (define_c_enum "unspec" [
|
|
42 UNSPEC_SET_GOT
|
|
43 UNSPEC_GOT
|
|
44 UNSPEC_GOTOFF
|
|
45 UNSPEC_TPOFF
|
|
46 UNSPEC_GOTTPOFF
|
|
47 UNSPEC_TLSGD
|
|
48 UNSPEC_MSYNC
|
|
49 ])
|
|
50
|
|
51 (define_c_enum "unspecv" [
|
|
52 UNSPECV_SET_GOT
|
|
53 UNSPECV_LL
|
|
54 UNSPECV_SC
|
|
55 ])
|
|
56
|
|
57 ;; Instruction scheduler
|
|
58
|
|
59 ; Most instructions are 4 bytes long.
|
|
60 (define_attr "length" "" (const_int 4))
|
|
61
|
|
62 (define_attr "type"
|
|
63 "alu,st,ld,control,multi,fpu"
|
|
64 (const_string "alu"))
|
|
65
|
|
66 (define_attr "insn_support" "class1,sext,sfimm,shftimm,ror,rori" (const_string "class1"))
|
|
67
|
|
68 (define_attr "enabled" ""
|
|
69 (cond [(eq_attr "insn_support" "class1") (const_int 1)
|
|
70 (and (eq_attr "insn_support" "sext")
|
|
71 (ne (symbol_ref "TARGET_SEXT") (const_int 0))) (const_int 1)
|
|
72 (and (eq_attr "insn_support" "sfimm")
|
|
73 (ne (symbol_ref "TARGET_SFIMM") (const_int 0))) (const_int 1)
|
|
74 (and (eq_attr "insn_support" "shftimm")
|
|
75 (ne (symbol_ref "TARGET_SHFTIMM") (const_int 0))) (const_int 1)
|
|
76 (and (eq_attr "insn_support" "ror")
|
|
77 (ne (symbol_ref "TARGET_ROR") (const_int 0))) (const_int 1)
|
|
78 (and (eq_attr "insn_support" "rori")
|
|
79 (ne (symbol_ref "TARGET_RORI") (const_int 0))) (const_int 1)]
|
|
80 (const_int 0)))
|
|
81
|
|
82 ;; Describe a user's asm statement.
|
|
83 (define_asm_attributes
|
|
84 [(set_attr "type" "multi")])
|
|
85
|
|
86 (define_automaton "or1k")
|
|
87 (define_cpu_unit "cpu" "or1k")
|
|
88 (define_insn_reservation "alu" 1
|
|
89 (eq_attr "type" "alu")
|
|
90 "cpu")
|
|
91 (define_insn_reservation "st" 1
|
|
92 (eq_attr "type" "st")
|
|
93 "cpu")
|
|
94 (define_insn_reservation "ld" 3
|
|
95 (eq_attr "type" "st")
|
|
96 "cpu")
|
|
97 (define_insn_reservation "control" 1
|
|
98 (eq_attr "type" "control")
|
|
99 "cpu")
|
|
100 (define_insn_reservation "fpu" 2
|
|
101 (eq_attr "type" "fpu")
|
|
102 "cpu")
|
|
103
|
|
104
|
|
105 ; Define delay slots for any branch
|
|
106 (define_delay (eq_attr "type" "control")
|
|
107 [(eq_attr "type" "alu,st,ld") (nil) (nil)])
|
|
108
|
|
109 ;; -------------------------------------------------------------------------
|
|
110 ;; nop instruction
|
|
111 ;; -------------------------------------------------------------------------
|
|
112
|
|
113 (define_insn "nop"
|
|
114 [(const_int 0)]
|
|
115 ""
|
|
116 "l.nop")
|
|
117
|
|
118 ;; -------------------------------------------------------------------------
|
|
119 ;; Arithmetic instructions
|
|
120 ;; -------------------------------------------------------------------------
|
|
121
|
|
122 (define_insn "addsi3"
|
|
123 [(set (match_operand:SI 0 "register_operand" "=r,r")
|
|
124 (plus:SI
|
|
125 (match_operand:SI 1 "register_operand" "%r,r")
|
|
126 (match_operand:SI 2 "reg_or_s16_operand" " r,I")))]
|
|
127 ""
|
|
128 "@
|
|
129 l.add\t%0, %1, %2
|
|
130 l.addi\t%0, %1, %2")
|
|
131
|
|
132 (define_insn "mulsi3"
|
|
133 [(set (match_operand:SI 0 "register_operand" "=r,r")
|
|
134 (mult:SI
|
|
135 (match_operand:SI 1 "register_operand" "%r,r")
|
|
136 (match_operand:SI 2 "reg_or_s16_operand" " r,I")))]
|
|
137 "!TARGET_SOFT_MUL"
|
|
138 "@
|
|
139 l.mul\t%0, %1, %2
|
|
140 l.muli\t%0, %1, %2")
|
|
141
|
|
142 (define_insn "divsi3"
|
|
143 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
144 (div:SI
|
|
145 (match_operand:SI 1 "register_operand" "r")
|
|
146 (match_operand:SI 2 "register_operand" "r")))]
|
|
147 "!TARGET_SOFT_DIV"
|
|
148 "l.div\t%0, %1, %2")
|
|
149
|
|
150 (define_insn "udivsi3"
|
|
151 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
152 (udiv:SI
|
|
153 (match_operand:SI 1 "register_operand" "r")
|
|
154 (match_operand:SI 2 "register_operand" "r")))]
|
|
155 "!TARGET_SOFT_DIV"
|
|
156 "l.divu\t%0, %1, %2")
|
|
157
|
|
158 (define_insn "subsi3"
|
|
159 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
160 (minus:SI
|
|
161 (match_operand:SI 1 "reg_or_0_operand" "rO")
|
|
162 (match_operand:SI 2 "register_operand" "r")))]
|
|
163 ""
|
|
164 "l.sub\t%0, %r1, %2")
|
|
165
|
|
166 ;; -------------------------------------------------------------------------
|
|
167 ;; Floating Point Arithmetic instructions
|
|
168 ;; -------------------------------------------------------------------------
|
|
169
|
|
170 ;; Mode iterator for single/double float
|
|
171 (define_mode_iterator F [(SF "TARGET_HARD_FLOAT")
|
|
172 (DF "TARGET_DOUBLE_FLOAT")])
|
|
173 (define_mode_attr f [(SF "s") (DF "d")])
|
|
174 (define_mode_attr fr [(SF "r") (DF "d")])
|
|
175 (define_mode_attr fi [(SF "si") (DF "di")])
|
|
176 (define_mode_attr FI [(SF "SI") (DF "DI")])
|
|
177
|
|
178 ;; Basic arithmetic instructions
|
|
179 (define_code_iterator FOP [plus minus mult div])
|
|
180 (define_code_attr fop [(plus "add") (minus "sub") (mult "mul") (div "div")])
|
|
181
|
|
182 (define_insn "<fop><F:mode>3"
|
|
183 [(set (match_operand:F 0 "register_operand" "=<fr>")
|
|
184 (FOP:F (match_operand:F 1 "register_operand" "<fr>")
|
|
185 (match_operand:F 2 "register_operand" "<fr>")))]
|
|
186 "TARGET_HARD_FLOAT"
|
|
187 "lf.<fop>.<f>\t%d0, %d1, %d2"
|
|
188 [(set_attr "type" "fpu")])
|
|
189
|
|
190 ;; Basic float<->int conversion
|
|
191 (define_insn "float<fi><F:mode>2"
|
|
192 [(set (match_operand:F 0 "register_operand" "=<fr>")
|
|
193 (float:F
|
|
194 (match_operand:<FI> 1 "register_operand" "<fr>")))]
|
|
195 "TARGET_HARD_FLOAT"
|
|
196 "lf.itof.<f>\t%d0, %d1"
|
|
197 [(set_attr "type" "fpu")])
|
|
198
|
|
199 (define_insn "fix_trunc<F:mode><fi>2"
|
|
200 [(set (match_operand:<FI> 0 "register_operand" "=<fr>")
|
|
201 (fix:<FI>
|
|
202 (match_operand:F 1 "register_operand" "<fr>")))]
|
|
203 "TARGET_HARD_FLOAT"
|
|
204 "lf.ftoi.<f>\t%d0, %d1"
|
|
205 [(set_attr "type" "fpu")])
|
|
206
|
|
207 ;; -------------------------------------------------------------------------
|
|
208 ;; Logical operators
|
|
209 ;; -------------------------------------------------------------------------
|
|
210
|
|
211 (define_code_iterator SHIFT [ashift ashiftrt lshiftrt])
|
|
212 (define_code_attr shift_op [(ashift "ashl") (ashiftrt "ashr")
|
|
213 (lshiftrt "lshr")])
|
|
214 (define_code_attr shift_asm [(ashift "sll") (ashiftrt "sra")
|
|
215 (lshiftrt "srl")])
|
|
216
|
|
217 (define_insn "<shift_op>si3"
|
|
218 [(set (match_operand:SI 0 "register_operand" "=r,r")
|
|
219 (SHIFT:SI (match_operand:SI 1 "register_operand" "r,r")
|
|
220 (match_operand:SI 2 "reg_or_u6_operand" "r,n")))]
|
|
221 ""
|
|
222 "@
|
|
223 l.<shift_asm>\t%0, %1, %2
|
|
224 l.<shift_asm>i\t%0, %1, %2"
|
|
225 [(set_attr "insn_support" "*,shftimm")])
|
|
226
|
|
227 (define_insn "rotrsi3"
|
|
228 [(set (match_operand:SI 0 "register_operand" "=r,r")
|
|
229 (rotatert:SI (match_operand:SI 1 "register_operand" "r,r")
|
|
230 (match_operand:SI 2 "ror_reg_or_u6_operand" "r,n")))]
|
|
231 "TARGET_ROR || TARGET_RORI"
|
|
232 "@
|
|
233 l.ror\t%0, %1, %2
|
|
234 l.rori\t%0, %1, %2"
|
|
235 [(set_attr "insn_support" "ror,rori")])
|
|
236
|
|
237 (define_insn "andsi3"
|
|
238 [(set (match_operand:SI 0 "register_operand" "=r,r")
|
|
239 (and:SI
|
|
240 (match_operand:SI 1 "register_operand" "%r,r")
|
|
241 (match_operand:SI 2 "reg_or_u16_operand" " r,K")))]
|
|
242 ""
|
|
243 "@
|
|
244 l.and\t%0, %1, %2
|
|
245 l.andi\t%0, %1, %2")
|
|
246
|
|
247 (define_insn "xorsi3"
|
|
248 [(set (match_operand:SI 0 "register_operand" "=r,r")
|
|
249 (xor:SI
|
|
250 (match_operand:SI 1 "register_operand" "%r,r")
|
|
251 (match_operand:SI 2 "reg_or_s16_operand" " r,I")))]
|
|
252 ""
|
|
253 "@
|
|
254 l.xor\t%0, %1, %2
|
|
255 l.xori\t%0, %1, %2")
|
|
256
|
|
257 (define_insn "iorsi3"
|
|
258 [(set (match_operand:SI 0 "register_operand" "=r,r")
|
|
259 (ior:SI
|
|
260 (match_operand:SI 1 "register_operand" "%r,r")
|
|
261 (match_operand:SI 2 "reg_or_u16_operand" " r,K")))]
|
|
262 ""
|
|
263 "@
|
|
264 l.or\t%0, %1, %2
|
|
265 l.ori\t%0, %1, %2")
|
|
266
|
|
267 (define_expand "one_cmplsi2"
|
|
268 [(set (match_operand:SI 0 "register_operand" "")
|
|
269 (xor:SI (match_operand:SI 1 "register_operand" "") (const_int -1)))]
|
|
270 ""
|
|
271 "")
|
|
272
|
|
273 ;; -------------------------------------------------------------------------
|
|
274 ;; Move instructions
|
|
275 ;; -------------------------------------------------------------------------
|
|
276
|
|
277 (define_mode_iterator I [QI HI SI])
|
|
278 (define_mode_iterator I12 [QI HI])
|
|
279
|
|
280 (define_mode_attr ldst [(QI "b") (HI "h") (SI "w")])
|
|
281 (define_mode_attr zext_andi [(QI "0xff") (HI "0xffff")])
|
|
282
|
|
283 (define_expand "mov<I:mode>"
|
|
284 [(set (match_operand:I 0 "nonimmediate_operand" "")
|
|
285 (match_operand:I 1 "general_operand" ""))]
|
|
286 ""
|
|
287 {
|
|
288 or1k_expand_move (<MODE>mode, operands[0], operands[1]);
|
|
289 DONE;
|
|
290 })
|
|
291
|
|
292 ;; 8-bit, 16-bit and 32-bit moves
|
|
293
|
|
294 (define_insn "*mov<I:mode>_internal"
|
|
295 [(set (match_operand:I 0 "nonimmediate_operand" "=r,r,r,r, m,r")
|
|
296 (match_operand:I 1 "input_operand" " r,M,K,I,rO,m"))]
|
|
297 "register_operand (operands[0], <I:MODE>mode)
|
|
298 || reg_or_0_operand (operands[1], <I:MODE>mode)"
|
|
299 "@
|
|
300 l.or\t%0, %1, %1
|
|
301 l.movhi\t%0, hi(%1)
|
|
302 l.ori\t%0, r0, %1
|
|
303 l.xori\t%0, r0, %1
|
|
304 l.s<I:ldst>\t%0, %r1
|
|
305 l.l<I:ldst>z\t%0, %1"
|
|
306 [(set_attr "type" "alu,alu,alu,alu,st,ld")])
|
|
307
|
|
308 ;; Hi/Low moves for constant and symbol loading
|
|
309
|
|
310 (define_insn "movsi_high"
|
|
311 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
312 (high:SI (match_operand:SI 1 "high_operand" "")))]
|
|
313 ""
|
|
314 "l.movhi\t%0, %h1"
|
|
315 [(set_attr "type" "alu")])
|
|
316
|
|
317 (define_insn "*movsi_lo_sum_iori"
|
|
318 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
319 (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
|
|
320 (match_operand:SI 2 "losum_ior_operand" "")))]
|
|
321 ""
|
|
322 "l.ori\t%0, %1, %L2"
|
|
323 [(set_attr "type" "alu")])
|
|
324
|
|
325 (define_insn "*movsi_lo_sum_addi"
|
|
326 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
327 (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
|
|
328 (match_operand:SI 2 "losum_add_operand" "")))]
|
|
329 ""
|
|
330 "l.addi\t%0, %1, %L2"
|
|
331 [(set_attr "type" "alu")])
|
|
332
|
|
333 ;; 64-bit moves
|
|
334 ;; ??? The clobber that emit_move_multi_word emits is arguably incorrect.
|
|
335 ;; Consider gcc.c-torture/execute/20030222-1.c, where a reg-reg DImode
|
|
336 ;; move gets register allocated to a no-op move. At which point the
|
|
337 ;; we actively clobber the input.
|
|
338
|
|
339 (define_expand "movdi"
|
|
340 [(set (match_operand:DI 0 "nonimmediate_operand" "")
|
|
341 (match_operand:DI 1 "general_operand" ""))]
|
|
342 ""
|
|
343 {
|
|
344 if (MEM_P (operands[0]) && !const0_operand(operands[1], DImode))
|
|
345 operands[1] = force_reg (DImode, operands[1]);
|
|
346 })
|
|
347
|
|
348 (define_insn_and_split "*movdi"
|
|
349 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,o,r")
|
|
350 (match_operand:DI 1 "general_operand" " r,o,rO,n"))]
|
|
351 "register_operand (operands[0], DImode)
|
|
352 || reg_or_0_operand (operands[1], DImode)"
|
|
353 "#"
|
|
354 ""
|
|
355 [(const_int 0)]
|
|
356 {
|
|
357 rtx l0 = operand_subword (operands[0], 0, 0, DImode);
|
|
358 rtx l1 = operand_subword (operands[1], 0, 0, DImode);
|
|
359 rtx h0 = operand_subword (operands[0], 1, 0, DImode);
|
|
360 rtx h1 = operand_subword (operands[1], 1, 0, DImode);
|
|
361
|
|
362 if (reload_completed && reg_overlap_mentioned_p (l0, h1))
|
|
363 {
|
|
364 gcc_assert (!reg_overlap_mentioned_p (h0, l1));
|
|
365 emit_move_insn (h0, h1);
|
|
366 emit_move_insn (l0, l1);
|
|
367 }
|
|
368 else
|
|
369 {
|
|
370 emit_move_insn (l0, l1);
|
|
371 emit_move_insn (h0, h1);
|
|
372 }
|
|
373 DONE;
|
|
374 })
|
|
375
|
|
376 ;; -------------------------------------------------------------------------
|
|
377 ;; Sign Extending
|
|
378 ;; -------------------------------------------------------------------------
|
|
379
|
|
380 ;; Zero extension can always be done with AND or an extending load.
|
|
381
|
|
382 (define_insn "zero_extend<mode>si2"
|
|
383 [(set (match_operand:SI 0 "register_operand" "=r,r")
|
|
384 (zero_extend:SI (match_operand:I12 1 "reg_or_mem_operand" "r,m")))]
|
|
385 ""
|
|
386 "@
|
|
387 l.andi\t%0, %1, <zext_andi>
|
|
388 l.l<ldst>z\t%0, %1")
|
|
389
|
|
390 ;; Sign extension in registers is an optional extension, but the
|
|
391 ;; extending load is always available. If SEXT is not available,
|
|
392 ;; force the middle-end to do the expansion to shifts.
|
|
393
|
|
394 (define_insn "extend<mode>si2"
|
|
395 [(set (match_operand:SI 0 "register_operand" "=r,r")
|
|
396 (sign_extend:SI (match_operand:I12 1 "reg_or_mem_operand" "r,m")))]
|
|
397 "TARGET_SEXT"
|
|
398 "@
|
|
399 l.ext<ldst>s\t%0, %1
|
|
400 l.l<ldst>s\t%0, %1")
|
|
401
|
|
402 (define_insn "*extend<mode>si2_mem"
|
|
403 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
404 (sign_extend:SI (match_operand:I12 1 "memory_operand" "m")))]
|
|
405 ""
|
|
406 "l.l<ldst>s\t%0, %1")
|
|
407
|
|
408 ;; -------------------------------------------------------------------------
|
|
409 ;; Compare instructions
|
|
410 ;; -------------------------------------------------------------------------
|
|
411
|
|
412 ;; OpenRISC supports these integer comparisons:
|
|
413 ;;
|
|
414 ;; l.sfeq[i] - equality, r r or r i
|
|
415 ;; l.sfne[i] - not equal, r r or r i
|
|
416 ;; l.sflt{s,u}[i] - less than, signed or unsigned, r r or r i
|
|
417 ;; l.sfle{s,u}[i] - less than or equal, signed or unsigned, r r or r i
|
|
418 ;; l.sfgt{s,u}[i] - greater than, signed or unsigned, r r or r i
|
|
419 ;; l.sfge{s,u}[i] - greater than or equal, signed or unsigned, r r or r i
|
|
420 ;;
|
|
421 ;; EQ,NE,LT,LTU,LE,LEU,GT,GTU,GE,GEU
|
|
422 ;; We iterate through all of these
|
|
423 ;;
|
|
424
|
|
425 (define_code_iterator intcmpcc [ne eq lt ltu gt gtu ge le geu leu])
|
|
426 (define_code_attr insn [(ne "ne") (eq "eq") (lt "lts") (ltu "ltu")
|
|
427 (gt "gts") (gtu "gtu") (ge "ges") (le "les")
|
|
428 (geu "geu") (leu "leu")])
|
|
429
|
|
430 (define_insn "*sf_insn"
|
|
431 [(set (reg:BI SR_F_REGNUM)
|
|
432 (intcmpcc:BI (match_operand:SI 0 "reg_or_0_operand" "rO,rO")
|
|
433 (match_operand:SI 1 "reg_or_s16_operand" "r,I")))]
|
|
434 ""
|
|
435 "@
|
|
436 l.sf<insn>\t%r0, %1
|
|
437 l.sf<insn>i\t%r0, %1"
|
|
438 [(set_attr "insn_support" "*,sfimm")])
|
|
439
|
|
440 ;; Support FP comparisons too
|
|
441
|
|
442 ;; The OpenRISC FPU supports these comparisons:
|
|
443 ;;
|
|
444 ;; lf.sfeq.{d,s} - equality, r r, double or single precision
|
|
445 ;; lf.sfge.{d,s} - greater than or equal, r r, double or single precision
|
|
446 ;; lf.sfgt.{d,s} - greater than, r r, double or single precision
|
|
447 ;; lf.sfle.{d,s} - less than or equal, r r, double or single precision
|
|
448 ;; lf.sflt.{d,s} - less than, r r, double or single precision
|
|
449 ;; lf.sfne.{d,s} - not equal, r r, double or single precision
|
|
450 ;;
|
|
451 ;; Double precision is only supported on some hardware. Only register/register
|
|
452 ;; comparisons are supported. All comparisons are signed.
|
|
453
|
|
454 (define_code_iterator fpcmpcc [ne eq lt gt ge le uneq unle unlt ungt unge
|
|
455 unordered])
|
|
456 (define_code_attr fpcmpinsn [(ne "ne") (eq "eq") (lt "lt") (gt "gt") (ge "ge")
|
|
457 (le "le") (uneq "ueq") (unle "ule") (unlt "ult")
|
|
458 (ungt "ugt") (unge "uge") (unordered "un")])
|
|
459
|
|
460
|
|
461 (define_insn "*sf_fp_insn"
|
|
462 [(set (reg:BI SR_F_REGNUM)
|
|
463 (fpcmpcc:BI (match_operand:F 0 "register_operand" "<fr>")
|
|
464 (match_operand:F 1 "register_operand" "<fr>")))]
|
|
465 "TARGET_HARD_FLOAT"
|
|
466 "lf.sf<fpcmpinsn>.<f>\t%d0, %d1"
|
|
467 [(set_attr "type" "fpu")])
|
|
468
|
|
469
|
|
470 ;; -------------------------------------------------------------------------
|
|
471 ;; Conditional Store instructions
|
|
472 ;; -------------------------------------------------------------------------
|
|
473
|
|
474 (define_expand "cstoresi4"
|
|
475 [(set (match_operand:SI 0 "register_operand" "")
|
|
476 (if_then_else:SI
|
|
477 (match_operator 1 "comparison_operator"
|
|
478 [(match_operand:SI 2 "reg_or_0_operand" "")
|
|
479 (match_operand:SI 3 "reg_or_s16_operand" "")])
|
|
480 (match_dup 0)
|
|
481 (const_int 0)))]
|
|
482 ""
|
|
483 {
|
|
484 or1k_expand_compare (operands + 1);
|
|
485 PUT_MODE (operands[1], SImode);
|
|
486 emit_insn (gen_rtx_SET (operands[0], operands[1]));
|
|
487 DONE;
|
|
488 })
|
|
489
|
|
490 ;; Support FP cstores too
|
|
491 (define_expand "cstore<F:mode>4"
|
|
492 [(set (match_operand:SI 0 "register_operand" "")
|
|
493 (if_then_else:F
|
|
494 (match_operator 1 "fp_comparison_operator"
|
|
495 [(match_operand:F 2 "register_operand" "")
|
|
496 (match_operand:F 3 "register_operand" "")])
|
|
497 (match_dup 0)
|
|
498 (const_int 0)))]
|
|
499 "TARGET_HARD_FLOAT"
|
|
500 {
|
|
501 or1k_expand_compare (operands + 1);
|
|
502 PUT_MODE (operands[1], SImode);
|
|
503 emit_insn (gen_rtx_SET (operands[0], operands[1]));
|
|
504 DONE;
|
|
505 })
|
|
506
|
|
507 ;; Being able to "copy" SR_F to a general register is helpful for
|
|
508 ;; the atomic insns, wherein the usual usage is to test the success
|
|
509 ;; of the compare-and-swap. Representing the operation in this way,
|
|
510 ;; rather than exposing the cmov immediately, allows the optimizers
|
|
511 ;; to propagate the use of SR_F directly into a branch.
|
|
512
|
|
513 (define_expand "sne_sr_f"
|
|
514 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
515 (ne:SI (reg:BI SR_F_REGNUM) (const_int 0)))]
|
|
516 "")
|
|
517
|
|
518 (define_insn_and_split "*scc"
|
|
519 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
520 (match_operator:SI 1 "equality_comparison_operator"
|
|
521 [(reg:BI SR_F_REGNUM) (const_int 0)]))]
|
|
522 ""
|
|
523 "#"
|
|
524 "reload_completed"
|
|
525 [(set (match_dup 0) (const_int 1))
|
|
526 (set (match_dup 0)
|
|
527 (if_then_else:SI (match_dup 1)
|
|
528 (match_dup 0)
|
|
529 (const_int 0)))]
|
|
530 "")
|
|
531
|
|
532 (define_expand "mov<I:mode>cc"
|
|
533 [(set (match_operand:I 0 "register_operand" "")
|
|
534 (if_then_else:I (match_operand 1 "comparison_operator" "")
|
|
535 (match_operand:I 2 "reg_or_0_operand" "")
|
|
536 (match_operand:I 3 "reg_or_0_operand" "")))]
|
|
537 ""
|
|
538 {
|
|
539 rtx xops[3] = { operands[1], XEXP (operands[1], 0), XEXP (operands[1], 1) };
|
|
540 or1k_expand_compare (xops);
|
|
541 operands[1] = xops[0];
|
|
542 })
|
|
543
|
|
544 (define_insn_and_split "*cmov<I:mode>"
|
|
545 [(set (match_operand:I 0 "register_operand" "=r")
|
|
546 (if_then_else:I
|
|
547 (match_operator 3 "equality_comparison_operator"
|
|
548 [(reg:BI SR_F_REGNUM) (const_int 0)])
|
|
549 (match_operand:I 1 "reg_or_0_operand" "rO")
|
|
550 (match_operand:I 2 "reg_or_0_operand" "rO")))]
|
|
551 ""
|
|
552 {
|
|
553 return (GET_CODE (operands[3]) == NE
|
|
554 ? "l.cmov\t%0, %r1, %r2"
|
|
555 : "l.cmov\t%0, %r2, %r1");
|
|
556 }
|
|
557 "!TARGET_CMOV"
|
|
558 [(const_int 0)]
|
|
559 {
|
|
560 rtx x;
|
|
561 rtx label = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
|
|
562
|
|
563 /* Generated a *cbranch pattern. */
|
|
564 if (rtx_equal_p (operands[0], operands[2]))
|
|
565 {
|
|
566 PUT_CODE (operands[3], (GET_CODE (operands[3]) == NE) ? EQ : NE);
|
|
567 x = gen_rtx_IF_THEN_ELSE (VOIDmode, operands[3], label, pc_rtx);
|
|
568 emit_jump_insn (gen_rtx_SET (pc_rtx, x));
|
|
569 emit_move_insn (operands[0], operands[1]);
|
|
570 }
|
|
571 else
|
|
572 {
|
|
573 x = gen_rtx_IF_THEN_ELSE (VOIDmode, operands[3], label, pc_rtx);
|
|
574 emit_move_insn (operands[0], operands[1]);
|
|
575 emit_jump_insn (gen_rtx_SET (pc_rtx, x));
|
|
576 emit_move_insn (operands[0], operands[2]);
|
|
577 }
|
|
578
|
|
579 emit_label (XEXP (label, 0));
|
|
580 DONE;
|
|
581 })
|
|
582
|
|
583 ;; -------------------------------------------------------------------------
|
|
584 ;; Branch instructions
|
|
585 ;; -------------------------------------------------------------------------
|
|
586
|
|
587 (define_expand "cbranchsi4"
|
|
588 [(set (pc)
|
|
589 (if_then_else
|
|
590 (match_operator 0 "comparison_operator"
|
|
591 [(match_operand:SI 1 "reg_or_0_operand" "")
|
|
592 (match_operand:SI 2 "reg_or_s16_operand" "")])
|
|
593 (label_ref (match_operand 3 "" ""))
|
|
594 (pc)))]
|
|
595 ""
|
|
596 {
|
|
597 or1k_expand_compare (operands);
|
|
598 })
|
|
599
|
|
600 ;; Support FP branching
|
|
601
|
|
602 (define_expand "cbranch<F:mode>4"
|
|
603 [(set (pc)
|
|
604 (if_then_else
|
|
605 (match_operator 0 "fp_comparison_operator"
|
|
606 [(match_operand:F 1 "register_operand" "")
|
|
607 (match_operand:F 2 "register_operand" "")])
|
|
608 (label_ref (match_operand 3 "" ""))
|
|
609 (pc)))]
|
|
610 "TARGET_HARD_FLOAT"
|
|
611 {
|
|
612 or1k_expand_compare (operands);
|
|
613 })
|
|
614
|
|
615 (define_insn "*cbranch"
|
|
616 [(set (pc)
|
|
617 (if_then_else
|
|
618 (match_operator 1 "equality_comparison_operator"
|
|
619 [(reg:BI SR_F_REGNUM) (const_int 0)])
|
|
620 (label_ref (match_operand 0 "" ""))
|
|
621 (pc)))]
|
|
622 ""
|
|
623 {
|
|
624 return (GET_CODE (operands[1]) == NE
|
|
625 ? "l.bf\t%0%#"
|
|
626 : "l.bnf\t%0%#");
|
|
627 }
|
|
628 [(set_attr "type" "control")])
|
|
629
|
|
630 ;; -------------------------------------------------------------------------
|
|
631 ;; Jump instructions
|
|
632 ;; -------------------------------------------------------------------------
|
|
633
|
|
634 (define_insn "jump"
|
|
635 [(set (pc) (label_ref (match_operand 0 "" "")))]
|
|
636 ""
|
|
637 "l.j\t%0%#"
|
|
638 [(set_attr "type" "control")])
|
|
639
|
|
640 (define_insn "indirect_jump"
|
|
641 [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
|
|
642 ""
|
|
643 "l.jr\t%0%#"
|
|
644 [(set_attr "type" "control")])
|
|
645
|
|
646 ;; -------------------------------------------------------------------------
|
|
647 ;; Prologue & Epilogue
|
|
648 ;; -------------------------------------------------------------------------
|
|
649
|
|
650 (define_expand "prologue"
|
|
651 [(const_int 1)]
|
|
652 ""
|
|
653 {
|
|
654 or1k_expand_prologue ();
|
|
655 DONE;
|
|
656 })
|
|
657
|
|
658 ;; Expand epilogue as RTL
|
|
659 (define_expand "epilogue"
|
|
660 [(return)]
|
|
661 ""
|
|
662 {
|
|
663 or1k_expand_epilogue ();
|
|
664 emit_jump_insn (gen_simple_return ());
|
|
665 DONE;
|
|
666 })
|
|
667
|
|
668 (define_expand "sibcall_epilogue"
|
|
669 [(return)]
|
|
670 ""
|
|
671 {
|
|
672 or1k_expand_epilogue ();
|
|
673 /* Placing a USE of LR here, rather than as a REG_USE on the
|
|
674 sibcall itself, means that LR is not unnecessarily live
|
|
675 within the function itself, which would force creation of
|
|
676 a stack frame. */
|
|
677 emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, LR_REGNUM)));
|
|
678 DONE;
|
|
679 })
|
|
680
|
|
681 (define_expand "simple_return"
|
|
682 [(parallel [(simple_return) (use (match_dup 0))])]
|
|
683 ""
|
|
684 {
|
|
685 operands[0] = gen_rtx_REG (Pmode, LR_REGNUM);
|
|
686 })
|
|
687
|
|
688 (define_insn "*simple_return"
|
|
689 [(simple_return)
|
|
690 (use (match_operand:SI 0 "register_operand" "r"))]
|
|
691 ""
|
|
692 "l.jr\t%0%#"
|
|
693 [(set_attr "type" "control")])
|
|
694
|
|
695 (define_expand "eh_return"
|
|
696 [(use (match_operand 0 "general_operand"))]
|
|
697 ""
|
|
698 {
|
|
699 or1k_expand_eh_return (operands[0]);
|
|
700 DONE;
|
|
701 })
|
|
702
|
|
703 ;; This is a placeholder, during RA, in order to create the PIC regiter.
|
|
704 ;; We do this so that we don't unconditionally mark the LR register as
|
|
705 ;; clobbered. It is replaced during prologue generation with the proper
|
|
706 ;; set_got pattern below. This works because the set_got_tmp insn is the
|
|
707 ;; first insn in the stream and that it isn't moved during RA.
|
|
708 (define_insn "set_got_tmp"
|
|
709 [(set (match_operand:SI 0 "register_operand" "=t")
|
|
710 (unspec_volatile:SI [(const_int 0)] UNSPECV_SET_GOT))]
|
|
711 ""
|
|
712 {
|
|
713 gcc_unreachable ();
|
|
714 })
|
|
715
|
|
716 ;; The insn to initialize the GOT.
|
|
717 (define_insn "set_got"
|
|
718 [(set (match_operand:SI 0 "register_operand" "=t")
|
|
719 (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
|
|
720 (clobber (reg:SI LR_REGNUM))]
|
|
721 ""
|
|
722 {
|
|
723 return ("l.jal\t8\;"
|
|
724 " l.movhi\t%0, gotpchi(_GLOBAL_OFFSET_TABLE_-4)\;"
|
|
725 "l.ori\t%0, %0, gotpclo(_GLOBAL_OFFSET_TABLE_+0)\;"
|
|
726 "l.add\t%0, %0, r9");
|
|
727 }
|
|
728 [(set_attr "length" "16")
|
|
729 (set_attr "type" "multi")])
|
|
730
|
|
731 ;; Block memory operations from being scheduled across frame (de)allocation.
|
|
732 (define_insn "frame_addsi3"
|
|
733 [(set (match_operand:SI 0 "register_operand" "=r,r")
|
|
734 (plus:SI
|
|
735 (match_operand:SI 1 "register_operand" "%r,r")
|
|
736 (match_operand:SI 2 "reg_or_s16_operand" " r,I")))
|
|
737 (clobber (mem:BLK (scratch)))]
|
|
738 "reload_completed"
|
|
739 "@
|
|
740 l.add\t%0, %1, %2
|
|
741 l.addi\t%0, %1, %2")
|
|
742
|
|
743 ;; -------------------------------------------------------------------------
|
|
744 ;; Atomic Operations
|
|
745 ;; -------------------------------------------------------------------------
|
|
746
|
|
747 ;; Note that MULT stands in for the non-existant NAND rtx_code.
|
|
748 (define_code_iterator FETCHOP [plus minus ior xor and mult])
|
|
749
|
|
750 (define_code_attr fetchop_name
|
|
751 [(plus "add")
|
|
752 (minus "sub")
|
|
753 (ior "or")
|
|
754 (xor "xor")
|
|
755 (and "and")
|
|
756 (mult "nand")])
|
|
757
|
|
758 (define_code_attr fetchop_pred
|
|
759 [(plus "reg_or_s16_operand")
|
|
760 (minus "register_operand")
|
|
761 (ior "reg_or_u16_operand")
|
|
762 (xor "reg_or_s16_operand")
|
|
763 (and "reg_or_u16_operand")
|
|
764 (mult "reg_or_u16_operand")])
|
|
765
|
|
766 (define_expand "mem_thread_fence"
|
|
767 [(match_operand:SI 0 "const_int_operand" "")] ;; model
|
|
768 ""
|
|
769 {
|
|
770 memmodel model = memmodel_base (INTVAL (operands[0]));
|
|
771 if (model != MEMMODEL_RELAXED)
|
|
772 emit_insn (gen_msync ());
|
|
773 DONE;
|
|
774 })
|
|
775
|
|
776 (define_expand "msync"
|
|
777 [(set (match_dup 0) (unspec:BLK [(match_dup 0)] UNSPEC_MSYNC))]
|
|
778 ""
|
|
779 {
|
|
780 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
|
|
781 MEM_VOLATILE_P (operands[0]) = 1;
|
|
782 })
|
|
783
|
|
784 (define_insn "*msync"
|
|
785 [(set (match_operand:BLK 0 "" "")
|
|
786 (unspec:BLK [(match_dup 0)] UNSPEC_MSYNC))]
|
|
787 ""
|
|
788 "l.msync")
|
|
789
|
|
790 (define_insn "load_locked_si"
|
|
791 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
792 (unspec_volatile:SI
|
|
793 [(match_operand:SI 1 "memory_operand" "m")] UNSPECV_LL))]
|
|
794 ""
|
|
795 "l.lwa\t%0,%1"
|
|
796 [(set_attr "type" "ld")])
|
|
797
|
|
798 (define_insn "store_conditional_si"
|
|
799 [(set (reg:BI SR_F_REGNUM)
|
|
800 (unspec_volatile:BI [(const_int 0)] UNSPECV_SC))
|
|
801 (set (match_operand:SI 0 "memory_operand" "=m")
|
|
802 (match_operand:SI 1 "reg_or_0_operand" "rO"))]
|
|
803 ""
|
|
804 "l.swa\t%0,%r1"
|
|
805 [(set_attr "type" "st")])
|
|
806
|
|
807 (define_expand "atomic_compare_and_swapsi"
|
|
808 [(match_operand:SI 0 "register_operand") ;; bool output
|
|
809 (match_operand:SI 1 "register_operand") ;; val output
|
|
810 (match_operand:SI 2 "memory_operand") ;; memory
|
|
811 (match_operand:SI 3 "reg_or_s16_operand") ;; expected
|
|
812 (match_operand:SI 4 "reg_or_0_operand") ;; desired
|
|
813 (match_operand:SI 5 "const_int_operand") ;; is_weak
|
|
814 (match_operand:SI 6 "const_int_operand") ;; mod_s
|
|
815 (match_operand:SI 7 "const_int_operand")] ;; mod_f
|
|
816 ""
|
|
817 {
|
|
818 or1k_expand_atomic_compare_and_swap (operands);
|
|
819 DONE;
|
|
820 })
|
|
821
|
|
822 (define_expand "atomic_compare_and_swap<mode>"
|
|
823 [(match_operand:SI 0 "register_operand") ;; bool output
|
|
824 (match_operand:I12 1 "register_operand") ;; val output
|
|
825 (match_operand:I12 2 "memory_operand") ;; memory
|
|
826 (match_operand:I12 3 "register_operand") ;; expected
|
|
827 (match_operand:I12 4 "reg_or_0_operand") ;; desired
|
|
828 (match_operand:SI 5 "const_int_operand") ;; is_weak
|
|
829 (match_operand:SI 6 "const_int_operand") ;; mod_s
|
|
830 (match_operand:SI 7 "const_int_operand")] ;; mod_f
|
|
831 ""
|
|
832 {
|
|
833 or1k_expand_atomic_compare_and_swap_qihi (operands);
|
|
834 DONE;
|
|
835 })
|
|
836
|
|
837 (define_expand "atomic_exchangesi"
|
|
838 [(match_operand:SI 0 "register_operand") ;; output
|
|
839 (match_operand:SI 1 "memory_operand") ;; memory
|
|
840 (match_operand:SI 2 "reg_or_0_operand") ;; input
|
|
841 (match_operand:SI 3 "const_int_operand")] ;; model
|
|
842 ""
|
|
843 {
|
|
844 or1k_expand_atomic_exchange (operands);
|
|
845 DONE;
|
|
846 })
|
|
847
|
|
848 (define_expand "atomic_exchange<mode>"
|
|
849 [(match_operand:I12 0 "register_operand") ;; output
|
|
850 (match_operand:I12 1 "memory_operand") ;; memory
|
|
851 (match_operand:I12 2 "reg_or_0_operand") ;; input
|
|
852 (match_operand:SI 3 "const_int_operand")] ;; model
|
|
853 ""
|
|
854 {
|
|
855 or1k_expand_atomic_exchange_qihi (operands);
|
|
856 DONE;
|
|
857 })
|
|
858
|
|
859 (define_expand "atomic_<fetchop_name>si"
|
|
860 [(match_operand:SI 0 "memory_operand") ;; memory
|
|
861 (FETCHOP:SI (match_dup 0)
|
|
862 (match_operand:SI 1 "<fetchop_pred>")) ;; operand
|
|
863 (match_operand:SI 2 "const_int_operand")] ;; model
|
|
864 ""
|
|
865 {
|
|
866 or1k_expand_atomic_op (<CODE>, operands[0], operands[1], NULL, NULL);
|
|
867 DONE;
|
|
868 })
|
|
869
|
|
870 (define_expand "atomic_<fetchop_name><mode>"
|
|
871 [(match_operand:I12 0 "memory_operand") ;; memory
|
|
872 (FETCHOP:I12 (match_dup 0)
|
|
873 (match_operand:I12 1 "register_operand")) ;; operand
|
|
874 (match_operand:SI 2 "const_int_operand")] ;; model
|
|
875 ""
|
|
876 {
|
|
877 or1k_expand_atomic_op_qihi (<CODE>, operands[0], operands[1], NULL, NULL);
|
|
878 DONE;
|
|
879 })
|
|
880
|
|
881 (define_expand "atomic_fetch_<fetchop_name>si"
|
|
882 [(match_operand:SI 0 "register_operand" "") ;; output
|
|
883 (match_operand:SI 1 "memory_operand" "") ;; memory
|
|
884 (FETCHOP:SI (match_dup 1)
|
|
885 (match_operand:SI 2 "<fetchop_pred>" "")) ;; operand
|
|
886 (match_operand:SI 3 "const_int_operand" "")] ;; model
|
|
887 ""
|
|
888 {
|
|
889 or1k_expand_atomic_op (<CODE>, operands[1], operands[2], operands[0], NULL);
|
|
890 DONE;
|
|
891 })
|
|
892
|
|
893 (define_expand "atomic_fetch_<fetchop_name><mode>"
|
|
894 [(match_operand:I12 0 "register_operand" "") ;; output
|
|
895 (match_operand:I12 1 "memory_operand" "") ;; memory
|
|
896 (FETCHOP:I12 (match_dup 1)
|
|
897 (match_operand:I12 2 "<fetchop_pred>" "")) ;; operand
|
|
898 (match_operand:SI 3 "const_int_operand" "")] ;; model
|
|
899 ""
|
|
900 {
|
|
901 or1k_expand_atomic_op_qihi (<CODE>, operands[1], operands[2],
|
|
902 operands[0], NULL);
|
|
903 DONE;
|
|
904 })
|
|
905
|
|
906 (define_expand "atomic_<fetchop_name>_fetchsi"
|
|
907 [(match_operand:SI 0 "register_operand" "") ;; output
|
|
908 (match_operand:SI 1 "memory_operand" "") ;; memory
|
|
909 (FETCHOP:SI (match_dup 1)
|
|
910 (match_operand:SI 2 "<fetchop_pred>" "")) ;; operand
|
|
911 (match_operand:SI 3 "const_int_operand" "")] ;; model
|
|
912 ""
|
|
913 {
|
|
914 or1k_expand_atomic_op (<CODE>, operands[1], operands[2], NULL, operands[0]);
|
|
915 DONE;
|
|
916 })
|
|
917
|
|
918 (define_expand "atomic_<fetchop_name>_fetch<mode>"
|
|
919 [(match_operand:I12 0 "register_operand" "") ;; output
|
|
920 (match_operand:I12 1 "memory_operand" "") ;; memory
|
|
921 (FETCHOP:I12 (match_dup 1)
|
|
922 (match_operand:I12 2 "<fetchop_pred>" "")) ;; operand
|
|
923 (match_operand:SI 3 "const_int_operand" "")] ;; model
|
|
924 ""
|
|
925 {
|
|
926 or1k_expand_atomic_op_qihi (<CODE>, operands[1], operands[2],
|
|
927 NULL, operands[0]);
|
|
928 DONE;
|
|
929 })
|
|
930
|
|
931 ;; -------------------------------------------------------------------------
|
|
932 ;; Call Instructions
|
|
933 ;; -------------------------------------------------------------------------
|
|
934
|
|
935 ;; Leave these to last, as the modeless operand for call_value
|
|
936 ;; interferes with normal patterns.
|
|
937
|
|
938 (define_expand "call"
|
|
939 [(call (match_operand 0) (match_operand 1))]
|
|
940 ""
|
|
941 {
|
|
942 or1k_expand_call (NULL, operands[0], operands[1], false);
|
|
943 DONE;
|
|
944 })
|
|
945
|
|
946 (define_expand "sibcall"
|
|
947 [(call (match_operand 0) (match_operand 1))]
|
|
948 ""
|
|
949 {
|
|
950 or1k_expand_call (NULL, operands[0], operands[1], true);
|
|
951 DONE;
|
|
952 })
|
|
953
|
|
954 (define_expand "call_value"
|
|
955 [(set (match_operand 0) (call (match_operand 1) (match_operand 2)))]
|
|
956 ""
|
|
957 {
|
|
958 or1k_expand_call (operands[0], operands[1], operands[2], false);
|
|
959 DONE;
|
|
960 })
|
|
961
|
|
962 (define_expand "sibcall_value"
|
|
963 [(set (match_operand 0) (call (match_operand 1) (match_operand 2)))]
|
|
964 ""
|
|
965 {
|
|
966 or1k_expand_call (operands[0], operands[1], operands[2], true);
|
|
967 DONE;
|
|
968 })
|
|
969
|
|
970 (define_insn "*call"
|
|
971 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "r,s"))
|
|
972 (match_operand 1))
|
|
973 (clobber (reg:SI LR_REGNUM))]
|
|
974 "!SIBLING_CALL_P (insn)"
|
|
975 "@
|
|
976 l.jalr\t%0%#
|
|
977 l.jal\t%P0%#"
|
|
978 [(set_attr "type" "control")])
|
|
979
|
|
980 (define_insn "*sibcall"
|
|
981 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "c,s"))
|
|
982 (match_operand 1))]
|
|
983 "SIBLING_CALL_P (insn)"
|
|
984 "@
|
|
985 l.jr\t%0%#
|
|
986 l.j\t%P0%#"
|
|
987 [(set_attr "type" "control")])
|
|
988
|
|
989 (define_insn "*call_value"
|
|
990 [(set (match_operand 0)
|
|
991 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "r,s"))
|
|
992 (match_operand 2)))
|
|
993 (clobber (reg:SI LR_REGNUM))]
|
|
994 "!SIBLING_CALL_P (insn)"
|
|
995 "@
|
|
996 l.jalr\t%1%#
|
|
997 l.jal\t%P1%#"
|
|
998 [(set_attr "type" "control")])
|
|
999
|
|
1000 (define_insn "*sibcall_value"
|
|
1001 [(set (match_operand 0)
|
|
1002 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "c,s"))
|
|
1003 (match_operand 2)))]
|
|
1004 "SIBLING_CALL_P (insn)"
|
|
1005 "@
|
|
1006 l.jr\t%1%#
|
|
1007 l.j\t%P1%#"
|
|
1008 [(set_attr "type" "control")])
|