]>
Commit | Line | Data |
---|---|---|
e430824f | 1 | ;; Machine Description for Altera Nios II. |
23a5b65a | 2 | ;; Copyright (C) 2012-2014 Free Software Foundation, Inc. |
e430824f CLT |
3 | ;; Contributed by Jonah Graham (jgraham@altera.com) and |
4 | ;; Will Reece (wreece@altera.com). | |
5 | ;; Contributed by Mentor Graphics, Inc. | |
6 | ;; | |
7 | ;; This file is part of GCC. | |
8 | ;; | |
9 | ;; GCC is free software; you can redistribute it and/or modify | |
10 | ;; it under the terms of the GNU General Public License as published by | |
11 | ;; the Free Software Foundation; either version 3, or (at your option) | |
12 | ;; any later version. | |
13 | ;; | |
14 | ;; GCC is distributed in the hope that it will be useful, | |
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | ;; GNU General Public License for more details. | |
18 | ;; | |
19 | ;; You should have received a copy of the GNU General Public License | |
20 | ;; along with GCC; see the file COPYING3. If not see | |
21 | ;; <http://www.gnu.org/licenses/>. | |
22 | ||
23 | ;; Register numbers | |
24 | (define_constants | |
25 | [ | |
26 | (FIRST_RETVAL_REGNO 2) ; Return value registers | |
27 | (LAST_RETVAL_REGNO 3) ; | |
28 | (FIRST_ARG_REGNO 4) ; Argument registers | |
29 | (LAST_ARG_REGNO 7) ; | |
30 | ||
31 | (TP_REGNO 23) ; Thread pointer register | |
32 | (GP_REGNO 26) ; Global pointer register | |
33 | (FP_REGNO 28) ; Frame pointer register | |
34 | (EA_REGNO 29) ; Exception return address register | |
35 | (RA_REGNO 31) ; Return address register | |
36 | (LAST_GP_REG 31) ; Last general purpose register | |
37 | ||
38 | ;; Target register definitions | |
39 | (STATIC_CHAIN_REGNUM 12) | |
40 | (STACK_POINTER_REGNUM 27) | |
41 | (HARD_FRAME_POINTER_REGNUM 28) | |
42 | (PC_REGNUM 37) | |
43 | (FRAME_POINTER_REGNUM 38) | |
44 | (ARG_POINTER_REGNUM 39) | |
45 | (FIRST_PSEUDO_REGISTER 40) | |
46 | ] | |
47 | ) | |
48 | ||
49 | ;; Enumeration of UNSPECs | |
50 | ||
51 | (define_c_enum "unspecv" [ | |
52 | UNSPECV_BLOCKAGE | |
53 | UNSPECV_WRCTL | |
54 | UNSPECV_RDCTL | |
55 | UNSPECV_FWRX | |
56 | UNSPECV_FWRY | |
57 | UNSPECV_FRDXLO | |
58 | UNSPECV_FRDXHI | |
59 | UNSPECV_FRDY | |
60 | UNSPECV_CUSTOM_NXX | |
61 | UNSPECV_CUSTOM_XNXX | |
62 | UNSPECV_LDXIO | |
63 | UNSPECV_STXIO | |
64 | ]) | |
65 | ||
66 | (define_c_enum "unspec" [ | |
67 | UNSPEC_FCOS | |
68 | UNSPEC_FSIN | |
69 | UNSPEC_FTAN | |
70 | UNSPEC_FATAN | |
71 | UNSPEC_FEXP | |
72 | UNSPEC_FLOG | |
73 | UNSPEC_LOAD_GOT_REGISTER | |
74 | UNSPEC_PIC_SYM | |
75 | UNSPEC_PIC_CALL_SYM | |
76 | UNSPEC_TLS | |
77 | UNSPEC_TLS_LDM | |
78 | UNSPEC_LOAD_TLS_IE | |
79 | UNSPEC_ADD_TLS_LE | |
80 | UNSPEC_ADD_TLS_GD | |
81 | UNSPEC_ADD_TLS_LDM | |
82 | UNSPEC_ADD_TLS_LDO | |
83 | UNSPEC_EH_RETURN | |
84 | UNSPEC_SYNC | |
85 | ]) | |
86 | ||
87 | \f | |
88 | ;; Instruction scheduler | |
89 | ||
90 | ; No schedule info is currently available, using an assumption that no | |
91 | ; instruction can use the results of the previous instruction without | |
92 | ; incuring a stall. | |
93 | ||
94 | ; length of an instruction (in bytes) | |
95 | (define_attr "length" "" (const_int 4)) | |
96 | (define_attr "type" | |
97 | "unknown,complex,control,alu,cond_alu,st,ld,shift,mul,div,custom" | |
98 | (const_string "complex")) | |
99 | ||
100 | (define_asm_attributes | |
101 | [(set_attr "length" "4") | |
102 | (set_attr "type" "complex")]) | |
103 | ||
104 | (define_automaton "nios2") | |
105 | (automata_option "v") | |
106 | ;(automata_option "no-minimization") | |
107 | (automata_option "ndfa") | |
108 | ||
109 | ; The nios2 pipeline is fairly straightforward for the fast model. | |
110 | ; Every alu operation is pipelined so that an instruction can | |
111 | ; be issued every cycle. However, there are still potential | |
112 | ; stalls which this description tries to deal with. | |
113 | ||
114 | (define_cpu_unit "cpu" "nios2") | |
115 | ||
116 | (define_insn_reservation "complex" 1 | |
117 | (eq_attr "type" "complex") | |
118 | "cpu") | |
119 | ||
120 | (define_insn_reservation "control" 1 | |
121 | (eq_attr "type" "control") | |
122 | "cpu") | |
123 | ||
124 | (define_insn_reservation "alu" 1 | |
125 | (eq_attr "type" "alu") | |
126 | "cpu") | |
127 | ||
128 | (define_insn_reservation "cond_alu" 1 | |
129 | (eq_attr "type" "cond_alu") | |
130 | "cpu") | |
131 | ||
132 | (define_insn_reservation "st" 1 | |
133 | (eq_attr "type" "st") | |
134 | "cpu") | |
135 | ||
136 | (define_insn_reservation "custom" 1 | |
137 | (eq_attr "type" "custom") | |
138 | "cpu") | |
139 | ||
140 | ; shifts, muls and lds have three cycle latency | |
141 | (define_insn_reservation "ld" 3 | |
142 | (eq_attr "type" "ld") | |
143 | "cpu") | |
144 | ||
145 | (define_insn_reservation "shift" 3 | |
146 | (eq_attr "type" "shift") | |
147 | "cpu") | |
148 | ||
149 | (define_insn_reservation "mul" 3 | |
150 | (eq_attr "type" "mul") | |
151 | "cpu") | |
152 | ||
153 | (define_insn_reservation "div" 1 | |
154 | (eq_attr "type" "div") | |
155 | "cpu") | |
156 | ||
157 | (include "predicates.md") | |
158 | (include "constraints.md") | |
159 | ||
160 | \f | |
161 | ;; Move instructions | |
162 | ||
163 | (define_mode_iterator M [QI HI SI]) | |
164 | ||
165 | (define_expand "mov<mode>" | |
166 | [(set (match_operand:M 0 "nonimmediate_operand" "") | |
167 | (match_operand:M 1 "general_operand" ""))] | |
168 | "" | |
169 | { | |
170 | if (nios2_emit_move_sequence (operands, <MODE>mode)) | |
171 | DONE; | |
172 | }) | |
173 | ||
174 | (define_insn "movqi_internal" | |
175 | [(set (match_operand:QI 0 "nonimmediate_operand" "=m, r,r, r") | |
176 | (match_operand:QI 1 "general_operand" "rM,m,rM,I"))] | |
177 | "(register_operand (operands[0], QImode) | |
178 | || reg_or_0_operand (operands[1], QImode))" | |
179 | "@ | |
180 | stb%o0\\t%z1, %0 | |
181 | ldbu%o1\\t%0, %1 | |
182 | mov\\t%0, %z1 | |
183 | movi\\t%0, %1" | |
184 | [(set_attr "type" "st,ld,alu,alu")]) | |
185 | ||
186 | (define_insn "movhi_internal" | |
187 | [(set (match_operand:HI 0 "nonimmediate_operand" "=m, r,r, r") | |
188 | (match_operand:HI 1 "general_operand" "rM,m,rM,I"))] | |
189 | "(register_operand (operands[0], HImode) | |
190 | || reg_or_0_operand (operands[1], HImode))" | |
191 | "@ | |
192 | sth%o0\\t%z1, %0 | |
193 | ldhu%o1\\t%0, %1 | |
194 | mov\\t%0, %z1 | |
195 | movi\\t%0, %1" | |
196 | [(set_attr "type" "st,ld,alu,alu")]) | |
197 | ||
198 | (define_insn "movsi_internal" | |
199 | [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r, r,r,r,r,r") | |
200 | (match_operand:SI 1 "general_operand" "rM,m,rM,I,J,K,S,i"))] | |
201 | "(register_operand (operands[0], SImode) | |
202 | || reg_or_0_operand (operands[1], SImode))" | |
203 | "@ | |
204 | stw%o0\\t%z1, %0 | |
205 | ldw%o1\\t%0, %1 | |
206 | mov\\t%0, %z1 | |
207 | movi\\t%0, %1 | |
208 | movui\\t%0, %1 | |
209 | movhi\\t%0, %H1 | |
210 | addi\\t%0, gp, %%gprel(%1) | |
211 | movhi\\t%0, %H1\;addi\\t%0, %0, %L1" | |
212 | [(set_attr "type" "st,ld,alu,alu,alu,alu,alu,alu") | |
213 | (set_attr "length" "4,4,4,4,4,4,4,8")]) | |
214 | ||
215 | (define_mode_iterator BH [QI HI]) | |
216 | (define_mode_iterator BHW [QI HI SI]) | |
217 | (define_mode_attr bh [(QI "b") (HI "h")]) | |
218 | (define_mode_attr bhw [(QI "b") (HI "h") (SI "w")]) | |
219 | (define_mode_attr bhw_uns [(QI "bu") (HI "hu") (SI "w")]) | |
220 | ||
221 | (define_insn "ld<bhw_uns>io" | |
222 | [(set (match_operand:BHW 0 "register_operand" "=r") | |
223 | (unspec_volatile:BHW | |
224 | [(match_operand:BHW 1 "memory_operand" "m")] UNSPECV_LDXIO))] | |
225 | "" | |
226 | "ld<bhw_uns>io\\t%0, %1" | |
227 | [(set_attr "type" "ld")]) | |
228 | ||
229 | (define_expand "ld<bh>io" | |
230 | [(set (match_operand:BH 0 "register_operand" "=r") | |
231 | (match_operand:BH 1 "memory_operand" "m"))] | |
232 | "" | |
233 | { | |
234 | rtx tmp = gen_reg_rtx (SImode); | |
235 | emit_insn (gen_ld<bh>io_signed (tmp, operands[1])); | |
236 | emit_insn (gen_mov<mode> (operands[0], gen_lowpart (<MODE>mode, tmp))); | |
237 | DONE; | |
238 | }) | |
239 | ||
240 | (define_insn "ld<bh>io_signed" | |
241 | [(set (match_operand:SI 0 "register_operand" "=r") | |
242 | (sign_extend:SI | |
243 | (unspec_volatile:BH | |
244 | [(match_operand:BH 1 "memory_operand" "m")] UNSPECV_LDXIO)))] | |
245 | "" | |
246 | "ld<bh>io\\t%0, %1" | |
247 | [(set_attr "type" "ld")]) | |
248 | ||
249 | (define_insn "st<bhw>io" | |
250 | [(set (match_operand:BHW 0 "memory_operand" "=m") | |
251 | (unspec_volatile:BHW | |
252 | [(match_operand:BHW 1 "reg_or_0_operand" "rM")] UNSPECV_STXIO))] | |
253 | "" | |
254 | "st<bhw>io\\t%z1, %0" | |
255 | [(set_attr "type" "st")]) | |
256 | ||
257 | \f | |
258 | ;; QI to [HI, SI] extension patterns are collected together | |
259 | (define_mode_iterator QX [HI SI]) | |
260 | ||
261 | ;; Zero extension patterns | |
262 | (define_insn "zero_extendhisi2" | |
263 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
264 | (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] | |
265 | "" | |
266 | "@ | |
267 | andi\\t%0, %1, 0xffff | |
268 | ldhu%o1\\t%0, %1" | |
269 | [(set_attr "type" "alu,ld")]) | |
270 | ||
271 | (define_insn "zero_extendqi<mode>2" | |
272 | [(set (match_operand:QX 0 "register_operand" "=r,r") | |
273 | (zero_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))] | |
274 | "" | |
275 | "@ | |
276 | andi\\t%0, %1, 0xff | |
277 | ldbu%o1\\t%0, %1" | |
278 | [(set_attr "type" "alu,ld")]) | |
279 | ||
280 | ;; Sign extension patterns | |
281 | ||
282 | (define_insn "extendhisi2" | |
283 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
284 | (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] | |
285 | "" | |
286 | "@ | |
287 | # | |
288 | ldh%o1\\t%0, %1" | |
289 | [(set_attr "type" "alu,ld")]) | |
290 | ||
291 | (define_insn "extendqi<mode>2" | |
292 | [(set (match_operand:QX 0 "register_operand" "=r,r") | |
293 | (sign_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))] | |
294 | "" | |
295 | "@ | |
296 | # | |
297 | ldb%o1\\t%0, %1" | |
298 | [(set_attr "type" "alu,ld")]) | |
299 | ||
300 | ;; Split patterns for register alternative cases. | |
301 | (define_split | |
302 | [(set (match_operand:SI 0 "register_operand" "") | |
303 | (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] | |
304 | "reload_completed" | |
305 | [(set (match_dup 0) | |
306 | (and:SI (match_dup 1) (const_int 65535))) | |
307 | (set (match_dup 0) | |
308 | (xor:SI (match_dup 0) (const_int 32768))) | |
309 | (set (match_dup 0) | |
310 | (plus:SI (match_dup 0) (const_int -32768)))] | |
311 | "operands[1] = gen_lowpart (SImode, operands[1]);") | |
312 | ||
313 | (define_split | |
314 | [(set (match_operand:QX 0 "register_operand" "") | |
315 | (sign_extend:QX (match_operand:QI 1 "register_operand" "")))] | |
316 | "reload_completed" | |
317 | [(set (match_dup 0) | |
318 | (and:SI (match_dup 1) (const_int 255))) | |
319 | (set (match_dup 0) | |
320 | (xor:SI (match_dup 0) (const_int 128))) | |
321 | (set (match_dup 0) | |
322 | (plus:SI (match_dup 0) (const_int -128)))] | |
323 | "operands[0] = gen_lowpart (SImode, operands[0]); | |
324 | operands[1] = gen_lowpart (SImode, operands[1]);") | |
325 | ||
326 | \f | |
327 | ;; Arithmetic Operations | |
328 | ||
329 | (define_insn "addsi3" | |
330 | [(set (match_operand:SI 0 "register_operand" "=r") | |
331 | (plus:SI (match_operand:SI 1 "register_operand" "%r") | |
332 | (match_operand:SI 2 "add_regimm_operand" "rIT")))] | |
333 | "" | |
334 | "add%i2\\t%0, %1, %z2" | |
335 | [(set_attr "type" "alu")]) | |
336 | ||
337 | (define_insn "subsi3" | |
338 | [(set (match_operand:SI 0 "register_operand" "=r") | |
339 | (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rM") | |
340 | (match_operand:SI 2 "register_operand" "r")))] | |
341 | "" | |
342 | "sub\\t%0, %z1, %2" | |
343 | [(set_attr "type" "alu")]) | |
344 | ||
345 | (define_insn "mulsi3" | |
346 | [(set (match_operand:SI 0 "register_operand" "=r") | |
347 | (mult:SI (match_operand:SI 1 "register_operand" "%r") | |
348 | (match_operand:SI 2 "arith_operand" "rI")))] | |
349 | "TARGET_HAS_MUL" | |
350 | "mul%i2\\t%0, %1, %z2" | |
351 | [(set_attr "type" "mul")]) | |
352 | ||
353 | (define_expand "divsi3" | |
354 | [(set (match_operand:SI 0 "register_operand" "=r") | |
355 | (div:SI (match_operand:SI 1 "register_operand" "r") | |
356 | (match_operand:SI 2 "register_operand" "r")))] | |
357 | "" | |
358 | { | |
359 | if (!TARGET_HAS_DIV) | |
360 | { | |
361 | if (TARGET_FAST_SW_DIV) | |
362 | { | |
363 | nios2_emit_expensive_div (operands, SImode); | |
364 | DONE; | |
365 | } | |
366 | else | |
367 | FAIL; | |
368 | } | |
369 | }) | |
370 | ||
371 | (define_insn "divsi3_insn" | |
372 | [(set (match_operand:SI 0 "register_operand" "=r") | |
373 | (div:SI (match_operand:SI 1 "register_operand" "r") | |
374 | (match_operand:SI 2 "register_operand" "r")))] | |
375 | "TARGET_HAS_DIV" | |
376 | "div\\t%0, %1, %2" | |
377 | [(set_attr "type" "div")]) | |
378 | ||
379 | (define_insn "udivsi3" | |
380 | [(set (match_operand:SI 0 "register_operand" "=r") | |
381 | (udiv:SI (match_operand:SI 1 "register_operand" "r") | |
382 | (match_operand:SI 2 "register_operand" "r")))] | |
383 | "TARGET_HAS_DIV" | |
384 | "divu\\t%0, %1, %2" | |
385 | [(set_attr "type" "div")]) | |
386 | ||
387 | (define_code_iterator EXTEND [sign_extend zero_extend]) | |
388 | (define_code_attr us [(sign_extend "s") (zero_extend "u")]) | |
389 | (define_code_attr mul [(sign_extend "mul") (zero_extend "umul")]) | |
390 | ||
391 | (define_insn "<us>mulsi3_highpart" | |
392 | [(set (match_operand:SI 0 "register_operand" "=r") | |
393 | (truncate:SI | |
394 | (lshiftrt:DI | |
395 | (mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand" "r")) | |
396 | (EXTEND:DI (match_operand:SI 2 "register_operand" "r"))) | |
397 | (const_int 32))))] | |
398 | "TARGET_HAS_MULX" | |
399 | "mulx<us><us>\\t%0, %1, %2" | |
400 | [(set_attr "type" "mul")]) | |
401 | ||
402 | (define_expand "<mul>sidi3" | |
403 | [(set (match_operand:DI 0 "register_operand" "") | |
404 | (mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand" "")) | |
405 | (EXTEND:DI (match_operand:SI 2 "register_operand" ""))))] | |
406 | "TARGET_HAS_MULX" | |
407 | { | |
408 | rtx hi = gen_reg_rtx (SImode); | |
409 | rtx lo = gen_reg_rtx (SImode); | |
410 | ||
411 | emit_insn (gen_<us>mulsi3_highpart (hi, operands[1], operands[2])); | |
412 | emit_insn (gen_mulsi3 (lo, operands[1], operands[2])); | |
413 | emit_move_insn (gen_lowpart (SImode, operands[0]), lo); | |
414 | emit_move_insn (gen_highpart (SImode, operands[0]), hi); | |
415 | DONE; | |
416 | }) | |
417 | ||
418 | \f | |
419 | ;; Negate and ones complement | |
420 | ||
421 | (define_insn "negsi2" | |
422 | [(set (match_operand:SI 0 "register_operand" "=r") | |
423 | (neg:SI (match_operand:SI 1 "register_operand" "r")))] | |
424 | "" | |
425 | "sub\\t%0, zero, %1" | |
426 | [(set_attr "type" "alu")]) | |
427 | ||
428 | (define_insn "one_cmplsi2" | |
429 | [(set (match_operand:SI 0 "register_operand" "=r") | |
430 | (not:SI (match_operand:SI 1 "register_operand" "r")))] | |
431 | "" | |
432 | "nor\\t%0, zero, %1" | |
433 | [(set_attr "type" "alu")]) | |
434 | ||
435 | \f | |
436 | ;; Integer logical Operations | |
437 | ||
438 | (define_code_iterator LOGICAL [and ior xor]) | |
439 | (define_code_attr logical_asm [(and "and") (ior "or") (xor "xor")]) | |
440 | ||
441 | (define_insn "<code>si3" | |
442 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
443 | (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r,r") | |
444 | (match_operand:SI 2 "logical_operand" "rM,J,K")))] | |
445 | "" | |
446 | "@ | |
447 | <logical_asm>\\t%0, %1, %z2 | |
448 | <logical_asm>%i2\\t%0, %1, %2 | |
449 | <logical_asm>h%i2\\t%0, %1, %U2" | |
450 | [(set_attr "type" "alu")]) | |
451 | ||
452 | (define_insn "*norsi3" | |
453 | [(set (match_operand:SI 0 "register_operand" "=r") | |
454 | (and:SI (not:SI (match_operand:SI 1 "register_operand" "%r")) | |
455 | (not:SI (match_operand:SI 2 "register_operand" "r"))))] | |
456 | "" | |
457 | "nor\\t%0, %1, %2" | |
458 | [(set_attr "type" "alu")]) | |
459 | ||
460 | \f | |
461 | ;; Shift instructions | |
462 | ||
463 | (define_code_iterator SHIFT [ashift ashiftrt lshiftrt rotate]) | |
464 | (define_code_attr shift_op [(ashift "ashl") (ashiftrt "ashr") | |
465 | (lshiftrt "lshr") (rotate "rotl")]) | |
466 | (define_code_attr shift_asm [(ashift "sll") (ashiftrt "sra") | |
467 | (lshiftrt "srl") (rotate "rol")]) | |
468 | ||
469 | (define_insn "<shift_op>si3" | |
470 | [(set (match_operand:SI 0 "register_operand" "=r") | |
471 | (SHIFT:SI (match_operand:SI 1 "register_operand" "r") | |
472 | (match_operand:SI 2 "shift_operand" "rL")))] | |
473 | "" | |
474 | "<shift_asm>%i2\\t%0, %1, %z2" | |
475 | [(set_attr "type" "shift")]) | |
476 | ||
477 | (define_insn "rotrsi3" | |
478 | [(set (match_operand:SI 0 "register_operand" "=r") | |
479 | (rotatert:SI (match_operand:SI 1 "register_operand" "r") | |
480 | (match_operand:SI 2 "register_operand" "r")))] | |
481 | "" | |
482 | "ror\\t%0, %1, %2" | |
483 | [(set_attr "type" "shift")]) | |
484 | ||
485 | \f | |
486 | ;; Floating point instructions | |
487 | ||
488 | ;; Mode iterator for single/double float | |
489 | (define_mode_iterator F [SF DF]) | |
490 | (define_mode_attr f [(SF "s") (DF "d")]) | |
491 | ||
492 | ;; Basic arithmetic instructions | |
493 | (define_code_iterator FOP3 [plus minus mult div]) | |
494 | (define_code_attr fop3 [(plus "add") (minus "sub") (mult "mul") (div "div")]) | |
495 | ||
496 | (define_insn "<fop3><mode>3" | |
497 | [(set (match_operand:F 0 "register_operand" "=r") | |
498 | (FOP3:F (match_operand:F 1 "register_operand" "r") | |
499 | (match_operand:F 2 "register_operand" "r")))] | |
500 | "nios2_fpu_insn_enabled (n2fpu_f<fop3><f>)" | |
501 | { return nios2_fpu_insn_asm (n2fpu_f<fop3><f>); } | |
502 | [(set_attr "type" "custom")]) | |
503 | ||
504 | ;; Floating point min/max operations | |
505 | (define_code_iterator SMINMAX [smin smax]) | |
506 | (define_code_attr minmax [(smin "min") (smax "max")]) | |
507 | (define_insn "<code><mode>3" | |
508 | [(set (match_operand:F 0 "register_operand" "=r") | |
509 | (SMINMAX:F (match_operand:F 1 "register_operand" "r") | |
510 | (match_operand:F 2 "register_operand" "r")))] | |
511 | "nios2_fpu_insn_enabled (n2fpu_f<minmax><f>)" | |
512 | { return nios2_fpu_insn_asm (n2fpu_f<minmax><f>); } | |
513 | [(set_attr "type" "custom")]) | |
514 | ||
515 | ;; These 2-operand FP operations can be collected together | |
516 | (define_code_iterator FOP2 [abs neg sqrt]) | |
517 | (define_insn "<code><mode>2" | |
518 | [(set (match_operand:F 0 "register_operand" "=r") | |
519 | (FOP2:F (match_operand:F 1 "register_operand" "r")))] | |
520 | "nios2_fpu_insn_enabled (n2fpu_f<code><f>)" | |
521 | { return nios2_fpu_insn_asm (n2fpu_f<code><f>); } | |
522 | [(set_attr "type" "custom")]) | |
523 | ||
524 | ;; X, Y register access instructions | |
525 | (define_insn "nios2_fwrx" | |
526 | [(unspec_volatile [(match_operand:DF 0 "register_operand" "r")] UNSPECV_FWRX)] | |
527 | "nios2_fpu_insn_enabled (n2fpu_fwrx)" | |
528 | { return nios2_fpu_insn_asm (n2fpu_fwrx); } | |
529 | [(set_attr "type" "custom")]) | |
530 | ||
531 | (define_insn "nios2_fwry" | |
532 | [(unspec_volatile [(match_operand:SF 0 "register_operand" "r")] UNSPECV_FWRY)] | |
533 | "nios2_fpu_insn_enabled (n2fpu_fwry)" | |
534 | { return nios2_fpu_insn_asm (n2fpu_fwry); } | |
535 | [(set_attr "type" "custom")]) | |
536 | ||
537 | ;; The X, Y read insns uses an int iterator | |
538 | (define_int_iterator UNSPEC_READ_XY [UNSPECV_FRDXLO UNSPECV_FRDXHI | |
539 | UNSPECV_FRDY]) | |
540 | (define_int_attr read_xy [(UNSPECV_FRDXLO "frdxlo") (UNSPECV_FRDXHI "frdxhi") | |
541 | (UNSPECV_FRDY "frdy")]) | |
542 | (define_insn "nios2_<read_xy>" | |
543 | [(set (match_operand:SF 0 "register_operand" "=r") | |
544 | (unspec_volatile:SF [(const_int 0)] UNSPEC_READ_XY))] | |
545 | "nios2_fpu_insn_enabled (n2fpu_<read_xy>)" | |
546 | { return nios2_fpu_insn_asm (n2fpu_<read_xy>); } | |
547 | [(set_attr "type" "custom")]) | |
548 | ||
549 | ;; Various math functions | |
550 | (define_int_iterator MATHFUNC | |
551 | [UNSPEC_FCOS UNSPEC_FSIN UNSPEC_FTAN UNSPEC_FATAN UNSPEC_FEXP UNSPEC_FLOG]) | |
552 | (define_int_attr mathfunc [(UNSPEC_FCOS "cos") (UNSPEC_FSIN "sin") | |
553 | (UNSPEC_FTAN "tan") (UNSPEC_FATAN "atan") | |
554 | (UNSPEC_FEXP "exp") (UNSPEC_FLOG "log")]) | |
555 | ||
556 | (define_insn "<mathfunc><mode>2" | |
557 | [(set (match_operand:F 0 "register_operand" "=r") | |
558 | (unspec:F [(match_operand:F 1 "register_operand" "r")] MATHFUNC))] | |
559 | "nios2_fpu_insn_enabled (n2fpu_f<mathfunc><f>)" | |
560 | { return nios2_fpu_insn_asm (n2fpu_f<mathfunc><f>); } | |
561 | [(set_attr "type" "custom")]) | |
562 | ||
563 | ;; Converting between floating point and fixed point | |
564 | ||
565 | (define_code_iterator FLOAT [float unsigned_float]) | |
566 | (define_code_iterator FIX [fix unsigned_fix]) | |
567 | ||
568 | (define_code_attr conv_op [(float "float") (unsigned_float "floatuns") | |
569 | (fix "fix") (unsigned_fix "fixuns")]) | |
570 | (define_code_attr i [(float "i") (unsigned_float "u") | |
571 | (fix "i") (unsigned_fix "u")]) | |
572 | ||
573 | ;; Integer to float conversions | |
574 | (define_insn "<conv_op>si<mode>2" | |
575 | [(set (match_operand:F 0 "register_operand" "=r") | |
576 | (FLOAT:F (match_operand:SI 1 "register_operand" "r")))] | |
577 | "nios2_fpu_insn_enabled (n2fpu_float<i><f>)" | |
578 | { return nios2_fpu_insn_asm (n2fpu_float<i><f>); } | |
579 | [(set_attr "type" "custom")]) | |
580 | ||
581 | ;; Float to integer conversions | |
582 | (define_insn "<conv_op>_trunc<mode>si2" | |
583 | [(set (match_operand:SI 0 "register_operand" "=r") | |
584 | (FIX:SI (match_operand:F 1 "general_operand" "r")))] | |
585 | "nios2_fpu_insn_enabled (n2fpu_fix<f><i>)" | |
586 | { return nios2_fpu_insn_asm (n2fpu_fix<f><i>); } | |
587 | [(set_attr "type" "custom")]) | |
588 | ||
589 | (define_insn "extendsfdf2" | |
590 | [(set (match_operand:DF 0 "register_operand" "=r") | |
591 | (float_extend:DF (match_operand:SF 1 "general_operand" "r")))] | |
592 | "nios2_fpu_insn_enabled (n2fpu_fextsd)" | |
593 | { return nios2_fpu_insn_asm (n2fpu_fextsd); } | |
594 | [(set_attr "type" "custom")]) | |
595 | ||
596 | (define_insn "truncdfsf2" | |
597 | [(set (match_operand:SF 0 "register_operand" "=r") | |
598 | (float_truncate:SF (match_operand:DF 1 "general_operand" "r")))] | |
599 | "nios2_fpu_insn_enabled (n2fpu_ftruncds)" | |
600 | { return nios2_fpu_insn_asm (n2fpu_ftruncds); } | |
601 | [(set_attr "type" "custom")]) | |
602 | ||
603 | ||
604 | \f | |
605 | ;; Prologue, Epilogue and Return | |
606 | ||
607 | (define_expand "prologue" | |
608 | [(const_int 1)] | |
609 | "" | |
610 | { | |
611 | nios2_expand_prologue (); | |
612 | DONE; | |
613 | }) | |
614 | ||
615 | (define_expand "epilogue" | |
616 | [(return)] | |
617 | "" | |
618 | { | |
619 | nios2_expand_epilogue (false); | |
620 | DONE; | |
621 | }) | |
622 | ||
623 | (define_expand "sibcall_epilogue" | |
624 | [(return)] | |
625 | "" | |
626 | { | |
627 | nios2_expand_epilogue (true); | |
628 | DONE; | |
629 | }) | |
630 | ||
631 | (define_insn "return" | |
632 | [(simple_return)] | |
633 | "nios2_can_use_return_insn ()" | |
634 | "ret") | |
635 | ||
636 | (define_insn "simple_return" | |
637 | [(simple_return)] | |
638 | "" | |
639 | "ret") | |
640 | ||
641 | ;; Block any insns from being moved before this point, since the | |
642 | ;; profiling call to mcount can use various registers that aren't | |
643 | ;; saved or used to pass arguments. | |
644 | ||
645 | (define_insn "blockage" | |
646 | [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] | |
647 | "" | |
648 | "" | |
649 | [(set_attr "type" "unknown") | |
650 | (set_attr "length" "0")]) | |
651 | ||
652 | ;; This is used in compiling the unwind routines. | |
653 | (define_expand "eh_return" | |
654 | [(use (match_operand 0 "general_operand"))] | |
655 | "" | |
656 | { | |
657 | if (GET_MODE (operands[0]) != Pmode) | |
658 | operands[0] = convert_to_mode (Pmode, operands[0], 0); | |
659 | emit_insn (gen_eh_set_ra (operands[0])); | |
660 | DONE; | |
661 | }) | |
662 | ||
663 | ;; Modify the return address for EH return. We can't expand this | |
664 | ;; until we know where it will be put in the stack frame. | |
665 | ||
666 | (define_insn_and_split "eh_set_ra" | |
667 | [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN) | |
668 | (clobber (match_scratch:SI 1 "=&r"))] | |
669 | "" | |
670 | "#" | |
671 | "reload_completed" | |
672 | [(const_int 0)] | |
673 | { | |
674 | nios2_set_return_address (operands[0], operands[1]); | |
675 | DONE; | |
676 | }) | |
677 | ||
678 | \f | |
679 | ;; Jumps and calls | |
680 | ||
681 | ; Note that the assembler fixes up any out-of-range branch instructions not | |
682 | ; caught by the compiler branch shortening code. The sequence emitted by | |
683 | ; the assembler can be very inefficient, but it is correct for PIC code. | |
684 | ; For non-PIC we are better off converting to an absolute JMPI. | |
685 | ; | |
686 | ; Direct calls and sibcalls use the CALL and JMPI instructions, respectively. | |
687 | ; These instructions have an immediate operand that specifies the low 28 bits | |
688 | ; of the PC, effectively allowing direct calls within a 256MB memory segment. | |
689 | ; Per the Nios II Processor Reference Handbook, the linker is not required to | |
690 | ; check or adjust for overflow. | |
691 | ||
692 | (define_insn "indirect_jump" | |
693 | [(set (pc) (match_operand:SI 0 "register_operand" "r"))] | |
694 | "" | |
695 | "jmp\\t%0" | |
696 | [(set_attr "type" "control")]) | |
697 | ||
698 | (define_insn "jump" | |
699 | [(set (pc) | |
700 | (label_ref (match_operand 0 "" "")))] | |
701 | "" | |
702 | { | |
703 | if (flag_pic || get_attr_length (insn) == 4) | |
704 | return "br\\t%0"; | |
705 | else | |
706 | return "jmpi\\t%0"; | |
707 | } | |
708 | [(set_attr "type" "control") | |
709 | (set (attr "length") | |
710 | (if_then_else | |
711 | (and (ge (minus (match_dup 0) (pc)) (const_int -32768)) | |
712 | (le (minus (match_dup 0) (pc)) (const_int 32764))) | |
713 | (const_int 4) | |
714 | (const_int 8)))]) | |
715 | ||
716 | ||
717 | (define_expand "call" | |
718 | [(parallel [(call (match_operand 0 "" "") | |
719 | (match_operand 1 "" "")) | |
720 | (clobber (reg:SI RA_REGNO))])] | |
721 | "" | |
722 | "nios2_adjust_call_address (&operands[0]);") | |
723 | ||
724 | (define_expand "call_value" | |
725 | [(parallel [(set (match_operand 0 "" "") | |
726 | (call (match_operand 1 "" "") | |
727 | (match_operand 2 "" ""))) | |
728 | (clobber (reg:SI RA_REGNO))])] | |
729 | "" | |
730 | "nios2_adjust_call_address (&operands[1]);") | |
731 | ||
732 | (define_insn "*call" | |
733 | [(call (mem:QI (match_operand:SI 0 "call_operand" "i,r")) | |
734 | (match_operand 1 "" "")) | |
735 | (clobber (reg:SI RA_REGNO))] | |
736 | "" | |
737 | "@ | |
738 | call\\t%0 | |
739 | callr\\t%0" | |
740 | [(set_attr "type" "control")]) | |
741 | ||
742 | (define_insn "*call_value" | |
743 | [(set (match_operand 0 "" "") | |
744 | (call (mem:QI (match_operand:SI 1 "call_operand" "i,r")) | |
745 | (match_operand 2 "" ""))) | |
746 | (clobber (reg:SI RA_REGNO))] | |
747 | "" | |
748 | "@ | |
749 | call\\t%1 | |
750 | callr\\t%1" | |
751 | [(set_attr "type" "control")]) | |
752 | ||
753 | (define_expand "sibcall" | |
754 | [(parallel [(call (match_operand 0 "" "") | |
755 | (match_operand 1 "" "")) | |
756 | (return)])] | |
757 | "" | |
758 | "nios2_adjust_call_address (&operands[0]);") | |
759 | ||
760 | (define_expand "sibcall_value" | |
761 | [(parallel [(set (match_operand 0 "" "") | |
762 | (call (match_operand 1 "" "") | |
763 | (match_operand 2 "" ""))) | |
764 | (return)])] | |
765 | "" | |
766 | "nios2_adjust_call_address (&operands[1]);") | |
767 | ||
768 | (define_insn "*sibcall" | |
769 | [(call (mem:QI (match_operand:SI 0 "call_operand" "i,j")) | |
770 | (match_operand 1 "" "")) | |
771 | (return)] | |
772 | "" | |
773 | "@ | |
774 | jmpi\\t%0 | |
775 | jmp\\t%0" | |
776 | [(set_attr "type" "control")]) | |
777 | ||
778 | (define_insn "*sibcall_value" | |
779 | [(set (match_operand 0 "register_operand" "") | |
780 | (call (mem:QI (match_operand:SI 1 "call_operand" "i,j")) | |
781 | (match_operand 2 "" ""))) | |
782 | (return)] | |
783 | "" | |
784 | "@ | |
785 | jmpi\\t%1 | |
786 | jmp\\t%1" | |
787 | [(set_attr "type" "control")]) | |
788 | ||
789 | (define_expand "tablejump" | |
790 | [(parallel [(set (pc) (match_operand 0 "register_operand" "r")) | |
791 | (use (label_ref (match_operand 1 "" "")))])] | |
792 | "" | |
793 | { | |
794 | if (flag_pic) | |
795 | { | |
796 | /* Hopefully, CSE will eliminate this copy. */ | |
797 | rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1])); | |
798 | rtx reg2 = gen_reg_rtx (SImode); | |
799 | ||
800 | emit_insn (gen_addsi3 (reg2, operands[0], reg1)); | |
801 | operands[0] = reg2; | |
802 | } | |
803 | }) | |
804 | ||
805 | (define_insn "*tablejump" | |
806 | [(set (pc) | |
807 | (match_operand:SI 0 "register_operand" "r")) | |
808 | (use (label_ref (match_operand 1 "" "")))] | |
809 | "" | |
810 | "jmp\\t%0" | |
811 | [(set_attr "type" "control")]) | |
812 | ||
813 | \f | |
814 | ;; cstore, cbranch patterns | |
815 | ||
816 | (define_mode_iterator CM [SI SF DF]) | |
817 | ||
818 | (define_expand "cstore<mode>4" | |
819 | [(set (match_operand:SI 0 "register_operand" "=r") | |
820 | (match_operator:SI 1 "expandable_comparison_operator" | |
821 | [(match_operand:CM 2 "register_operand") | |
822 | (match_operand:CM 3 "nonmemory_operand")]))] | |
823 | "" | |
824 | { | |
825 | if (!nios2_validate_compare (<MODE>mode, &operands[1], &operands[2], | |
826 | &operands[3])) | |
827 | FAIL; | |
828 | }) | |
829 | ||
830 | (define_expand "cbranch<mode>4" | |
831 | [(set (pc) | |
832 | (if_then_else | |
833 | (match_operator 0 "expandable_comparison_operator" | |
834 | [(match_operand:CM 1 "register_operand") | |
835 | (match_operand:CM 2 "nonmemory_operand")]) | |
836 | (label_ref (match_operand 3 "")) | |
837 | (pc)))] | |
838 | "" | |
839 | { | |
840 | if (!nios2_validate_compare (<MODE>mode, &operands[0], &operands[1], | |
841 | &operands[2])) | |
842 | FAIL; | |
843 | if (GET_MODE_CLASS (<MODE>mode) == MODE_FLOAT | |
844 | || !reg_or_0_operand (operands[2], <MODE>mode)) | |
845 | { | |
846 | rtx condreg = gen_reg_rtx (SImode); | |
847 | emit_insn (gen_cstore<mode>4 | |
848 | (condreg, operands[0], operands[1], operands[2])); | |
849 | operands[1] = condreg; | |
850 | operands[2] = const0_rtx; | |
851 | operands[0] = gen_rtx_fmt_ee (NE, VOIDmode, condreg, const0_rtx); | |
852 | } | |
853 | }) | |
854 | ||
855 | (define_insn "nios2_cbranch" | |
856 | [(set (pc) | |
857 | (if_then_else | |
858 | (match_operator 0 "ordered_comparison_operator" | |
859 | [(match_operand:SI 1 "reg_or_0_operand" "rM") | |
860 | (match_operand:SI 2 "reg_or_0_operand" "rM")]) | |
861 | (label_ref (match_operand 3 "" "")) | |
862 | (pc)))] | |
863 | "" | |
864 | { | |
865 | if (flag_pic || get_attr_length (insn) == 4) | |
866 | return "b%0\t%z1, %z2, %l3"; | |
867 | else | |
868 | return "b%R0\t%z1, %z2, .+8;jmpi\t%l3"; | |
869 | } | |
870 | [(set_attr "type" "control") | |
871 | (set (attr "length") | |
872 | (if_then_else | |
873 | (and (ge (minus (match_dup 1) (pc)) (const_int -32768)) | |
874 | (le (minus (match_dup 1) (pc)) (const_int 32764))) | |
875 | (const_int 4) (const_int 8)))]) | |
876 | ||
877 | ;; Floating point comparisons | |
878 | (define_code_iterator FCMP [eq ne gt ge le lt]) | |
879 | (define_insn "nios2_s<code><mode>" | |
880 | [(set (match_operand:SI 0 "register_operand" "=r") | |
881 | (FCMP:SI (match_operand:F 1 "register_operand" "r") | |
882 | (match_operand:F 2 "register_operand" "r")))] | |
883 | "nios2_fpu_insn_enabled (n2fpu_fcmp<code><f>)" | |
884 | { return nios2_fpu_insn_asm (n2fpu_fcmp<code><f>); } | |
885 | [(set_attr "type" "custom")]) | |
886 | ||
887 | ;; Integer comparisons | |
888 | ||
889 | (define_code_iterator EQNE [eq ne]) | |
890 | (define_insn "nios2_cmp<code>" | |
891 | [(set (match_operand:SI 0 "register_operand" "=r") | |
892 | (EQNE:SI (match_operand:SI 1 "register_operand" "%r") | |
893 | (match_operand:SI 2 "arith_operand" "rI")))] | |
894 | "" | |
895 | "cmp<code>%i2\\t%0, %1, %z2" | |
896 | [(set_attr "type" "alu")]) | |
897 | ||
898 | (define_code_iterator SCMP [ge lt]) | |
899 | (define_insn "nios2_cmp<code>" | |
900 | [(set (match_operand:SI 0 "register_operand" "=r") | |
901 | (SCMP:SI (match_operand:SI 1 "reg_or_0_operand" "rM") | |
902 | (match_operand:SI 2 "arith_operand" "rI")))] | |
903 | "" | |
904 | "cmp<code>%i2\\t%0, %z1, %z2" | |
905 | [(set_attr "type" "alu")]) | |
906 | ||
907 | (define_code_iterator UCMP [geu ltu]) | |
908 | (define_insn "nios2_cmp<code>" | |
909 | [(set (match_operand:SI 0 "register_operand" "=r") | |
910 | (UCMP:SI (match_operand:SI 1 "reg_or_0_operand" "rM") | |
911 | (match_operand:SI 2 "uns_arith_operand" "rJ")))] | |
912 | "" | |
913 | "cmp<code>%i2\\t%0, %z1, %z2" | |
914 | [(set_attr "type" "alu")]) | |
915 | ||
916 | ||
917 | \f | |
918 | ;; Custom instruction patterns. The operands are intentionally | |
919 | ;; mode-less, to serve as generic carriers of all Altera defined | |
920 | ;; built-in instruction/function types. | |
921 | ||
922 | (define_insn "custom_nxx" | |
923 | [(unspec_volatile [(match_operand 0 "custom_insn_opcode" "N") | |
924 | (match_operand 1 "reg_or_0_operand" "rM") | |
925 | (match_operand 2 "reg_or_0_operand" "rM")] | |
926 | UNSPECV_CUSTOM_NXX)] | |
927 | "" | |
928 | "custom\\t%0, zero, %z1, %z2" | |
929 | [(set_attr "type" "custom")]) | |
930 | ||
931 | (define_insn "custom_xnxx" | |
932 | [(set (match_operand 0 "register_operand" "=r") | |
933 | (unspec_volatile [(match_operand 1 "custom_insn_opcode" "N") | |
934 | (match_operand 2 "reg_or_0_operand" "rM") | |
935 | (match_operand 3 "reg_or_0_operand" "rM")] | |
936 | UNSPECV_CUSTOM_XNXX))] | |
937 | "" | |
938 | "custom\\t%1, %0, %z2, %z3" | |
939 | [(set_attr "type" "custom")]) | |
940 | ||
941 | \f | |
942 | ;; Misc. patterns | |
943 | ||
944 | (define_insn "nop" | |
945 | [(const_int 0)] | |
946 | "" | |
947 | "nop" | |
948 | [(set_attr "type" "alu")]) | |
949 | ||
950 | ;; Connect 'sync' to 'memory_barrier' standard expand name | |
951 | (define_expand "memory_barrier" | |
952 | [(const_int 0)] | |
953 | "" | |
954 | { | |
955 | emit_insn (gen_sync ()); | |
956 | DONE; | |
957 | }) | |
958 | ||
959 | ;; For the nios2 __builtin_sync built-in function | |
960 | (define_expand "sync" | |
961 | [(set (match_dup 0) | |
962 | (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))] | |
963 | "" | |
964 | { | |
965 | operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); | |
966 | MEM_VOLATILE_P (operands[0]) = 1; | |
967 | }) | |
968 | ||
969 | (define_insn "*sync_insn" | |
970 | [(set (match_operand:BLK 0 "" "") | |
971 | (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))] | |
972 | "" | |
973 | "sync" | |
974 | [(set_attr "type" "control")]) | |
975 | ||
976 | (define_insn "rdctl" | |
977 | [(set (match_operand:SI 0 "register_operand" "=r") | |
978 | (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")] | |
979 | UNSPECV_RDCTL))] | |
980 | "" | |
981 | "rdctl\\t%0, ctl%1" | |
982 | [(set_attr "type" "control")]) | |
983 | ||
984 | (define_insn "wrctl" | |
985 | [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand" "O") | |
986 | (match_operand:SI 1 "reg_or_0_operand" "rM")] | |
987 | UNSPECV_WRCTL)] | |
988 | "" | |
989 | "wrctl\\tctl%0, %z1" | |
990 | [(set_attr "type" "control")]) | |
991 | ||
992 | ;; Trap patterns | |
993 | (define_insn "trap" | |
994 | [(trap_if (const_int 1) (const_int 3))] | |
995 | "" | |
996 | "break\\t3" | |
997 | [(set_attr "type" "control")]) | |
998 | ||
999 | (define_insn "ctrapsi4" | |
1000 | [(trap_if (match_operator 0 "ordered_comparison_operator" | |
1001 | [(match_operand:SI 1 "reg_or_0_operand" "rM") | |
1002 | (match_operand:SI 2 "reg_or_0_operand" "rM")]) | |
1003 | (match_operand 3 "const_int_operand" "i"))] | |
1004 | "" | |
1005 | "b%R0\\t%z1, %z2, 1f\;break\\t%3\;1:" | |
1006 | [(set_attr "type" "control") | |
1007 | (set_attr "length" "8")]) | |
1008 | ||
1009 | ;; Load the GOT register. | |
1010 | (define_insn "load_got_register" | |
1011 | [(set (match_operand:SI 0 "register_operand" "=&r") | |
1012 | (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER)) | |
1013 | (set (match_operand:SI 1 "register_operand" "=r") | |
1014 | (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))] | |
1015 | "" | |
1016 | "nextpc\\t%0 | |
1017 | \\t1: | |
02b67731 SL |
1018 | \\tmovhi\\t%1, %%hiadj(_gp_got - 1b) |
1019 | \\taddi\\t%1, %1, %%lo(_gp_got - 1b)" | |
e430824f CLT |
1020 | [(set_attr "length" "12")]) |
1021 | ||
1022 | ;; Read thread pointer register | |
1023 | (define_expand "get_thread_pointersi" | |
1024 | [(match_operand:SI 0 "register_operand" "=r")] | |
1025 | "TARGET_LINUX_ABI" | |
1026 | { | |
1027 | emit_move_insn (operands[0], gen_rtx_REG (Pmode, TP_REGNO)); | |
1028 | DONE; | |
1029 | }) |