]>
Commit | Line | Data |
---|---|---|
09cae750 PD |
1 | /* Subroutines used for code generation for RISC-V. |
2 | Copyright (C) 2011-2017 Free Software Foundation, Inc. | |
3 | Contributed by Andrew Waterman (andrew@sifive.com). | |
4 | Based on MIPS target for GNU compiler. | |
5 | ||
6 | This file is part of GCC. | |
7 | ||
8 | GCC is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 3, or (at your option) | |
11 | any later version. | |
12 | ||
13 | GCC is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with GCC; see the file COPYING3. If not see | |
20 | <http://www.gnu.org/licenses/>. */ | |
21 | ||
22 | #include "config.h" | |
23 | #include "system.h" | |
24 | #include "coretypes.h" | |
25 | #include "tm.h" | |
26 | #include "rtl.h" | |
27 | #include "regs.h" | |
09cae750 | 28 | #include "insn-config.h" |
09cae750 PD |
29 | #include "insn-attr.h" |
30 | #include "recog.h" | |
31 | #include "output.h" | |
09cae750 | 32 | #include "alias.h" |
09cae750 | 33 | #include "tree.h" |
314e6352 ML |
34 | #include "stringpool.h" |
35 | #include "attribs.h" | |
09cae750 | 36 | #include "varasm.h" |
09cae750 PD |
37 | #include "stor-layout.h" |
38 | #include "calls.h" | |
39 | #include "function.h" | |
09cae750 PD |
40 | #include "explow.h" |
41 | #include "memmodel.h" | |
42 | #include "emit-rtl.h" | |
09cae750 PD |
43 | #include "reload.h" |
44 | #include "tm_p.h" | |
09cae750 PD |
45 | #include "target.h" |
46 | #include "target-def.h" | |
09cae750 | 47 | #include "basic-block.h" |
1b68a156 JL |
48 | #include "expr.h" |
49 | #include "optabs.h" | |
09cae750 | 50 | #include "bitmap.h" |
09cae750 | 51 | #include "df.h" |
09cae750 | 52 | #include "diagnostic.h" |
09cae750 | 53 | #include "builtins.h" |
09cae750 PD |
54 | |
55 | /* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */ | |
56 | #define UNSPEC_ADDRESS_P(X) \ | |
57 | (GET_CODE (X) == UNSPEC \ | |
58 | && XINT (X, 1) >= UNSPEC_ADDRESS_FIRST \ | |
59 | && XINT (X, 1) < UNSPEC_ADDRESS_FIRST + NUM_SYMBOL_TYPES) | |
60 | ||
61 | /* Extract the symbol or label from UNSPEC wrapper X. */ | |
62 | #define UNSPEC_ADDRESS(X) \ | |
63 | XVECEXP (X, 0, 0) | |
64 | ||
65 | /* Extract the symbol type from UNSPEC wrapper X. */ | |
66 | #define UNSPEC_ADDRESS_TYPE(X) \ | |
67 | ((enum riscv_symbol_type) (XINT (X, 1) - UNSPEC_ADDRESS_FIRST)) | |
68 | ||
69 | /* True if bit BIT is set in VALUE. */ | |
70 | #define BITSET_P(VALUE, BIT) (((VALUE) & (1ULL << (BIT))) != 0) | |
71 | ||
72 | /* Classifies an address. | |
73 | ||
74 | ADDRESS_REG | |
75 | A natural register + offset address. The register satisfies | |
76 | riscv_valid_base_register_p and the offset is a const_arith_operand. | |
77 | ||
78 | ADDRESS_LO_SUM | |
79 | A LO_SUM rtx. The first operand is a valid base register and | |
80 | the second operand is a symbolic address. | |
81 | ||
82 | ADDRESS_CONST_INT | |
83 | A signed 16-bit constant address. | |
84 | ||
85 | ADDRESS_SYMBOLIC: | |
86 | A constant symbolic address. */ | |
87 | enum riscv_address_type { | |
88 | ADDRESS_REG, | |
89 | ADDRESS_LO_SUM, | |
90 | ADDRESS_CONST_INT, | |
91 | ADDRESS_SYMBOLIC | |
92 | }; | |
93 | ||
94 | /* Information about a function's frame layout. */ | |
95 | struct GTY(()) riscv_frame_info { | |
96 | /* The size of the frame in bytes. */ | |
97 | HOST_WIDE_INT total_size; | |
98 | ||
99 | /* Bit X is set if the function saves or restores GPR X. */ | |
100 | unsigned int mask; | |
101 | ||
102 | /* Likewise FPR X. */ | |
103 | unsigned int fmask; | |
104 | ||
105 | /* How much the GPR save/restore routines adjust sp (or 0 if unused). */ | |
106 | unsigned save_libcall_adjustment; | |
107 | ||
108 | /* Offsets of fixed-point and floating-point save areas from frame bottom */ | |
109 | HOST_WIDE_INT gp_sp_offset; | |
110 | HOST_WIDE_INT fp_sp_offset; | |
111 | ||
112 | /* Offset of virtual frame pointer from stack pointer/frame bottom */ | |
113 | HOST_WIDE_INT frame_pointer_offset; | |
114 | ||
115 | /* Offset of hard frame pointer from stack pointer/frame bottom */ | |
116 | HOST_WIDE_INT hard_frame_pointer_offset; | |
117 | ||
118 | /* The offset of arg_pointer_rtx from the bottom of the frame. */ | |
119 | HOST_WIDE_INT arg_pointer_offset; | |
120 | }; | |
121 | ||
122 | struct GTY(()) machine_function { | |
123 | /* The number of extra stack bytes taken up by register varargs. | |
124 | This area is allocated by the callee at the very top of the frame. */ | |
125 | int varargs_size; | |
126 | ||
127 | /* Memoized return value of leaf_function_p. <0 if false, >0 if true. */ | |
128 | int is_leaf; | |
129 | ||
130 | /* The current frame information, calculated by riscv_compute_frame_info. */ | |
131 | struct riscv_frame_info frame; | |
132 | }; | |
133 | ||
134 | /* Information about a single argument. */ | |
135 | struct riscv_arg_info { | |
136 | /* True if the argument is at least partially passed on the stack. */ | |
137 | bool stack_p; | |
138 | ||
139 | /* The number of integer registers allocated to this argument. */ | |
140 | unsigned int num_gprs; | |
141 | ||
142 | /* The offset of the first register used, provided num_gprs is nonzero. | |
143 | If passed entirely on the stack, the value is MAX_ARGS_IN_REGISTERS. */ | |
144 | unsigned int gpr_offset; | |
145 | ||
146 | /* The number of floating-point registers allocated to this argument. */ | |
147 | unsigned int num_fprs; | |
148 | ||
149 | /* The offset of the first register used, provided num_fprs is nonzero. */ | |
150 | unsigned int fpr_offset; | |
151 | }; | |
152 | ||
153 | /* Information about an address described by riscv_address_type. | |
154 | ||
155 | ADDRESS_CONST_INT | |
156 | No fields are used. | |
157 | ||
158 | ADDRESS_REG | |
159 | REG is the base register and OFFSET is the constant offset. | |
160 | ||
161 | ADDRESS_LO_SUM | |
162 | REG and OFFSET are the operands to the LO_SUM and SYMBOL_TYPE | |
163 | is the type of symbol it references. | |
164 | ||
165 | ADDRESS_SYMBOLIC | |
166 | SYMBOL_TYPE is the type of symbol that the address references. */ | |
167 | struct riscv_address_info { | |
168 | enum riscv_address_type type; | |
169 | rtx reg; | |
170 | rtx offset; | |
171 | enum riscv_symbol_type symbol_type; | |
172 | }; | |
173 | ||
174 | /* One stage in a constant building sequence. These sequences have | |
175 | the form: | |
176 | ||
177 | A = VALUE[0] | |
178 | A = A CODE[1] VALUE[1] | |
179 | A = A CODE[2] VALUE[2] | |
180 | ... | |
181 | ||
182 | where A is an accumulator, each CODE[i] is a binary rtl operation | |
183 | and each VALUE[i] is a constant integer. CODE[0] is undefined. */ | |
184 | struct riscv_integer_op { | |
185 | enum rtx_code code; | |
186 | unsigned HOST_WIDE_INT value; | |
187 | }; | |
188 | ||
189 | /* The largest number of operations needed to load an integer constant. | |
190 | The worst case is LUI, ADDI, SLLI, ADDI, SLLI, ADDI, SLLI, ADDI. */ | |
191 | #define RISCV_MAX_INTEGER_OPS 8 | |
192 | ||
193 | /* Costs of various operations on the different architectures. */ | |
194 | ||
195 | struct riscv_tune_info | |
196 | { | |
197 | unsigned short fp_add[2]; | |
198 | unsigned short fp_mul[2]; | |
199 | unsigned short fp_div[2]; | |
200 | unsigned short int_mul[2]; | |
201 | unsigned short int_div[2]; | |
202 | unsigned short issue_rate; | |
203 | unsigned short branch_cost; | |
204 | unsigned short memory_cost; | |
82285692 | 205 | bool slow_unaligned_access; |
09cae750 PD |
206 | }; |
207 | ||
208 | /* Information about one CPU we know about. */ | |
209 | struct riscv_cpu_info { | |
210 | /* This CPU's canonical name. */ | |
211 | const char *name; | |
212 | ||
213 | /* Tuning parameters for this CPU. */ | |
214 | const struct riscv_tune_info *tune_info; | |
215 | }; | |
216 | ||
217 | /* Global variables for machine-dependent things. */ | |
218 | ||
82285692 | 219 | /* Whether unaligned accesses execute very slowly. */ |
e0bd6c9f | 220 | static bool riscv_slow_unaligned_access_p; |
82285692 | 221 | |
09cae750 PD |
222 | /* Which tuning parameters to use. */ |
223 | static const struct riscv_tune_info *tune_info; | |
224 | ||
225 | /* Index R is the smallest register class that contains register R. */ | |
226 | const enum reg_class riscv_regno_to_class[FIRST_PSEUDO_REGISTER] = { | |
227 | GR_REGS, GR_REGS, GR_REGS, GR_REGS, | |
228 | GR_REGS, GR_REGS, SIBCALL_REGS, SIBCALL_REGS, | |
229 | JALR_REGS, JALR_REGS, JALR_REGS, JALR_REGS, | |
230 | JALR_REGS, JALR_REGS, JALR_REGS, JALR_REGS, | |
231 | JALR_REGS, JALR_REGS, JALR_REGS, JALR_REGS, | |
232 | JALR_REGS, JALR_REGS, JALR_REGS, JALR_REGS, | |
233 | JALR_REGS, JALR_REGS, JALR_REGS, JALR_REGS, | |
234 | SIBCALL_REGS, SIBCALL_REGS, SIBCALL_REGS, SIBCALL_REGS, | |
235 | FP_REGS, FP_REGS, FP_REGS, FP_REGS, | |
236 | FP_REGS, FP_REGS, FP_REGS, FP_REGS, | |
237 | FP_REGS, FP_REGS, FP_REGS, FP_REGS, | |
238 | FP_REGS, FP_REGS, FP_REGS, FP_REGS, | |
239 | FP_REGS, FP_REGS, FP_REGS, FP_REGS, | |
240 | FP_REGS, FP_REGS, FP_REGS, FP_REGS, | |
241 | FP_REGS, FP_REGS, FP_REGS, FP_REGS, | |
242 | FP_REGS, FP_REGS, FP_REGS, FP_REGS, | |
243 | FRAME_REGS, FRAME_REGS, | |
244 | }; | |
245 | ||
246 | /* Costs to use when optimizing for rocket. */ | |
247 | static const struct riscv_tune_info rocket_tune_info = { | |
248 | {COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_add */ | |
249 | {COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_mul */ | |
250 | {COSTS_N_INSNS (20), COSTS_N_INSNS (20)}, /* fp_div */ | |
251 | {COSTS_N_INSNS (4), COSTS_N_INSNS (4)}, /* int_mul */ | |
252 | {COSTS_N_INSNS (6), COSTS_N_INSNS (6)}, /* int_div */ | |
253 | 1, /* issue_rate */ | |
254 | 3, /* branch_cost */ | |
82285692 AW |
255 | 5, /* memory_cost */ |
256 | true, /* slow_unaligned_access */ | |
09cae750 PD |
257 | }; |
258 | ||
259 | /* Costs to use when optimizing for size. */ | |
260 | static const struct riscv_tune_info optimize_size_tune_info = { | |
261 | {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* fp_add */ | |
262 | {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* fp_mul */ | |
263 | {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* fp_div */ | |
264 | {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* int_mul */ | |
265 | {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* int_div */ | |
266 | 1, /* issue_rate */ | |
267 | 1, /* branch_cost */ | |
82285692 AW |
268 | 2, /* memory_cost */ |
269 | false, /* slow_unaligned_access */ | |
09cae750 PD |
270 | }; |
271 | ||
272 | /* A table describing all the processors GCC knows about. */ | |
273 | static const struct riscv_cpu_info riscv_cpu_info_table[] = { | |
274 | { "rocket", &rocket_tune_info }, | |
82285692 | 275 | { "size", &optimize_size_tune_info }, |
09cae750 PD |
276 | }; |
277 | ||
278 | /* Return the riscv_cpu_info entry for the given name string. */ | |
279 | ||
280 | static const struct riscv_cpu_info * | |
281 | riscv_parse_cpu (const char *cpu_string) | |
282 | { | |
283 | for (unsigned i = 0; i < ARRAY_SIZE (riscv_cpu_info_table); i++) | |
284 | if (strcmp (riscv_cpu_info_table[i].name, cpu_string) == 0) | |
285 | return riscv_cpu_info_table + i; | |
286 | ||
287 | error ("unknown cpu %qs for -mtune", cpu_string); | |
288 | return riscv_cpu_info_table; | |
289 | } | |
290 | ||
291 | /* Helper function for riscv_build_integer; arguments are as for | |
292 | riscv_build_integer. */ | |
293 | ||
294 | static int | |
295 | riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS], | |
b8506a8a | 296 | HOST_WIDE_INT value, machine_mode mode) |
09cae750 PD |
297 | { |
298 | HOST_WIDE_INT low_part = CONST_LOW_PART (value); | |
299 | int cost = RISCV_MAX_INTEGER_OPS + 1, alt_cost; | |
300 | struct riscv_integer_op alt_codes[RISCV_MAX_INTEGER_OPS]; | |
301 | ||
302 | if (SMALL_OPERAND (value) || LUI_OPERAND (value)) | |
303 | { | |
304 | /* Simply ADDI or LUI. */ | |
305 | codes[0].code = UNKNOWN; | |
306 | codes[0].value = value; | |
307 | return 1; | |
308 | } | |
309 | ||
310 | /* End with ADDI. When constructing HImode constants, do not generate any | |
311 | intermediate value that is not itself a valid HImode constant. The | |
312 | XORI case below will handle those remaining HImode constants. */ | |
01726bc9 KT |
313 | if (low_part != 0 |
314 | && (mode != HImode | |
315 | || value - low_part <= ((1 << (GET_MODE_BITSIZE (HImode) - 1)) - 1))) | |
09cae750 PD |
316 | { |
317 | alt_cost = 1 + riscv_build_integer_1 (alt_codes, value - low_part, mode); | |
318 | if (alt_cost < cost) | |
319 | { | |
320 | alt_codes[alt_cost-1].code = PLUS; | |
321 | alt_codes[alt_cost-1].value = low_part; | |
322 | memcpy (codes, alt_codes, sizeof (alt_codes)); | |
323 | cost = alt_cost; | |
324 | } | |
325 | } | |
326 | ||
327 | /* End with XORI. */ | |
328 | if (cost > 2 && (low_part < 0 || mode == HImode)) | |
329 | { | |
330 | alt_cost = 1 + riscv_build_integer_1 (alt_codes, value ^ low_part, mode); | |
331 | if (alt_cost < cost) | |
332 | { | |
333 | alt_codes[alt_cost-1].code = XOR; | |
334 | alt_codes[alt_cost-1].value = low_part; | |
335 | memcpy (codes, alt_codes, sizeof (alt_codes)); | |
336 | cost = alt_cost; | |
337 | } | |
338 | } | |
339 | ||
340 | /* Eliminate trailing zeros and end with SLLI. */ | |
341 | if (cost > 2 && (value & 1) == 0) | |
342 | { | |
343 | int shift = ctz_hwi (value); | |
344 | unsigned HOST_WIDE_INT x = value; | |
345 | x = sext_hwi (x >> shift, HOST_BITS_PER_WIDE_INT - shift); | |
346 | ||
347 | /* Don't eliminate the lower 12 bits if LUI might apply. */ | |
348 | if (shift > IMM_BITS && !SMALL_OPERAND (x) && LUI_OPERAND (x << IMM_BITS)) | |
349 | shift -= IMM_BITS, x <<= IMM_BITS; | |
350 | ||
351 | alt_cost = 1 + riscv_build_integer_1 (alt_codes, x, mode); | |
352 | if (alt_cost < cost) | |
353 | { | |
354 | alt_codes[alt_cost-1].code = ASHIFT; | |
355 | alt_codes[alt_cost-1].value = shift; | |
356 | memcpy (codes, alt_codes, sizeof (alt_codes)); | |
357 | cost = alt_cost; | |
358 | } | |
359 | } | |
360 | ||
361 | gcc_assert (cost <= RISCV_MAX_INTEGER_OPS); | |
362 | return cost; | |
363 | } | |
364 | ||
365 | /* Fill CODES with a sequence of rtl operations to load VALUE. | |
366 | Return the number of operations needed. */ | |
367 | ||
368 | static int | |
369 | riscv_build_integer (struct riscv_integer_op *codes, HOST_WIDE_INT value, | |
b8506a8a | 370 | machine_mode mode) |
09cae750 PD |
371 | { |
372 | int cost = riscv_build_integer_1 (codes, value, mode); | |
373 | ||
374 | /* Eliminate leading zeros and end with SRLI. */ | |
375 | if (value > 0 && cost > 2) | |
376 | { | |
377 | struct riscv_integer_op alt_codes[RISCV_MAX_INTEGER_OPS]; | |
378 | int alt_cost, shift = clz_hwi (value); | |
379 | HOST_WIDE_INT shifted_val; | |
380 | ||
381 | /* Try filling trailing bits with 1s. */ | |
382 | shifted_val = (value << shift) | ((((HOST_WIDE_INT) 1) << shift) - 1); | |
383 | alt_cost = 1 + riscv_build_integer_1 (alt_codes, shifted_val, mode); | |
384 | if (alt_cost < cost) | |
385 | { | |
386 | alt_codes[alt_cost-1].code = LSHIFTRT; | |
387 | alt_codes[alt_cost-1].value = shift; | |
388 | memcpy (codes, alt_codes, sizeof (alt_codes)); | |
389 | cost = alt_cost; | |
390 | } | |
391 | ||
392 | /* Try filling trailing bits with 0s. */ | |
393 | shifted_val = value << shift; | |
394 | alt_cost = 1 + riscv_build_integer_1 (alt_codes, shifted_val, mode); | |
395 | if (alt_cost < cost) | |
396 | { | |
397 | alt_codes[alt_cost-1].code = LSHIFTRT; | |
398 | alt_codes[alt_cost-1].value = shift; | |
399 | memcpy (codes, alt_codes, sizeof (alt_codes)); | |
400 | cost = alt_cost; | |
401 | } | |
402 | } | |
403 | ||
404 | return cost; | |
405 | } | |
406 | ||
407 | /* Return the cost of constructing VAL in the event that a scratch | |
408 | register is available. */ | |
409 | ||
410 | static int | |
411 | riscv_split_integer_cost (HOST_WIDE_INT val) | |
412 | { | |
413 | int cost; | |
414 | unsigned HOST_WIDE_INT loval = sext_hwi (val, 32); | |
415 | unsigned HOST_WIDE_INT hival = sext_hwi ((val - loval) >> 32, 32); | |
416 | struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS]; | |
417 | ||
418 | cost = 2 + riscv_build_integer (codes, loval, VOIDmode); | |
419 | if (loval != hival) | |
420 | cost += riscv_build_integer (codes, hival, VOIDmode); | |
421 | ||
422 | return cost; | |
423 | } | |
424 | ||
425 | /* Return the cost of constructing the integer constant VAL. */ | |
426 | ||
427 | static int | |
428 | riscv_integer_cost (HOST_WIDE_INT val) | |
429 | { | |
430 | struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS]; | |
431 | return MIN (riscv_build_integer (codes, val, VOIDmode), | |
432 | riscv_split_integer_cost (val)); | |
433 | } | |
434 | ||
435 | /* Try to split a 64b integer into 32b parts, then reassemble. */ | |
436 | ||
437 | static rtx | |
b8506a8a | 438 | riscv_split_integer (HOST_WIDE_INT val, machine_mode mode) |
09cae750 PD |
439 | { |
440 | unsigned HOST_WIDE_INT loval = sext_hwi (val, 32); | |
441 | unsigned HOST_WIDE_INT hival = sext_hwi ((val - loval) >> 32, 32); | |
442 | rtx hi = gen_reg_rtx (mode), lo = gen_reg_rtx (mode); | |
443 | ||
444 | riscv_move_integer (hi, hi, hival); | |
445 | riscv_move_integer (lo, lo, loval); | |
446 | ||
447 | hi = gen_rtx_fmt_ee (ASHIFT, mode, hi, GEN_INT (32)); | |
448 | hi = force_reg (mode, hi); | |
449 | ||
450 | return gen_rtx_fmt_ee (PLUS, mode, hi, lo); | |
451 | } | |
452 | ||
453 | /* Return true if X is a thread-local symbol. */ | |
454 | ||
455 | static bool | |
456 | riscv_tls_symbol_p (const_rtx x) | |
457 | { | |
458 | return SYMBOL_REF_P (x) && SYMBOL_REF_TLS_MODEL (x) != 0; | |
459 | } | |
460 | ||
461 | /* Return true if symbol X binds locally. */ | |
462 | ||
463 | static bool | |
464 | riscv_symbol_binds_local_p (const_rtx x) | |
465 | { | |
466 | if (SYMBOL_REF_P (x)) | |
467 | return (SYMBOL_REF_DECL (x) | |
468 | ? targetm.binds_local_p (SYMBOL_REF_DECL (x)) | |
469 | : SYMBOL_REF_LOCAL_P (x)); | |
470 | else | |
471 | return false; | |
472 | } | |
473 | ||
474 | /* Return the method that should be used to access SYMBOL_REF or | |
475 | LABEL_REF X. */ | |
476 | ||
477 | static enum riscv_symbol_type | |
478 | riscv_classify_symbol (const_rtx x) | |
479 | { | |
480 | if (riscv_tls_symbol_p (x)) | |
481 | return SYMBOL_TLS; | |
482 | ||
483 | if (GET_CODE (x) == SYMBOL_REF && flag_pic && !riscv_symbol_binds_local_p (x)) | |
484 | return SYMBOL_GOT_DISP; | |
485 | ||
486 | return riscv_cmodel == CM_MEDLOW ? SYMBOL_ABSOLUTE : SYMBOL_PCREL; | |
487 | } | |
488 | ||
489 | /* Classify the base of symbolic expression X. */ | |
490 | ||
491 | enum riscv_symbol_type | |
492 | riscv_classify_symbolic_expression (rtx x) | |
493 | { | |
494 | rtx offset; | |
495 | ||
496 | split_const (x, &x, &offset); | |
497 | if (UNSPEC_ADDRESS_P (x)) | |
498 | return UNSPEC_ADDRESS_TYPE (x); | |
499 | ||
500 | return riscv_classify_symbol (x); | |
501 | } | |
502 | ||
503 | /* Return true if X is a symbolic constant. If it is, store the type of | |
504 | the symbol in *SYMBOL_TYPE. */ | |
505 | ||
506 | bool | |
507 | riscv_symbolic_constant_p (rtx x, enum riscv_symbol_type *symbol_type) | |
508 | { | |
509 | rtx offset; | |
510 | ||
511 | split_const (x, &x, &offset); | |
512 | if (UNSPEC_ADDRESS_P (x)) | |
513 | { | |
514 | *symbol_type = UNSPEC_ADDRESS_TYPE (x); | |
515 | x = UNSPEC_ADDRESS (x); | |
516 | } | |
517 | else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) | |
518 | *symbol_type = riscv_classify_symbol (x); | |
519 | else | |
520 | return false; | |
521 | ||
522 | if (offset == const0_rtx) | |
523 | return true; | |
524 | ||
525 | /* Nonzero offsets are only valid for references that don't use the GOT. */ | |
526 | switch (*symbol_type) | |
527 | { | |
528 | case SYMBOL_ABSOLUTE: | |
529 | case SYMBOL_PCREL: | |
530 | case SYMBOL_TLS_LE: | |
531 | /* GAS rejects offsets outside the range [-2^31, 2^31-1]. */ | |
532 | return sext_hwi (INTVAL (offset), 32) == INTVAL (offset); | |
533 | ||
534 | default: | |
535 | return false; | |
536 | } | |
537 | } | |
538 | ||
539 | /* Returns the number of instructions necessary to reference a symbol. */ | |
540 | ||
541 | static int riscv_symbol_insns (enum riscv_symbol_type type) | |
542 | { | |
543 | switch (type) | |
544 | { | |
545 | case SYMBOL_TLS: return 0; /* Depends on the TLS model. */ | |
546 | case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference. */ | |
547 | case SYMBOL_PCREL: return 2; /* AUIPC + the reference. */ | |
548 | case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference. */ | |
549 | case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference. */ | |
550 | default: gcc_unreachable (); | |
551 | } | |
552 | } | |
553 | ||
554 | /* Implement TARGET_LEGITIMATE_CONSTANT_P. */ | |
555 | ||
556 | static bool | |
b8506a8a | 557 | riscv_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x) |
09cae750 PD |
558 | { |
559 | return riscv_const_insns (x) > 0; | |
560 | } | |
561 | ||
562 | /* Implement TARGET_CANNOT_FORCE_CONST_MEM. */ | |
563 | ||
564 | static bool | |
b8506a8a | 565 | riscv_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x) |
09cae750 PD |
566 | { |
567 | enum riscv_symbol_type type; | |
568 | rtx base, offset; | |
569 | ||
570 | /* There is no assembler syntax for expressing an address-sized | |
571 | high part. */ | |
572 | if (GET_CODE (x) == HIGH) | |
573 | return true; | |
574 | ||
575 | split_const (x, &base, &offset); | |
576 | if (riscv_symbolic_constant_p (base, &type)) | |
577 | { | |
578 | /* As an optimization, don't spill symbolic constants that are as | |
579 | cheap to rematerialize as to access in the constant pool. */ | |
580 | if (SMALL_OPERAND (INTVAL (offset)) && riscv_symbol_insns (type) > 0) | |
581 | return true; | |
582 | ||
583 | /* As an optimization, avoid needlessly generate dynamic relocations. */ | |
584 | if (flag_pic) | |
585 | return true; | |
586 | } | |
587 | ||
588 | /* TLS symbols must be computed by riscv_legitimize_move. */ | |
589 | if (tls_referenced_p (x)) | |
590 | return true; | |
591 | ||
592 | return false; | |
593 | } | |
594 | ||
595 | /* Return true if register REGNO is a valid base register for mode MODE. | |
596 | STRICT_P is true if REG_OK_STRICT is in effect. */ | |
597 | ||
598 | int | |
599 | riscv_regno_mode_ok_for_base_p (int regno, | |
b8506a8a | 600 | machine_mode mode ATTRIBUTE_UNUSED, |
09cae750 PD |
601 | bool strict_p) |
602 | { | |
603 | if (!HARD_REGISTER_NUM_P (regno)) | |
604 | { | |
605 | if (!strict_p) | |
606 | return true; | |
607 | regno = reg_renumber[regno]; | |
608 | } | |
609 | ||
610 | /* These fake registers will be eliminated to either the stack or | |
611 | hard frame pointer, both of which are usually valid base registers. | |
612 | Reload deals with the cases where the eliminated form isn't valid. */ | |
613 | if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM) | |
614 | return true; | |
615 | ||
616 | return GP_REG_P (regno); | |
617 | } | |
618 | ||
619 | /* Return true if X is a valid base register for mode MODE. | |
620 | STRICT_P is true if REG_OK_STRICT is in effect. */ | |
621 | ||
622 | static bool | |
b8506a8a | 623 | riscv_valid_base_register_p (rtx x, machine_mode mode, bool strict_p) |
09cae750 PD |
624 | { |
625 | if (!strict_p && GET_CODE (x) == SUBREG) | |
626 | x = SUBREG_REG (x); | |
627 | ||
628 | return (REG_P (x) | |
629 | && riscv_regno_mode_ok_for_base_p (REGNO (x), mode, strict_p)); | |
630 | } | |
631 | ||
632 | /* Return true if, for every base register BASE_REG, (plus BASE_REG X) | |
633 | can address a value of mode MODE. */ | |
634 | ||
635 | static bool | |
b8506a8a | 636 | riscv_valid_offset_p (rtx x, machine_mode mode) |
09cae750 PD |
637 | { |
638 | /* Check that X is a signed 12-bit number. */ | |
639 | if (!const_arith_operand (x, Pmode)) | |
640 | return false; | |
641 | ||
642 | /* We may need to split multiword moves, so make sure that every word | |
643 | is accessible. */ | |
644 | if (GET_MODE_SIZE (mode) > UNITS_PER_WORD | |
645 | && !SMALL_OPERAND (INTVAL (x) + GET_MODE_SIZE (mode) - UNITS_PER_WORD)) | |
646 | return false; | |
647 | ||
648 | return true; | |
649 | } | |
650 | ||
651 | /* Should a symbol of type SYMBOL_TYPE should be split in two? */ | |
652 | ||
653 | bool | |
654 | riscv_split_symbol_type (enum riscv_symbol_type symbol_type) | |
655 | { | |
656 | if (symbol_type == SYMBOL_TLS_LE) | |
657 | return true; | |
658 | ||
659 | if (!TARGET_EXPLICIT_RELOCS) | |
660 | return false; | |
661 | ||
662 | return symbol_type == SYMBOL_ABSOLUTE || symbol_type == SYMBOL_PCREL; | |
663 | } | |
664 | ||
665 | /* Return true if a LO_SUM can address a value of mode MODE when the | |
666 | LO_SUM symbol has type SYM_TYPE. */ | |
667 | ||
668 | static bool | |
b8506a8a | 669 | riscv_valid_lo_sum_p (enum riscv_symbol_type sym_type, machine_mode mode) |
09cae750 PD |
670 | { |
671 | /* Check that symbols of type SYMBOL_TYPE can be used to access values | |
672 | of mode MODE. */ | |
673 | if (riscv_symbol_insns (sym_type) == 0) | |
674 | return false; | |
675 | ||
676 | /* Check that there is a known low-part relocation. */ | |
677 | if (!riscv_split_symbol_type (sym_type)) | |
678 | return false; | |
679 | ||
680 | /* We may need to split multiword moves, so make sure that each word | |
681 | can be accessed without inducing a carry. */ | |
682 | if (GET_MODE_SIZE (mode) > UNITS_PER_WORD | |
82285692 AW |
683 | && (!TARGET_STRICT_ALIGN |
684 | || GET_MODE_BITSIZE (mode) > GET_MODE_ALIGNMENT (mode))) | |
09cae750 PD |
685 | return false; |
686 | ||
687 | return true; | |
688 | } | |
689 | ||
690 | /* Return true if X is a valid address for machine mode MODE. If it is, | |
691 | fill in INFO appropriately. STRICT_P is true if REG_OK_STRICT is in | |
692 | effect. */ | |
693 | ||
694 | static bool | |
695 | riscv_classify_address (struct riscv_address_info *info, rtx x, | |
b8506a8a | 696 | machine_mode mode, bool strict_p) |
09cae750 PD |
697 | { |
698 | switch (GET_CODE (x)) | |
699 | { | |
700 | case REG: | |
701 | case SUBREG: | |
702 | info->type = ADDRESS_REG; | |
703 | info->reg = x; | |
704 | info->offset = const0_rtx; | |
705 | return riscv_valid_base_register_p (info->reg, mode, strict_p); | |
706 | ||
707 | case PLUS: | |
708 | info->type = ADDRESS_REG; | |
709 | info->reg = XEXP (x, 0); | |
710 | info->offset = XEXP (x, 1); | |
711 | return (riscv_valid_base_register_p (info->reg, mode, strict_p) | |
712 | && riscv_valid_offset_p (info->offset, mode)); | |
713 | ||
714 | case LO_SUM: | |
715 | info->type = ADDRESS_LO_SUM; | |
716 | info->reg = XEXP (x, 0); | |
717 | info->offset = XEXP (x, 1); | |
718 | /* We have to trust the creator of the LO_SUM to do something vaguely | |
719 | sane. Target-independent code that creates a LO_SUM should also | |
720 | create and verify the matching HIGH. Target-independent code that | |
721 | adds an offset to a LO_SUM must prove that the offset will not | |
722 | induce a carry. Failure to do either of these things would be | |
723 | a bug, and we are not required to check for it here. The RISC-V | |
724 | backend itself should only create LO_SUMs for valid symbolic | |
725 | constants, with the high part being either a HIGH or a copy | |
726 | of _gp. */ | |
727 | info->symbol_type | |
728 | = riscv_classify_symbolic_expression (info->offset); | |
729 | return (riscv_valid_base_register_p (info->reg, mode, strict_p) | |
730 | && riscv_valid_lo_sum_p (info->symbol_type, mode)); | |
731 | ||
732 | case CONST_INT: | |
733 | /* Small-integer addresses don't occur very often, but they | |
734 | are legitimate if x0 is a valid base register. */ | |
735 | info->type = ADDRESS_CONST_INT; | |
736 | return SMALL_OPERAND (INTVAL (x)); | |
737 | ||
738 | default: | |
739 | return false; | |
740 | } | |
741 | } | |
742 | ||
743 | /* Implement TARGET_LEGITIMATE_ADDRESS_P. */ | |
744 | ||
745 | static bool | |
b8506a8a | 746 | riscv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p) |
09cae750 PD |
747 | { |
748 | struct riscv_address_info addr; | |
749 | ||
750 | return riscv_classify_address (&addr, x, mode, strict_p); | |
751 | } | |
752 | ||
753 | /* Return the number of instructions needed to load or store a value | |
754 | of mode MODE at address X. Return 0 if X isn't valid for MODE. | |
755 | Assume that multiword moves may need to be split into word moves | |
756 | if MIGHT_SPLIT_P, otherwise assume that a single load or store is | |
757 | enough. */ | |
758 | ||
759 | int | |
b8506a8a | 760 | riscv_address_insns (rtx x, machine_mode mode, bool might_split_p) |
09cae750 PD |
761 | { |
762 | struct riscv_address_info addr; | |
763 | int n = 1; | |
764 | ||
765 | if (!riscv_classify_address (&addr, x, mode, false)) | |
766 | return 0; | |
767 | ||
768 | /* BLKmode is used for single unaligned loads and stores and should | |
769 | not count as a multiword mode. */ | |
770 | if (mode != BLKmode && might_split_p) | |
771 | n += (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; | |
772 | ||
773 | if (addr.type == ADDRESS_LO_SUM) | |
774 | n += riscv_symbol_insns (addr.symbol_type) - 1; | |
775 | ||
776 | return n; | |
777 | } | |
778 | ||
779 | /* Return the number of instructions needed to load constant X. | |
780 | Return 0 if X isn't a valid constant. */ | |
781 | ||
782 | int | |
783 | riscv_const_insns (rtx x) | |
784 | { | |
785 | enum riscv_symbol_type symbol_type; | |
786 | rtx offset; | |
787 | ||
788 | switch (GET_CODE (x)) | |
789 | { | |
790 | case HIGH: | |
791 | if (!riscv_symbolic_constant_p (XEXP (x, 0), &symbol_type) | |
792 | || !riscv_split_symbol_type (symbol_type)) | |
793 | return 0; | |
794 | ||
795 | /* This is simply an LUI. */ | |
796 | return 1; | |
797 | ||
798 | case CONST_INT: | |
799 | { | |
800 | int cost = riscv_integer_cost (INTVAL (x)); | |
801 | /* Force complicated constants to memory. */ | |
802 | return cost < 4 ? cost : 0; | |
803 | } | |
804 | ||
805 | case CONST_DOUBLE: | |
806 | case CONST_VECTOR: | |
807 | /* We can use x0 to load floating-point zero. */ | |
808 | return x == CONST0_RTX (GET_MODE (x)) ? 1 : 0; | |
809 | ||
810 | case CONST: | |
811 | /* See if we can refer to X directly. */ | |
812 | if (riscv_symbolic_constant_p (x, &symbol_type)) | |
813 | return riscv_symbol_insns (symbol_type); | |
814 | ||
815 | /* Otherwise try splitting the constant into a base and offset. */ | |
816 | split_const (x, &x, &offset); | |
817 | if (offset != 0) | |
818 | { | |
819 | int n = riscv_const_insns (x); | |
820 | if (n != 0) | |
821 | return n + riscv_integer_cost (INTVAL (offset)); | |
822 | } | |
823 | return 0; | |
824 | ||
825 | case SYMBOL_REF: | |
826 | case LABEL_REF: | |
827 | return riscv_symbol_insns (riscv_classify_symbol (x)); | |
828 | ||
829 | default: | |
830 | return 0; | |
831 | } | |
832 | } | |
833 | ||
834 | /* X is a doubleword constant that can be handled by splitting it into | |
835 | two words and loading each word separately. Return the number of | |
836 | instructions required to do this. */ | |
837 | ||
838 | int | |
839 | riscv_split_const_insns (rtx x) | |
840 | { | |
841 | unsigned int low, high; | |
842 | ||
843 | low = riscv_const_insns (riscv_subword (x, false)); | |
844 | high = riscv_const_insns (riscv_subword (x, true)); | |
845 | gcc_assert (low > 0 && high > 0); | |
846 | return low + high; | |
847 | } | |
848 | ||
849 | /* Return the number of instructions needed to implement INSN, | |
850 | given that it loads from or stores to MEM. */ | |
851 | ||
852 | int | |
853 | riscv_load_store_insns (rtx mem, rtx_insn *insn) | |
854 | { | |
b8506a8a | 855 | machine_mode mode; |
09cae750 PD |
856 | bool might_split_p; |
857 | rtx set; | |
858 | ||
859 | gcc_assert (MEM_P (mem)); | |
860 | mode = GET_MODE (mem); | |
861 | ||
862 | /* Try to prove that INSN does not need to be split. */ | |
863 | might_split_p = true; | |
864 | if (GET_MODE_BITSIZE (mode) <= 32) | |
865 | might_split_p = false; | |
866 | else if (GET_MODE_BITSIZE (mode) == 64) | |
867 | { | |
868 | set = single_set (insn); | |
869 | if (set && !riscv_split_64bit_move_p (SET_DEST (set), SET_SRC (set))) | |
870 | might_split_p = false; | |
871 | } | |
872 | ||
873 | return riscv_address_insns (XEXP (mem, 0), mode, might_split_p); | |
874 | } | |
875 | ||
876 | /* Emit a move from SRC to DEST. Assume that the move expanders can | |
877 | handle all moves if !can_create_pseudo_p (). The distinction is | |
878 | important because, unlike emit_move_insn, the move expanders know | |
879 | how to force Pmode objects into the constant pool even when the | |
880 | constant pool address is not itself legitimate. */ | |
881 | ||
882 | rtx | |
883 | riscv_emit_move (rtx dest, rtx src) | |
884 | { | |
885 | return (can_create_pseudo_p () | |
886 | ? emit_move_insn (dest, src) | |
887 | : emit_move_insn_1 (dest, src)); | |
888 | } | |
889 | ||
890 | /* Emit an instruction of the form (set TARGET SRC). */ | |
891 | ||
892 | static rtx | |
893 | riscv_emit_set (rtx target, rtx src) | |
894 | { | |
895 | emit_insn (gen_rtx_SET (target, src)); | |
896 | return target; | |
897 | } | |
898 | ||
899 | /* Emit an instruction of the form (set DEST (CODE X Y)). */ | |
900 | ||
901 | static rtx | |
902 | riscv_emit_binary (enum rtx_code code, rtx dest, rtx x, rtx y) | |
903 | { | |
904 | return riscv_emit_set (dest, gen_rtx_fmt_ee (code, GET_MODE (dest), x, y)); | |
905 | } | |
906 | ||
907 | /* Compute (CODE X Y) and store the result in a new register | |
908 | of mode MODE. Return that new register. */ | |
909 | ||
910 | static rtx | |
b8506a8a | 911 | riscv_force_binary (machine_mode mode, enum rtx_code code, rtx x, rtx y) |
09cae750 PD |
912 | { |
913 | return riscv_emit_binary (code, gen_reg_rtx (mode), x, y); | |
914 | } | |
915 | ||
916 | /* Copy VALUE to a register and return that register. If new pseudos | |
917 | are allowed, copy it into a new register, otherwise use DEST. */ | |
918 | ||
919 | static rtx | |
920 | riscv_force_temporary (rtx dest, rtx value) | |
921 | { | |
922 | if (can_create_pseudo_p ()) | |
923 | return force_reg (Pmode, value); | |
924 | else | |
925 | { | |
926 | riscv_emit_move (dest, value); | |
927 | return dest; | |
928 | } | |
929 | } | |
930 | ||
931 | /* Wrap symbol or label BASE in an UNSPEC address of type SYMBOL_TYPE, | |
932 | then add CONST_INT OFFSET to the result. */ | |
933 | ||
934 | static rtx | |
935 | riscv_unspec_address_offset (rtx base, rtx offset, | |
936 | enum riscv_symbol_type symbol_type) | |
937 | { | |
938 | base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), | |
939 | UNSPEC_ADDRESS_FIRST + symbol_type); | |
940 | if (offset != const0_rtx) | |
941 | base = gen_rtx_PLUS (Pmode, base, offset); | |
942 | return gen_rtx_CONST (Pmode, base); | |
943 | } | |
944 | ||
945 | /* Return an UNSPEC address with underlying address ADDRESS and symbol | |
946 | type SYMBOL_TYPE. */ | |
947 | ||
948 | rtx | |
949 | riscv_unspec_address (rtx address, enum riscv_symbol_type symbol_type) | |
950 | { | |
951 | rtx base, offset; | |
952 | ||
953 | split_const (address, &base, &offset); | |
954 | return riscv_unspec_address_offset (base, offset, symbol_type); | |
955 | } | |
956 | ||
957 | /* If OP is an UNSPEC address, return the address to which it refers, | |
958 | otherwise return OP itself. */ | |
959 | ||
960 | static rtx | |
961 | riscv_strip_unspec_address (rtx op) | |
962 | { | |
963 | rtx base, offset; | |
964 | ||
965 | split_const (op, &base, &offset); | |
966 | if (UNSPEC_ADDRESS_P (base)) | |
967 | op = plus_constant (Pmode, UNSPEC_ADDRESS (base), INTVAL (offset)); | |
968 | return op; | |
969 | } | |
970 | ||
971 | /* If riscv_unspec_address (ADDR, SYMBOL_TYPE) is a 32-bit value, add the | |
972 | high part to BASE and return the result. Just return BASE otherwise. | |
973 | TEMP is as for riscv_force_temporary. | |
974 | ||
975 | The returned expression can be used as the first operand to a LO_SUM. */ | |
976 | ||
977 | static rtx | |
978 | riscv_unspec_offset_high (rtx temp, rtx addr, enum riscv_symbol_type symbol_type) | |
979 | { | |
980 | addr = gen_rtx_HIGH (Pmode, riscv_unspec_address (addr, symbol_type)); | |
981 | return riscv_force_temporary (temp, addr); | |
982 | } | |
983 | ||
984 | /* Load an entry from the GOT for a TLS GD access. */ | |
985 | ||
986 | static rtx riscv_got_load_tls_gd (rtx dest, rtx sym) | |
987 | { | |
988 | if (Pmode == DImode) | |
989 | return gen_got_load_tls_gddi (dest, sym); | |
990 | else | |
991 | return gen_got_load_tls_gdsi (dest, sym); | |
992 | } | |
993 | ||
994 | /* Load an entry from the GOT for a TLS IE access. */ | |
995 | ||
996 | static rtx riscv_got_load_tls_ie (rtx dest, rtx sym) | |
997 | { | |
998 | if (Pmode == DImode) | |
999 | return gen_got_load_tls_iedi (dest, sym); | |
1000 | else | |
1001 | return gen_got_load_tls_iesi (dest, sym); | |
1002 | } | |
1003 | ||
1004 | /* Add in the thread pointer for a TLS LE access. */ | |
1005 | ||
1006 | static rtx riscv_tls_add_tp_le (rtx dest, rtx base, rtx sym) | |
1007 | { | |
1008 | rtx tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); | |
1009 | if (Pmode == DImode) | |
1010 | return gen_tls_add_tp_ledi (dest, base, tp, sym); | |
1011 | else | |
1012 | return gen_tls_add_tp_lesi (dest, base, tp, sym); | |
1013 | } | |
1014 | ||
1015 | /* If MODE is MAX_MACHINE_MODE, ADDR appears as a move operand, otherwise | |
1016 | it appears in a MEM of that mode. Return true if ADDR is a legitimate | |
1017 | constant in that context and can be split into high and low parts. | |
1018 | If so, and if LOW_OUT is nonnull, emit the high part and store the | |
1019 | low part in *LOW_OUT. Leave *LOW_OUT unchanged otherwise. | |
1020 | ||
1021 | TEMP is as for riscv_force_temporary and is used to load the high | |
1022 | part into a register. | |
1023 | ||
1024 | When MODE is MAX_MACHINE_MODE, the low part is guaranteed to be | |
1025 | a legitimize SET_SRC for an .md pattern, otherwise the low part | |
1026 | is guaranteed to be a legitimate address for mode MODE. */ | |
1027 | ||
1028 | bool | |
b8506a8a | 1029 | riscv_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out) |
09cae750 PD |
1030 | { |
1031 | enum riscv_symbol_type symbol_type; | |
1032 | ||
1033 | if ((GET_CODE (addr) == HIGH && mode == MAX_MACHINE_MODE) | |
1034 | || !riscv_symbolic_constant_p (addr, &symbol_type) | |
1035 | || riscv_symbol_insns (symbol_type) == 0 | |
1036 | || !riscv_split_symbol_type (symbol_type)) | |
1037 | return false; | |
1038 | ||
1039 | if (low_out) | |
1040 | switch (symbol_type) | |
1041 | { | |
1042 | case SYMBOL_ABSOLUTE: | |
1043 | { | |
1044 | rtx high = gen_rtx_HIGH (Pmode, copy_rtx (addr)); | |
1045 | high = riscv_force_temporary (temp, high); | |
1046 | *low_out = gen_rtx_LO_SUM (Pmode, high, addr); | |
1047 | } | |
1048 | break; | |
1049 | ||
1050 | case SYMBOL_PCREL: | |
1051 | { | |
1052 | static unsigned seqno; | |
1053 | char buf[32]; | |
1054 | rtx label; | |
1055 | ||
1056 | ssize_t bytes = snprintf (buf, sizeof (buf), ".LA%u", seqno); | |
1057 | gcc_assert ((size_t) bytes < sizeof (buf)); | |
1058 | ||
1059 | label = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)); | |
1060 | SYMBOL_REF_FLAGS (label) |= SYMBOL_FLAG_LOCAL; | |
1061 | ||
1062 | if (temp == NULL) | |
1063 | temp = gen_reg_rtx (Pmode); | |
1064 | ||
1065 | if (Pmode == DImode) | |
1066 | emit_insn (gen_auipcdi (temp, copy_rtx (addr), GEN_INT (seqno))); | |
1067 | else | |
1068 | emit_insn (gen_auipcsi (temp, copy_rtx (addr), GEN_INT (seqno))); | |
1069 | ||
1070 | *low_out = gen_rtx_LO_SUM (Pmode, temp, label); | |
1071 | ||
1072 | seqno++; | |
1073 | } | |
1074 | break; | |
1075 | ||
1076 | default: | |
1077 | gcc_unreachable (); | |
1078 | } | |
1079 | ||
1080 | return true; | |
1081 | } | |
1082 | ||
1083 | /* Return a legitimate address for REG + OFFSET. TEMP is as for | |
1084 | riscv_force_temporary; it is only needed when OFFSET is not a | |
1085 | SMALL_OPERAND. */ | |
1086 | ||
1087 | static rtx | |
1088 | riscv_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset) | |
1089 | { | |
1090 | if (!SMALL_OPERAND (offset)) | |
1091 | { | |
1092 | rtx high; | |
1093 | ||
1094 | /* Leave OFFSET as a 16-bit offset and put the excess in HIGH. | |
1095 | The addition inside the macro CONST_HIGH_PART may cause an | |
1096 | overflow, so we need to force a sign-extension check. */ | |
1097 | high = gen_int_mode (CONST_HIGH_PART (offset), Pmode); | |
1098 | offset = CONST_LOW_PART (offset); | |
1099 | high = riscv_force_temporary (temp, high); | |
1100 | reg = riscv_force_temporary (temp, gen_rtx_PLUS (Pmode, high, reg)); | |
1101 | } | |
1102 | return plus_constant (Pmode, reg, offset); | |
1103 | } | |
1104 | ||
1105 | /* The __tls_get_attr symbol. */ | |
1106 | static GTY(()) rtx riscv_tls_symbol; | |
1107 | ||
1108 | /* Return an instruction sequence that calls __tls_get_addr. SYM is | |
1109 | the TLS symbol we are referencing and TYPE is the symbol type to use | |
1110 | (either global dynamic or local dynamic). RESULT is an RTX for the | |
1111 | return value location. */ | |
1112 | ||
1113 | static rtx_insn * | |
1114 | riscv_call_tls_get_addr (rtx sym, rtx result) | |
1115 | { | |
1116 | rtx a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST), func; | |
1117 | rtx_insn *insn; | |
1118 | ||
1119 | if (!riscv_tls_symbol) | |
1120 | riscv_tls_symbol = init_one_libfunc ("__tls_get_addr"); | |
1121 | func = gen_rtx_MEM (FUNCTION_MODE, riscv_tls_symbol); | |
1122 | ||
1123 | start_sequence (); | |
1124 | ||
1125 | emit_insn (riscv_got_load_tls_gd (a0, sym)); | |
1126 | insn = emit_call_insn (gen_call_value (result, func, const0_rtx, NULL)); | |
1127 | RTL_CONST_CALL_P (insn) = 1; | |
1128 | use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0); | |
1129 | insn = get_insns (); | |
1130 | ||
1131 | end_sequence (); | |
1132 | ||
1133 | return insn; | |
1134 | } | |
1135 | ||
1136 | /* Generate the code to access LOC, a thread-local SYMBOL_REF, and return | |
1137 | its address. The return value will be both a valid address and a valid | |
1138 | SET_SRC (either a REG or a LO_SUM). */ | |
1139 | ||
1140 | static rtx | |
1141 | riscv_legitimize_tls_address (rtx loc) | |
1142 | { | |
1143 | rtx dest, tp, tmp; | |
1144 | enum tls_model model = SYMBOL_REF_TLS_MODEL (loc); | |
1145 | ||
1146 | /* Since we support TLS copy relocs, non-PIC TLS accesses may all use LE. */ | |
1147 | if (!flag_pic) | |
1148 | model = TLS_MODEL_LOCAL_EXEC; | |
1149 | ||
1150 | switch (model) | |
1151 | { | |
1152 | case TLS_MODEL_LOCAL_DYNAMIC: | |
1153 | /* Rely on section anchors for the optimization that LDM TLS | |
1154 | provides. The anchor's address is loaded with GD TLS. */ | |
1155 | case TLS_MODEL_GLOBAL_DYNAMIC: | |
1156 | tmp = gen_rtx_REG (Pmode, GP_RETURN); | |
1157 | dest = gen_reg_rtx (Pmode); | |
1158 | emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp, loc); | |
1159 | break; | |
1160 | ||
1161 | case TLS_MODEL_INITIAL_EXEC: | |
1162 | /* la.tls.ie; tp-relative add */ | |
1163 | tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); | |
1164 | tmp = gen_reg_rtx (Pmode); | |
1165 | emit_insn (riscv_got_load_tls_ie (tmp, loc)); | |
1166 | dest = gen_reg_rtx (Pmode); | |
1167 | emit_insn (gen_add3_insn (dest, tmp, tp)); | |
1168 | break; | |
1169 | ||
1170 | case TLS_MODEL_LOCAL_EXEC: | |
1171 | tmp = riscv_unspec_offset_high (NULL, loc, SYMBOL_TLS_LE); | |
1172 | dest = gen_reg_rtx (Pmode); | |
1173 | emit_insn (riscv_tls_add_tp_le (dest, tmp, loc)); | |
1174 | dest = gen_rtx_LO_SUM (Pmode, dest, | |
1175 | riscv_unspec_address (loc, SYMBOL_TLS_LE)); | |
1176 | break; | |
1177 | ||
1178 | default: | |
1179 | gcc_unreachable (); | |
1180 | } | |
1181 | return dest; | |
1182 | } | |
1183 | \f | |
1184 | /* If X is not a valid address for mode MODE, force it into a register. */ | |
1185 | ||
1186 | static rtx | |
b8506a8a | 1187 | riscv_force_address (rtx x, machine_mode mode) |
09cae750 PD |
1188 | { |
1189 | if (!riscv_legitimate_address_p (mode, x, false)) | |
1190 | x = force_reg (Pmode, x); | |
1191 | return x; | |
1192 | } | |
1193 | ||
1194 | /* This function is used to implement LEGITIMIZE_ADDRESS. If X can | |
1195 | be legitimized in a way that the generic machinery might not expect, | |
1196 | return a new address, otherwise return NULL. MODE is the mode of | |
1197 | the memory being accessed. */ | |
1198 | ||
1199 | static rtx | |
1200 | riscv_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, | |
b8506a8a | 1201 | machine_mode mode) |
09cae750 PD |
1202 | { |
1203 | rtx addr; | |
1204 | ||
1205 | if (riscv_tls_symbol_p (x)) | |
1206 | return riscv_legitimize_tls_address (x); | |
1207 | ||
1208 | /* See if the address can split into a high part and a LO_SUM. */ | |
1209 | if (riscv_split_symbol (NULL, x, mode, &addr)) | |
1210 | return riscv_force_address (addr, mode); | |
1211 | ||
1212 | /* Handle BASE + OFFSET using riscv_add_offset. */ | |
1213 | if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1)) | |
1214 | && INTVAL (XEXP (x, 1)) != 0) | |
1215 | { | |
1216 | rtx base = XEXP (x, 0); | |
1217 | HOST_WIDE_INT offset = INTVAL (XEXP (x, 1)); | |
1218 | ||
1219 | if (!riscv_valid_base_register_p (base, mode, false)) | |
1220 | base = copy_to_mode_reg (Pmode, base); | |
1221 | addr = riscv_add_offset (NULL, base, offset); | |
1222 | return riscv_force_address (addr, mode); | |
1223 | } | |
1224 | ||
1225 | return x; | |
1226 | } | |
1227 | ||
1228 | /* Load VALUE into DEST. TEMP is as for riscv_force_temporary. */ | |
1229 | ||
1230 | void | |
1231 | riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value) | |
1232 | { | |
1233 | struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS]; | |
b8506a8a | 1234 | machine_mode mode; |
09cae750 PD |
1235 | int i, num_ops; |
1236 | rtx x; | |
1237 | ||
1238 | mode = GET_MODE (dest); | |
1239 | num_ops = riscv_build_integer (codes, value, mode); | |
1240 | ||
1241 | if (can_create_pseudo_p () && num_ops > 2 /* not a simple constant */ | |
1242 | && num_ops >= riscv_split_integer_cost (value)) | |
1243 | x = riscv_split_integer (value, mode); | |
1244 | else | |
1245 | { | |
1246 | /* Apply each binary operation to X. */ | |
1247 | x = GEN_INT (codes[0].value); | |
1248 | ||
1249 | for (i = 1; i < num_ops; i++) | |
1250 | { | |
1251 | if (!can_create_pseudo_p ()) | |
1252 | x = riscv_emit_set (temp, x); | |
1253 | else | |
1254 | x = force_reg (mode, x); | |
1255 | ||
1256 | x = gen_rtx_fmt_ee (codes[i].code, mode, x, GEN_INT (codes[i].value)); | |
1257 | } | |
1258 | } | |
1259 | ||
1260 | riscv_emit_set (dest, x); | |
1261 | } | |
1262 | ||
1263 | /* Subroutine of riscv_legitimize_move. Move constant SRC into register | |
1264 | DEST given that SRC satisfies immediate_operand but doesn't satisfy | |
1265 | move_operand. */ | |
1266 | ||
1267 | static void | |
b8506a8a | 1268 | riscv_legitimize_const_move (machine_mode mode, rtx dest, rtx src) |
09cae750 PD |
1269 | { |
1270 | rtx base, offset; | |
1271 | ||
1272 | /* Split moves of big integers into smaller pieces. */ | |
1273 | if (splittable_const_int_operand (src, mode)) | |
1274 | { | |
1275 | riscv_move_integer (dest, dest, INTVAL (src)); | |
1276 | return; | |
1277 | } | |
1278 | ||
1279 | /* Split moves of symbolic constants into high/low pairs. */ | |
1280 | if (riscv_split_symbol (dest, src, MAX_MACHINE_MODE, &src)) | |
1281 | { | |
1282 | riscv_emit_set (dest, src); | |
1283 | return; | |
1284 | } | |
1285 | ||
1286 | /* Generate the appropriate access sequences for TLS symbols. */ | |
1287 | if (riscv_tls_symbol_p (src)) | |
1288 | { | |
1289 | riscv_emit_move (dest, riscv_legitimize_tls_address (src)); | |
1290 | return; | |
1291 | } | |
1292 | ||
1293 | /* If we have (const (plus symbol offset)), and that expression cannot | |
1294 | be forced into memory, load the symbol first and add in the offset. Also | |
1295 | prefer to do this even if the constant _can_ be forced into memory, as it | |
1296 | usually produces better code. */ | |
1297 | split_const (src, &base, &offset); | |
1298 | if (offset != const0_rtx | |
1299 | && (targetm.cannot_force_const_mem (mode, src) || can_create_pseudo_p ())) | |
1300 | { | |
1301 | base = riscv_force_temporary (dest, base); | |
1302 | riscv_emit_move (dest, riscv_add_offset (NULL, base, INTVAL (offset))); | |
1303 | return; | |
1304 | } | |
1305 | ||
1306 | src = force_const_mem (mode, src); | |
1307 | ||
1308 | /* When using explicit relocs, constant pool references are sometimes | |
1309 | not legitimate addresses. */ | |
1310 | riscv_split_symbol (dest, XEXP (src, 0), mode, &XEXP (src, 0)); | |
1311 | riscv_emit_move (dest, src); | |
1312 | } | |
1313 | ||
1314 | /* If (set DEST SRC) is not a valid move instruction, emit an equivalent | |
1315 | sequence that is valid. */ | |
1316 | ||
1317 | bool | |
b8506a8a | 1318 | riscv_legitimize_move (machine_mode mode, rtx dest, rtx src) |
09cae750 PD |
1319 | { |
1320 | if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode)) | |
1321 | { | |
1322 | riscv_emit_move (dest, force_reg (mode, src)); | |
1323 | return true; | |
1324 | } | |
1325 | ||
1326 | /* We need to deal with constants that would be legitimate | |
1327 | immediate_operands but aren't legitimate move_operands. */ | |
1328 | if (CONSTANT_P (src) && !move_operand (src, mode)) | |
1329 | { | |
1330 | riscv_legitimize_const_move (mode, dest, src); | |
1331 | set_unique_reg_note (get_last_insn (), REG_EQUAL, copy_rtx (src)); | |
1332 | return true; | |
1333 | } | |
1334 | ||
13e4f305 KC |
1335 | /* RISC-V GCC may generate non-legitimate address due to we provide some |
1336 | pattern for optimize access PIC local symbol and it's make GCC generate | |
1337 | unrecognizable instruction during optmizing. */ | |
1338 | ||
1339 | if (MEM_P (dest) && !riscv_legitimate_address_p (mode, XEXP (dest, 0), | |
1340 | reload_completed)) | |
1341 | { | |
1342 | XEXP (dest, 0) = riscv_force_address (XEXP (dest, 0), mode); | |
1343 | } | |
1344 | ||
1345 | if (MEM_P (src) && !riscv_legitimate_address_p (mode, XEXP (src, 0), | |
1346 | reload_completed)) | |
1347 | { | |
1348 | XEXP (src, 0) = riscv_force_address (XEXP (src, 0), mode); | |
1349 | } | |
1350 | ||
09cae750 PD |
1351 | return false; |
1352 | } | |
1353 | ||
1354 | /* Return true if there is an instruction that implements CODE and accepts | |
1355 | X as an immediate operand. */ | |
1356 | ||
1357 | static int | |
1358 | riscv_immediate_operand_p (int code, HOST_WIDE_INT x) | |
1359 | { | |
1360 | switch (code) | |
1361 | { | |
1362 | case ASHIFT: | |
1363 | case ASHIFTRT: | |
1364 | case LSHIFTRT: | |
1365 | /* All shift counts are truncated to a valid constant. */ | |
1366 | return true; | |
1367 | ||
1368 | case AND: | |
1369 | case IOR: | |
1370 | case XOR: | |
1371 | case PLUS: | |
1372 | case LT: | |
1373 | case LTU: | |
1374 | /* These instructions take 12-bit signed immediates. */ | |
1375 | return SMALL_OPERAND (x); | |
1376 | ||
1377 | case LE: | |
1378 | /* We add 1 to the immediate and use SLT. */ | |
1379 | return SMALL_OPERAND (x + 1); | |
1380 | ||
1381 | case LEU: | |
1382 | /* Likewise SLTU, but reject the always-true case. */ | |
1383 | return SMALL_OPERAND (x + 1) && x + 1 != 0; | |
1384 | ||
1385 | case GE: | |
1386 | case GEU: | |
1387 | /* We can emulate an immediate of 1 by using GT/GTU against x0. */ | |
1388 | return x == 1; | |
1389 | ||
1390 | default: | |
1391 | /* By default assume that x0 can be used for 0. */ | |
1392 | return x == 0; | |
1393 | } | |
1394 | } | |
1395 | ||
1396 | /* Return the cost of binary operation X, given that the instruction | |
1397 | sequence for a word-sized or smaller operation takes SIGNLE_INSNS | |
1398 | instructions and that the sequence of a double-word operation takes | |
1399 | DOUBLE_INSNS instructions. */ | |
1400 | ||
1401 | static int | |
1402 | riscv_binary_cost (rtx x, int single_insns, int double_insns) | |
1403 | { | |
1404 | if (GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD * 2) | |
1405 | return COSTS_N_INSNS (double_insns); | |
1406 | return COSTS_N_INSNS (single_insns); | |
1407 | } | |
1408 | ||
1409 | /* Return the cost of sign- or zero-extending OP. */ | |
1410 | ||
1411 | static int | |
1412 | riscv_extend_cost (rtx op, bool unsigned_p) | |
1413 | { | |
1414 | if (MEM_P (op)) | |
1415 | return 0; | |
1416 | ||
1417 | if (unsigned_p && GET_MODE (op) == QImode) | |
1418 | /* We can use ANDI. */ | |
1419 | return COSTS_N_INSNS (1); | |
1420 | ||
1421 | if (!unsigned_p && GET_MODE (op) == SImode) | |
1422 | /* We can use SEXT.W. */ | |
1423 | return COSTS_N_INSNS (1); | |
1424 | ||
1425 | /* We need to use a shift left and a shift right. */ | |
1426 | return COSTS_N_INSNS (2); | |
1427 | } | |
1428 | ||
1429 | /* Implement TARGET_RTX_COSTS. */ | |
1430 | ||
1431 | static bool | |
1432 | riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UNUSED, | |
1433 | int *total, bool speed) | |
1434 | { | |
1435 | bool float_mode_p = FLOAT_MODE_P (mode); | |
1436 | int cost; | |
1437 | ||
1438 | switch (GET_CODE (x)) | |
1439 | { | |
1440 | case CONST_INT: | |
1441 | if (riscv_immediate_operand_p (outer_code, INTVAL (x))) | |
1442 | { | |
1443 | *total = 0; | |
1444 | return true; | |
1445 | } | |
1446 | /* Fall through. */ | |
1447 | ||
1448 | case SYMBOL_REF: | |
1449 | case LABEL_REF: | |
1450 | case CONST_DOUBLE: | |
1451 | case CONST: | |
1452 | if ((cost = riscv_const_insns (x)) > 0) | |
1453 | { | |
1454 | /* If the constant is likely to be stored in a GPR, SETs of | |
1455 | single-insn constants are as cheap as register sets; we | |
1456 | never want to CSE them. */ | |
1457 | if (cost == 1 && outer_code == SET) | |
1458 | *total = 0; | |
1459 | /* When we load a constant more than once, it usually is better | |
1460 | to duplicate the last operation in the sequence than to CSE | |
1461 | the constant itself. */ | |
1462 | else if (outer_code == SET || GET_MODE (x) == VOIDmode) | |
1463 | *total = COSTS_N_INSNS (1); | |
1464 | } | |
1465 | else /* The instruction will be fetched from the constant pool. */ | |
1466 | *total = COSTS_N_INSNS (riscv_symbol_insns (SYMBOL_ABSOLUTE)); | |
1467 | return true; | |
1468 | ||
1469 | case MEM: | |
1470 | /* If the address is legitimate, return the number of | |
1471 | instructions it needs. */ | |
1472 | if ((cost = riscv_address_insns (XEXP (x, 0), mode, true)) > 0) | |
1473 | { | |
1474 | *total = COSTS_N_INSNS (cost + tune_info->memory_cost); | |
1475 | return true; | |
1476 | } | |
1477 | /* Otherwise use the default handling. */ | |
1478 | return false; | |
1479 | ||
1480 | case NOT: | |
1481 | *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1); | |
1482 | return false; | |
1483 | ||
1484 | case AND: | |
1485 | case IOR: | |
1486 | case XOR: | |
1487 | /* Double-word operations use two single-word operations. */ | |
1488 | *total = riscv_binary_cost (x, 1, 2); | |
1489 | return false; | |
1490 | ||
1491 | case ASHIFT: | |
1492 | case ASHIFTRT: | |
1493 | case LSHIFTRT: | |
1494 | *total = riscv_binary_cost (x, 1, CONSTANT_P (XEXP (x, 1)) ? 4 : 9); | |
1495 | return false; | |
1496 | ||
1497 | case ABS: | |
1498 | *total = COSTS_N_INSNS (float_mode_p ? 1 : 3); | |
1499 | return false; | |
1500 | ||
1501 | case LO_SUM: | |
1502 | *total = set_src_cost (XEXP (x, 0), mode, speed); | |
1503 | return true; | |
1504 | ||
1505 | case LT: | |
1506 | case LTU: | |
1507 | case LE: | |
1508 | case LEU: | |
1509 | case GT: | |
1510 | case GTU: | |
1511 | case GE: | |
1512 | case GEU: | |
1513 | case EQ: | |
1514 | case NE: | |
1515 | /* Branch comparisons have VOIDmode, so use the first operand's | |
1516 | mode instead. */ | |
1517 | mode = GET_MODE (XEXP (x, 0)); | |
1518 | if (float_mode_p) | |
1519 | *total = tune_info->fp_add[mode == DFmode]; | |
1520 | else | |
1521 | *total = riscv_binary_cost (x, 1, 3); | |
1522 | return false; | |
1523 | ||
1524 | case UNORDERED: | |
1525 | case ORDERED: | |
1526 | /* (FEQ(A, A) & FEQ(B, B)) compared against 0. */ | |
1527 | mode = GET_MODE (XEXP (x, 0)); | |
1528 | *total = tune_info->fp_add[mode == DFmode] + COSTS_N_INSNS (2); | |
1529 | return false; | |
1530 | ||
1531 | case UNEQ: | |
1532 | case LTGT: | |
1533 | /* (FEQ(A, A) & FEQ(B, B)) compared against FEQ(A, B). */ | |
1534 | mode = GET_MODE (XEXP (x, 0)); | |
1535 | *total = tune_info->fp_add[mode == DFmode] + COSTS_N_INSNS (3); | |
1536 | return false; | |
1537 | ||
1538 | case UNGE: | |
1539 | case UNGT: | |
1540 | case UNLE: | |
1541 | case UNLT: | |
1542 | /* FLT or FLE, but guarded by an FFLAGS read and write. */ | |
1543 | mode = GET_MODE (XEXP (x, 0)); | |
1544 | *total = tune_info->fp_add[mode == DFmode] + COSTS_N_INSNS (4); | |
1545 | return false; | |
1546 | ||
1547 | case MINUS: | |
1548 | case PLUS: | |
1549 | if (float_mode_p) | |
1550 | *total = tune_info->fp_add[mode == DFmode]; | |
1551 | else | |
1552 | *total = riscv_binary_cost (x, 1, 4); | |
1553 | return false; | |
1554 | ||
1555 | case NEG: | |
1556 | { | |
1557 | rtx op = XEXP (x, 0); | |
1558 | if (GET_CODE (op) == FMA && !HONOR_SIGNED_ZEROS (mode)) | |
1559 | { | |
1560 | *total = (tune_info->fp_mul[mode == DFmode] | |
1561 | + set_src_cost (XEXP (op, 0), mode, speed) | |
1562 | + set_src_cost (XEXP (op, 1), mode, speed) | |
1563 | + set_src_cost (XEXP (op, 2), mode, speed)); | |
1564 | return true; | |
1565 | } | |
1566 | } | |
1567 | ||
1568 | if (float_mode_p) | |
1569 | *total = tune_info->fp_add[mode == DFmode]; | |
1570 | else | |
1571 | *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 4 : 1); | |
1572 | return false; | |
1573 | ||
1574 | case MULT: | |
1575 | if (float_mode_p) | |
1576 | *total = tune_info->fp_mul[mode == DFmode]; | |
1577 | else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) | |
1578 | *total = 3 * tune_info->int_mul[0] + COSTS_N_INSNS (2); | |
1579 | else if (!speed) | |
1580 | *total = COSTS_N_INSNS (1); | |
1581 | else | |
1582 | *total = tune_info->int_mul[mode == DImode]; | |
1583 | return false; | |
1584 | ||
1585 | case DIV: | |
1586 | case SQRT: | |
1587 | case MOD: | |
1588 | if (float_mode_p) | |
1589 | { | |
1590 | *total = tune_info->fp_div[mode == DFmode]; | |
1591 | return false; | |
1592 | } | |
1593 | /* Fall through. */ | |
1594 | ||
1595 | case UDIV: | |
1596 | case UMOD: | |
1597 | if (speed) | |
1598 | *total = tune_info->int_div[mode == DImode]; | |
1599 | else | |
1600 | *total = COSTS_N_INSNS (1); | |
1601 | return false; | |
1602 | ||
1603 | case SIGN_EXTEND: | |
1604 | case ZERO_EXTEND: | |
1605 | *total = riscv_extend_cost (XEXP (x, 0), GET_CODE (x) == ZERO_EXTEND); | |
1606 | return false; | |
1607 | ||
1608 | case FLOAT: | |
1609 | case UNSIGNED_FLOAT: | |
1610 | case FIX: | |
1611 | case FLOAT_EXTEND: | |
1612 | case FLOAT_TRUNCATE: | |
1613 | *total = tune_info->fp_add[mode == DFmode]; | |
1614 | return false; | |
1615 | ||
1616 | case FMA: | |
1617 | *total = (tune_info->fp_mul[mode == DFmode] | |
1618 | + set_src_cost (XEXP (x, 0), mode, speed) | |
1619 | + set_src_cost (XEXP (x, 1), mode, speed) | |
1620 | + set_src_cost (XEXP (x, 2), mode, speed)); | |
1621 | return true; | |
1622 | ||
1623 | case UNSPEC: | |
1624 | if (XINT (x, 1) == UNSPEC_AUIPC) | |
1625 | { | |
1626 | /* Make AUIPC cheap to avoid spilling its result to the stack. */ | |
1627 | *total = 1; | |
1628 | return true; | |
1629 | } | |
1630 | return false; | |
1631 | ||
1632 | default: | |
1633 | return false; | |
1634 | } | |
1635 | } | |
1636 | ||
1637 | /* Implement TARGET_ADDRESS_COST. */ | |
1638 | ||
1639 | static int | |
b8506a8a | 1640 | riscv_address_cost (rtx addr, machine_mode mode, |
09cae750 PD |
1641 | addr_space_t as ATTRIBUTE_UNUSED, |
1642 | bool speed ATTRIBUTE_UNUSED) | |
1643 | { | |
1644 | return riscv_address_insns (addr, mode, false); | |
1645 | } | |
1646 | ||
1647 | /* Return one word of double-word value OP. HIGH_P is true to select the | |
1648 | high part or false to select the low part. */ | |
1649 | ||
1650 | rtx | |
1651 | riscv_subword (rtx op, bool high_p) | |
1652 | { | |
1653 | unsigned int byte = high_p ? UNITS_PER_WORD : 0; | |
b8506a8a | 1654 | machine_mode mode = GET_MODE (op); |
09cae750 PD |
1655 | |
1656 | if (mode == VOIDmode) | |
1657 | mode = TARGET_64BIT ? TImode : DImode; | |
1658 | ||
1659 | if (MEM_P (op)) | |
1660 | return adjust_address (op, word_mode, byte); | |
1661 | ||
1662 | if (REG_P (op)) | |
1663 | gcc_assert (!FP_REG_RTX_P (op)); | |
1664 | ||
1665 | return simplify_gen_subreg (word_mode, op, mode, byte); | |
1666 | } | |
1667 | ||
1668 | /* Return true if a 64-bit move from SRC to DEST should be split into two. */ | |
1669 | ||
1670 | bool | |
1671 | riscv_split_64bit_move_p (rtx dest, rtx src) | |
1672 | { | |
1673 | if (TARGET_64BIT) | |
1674 | return false; | |
1675 | ||
1676 | /* Allow FPR <-> FPR and FPR <-> MEM moves, and permit the special case | |
1677 | of zeroing an FPR with FCVT.D.W. */ | |
1678 | if (TARGET_DOUBLE_FLOAT | |
1679 | && ((FP_REG_RTX_P (src) && FP_REG_RTX_P (dest)) | |
1680 | || (FP_REG_RTX_P (dest) && MEM_P (src)) | |
1681 | || (FP_REG_RTX_P (src) && MEM_P (dest)) | |
1682 | || (FP_REG_RTX_P (dest) && src == CONST0_RTX (GET_MODE (src))))) | |
1683 | return false; | |
1684 | ||
1685 | return true; | |
1686 | } | |
1687 | ||
1688 | /* Split a doubleword move from SRC to DEST. On 32-bit targets, | |
1689 | this function handles 64-bit moves for which riscv_split_64bit_move_p | |
1690 | holds. For 64-bit targets, this function handles 128-bit moves. */ | |
1691 | ||
1692 | void | |
1693 | riscv_split_doubleword_move (rtx dest, rtx src) | |
1694 | { | |
1695 | rtx low_dest; | |
1696 | ||
1697 | /* The operation can be split into two normal moves. Decide in | |
1698 | which order to do them. */ | |
1699 | low_dest = riscv_subword (dest, false); | |
1700 | if (REG_P (low_dest) && reg_overlap_mentioned_p (low_dest, src)) | |
1701 | { | |
1702 | riscv_emit_move (riscv_subword (dest, true), riscv_subword (src, true)); | |
1703 | riscv_emit_move (low_dest, riscv_subword (src, false)); | |
1704 | } | |
1705 | else | |
1706 | { | |
1707 | riscv_emit_move (low_dest, riscv_subword (src, false)); | |
1708 | riscv_emit_move (riscv_subword (dest, true), riscv_subword (src, true)); | |
1709 | } | |
1710 | } | |
1711 | \f | |
1712 | /* Return the appropriate instructions to move SRC into DEST. Assume | |
1713 | that SRC is operand 1 and DEST is operand 0. */ | |
1714 | ||
1715 | const char * | |
1716 | riscv_output_move (rtx dest, rtx src) | |
1717 | { | |
1718 | enum rtx_code dest_code, src_code; | |
b8506a8a | 1719 | machine_mode mode; |
09cae750 PD |
1720 | bool dbl_p; |
1721 | ||
1722 | dest_code = GET_CODE (dest); | |
1723 | src_code = GET_CODE (src); | |
1724 | mode = GET_MODE (dest); | |
1725 | dbl_p = (GET_MODE_SIZE (mode) == 8); | |
1726 | ||
1727 | if (dbl_p && riscv_split_64bit_move_p (dest, src)) | |
1728 | return "#"; | |
1729 | ||
1730 | if (dest_code == REG && GP_REG_P (REGNO (dest))) | |
1731 | { | |
1732 | if (src_code == REG && FP_REG_P (REGNO (src))) | |
1733 | return dbl_p ? "fmv.x.d\t%0,%1" : "fmv.x.s\t%0,%1"; | |
1734 | ||
1735 | if (src_code == MEM) | |
1736 | switch (GET_MODE_SIZE (mode)) | |
1737 | { | |
1738 | case 1: return "lbu\t%0,%1"; | |
1739 | case 2: return "lhu\t%0,%1"; | |
1740 | case 4: return "lw\t%0,%1"; | |
1741 | case 8: return "ld\t%0,%1"; | |
1742 | } | |
1743 | ||
1744 | if (src_code == CONST_INT) | |
1745 | return "li\t%0,%1"; | |
1746 | ||
1747 | if (src_code == HIGH) | |
1748 | return "lui\t%0,%h1"; | |
1749 | ||
1750 | if (symbolic_operand (src, VOIDmode)) | |
1751 | switch (riscv_classify_symbolic_expression (src)) | |
1752 | { | |
1753 | case SYMBOL_GOT_DISP: return "la\t%0,%1"; | |
1754 | case SYMBOL_ABSOLUTE: return "lla\t%0,%1"; | |
1755 | case SYMBOL_PCREL: return "lla\t%0,%1"; | |
1756 | default: gcc_unreachable (); | |
1757 | } | |
1758 | } | |
1759 | if ((src_code == REG && GP_REG_P (REGNO (src))) | |
1760 | || (src == CONST0_RTX (mode))) | |
1761 | { | |
1762 | if (dest_code == REG) | |
1763 | { | |
1764 | if (GP_REG_P (REGNO (dest))) | |
1765 | return "mv\t%0,%z1"; | |
1766 | ||
1767 | if (FP_REG_P (REGNO (dest))) | |
1768 | { | |
1769 | if (!dbl_p) | |
1770 | return "fmv.s.x\t%0,%z1"; | |
1771 | if (TARGET_64BIT) | |
1772 | return "fmv.d.x\t%0,%z1"; | |
1773 | /* in RV32, we can emulate fmv.d.x %0, x0 using fcvt.d.w */ | |
1774 | gcc_assert (src == CONST0_RTX (mode)); | |
1775 | return "fcvt.d.w\t%0,x0"; | |
1776 | } | |
1777 | } | |
1778 | if (dest_code == MEM) | |
1779 | switch (GET_MODE_SIZE (mode)) | |
1780 | { | |
1781 | case 1: return "sb\t%z1,%0"; | |
1782 | case 2: return "sh\t%z1,%0"; | |
1783 | case 4: return "sw\t%z1,%0"; | |
1784 | case 8: return "sd\t%z1,%0"; | |
1785 | } | |
1786 | } | |
1787 | if (src_code == REG && FP_REG_P (REGNO (src))) | |
1788 | { | |
1789 | if (dest_code == REG && FP_REG_P (REGNO (dest))) | |
1790 | return dbl_p ? "fmv.d\t%0,%1" : "fmv.s\t%0,%1"; | |
1791 | ||
1792 | if (dest_code == MEM) | |
1793 | return dbl_p ? "fsd\t%1,%0" : "fsw\t%1,%0"; | |
1794 | } | |
1795 | if (dest_code == REG && FP_REG_P (REGNO (dest))) | |
1796 | { | |
1797 | if (src_code == MEM) | |
1798 | return dbl_p ? "fld\t%0,%1" : "flw\t%0,%1"; | |
1799 | } | |
1800 | gcc_unreachable (); | |
1801 | } | |
1802 | \f | |
1803 | /* Return true if CMP1 is a suitable second operand for integer ordering | |
1804 | test CODE. See also the *sCC patterns in riscv.md. */ | |
1805 | ||
1806 | static bool | |
1807 | riscv_int_order_operand_ok_p (enum rtx_code code, rtx cmp1) | |
1808 | { | |
1809 | switch (code) | |
1810 | { | |
1811 | case GT: | |
1812 | case GTU: | |
1813 | return reg_or_0_operand (cmp1, VOIDmode); | |
1814 | ||
1815 | case GE: | |
1816 | case GEU: | |
1817 | return cmp1 == const1_rtx; | |
1818 | ||
1819 | case LT: | |
1820 | case LTU: | |
1821 | return arith_operand (cmp1, VOIDmode); | |
1822 | ||
1823 | case LE: | |
1824 | return sle_operand (cmp1, VOIDmode); | |
1825 | ||
1826 | case LEU: | |
1827 | return sleu_operand (cmp1, VOIDmode); | |
1828 | ||
1829 | default: | |
1830 | gcc_unreachable (); | |
1831 | } | |
1832 | } | |
1833 | ||
1834 | /* Return true if *CMP1 (of mode MODE) is a valid second operand for | |
1835 | integer ordering test *CODE, or if an equivalent combination can | |
1836 | be formed by adjusting *CODE and *CMP1. When returning true, update | |
1837 | *CODE and *CMP1 with the chosen code and operand, otherwise leave | |
1838 | them alone. */ | |
1839 | ||
1840 | static bool | |
1841 | riscv_canonicalize_int_order_test (enum rtx_code *code, rtx *cmp1, | |
b8506a8a | 1842 | machine_mode mode) |
09cae750 PD |
1843 | { |
1844 | HOST_WIDE_INT plus_one; | |
1845 | ||
1846 | if (riscv_int_order_operand_ok_p (*code, *cmp1)) | |
1847 | return true; | |
1848 | ||
1849 | if (CONST_INT_P (*cmp1)) | |
1850 | switch (*code) | |
1851 | { | |
1852 | case LE: | |
1853 | plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode); | |
1854 | if (INTVAL (*cmp1) < plus_one) | |
1855 | { | |
1856 | *code = LT; | |
1857 | *cmp1 = force_reg (mode, GEN_INT (plus_one)); | |
1858 | return true; | |
1859 | } | |
1860 | break; | |
1861 | ||
1862 | case LEU: | |
1863 | plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode); | |
1864 | if (plus_one != 0) | |
1865 | { | |
1866 | *code = LTU; | |
1867 | *cmp1 = force_reg (mode, GEN_INT (plus_one)); | |
1868 | return true; | |
1869 | } | |
1870 | break; | |
1871 | ||
1872 | default: | |
1873 | break; | |
1874 | } | |
1875 | return false; | |
1876 | } | |
1877 | ||
1878 | /* Compare CMP0 and CMP1 using ordering test CODE and store the result | |
1879 | in TARGET. CMP0 and TARGET are register_operands. If INVERT_PTR | |
1880 | is nonnull, it's OK to set TARGET to the inverse of the result and | |
1881 | flip *INVERT_PTR instead. */ | |
1882 | ||
1883 | static void | |
1884 | riscv_emit_int_order_test (enum rtx_code code, bool *invert_ptr, | |
1885 | rtx target, rtx cmp0, rtx cmp1) | |
1886 | { | |
b8506a8a | 1887 | machine_mode mode; |
09cae750 PD |
1888 | |
1889 | /* First see if there is a RISCV instruction that can do this operation. | |
1890 | If not, try doing the same for the inverse operation. If that also | |
1891 | fails, force CMP1 into a register and try again. */ | |
1892 | mode = GET_MODE (cmp0); | |
1893 | if (riscv_canonicalize_int_order_test (&code, &cmp1, mode)) | |
1894 | riscv_emit_binary (code, target, cmp0, cmp1); | |
1895 | else | |
1896 | { | |
1897 | enum rtx_code inv_code = reverse_condition (code); | |
1898 | if (!riscv_canonicalize_int_order_test (&inv_code, &cmp1, mode)) | |
1899 | { | |
1900 | cmp1 = force_reg (mode, cmp1); | |
1901 | riscv_emit_int_order_test (code, invert_ptr, target, cmp0, cmp1); | |
1902 | } | |
1903 | else if (invert_ptr == 0) | |
1904 | { | |
1905 | rtx inv_target = riscv_force_binary (GET_MODE (target), | |
1906 | inv_code, cmp0, cmp1); | |
1907 | riscv_emit_binary (XOR, target, inv_target, const1_rtx); | |
1908 | } | |
1909 | else | |
1910 | { | |
1911 | *invert_ptr = !*invert_ptr; | |
1912 | riscv_emit_binary (inv_code, target, cmp0, cmp1); | |
1913 | } | |
1914 | } | |
1915 | } | |
1916 | ||
1917 | /* Return a register that is zero iff CMP0 and CMP1 are equal. | |
1918 | The register will have the same mode as CMP0. */ | |
1919 | ||
1920 | static rtx | |
1921 | riscv_zero_if_equal (rtx cmp0, rtx cmp1) | |
1922 | { | |
1923 | if (cmp1 == const0_rtx) | |
1924 | return cmp0; | |
1925 | ||
1926 | return expand_binop (GET_MODE (cmp0), sub_optab, | |
1927 | cmp0, cmp1, 0, 0, OPTAB_DIRECT); | |
1928 | } | |
1929 | ||
1930 | /* Sign- or zero-extend OP0 and OP1 for integer comparisons. */ | |
1931 | ||
1932 | static void | |
1933 | riscv_extend_comparands (rtx_code code, rtx *op0, rtx *op1) | |
1934 | { | |
1935 | /* Comparisons consider all XLEN bits, so extend sub-XLEN values. */ | |
1936 | if (GET_MODE_SIZE (word_mode) > GET_MODE_SIZE (GET_MODE (*op0))) | |
1937 | { | |
1938 | /* It is more profitable to zero-extend QImode values. */ | |
1939 | if (unsigned_condition (code) == code && GET_MODE (*op0) == QImode) | |
1940 | { | |
1941 | *op0 = gen_rtx_ZERO_EXTEND (word_mode, *op0); | |
1942 | if (CONST_INT_P (*op1)) | |
1943 | *op1 = GEN_INT ((uint8_t) INTVAL (*op1)); | |
1944 | else | |
1945 | *op1 = gen_rtx_ZERO_EXTEND (word_mode, *op1); | |
1946 | } | |
1947 | else | |
1948 | { | |
1949 | *op0 = gen_rtx_SIGN_EXTEND (word_mode, *op0); | |
1950 | if (*op1 != const0_rtx) | |
1951 | *op1 = gen_rtx_SIGN_EXTEND (word_mode, *op1); | |
1952 | } | |
1953 | } | |
1954 | } | |
1955 | ||
1956 | /* Convert a comparison into something that can be used in a branch. On | |
1957 | entry, *OP0 and *OP1 are the values being compared and *CODE is the code | |
1958 | used to compare them. Update them to describe the final comparison. */ | |
1959 | ||
1960 | static void | |
1961 | riscv_emit_int_compare (enum rtx_code *code, rtx *op0, rtx *op1) | |
1962 | { | |
1963 | if (splittable_const_int_operand (*op1, VOIDmode)) | |
1964 | { | |
1965 | HOST_WIDE_INT rhs = INTVAL (*op1); | |
1966 | ||
1967 | if (*code == EQ || *code == NE) | |
1968 | { | |
1969 | /* Convert e.g. OP0 == 2048 into OP0 - 2048 == 0. */ | |
1970 | if (SMALL_OPERAND (-rhs)) | |
1971 | { | |
1972 | *op0 = riscv_force_binary (GET_MODE (*op0), PLUS, *op0, | |
1973 | GEN_INT (-rhs)); | |
1974 | *op1 = const0_rtx; | |
1975 | } | |
1976 | } | |
1977 | else | |
1978 | { | |
1979 | static const enum rtx_code mag_comparisons[][2] = { | |
1980 | {LEU, LTU}, {GTU, GEU}, {LE, LT}, {GT, GE} | |
1981 | }; | |
1982 | ||
1983 | /* Convert e.g. (OP0 <= 0xFFF) into (OP0 < 0x1000). */ | |
1984 | for (size_t i = 0; i < ARRAY_SIZE (mag_comparisons); i++) | |
1985 | { | |
1986 | HOST_WIDE_INT new_rhs; | |
1987 | bool increment = *code == mag_comparisons[i][0]; | |
1988 | bool decrement = *code == mag_comparisons[i][1]; | |
1989 | if (!increment && !decrement) | |
1990 | continue; | |
1991 | ||
1992 | new_rhs = rhs + (increment ? 1 : -1); | |
1993 | if (riscv_integer_cost (new_rhs) < riscv_integer_cost (rhs) | |
1994 | && (rhs < 0) == (new_rhs < 0)) | |
1995 | { | |
1996 | *op1 = GEN_INT (new_rhs); | |
1997 | *code = mag_comparisons[i][increment]; | |
1998 | } | |
1999 | break; | |
2000 | } | |
2001 | } | |
2002 | } | |
2003 | ||
2004 | riscv_extend_comparands (*code, op0, op1); | |
2005 | ||
2006 | *op0 = force_reg (word_mode, *op0); | |
2007 | if (*op1 != const0_rtx) | |
2008 | *op1 = force_reg (word_mode, *op1); | |
2009 | } | |
2010 | ||
2011 | /* Like riscv_emit_int_compare, but for floating-point comparisons. */ | |
2012 | ||
2013 | static void | |
2014 | riscv_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1) | |
2015 | { | |
2016 | rtx tmp0, tmp1, cmp_op0 = *op0, cmp_op1 = *op1; | |
2017 | enum rtx_code fp_code = *code; | |
2018 | *code = NE; | |
2019 | ||
2020 | switch (fp_code) | |
2021 | { | |
2022 | case UNORDERED: | |
2023 | *code = EQ; | |
2024 | /* Fall through. */ | |
2025 | ||
2026 | case ORDERED: | |
2027 | /* a == a && b == b */ | |
2028 | tmp0 = riscv_force_binary (word_mode, EQ, cmp_op0, cmp_op0); | |
2029 | tmp1 = riscv_force_binary (word_mode, EQ, cmp_op1, cmp_op1); | |
2030 | *op0 = riscv_force_binary (word_mode, AND, tmp0, tmp1); | |
2031 | *op1 = const0_rtx; | |
2032 | break; | |
2033 | ||
2034 | case UNEQ: | |
2035 | case LTGT: | |
2036 | /* ordered(a, b) > (a == b) */ | |
2037 | *code = fp_code == LTGT ? GTU : EQ; | |
2038 | tmp0 = riscv_force_binary (word_mode, EQ, cmp_op0, cmp_op0); | |
2039 | tmp1 = riscv_force_binary (word_mode, EQ, cmp_op1, cmp_op1); | |
2040 | *op0 = riscv_force_binary (word_mode, AND, tmp0, tmp1); | |
2041 | *op1 = riscv_force_binary (word_mode, EQ, cmp_op0, cmp_op1); | |
2042 | break; | |
2043 | ||
2044 | #define UNORDERED_COMPARISON(CODE, CMP) \ | |
2045 | case CODE: \ | |
2046 | *code = EQ; \ | |
2047 | *op0 = gen_reg_rtx (word_mode); \ | |
2048 | if (GET_MODE (cmp_op0) == SFmode && TARGET_64BIT) \ | |
2049 | emit_insn (gen_f##CMP##_quietsfdi4 (*op0, cmp_op0, cmp_op1)); \ | |
2050 | else if (GET_MODE (cmp_op0) == SFmode) \ | |
2051 | emit_insn (gen_f##CMP##_quietsfsi4 (*op0, cmp_op0, cmp_op1)); \ | |
2052 | else if (GET_MODE (cmp_op0) == DFmode && TARGET_64BIT) \ | |
2053 | emit_insn (gen_f##CMP##_quietdfdi4 (*op0, cmp_op0, cmp_op1)); \ | |
2054 | else if (GET_MODE (cmp_op0) == DFmode) \ | |
2055 | emit_insn (gen_f##CMP##_quietdfsi4 (*op0, cmp_op0, cmp_op1)); \ | |
2056 | else \ | |
2057 | gcc_unreachable (); \ | |
2058 | *op1 = const0_rtx; \ | |
2059 | break; | |
2060 | ||
2061 | case UNLT: | |
2062 | std::swap (cmp_op0, cmp_op1); | |
cccfcff4 | 2063 | gcc_fallthrough (); |
09cae750 PD |
2064 | |
2065 | UNORDERED_COMPARISON(UNGT, le) | |
2066 | ||
2067 | case UNLE: | |
2068 | std::swap (cmp_op0, cmp_op1); | |
cccfcff4 | 2069 | gcc_fallthrough (); |
09cae750 PD |
2070 | |
2071 | UNORDERED_COMPARISON(UNGE, lt) | |
2072 | #undef UNORDERED_COMPARISON | |
2073 | ||
2074 | case NE: | |
2075 | fp_code = EQ; | |
2076 | *code = EQ; | |
2077 | /* Fall through. */ | |
2078 | ||
2079 | case EQ: | |
2080 | case LE: | |
2081 | case LT: | |
2082 | case GE: | |
2083 | case GT: | |
2084 | /* We have instructions for these cases. */ | |
2085 | *op0 = riscv_force_binary (word_mode, fp_code, cmp_op0, cmp_op1); | |
2086 | *op1 = const0_rtx; | |
2087 | break; | |
2088 | ||
2089 | default: | |
2090 | gcc_unreachable (); | |
2091 | } | |
2092 | } | |
2093 | ||
2094 | /* CODE-compare OP0 and OP1. Store the result in TARGET. */ | |
2095 | ||
2096 | void | |
2097 | riscv_expand_int_scc (rtx target, enum rtx_code code, rtx op0, rtx op1) | |
2098 | { | |
2099 | riscv_extend_comparands (code, &op0, &op1); | |
2100 | op0 = force_reg (word_mode, op0); | |
2101 | ||
2102 | if (code == EQ || code == NE) | |
2103 | { | |
2104 | rtx zie = riscv_zero_if_equal (op0, op1); | |
2105 | riscv_emit_binary (code, target, zie, const0_rtx); | |
2106 | } | |
2107 | else | |
2108 | riscv_emit_int_order_test (code, 0, target, op0, op1); | |
2109 | } | |
2110 | ||
2111 | /* Like riscv_expand_int_scc, but for floating-point comparisons. */ | |
2112 | ||
2113 | void | |
2114 | riscv_expand_float_scc (rtx target, enum rtx_code code, rtx op0, rtx op1) | |
2115 | { | |
2116 | riscv_emit_float_compare (&code, &op0, &op1); | |
2117 | ||
2118 | rtx cmp = riscv_force_binary (word_mode, code, op0, op1); | |
2119 | riscv_emit_set (target, lowpart_subreg (SImode, cmp, word_mode)); | |
2120 | } | |
2121 | ||
2122 | /* Jump to LABEL if (CODE OP0 OP1) holds. */ | |
2123 | ||
2124 | void | |
2125 | riscv_expand_conditional_branch (rtx label, rtx_code code, rtx op0, rtx op1) | |
2126 | { | |
2127 | if (FLOAT_MODE_P (GET_MODE (op1))) | |
2128 | riscv_emit_float_compare (&code, &op0, &op1); | |
2129 | else | |
2130 | riscv_emit_int_compare (&code, &op0, &op1); | |
2131 | ||
2132 | rtx condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1); | |
2133 | emit_jump_insn (gen_condjump (condition, label)); | |
2134 | } | |
2135 | ||
2136 | /* Implement TARGET_FUNCTION_ARG_BOUNDARY. Every parameter gets at | |
2137 | least PARM_BOUNDARY bits of alignment, but will be given anything up | |
2138 | to STACK_BOUNDARY bits if the type requires it. */ | |
2139 | ||
2140 | static unsigned int | |
b8506a8a | 2141 | riscv_function_arg_boundary (machine_mode mode, const_tree type) |
09cae750 PD |
2142 | { |
2143 | unsigned int alignment; | |
2144 | ||
2145 | /* Use natural alignment if the type is not aggregate data. */ | |
2146 | if (type && !AGGREGATE_TYPE_P (type)) | |
2147 | alignment = TYPE_ALIGN (TYPE_MAIN_VARIANT (type)); | |
2148 | else | |
2149 | alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode); | |
2150 | ||
2151 | return MIN (STACK_BOUNDARY, MAX (PARM_BOUNDARY, alignment)); | |
2152 | } | |
2153 | ||
2154 | /* If MODE represents an argument that can be passed or returned in | |
2155 | floating-point registers, return the number of registers, else 0. */ | |
2156 | ||
2157 | static unsigned | |
b8506a8a | 2158 | riscv_pass_mode_in_fpr_p (machine_mode mode) |
09cae750 PD |
2159 | { |
2160 | if (GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_FP_ARG) | |
2161 | { | |
2162 | if (GET_MODE_CLASS (mode) == MODE_FLOAT) | |
2163 | return 1; | |
2164 | ||
2165 | if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT) | |
2166 | return 2; | |
2167 | } | |
2168 | ||
2169 | return 0; | |
2170 | } | |
2171 | ||
2172 | typedef struct { | |
2173 | const_tree type; | |
2174 | HOST_WIDE_INT offset; | |
2175 | } riscv_aggregate_field; | |
2176 | ||
2177 | /* Identify subfields of aggregates that are candidates for passing in | |
2178 | floating-point registers. */ | |
2179 | ||
2180 | static int | |
2181 | riscv_flatten_aggregate_field (const_tree type, | |
2182 | riscv_aggregate_field fields[2], | |
2183 | int n, HOST_WIDE_INT offset) | |
2184 | { | |
2185 | switch (TREE_CODE (type)) | |
2186 | { | |
2187 | case RECORD_TYPE: | |
2188 | /* Can't handle incomplete types nor sizes that are not fixed. */ | |
2189 | if (!COMPLETE_TYPE_P (type) | |
2190 | || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST | |
2191 | || !tree_fits_uhwi_p (TYPE_SIZE (type))) | |
2192 | return -1; | |
2193 | ||
2194 | for (tree f = TYPE_FIELDS (type); f; f = DECL_CHAIN (f)) | |
2195 | if (TREE_CODE (f) == FIELD_DECL) | |
2196 | { | |
2197 | if (!TYPE_P (TREE_TYPE (f))) | |
2198 | return -1; | |
2199 | ||
2200 | HOST_WIDE_INT pos = offset + int_byte_position (f); | |
2201 | n = riscv_flatten_aggregate_field (TREE_TYPE (f), fields, n, pos); | |
2202 | if (n < 0) | |
2203 | return -1; | |
2204 | } | |
2205 | return n; | |
2206 | ||
2207 | case ARRAY_TYPE: | |
2208 | { | |
2209 | HOST_WIDE_INT n_elts; | |
2210 | riscv_aggregate_field subfields[2]; | |
2211 | tree index = TYPE_DOMAIN (type); | |
2212 | tree elt_size = TYPE_SIZE_UNIT (TREE_TYPE (type)); | |
2213 | int n_subfields = riscv_flatten_aggregate_field (TREE_TYPE (type), | |
2214 | subfields, 0, offset); | |
2215 | ||
2216 | /* Can't handle incomplete types nor sizes that are not fixed. */ | |
2217 | if (n_subfields <= 0 | |
2218 | || !COMPLETE_TYPE_P (type) | |
2219 | || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST | |
2220 | || !index | |
2221 | || !TYPE_MAX_VALUE (index) | |
2222 | || !tree_fits_uhwi_p (TYPE_MAX_VALUE (index)) | |
2223 | || !TYPE_MIN_VALUE (index) | |
2224 | || !tree_fits_uhwi_p (TYPE_MIN_VALUE (index)) | |
2225 | || !tree_fits_uhwi_p (elt_size)) | |
2226 | return -1; | |
2227 | ||
2228 | n_elts = 1 + tree_to_uhwi (TYPE_MAX_VALUE (index)) | |
2229 | - tree_to_uhwi (TYPE_MIN_VALUE (index)); | |
2230 | gcc_assert (n_elts >= 0); | |
2231 | ||
2232 | for (HOST_WIDE_INT i = 0; i < n_elts; i++) | |
2233 | for (int j = 0; j < n_subfields; j++) | |
2234 | { | |
2235 | if (n >= 2) | |
2236 | return -1; | |
2237 | ||
2238 | fields[n] = subfields[j]; | |
2239 | fields[n++].offset += i * tree_to_uhwi (elt_size); | |
2240 | } | |
2241 | ||
2242 | return n; | |
2243 | } | |
2244 | ||
2245 | case COMPLEX_TYPE: | |
2246 | { | |
2247 | /* Complex type need consume 2 field, so n must be 0. */ | |
2248 | if (n != 0) | |
2249 | return -1; | |
2250 | ||
2251 | HOST_WIDE_INT elt_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (type))); | |
2252 | ||
2253 | if (elt_size <= UNITS_PER_FP_ARG) | |
2254 | { | |
2255 | fields[0].type = TREE_TYPE (type); | |
2256 | fields[0].offset = offset; | |
2257 | fields[1].type = TREE_TYPE (type); | |
2258 | fields[1].offset = offset + elt_size; | |
2259 | ||
2260 | return 2; | |
2261 | } | |
2262 | ||
2263 | return -1; | |
2264 | } | |
2265 | ||
2266 | default: | |
2267 | if (n < 2 | |
2268 | && ((SCALAR_FLOAT_TYPE_P (type) | |
2269 | && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FP_ARG) | |
2270 | || (INTEGRAL_TYPE_P (type) | |
2271 | && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_WORD))) | |
2272 | { | |
2273 | fields[n].type = type; | |
2274 | fields[n].offset = offset; | |
2275 | return n + 1; | |
2276 | } | |
2277 | else | |
2278 | return -1; | |
2279 | } | |
2280 | } | |
2281 | ||
2282 | /* Identify candidate aggregates for passing in floating-point registers. | |
2283 | Candidates have at most two fields after flattening. */ | |
2284 | ||
2285 | static int | |
2286 | riscv_flatten_aggregate_argument (const_tree type, | |
2287 | riscv_aggregate_field fields[2]) | |
2288 | { | |
2289 | if (!type || TREE_CODE (type) != RECORD_TYPE) | |
2290 | return -1; | |
2291 | ||
2292 | return riscv_flatten_aggregate_field (type, fields, 0, 0); | |
2293 | } | |
2294 | ||
2295 | /* See whether TYPE is a record whose fields should be returned in one or | |
2296 | two floating-point registers. If so, populate FIELDS accordingly. */ | |
2297 | ||
2298 | static unsigned | |
2299 | riscv_pass_aggregate_in_fpr_pair_p (const_tree type, | |
2300 | riscv_aggregate_field fields[2]) | |
2301 | { | |
2302 | int n = riscv_flatten_aggregate_argument (type, fields); | |
2303 | ||
2304 | for (int i = 0; i < n; i++) | |
2305 | if (!SCALAR_FLOAT_TYPE_P (fields[i].type)) | |
2306 | return 0; | |
2307 | ||
2308 | return n > 0 ? n : 0; | |
2309 | } | |
2310 | ||
2311 | /* See whether TYPE is a record whose fields should be returned in one or | |
2312 | floating-point register and one integer register. If so, populate | |
2313 | FIELDS accordingly. */ | |
2314 | ||
2315 | static bool | |
2316 | riscv_pass_aggregate_in_fpr_and_gpr_p (const_tree type, | |
2317 | riscv_aggregate_field fields[2]) | |
2318 | { | |
2319 | unsigned num_int = 0, num_float = 0; | |
2320 | int n = riscv_flatten_aggregate_argument (type, fields); | |
2321 | ||
2322 | for (int i = 0; i < n; i++) | |
2323 | { | |
2324 | num_float += SCALAR_FLOAT_TYPE_P (fields[i].type); | |
2325 | num_int += INTEGRAL_TYPE_P (fields[i].type); | |
2326 | } | |
2327 | ||
2328 | return num_int == 1 && num_float == 1; | |
2329 | } | |
2330 | ||
2331 | /* Return the representation of an argument passed or returned in an FPR | |
2332 | when the value has mode VALUE_MODE and the type has TYPE_MODE. The | |
2333 | two modes may be different for structures like: | |
2334 | ||
2335 | struct __attribute__((packed)) foo { float f; } | |
2336 | ||
2337 | where the SFmode value "f" is passed in REGNO but the struct itself | |
2338 | has mode BLKmode. */ | |
2339 | ||
2340 | static rtx | |
b8506a8a RS |
2341 | riscv_pass_fpr_single (machine_mode type_mode, unsigned regno, |
2342 | machine_mode value_mode) | |
09cae750 PD |
2343 | { |
2344 | rtx x = gen_rtx_REG (value_mode, regno); | |
2345 | ||
2346 | if (type_mode != value_mode) | |
2347 | { | |
2348 | x = gen_rtx_EXPR_LIST (VOIDmode, x, const0_rtx); | |
2349 | x = gen_rtx_PARALLEL (type_mode, gen_rtvec (1, x)); | |
2350 | } | |
2351 | return x; | |
2352 | } | |
2353 | ||
2354 | /* Pass or return a composite value in the FPR pair REGNO and REGNO + 1. | |
2355 | MODE is the mode of the composite. MODE1 and OFFSET1 are the mode and | |
2356 | byte offset for the first value, likewise MODE2 and OFFSET2 for the | |
2357 | second value. */ | |
2358 | ||
2359 | static rtx | |
b8506a8a RS |
2360 | riscv_pass_fpr_pair (machine_mode mode, unsigned regno1, |
2361 | machine_mode mode1, HOST_WIDE_INT offset1, | |
2362 | unsigned regno2, machine_mode mode2, | |
09cae750 PD |
2363 | HOST_WIDE_INT offset2) |
2364 | { | |
2365 | return gen_rtx_PARALLEL | |
2366 | (mode, | |
2367 | gen_rtvec (2, | |
2368 | gen_rtx_EXPR_LIST (VOIDmode, | |
2369 | gen_rtx_REG (mode1, regno1), | |
2370 | GEN_INT (offset1)), | |
2371 | gen_rtx_EXPR_LIST (VOIDmode, | |
2372 | gen_rtx_REG (mode2, regno2), | |
2373 | GEN_INT (offset2)))); | |
2374 | } | |
2375 | ||
2376 | /* Fill INFO with information about a single argument, and return an | |
2377 | RTL pattern to pass or return the argument. CUM is the cumulative | |
2378 | state for earlier arguments. MODE is the mode of this argument and | |
2379 | TYPE is its type (if known). NAMED is true if this is a named | |
2380 | (fixed) argument rather than a variable one. RETURN_P is true if | |
2381 | returning the argument, or false if passing the argument. */ | |
2382 | ||
2383 | static rtx | |
2384 | riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum, | |
b8506a8a | 2385 | machine_mode mode, const_tree type, bool named, |
09cae750 PD |
2386 | bool return_p) |
2387 | { | |
2388 | unsigned num_bytes, num_words; | |
2389 | unsigned fpr_base = return_p ? FP_RETURN : FP_ARG_FIRST; | |
2390 | unsigned gpr_base = return_p ? GP_RETURN : GP_ARG_FIRST; | |
2391 | unsigned alignment = riscv_function_arg_boundary (mode, type); | |
2392 | ||
2393 | memset (info, 0, sizeof (*info)); | |
2394 | info->gpr_offset = cum->num_gprs; | |
2395 | info->fpr_offset = cum->num_fprs; | |
2396 | ||
2397 | if (named) | |
2398 | { | |
2399 | riscv_aggregate_field fields[2]; | |
2400 | unsigned fregno = fpr_base + info->fpr_offset; | |
2401 | unsigned gregno = gpr_base + info->gpr_offset; | |
2402 | ||
2403 | /* Pass one- or two-element floating-point aggregates in FPRs. */ | |
2404 | if ((info->num_fprs = riscv_pass_aggregate_in_fpr_pair_p (type, fields)) | |
2405 | && info->fpr_offset + info->num_fprs <= MAX_ARGS_IN_REGISTERS) | |
2406 | switch (info->num_fprs) | |
2407 | { | |
2408 | case 1: | |
2409 | return riscv_pass_fpr_single (mode, fregno, | |
2410 | TYPE_MODE (fields[0].type)); | |
2411 | ||
2412 | case 2: | |
2413 | return riscv_pass_fpr_pair (mode, fregno, | |
2414 | TYPE_MODE (fields[0].type), | |
2415 | fields[0].offset, | |
2416 | fregno + 1, | |
2417 | TYPE_MODE (fields[1].type), | |
2418 | fields[1].offset); | |
2419 | ||
2420 | default: | |
2421 | gcc_unreachable (); | |
2422 | } | |
2423 | ||
2424 | /* Pass real and complex floating-point numbers in FPRs. */ | |
2425 | if ((info->num_fprs = riscv_pass_mode_in_fpr_p (mode)) | |
2426 | && info->fpr_offset + info->num_fprs <= MAX_ARGS_IN_REGISTERS) | |
2427 | switch (GET_MODE_CLASS (mode)) | |
2428 | { | |
2429 | case MODE_FLOAT: | |
2430 | return gen_rtx_REG (mode, fregno); | |
2431 | ||
2432 | case MODE_COMPLEX_FLOAT: | |
2433 | return riscv_pass_fpr_pair (mode, fregno, GET_MODE_INNER (mode), 0, | |
2434 | fregno + 1, GET_MODE_INNER (mode), | |
2435 | GET_MODE_UNIT_SIZE (mode)); | |
2436 | ||
2437 | default: | |
2438 | gcc_unreachable (); | |
2439 | } | |
2440 | ||
2441 | /* Pass structs with one float and one integer in an FPR and a GPR. */ | |
2442 | if (riscv_pass_aggregate_in_fpr_and_gpr_p (type, fields) | |
2443 | && info->gpr_offset < MAX_ARGS_IN_REGISTERS | |
2444 | && info->fpr_offset < MAX_ARGS_IN_REGISTERS) | |
2445 | { | |
2446 | info->num_gprs = 1; | |
2447 | info->num_fprs = 1; | |
2448 | ||
2449 | if (!SCALAR_FLOAT_TYPE_P (fields[0].type)) | |
2450 | std::swap (fregno, gregno); | |
2451 | ||
2452 | return riscv_pass_fpr_pair (mode, fregno, TYPE_MODE (fields[0].type), | |
2453 | fields[0].offset, | |
2454 | gregno, TYPE_MODE (fields[1].type), | |
2455 | fields[1].offset); | |
2456 | } | |
2457 | } | |
2458 | ||
2459 | /* Work out the size of the argument. */ | |
2460 | num_bytes = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); | |
2461 | num_words = (num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; | |
2462 | ||
2463 | /* Doubleword-aligned varargs start on an even register boundary. */ | |
2464 | if (!named && num_bytes != 0 && alignment > BITS_PER_WORD) | |
2465 | info->gpr_offset += info->gpr_offset & 1; | |
2466 | ||
2467 | /* Partition the argument between registers and stack. */ | |
2468 | info->num_fprs = 0; | |
2469 | info->num_gprs = MIN (num_words, MAX_ARGS_IN_REGISTERS - info->gpr_offset); | |
2470 | info->stack_p = (num_words - info->num_gprs) != 0; | |
2471 | ||
2472 | if (info->num_gprs || return_p) | |
2473 | return gen_rtx_REG (mode, gpr_base + info->gpr_offset); | |
2474 | ||
2475 | return NULL_RTX; | |
2476 | } | |
2477 | ||
2478 | /* Implement TARGET_FUNCTION_ARG. */ | |
2479 | ||
2480 | static rtx | |
b8506a8a | 2481 | riscv_function_arg (cumulative_args_t cum_v, machine_mode mode, |
09cae750 PD |
2482 | const_tree type, bool named) |
2483 | { | |
2484 | CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); | |
2485 | struct riscv_arg_info info; | |
2486 | ||
2487 | if (mode == VOIDmode) | |
2488 | return NULL; | |
2489 | ||
2490 | return riscv_get_arg_info (&info, cum, mode, type, named, false); | |
2491 | } | |
2492 | ||
2493 | /* Implement TARGET_FUNCTION_ARG_ADVANCE. */ | |
2494 | ||
2495 | static void | |
b8506a8a | 2496 | riscv_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, |
09cae750 PD |
2497 | const_tree type, bool named) |
2498 | { | |
2499 | CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); | |
2500 | struct riscv_arg_info info; | |
2501 | ||
2502 | riscv_get_arg_info (&info, cum, mode, type, named, false); | |
2503 | ||
2504 | /* Advance the register count. This has the effect of setting | |
2505 | num_gprs to MAX_ARGS_IN_REGISTERS if a doubleword-aligned | |
2506 | argument required us to skip the final GPR and pass the whole | |
2507 | argument on the stack. */ | |
2508 | cum->num_fprs = info.fpr_offset + info.num_fprs; | |
2509 | cum->num_gprs = info.gpr_offset + info.num_gprs; | |
2510 | } | |
2511 | ||
2512 | /* Implement TARGET_ARG_PARTIAL_BYTES. */ | |
2513 | ||
2514 | static int | |
2515 | riscv_arg_partial_bytes (cumulative_args_t cum, | |
b8506a8a | 2516 | machine_mode mode, tree type, bool named) |
09cae750 PD |
2517 | { |
2518 | struct riscv_arg_info arg; | |
2519 | ||
2520 | riscv_get_arg_info (&arg, get_cumulative_args (cum), mode, type, named, false); | |
2521 | return arg.stack_p ? arg.num_gprs * UNITS_PER_WORD : 0; | |
2522 | } | |
2523 | ||
2524 | /* Implement FUNCTION_VALUE and LIBCALL_VALUE. For normal calls, | |
2525 | VALTYPE is the return type and MODE is VOIDmode. For libcalls, | |
2526 | VALTYPE is null and MODE is the mode of the return value. */ | |
2527 | ||
2528 | rtx | |
b8506a8a | 2529 | riscv_function_value (const_tree type, const_tree func, machine_mode mode) |
09cae750 PD |
2530 | { |
2531 | struct riscv_arg_info info; | |
2532 | CUMULATIVE_ARGS args; | |
2533 | ||
2534 | if (type) | |
2535 | { | |
2536 | int unsigned_p = TYPE_UNSIGNED (type); | |
2537 | ||
2538 | mode = TYPE_MODE (type); | |
2539 | ||
2540 | /* Since TARGET_PROMOTE_FUNCTION_MODE unconditionally promotes, | |
2541 | return values, promote the mode here too. */ | |
2542 | mode = promote_function_mode (type, mode, &unsigned_p, func, 1); | |
2543 | } | |
2544 | ||
2545 | memset (&args, 0, sizeof args); | |
2546 | return riscv_get_arg_info (&info, &args, mode, type, true, true); | |
2547 | } | |
2548 | ||
2549 | /* Implement TARGET_PASS_BY_REFERENCE. */ | |
2550 | ||
2551 | static bool | |
b8506a8a | 2552 | riscv_pass_by_reference (cumulative_args_t cum_v, machine_mode mode, |
09cae750 PD |
2553 | const_tree type, bool named) |
2554 | { | |
2555 | HOST_WIDE_INT size = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); | |
2556 | struct riscv_arg_info info; | |
2557 | CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); | |
2558 | ||
2559 | /* ??? std_gimplify_va_arg_expr passes NULL for cum. Fortunately, we | |
2560 | never pass variadic arguments in floating-point registers, so we can | |
2561 | avoid the call to riscv_get_arg_info in this case. */ | |
2562 | if (cum != NULL) | |
2563 | { | |
2564 | /* Don't pass by reference if we can use a floating-point register. */ | |
2565 | riscv_get_arg_info (&info, cum, mode, type, named, false); | |
2566 | if (info.num_fprs) | |
2567 | return false; | |
2568 | } | |
2569 | ||
2570 | /* Pass by reference if the data do not fit in two integer registers. */ | |
2571 | return !IN_RANGE (size, 0, 2 * UNITS_PER_WORD); | |
2572 | } | |
2573 | ||
2574 | /* Implement TARGET_RETURN_IN_MEMORY. */ | |
2575 | ||
2576 | static bool | |
2577 | riscv_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED) | |
2578 | { | |
2579 | CUMULATIVE_ARGS args; | |
2580 | cumulative_args_t cum = pack_cumulative_args (&args); | |
2581 | ||
2582 | /* The rules for returning in memory are the same as for passing the | |
2583 | first named argument by reference. */ | |
2584 | memset (&args, 0, sizeof args); | |
2585 | return riscv_pass_by_reference (cum, TYPE_MODE (type), type, true); | |
2586 | } | |
2587 | ||
2588 | /* Implement TARGET_SETUP_INCOMING_VARARGS. */ | |
2589 | ||
2590 | static void | |
b8506a8a | 2591 | riscv_setup_incoming_varargs (cumulative_args_t cum, machine_mode mode, |
09cae750 PD |
2592 | tree type, int *pretend_size ATTRIBUTE_UNUSED, |
2593 | int no_rtl) | |
2594 | { | |
2595 | CUMULATIVE_ARGS local_cum; | |
2596 | int gp_saved; | |
2597 | ||
2598 | /* The caller has advanced CUM up to, but not beyond, the last named | |
2599 | argument. Advance a local copy of CUM past the last "real" named | |
2600 | argument, to find out how many registers are left over. */ | |
2601 | local_cum = *get_cumulative_args (cum); | |
2602 | riscv_function_arg_advance (pack_cumulative_args (&local_cum), mode, type, 1); | |
2603 | ||
2604 | /* Found out how many registers we need to save. */ | |
2605 | gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs; | |
2606 | ||
2607 | if (!no_rtl && gp_saved > 0) | |
2608 | { | |
2609 | rtx ptr = plus_constant (Pmode, virtual_incoming_args_rtx, | |
2610 | REG_PARM_STACK_SPACE (cfun->decl) | |
2611 | - gp_saved * UNITS_PER_WORD); | |
2612 | rtx mem = gen_frame_mem (BLKmode, ptr); | |
2613 | set_mem_alias_set (mem, get_varargs_alias_set ()); | |
2614 | ||
2615 | move_block_from_reg (local_cum.num_gprs + GP_ARG_FIRST, | |
2616 | mem, gp_saved); | |
2617 | } | |
2618 | if (REG_PARM_STACK_SPACE (cfun->decl) == 0) | |
2619 | cfun->machine->varargs_size = gp_saved * UNITS_PER_WORD; | |
2620 | } | |
2621 | ||
2622 | /* Implement TARGET_EXPAND_BUILTIN_VA_START. */ | |
2623 | ||
2624 | static void | |
2625 | riscv_va_start (tree valist, rtx nextarg) | |
2626 | { | |
2627 | nextarg = plus_constant (Pmode, nextarg, -cfun->machine->varargs_size); | |
2628 | std_expand_builtin_va_start (valist, nextarg); | |
2629 | } | |
2630 | ||
2631 | /* Make ADDR suitable for use as a call or sibcall target. */ | |
2632 | ||
2633 | rtx | |
2634 | riscv_legitimize_call_address (rtx addr) | |
2635 | { | |
2636 | if (!call_insn_operand (addr, VOIDmode)) | |
2637 | { | |
2638 | rtx reg = RISCV_PROLOGUE_TEMP (Pmode); | |
2639 | riscv_emit_move (reg, addr); | |
2640 | return reg; | |
2641 | } | |
2642 | return addr; | |
2643 | } | |
2644 | ||
2645 | /* Print symbolic operand OP, which is part of a HIGH or LO_SUM | |
2646 | in context CONTEXT. HI_RELOC indicates a high-part reloc. */ | |
2647 | ||
2648 | static void | |
2649 | riscv_print_operand_reloc (FILE *file, rtx op, bool hi_reloc) | |
2650 | { | |
2651 | const char *reloc; | |
2652 | ||
2653 | switch (riscv_classify_symbolic_expression (op)) | |
2654 | { | |
2655 | case SYMBOL_ABSOLUTE: | |
2656 | reloc = hi_reloc ? "%hi" : "%lo"; | |
2657 | break; | |
2658 | ||
2659 | case SYMBOL_PCREL: | |
2660 | reloc = hi_reloc ? "%pcrel_hi" : "%pcrel_lo"; | |
2661 | break; | |
2662 | ||
2663 | case SYMBOL_TLS_LE: | |
2664 | reloc = hi_reloc ? "%tprel_hi" : "%tprel_lo"; | |
2665 | break; | |
2666 | ||
2667 | default: | |
2668 | gcc_unreachable (); | |
2669 | } | |
2670 | ||
2671 | fprintf (file, "%s(", reloc); | |
2672 | output_addr_const (file, riscv_strip_unspec_address (op)); | |
2673 | fputc (')', file); | |
2674 | } | |
2675 | ||
2676 | /* Return true if the .AQ suffix should be added to an AMO to implement the | |
2677 | acquire portion of memory model MODEL. */ | |
2678 | ||
2679 | static bool | |
2680 | riscv_memmodel_needs_amo_acquire (enum memmodel model) | |
2681 | { | |
2682 | switch (model) | |
2683 | { | |
2684 | case MEMMODEL_ACQ_REL: | |
2685 | case MEMMODEL_SEQ_CST: | |
2686 | case MEMMODEL_SYNC_SEQ_CST: | |
2687 | case MEMMODEL_ACQUIRE: | |
2688 | case MEMMODEL_CONSUME: | |
2689 | case MEMMODEL_SYNC_ACQUIRE: | |
2690 | return true; | |
2691 | ||
2692 | case MEMMODEL_RELEASE: | |
2693 | case MEMMODEL_SYNC_RELEASE: | |
2694 | case MEMMODEL_RELAXED: | |
2695 | return false; | |
2696 | ||
2697 | default: | |
2698 | gcc_unreachable (); | |
2699 | } | |
2700 | } | |
2701 | ||
2702 | /* Return true if a FENCE should be emitted to before a memory access to | |
2703 | implement the release portion of memory model MODEL. */ | |
2704 | ||
2705 | static bool | |
2706 | riscv_memmodel_needs_release_fence (enum memmodel model) | |
2707 | { | |
2708 | switch (model) | |
2709 | { | |
2710 | case MEMMODEL_ACQ_REL: | |
2711 | case MEMMODEL_SEQ_CST: | |
2712 | case MEMMODEL_SYNC_SEQ_CST: | |
2713 | case MEMMODEL_RELEASE: | |
2714 | case MEMMODEL_SYNC_RELEASE: | |
2715 | return true; | |
2716 | ||
2717 | case MEMMODEL_ACQUIRE: | |
2718 | case MEMMODEL_CONSUME: | |
2719 | case MEMMODEL_SYNC_ACQUIRE: | |
2720 | case MEMMODEL_RELAXED: | |
2721 | return false; | |
2722 | ||
2723 | default: | |
2724 | gcc_unreachable (); | |
2725 | } | |
2726 | } | |
2727 | ||
2728 | /* Implement TARGET_PRINT_OPERAND. The RISCV-specific operand codes are: | |
2729 | ||
2730 | 'h' Print the high-part relocation associated with OP, after stripping | |
2731 | any outermost HIGH. | |
2732 | 'R' Print the low-part relocation associated with OP. | |
2733 | 'C' Print the integer branch condition for comparison OP. | |
2734 | 'A' Print the atomic operation suffix for memory model OP. | |
2735 | 'F' Print a FENCE if the memory model requires a release. | |
0791ac18 MC |
2736 | 'z' Print x0 if OP is zero, otherwise print OP normally. |
2737 | 'i' Print i if the operand is not a register. */ | |
09cae750 PD |
2738 | |
2739 | static void | |
2740 | riscv_print_operand (FILE *file, rtx op, int letter) | |
2741 | { | |
b8506a8a | 2742 | machine_mode mode = GET_MODE (op); |
09cae750 PD |
2743 | enum rtx_code code = GET_CODE (op); |
2744 | ||
2745 | switch (letter) | |
2746 | { | |
2747 | case 'h': | |
2748 | if (code == HIGH) | |
2749 | op = XEXP (op, 0); | |
2750 | riscv_print_operand_reloc (file, op, true); | |
2751 | break; | |
2752 | ||
2753 | case 'R': | |
2754 | riscv_print_operand_reloc (file, op, false); | |
2755 | break; | |
2756 | ||
2757 | case 'C': | |
2758 | /* The RTL names match the instruction names. */ | |
2759 | fputs (GET_RTX_NAME (code), file); | |
2760 | break; | |
2761 | ||
2762 | case 'A': | |
2763 | if (riscv_memmodel_needs_amo_acquire ((enum memmodel) INTVAL (op))) | |
2764 | fputs (".aq", file); | |
2765 | break; | |
2766 | ||
2767 | case 'F': | |
2768 | if (riscv_memmodel_needs_release_fence ((enum memmodel) INTVAL (op))) | |
e05a9f8e | 2769 | fputs ("fence iorw,ow; ", file); |
09cae750 PD |
2770 | break; |
2771 | ||
0791ac18 MC |
2772 | case 'i': |
2773 | if (code != REG) | |
2774 | fputs ("i", file); | |
2775 | break; | |
2776 | ||
09cae750 PD |
2777 | default: |
2778 | switch (code) | |
2779 | { | |
2780 | case REG: | |
2781 | if (letter && letter != 'z') | |
2782 | output_operand_lossage ("invalid use of '%%%c'", letter); | |
2783 | fprintf (file, "%s", reg_names[REGNO (op)]); | |
2784 | break; | |
2785 | ||
2786 | case MEM: | |
2787 | if (letter && letter != 'z') | |
2788 | output_operand_lossage ("invalid use of '%%%c'", letter); | |
2789 | else | |
2790 | output_address (mode, XEXP (op, 0)); | |
2791 | break; | |
2792 | ||
2793 | default: | |
2794 | if (letter == 'z' && op == CONST0_RTX (GET_MODE (op))) | |
2795 | fputs (reg_names[GP_REG_FIRST], file); | |
2796 | else if (letter && letter != 'z') | |
2797 | output_operand_lossage ("invalid use of '%%%c'", letter); | |
2798 | else | |
2799 | output_addr_const (file, riscv_strip_unspec_address (op)); | |
2800 | break; | |
2801 | } | |
2802 | } | |
2803 | } | |
2804 | ||
2805 | /* Implement TARGET_PRINT_OPERAND_ADDRESS. */ | |
2806 | ||
2807 | static void | |
2808 | riscv_print_operand_address (FILE *file, machine_mode mode ATTRIBUTE_UNUSED, rtx x) | |
2809 | { | |
2810 | struct riscv_address_info addr; | |
2811 | ||
2812 | if (riscv_classify_address (&addr, x, word_mode, true)) | |
2813 | switch (addr.type) | |
2814 | { | |
2815 | case ADDRESS_REG: | |
2816 | riscv_print_operand (file, addr.offset, 0); | |
2817 | fprintf (file, "(%s)", reg_names[REGNO (addr.reg)]); | |
2818 | return; | |
2819 | ||
2820 | case ADDRESS_LO_SUM: | |
2821 | riscv_print_operand_reloc (file, addr.offset, false); | |
2822 | fprintf (file, "(%s)", reg_names[REGNO (addr.reg)]); | |
2823 | return; | |
2824 | ||
2825 | case ADDRESS_CONST_INT: | |
2826 | output_addr_const (file, x); | |
2827 | fprintf (file, "(%s)", reg_names[GP_REG_FIRST]); | |
2828 | return; | |
2829 | ||
2830 | case ADDRESS_SYMBOLIC: | |
2831 | output_addr_const (file, riscv_strip_unspec_address (x)); | |
2832 | return; | |
2833 | } | |
2834 | gcc_unreachable (); | |
2835 | } | |
2836 | ||
2837 | static bool | |
2838 | riscv_size_ok_for_small_data_p (int size) | |
2839 | { | |
2840 | return g_switch_value && IN_RANGE (size, 1, g_switch_value); | |
2841 | } | |
2842 | ||
2843 | /* Return true if EXP should be placed in the small data section. */ | |
2844 | ||
2845 | static bool | |
2846 | riscv_in_small_data_p (const_tree x) | |
2847 | { | |
2848 | if (TREE_CODE (x) == STRING_CST || TREE_CODE (x) == FUNCTION_DECL) | |
2849 | return false; | |
2850 | ||
2851 | if (TREE_CODE (x) == VAR_DECL && DECL_SECTION_NAME (x)) | |
2852 | { | |
2853 | const char *sec = DECL_SECTION_NAME (x); | |
2854 | return strcmp (sec, ".sdata") == 0 || strcmp (sec, ".sbss") == 0; | |
2855 | } | |
2856 | ||
2857 | return riscv_size_ok_for_small_data_p (int_size_in_bytes (TREE_TYPE (x))); | |
2858 | } | |
2859 | ||
2860 | /* Return a section for X, handling small data. */ | |
2861 | ||
2862 | static section * | |
b8506a8a | 2863 | riscv_elf_select_rtx_section (machine_mode mode, rtx x, |
09cae750 PD |
2864 | unsigned HOST_WIDE_INT align) |
2865 | { | |
2866 | section *s = default_elf_select_rtx_section (mode, x, align); | |
2867 | ||
2868 | if (riscv_size_ok_for_small_data_p (GET_MODE_SIZE (mode))) | |
2869 | { | |
2870 | if (strncmp (s->named.name, ".rodata.cst", strlen (".rodata.cst")) == 0) | |
2871 | { | |
2872 | /* Rename .rodata.cst* to .srodata.cst*. */ | |
2873 | char *name = (char *) alloca (strlen (s->named.name) + 2); | |
2874 | sprintf (name, ".s%s", s->named.name + 1); | |
2875 | return get_section (name, s->named.common.flags, NULL); | |
2876 | } | |
2877 | ||
2878 | if (s == data_section) | |
2879 | return sdata_section; | |
2880 | } | |
2881 | ||
2882 | return s; | |
2883 | } | |
2884 | ||
2885 | /* Make the last instruction frame-related and note that it performs | |
2886 | the operation described by FRAME_PATTERN. */ | |
2887 | ||
2888 | static void | |
2889 | riscv_set_frame_expr (rtx frame_pattern) | |
2890 | { | |
2891 | rtx insn; | |
2892 | ||
2893 | insn = get_last_insn (); | |
2894 | RTX_FRAME_RELATED_P (insn) = 1; | |
2895 | REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR, | |
2896 | frame_pattern, | |
2897 | REG_NOTES (insn)); | |
2898 | } | |
2899 | ||
2900 | /* Return a frame-related rtx that stores REG at MEM. | |
2901 | REG must be a single register. */ | |
2902 | ||
2903 | static rtx | |
2904 | riscv_frame_set (rtx mem, rtx reg) | |
2905 | { | |
2906 | rtx set = gen_rtx_SET (mem, reg); | |
2907 | RTX_FRAME_RELATED_P (set) = 1; | |
2908 | return set; | |
2909 | } | |
2910 | ||
2911 | /* Return true if the current function must save register REGNO. */ | |
2912 | ||
2913 | static bool | |
2914 | riscv_save_reg_p (unsigned int regno) | |
2915 | { | |
2916 | bool call_saved = !global_regs[regno] && !call_used_regs[regno]; | |
2917 | bool might_clobber = crtl->saves_all_registers | |
2918 | || df_regs_ever_live_p (regno); | |
2919 | ||
2920 | if (call_saved && might_clobber) | |
2921 | return true; | |
2922 | ||
2923 | if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) | |
2924 | return true; | |
2925 | ||
2926 | if (regno == RETURN_ADDR_REGNUM && crtl->calls_eh_return) | |
2927 | return true; | |
2928 | ||
2929 | return false; | |
2930 | } | |
2931 | ||
2932 | /* Determine whether to call GPR save/restore routines. */ | |
2933 | static bool | |
2934 | riscv_use_save_libcall (const struct riscv_frame_info *frame) | |
2935 | { | |
2936 | if (!TARGET_SAVE_RESTORE || crtl->calls_eh_return || frame_pointer_needed) | |
2937 | return false; | |
2938 | ||
2939 | return frame->save_libcall_adjustment != 0; | |
2940 | } | |
2941 | ||
2942 | /* Determine which GPR save/restore routine to call. */ | |
2943 | ||
2944 | static unsigned | |
2945 | riscv_save_libcall_count (unsigned mask) | |
2946 | { | |
2947 | for (unsigned n = GP_REG_LAST; n > GP_REG_FIRST; n--) | |
2948 | if (BITSET_P (mask, n)) | |
2949 | return CALLEE_SAVED_REG_NUMBER (n) + 1; | |
2950 | abort (); | |
2951 | } | |
2952 | ||
2953 | /* Populate the current function's riscv_frame_info structure. | |
2954 | ||
2955 | RISC-V stack frames grown downward. High addresses are at the top. | |
2956 | ||
2957 | +-------------------------------+ | |
2958 | | | | |
2959 | | incoming stack arguments | | |
2960 | | | | |
2961 | +-------------------------------+ <-- incoming stack pointer | |
2962 | | | | |
2963 | | callee-allocated save area | | |
2964 | | for arguments that are | | |
2965 | | split between registers and | | |
2966 | | the stack | | |
2967 | | | | |
2968 | +-------------------------------+ <-- arg_pointer_rtx | |
2969 | | | | |
2970 | | callee-allocated save area | | |
2971 | | for register varargs | | |
2972 | | | | |
2973 | +-------------------------------+ <-- hard_frame_pointer_rtx; | |
2974 | | | stack_pointer_rtx + gp_sp_offset | |
2975 | | GPR save area | + UNITS_PER_WORD | |
2976 | | | | |
2977 | +-------------------------------+ <-- stack_pointer_rtx + fp_sp_offset | |
2978 | | | + UNITS_PER_HWVALUE | |
2979 | | FPR save area | | |
2980 | | | | |
2981 | +-------------------------------+ <-- frame_pointer_rtx (virtual) | |
2982 | | | | |
2983 | | local variables | | |
2984 | | | | |
2985 | P +-------------------------------+ | |
2986 | | | | |
2987 | | outgoing stack arguments | | |
2988 | | | | |
2989 | +-------------------------------+ <-- stack_pointer_rtx | |
2990 | ||
2991 | Dynamic stack allocations such as alloca insert data at point P. | |
2992 | They decrease stack_pointer_rtx but leave frame_pointer_rtx and | |
2993 | hard_frame_pointer_rtx unchanged. */ | |
2994 | ||
2995 | static void | |
2996 | riscv_compute_frame_info (void) | |
2997 | { | |
2998 | struct riscv_frame_info *frame; | |
2999 | HOST_WIDE_INT offset; | |
3000 | unsigned int regno, i, num_x_saved = 0, num_f_saved = 0; | |
3001 | ||
3002 | frame = &cfun->machine->frame; | |
3003 | memset (frame, 0, sizeof (*frame)); | |
3004 | ||
3005 | /* Find out which GPRs we need to save. */ | |
3006 | for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) | |
3007 | if (riscv_save_reg_p (regno)) | |
3008 | frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++; | |
3009 | ||
3010 | /* If this function calls eh_return, we must also save and restore the | |
3011 | EH data registers. */ | |
3012 | if (crtl->calls_eh_return) | |
3013 | for (i = 0; (regno = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++) | |
3014 | frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++; | |
3015 | ||
3016 | /* Find out which FPRs we need to save. This loop must iterate over | |
3017 | the same space as its companion in riscv_for_each_saved_reg. */ | |
3018 | if (TARGET_HARD_FLOAT) | |
3019 | for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) | |
3020 | if (riscv_save_reg_p (regno)) | |
3021 | frame->fmask |= 1 << (regno - FP_REG_FIRST), num_f_saved++; | |
3022 | ||
3023 | /* At the bottom of the frame are any outgoing stack arguments. */ | |
3024 | offset = crtl->outgoing_args_size; | |
3025 | /* Next are local stack variables. */ | |
3026 | offset += RISCV_STACK_ALIGN (get_frame_size ()); | |
3027 | /* The virtual frame pointer points above the local variables. */ | |
3028 | frame->frame_pointer_offset = offset; | |
3029 | /* Next are the callee-saved FPRs. */ | |
3030 | if (frame->fmask) | |
3031 | offset += RISCV_STACK_ALIGN (num_f_saved * UNITS_PER_FP_REG); | |
3032 | frame->fp_sp_offset = offset - UNITS_PER_FP_REG; | |
3033 | /* Next are the callee-saved GPRs. */ | |
3034 | if (frame->mask) | |
3035 | { | |
3036 | unsigned x_save_size = RISCV_STACK_ALIGN (num_x_saved * UNITS_PER_WORD); | |
3037 | unsigned num_save_restore = 1 + riscv_save_libcall_count (frame->mask); | |
3038 | ||
3039 | /* Only use save/restore routines if they don't alter the stack size. */ | |
3040 | if (RISCV_STACK_ALIGN (num_save_restore * UNITS_PER_WORD) == x_save_size) | |
3041 | frame->save_libcall_adjustment = x_save_size; | |
3042 | ||
3043 | offset += x_save_size; | |
3044 | } | |
3045 | frame->gp_sp_offset = offset - UNITS_PER_WORD; | |
3046 | /* The hard frame pointer points above the callee-saved GPRs. */ | |
3047 | frame->hard_frame_pointer_offset = offset; | |
3048 | /* Above the hard frame pointer is the callee-allocated varags save area. */ | |
3049 | offset += RISCV_STACK_ALIGN (cfun->machine->varargs_size); | |
3050 | frame->arg_pointer_offset = offset; | |
3051 | /* Next is the callee-allocated area for pretend stack arguments. */ | |
3052 | offset += crtl->args.pretend_args_size; | |
3053 | frame->total_size = offset; | |
3054 | /* Next points the incoming stack pointer and any incoming arguments. */ | |
3055 | ||
3056 | /* Only use save/restore routines when the GPRs are atop the frame. */ | |
3057 | if (frame->hard_frame_pointer_offset != frame->total_size) | |
3058 | frame->save_libcall_adjustment = 0; | |
3059 | } | |
3060 | ||
3061 | /* Make sure that we're not trying to eliminate to the wrong hard frame | |
3062 | pointer. */ | |
3063 | ||
3064 | static bool | |
3065 | riscv_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) | |
3066 | { | |
3067 | return (to == HARD_FRAME_POINTER_REGNUM || to == STACK_POINTER_REGNUM); | |
3068 | } | |
3069 | ||
3070 | /* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame pointer | |
3071 | or argument pointer. TO is either the stack pointer or hard frame | |
3072 | pointer. */ | |
3073 | ||
3074 | HOST_WIDE_INT | |
3075 | riscv_initial_elimination_offset (int from, int to) | |
3076 | { | |
3077 | HOST_WIDE_INT src, dest; | |
3078 | ||
3079 | riscv_compute_frame_info (); | |
3080 | ||
3081 | if (to == HARD_FRAME_POINTER_REGNUM) | |
3082 | dest = cfun->machine->frame.hard_frame_pointer_offset; | |
3083 | else if (to == STACK_POINTER_REGNUM) | |
3084 | dest = 0; /* The stack pointer is the base of all offsets, hence 0. */ | |
3085 | else | |
3086 | gcc_unreachable (); | |
3087 | ||
3088 | if (from == FRAME_POINTER_REGNUM) | |
3089 | src = cfun->machine->frame.frame_pointer_offset; | |
3090 | else if (from == ARG_POINTER_REGNUM) | |
3091 | src = cfun->machine->frame.arg_pointer_offset; | |
3092 | else | |
3093 | gcc_unreachable (); | |
3094 | ||
3095 | return src - dest; | |
3096 | } | |
3097 | ||
3098 | /* Implement RETURN_ADDR_RTX. We do not support moving back to a | |
3099 | previous frame. */ | |
3100 | ||
3101 | rtx | |
3102 | riscv_return_addr (int count, rtx frame ATTRIBUTE_UNUSED) | |
3103 | { | |
3104 | if (count != 0) | |
3105 | return const0_rtx; | |
3106 | ||
3107 | return get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM); | |
3108 | } | |
3109 | ||
3110 | /* Emit code to change the current function's return address to | |
3111 | ADDRESS. SCRATCH is available as a scratch register, if needed. | |
3112 | ADDRESS and SCRATCH are both word-mode GPRs. */ | |
3113 | ||
3114 | void | |
3115 | riscv_set_return_address (rtx address, rtx scratch) | |
3116 | { | |
3117 | rtx slot_address; | |
3118 | ||
3119 | gcc_assert (BITSET_P (cfun->machine->frame.mask, RETURN_ADDR_REGNUM)); | |
3120 | slot_address = riscv_add_offset (scratch, stack_pointer_rtx, | |
3121 | cfun->machine->frame.gp_sp_offset); | |
3122 | riscv_emit_move (gen_frame_mem (GET_MODE (address), slot_address), address); | |
3123 | } | |
3124 | ||
3125 | /* A function to save or store a register. The first argument is the | |
3126 | register and the second is the stack slot. */ | |
3127 | typedef void (*riscv_save_restore_fn) (rtx, rtx); | |
3128 | ||
3129 | /* Use FN to save or restore register REGNO. MODE is the register's | |
3130 | mode and OFFSET is the offset of its save slot from the current | |
3131 | stack pointer. */ | |
3132 | ||
3133 | static void | |
b8506a8a | 3134 | riscv_save_restore_reg (machine_mode mode, int regno, |
09cae750 PD |
3135 | HOST_WIDE_INT offset, riscv_save_restore_fn fn) |
3136 | { | |
3137 | rtx mem; | |
3138 | ||
3139 | mem = gen_frame_mem (mode, plus_constant (Pmode, stack_pointer_rtx, offset)); | |
3140 | fn (gen_rtx_REG (mode, regno), mem); | |
3141 | } | |
3142 | ||
3143 | /* Call FN for each register that is saved by the current function. | |
3144 | SP_OFFSET is the offset of the current stack pointer from the start | |
3145 | of the frame. */ | |
3146 | ||
3147 | static void | |
3148 | riscv_for_each_saved_reg (HOST_WIDE_INT sp_offset, riscv_save_restore_fn fn) | |
3149 | { | |
3150 | HOST_WIDE_INT offset; | |
3151 | ||
3152 | /* Save the link register and s-registers. */ | |
3153 | offset = cfun->machine->frame.gp_sp_offset - sp_offset; | |
3154 | for (int regno = GP_REG_FIRST; regno <= GP_REG_LAST-1; regno++) | |
3155 | if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST)) | |
3156 | { | |
3157 | riscv_save_restore_reg (word_mode, regno, offset, fn); | |
3158 | offset -= UNITS_PER_WORD; | |
3159 | } | |
3160 | ||
3161 | /* This loop must iterate over the same space as its companion in | |
3162 | riscv_compute_frame_info. */ | |
3163 | offset = cfun->machine->frame.fp_sp_offset - sp_offset; | |
3164 | for (int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) | |
3165 | if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST)) | |
3166 | { | |
b8506a8a | 3167 | machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode; |
09cae750 PD |
3168 | |
3169 | riscv_save_restore_reg (mode, regno, offset, fn); | |
3170 | offset -= GET_MODE_SIZE (mode); | |
3171 | } | |
3172 | } | |
3173 | ||
3174 | /* Save register REG to MEM. Make the instruction frame-related. */ | |
3175 | ||
3176 | static void | |
3177 | riscv_save_reg (rtx reg, rtx mem) | |
3178 | { | |
3179 | riscv_emit_move (mem, reg); | |
3180 | riscv_set_frame_expr (riscv_frame_set (mem, reg)); | |
3181 | } | |
3182 | ||
3183 | /* Restore register REG from MEM. */ | |
3184 | ||
3185 | static void | |
3186 | riscv_restore_reg (rtx reg, rtx mem) | |
3187 | { | |
3188 | rtx insn = riscv_emit_move (reg, mem); | |
3189 | rtx dwarf = NULL_RTX; | |
3190 | dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf); | |
3191 | REG_NOTES (insn) = dwarf; | |
3192 | ||
3193 | RTX_FRAME_RELATED_P (insn) = 1; | |
3194 | } | |
3195 | ||
3196 | /* Return the code to invoke the GPR save routine. */ | |
3197 | ||
3198 | const char * | |
3199 | riscv_output_gpr_save (unsigned mask) | |
3200 | { | |
3201 | static char s[32]; | |
3202 | unsigned n = riscv_save_libcall_count (mask); | |
3203 | ||
3204 | ssize_t bytes = snprintf (s, sizeof (s), "call\tt0,__riscv_save_%u", n); | |
3205 | gcc_assert ((size_t) bytes < sizeof (s)); | |
3206 | ||
3207 | return s; | |
3208 | } | |
3209 | ||
3210 | /* For stack frames that can't be allocated with a single ADDI instruction, | |
3211 | compute the best value to initially allocate. It must at a minimum | |
3212 | allocate enough space to spill the callee-saved registers. */ | |
3213 | ||
3214 | static HOST_WIDE_INT | |
3215 | riscv_first_stack_step (struct riscv_frame_info *frame) | |
3216 | { | |
3217 | HOST_WIDE_INT min_first_step = frame->total_size - frame->fp_sp_offset; | |
3218 | HOST_WIDE_INT max_first_step = IMM_REACH / 2 - STACK_BOUNDARY / 8; | |
3219 | ||
3220 | if (SMALL_OPERAND (frame->total_size)) | |
3221 | return frame->total_size; | |
3222 | ||
3223 | /* As an optimization, use the least-significant bits of the total frame | |
3224 | size, so that the second adjustment step is just LUI + ADD. */ | |
3225 | if (!SMALL_OPERAND (frame->total_size - max_first_step) | |
3226 | && frame->total_size % IMM_REACH < IMM_REACH / 2 | |
3227 | && frame->total_size % IMM_REACH >= min_first_step) | |
3228 | return frame->total_size % IMM_REACH; | |
3229 | ||
3230 | gcc_assert (min_first_step <= max_first_step); | |
3231 | return max_first_step; | |
3232 | } | |
3233 | ||
3234 | static rtx | |
3235 | riscv_adjust_libcall_cfi_prologue () | |
3236 | { | |
3237 | rtx dwarf = NULL_RTX; | |
3238 | rtx adjust_sp_rtx, reg, mem, insn; | |
3239 | int saved_size = cfun->machine->frame.save_libcall_adjustment; | |
3240 | int offset; | |
3241 | ||
3242 | for (int regno = GP_REG_FIRST; regno <= GP_REG_LAST-1; regno++) | |
3243 | if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST)) | |
3244 | { | |
3245 | /* The save order is ra, s0, s1, s2 to s11. */ | |
3246 | if (regno == RETURN_ADDR_REGNUM) | |
3247 | offset = saved_size - UNITS_PER_WORD; | |
3248 | else if (regno == S0_REGNUM) | |
3249 | offset = saved_size - UNITS_PER_WORD * 2; | |
3250 | else if (regno == S1_REGNUM) | |
3251 | offset = saved_size - UNITS_PER_WORD * 3; | |
3252 | else | |
3253 | offset = saved_size - ((regno - S2_REGNUM + 4) * UNITS_PER_WORD); | |
3254 | ||
3255 | reg = gen_rtx_REG (SImode, regno); | |
3256 | mem = gen_frame_mem (SImode, plus_constant (Pmode, | |
3257 | stack_pointer_rtx, | |
3258 | offset)); | |
3259 | ||
3260 | insn = gen_rtx_SET (mem, reg); | |
3261 | dwarf = alloc_reg_note (REG_CFA_OFFSET, insn, dwarf); | |
3262 | } | |
3263 | ||
3264 | /* Debug info for adjust sp. */ | |
3265 | adjust_sp_rtx = gen_add3_insn (stack_pointer_rtx, | |
3266 | stack_pointer_rtx, GEN_INT (-saved_size)); | |
3267 | dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, adjust_sp_rtx, | |
3268 | dwarf); | |
3269 | return dwarf; | |
3270 | } | |
3271 | ||
3272 | static void | |
3273 | riscv_emit_stack_tie (void) | |
3274 | { | |
3275 | if (Pmode == SImode) | |
3276 | emit_insn (gen_stack_tiesi (stack_pointer_rtx, hard_frame_pointer_rtx)); | |
3277 | else | |
3278 | emit_insn (gen_stack_tiedi (stack_pointer_rtx, hard_frame_pointer_rtx)); | |
3279 | } | |
3280 | ||
3281 | /* Expand the "prologue" pattern. */ | |
3282 | ||
3283 | void | |
3284 | riscv_expand_prologue (void) | |
3285 | { | |
3286 | struct riscv_frame_info *frame = &cfun->machine->frame; | |
3287 | HOST_WIDE_INT size = frame->total_size; | |
3288 | unsigned mask = frame->mask; | |
3289 | rtx insn; | |
3290 | ||
3291 | if (flag_stack_usage_info) | |
3292 | current_function_static_stack_size = size; | |
3293 | ||
3294 | /* When optimizing for size, call a subroutine to save the registers. */ | |
3295 | if (riscv_use_save_libcall (frame)) | |
3296 | { | |
3297 | rtx dwarf = NULL_RTX; | |
3298 | dwarf = riscv_adjust_libcall_cfi_prologue (); | |
3299 | ||
3300 | frame->mask = 0; /* Temporarily fib that we need not save GPRs. */ | |
3301 | size -= frame->save_libcall_adjustment; | |
3302 | insn = emit_insn (gen_gpr_save (GEN_INT (mask))); | |
3303 | ||
3304 | RTX_FRAME_RELATED_P (insn) = 1; | |
3305 | REG_NOTES (insn) = dwarf; | |
3306 | } | |
3307 | ||
3308 | /* Save the registers. */ | |
3309 | if ((frame->mask | frame->fmask) != 0) | |
3310 | { | |
3311 | HOST_WIDE_INT step1 = MIN (size, riscv_first_stack_step (frame)); | |
3312 | ||
3313 | insn = gen_add3_insn (stack_pointer_rtx, | |
3314 | stack_pointer_rtx, | |
3315 | GEN_INT (-step1)); | |
3316 | RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; | |
3317 | size -= step1; | |
3318 | riscv_for_each_saved_reg (size, riscv_save_reg); | |
3319 | } | |
3320 | ||
3321 | frame->mask = mask; /* Undo the above fib. */ | |
3322 | ||
3323 | /* Set up the frame pointer, if we're using one. */ | |
3324 | if (frame_pointer_needed) | |
3325 | { | |
3326 | insn = gen_add3_insn (hard_frame_pointer_rtx, stack_pointer_rtx, | |
3327 | GEN_INT (frame->hard_frame_pointer_offset - size)); | |
3328 | RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; | |
3329 | ||
3330 | riscv_emit_stack_tie (); | |
3331 | } | |
3332 | ||
3333 | /* Allocate the rest of the frame. */ | |
3334 | if (size > 0) | |
3335 | { | |
3336 | if (SMALL_OPERAND (-size)) | |
3337 | { | |
3338 | insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, | |
3339 | GEN_INT (-size)); | |
3340 | RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; | |
3341 | } | |
3342 | else | |
3343 | { | |
3344 | riscv_emit_move (RISCV_PROLOGUE_TEMP (Pmode), GEN_INT (-size)); | |
3345 | emit_insn (gen_add3_insn (stack_pointer_rtx, | |
3346 | stack_pointer_rtx, | |
3347 | RISCV_PROLOGUE_TEMP (Pmode))); | |
3348 | ||
3349 | /* Describe the effect of the previous instructions. */ | |
3350 | insn = plus_constant (Pmode, stack_pointer_rtx, -size); | |
3351 | insn = gen_rtx_SET (stack_pointer_rtx, insn); | |
3352 | riscv_set_frame_expr (insn); | |
3353 | } | |
3354 | } | |
3355 | } | |
3356 | ||
3357 | static rtx | |
3358 | riscv_adjust_libcall_cfi_epilogue () | |
3359 | { | |
3360 | rtx dwarf = NULL_RTX; | |
3361 | rtx adjust_sp_rtx, reg; | |
3362 | int saved_size = cfun->machine->frame.save_libcall_adjustment; | |
3363 | ||
3364 | /* Debug info for adjust sp. */ | |
3365 | adjust_sp_rtx = gen_add3_insn (stack_pointer_rtx, | |
3366 | stack_pointer_rtx, GEN_INT (saved_size)); | |
3367 | dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, adjust_sp_rtx, | |
3368 | dwarf); | |
3369 | ||
3370 | for (int regno = GP_REG_FIRST; regno <= GP_REG_LAST-1; regno++) | |
3371 | if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST)) | |
3372 | { | |
3373 | reg = gen_rtx_REG (SImode, regno); | |
3374 | dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf); | |
3375 | } | |
3376 | ||
3377 | return dwarf; | |
3378 | } | |
3379 | ||
3380 | /* Expand an "epilogue" or "sibcall_epilogue" pattern; SIBCALL_P | |
3381 | says which. */ | |
3382 | ||
3383 | void | |
3384 | riscv_expand_epilogue (bool sibcall_p) | |
3385 | { | |
3386 | /* Split the frame into two. STEP1 is the amount of stack we should | |
3387 | deallocate before restoring the registers. STEP2 is the amount we | |
3388 | should deallocate afterwards. | |
3389 | ||
3390 | Start off by assuming that no registers need to be restored. */ | |
3391 | struct riscv_frame_info *frame = &cfun->machine->frame; | |
3392 | unsigned mask = frame->mask; | |
3393 | HOST_WIDE_INT step1 = frame->total_size; | |
3394 | HOST_WIDE_INT step2 = 0; | |
3395 | bool use_restore_libcall = !sibcall_p && riscv_use_save_libcall (frame); | |
3396 | rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM); | |
3397 | rtx insn; | |
3398 | ||
3399 | /* We need to add memory barrier to prevent read from deallocated stack. */ | |
3400 | bool need_barrier_p = (get_frame_size () | |
3401 | + cfun->machine->frame.arg_pointer_offset) != 0; | |
3402 | ||
3403 | if (!sibcall_p && riscv_can_use_return_insn ()) | |
3404 | { | |
3405 | emit_jump_insn (gen_return ()); | |
3406 | return; | |
3407 | } | |
3408 | ||
3409 | /* Move past any dynamic stack allocations. */ | |
3410 | if (cfun->calls_alloca) | |
3411 | { | |
3412 | /* Emit a barrier to prevent loads from a deallocated stack. */ | |
3413 | riscv_emit_stack_tie (); | |
3414 | need_barrier_p = false; | |
3415 | ||
3416 | rtx adjust = GEN_INT (-frame->hard_frame_pointer_offset); | |
3417 | if (!SMALL_OPERAND (INTVAL (adjust))) | |
3418 | { | |
3419 | riscv_emit_move (RISCV_PROLOGUE_TEMP (Pmode), adjust); | |
3420 | adjust = RISCV_PROLOGUE_TEMP (Pmode); | |
3421 | } | |
3422 | ||
3423 | insn = emit_insn ( | |
3424 | gen_add3_insn (stack_pointer_rtx, hard_frame_pointer_rtx, | |
3425 | adjust)); | |
3426 | ||
3427 | rtx dwarf = NULL_RTX; | |
3428 | rtx cfa_adjust_value = gen_rtx_PLUS ( | |
3429 | Pmode, hard_frame_pointer_rtx, | |
3430 | GEN_INT (-frame->hard_frame_pointer_offset)); | |
3431 | rtx cfa_adjust_rtx = gen_rtx_SET (stack_pointer_rtx, cfa_adjust_value); | |
3432 | dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, cfa_adjust_rtx, dwarf); | |
3433 | RTX_FRAME_RELATED_P (insn) = 1; | |
3434 | ||
3435 | REG_NOTES (insn) = dwarf; | |
3436 | } | |
3437 | ||
3438 | /* If we need to restore registers, deallocate as much stack as | |
3439 | possible in the second step without going out of range. */ | |
3440 | if ((frame->mask | frame->fmask) != 0) | |
3441 | { | |
3442 | step2 = riscv_first_stack_step (frame); | |
3443 | step1 -= step2; | |
3444 | } | |
3445 | ||
3446 | /* Set TARGET to BASE + STEP1. */ | |
3447 | if (step1 > 0) | |
3448 | { | |
3449 | /* Emit a barrier to prevent loads from a deallocated stack. */ | |
3450 | riscv_emit_stack_tie (); | |
3451 | need_barrier_p = false; | |
3452 | ||
3453 | /* Get an rtx for STEP1 that we can add to BASE. */ | |
3454 | rtx adjust = GEN_INT (step1); | |
3455 | if (!SMALL_OPERAND (step1)) | |
3456 | { | |
3457 | riscv_emit_move (RISCV_PROLOGUE_TEMP (Pmode), adjust); | |
3458 | adjust = RISCV_PROLOGUE_TEMP (Pmode); | |
3459 | } | |
3460 | ||
3461 | insn = emit_insn ( | |
3462 | gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, adjust)); | |
3463 | ||
3464 | rtx dwarf = NULL_RTX; | |
3465 | rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx, | |
3466 | GEN_INT (step2)); | |
3467 | ||
3468 | dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf); | |
3469 | RTX_FRAME_RELATED_P (insn) = 1; | |
3470 | ||
3471 | REG_NOTES (insn) = dwarf; | |
3472 | } | |
3473 | ||
3474 | if (use_restore_libcall) | |
3475 | frame->mask = 0; /* Temporarily fib that we need not save GPRs. */ | |
3476 | ||
3477 | /* Restore the registers. */ | |
3478 | riscv_for_each_saved_reg (frame->total_size - step2, riscv_restore_reg); | |
3479 | ||
3480 | if (use_restore_libcall) | |
3481 | { | |
3482 | frame->mask = mask; /* Undo the above fib. */ | |
3483 | gcc_assert (step2 >= frame->save_libcall_adjustment); | |
3484 | step2 -= frame->save_libcall_adjustment; | |
3485 | } | |
3486 | ||
3487 | if (need_barrier_p) | |
3488 | riscv_emit_stack_tie (); | |
3489 | ||
3490 | /* Deallocate the final bit of the frame. */ | |
3491 | if (step2 > 0) | |
3492 | { | |
3493 | insn = emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, | |
3494 | GEN_INT (step2))); | |
3495 | ||
3496 | rtx dwarf = NULL_RTX; | |
3497 | rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx, | |
3498 | const0_rtx); | |
3499 | dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf); | |
3500 | RTX_FRAME_RELATED_P (insn) = 1; | |
3501 | ||
3502 | REG_NOTES (insn) = dwarf; | |
3503 | } | |
3504 | ||
3505 | if (use_restore_libcall) | |
3506 | { | |
3507 | rtx dwarf = riscv_adjust_libcall_cfi_epilogue (); | |
3508 | insn = emit_insn (gen_gpr_restore (GEN_INT (riscv_save_libcall_count (mask)))); | |
3509 | RTX_FRAME_RELATED_P (insn) = 1; | |
3510 | REG_NOTES (insn) = dwarf; | |
3511 | ||
3512 | emit_jump_insn (gen_gpr_restore_return (ra)); | |
3513 | return; | |
3514 | } | |
3515 | ||
3516 | /* Add in the __builtin_eh_return stack adjustment. */ | |
3517 | if (crtl->calls_eh_return) | |
3518 | emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, | |
3519 | EH_RETURN_STACKADJ_RTX)); | |
3520 | ||
3521 | if (!sibcall_p) | |
3522 | emit_jump_insn (gen_simple_return_internal (ra)); | |
3523 | } | |
3524 | ||
3525 | /* Return nonzero if this function is known to have a null epilogue. | |
3526 | This allows the optimizer to omit jumps to jumps if no stack | |
3527 | was created. */ | |
3528 | ||
3529 | bool | |
3530 | riscv_can_use_return_insn (void) | |
3531 | { | |
3532 | return reload_completed && cfun->machine->frame.total_size == 0; | |
3533 | } | |
3534 | ||
f15643d4 RS |
3535 | /* Implement TARGET_SECONDARY_MEMORY_NEEDED. |
3536 | ||
3537 | When floating-point registers are wider than integer ones, moves between | |
3538 | them must go through memory. */ | |
3539 | ||
3540 | static bool | |
3541 | riscv_secondary_memory_needed (machine_mode mode, reg_class_t class1, | |
3542 | reg_class_t class2) | |
3543 | { | |
3544 | return (GET_MODE_SIZE (mode) > UNITS_PER_WORD | |
3545 | && (class1 == FP_REGS) != (class2 == FP_REGS)); | |
3546 | } | |
3547 | ||
09cae750 PD |
3548 | /* Implement TARGET_REGISTER_MOVE_COST. */ |
3549 | ||
3550 | static int | |
b8506a8a | 3551 | riscv_register_move_cost (machine_mode mode, |
09cae750 PD |
3552 | reg_class_t from, reg_class_t to) |
3553 | { | |
f15643d4 | 3554 | return riscv_secondary_memory_needed (mode, from, to) ? 8 : 2; |
09cae750 PD |
3555 | } |
3556 | ||
c43f4279 RS |
3557 | /* Implement TARGET_HARD_REGNO_NREGS. */ |
3558 | ||
3559 | static unsigned int | |
3560 | riscv_hard_regno_nregs (unsigned int regno, machine_mode mode) | |
3561 | { | |
3562 | if (FP_REG_P (regno)) | |
3563 | return (GET_MODE_SIZE (mode) + UNITS_PER_FP_REG - 1) / UNITS_PER_FP_REG; | |
3564 | ||
3565 | /* All other registers are word-sized. */ | |
3566 | return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; | |
3567 | } | |
3568 | ||
f939c3e6 | 3569 | /* Implement TARGET_HARD_REGNO_MODE_OK. */ |
09cae750 | 3570 | |
f939c3e6 RS |
3571 | static bool |
3572 | riscv_hard_regno_mode_ok (unsigned int regno, machine_mode mode) | |
09cae750 PD |
3573 | { |
3574 | unsigned int nregs = riscv_hard_regno_nregs (regno, mode); | |
3575 | ||
3576 | if (GP_REG_P (regno)) | |
3577 | { | |
3578 | if (!GP_REG_P (regno + nregs - 1)) | |
3579 | return false; | |
3580 | } | |
3581 | else if (FP_REG_P (regno)) | |
3582 | { | |
3583 | if (!FP_REG_P (regno + nregs - 1)) | |
3584 | return false; | |
3585 | ||
3586 | if (GET_MODE_CLASS (mode) != MODE_FLOAT | |
3587 | && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT) | |
3588 | return false; | |
3589 | ||
3590 | /* Only use callee-saved registers if a potential callee is guaranteed | |
3591 | to spill the requisite width. */ | |
3592 | if (GET_MODE_UNIT_SIZE (mode) > UNITS_PER_FP_REG | |
3593 | || (!call_used_regs[regno] | |
3594 | && GET_MODE_UNIT_SIZE (mode) > UNITS_PER_FP_ARG)) | |
3595 | return false; | |
3596 | } | |
3597 | else | |
3598 | return false; | |
3599 | ||
3600 | /* Require same callee-savedness for all registers. */ | |
3601 | for (unsigned i = 1; i < nregs; i++) | |
3602 | if (call_used_regs[regno] != call_used_regs[regno + i]) | |
3603 | return false; | |
3604 | ||
3605 | return true; | |
3606 | } | |
3607 | ||
99e1629f RS |
3608 | /* Implement TARGET_MODES_TIEABLE_P. |
3609 | ||
3610 | Don't allow floating-point modes to be tied, since type punning of | |
3611 | single-precision and double-precision is implementation defined. */ | |
3612 | ||
3613 | static bool | |
3614 | riscv_modes_tieable_p (machine_mode mode1, machine_mode mode2) | |
3615 | { | |
3616 | return (mode1 == mode2 | |
3617 | || !(GET_MODE_CLASS (mode1) == MODE_FLOAT | |
3618 | && GET_MODE_CLASS (mode2) == MODE_FLOAT)); | |
3619 | } | |
3620 | ||
09cae750 PD |
3621 | /* Implement CLASS_MAX_NREGS. */ |
3622 | ||
3623 | static unsigned char | |
b8506a8a | 3624 | riscv_class_max_nregs (reg_class_t rclass, machine_mode mode) |
09cae750 PD |
3625 | { |
3626 | if (reg_class_subset_p (FP_REGS, rclass)) | |
3627 | return riscv_hard_regno_nregs (FP_REG_FIRST, mode); | |
3628 | ||
3629 | if (reg_class_subset_p (GR_REGS, rclass)) | |
3630 | return riscv_hard_regno_nregs (GP_REG_FIRST, mode); | |
3631 | ||
3632 | return 0; | |
3633 | } | |
3634 | ||
09cae750 PD |
3635 | /* Implement TARGET_MEMORY_MOVE_COST. */ |
3636 | ||
3637 | static int | |
b8506a8a | 3638 | riscv_memory_move_cost (machine_mode mode, reg_class_t rclass, bool in) |
09cae750 PD |
3639 | { |
3640 | return (tune_info->memory_cost | |
3641 | + memory_move_secondary_cost (mode, rclass, in)); | |
3642 | } | |
3643 | ||
3644 | /* Return the number of instructions that can be issued per cycle. */ | |
3645 | ||
3646 | static int | |
3647 | riscv_issue_rate (void) | |
3648 | { | |
3649 | return tune_info->issue_rate; | |
3650 | } | |
3651 | ||
3652 | /* Implement TARGET_ASM_FILE_START. */ | |
3653 | ||
3654 | static void | |
3655 | riscv_file_start (void) | |
3656 | { | |
3657 | default_file_start (); | |
3658 | ||
3659 | /* Instruct GAS to generate position-[in]dependent code. */ | |
3660 | fprintf (asm_out_file, "\t.option %spic\n", (flag_pic ? "" : "no")); | |
3661 | } | |
3662 | ||
3663 | /* Implement TARGET_ASM_OUTPUT_MI_THUNK. Generate rtl rather than asm text | |
3664 | in order to avoid duplicating too much logic from elsewhere. */ | |
3665 | ||
3666 | static void | |
3667 | riscv_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, | |
3668 | HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset, | |
3669 | tree function) | |
3670 | { | |
3671 | rtx this_rtx, temp1, temp2, fnaddr; | |
3672 | rtx_insn *insn; | |
3673 | ||
3674 | /* Pretend to be a post-reload pass while generating rtl. */ | |
3675 | reload_completed = 1; | |
3676 | ||
3677 | /* Mark the end of the (empty) prologue. */ | |
3678 | emit_note (NOTE_INSN_PROLOGUE_END); | |
3679 | ||
3680 | /* Determine if we can use a sibcall to call FUNCTION directly. */ | |
3681 | fnaddr = gen_rtx_MEM (FUNCTION_MODE, XEXP (DECL_RTL (function), 0)); | |
3682 | ||
3683 | /* We need two temporary registers in some cases. */ | |
3684 | temp1 = gen_rtx_REG (Pmode, RISCV_PROLOGUE_TEMP_REGNUM); | |
3685 | temp2 = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM); | |
3686 | ||
3687 | /* Find out which register contains the "this" pointer. */ | |
3688 | if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)) | |
3689 | this_rtx = gen_rtx_REG (Pmode, GP_ARG_FIRST + 1); | |
3690 | else | |
3691 | this_rtx = gen_rtx_REG (Pmode, GP_ARG_FIRST); | |
3692 | ||
3693 | /* Add DELTA to THIS_RTX. */ | |
3694 | if (delta != 0) | |
3695 | { | |
3696 | rtx offset = GEN_INT (delta); | |
3697 | if (!SMALL_OPERAND (delta)) | |
3698 | { | |
3699 | riscv_emit_move (temp1, offset); | |
3700 | offset = temp1; | |
3701 | } | |
3702 | emit_insn (gen_add3_insn (this_rtx, this_rtx, offset)); | |
3703 | } | |
3704 | ||
3705 | /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX. */ | |
3706 | if (vcall_offset != 0) | |
3707 | { | |
3708 | rtx addr; | |
3709 | ||
3710 | /* Set TEMP1 to *THIS_RTX. */ | |
3711 | riscv_emit_move (temp1, gen_rtx_MEM (Pmode, this_rtx)); | |
3712 | ||
3713 | /* Set ADDR to a legitimate address for *THIS_RTX + VCALL_OFFSET. */ | |
3714 | addr = riscv_add_offset (temp2, temp1, vcall_offset); | |
3715 | ||
3716 | /* Load the offset and add it to THIS_RTX. */ | |
3717 | riscv_emit_move (temp1, gen_rtx_MEM (Pmode, addr)); | |
3718 | emit_insn (gen_add3_insn (this_rtx, this_rtx, temp1)); | |
3719 | } | |
3720 | ||
3721 | /* Jump to the target function. */ | |
3722 | insn = emit_call_insn (gen_sibcall (fnaddr, const0_rtx, NULL, const0_rtx)); | |
3723 | SIBLING_CALL_P (insn) = 1; | |
3724 | ||
3725 | /* Run just enough of rest_of_compilation. This sequence was | |
3726 | "borrowed" from alpha.c. */ | |
3727 | insn = get_insns (); | |
3728 | split_all_insns_noflow (); | |
3729 | shorten_branches (insn); | |
3730 | final_start_function (insn, file, 1); | |
3731 | final (insn, file, 1); | |
3732 | final_end_function (); | |
3733 | ||
3734 | /* Clean up the vars set above. Note that final_end_function resets | |
3735 | the global pointer for us. */ | |
3736 | reload_completed = 0; | |
3737 | } | |
3738 | ||
3739 | /* Allocate a chunk of memory for per-function machine-dependent data. */ | |
3740 | ||
3741 | static struct machine_function * | |
3742 | riscv_init_machine_status (void) | |
3743 | { | |
3744 | return ggc_cleared_alloc<machine_function> (); | |
3745 | } | |
3746 | ||
3747 | /* Implement TARGET_OPTION_OVERRIDE. */ | |
3748 | ||
3749 | static void | |
3750 | riscv_option_override (void) | |
3751 | { | |
3752 | const struct riscv_cpu_info *cpu; | |
3753 | ||
3754 | #ifdef SUBTARGET_OVERRIDE_OPTIONS | |
3755 | SUBTARGET_OVERRIDE_OPTIONS; | |
3756 | #endif | |
3757 | ||
3758 | flag_pcc_struct_return = 0; | |
3759 | ||
3760 | if (flag_pic) | |
3761 | g_switch_value = 0; | |
3762 | ||
3763 | /* The presence of the M extension implies that division instructions | |
3764 | are present, so include them unless explicitly disabled. */ | |
3765 | if (TARGET_MUL && (target_flags_explicit & MASK_DIV) == 0) | |
3766 | target_flags |= MASK_DIV; | |
3767 | else if (!TARGET_MUL && TARGET_DIV) | |
3768 | error ("-mdiv requires -march to subsume the %<M%> extension"); | |
3769 | ||
3770 | /* Likewise floating-point division and square root. */ | |
3771 | if (TARGET_HARD_FLOAT && (target_flags_explicit & MASK_FDIV) == 0) | |
3772 | target_flags |= MASK_FDIV; | |
3773 | ||
3774 | /* Handle -mtune. */ | |
3775 | cpu = riscv_parse_cpu (riscv_tune_string ? riscv_tune_string : | |
3776 | RISCV_TUNE_STRING_DEFAULT); | |
3777 | tune_info = optimize_size ? &optimize_size_tune_info : cpu->tune_info; | |
3778 | ||
82285692 AW |
3779 | /* Use -mtune's setting for slow_unaligned_access, even when optimizing |
3780 | for size. For architectures that trap and emulate unaligned accesses, | |
caf1c1cd AW |
3781 | the performance cost is too great, even for -Os. Similarly, if |
3782 | -m[no-]strict-align is left unspecified, heed -mtune's advice. */ | |
e0bd6c9f RS |
3783 | riscv_slow_unaligned_access_p = (cpu->tune_info->slow_unaligned_access |
3784 | || TARGET_STRICT_ALIGN); | |
caf1c1cd AW |
3785 | if ((target_flags_explicit & MASK_STRICT_ALIGN) == 0 |
3786 | && cpu->tune_info->slow_unaligned_access) | |
3787 | target_flags |= MASK_STRICT_ALIGN; | |
82285692 | 3788 | |
09cae750 PD |
3789 | /* If the user hasn't specified a branch cost, use the processor's |
3790 | default. */ | |
3791 | if (riscv_branch_cost == 0) | |
3792 | riscv_branch_cost = tune_info->branch_cost; | |
3793 | ||
3794 | /* Function to allocate machine-dependent function status. */ | |
3795 | init_machine_status = &riscv_init_machine_status; | |
3796 | ||
3797 | if (flag_pic) | |
3798 | riscv_cmodel = CM_PIC; | |
3799 | ||
3800 | /* We get better code with explicit relocs for CM_MEDLOW, but | |
3801 | worse code for the others (for now). Pick the best default. */ | |
3802 | if ((target_flags_explicit & MASK_EXPLICIT_RELOCS) == 0) | |
3803 | if (riscv_cmodel == CM_MEDLOW) | |
3804 | target_flags |= MASK_EXPLICIT_RELOCS; | |
3805 | ||
3806 | /* Require that the ISA supports the requested floating-point ABI. */ | |
3807 | if (UNITS_PER_FP_ARG > (TARGET_HARD_FLOAT ? UNITS_PER_FP_REG : 0)) | |
3808 | error ("requested ABI requires -march to subsume the %qc extension", | |
3809 | UNITS_PER_FP_ARG > 8 ? 'Q' : (UNITS_PER_FP_ARG > 4 ? 'D' : 'F')); | |
3810 | ||
3811 | /* We do not yet support ILP32 on RV64. */ | |
3812 | if (BITS_PER_WORD != POINTER_SIZE) | |
3813 | error ("ABI requires -march=rv%d", POINTER_SIZE); | |
3814 | } | |
3815 | ||
3816 | /* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */ | |
3817 | ||
3818 | static void | |
3819 | riscv_conditional_register_usage (void) | |
3820 | { | |
3821 | if (!TARGET_HARD_FLOAT) | |
3822 | { | |
3823 | for (int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) | |
3824 | fixed_regs[regno] = call_used_regs[regno] = 1; | |
3825 | } | |
3826 | } | |
3827 | ||
3828 | /* Return a register priority for hard reg REGNO. */ | |
3829 | ||
3830 | static int | |
3831 | riscv_register_priority (int regno) | |
3832 | { | |
3833 | /* Favor x8-x15/f8-f15 to improve the odds of RVC instruction selection. */ | |
3834 | if (TARGET_RVC && (IN_RANGE (regno, GP_REG_FIRST + 8, GP_REG_FIRST + 15) | |
3835 | || IN_RANGE (regno, FP_REG_FIRST + 8, FP_REG_FIRST + 15))) | |
3836 | return 1; | |
3837 | ||
3838 | return 0; | |
3839 | } | |
3840 | ||
3841 | /* Implement TARGET_TRAMPOLINE_INIT. */ | |
3842 | ||
3843 | static void | |
3844 | riscv_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) | |
3845 | { | |
3846 | rtx addr, end_addr, mem; | |
3847 | uint32_t trampoline[4]; | |
3848 | unsigned int i; | |
3849 | HOST_WIDE_INT static_chain_offset, target_function_offset; | |
3850 | ||
3851 | /* Work out the offsets of the pointers from the start of the | |
3852 | trampoline code. */ | |
3853 | gcc_assert (ARRAY_SIZE (trampoline) * 4 == TRAMPOLINE_CODE_SIZE); | |
3854 | ||
3855 | /* Get pointers to the beginning and end of the code block. */ | |
3856 | addr = force_reg (Pmode, XEXP (m_tramp, 0)); | |
3857 | end_addr = riscv_force_binary (Pmode, PLUS, addr, | |
3858 | GEN_INT (TRAMPOLINE_CODE_SIZE)); | |
3859 | ||
3860 | ||
3861 | if (Pmode == SImode) | |
3862 | { | |
3863 | chain_value = force_reg (Pmode, chain_value); | |
3864 | ||
3865 | rtx target_function = force_reg (Pmode, XEXP (DECL_RTL (fndecl), 0)); | |
3866 | /* lui t2, hi(chain) | |
3867 | lui t1, hi(func) | |
3868 | addi t2, t2, lo(chain) | |
3869 | jr r1, lo(func) | |
3870 | */ | |
3871 | unsigned HOST_WIDE_INT lui_hi_chain_code, lui_hi_func_code; | |
3872 | unsigned HOST_WIDE_INT lo_chain_code, lo_func_code; | |
3873 | ||
3874 | rtx uimm_mask = force_reg (SImode, gen_int_mode (-IMM_REACH, SImode)); | |
3875 | ||
3876 | /* 0xfff. */ | |
3877 | rtx imm12_mask = gen_reg_rtx (SImode); | |
3878 | emit_insn (gen_one_cmplsi2 (imm12_mask, uimm_mask)); | |
3879 | ||
3880 | rtx fixup_value = force_reg (SImode, gen_int_mode (IMM_REACH/2, SImode)); | |
3881 | ||
3882 | /* Gen lui t2, hi(chain). */ | |
3883 | rtx hi_chain = riscv_force_binary (SImode, PLUS, chain_value, | |
3884 | fixup_value); | |
3885 | hi_chain = riscv_force_binary (SImode, AND, hi_chain, | |
3886 | uimm_mask); | |
3887 | lui_hi_chain_code = OPCODE_LUI | (STATIC_CHAIN_REGNUM << SHIFT_RD); | |
3888 | rtx lui_hi_chain = riscv_force_binary (SImode, IOR, hi_chain, | |
3889 | gen_int_mode (lui_hi_chain_code, SImode)); | |
3890 | ||
3891 | mem = adjust_address (m_tramp, SImode, 0); | |
3892 | riscv_emit_move (mem, lui_hi_chain); | |
3893 | ||
3894 | /* Gen lui t1, hi(func). */ | |
3895 | rtx hi_func = riscv_force_binary (SImode, PLUS, target_function, | |
3896 | fixup_value); | |
3897 | hi_func = riscv_force_binary (SImode, AND, hi_func, | |
3898 | uimm_mask); | |
3899 | lui_hi_func_code = OPCODE_LUI | (RISCV_PROLOGUE_TEMP_REGNUM << SHIFT_RD); | |
3900 | rtx lui_hi_func = riscv_force_binary (SImode, IOR, hi_func, | |
3901 | gen_int_mode (lui_hi_func_code, SImode)); | |
3902 | ||
3903 | mem = adjust_address (m_tramp, SImode, 1 * GET_MODE_SIZE (SImode)); | |
3904 | riscv_emit_move (mem, lui_hi_func); | |
3905 | ||
3906 | /* Gen addi t2, t2, lo(chain). */ | |
3907 | rtx lo_chain = riscv_force_binary (SImode, AND, chain_value, | |
3908 | imm12_mask); | |
3909 | lo_chain = riscv_force_binary (SImode, ASHIFT, lo_chain, GEN_INT (20)); | |
3910 | ||
3911 | lo_chain_code = OPCODE_ADDI | |
3912 | | (STATIC_CHAIN_REGNUM << SHIFT_RD) | |
3913 | | (STATIC_CHAIN_REGNUM << SHIFT_RS1); | |
3914 | ||
3915 | rtx addi_lo_chain = riscv_force_binary (SImode, IOR, lo_chain, | |
3916 | force_reg (SImode, GEN_INT (lo_chain_code))); | |
3917 | ||
3918 | mem = adjust_address (m_tramp, SImode, 2 * GET_MODE_SIZE (SImode)); | |
3919 | riscv_emit_move (mem, addi_lo_chain); | |
3920 | ||
3921 | /* Gen jr r1, lo(func). */ | |
3922 | rtx lo_func = riscv_force_binary (SImode, AND, target_function, | |
3923 | imm12_mask); | |
3924 | lo_func = riscv_force_binary (SImode, ASHIFT, lo_func, GEN_INT (20)); | |
3925 | ||
3926 | lo_func_code = OPCODE_JALR | (RISCV_PROLOGUE_TEMP_REGNUM << SHIFT_RS1); | |
3927 | ||
3928 | rtx jr_lo_func = riscv_force_binary (SImode, IOR, lo_func, | |
3929 | force_reg (SImode, GEN_INT (lo_func_code))); | |
3930 | ||
3931 | mem = adjust_address (m_tramp, SImode, 3 * GET_MODE_SIZE (SImode)); | |
3932 | riscv_emit_move (mem, jr_lo_func); | |
3933 | } | |
3934 | else | |
3935 | { | |
3936 | static_chain_offset = TRAMPOLINE_CODE_SIZE; | |
3937 | target_function_offset = static_chain_offset + GET_MODE_SIZE (ptr_mode); | |
3938 | ||
3939 | /* auipc t2, 0 | |
3940 | l[wd] t1, target_function_offset(t2) | |
3941 | l[wd] t2, static_chain_offset(t2) | |
3942 | jr t1 | |
3943 | */ | |
3944 | trampoline[0] = OPCODE_AUIPC | (STATIC_CHAIN_REGNUM << SHIFT_RD); | |
3945 | trampoline[1] = (Pmode == DImode ? OPCODE_LD : OPCODE_LW) | |
3946 | | (RISCV_PROLOGUE_TEMP_REGNUM << SHIFT_RD) | |
3947 | | (STATIC_CHAIN_REGNUM << SHIFT_RS1) | |
3948 | | (target_function_offset << SHIFT_IMM); | |
3949 | trampoline[2] = (Pmode == DImode ? OPCODE_LD : OPCODE_LW) | |
3950 | | (STATIC_CHAIN_REGNUM << SHIFT_RD) | |
3951 | | (STATIC_CHAIN_REGNUM << SHIFT_RS1) | |
3952 | | (static_chain_offset << SHIFT_IMM); | |
3953 | trampoline[3] = OPCODE_JALR | (RISCV_PROLOGUE_TEMP_REGNUM << SHIFT_RS1); | |
3954 | ||
3955 | /* Copy the trampoline code. */ | |
3956 | for (i = 0; i < ARRAY_SIZE (trampoline); i++) | |
3957 | { | |
3958 | mem = adjust_address (m_tramp, SImode, i * GET_MODE_SIZE (SImode)); | |
3959 | riscv_emit_move (mem, gen_int_mode (trampoline[i], SImode)); | |
3960 | } | |
3961 | ||
3962 | /* Set up the static chain pointer field. */ | |
3963 | mem = adjust_address (m_tramp, ptr_mode, static_chain_offset); | |
3964 | riscv_emit_move (mem, chain_value); | |
3965 | ||
3966 | /* Set up the target function field. */ | |
3967 | mem = adjust_address (m_tramp, ptr_mode, target_function_offset); | |
3968 | riscv_emit_move (mem, XEXP (DECL_RTL (fndecl), 0)); | |
3969 | } | |
3970 | ||
3971 | /* Flush the code part of the trampoline. */ | |
3972 | emit_insn (gen_add3_insn (end_addr, addr, GEN_INT (TRAMPOLINE_SIZE))); | |
3973 | emit_insn (gen_clear_cache (addr, end_addr)); | |
3974 | } | |
3975 | ||
3976 | /* Return leaf_function_p () and memoize the result. */ | |
3977 | ||
3978 | static bool | |
3979 | riscv_leaf_function_p (void) | |
3980 | { | |
3981 | if (cfun->machine->is_leaf == 0) | |
3982 | cfun->machine->is_leaf = leaf_function_p () ? 1 : -1; | |
3983 | ||
3984 | return cfun->machine->is_leaf > 0; | |
3985 | } | |
3986 | ||
3987 | /* Implement TARGET_FUNCTION_OK_FOR_SIBCALL. */ | |
3988 | ||
3989 | static bool | |
3990 | riscv_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED, | |
3991 | tree exp ATTRIBUTE_UNUSED) | |
3992 | { | |
3993 | /* When optimzing for size, don't use sibcalls in non-leaf routines */ | |
3994 | if (TARGET_SAVE_RESTORE) | |
3995 | return riscv_leaf_function_p (); | |
3996 | ||
3997 | return true; | |
3998 | } | |
3999 | ||
4000 | /* Implement TARGET_CANNOT_COPY_INSN_P. */ | |
4001 | ||
4002 | static bool | |
4003 | riscv_cannot_copy_insn_p (rtx_insn *insn) | |
4004 | { | |
4005 | return recog_memoized (insn) >= 0 && get_attr_cannot_copy (insn); | |
4006 | } | |
4007 | ||
e0bd6c9f RS |
4008 | /* Implement TARGET_SLOW_UNALIGNED_ACCESS. */ |
4009 | ||
4010 | static bool | |
4011 | riscv_slow_unaligned_access (machine_mode, unsigned int) | |
4012 | { | |
4013 | return riscv_slow_unaligned_access_p; | |
4014 | } | |
4015 | ||
0d803030 RS |
4016 | /* Implement TARGET_CAN_CHANGE_MODE_CLASS. */ |
4017 | ||
4018 | static bool | |
4019 | riscv_can_change_mode_class (machine_mode, machine_mode, reg_class_t rclass) | |
4020 | { | |
4021 | return !reg_classes_intersect_p (FP_REGS, rclass); | |
4022 | } | |
4023 | ||
58e17cf8 RS |
4024 | |
4025 | /* Implement TARGET_CONSTANT_ALIGNMENT. */ | |
4026 | ||
4027 | static HOST_WIDE_INT | |
4028 | riscv_constant_alignment (const_tree exp, HOST_WIDE_INT align) | |
4029 | { | |
4030 | if (TREE_CODE (exp) == STRING_CST || TREE_CODE (exp) == CONSTRUCTOR) | |
4031 | return MAX (align, BITS_PER_WORD); | |
4032 | return align; | |
4033 | } | |
4034 | ||
09cae750 PD |
4035 | /* Initialize the GCC target structure. */ |
4036 | #undef TARGET_ASM_ALIGNED_HI_OP | |
4037 | #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" | |
4038 | #undef TARGET_ASM_ALIGNED_SI_OP | |
4039 | #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t" | |
4040 | #undef TARGET_ASM_ALIGNED_DI_OP | |
4041 | #define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t" | |
4042 | ||
4043 | #undef TARGET_OPTION_OVERRIDE | |
4044 | #define TARGET_OPTION_OVERRIDE riscv_option_override | |
4045 | ||
4046 | #undef TARGET_LEGITIMIZE_ADDRESS | |
4047 | #define TARGET_LEGITIMIZE_ADDRESS riscv_legitimize_address | |
4048 | ||
4049 | #undef TARGET_SCHED_ISSUE_RATE | |
4050 | #define TARGET_SCHED_ISSUE_RATE riscv_issue_rate | |
4051 | ||
4052 | #undef TARGET_FUNCTION_OK_FOR_SIBCALL | |
4053 | #define TARGET_FUNCTION_OK_FOR_SIBCALL riscv_function_ok_for_sibcall | |
4054 | ||
4055 | #undef TARGET_REGISTER_MOVE_COST | |
4056 | #define TARGET_REGISTER_MOVE_COST riscv_register_move_cost | |
4057 | #undef TARGET_MEMORY_MOVE_COST | |
4058 | #define TARGET_MEMORY_MOVE_COST riscv_memory_move_cost | |
4059 | #undef TARGET_RTX_COSTS | |
4060 | #define TARGET_RTX_COSTS riscv_rtx_costs | |
4061 | #undef TARGET_ADDRESS_COST | |
4062 | #define TARGET_ADDRESS_COST riscv_address_cost | |
4063 | ||
09cae750 PD |
4064 | #undef TARGET_ASM_FILE_START |
4065 | #define TARGET_ASM_FILE_START riscv_file_start | |
4066 | #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE | |
4067 | #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true | |
4068 | ||
4069 | #undef TARGET_EXPAND_BUILTIN_VA_START | |
4070 | #define TARGET_EXPAND_BUILTIN_VA_START riscv_va_start | |
4071 | ||
4072 | #undef TARGET_PROMOTE_FUNCTION_MODE | |
4073 | #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote | |
4074 | ||
4075 | #undef TARGET_RETURN_IN_MEMORY | |
4076 | #define TARGET_RETURN_IN_MEMORY riscv_return_in_memory | |
4077 | ||
4078 | #undef TARGET_ASM_OUTPUT_MI_THUNK | |
4079 | #define TARGET_ASM_OUTPUT_MI_THUNK riscv_output_mi_thunk | |
4080 | #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK | |
4081 | #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true | |
4082 | ||
4083 | #undef TARGET_PRINT_OPERAND | |
4084 | #define TARGET_PRINT_OPERAND riscv_print_operand | |
4085 | #undef TARGET_PRINT_OPERAND_ADDRESS | |
4086 | #define TARGET_PRINT_OPERAND_ADDRESS riscv_print_operand_address | |
4087 | ||
4088 | #undef TARGET_SETUP_INCOMING_VARARGS | |
4089 | #define TARGET_SETUP_INCOMING_VARARGS riscv_setup_incoming_varargs | |
4090 | #undef TARGET_STRICT_ARGUMENT_NAMING | |
4091 | #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true | |
4092 | #undef TARGET_MUST_PASS_IN_STACK | |
4093 | #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size | |
4094 | #undef TARGET_PASS_BY_REFERENCE | |
4095 | #define TARGET_PASS_BY_REFERENCE riscv_pass_by_reference | |
4096 | #undef TARGET_ARG_PARTIAL_BYTES | |
4097 | #define TARGET_ARG_PARTIAL_BYTES riscv_arg_partial_bytes | |
4098 | #undef TARGET_FUNCTION_ARG | |
4099 | #define TARGET_FUNCTION_ARG riscv_function_arg | |
4100 | #undef TARGET_FUNCTION_ARG_ADVANCE | |
4101 | #define TARGET_FUNCTION_ARG_ADVANCE riscv_function_arg_advance | |
4102 | #undef TARGET_FUNCTION_ARG_BOUNDARY | |
4103 | #define TARGET_FUNCTION_ARG_BOUNDARY riscv_function_arg_boundary | |
4104 | ||
4105 | /* The generic ELF target does not always have TLS support. */ | |
4106 | #ifdef HAVE_AS_TLS | |
4107 | #undef TARGET_HAVE_TLS | |
4108 | #define TARGET_HAVE_TLS true | |
4109 | #endif | |
4110 | ||
4111 | #undef TARGET_CANNOT_FORCE_CONST_MEM | |
4112 | #define TARGET_CANNOT_FORCE_CONST_MEM riscv_cannot_force_const_mem | |
4113 | ||
4114 | #undef TARGET_LEGITIMATE_CONSTANT_P | |
4115 | #define TARGET_LEGITIMATE_CONSTANT_P riscv_legitimate_constant_p | |
4116 | ||
4117 | #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P | |
4118 | #define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_true | |
4119 | ||
4120 | #undef TARGET_LEGITIMATE_ADDRESS_P | |
4121 | #define TARGET_LEGITIMATE_ADDRESS_P riscv_legitimate_address_p | |
4122 | ||
4123 | #undef TARGET_CAN_ELIMINATE | |
4124 | #define TARGET_CAN_ELIMINATE riscv_can_eliminate | |
4125 | ||
4126 | #undef TARGET_CONDITIONAL_REGISTER_USAGE | |
4127 | #define TARGET_CONDITIONAL_REGISTER_USAGE riscv_conditional_register_usage | |
4128 | ||
4129 | #undef TARGET_CLASS_MAX_NREGS | |
4130 | #define TARGET_CLASS_MAX_NREGS riscv_class_max_nregs | |
4131 | ||
4132 | #undef TARGET_TRAMPOLINE_INIT | |
4133 | #define TARGET_TRAMPOLINE_INIT riscv_trampoline_init | |
4134 | ||
4135 | #undef TARGET_IN_SMALL_DATA_P | |
4136 | #define TARGET_IN_SMALL_DATA_P riscv_in_small_data_p | |
4137 | ||
4138 | #undef TARGET_ASM_SELECT_RTX_SECTION | |
4139 | #define TARGET_ASM_SELECT_RTX_SECTION riscv_elf_select_rtx_section | |
4140 | ||
4141 | #undef TARGET_MIN_ANCHOR_OFFSET | |
4142 | #define TARGET_MIN_ANCHOR_OFFSET (-IMM_REACH/2) | |
4143 | ||
4144 | #undef TARGET_MAX_ANCHOR_OFFSET | |
4145 | #define TARGET_MAX_ANCHOR_OFFSET (IMM_REACH/2-1) | |
4146 | ||
4147 | #undef TARGET_REGISTER_PRIORITY | |
4148 | #define TARGET_REGISTER_PRIORITY riscv_register_priority | |
4149 | ||
4150 | #undef TARGET_CANNOT_COPY_INSN_P | |
4151 | #define TARGET_CANNOT_COPY_INSN_P riscv_cannot_copy_insn_p | |
4152 | ||
4153 | #undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV | |
4154 | #define TARGET_ATOMIC_ASSIGN_EXPAND_FENV riscv_atomic_assign_expand_fenv | |
4155 | ||
4156 | #undef TARGET_INIT_BUILTINS | |
4157 | #define TARGET_INIT_BUILTINS riscv_init_builtins | |
4158 | ||
4159 | #undef TARGET_BUILTIN_DECL | |
4160 | #define TARGET_BUILTIN_DECL riscv_builtin_decl | |
4161 | ||
4162 | #undef TARGET_EXPAND_BUILTIN | |
4163 | #define TARGET_EXPAND_BUILTIN riscv_expand_builtin | |
4164 | ||
c43f4279 RS |
4165 | #undef TARGET_HARD_REGNO_NREGS |
4166 | #define TARGET_HARD_REGNO_NREGS riscv_hard_regno_nregs | |
f939c3e6 RS |
4167 | #undef TARGET_HARD_REGNO_MODE_OK |
4168 | #define TARGET_HARD_REGNO_MODE_OK riscv_hard_regno_mode_ok | |
4169 | ||
99e1629f RS |
4170 | #undef TARGET_MODES_TIEABLE_P |
4171 | #define TARGET_MODES_TIEABLE_P riscv_modes_tieable_p | |
4172 | ||
e0bd6c9f RS |
4173 | #undef TARGET_SLOW_UNALIGNED_ACCESS |
4174 | #define TARGET_SLOW_UNALIGNED_ACCESS riscv_slow_unaligned_access | |
4175 | ||
f15643d4 RS |
4176 | #undef TARGET_SECONDARY_MEMORY_NEEDED |
4177 | #define TARGET_SECONDARY_MEMORY_NEEDED riscv_secondary_memory_needed | |
4178 | ||
0d803030 RS |
4179 | #undef TARGET_CAN_CHANGE_MODE_CLASS |
4180 | #define TARGET_CAN_CHANGE_MODE_CLASS riscv_can_change_mode_class | |
4181 | ||
58e17cf8 RS |
4182 | #undef TARGET_CONSTANT_ALIGNMENT |
4183 | #define TARGET_CONSTANT_ALIGNMENT riscv_constant_alignment | |
4184 | ||
09cae750 PD |
4185 | struct gcc_target targetm = TARGET_INITIALIZER; |
4186 | ||
4187 | #include "gt-riscv.h" |