]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/xtensa/xtensa.cc
modula-2, libm2min: Declare abort and exit as expected.
[thirdparty/gcc.git] / gcc / config / xtensa / xtensa.cc
CommitLineData
e53b6e56 1/* Subroutines for insn-output.cc for Tensilica's Xtensa architecture.
7adcbafe 2 Copyright (C) 2001-2022 Free Software Foundation, Inc.
03984308
BW
3 Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
2f83c7d6 9Software Foundation; either version 3, or (at your option) any later
03984308
BW
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
2f83c7d6
NC
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
03984308 20
8fcc61f8
RS
21#define IN_TARGET_CODE 1
22
03984308
BW
23#include "config.h"
24#include "system.h"
4977bab6 25#include "coretypes.h"
c7131fb2 26#include "backend.h"
e11c4407
AM
27#include "target.h"
28#include "rtl.h"
c7131fb2
AM
29#include "tree.h"
30#include "gimple.h"
e11c4407 31#include "cfghooks.h"
c7131fb2 32#include "df.h"
4d0cdd0c 33#include "memmodel.h"
e11c4407
AM
34#include "tm_p.h"
35#include "stringpool.h"
314e6352 36#include "attribs.h"
e11c4407 37#include "optabs.h"
03984308 38#include "regs.h"
e11c4407 39#include "emit-rtl.h"
03984308 40#include "recog.h"
e11c4407
AM
41#include "diagnostic-core.h"
42#include "cfgrtl.h"
03984308 43#include "output.h"
40e23961 44#include "fold-const.h"
d8a2d370
DN
45#include "stor-layout.h"
46#include "calls.h"
47#include "varasm.h"
36566b39 48#include "alias.h"
36566b39 49#include "explow.h"
36566b39 50#include "expr.h"
03984308 51#include "reload.h"
540eaea8 52#include "langhooks.h"
45b0be94 53#include "gimplify.h"
9b2b7279 54#include "builtins.h"
6383386a
FY
55#include "dumpfile.h"
56#include "hw-doloop.h"
2f36a994 57#include "rtl-iter.h"
ccd02e73 58#include "insn-attr.h"
4f3f0296 59#include "tree-pass.h"
85d53c1d 60
994c5d85 61/* This file should be included last. */
d58627a0 62#include "target-def.h"
03984308
BW
63
64/* Enumeration for all of the relational tests, so that we can build
65 arrays indexed by the test type, and not worry about the order
638db43e 66 of EQ, NE, etc. */
03984308 67
ffbc8796
BW
68enum internal_test
69{
70 ITEST_EQ,
71 ITEST_NE,
72 ITEST_GT,
73 ITEST_GE,
74 ITEST_LT,
75 ITEST_LE,
76 ITEST_GTU,
77 ITEST_GEU,
78 ITEST_LTU,
79 ITEST_LEU,
80 ITEST_MAX
81};
03984308 82
03984308
BW
83/* Array giving truth value on whether or not a given hard register
84 can support a given mode. */
f939c3e6
RS
85static char xtensa_hard_regno_mode_ok_p
86 [(int) MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];
03984308 87
a46bbb5a 88/* Largest block move to handle in-line. */
03984308
BW
89#define LARGEST_MOVE_RATIO 15
90
91/* Define the structure for the machine field in struct function. */
d1b38208 92struct GTY(()) machine_function
03984308
BW
93{
94 int accesses_prev_frame;
997b8b4d
BW
95 bool need_a7_copy;
96 bool vararg_a7;
0d8442b8 97 rtx vararg_a7_copy;
240a513f 98 rtx_insn *set_frame_ptr_insn;
ad89d820
MF
99 /* Current frame size calculated by compute_frame_size. */
100 unsigned current_frame_size;
101 /* Callee-save area size in the current frame calculated by
102 compute_frame_size. */
103 int callee_save_size;
104 bool frame_laid_out;
105 bool epilogue_done;
06c2756e 106 bool inhibit_logues_a1_adjusts;
03984308
BW
107};
108
109/* Vector, indexed by hard register number, which contains 1 for a
110 register that is allowable in a candidate for leaf function
638db43e 111 treatment. */
03984308
BW
112
113const char xtensa_leaf_regs[FIRST_PSEUDO_REGISTER] =
114{
115 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
116 1, 1, 1,
117 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
118 1
119};
120
c5387660 121static void xtensa_option_override (void);
ffbc8796 122static enum internal_test map_test_to_internal_test (enum rtx_code);
e1b193c1 123static rtx gen_int_relational (enum rtx_code, rtx, rtx);
ffbc8796 124static rtx gen_float_relational (enum rtx_code, rtx, rtx);
ef4bddc2 125static rtx gen_conditional_move (enum rtx_code, machine_mode, rtx, rtx);
ffbc8796 126static rtx fixup_subreg_mem (rtx);
ffbc8796 127static struct machine_function * xtensa_init_machine_status (void);
6a7a462c 128static rtx xtensa_legitimize_tls_address (rtx);
ef4bddc2 129static rtx xtensa_legitimize_address (rtx, rtx, machine_mode);
5bfed9a9 130static bool xtensa_mode_dependent_address_p (const_rtx, addr_space_t);
586de218 131static bool xtensa_return_in_msb (const_tree);
ffbc8796 132static void printx (FILE *, signed int);
4c45af42 133static rtx xtensa_builtin_saveregs (void);
ef4bddc2 134static bool xtensa_legitimate_address_p (machine_mode, rtx, bool);
ffbc8796
BW
135static unsigned int xtensa_multibss_section_type_flags (tree, const char *,
136 int) ATTRIBUTE_UNUSED;
ef4bddc2 137static section *xtensa_select_rtx_section (machine_mode, rtx,
d6b5193b 138 unsigned HOST_WIDE_INT);
e548c9df 139static bool xtensa_rtx_costs (rtx, machine_mode, int, int, int *, bool);
ccd02e73 140static int xtensa_insn_cost (rtx_insn *, bool);
ef4bddc2 141static int xtensa_register_move_cost (machine_mode, reg_class_t,
5378dda2 142 reg_class_t);
ef4bddc2 143static int xtensa_memory_move_cost (machine_mode, reg_class_t, bool);
c35d187f 144static tree xtensa_build_builtin_va_list (void);
586de218 145static bool xtensa_return_in_memory (const_tree, const_tree);
726a989a
RB
146static tree xtensa_gimplify_va_arg_expr (tree, tree, gimple_seq *,
147 gimple_seq *);
6930c98c
RS
148static void xtensa_function_arg_advance (cumulative_args_t,
149 const function_arg_info &);
6783fdb7 150static rtx xtensa_function_arg (cumulative_args_t, const function_arg_info &);
d5cc9181 151static rtx xtensa_function_incoming_arg (cumulative_args_t,
6783fdb7 152 const function_arg_info &);
e2b2d01e 153static rtx xtensa_function_value (const_tree, const_tree, bool);
ef4bddc2 154static rtx xtensa_libcall_value (machine_mode, const_rtx);
dde8a3a4 155static bool xtensa_function_value_regno_p (const unsigned int);
ef4bddc2 156static unsigned int xtensa_function_arg_boundary (machine_mode,
c2ed6cf8 157 const_tree);
09fa8841 158static void xtensa_init_builtins (void);
f311c3b4 159static tree xtensa_fold_builtin (tree, int, tree *, bool);
ef4bddc2 160static rtx xtensa_expand_builtin (tree, rtx, rtx, machine_mode, int);
9d0b1619 161static void xtensa_va_start (tree, rtx);
b52b1749 162static bool xtensa_frame_pointer_required (void);
2b4fa409 163static rtx xtensa_static_chain (const_tree, bool);
3c1229cb
RH
164static void xtensa_asm_trampoline_template (FILE *);
165static void xtensa_trampoline_init (rtx, tree, rtx);
2ac6bb04 166static bool xtensa_output_addr_const_extra (FILE *, rtx);
ef4bddc2 167static bool xtensa_cannot_force_const_mem (machine_mode, rtx);
b64a1b53 168
a6e508f9
AS
169static reg_class_t xtensa_preferred_reload_class (rtx, reg_class_t);
170static reg_class_t xtensa_preferred_output_reload_class (rtx, reg_class_t);
171static reg_class_t xtensa_secondary_reload (bool, rtx, reg_class_t,
ef4bddc2 172 machine_mode,
a6e508f9
AS
173 struct secondary_reload_info *);
174
a1a79768 175static bool constantpool_address_p (const_rtx addr);
ef4bddc2 176static bool xtensa_legitimate_constant_p (machine_mode, rtx);
6383386a
FY
177static void xtensa_reorg (void);
178static bool xtensa_can_use_doloop_p (const widest_int &, const widest_int &,
89d5982b 179 unsigned int, bool);
6383386a 180static const char *xtensa_invalid_within_doloop (const rtx_insn *);
a1a79768 181
d9886a9e 182static bool xtensa_member_type_forces_blk (const_tree,
ef4bddc2 183 machine_mode mode);
d9886a9e 184
590e2636 185static void xtensa_conditional_register_usage (void);
c43f4279 186static unsigned int xtensa_hard_regno_nregs (unsigned int, machine_mode);
f939c3e6 187static bool xtensa_hard_regno_mode_ok (unsigned int, machine_mode);
99e1629f 188static bool xtensa_modes_tieable_p (machine_mode, machine_mode);
58e17cf8 189static HOST_WIDE_INT xtensa_constant_alignment (const_tree, HOST_WIDE_INT);
f50c32fa
MF
190static bool xtensa_can_eliminate (const int from ATTRIBUTE_UNUSED,
191 const int to);
2a31c321 192static HOST_WIDE_INT xtensa_starting_frame_offset (void);
8c9ee176 193static unsigned HOST_WIDE_INT xtensa_asan_shadow_offset (void);
43b0c56f 194static bool xtensa_function_ok_for_sibcall (tree, tree);
0bf60f68
MF
195static bool xtensa_can_output_mi_thunk (const_tree thunk_fndecl ATTRIBUTE_UNUSED,
196 HOST_WIDE_INT delta ATTRIBUTE_UNUSED,
197 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
198 const_tree function ATTRIBUTE_UNUSED);
199static void xtensa_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
200 HOST_WIDE_INT delta,
201 HOST_WIDE_INT vcall_offset,
202 tree function);
4f3f0296 203static bool xtensa_lra_p (void);
0bf60f68 204
b7641550
MF
205static rtx xtensa_delegitimize_address (rtx);
206
590e2636 207\f
03984308
BW
208
209/* These hooks specify assembly directives for creating certain kinds
210 of integer object. */
211
212#undef TARGET_ASM_ALIGNED_SI_OP
213#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
214
b64a1b53
RH
215#undef TARGET_ASM_SELECT_RTX_SECTION
216#define TARGET_ASM_SELECT_RTX_SECTION xtensa_select_rtx_section
03984308 217
506d7b68
PB
218#undef TARGET_LEGITIMIZE_ADDRESS
219#define TARGET_LEGITIMIZE_ADDRESS xtensa_legitimize_address
a1a79768
AS
220#undef TARGET_MODE_DEPENDENT_ADDRESS_P
221#define TARGET_MODE_DEPENDENT_ADDRESS_P xtensa_mode_dependent_address_p
506d7b68 222
5378dda2
AS
223#undef TARGET_REGISTER_MOVE_COST
224#define TARGET_REGISTER_MOVE_COST xtensa_register_move_cost
225#undef TARGET_MEMORY_MOVE_COST
226#define TARGET_MEMORY_MOVE_COST xtensa_memory_move_cost
3c50106f
RH
227#undef TARGET_RTX_COSTS
228#define TARGET_RTX_COSTS xtensa_rtx_costs
ccd02e73
TJJS
229#undef TARGET_INSN_COST
230#define TARGET_INSN_COST xtensa_insn_cost
dcefdf67 231#undef TARGET_ADDRESS_COST
b413068c 232#define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
3c50106f 233
d9886a9e
L
234#undef TARGET_MEMBER_TYPE_FORCES_BLK
235#define TARGET_MEMBER_TYPE_FORCES_BLK xtensa_member_type_forces_blk
236
c35d187f
RH
237#undef TARGET_BUILD_BUILTIN_VA_LIST
238#define TARGET_BUILD_BUILTIN_VA_LIST xtensa_build_builtin_va_list
239
d7bd8aeb
JJ
240#undef TARGET_EXPAND_BUILTIN_VA_START
241#define TARGET_EXPAND_BUILTIN_VA_START xtensa_va_start
242
cde0f3fd
PB
243#undef TARGET_PROMOTE_FUNCTION_MODE
244#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
4c45af42 245#undef TARGET_PROMOTE_PROTOTYPES
586de218 246#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
4c45af42 247
4c45af42
KH
248#undef TARGET_RETURN_IN_MEMORY
249#define TARGET_RETURN_IN_MEMORY xtensa_return_in_memory
e2b2d01e
AS
250#undef TARGET_FUNCTION_VALUE
251#define TARGET_FUNCTION_VALUE xtensa_function_value
dde8a3a4
AS
252#undef TARGET_LIBCALL_VALUE
253#define TARGET_LIBCALL_VALUE xtensa_libcall_value
254#undef TARGET_FUNCTION_VALUE_REGNO_P
255#define TARGET_FUNCTION_VALUE_REGNO_P xtensa_function_value_regno_p
256
42ba5130 257#undef TARGET_SPLIT_COMPLEX_ARG
3101faab 258#define TARGET_SPLIT_COMPLEX_ARG hook_bool_const_tree_true
fe984136
RH
259#undef TARGET_MUST_PASS_IN_STACK
260#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
626a4b31
NF
261#undef TARGET_FUNCTION_ARG_ADVANCE
262#define TARGET_FUNCTION_ARG_ADVANCE xtensa_function_arg_advance
263#undef TARGET_FUNCTION_ARG
264#define TARGET_FUNCTION_ARG xtensa_function_arg
265#undef TARGET_FUNCTION_INCOMING_ARG
266#define TARGET_FUNCTION_INCOMING_ARG xtensa_function_incoming_arg
c2ed6cf8
NF
267#undef TARGET_FUNCTION_ARG_BOUNDARY
268#define TARGET_FUNCTION_ARG_BOUNDARY xtensa_function_arg_boundary
4c45af42
KH
269
270#undef TARGET_EXPAND_BUILTIN_SAVEREGS
271#define TARGET_EXPAND_BUILTIN_SAVEREGS xtensa_builtin_saveregs
85d53c1d
RH
272#undef TARGET_GIMPLIFY_VA_ARG_EXPR
273#define TARGET_GIMPLIFY_VA_ARG_EXPR xtensa_gimplify_va_arg_expr
4c45af42 274
6e5ff6e7
BW
275#undef TARGET_RETURN_IN_MSB
276#define TARGET_RETURN_IN_MSB xtensa_return_in_msb
277
09fa8841
BW
278#undef TARGET_INIT_BUILTINS
279#define TARGET_INIT_BUILTINS xtensa_init_builtins
280#undef TARGET_FOLD_BUILTIN
281#define TARGET_FOLD_BUILTIN xtensa_fold_builtin
282#undef TARGET_EXPAND_BUILTIN
283#define TARGET_EXPAND_BUILTIN xtensa_expand_builtin
284
a6e508f9
AS
285#undef TARGET_PREFERRED_RELOAD_CLASS
286#define TARGET_PREFERRED_RELOAD_CLASS xtensa_preferred_reload_class
287#undef TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
288#define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS xtensa_preferred_output_reload_class
289
37fbe8a3
BW
290#undef TARGET_SECONDARY_RELOAD
291#define TARGET_SECONDARY_RELOAD xtensa_secondary_reload
292
6a7a462c 293#undef TARGET_HAVE_TLS
e46dad5d 294#define TARGET_HAVE_TLS HAVE_AS_TLS
6a7a462c
BW
295
296#undef TARGET_CANNOT_FORCE_CONST_MEM
fbbf66e7 297#define TARGET_CANNOT_FORCE_CONST_MEM xtensa_cannot_force_const_mem
6a7a462c 298
d81db636 299#undef TARGET_LRA_P
4f3f0296 300#define TARGET_LRA_P xtensa_lra_p
d81db636 301
c6c3dba9
PB
302#undef TARGET_LEGITIMATE_ADDRESS_P
303#define TARGET_LEGITIMATE_ADDRESS_P xtensa_legitimate_address_p
304
b52b1749
AS
305#undef TARGET_FRAME_POINTER_REQUIRED
306#define TARGET_FRAME_POINTER_REQUIRED xtensa_frame_pointer_required
307
2b4fa409
RH
308#undef TARGET_STATIC_CHAIN
309#define TARGET_STATIC_CHAIN xtensa_static_chain
3c1229cb
RH
310#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
311#define TARGET_ASM_TRAMPOLINE_TEMPLATE xtensa_asm_trampoline_template
312#undef TARGET_TRAMPOLINE_INIT
313#define TARGET_TRAMPOLINE_INIT xtensa_trampoline_init
314
c5387660
JM
315#undef TARGET_OPTION_OVERRIDE
316#define TARGET_OPTION_OVERRIDE xtensa_option_override
317
2ac6bb04
AS
318#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
319#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA xtensa_output_addr_const_extra
320
1a627b35
RS
321#undef TARGET_LEGITIMATE_CONSTANT_P
322#define TARGET_LEGITIMATE_CONSTANT_P xtensa_legitimate_constant_p
323
6383386a
FY
324#undef TARGET_MACHINE_DEPENDENT_REORG
325#define TARGET_MACHINE_DEPENDENT_REORG xtensa_reorg
326
327#undef TARGET_CAN_USE_DOLOOP_P
328#define TARGET_CAN_USE_DOLOOP_P xtensa_can_use_doloop_p
329
330#undef TARGET_INVALID_WITHIN_DOLOOP
331#define TARGET_INVALID_WITHIN_DOLOOP xtensa_invalid_within_doloop
332
590e2636
MF
333#undef TARGET_CONDITIONAL_REGISTER_USAGE
334#define TARGET_CONDITIONAL_REGISTER_USAGE xtensa_conditional_register_usage
335
c43f4279
RS
336#undef TARGET_HARD_REGNO_NREGS
337#define TARGET_HARD_REGNO_NREGS xtensa_hard_regno_nregs
f939c3e6
RS
338#undef TARGET_HARD_REGNO_MODE_OK
339#define TARGET_HARD_REGNO_MODE_OK xtensa_hard_regno_mode_ok
340
99e1629f
RS
341#undef TARGET_MODES_TIEABLE_P
342#define TARGET_MODES_TIEABLE_P xtensa_modes_tieable_p
343
58e17cf8
RS
344#undef TARGET_CONSTANT_ALIGNMENT
345#define TARGET_CONSTANT_ALIGNMENT xtensa_constant_alignment
346
f50c32fa
MF
347#undef TARGET_CAN_ELIMINATE
348#define TARGET_CAN_ELIMINATE xtensa_can_eliminate
349
2a31c321
RS
350#undef TARGET_STARTING_FRAME_OFFSET
351#define TARGET_STARTING_FRAME_OFFSET xtensa_starting_frame_offset
352
8c9ee176
MF
353#undef TARGET_ASAN_SHADOW_OFFSET
354#define TARGET_ASAN_SHADOW_OFFSET xtensa_asan_shadow_offset
355
c6579387
MF
356#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
357#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
358
936efcac
TJJS
359#undef TARGET_DELEGITIMIZE_ADDRESS
360#define TARGET_DELEGITIMIZE_ADDRESS xtensa_delegitimize_address
361
48e40d0b
MF
362#undef TARGET_FUNCTION_OK_FOR_SIBCALL
363#define TARGET_FUNCTION_OK_FOR_SIBCALL xtensa_function_ok_for_sibcall
364
0bf60f68
MF
365#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
366#define TARGET_ASM_CAN_OUTPUT_MI_THUNK xtensa_can_output_mi_thunk
367
368#undef TARGET_ASM_OUTPUT_MI_THUNK
369#define TARGET_ASM_OUTPUT_MI_THUNK xtensa_output_mi_thunk
370
66d20d88
MF
371#undef TARGET_MAX_ANCHOR_OFFSET
372#define TARGET_MAX_ANCHOR_OFFSET 1020
373
b64a1b53 374struct gcc_target targetm = TARGET_INITIALIZER;
03984308 375
887af464
BW
376\f
377/* Functions to test Xtensa immediate operand validity. */
03984308 378
8eb1bc5c
BW
379bool
380xtensa_simm8 (HOST_WIDE_INT v)
381{
9b251fe2 382 return IN_RANGE (v, -128, 127);
8eb1bc5c
BW
383}
384
385
386bool
387xtensa_simm8x256 (HOST_WIDE_INT v)
388{
9b251fe2 389 return (v & 255) == 0 && IN_RANGE (v, -32768, 32512);
8eb1bc5c
BW
390}
391
392
393bool
394xtensa_simm12b (HOST_WIDE_INT v)
395{
9b251fe2 396 return IN_RANGE (v, -2048, 2047);
8eb1bc5c
BW
397}
398
399
400static bool
401xtensa_uimm8 (HOST_WIDE_INT v)
402{
9b251fe2 403 return IN_RANGE (v, 0, 255);
8eb1bc5c
BW
404}
405
406
407static bool
408xtensa_uimm8x2 (HOST_WIDE_INT v)
409{
9b251fe2 410 return (v & 1) == 0 && IN_RANGE (v, 0, 510);
8eb1bc5c
BW
411}
412
413
414static bool
415xtensa_uimm8x4 (HOST_WIDE_INT v)
416{
9b251fe2 417 return (v & 3) == 0 && IN_RANGE (v, 0, 1020);
8eb1bc5c
BW
418}
419
420
421static bool
422xtensa_b4const (HOST_WIDE_INT v)
03984308
BW
423{
424 switch (v)
425 {
8eb1bc5c
BW
426 case -1:
427 case 1:
03984308
BW
428 case 2:
429 case 3:
430 case 4:
431 case 5:
432 case 6:
433 case 7:
434 case 8:
435 case 10:
436 case 12:
437 case 16:
438 case 32:
439 case 64:
440 case 128:
441 case 256:
8eb1bc5c 442 return true;
03984308 443 }
8eb1bc5c 444 return false;
03984308
BW
445}
446
03984308 447
8eb1bc5c
BW
448bool
449xtensa_b4const_or_zero (HOST_WIDE_INT v)
03984308 450{
8eb1bc5c
BW
451 if (v == 0)
452 return true;
453 return xtensa_b4const (v);
03984308
BW
454}
455
03984308 456
8eb1bc5c
BW
457bool
458xtensa_b4constu (HOST_WIDE_INT v)
03984308
BW
459{
460 switch (v)
461 {
8eb1bc5c
BW
462 case 32768:
463 case 65536:
03984308
BW
464 case 2:
465 case 3:
466 case 4:
467 case 5:
468 case 6:
469 case 7:
470 case 8:
471 case 10:
472 case 12:
473 case 16:
474 case 32:
475 case 64:
476 case 128:
477 case 256:
8eb1bc5c 478 return true;
03984308 479 }
8eb1bc5c 480 return false;
03984308
BW
481}
482
03984308 483
8eb1bc5c
BW
484bool
485xtensa_mask_immediate (HOST_WIDE_INT v)
03984308 486{
b753405a 487 return IN_RANGE (exact_log2 (v + 1), 1, 16);
03984308
BW
488}
489
03984308 490
03984308 491/* This is just like the standard true_regnum() function except that it
638db43e 492 works even when reg_renumber is not initialized. */
03984308
BW
493
494int
ffbc8796 495xt_true_regnum (rtx x)
03984308 496{
4f3f0296 497 if (REG_P (x))
03984308 498 {
4f3f0296
TJJS
499 if (! HARD_REGISTER_P (x)
500 && reg_renumber
501 && (lra_in_progress || reg_renumber[REGNO (x)] >= 0))
03984308
BW
502 return reg_renumber[REGNO (x)];
503 return REGNO (x);
504 }
4f3f0296 505 if (SUBREG_P (x))
03984308
BW
506 {
507 int base = xt_true_regnum (SUBREG_REG (x));
4f3f0296
TJJS
508
509 if (base >= 0
510 && HARD_REGISTER_NUM_P (base))
511 {
512 struct subreg_info info;
513
514 subreg_get_info (lra_in_progress
515 ? (unsigned) base : REGNO (SUBREG_REG (x)),
516 GET_MODE (SUBREG_REG (x)),
517 SUBREG_BYTE (x), GET_MODE (x), &info);
518 if (info.representable_p)
519 return base + info.offset;
520 }
03984308
BW
521 }
522 return -1;
523}
524
525
03984308 526int
ef4bddc2 527xtensa_valid_move (machine_mode mode, rtx *operands)
03984308 528{
a8cacfd2
BW
529 /* Either the destination or source must be a register, and the
530 MAC16 accumulator doesn't count. */
531
532 if (register_operand (operands[0], mode))
533 {
534 int dst_regnum = xt_true_regnum (operands[0]);
535
a024f514
MF
536 if (xtensa_tls_referenced_p (operands[1]))
537 return FALSE;
538
638db43e 539 /* The stack pointer can only be assigned with a MOVSP opcode. */
a8cacfd2 540 if (dst_regnum == STACK_POINTER_REGNUM)
590e2636
MF
541 return !TARGET_WINDOWED_ABI
542 || (mode == SImode
543 && register_operand (operands[1], mode)
544 && !ACC_REG_P (xt_true_regnum (operands[1])));
a8cacfd2
BW
545
546 if (!ACC_REG_P (dst_regnum))
547 return true;
548 }
3437320b 549 if (register_operand (operands[1], mode))
a8cacfd2
BW
550 {
551 int src_regnum = xt_true_regnum (operands[1]);
552 if (!ACC_REG_P (src_regnum))
553 return true;
554 }
03984308
BW
555 return FALSE;
556}
557
558
03984308 559int
ffbc8796 560smalloffset_mem_p (rtx op)
03984308
BW
561{
562 if (GET_CODE (op) == MEM)
563 {
564 rtx addr = XEXP (op, 0);
565 if (GET_CODE (addr) == REG)
da1f39e4 566 return BASE_REG_P (addr, 0);
03984308
BW
567 if (GET_CODE (addr) == PLUS)
568 {
569 rtx offset = XEXP (addr, 0);
8eb1bc5c 570 HOST_WIDE_INT val;
03984308
BW
571 if (GET_CODE (offset) != CONST_INT)
572 offset = XEXP (addr, 1);
573 if (GET_CODE (offset) != CONST_INT)
574 return FALSE;
8eb1bc5c
BW
575
576 val = INTVAL (offset);
9b251fe2 577 return (val & 3) == 0 && IN_RANGE (val, 0, 60);
03984308
BW
578 }
579 }
580 return FALSE;
581}
582
583
a1a79768
AS
584static bool
585constantpool_address_p (const_rtx addr)
03984308 586{
a1a79768 587 const_rtx sym = addr;
03984308
BW
588
589 if (GET_CODE (addr) == CONST)
590 {
591 rtx offset;
592
3bbc2af6 593 /* Only handle (PLUS (SYM, OFFSET)) form. */
03984308
BW
594 addr = XEXP (addr, 0);
595 if (GET_CODE (addr) != PLUS)
a1a79768 596 return false;
03984308 597
3bbc2af6 598 /* Make sure the address is word aligned. */
03984308 599 offset = XEXP (addr, 1);
a1a79768 600 if ((!CONST_INT_P (offset))
03984308 601 || ((INTVAL (offset) & 3) != 0))
a1a79768 602 return false;
03984308
BW
603
604 sym = XEXP (addr, 0);
605 }
606
607 if ((GET_CODE (sym) == SYMBOL_REF)
608 && CONSTANT_POOL_ADDRESS_P (sym))
a1a79768
AS
609 return true;
610 return false;
03984308
BW
611}
612
613
614int
ffbc8796 615constantpool_mem_p (rtx op)
03984308 616{
63694bdd
BW
617 if (GET_CODE (op) == SUBREG)
618 op = SUBREG_REG (op);
03984308
BW
619 if (GET_CODE (op) == MEM)
620 return constantpool_address_p (XEXP (op, 0));
621 return FALSE;
622}
623
624
6a7a462c
BW
625/* Return TRUE if X is a thread-local symbol. */
626
627static bool
628xtensa_tls_symbol_p (rtx x)
629{
e46dad5d 630 if (! targetm.have_tls)
6a7a462c
BW
631 return false;
632
633 return GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0;
634}
635
636
03984308 637void
ffbc8796 638xtensa_extend_reg (rtx dst, rtx src)
03984308
BW
639{
640 rtx temp = gen_reg_rtx (SImode);
641 rtx shift = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (GET_MODE (src)));
642
3bbc2af6 643 /* Generate paradoxical subregs as needed so that the modes match. */
03984308
BW
644 src = simplify_gen_subreg (SImode, src, GET_MODE (src), 0);
645 dst = simplify_gen_subreg (SImode, dst, GET_MODE (dst), 0);
646
647 emit_insn (gen_ashlsi3 (temp, src, shift));
648 emit_insn (gen_ashrsi3 (dst, temp, shift));
649}
650
651
8eb1bc5c 652bool
ef4bddc2 653xtensa_mem_offset (unsigned v, machine_mode mode)
03984308
BW
654{
655 switch (mode)
656 {
4e10a5a7 657 case E_BLKmode:
03984308
BW
658 /* Handle the worst case for block moves. See xtensa_expand_block_move
659 where we emit an optimized block move operation if the block can be
660 moved in < "move_ratio" pieces. The worst case is when the block is
661 aligned but has a size of (3 mod 4) (does this happen?) so that the
638db43e 662 last piece requires a byte load/store. */
f42f5a1b
BW
663 return (xtensa_uimm8 (v)
664 && xtensa_uimm8 (v + MOVE_MAX * LARGEST_MOVE_RATIO));
03984308 665
4e10a5a7 666 case E_QImode:
03984308
BW
667 return xtensa_uimm8 (v);
668
4e10a5a7 669 case E_HImode:
03984308
BW
670 return xtensa_uimm8x2 (v);
671
738ae6ee 672 case E_DImode:
4e10a5a7 673 case E_DFmode:
03984308
BW
674 return (xtensa_uimm8x4 (v) && xtensa_uimm8x4 (v + 4));
675
676 default:
677 break;
678 }
679
680 return xtensa_uimm8x4 (v);
681}
682
683
ffbc8796 684/* Make normal rtx_code into something we can index from an array. */
03984308
BW
685
686static enum internal_test
ffbc8796 687map_test_to_internal_test (enum rtx_code test_code)
03984308
BW
688{
689 enum internal_test test = ITEST_MAX;
690
691 switch (test_code)
692 {
693 default: break;
694 case EQ: test = ITEST_EQ; break;
695 case NE: test = ITEST_NE; break;
696 case GT: test = ITEST_GT; break;
697 case GE: test = ITEST_GE; break;
698 case LT: test = ITEST_LT; break;
699 case LE: test = ITEST_LE; break;
700 case GTU: test = ITEST_GTU; break;
701 case GEU: test = ITEST_GEU; break;
702 case LTU: test = ITEST_LTU; break;
703 case LEU: test = ITEST_LEU; break;
704 }
705
706 return test;
707}
708
709
710/* Generate the code to compare two integer values. The return value is
638db43e 711 the comparison expression. */
03984308
BW
712
713static rtx
ffbc8796
BW
714gen_int_relational (enum rtx_code test_code, /* relational test (EQ, etc) */
715 rtx cmp0, /* first operand to compare */
e1b193c1 716 rtx cmp1 /* second operand to compare */)
03984308 717{
ffbc8796
BW
718 struct cmp_info
719 {
03984308 720 enum rtx_code test_code; /* test code to use in insn */
8eb1bc5c 721 bool (*const_range_p) (HOST_WIDE_INT); /* range check function */
03984308
BW
722 int const_add; /* constant to add (convert LE -> LT) */
723 int reverse_regs; /* reverse registers in test */
724 int invert_const; /* != 0 if invert value if cmp1 is constant */
725 int invert_reg; /* != 0 if invert value if cmp1 is register */
726 int unsignedp; /* != 0 for unsigned comparisons. */
727 };
728
729 static struct cmp_info info[ (int)ITEST_MAX ] = {
730
8eb1bc5c
BW
731 { EQ, xtensa_b4const_or_zero, 0, 0, 0, 0, 0 }, /* EQ */
732 { NE, xtensa_b4const_or_zero, 0, 0, 0, 0, 0 }, /* NE */
03984308 733
8eb1bc5c
BW
734 { LT, xtensa_b4const_or_zero, 1, 1, 1, 0, 0 }, /* GT */
735 { GE, xtensa_b4const_or_zero, 0, 0, 0, 0, 0 }, /* GE */
736 { LT, xtensa_b4const_or_zero, 0, 0, 0, 0, 0 }, /* LT */
737 { GE, xtensa_b4const_or_zero, 1, 1, 1, 0, 0 }, /* LE */
03984308
BW
738
739 { LTU, xtensa_b4constu, 1, 1, 1, 0, 1 }, /* GTU */
740 { GEU, xtensa_b4constu, 0, 0, 0, 0, 1 }, /* GEU */
741 { LTU, xtensa_b4constu, 0, 0, 0, 0, 1 }, /* LTU */
742 { GEU, xtensa_b4constu, 1, 1, 1, 0, 1 }, /* LEU */
743 };
744
745 enum internal_test test;
ef4bddc2 746 machine_mode mode;
03984308 747 struct cmp_info *p_info;
e1b193c1 748 int invert;
03984308
BW
749
750 test = map_test_to_internal_test (test_code);
177b6be0 751 gcc_assert (test != ITEST_MAX);
03984308
BW
752
753 p_info = &info[ (int)test ];
754
755 mode = GET_MODE (cmp0);
756 if (mode == VOIDmode)
757 mode = GET_MODE (cmp1);
758
759 /* Make sure we can handle any constants given to us. */
760 if (GET_CODE (cmp1) == CONST_INT)
761 {
762 HOST_WIDE_INT value = INTVAL (cmp1);
763 unsigned HOST_WIDE_INT uvalue = (unsigned HOST_WIDE_INT)value;
764
765 /* if the immediate overflows or does not fit in the immediate field,
766 spill it to a register */
767
768 if ((p_info->unsignedp ?
769 (uvalue + p_info->const_add > uvalue) :
770 (value + p_info->const_add > value)) != (p_info->const_add > 0))
771 {
772 cmp1 = force_reg (mode, cmp1);
773 }
774 else if (!(p_info->const_range_p) (value + p_info->const_add))
775 {
776 cmp1 = force_reg (mode, cmp1);
777 }
778 }
779 else if ((GET_CODE (cmp1) != REG) && (GET_CODE (cmp1) != SUBREG))
780 {
781 cmp1 = force_reg (mode, cmp1);
782 }
783
784 /* See if we need to invert the result. */
75ab2f0e 785 invert = (CONST_INT_P (cmp1)
e1b193c1
TJJS
786 ? p_info->invert_const
787 : p_info->invert_reg);
03984308
BW
788
789 /* Comparison to constants, may involve adding 1 to change a LT into LE.
790 Comparison between two registers, may involve switching operands. */
791 if (GET_CODE (cmp1) == CONST_INT)
792 {
793 if (p_info->const_add != 0)
794 cmp1 = GEN_INT (INTVAL (cmp1) + p_info->const_add);
795
796 }
797 else if (p_info->reverse_regs)
798 {
799 rtx temp = cmp0;
800 cmp0 = cmp1;
801 cmp1 = temp;
802 }
803
e1b193c1
TJJS
804 return gen_rtx_fmt_ee (invert ? reverse_condition (p_info->test_code)
805 : p_info->test_code,
806 VOIDmode, cmp0, cmp1);
03984308
BW
807}
808
809
810/* Generate the code to compare two float values. The return value is
638db43e 811 the comparison expression. */
03984308
BW
812
813static rtx
ffbc8796
BW
814gen_float_relational (enum rtx_code test_code, /* relational test (EQ, etc) */
815 rtx cmp0, /* first operand to compare */
816 rtx cmp1 /* second operand to compare */)
03984308 817{
ffbc8796 818 rtx (*gen_fn) (rtx, rtx, rtx);
03984308
BW
819 rtx brtmp;
820 int reverse_regs, invert;
821
822 switch (test_code)
823 {
824 case EQ: reverse_regs = 0; invert = 0; gen_fn = gen_seq_sf; break;
825 case NE: reverse_regs = 0; invert = 1; gen_fn = gen_seq_sf; break;
826 case LE: reverse_regs = 0; invert = 0; gen_fn = gen_sle_sf; break;
827 case GT: reverse_regs = 1; invert = 0; gen_fn = gen_slt_sf; break;
828 case LT: reverse_regs = 0; invert = 0; gen_fn = gen_slt_sf; break;
829 case GE: reverse_regs = 1; invert = 0; gen_fn = gen_sle_sf; break;
ff779f98
BW
830 case UNEQ: reverse_regs = 0; invert = 0; gen_fn = gen_suneq_sf; break;
831 case LTGT: reverse_regs = 0; invert = 1; gen_fn = gen_suneq_sf; break;
832 case UNLE: reverse_regs = 0; invert = 0; gen_fn = gen_sunle_sf; break;
833 case UNGT: reverse_regs = 1; invert = 0; gen_fn = gen_sunlt_sf; break;
834 case UNLT: reverse_regs = 0; invert = 0; gen_fn = gen_sunlt_sf; break;
835 case UNGE: reverse_regs = 1; invert = 0; gen_fn = gen_sunle_sf; break;
836 case UNORDERED:
837 reverse_regs = 0; invert = 0; gen_fn = gen_sunordered_sf; break;
838 case ORDERED:
839 reverse_regs = 0; invert = 1; gen_fn = gen_sunordered_sf; break;
633e4eb4 840 default:
1c563bed 841 fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1));
03984308
BW
842 reverse_regs = 0; invert = 0; gen_fn = 0; /* avoid compiler warnings */
843 }
844
845 if (reverse_regs)
846 {
847 rtx temp = cmp0;
848 cmp0 = cmp1;
849 cmp1 = temp;
850 }
851
852 brtmp = gen_rtx_REG (CCmode, FPCC_REGNUM);
853 emit_insn (gen_fn (brtmp, cmp0, cmp1));
854
1c563bed 855 return gen_rtx_fmt_ee (invert ? EQ : NE, VOIDmode, brtmp, const0_rtx);
03984308
BW
856}
857
858
859void
ef4bddc2 860xtensa_expand_conditional_branch (rtx *operands, machine_mode mode)
03984308 861{
f90b7a5a
PB
862 enum rtx_code test_code = GET_CODE (operands[0]);
863 rtx cmp0 = operands[1];
864 rtx cmp1 = operands[2];
e1b193c1 865 rtx cmp, label;
03984308 866
f90b7a5a 867 switch (mode)
03984308 868 {
e1b193c1
TJJS
869 case E_SFmode:
870 if (TARGET_HARD_FLOAT)
871 {
872 cmp = gen_float_relational (test_code, cmp0, cmp1);
873 break;
874 }
875 /* FALLTHRU */
876
4e10a5a7 877 case E_DFmode:
03984308 878 default:
1c563bed 879 fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1));
03984308 880
4e10a5a7 881 case E_SImode:
e1b193c1 882 cmp = gen_int_relational (test_code, cmp0, cmp1);
03984308
BW
883 break;
884 }
885
886 /* Generate the branch. */
e1b193c1 887 label = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
f7df4a84 888 emit_jump_insn (gen_rtx_SET (pc_rtx,
03984308 889 gen_rtx_IF_THEN_ELSE (VOIDmode, cmp,
e1b193c1
TJJS
890 label,
891 pc_rtx)));
03984308
BW
892}
893
894
895static rtx
ef4bddc2 896gen_conditional_move (enum rtx_code code, machine_mode mode,
f90b7a5a 897 rtx op0, rtx op1)
03984308 898{
f90b7a5a 899 if (mode == SImode)
03984308 900 {
f90b7a5a
PB
901 rtx cmp;
902
03984308
BW
903 /* Jump optimization calls get_condition() which canonicalizes
904 comparisons like (GE x <const>) to (GT x <const-1>).
905 Transform those comparisons back to GE, since that is the
906 comparison supported in Xtensa. We shouldn't have to
907 transform <LE x const> comparisons, because neither
908 xtensa_expand_conditional_branch() nor get_condition() will
638db43e 909 produce them. */
03984308
BW
910
911 if ((code == GT) && (op1 == constm1_rtx))
912 {
913 code = GE;
914 op1 = const0_rtx;
915 }
bd1cd0d0 916 cmp = gen_rtx_fmt_ee (code, VOIDmode, pc_rtx, const0_rtx);
03984308
BW
917
918 if (boolean_operator (cmp, VOIDmode))
919 {
3bbc2af6 920 /* Swap the operands to make const0 second. */
03984308
BW
921 if (op0 == const0_rtx)
922 {
923 op0 = op1;
924 op1 = const0_rtx;
925 }
926
3bbc2af6 927 /* If not comparing against zero, emit a comparison (subtract). */
03984308
BW
928 if (op1 != const0_rtx)
929 {
930 op0 = expand_binop (SImode, sub_optab, op0, op1,
931 0, 0, OPTAB_LIB_WIDEN);
932 op1 = const0_rtx;
933 }
934 }
935 else if (branch_operator (cmp, VOIDmode))
936 {
3bbc2af6 937 /* Swap the operands to make const0 second. */
03984308
BW
938 if (op0 == const0_rtx)
939 {
940 op0 = op1;
941 op1 = const0_rtx;
942
943 switch (code)
944 {
945 case LT: code = GE; break;
946 case GE: code = LT; break;
177b6be0 947 default: gcc_unreachable ();
03984308
BW
948 }
949 }
950
951 if (op1 != const0_rtx)
952 return 0;
953 }
954 else
955 return 0;
956
1c563bed 957 return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
03984308
BW
958 }
959
f90b7a5a 960 if (TARGET_HARD_FLOAT && mode == SFmode)
03984308
BW
961 return gen_float_relational (code, op0, op1);
962
963 return 0;
964}
965
966
967int
ffbc8796 968xtensa_expand_conditional_move (rtx *operands, int isflt)
03984308 969{
f90b7a5a
PB
970 rtx dest = operands[0];
971 rtx cmp = operands[1];
ef4bddc2 972 machine_mode cmp_mode = GET_MODE (XEXP (cmp, 0));
ffbc8796 973 rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx);
03984308 974
f90b7a5a
PB
975 if (!(cmp = gen_conditional_move (GET_CODE (cmp), cmp_mode,
976 XEXP (cmp, 0), XEXP (cmp, 1))))
03984308
BW
977 return 0;
978
979 if (isflt)
f90b7a5a 980 gen_fn = (cmp_mode == SImode
03984308
BW
981 ? gen_movsfcc_internal0
982 : gen_movsfcc_internal1);
983 else
f90b7a5a 984 gen_fn = (cmp_mode == SImode
03984308
BW
985 ? gen_movsicc_internal0
986 : gen_movsicc_internal1);
987
f90b7a5a 988 emit_insn (gen_fn (dest, XEXP (cmp, 0), operands[2], operands[3], cmp));
03984308
BW
989 return 1;
990}
991
992
993int
ef4bddc2 994xtensa_expand_scc (rtx operands[4], machine_mode cmp_mode)
03984308
BW
995{
996 rtx dest = operands[0];
f90b7a5a 997 rtx cmp;
03984308 998 rtx one_tmp, zero_tmp;
ffbc8796 999 rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx);
03984308 1000
f90b7a5a
PB
1001 if (!(cmp = gen_conditional_move (GET_CODE (operands[1]), cmp_mode,
1002 operands[2], operands[3])))
03984308
BW
1003 return 0;
1004
1005 one_tmp = gen_reg_rtx (SImode);
1006 zero_tmp = gen_reg_rtx (SImode);
1007 emit_insn (gen_movsi (one_tmp, const_true_rtx));
1008 emit_insn (gen_movsi (zero_tmp, const0_rtx));
1009
f90b7a5a 1010 gen_fn = (cmp_mode == SImode
03984308
BW
1011 ? gen_movsicc_internal0
1012 : gen_movsicc_internal1);
1013 emit_insn (gen_fn (dest, XEXP (cmp, 0), one_tmp, zero_tmp, cmp));
1014 return 1;
1015}
1016
1017
633e4eb4
BW
1018/* Split OP[1] into OP[2,3] and likewise for OP[0] into OP[0,1]. MODE is
1019 for the output, i.e., the input operands are twice as big as MODE. */
1020
1021void
ef4bddc2 1022xtensa_split_operand_pair (rtx operands[4], machine_mode mode)
633e4eb4
BW
1023{
1024 switch (GET_CODE (operands[1]))
1025 {
1026 case REG:
1027 operands[3] = gen_rtx_REG (mode, REGNO (operands[1]) + 1);
1028 operands[2] = gen_rtx_REG (mode, REGNO (operands[1]));
1029 break;
1030
1031 case MEM:
1032 operands[3] = adjust_address (operands[1], mode, GET_MODE_SIZE (mode));
1033 operands[2] = adjust_address (operands[1], mode, 0);
1034 break;
1035
1036 case CONST_INT:
1037 case CONST_DOUBLE:
1038 split_double (operands[1], &operands[2], &operands[3]);
1039 break;
1040
1041 default:
177b6be0 1042 gcc_unreachable ();
633e4eb4
BW
1043 }
1044
1045 switch (GET_CODE (operands[0]))
1046 {
1047 case REG:
1048 operands[1] = gen_rtx_REG (mode, REGNO (operands[0]) + 1);
1049 operands[0] = gen_rtx_REG (mode, REGNO (operands[0]));
1050 break;
1051
1052 case MEM:
1053 operands[1] = adjust_address (operands[0], mode, GET_MODE_SIZE (mode));
1054 operands[0] = adjust_address (operands[0], mode, 0);
1055 break;
1056
1057 default:
177b6be0 1058 gcc_unreachable ();
633e4eb4
BW
1059 }
1060}
1061
1062
cd02f15f
TJJS
1063/* Try to emit insns to load srcval (that cannot fit into signed 12-bit)
1064 into dst with synthesizing a such constant value from a sequence of
1065 load-immediate / arithmetic ones, instead of a L32R instruction
1066 (plus a constant in litpool). */
1067
cd02f15f
TJJS
1068static int
1069xtensa_constantsynth_2insn (rtx dst, HOST_WIDE_INT srcval,
1070 rtx (*gen_op)(rtx, HOST_WIDE_INT),
1071 HOST_WIDE_INT op_imm)
1072{
1884f897
TJJS
1073 HOST_WIDE_INT imm = INT_MAX;
1074 rtx x = NULL_RTX;
1075 int shift;
cd02f15f 1076
1884f897
TJJS
1077 gcc_assert (REG_P (dst));
1078
1079 shift = exact_log2 (srcval + 1);
cd02f15f
TJJS
1080 if (IN_RANGE (shift, 1, 31))
1081 {
1884f897
TJJS
1082 imm = -1;
1083 x = gen_lshrsi3 (dst, dst, GEN_INT (32 - shift));
1084 }
1085
1086
1087 shift = ctz_hwi (srcval);
1088 if ((!x || (TARGET_DENSITY && ! IN_RANGE (imm, -32, 95)))
1089 && xtensa_simm12b (srcval >> shift))
1090 {
1091 imm = srcval >> shift;
1092 x = gen_ashlsi3 (dst, dst, GEN_INT (shift));
cd02f15f
TJJS
1093 }
1094
1884f897
TJJS
1095 if ((!x || (TARGET_DENSITY && ! IN_RANGE (imm, -32, 95)))
1096 && IN_RANGE (srcval, (-2048 - 32768), (2047 + 32512)))
cd02f15f
TJJS
1097 {
1098 HOST_WIDE_INT imm0, imm1;
1099
1100 if (srcval < -32768)
1101 imm1 = -32768;
1102 else if (srcval > 32512)
1103 imm1 = 32512;
1104 else
1105 imm1 = srcval & ~255;
1106 imm0 = srcval - imm1;
1107 if (TARGET_DENSITY && imm1 < 32512 && IN_RANGE (imm0, 224, 255))
1108 imm0 -= 256, imm1 += 256;
1884f897
TJJS
1109 imm = imm0;
1110 x = gen_addsi3 (dst, dst, GEN_INT (imm1));
cd02f15f
TJJS
1111 }
1112
1884f897
TJJS
1113 if (!x)
1114 return 0;
cd02f15f 1115
1884f897
TJJS
1116 emit_move_insn (dst, GEN_INT (imm));
1117 emit_insn (x);
1118 if (gen_op)
1119 emit_move_insn (dst, gen_op (dst, op_imm));
1120
1121 return 1;
cd02f15f
TJJS
1122}
1123
1124static rtx
1125xtensa_constantsynth_rtx_SLLI (rtx reg, HOST_WIDE_INT imm)
1126{
1127 return gen_rtx_ASHIFT (SImode, reg, GEN_INT (imm));
1128}
1129
1130static rtx
1131xtensa_constantsynth_rtx_ADDSUBX (rtx reg, HOST_WIDE_INT imm)
1132{
1133 return imm == 7
1134 ? gen_rtx_MINUS (SImode, gen_rtx_ASHIFT (SImode, reg, GEN_INT (3)),
1135 reg)
1136 : gen_rtx_PLUS (SImode, gen_rtx_ASHIFT (SImode, reg,
1137 GEN_INT (floor_log2 (imm - 1))),
1138 reg);
1139}
1140
1141int
1142xtensa_constantsynth (rtx dst, HOST_WIDE_INT srcval)
1143{
1144 /* No need for synthesizing for what fits into MOVI instruction. */
1145 if (xtensa_simm12b (srcval))
1146 return 0;
1147
1148 /* 2-insns substitution. */
1149 if ((optimize_size || (optimize && xtensa_extra_l32r_costs >= 1))
1150 && xtensa_constantsynth_2insn (dst, srcval, NULL, 0))
1151 return 1;
1152
1153 /* 3-insns substitution. */
1154 if (optimize > 1 && !optimize_size && xtensa_extra_l32r_costs >= 2)
1155 {
1156 int shift, divisor;
1157
1158 /* 2-insns substitution followed by SLLI. */
1159 shift = ctz_hwi (srcval);
1160 if (IN_RANGE (shift, 1, 31) &&
1161 xtensa_constantsynth_2insn (dst, srcval >> shift,
1162 xtensa_constantsynth_rtx_SLLI,
1163 shift))
1164 return 1;
1165
1166 /* 2-insns substitution followed by ADDX[248] or SUBX8. */
1167 if (TARGET_ADDX)
1168 for (divisor = 3; divisor <= 9; divisor += 2)
1169 if (srcval % divisor == 0 &&
1170 xtensa_constantsynth_2insn (dst, srcval / divisor,
1171 xtensa_constantsynth_rtx_ADDSUBX,
1172 divisor))
1173 return 1;
75e5cc9c
TJJS
1174
1175 /* loading simm12 followed by left/right bitwise rotation:
1176 MOVI + SSAI + SRC. */
1177 if ((srcval & 0x001FF800) == 0
1178 || (srcval & 0x001FF800) == 0x001FF800)
1179 {
1180 int32_t v;
1181
1182 for (shift = 1; shift < 12; ++shift)
1183 {
1184 v = (int32_t)(((uint32_t)srcval >> shift)
1185 | ((uint32_t)srcval << (32 - shift)));
1186 if (xtensa_simm12b(v))
1187 {
1188 emit_move_insn (dst, GEN_INT (v));
1189 emit_insn (gen_rotlsi3 (dst, dst, GEN_INT (shift)));
1190 return 1;
1191 }
1192 }
1193 for (shift = 1; shift < 12; ++shift)
1194 {
1195 v = (int32_t)(((uint32_t)srcval << shift)
1196 | ((uint32_t)srcval >> (32 - shift)));
1197 if (xtensa_simm12b(v))
1198 {
1199 emit_move_insn (dst, GEN_INT (v));
1200 emit_insn (gen_rotrsi3 (dst, dst, GEN_INT (shift)));
1201 return 1;
1202 }
1203 }
1204 }
cd02f15f
TJJS
1205 }
1206
1207 return 0;
1208}
1209
1210
03984308 1211/* Emit insns to move operands[1] into operands[0].
03984308
BW
1212 Return 1 if we have written out everything that needs to be done to
1213 do the move. Otherwise, return 0 and the caller will emit the move
1214 normally. */
1215
1216int
ef4bddc2 1217xtensa_emit_move_sequence (rtx *operands, machine_mode mode)
03984308 1218{
6a7a462c
BW
1219 rtx src = operands[1];
1220
1221 if (CONSTANT_P (src)
1222 && (GET_CODE (src) != CONST_INT || ! xtensa_simm12b (INTVAL (src))))
03984308 1223 {
6a7a462c
BW
1224 rtx dst = operands[0];
1225
1226 if (xtensa_tls_referenced_p (src))
1227 {
1228 rtx addend = NULL;
1229
1230 if (GET_CODE (src) == CONST && GET_CODE (XEXP (src, 0)) == PLUS)
1231 {
1232 addend = XEXP (XEXP (src, 0), 1);
1233 src = XEXP (XEXP (src, 0), 0);
1234 }
1235
1236 src = xtensa_legitimize_tls_address (src);
1237 if (addend)
1238 {
1239 src = gen_rtx_PLUS (mode, src, addend);
1240 src = force_operand (src, dst);
1241 }
1242 emit_move_insn (dst, src);
1243 return 1;
1244 }
1245
479b6f44
TJJS
1246 if (! TARGET_AUTO_LITPOOLS && ! TARGET_CONST16
1247 && ! (CONST_INT_P (src) && can_create_pseudo_p ()))
6a7a462c
BW
1248 {
1249 src = force_const_mem (SImode, src);
1250 operands[1] = src;
1251 }
f42f5a1b
BW
1252
1253 /* PC-relative loads are always SImode, and CONST16 is only
1254 supported in the movsi pattern, so add a SUBREG for any other
1255 (smaller) mode. */
1256
1257 if (mode != SImode)
1258 {
6a7a462c 1259 if (register_operand (dst, mode))
f42f5a1b 1260 {
6a7a462c 1261 emit_move_insn (simplify_gen_subreg (SImode, dst, mode, 0), src);
f42f5a1b
BW
1262 return 1;
1263 }
1264 else
1265 {
6a7a462c
BW
1266 src = force_reg (SImode, src);
1267 src = gen_lowpart_SUBREG (mode, src);
1268 operands[1] = src;
f42f5a1b
BW
1269 }
1270 }
03984308
BW
1271 }
1272
75ab2f0e 1273 if (can_create_pseudo_p ()
997b8b4d
BW
1274 && !xtensa_valid_move (mode, operands))
1275 operands[1] = force_reg (mode, operands[1]);
03984308 1276
997b8b4d 1277 operands[1] = xtensa_copy_incoming_a7 (operands[1]);
03984308
BW
1278
1279 /* During reload we don't want to emit (subreg:X (mem:Y)) since that
638db43e
BW
1280 instruction won't be recognized after reload, so we remove the
1281 subreg and adjust mem accordingly. */
03984308
BW
1282 if (reload_in_progress)
1283 {
1284 operands[0] = fixup_subreg_mem (operands[0]);
1285 operands[1] = fixup_subreg_mem (operands[1]);
1286 }
1287 return 0;
1288}
1289
f42f5a1b 1290
03984308 1291static rtx
ffbc8796 1292fixup_subreg_mem (rtx x)
03984308
BW
1293{
1294 if (GET_CODE (x) == SUBREG
1295 && GET_CODE (SUBREG_REG (x)) == REG
1296 && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER)
1297 {
1298 rtx temp =
1299 gen_rtx_SUBREG (GET_MODE (x),
f2034d06 1300 reg_equiv_mem (REGNO (SUBREG_REG (x))),
03984308 1301 SUBREG_BYTE (x));
55a2c322 1302 x = alter_subreg (&temp, true);
03984308
BW
1303 }
1304 return x;
1305}
1306
1307
997b8b4d
BW
1308/* Check if an incoming argument in a7 is expected to be used soon and
1309 if OPND is a register or register pair that includes a7. If so,
1310 create a new pseudo and copy a7 into that pseudo at the very
1311 beginning of the function, followed by the special "set_frame_ptr"
1312 unspec_volatile insn. The return value is either the original
1313 operand, if it is not a7, or the new pseudo containing a copy of
1314 the incoming argument. This is necessary because the register
1315 allocator will ignore conflicts with a7 and may either assign some
1316 other pseudo to a7 or use a7 as the hard_frame_pointer, clobbering
1317 the incoming argument in a7. By copying the argument out of a7 as
1318 the very first thing, and then immediately following that with an
1319 unspec_volatile to keep the scheduler away, we should avoid any
1320 problems. Putting the set_frame_ptr insn at the beginning, with
1321 only the a7 copy before it, also makes it easier for the prologue
1322 expander to initialize the frame pointer after the a7 copy and to
1323 fix up the a7 copy to use the stack pointer instead of the frame
1324 pointer. */
58db834b 1325
997b8b4d
BW
1326rtx
1327xtensa_copy_incoming_a7 (rtx opnd)
58db834b 1328{
997b8b4d
BW
1329 rtx entry_insns = 0;
1330 rtx reg, tmp;
ef4bddc2 1331 machine_mode mode;
997b8b4d
BW
1332
1333 if (!cfun->machine->need_a7_copy)
1334 return opnd;
1335
1336 /* This function should never be called again once a7 has been copied. */
177b6be0 1337 gcc_assert (!cfun->machine->set_frame_ptr_insn);
997b8b4d
BW
1338
1339 mode = GET_MODE (opnd);
1340
1341 /* The operand using a7 may come in a later instruction, so just return
1342 the original operand if it doesn't use a7. */
1343 reg = opnd;
1344 if (GET_CODE (reg) == SUBREG)
58db834b 1345 {
177b6be0 1346 gcc_assert (SUBREG_BYTE (reg) == 0);
997b8b4d
BW
1347 reg = SUBREG_REG (reg);
1348 }
1349 if (GET_CODE (reg) != REG
1350 || REGNO (reg) > A7_REG
a93072ca 1351 || REGNO (reg) + hard_regno_nregs (A7_REG, mode) <= A7_REG)
997b8b4d 1352 return opnd;
e6aecf8e 1353
997b8b4d 1354 /* 1-word args will always be in a7; 2-word args in a6/a7. */
a93072ca 1355 gcc_assert (REGNO (reg) + hard_regno_nregs (A7_REG, mode) - 1 == A7_REG);
58db834b 1356
997b8b4d 1357 cfun->machine->need_a7_copy = false;
58db834b 1358
997b8b4d
BW
1359 /* Copy a7 to a new pseudo at the function entry. Use gen_raw_REG to
1360 create the REG for a7 so that hard_frame_pointer_rtx is not used. */
58db834b 1361
0d8442b8 1362 start_sequence ();
997b8b4d 1363 tmp = gen_reg_rtx (mode);
58db834b 1364
997b8b4d
BW
1365 switch (mode)
1366 {
4e10a5a7
RS
1367 case E_DFmode:
1368 case E_DImode:
b412869c
BW
1369 /* Copy the value out of A7 here but keep the first word in A6 until
1370 after the set_frame_ptr insn. Otherwise, the register allocator
1371 may decide to put "subreg (tmp, 0)" in A7 and clobber the incoming
1372 value. */
997b8b4d
BW
1373 emit_insn (gen_movsi_internal (gen_rtx_SUBREG (SImode, tmp, 4),
1374 gen_raw_REG (SImode, A7_REG)));
1375 break;
4e10a5a7 1376 case E_SFmode:
997b8b4d
BW
1377 emit_insn (gen_movsf_internal (tmp, gen_raw_REG (mode, A7_REG)));
1378 break;
4e10a5a7 1379 case E_SImode:
997b8b4d
BW
1380 emit_insn (gen_movsi_internal (tmp, gen_raw_REG (mode, A7_REG)));
1381 break;
4e10a5a7 1382 case E_HImode:
997b8b4d
BW
1383 emit_insn (gen_movhi_internal (tmp, gen_raw_REG (mode, A7_REG)));
1384 break;
4e10a5a7 1385 case E_QImode:
997b8b4d
BW
1386 emit_insn (gen_movqi_internal (tmp, gen_raw_REG (mode, A7_REG)));
1387 break;
1388 default:
177b6be0 1389 gcc_unreachable ();
58db834b
BW
1390 }
1391
997b8b4d 1392 cfun->machine->set_frame_ptr_insn = emit_insn (gen_set_frame_ptr ());
b412869c
BW
1393
1394 /* For DF and DI mode arguments, copy the incoming value in A6 now. */
1395 if (mode == DFmode || mode == DImode)
1396 emit_insn (gen_movsi_internal (gen_rtx_SUBREG (SImode, tmp, 0),
1397 gen_rtx_REG (SImode, A7_REG - 1)));
997b8b4d
BW
1398 entry_insns = get_insns ();
1399 end_sequence ();
1400
1401 if (cfun->machine->vararg_a7)
1402 {
0d8442b8
BW
1403 /* This is called from within builtin_saveregs, which will insert the
1404 saveregs code at the function entry, ahead of anything placed at
1405 the function entry now. Instead, save the sequence to be inserted
1406 at the beginning of the saveregs code. */
1407 cfun->machine->vararg_a7_copy = entry_insns;
997b8b4d
BW
1408 }
1409 else
1410 {
1411 /* Put entry_insns after the NOTE that starts the function. If
1412 this is inside a start_sequence, make the outer-level insn
1413 chain current, so the code is placed at the start of the
1414 function. */
1415 push_topmost_sequence ();
0d8442b8
BW
1416 /* Do not use entry_of_function() here. This is called from within
1417 expand_function_start, when the CFG still holds GIMPLE. */
997b8b4d
BW
1418 emit_insn_after (entry_insns, get_insns ());
1419 pop_topmost_sequence ();
1420 }
1421
1422 return tmp;
58db834b
BW
1423}
1424
1425
a46bbb5a
BW
1426/* Try to expand a block move operation to a sequence of RTL move
1427 instructions. If not optimizing, or if the block size is not a
1428 constant, or if the block is too large, the expansion fails and GCC
1429 falls back to calling memcpy().
03984308
BW
1430
1431 operands[0] is the destination
1432 operands[1] is the source
1433 operands[2] is the length
1434 operands[3] is the alignment */
1435
1436int
ffbc8796 1437xtensa_expand_block_move (rtx *operands)
03984308 1438{
ef4bddc2 1439 static const machine_mode mode_from_align[] =
7eda7cda
RH
1440 {
1441 VOIDmode, QImode, HImode, VOIDmode, SImode,
1442 };
1443
1444 rtx dst_mem = operands[0];
1445 rtx src_mem = operands[1];
1446 HOST_WIDE_INT bytes, align;
03984308 1447 int num_pieces, move_ratio;
7eda7cda 1448 rtx temp[2];
ef4bddc2 1449 machine_mode mode[2];
7eda7cda
RH
1450 int amount[2];
1451 bool active[2];
1452 int phase = 0;
1453 int next;
1454 int offset_ld = 0;
1455 int offset_st = 0;
1456 rtx x;
03984308 1457
3bbc2af6 1458 /* If this is not a fixed size move, just call memcpy. */
03984308
BW
1459 if (!optimize || (GET_CODE (operands[2]) != CONST_INT))
1460 return 0;
1461
7eda7cda
RH
1462 bytes = INTVAL (operands[2]);
1463 align = INTVAL (operands[3]);
1464
3bbc2af6 1465 /* Anything to move? */
03984308 1466 if (bytes <= 0)
7eda7cda 1467 return 0;
03984308
BW
1468
1469 if (align > MOVE_MAX)
1470 align = MOVE_MAX;
1471
3bbc2af6 1472 /* Decide whether to expand inline based on the optimization level. */
03984308
BW
1473 move_ratio = 4;
1474 if (optimize > 2)
1475 move_ratio = LARGEST_MOVE_RATIO;
3397563a 1476 num_pieces = (bytes / align) + ((bytes % align + 1) / 2);
7eda7cda 1477 if (num_pieces > move_ratio)
03984308
BW
1478 return 0;
1479
7eda7cda
RH
1480 x = XEXP (dst_mem, 0);
1481 if (!REG_P (x))
1482 {
1483 x = force_reg (Pmode, x);
1484 dst_mem = replace_equiv_address (dst_mem, x);
1485 }
03984308 1486
7eda7cda
RH
1487 x = XEXP (src_mem, 0);
1488 if (!REG_P (x))
1489 {
1490 x = force_reg (Pmode, x);
1491 src_mem = replace_equiv_address (src_mem, x);
1492 }
03984308 1493
7eda7cda 1494 active[0] = active[1] = false;
03984308 1495
7eda7cda 1496 do
03984308 1497 {
7eda7cda
RH
1498 next = phase;
1499 phase ^= 1;
03984308 1500
7eda7cda 1501 if (bytes > 0)
03984308 1502 {
7eda7cda 1503 int next_amount;
03984308 1504
7eda7cda
RH
1505 next_amount = (bytes >= 4 ? 4 : (bytes >= 2 ? 2 : 1));
1506 next_amount = MIN (next_amount, align);
03984308 1507
7eda7cda
RH
1508 amount[next] = next_amount;
1509 mode[next] = mode_from_align[next_amount];
1510 temp[next] = gen_reg_rtx (mode[next]);
03984308 1511
7eda7cda 1512 x = adjust_address (src_mem, mode[next], offset_ld);
3397563a 1513 emit_move_insn (temp[next], x);
03984308 1514
7eda7cda
RH
1515 offset_ld += next_amount;
1516 bytes -= next_amount;
1517 active[next] = true;
1518 }
03984308 1519
7eda7cda
RH
1520 if (active[phase])
1521 {
1522 active[phase] = false;
3397563a 1523
7eda7cda 1524 x = adjust_address (dst_mem, mode[phase], offset_st);
3397563a 1525 emit_move_insn (x, temp[phase]);
03984308 1526
7eda7cda
RH
1527 offset_st += amount[phase];
1528 }
03984308 1529 }
7eda7cda 1530 while (active[next]);
03984308 1531
7eda7cda 1532 return 1;
03984308
BW
1533}
1534
1535
6454b4a8
TJJS
1536/* Try to expand a block set operation to a sequence of RTL move
1537 instructions. If not optimizing, or if the block size is not a
1538 constant, or if the block is too large, or if the value to
1539 initialize the block with is not a constant, the expansion
1540 fails and GCC falls back to calling memset().
1541
1542 operands[0] is the destination
1543 operands[1] is the length
1544 operands[2] is the initialization value
1545 operands[3] is the alignment */
1546
1547static int
1548xtensa_sizeof_MOVI (HOST_WIDE_INT imm)
1549{
1550 return (TARGET_DENSITY && IN_RANGE (imm, -32, 95)) ? 2 : 3;
1551}
1552
1553int
1554xtensa_expand_block_set_unrolled_loop (rtx *operands)
1555{
1556 rtx dst_mem = operands[0];
1557 HOST_WIDE_INT bytes, value, align;
1558 int expand_len, funccall_len;
1559 rtx x, reg;
1560 int offset;
1561
1562 if (!CONST_INT_P (operands[1]) || !CONST_INT_P (operands[2]))
1563 return 0;
1564
1565 bytes = INTVAL (operands[1]);
1566 if (bytes <= 0)
1567 return 0;
1568 value = (int8_t)INTVAL (operands[2]);
1569 align = INTVAL (operands[3]);
1570 if (align > MOVE_MAX)
1571 align = MOVE_MAX;
1572
1573 /* Insn expansion: holding the init value.
1574 Either MOV(.N) or L32R w/litpool. */
1575 if (align == 1)
1576 expand_len = xtensa_sizeof_MOVI (value);
1577 else if (value == 0 || value == -1)
1578 expand_len = TARGET_DENSITY ? 2 : 3;
1579 else
1580 expand_len = 3 + 4;
1581 /* Insn expansion: a series of aligned memory stores.
1582 Consist of S8I, S16I or S32I(.N). */
1583 expand_len += (bytes / align) * (TARGET_DENSITY
1584 && align == 4 ? 2 : 3);
1585 /* Insn expansion: the remainder, sub-aligned memory stores.
1586 A combination of S8I and S16I as needed. */
1587 expand_len += ((bytes % align + 1) / 2) * 3;
1588
1589 /* Function call: preparing two arguments. */
1590 funccall_len = xtensa_sizeof_MOVI (value);
1591 funccall_len += xtensa_sizeof_MOVI (bytes);
1592 /* Function call: calling memset(). */
1593 funccall_len += TARGET_LONGCALLS ? (3 + 4 + 3) : 3;
1594
1595 /* Apply expansion bonus (2x) if optimizing for speed. */
1596 if (optimize > 1 && !optimize_size)
1597 funccall_len *= 2;
1598
1599 /* Decide whether to expand or not, based on the sum of the length
1600 of instructions. */
1601 if (expand_len > funccall_len)
1602 return 0;
1603
1604 x = XEXP (dst_mem, 0);
1605 if (!REG_P (x))
1606 dst_mem = replace_equiv_address (dst_mem, force_reg (Pmode, x));
1607 switch (align)
1608 {
1609 case 1:
1610 break;
1611 case 2:
1612 value = (int16_t)((uint8_t)value * 0x0101U);
1613 break;
1614 case 4:
1615 value = (int32_t)((uint8_t)value * 0x01010101U);
1616 break;
1617 default:
1618 gcc_unreachable ();
1619 }
1620 reg = force_reg (SImode, GEN_INT (value));
1621
1622 offset = 0;
1623 do
1624 {
1625 int unit_size = MIN (bytes, align);
1626 machine_mode unit_mode = (unit_size >= 4 ? SImode :
1627 (unit_size >= 2 ? HImode :
1628 QImode));
1629 unit_size = GET_MODE_SIZE (unit_mode);
1630
1631 emit_move_insn (adjust_address (dst_mem, unit_mode, offset),
1632 unit_mode == SImode ? reg
1633 : convert_to_mode (unit_mode, reg, true));
1634
1635 offset += unit_size;
1636 bytes -= unit_size;
1637 }
1638 while (bytes > 0);
1639
1640 return 1;
1641}
1642
1643int
1644xtensa_expand_block_set_small_loop (rtx *operands)
1645{
fddf0e10 1646 HOST_WIDE_INT bytes, value, align, count;
6454b4a8
TJJS
1647 int expand_len, funccall_len;
1648 rtx x, dst, end, reg;
1649 machine_mode unit_mode;
1650 rtx_code_label *label;
1651
1652 if (!CONST_INT_P (operands[1]) || !CONST_INT_P (operands[2]))
1653 return 0;
1654
1655 bytes = INTVAL (operands[1]);
1656 if (bytes <= 0)
1657 return 0;
1658 value = (int8_t)INTVAL (operands[2]);
1659 align = INTVAL (operands[3]);
1660 if (align > MOVE_MAX)
1661 align = MOVE_MAX;
1662
1663 /* Totally-aligned block only. */
1664 if (bytes % align != 0)
1665 return 0;
fddf0e10 1666 count = bytes / align;
6454b4a8 1667
fddf0e10
TJJS
1668 /* If the Loop Option (zero-overhead looping) is configured and active,
1669 almost no restrictions about the length of the block. */
1670 if (! (TARGET_LOOPS && optimize))
1671 {
1672 /* If 4-byte aligned, small loop substitution is almost optimal,
1673 thus limited to only offset to the end address for ADDI/ADDMI
1674 instruction. */
1675 if (align == 4
75ab2f0e 1676 && ! (bytes <= 127 || xtensa_simm8x256 (bytes)))
fddf0e10 1677 return 0;
6454b4a8 1678
fddf0e10
TJJS
1679 /* If no 4-byte aligned, loop count should be treated as the
1680 constraint. */
1681 if (align != 4
1682 && count > ((optimize > 1 && !optimize_size) ? 8 : 15))
1683 return 0;
1684 }
6454b4a8
TJJS
1685
1686 /* Insn expansion: holding the init value.
1687 Either MOV(.N) or L32R w/litpool. */
1688 if (align == 1)
1689 expand_len = xtensa_sizeof_MOVI (value);
1690 else if (value == 0 || value == -1)
1691 expand_len = TARGET_DENSITY ? 2 : 3;
1692 else
1693 expand_len = 3 + 4;
fddf0e10
TJJS
1694 if (TARGET_LOOPS && optimize) /* zero-overhead looping */
1695 {
1696 /* Insn translation: Either MOV(.N) or L32R w/litpool for the
1697 loop count. */
1698 expand_len += xtensa_simm12b (count) ? xtensa_sizeof_MOVI (count)
1699 : 3 + 4;
1700 /* Insn translation: LOOP, the zero-overhead looping setup
1701 instruction. */
1702 expand_len += 3;
1703 /* Insn expansion: the loop body instructions.
1704 For store, one of S8I, S16I or S32I(.N).
1705 For advance, ADDI(.N). */
1706 expand_len += (TARGET_DENSITY && align == 4 ? 2 : 3)
1707 + (TARGET_DENSITY ? 2 : 3);
1708 }
1709 else /* NO zero-overhead looping */
1710 {
1711 /* Insn expansion: Either ADDI(.N) or ADDMI for the end address. */
1712 expand_len += bytes > 127 ? 3
1713 : (TARGET_DENSITY && bytes <= 15) ? 2 : 3;
1714 /* Insn expansion: the loop body and branch instruction.
1715 For store, one of S8I, S16I or S32I(.N).
1716 For advance, ADDI(.N).
1717 For branch, BNE. */
1718 expand_len += (TARGET_DENSITY && align == 4 ? 2 : 3)
1719 + (TARGET_DENSITY ? 2 : 3) + 3;
1720 }
6454b4a8
TJJS
1721
1722 /* Function call: preparing two arguments. */
1723 funccall_len = xtensa_sizeof_MOVI (value);
1724 funccall_len += xtensa_sizeof_MOVI (bytes);
1725 /* Function call: calling memset(). */
1726 funccall_len += TARGET_LONGCALLS ? (3 + 4 + 3) : 3;
1727
1728 /* Apply expansion bonus (2x) if optimizing for speed. */
1729 if (optimize > 1 && !optimize_size)
1730 funccall_len *= 2;
1731
1732 /* Decide whether to expand or not, based on the sum of the length
1733 of instructions. */
1734 if (expand_len > funccall_len)
1735 return 0;
1736
1737 x = XEXP (operands[0], 0);
1738 if (!REG_P (x))
1739 x = XEXP (replace_equiv_address (operands[0], force_reg (Pmode, x)), 0);
1740 dst = gen_reg_rtx (SImode);
1741 emit_move_insn (dst, x);
1742 end = gen_reg_rtx (SImode);
fddf0e10
TJJS
1743 if (TARGET_LOOPS && optimize)
1744 x = force_reg (SImode, operands[1] /* the length */);
1745 else
1746 x = operands[1];
1747 emit_insn (gen_addsi3 (end, dst, x));
6454b4a8
TJJS
1748 switch (align)
1749 {
1750 case 1:
1751 unit_mode = QImode;
1752 break;
1753 case 2:
1754 value = (int16_t)((uint8_t)value * 0x0101U);
1755 unit_mode = HImode;
1756 break;
1757 case 4:
1758 value = (int32_t)((uint8_t)value * 0x01010101U);
1759 unit_mode = SImode;
1760 break;
1761 default:
1762 gcc_unreachable ();
1763 }
1764 reg = force_reg (unit_mode, GEN_INT (value));
1765
1766 label = gen_label_rtx ();
1767 emit_label (label);
1768 emit_move_insn (gen_rtx_MEM (unit_mode, dst), reg);
1769 emit_insn (gen_addsi3 (dst, dst, GEN_INT (align)));
1770 emit_cmp_and_jump_insns (dst, end, NE, const0_rtx, SImode, true, label);
1771
1772 return 1;
1773}
1774
1775
03984308 1776void
ffbc8796 1777xtensa_expand_nonlocal_goto (rtx *operands)
03984308
BW
1778{
1779 rtx goto_handler = operands[1];
1780 rtx containing_fp = operands[3];
1781
3bbc2af6
KH
1782 /* Generate a call to "__xtensa_nonlocal_goto" (in libgcc); the code
1783 is too big to generate in-line. */
03984308
BW
1784
1785 if (GET_CODE (containing_fp) != REG)
1786 containing_fp = force_reg (Pmode, containing_fp);
1787
03984308 1788 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_nonlocal_goto"),
db69559b 1789 LCT_NORMAL, VOIDmode,
03984308
BW
1790 containing_fp, Pmode,
1791 goto_handler, Pmode);
1792}
1793
1794
e2500fed 1795static struct machine_function *
ffbc8796 1796xtensa_init_machine_status (void)
03984308 1797{
766090c2 1798 return ggc_cleared_alloc<machine_function> ();
03984308
BW
1799}
1800
1801
2a48b790
BW
1802/* Shift VAL of mode MODE left by COUNT bits. */
1803
1804static inline rtx
ef4bddc2 1805xtensa_expand_mask_and_shift (rtx val, machine_mode mode, rtx count)
2a48b790
BW
1806{
1807 val = expand_simple_binop (SImode, AND, val, GEN_INT (GET_MODE_MASK (mode)),
1808 NULL_RTX, 1, OPTAB_DIRECT);
1809 return expand_simple_binop (SImode, ASHIFT, val, count,
1810 NULL_RTX, 1, OPTAB_DIRECT);
1811}
1812
1813
1814/* Structure to hold the initial parameters for a compare_and_swap operation
1815 in HImode and QImode. */
1816
1817struct alignment_context
1818{
1819 rtx memsi; /* SI aligned memory location. */
1820 rtx shift; /* Bit offset with regard to lsb. */
1821 rtx modemask; /* Mask of the HQImode shifted by SHIFT bits. */
1822 rtx modemaski; /* ~modemask */
1823};
1824
1825
1826/* Initialize structure AC for word access to HI and QI mode memory. */
1827
1828static void
1829init_alignment_context (struct alignment_context *ac, rtx mem)
1830{
ef4bddc2 1831 machine_mode mode = GET_MODE (mem);
2a48b790
BW
1832 rtx byteoffset = NULL_RTX;
1833 bool aligned = (MEM_ALIGN (mem) >= GET_MODE_BITSIZE (SImode));
1834
1835 if (aligned)
1836 ac->memsi = adjust_address (mem, SImode, 0); /* Memory is aligned. */
1837 else
1838 {
1839 /* Alignment is unknown. */
1840 rtx addr, align;
1841
1842 /* Force the address into a register. */
1843 addr = force_reg (Pmode, XEXP (mem, 0));
1844
1845 /* Align it to SImode. */
1846 align = expand_simple_binop (Pmode, AND, addr,
1847 GEN_INT (-GET_MODE_SIZE (SImode)),
1848 NULL_RTX, 1, OPTAB_DIRECT);
1849 /* Generate MEM. */
1850 ac->memsi = gen_rtx_MEM (SImode, align);
1851 MEM_VOLATILE_P (ac->memsi) = MEM_VOLATILE_P (mem);
1852 set_mem_alias_set (ac->memsi, ALIAS_SET_MEMORY_BARRIER);
1853 set_mem_align (ac->memsi, GET_MODE_BITSIZE (SImode));
1854
1855 byteoffset = expand_simple_binop (Pmode, AND, addr,
1856 GEN_INT (GET_MODE_SIZE (SImode) - 1),
1857 NULL_RTX, 1, OPTAB_DIRECT);
1858 }
1859
1860 /* Calculate shiftcount. */
1861 if (TARGET_BIG_ENDIAN)
1862 {
1863 ac->shift = GEN_INT (GET_MODE_SIZE (SImode) - GET_MODE_SIZE (mode));
1864 if (!aligned)
1865 ac->shift = expand_simple_binop (SImode, MINUS, ac->shift, byteoffset,
1866 NULL_RTX, 1, OPTAB_DIRECT);
1867 }
1868 else
1869 {
1870 if (aligned)
1871 ac->shift = NULL_RTX;
1872 else
1873 ac->shift = byteoffset;
1874 }
1875
1876 if (ac->shift != NULL_RTX)
1877 {
1878 /* Shift is the byte count, but we need the bitcount. */
91767ed1
MF
1879 gcc_assert (exact_log2 (BITS_PER_UNIT) >= 0);
1880 ac->shift = expand_simple_binop (SImode, ASHIFT, ac->shift,
1881 GEN_INT (exact_log2 (BITS_PER_UNIT)),
2a48b790
BW
1882 NULL_RTX, 1, OPTAB_DIRECT);
1883 ac->modemask = expand_simple_binop (SImode, ASHIFT,
1884 GEN_INT (GET_MODE_MASK (mode)),
1885 ac->shift,
1886 NULL_RTX, 1, OPTAB_DIRECT);
1887 }
1888 else
1889 ac->modemask = GEN_INT (GET_MODE_MASK (mode));
1890
1891 ac->modemaski = expand_simple_unop (SImode, NOT, ac->modemask, NULL_RTX, 1);
1892}
1893
1894
1895/* Expand an atomic compare and swap operation for HImode and QImode.
1896 MEM is the memory location, CMP the old value to compare MEM with
0a2aaacc 1897 and NEW_RTX the value to set if CMP == MEM. */
2a48b790
BW
1898
1899void
0a2aaacc 1900xtensa_expand_compare_and_swap (rtx target, rtx mem, rtx cmp, rtx new_rtx)
2a48b790 1901{
ef4bddc2 1902 machine_mode mode = GET_MODE (mem);
2a48b790
BW
1903 struct alignment_context ac;
1904 rtx tmp, cmpv, newv, val;
1905 rtx oldval = gen_reg_rtx (SImode);
1906 rtx res = gen_reg_rtx (SImode);
240a513f
DM
1907 rtx_code_label *csloop = gen_label_rtx ();
1908 rtx_code_label *csend = gen_label_rtx ();
2a48b790
BW
1909
1910 init_alignment_context (&ac, mem);
1911
1912 if (ac.shift != NULL_RTX)
1913 {
1914 cmp = xtensa_expand_mask_and_shift (cmp, mode, ac.shift);
0a2aaacc 1915 new_rtx = xtensa_expand_mask_and_shift (new_rtx, mode, ac.shift);
2a48b790
BW
1916 }
1917
1918 /* Load the surrounding word into VAL with the MEM value masked out. */
1919 val = force_reg (SImode, expand_simple_binop (SImode, AND, ac.memsi,
1920 ac.modemaski, NULL_RTX, 1,
1921 OPTAB_DIRECT));
1922 emit_label (csloop);
1923
0a2aaacc 1924 /* Patch CMP and NEW_RTX into VAL at correct position. */
2a48b790
BW
1925 cmpv = force_reg (SImode, expand_simple_binop (SImode, IOR, cmp, val,
1926 NULL_RTX, 1, OPTAB_DIRECT));
0a2aaacc 1927 newv = force_reg (SImode, expand_simple_binop (SImode, IOR, new_rtx, val,
2a48b790
BW
1928 NULL_RTX, 1, OPTAB_DIRECT));
1929
1930 /* Jump to end if we're done. */
1931 emit_insn (gen_sync_compare_and_swapsi (res, ac.memsi, cmpv, newv));
1932 emit_cmp_and_jump_insns (res, cmpv, EQ, const0_rtx, SImode, true, csend);
1933
1934 /* Check for changes outside mode. */
1935 emit_move_insn (oldval, val);
1936 tmp = expand_simple_binop (SImode, AND, res, ac.modemaski,
1937 val, 1, OPTAB_DIRECT);
1938 if (tmp != val)
1939 emit_move_insn (val, tmp);
1940
1941 /* Loop internal if so. */
1942 emit_cmp_and_jump_insns (oldval, val, NE, const0_rtx, SImode, true, csloop);
1943
1944 emit_label (csend);
1945
1946 /* Return the correct part of the bitfield. */
1947 convert_move (target,
1948 (ac.shift == NULL_RTX ? res
1949 : expand_simple_binop (SImode, LSHIFTRT, res, ac.shift,
1950 NULL_RTX, 1, OPTAB_DIRECT)),
1951 1);
1952}
1953
1954
1955/* Expand an atomic operation CODE of mode MODE (either HImode or QImode --
1956 the default expansion works fine for SImode). MEM is the memory location
1957 and VAL the value to play with. If AFTER is true then store the value
1958 MEM holds after the operation, if AFTER is false then store the value MEM
1959 holds before the operation. If TARGET is zero then discard that value, else
1960 store it to TARGET. */
1961
1962void
1963xtensa_expand_atomic (enum rtx_code code, rtx target, rtx mem, rtx val,
1964 bool after)
1965{
ef4bddc2 1966 machine_mode mode = GET_MODE (mem);
2a48b790 1967 struct alignment_context ac;
240a513f 1968 rtx_code_label *csloop = gen_label_rtx ();
2a48b790
BW
1969 rtx cmp, tmp;
1970 rtx old = gen_reg_rtx (SImode);
0a2aaacc 1971 rtx new_rtx = gen_reg_rtx (SImode);
2a48b790
BW
1972 rtx orig = NULL_RTX;
1973
1974 init_alignment_context (&ac, mem);
1975
1976 /* Prepare values before the compare-and-swap loop. */
1977 if (ac.shift != NULL_RTX)
1978 val = xtensa_expand_mask_and_shift (val, mode, ac.shift);
1979 switch (code)
1980 {
1981 case PLUS:
1982 case MINUS:
1983 orig = gen_reg_rtx (SImode);
1984 convert_move (orig, val, 1);
1985 break;
1986
1987 case SET:
1988 case IOR:
1989 case XOR:
1990 break;
1991
1992 case MULT: /* NAND */
1993 case AND:
1994 /* val = "11..1<val>11..1" */
1995 val = expand_simple_binop (SImode, XOR, val, ac.modemaski,
1996 NULL_RTX, 1, OPTAB_DIRECT);
1997 break;
1998
1999 default:
2000 gcc_unreachable ();
2001 }
2002
2003 /* Load full word. Subsequent loads are performed by S32C1I. */
2004 cmp = force_reg (SImode, ac.memsi);
2005
2006 emit_label (csloop);
2007 emit_move_insn (old, cmp);
2008
2009 switch (code)
2010 {
2011 case PLUS:
2012 case MINUS:
2013 val = expand_simple_binop (SImode, code, old, orig,
2014 NULL_RTX, 1, OPTAB_DIRECT);
2015 val = expand_simple_binop (SImode, AND, val, ac.modemask,
2016 NULL_RTX, 1, OPTAB_DIRECT);
2017 /* FALLTHRU */
2018 case SET:
2019 tmp = expand_simple_binop (SImode, AND, old, ac.modemaski,
2020 NULL_RTX, 1, OPTAB_DIRECT);
2021 tmp = expand_simple_binop (SImode, IOR, tmp, val,
0a2aaacc 2022 new_rtx, 1, OPTAB_DIRECT);
2a48b790
BW
2023 break;
2024
2025 case AND:
2026 case IOR:
2027 case XOR:
2028 tmp = expand_simple_binop (SImode, code, old, val,
0a2aaacc 2029 new_rtx, 1, OPTAB_DIRECT);
2a48b790
BW
2030 break;
2031
2032 case MULT: /* NAND */
2a17b239 2033 tmp = expand_simple_binop (SImode, AND, old, val,
2a48b790 2034 NULL_RTX, 1, OPTAB_DIRECT);
2a17b239 2035 tmp = expand_simple_binop (SImode, XOR, tmp, ac.modemask,
0a2aaacc 2036 new_rtx, 1, OPTAB_DIRECT);
2a48b790
BW
2037 break;
2038
2039 default:
2040 gcc_unreachable ();
2041 }
2042
0a2aaacc
KG
2043 if (tmp != new_rtx)
2044 emit_move_insn (new_rtx, tmp);
2045 emit_insn (gen_sync_compare_and_swapsi (cmp, ac.memsi, old, new_rtx));
2a48b790
BW
2046 emit_cmp_and_jump_insns (cmp, old, NE, const0_rtx, SImode, true, csloop);
2047
2048 if (target)
2049 {
0a2aaacc 2050 tmp = (after ? new_rtx : cmp);
2a48b790
BW
2051 convert_move (target,
2052 (ac.shift == NULL_RTX ? tmp
2053 : expand_simple_binop (SImode, LSHIFTRT, tmp, ac.shift,
2054 NULL_RTX, 1, OPTAB_DIRECT)),
2055 1);
2056 }
2057}
2058
2059
03984308 2060void
ffbc8796 2061xtensa_setup_frame_addresses (void)
03984308 2062{
b52b1749 2063 /* Set flag to cause TARGET_FRAME_POINTER_REQUIRED to return true. */
03984308
BW
2064 cfun->machine->accesses_prev_frame = 1;
2065
590e2636
MF
2066 if (TARGET_WINDOWED_ABI)
2067 emit_library_call
2068 (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_libgcc_window_spill"),
db69559b 2069 LCT_NORMAL, VOIDmode);
03984308
BW
2070}
2071
2072
638db43e
BW
2073/* Emit the assembly for the end of a zero-cost loop. Normally we just emit
2074 a comment showing where the end of the loop is. However, if there is a
03984308 2075 label or a branch at the end of the loop then we need to place a nop
638db43e 2076 there. If the loop ends with a label we need the nop so that branches
839a4992
KH
2077 targeting that label will target the nop (and thus remain in the loop),
2078 instead of targeting the instruction after the loop (and thus exiting
638db43e 2079 the loop). If the loop ends with a branch, we need the nop in case the
839a4992 2080 branch is targeting a location inside the loop. When the branch
03984308
BW
2081 executes it will cause the loop count to be decremented even if it is
2082 taken (because it is the last instruction in the loop), so we need to
2083 nop after the branch to prevent the loop count from being decremented
638db43e 2084 when the branch is taken. */
03984308
BW
2085
2086void
240a513f 2087xtensa_emit_loop_end (rtx_insn *insn, rtx *operands)
03984308
BW
2088{
2089 char done = 0;
2090
2091 for (insn = PREV_INSN (insn); insn && !done; insn = PREV_INSN (insn))
2092 {
2093 switch (GET_CODE (insn))
2094 {
2095 case NOTE:
2096 case BARRIER:
2097 break;
2098
2099 case CODE_LABEL:
0bd0703d 2100 output_asm_insn (TARGET_DENSITY ? "nop.n" : "nop", operands);
03984308
BW
2101 done = 1;
2102 break;
2103
2104 default:
2105 {
2106 rtx body = PATTERN (insn);
2107
b64925dc 2108 if (JUMP_P (body))
03984308 2109 {
0bd0703d 2110 output_asm_insn (TARGET_DENSITY ? "nop.n" : "nop", operands);
03984308
BW
2111 done = 1;
2112 }
2113 else if ((GET_CODE (body) != USE)
2114 && (GET_CODE (body) != CLOBBER))
2115 done = 1;
2116 }
2117 break;
89d5982b 2118 }
03984308
BW
2119 }
2120
6383386a 2121 output_asm_insn ("%1_LEND:", operands);
03984308
BW
2122}
2123
2124
036a2b7a 2125char *
e1b193c1 2126xtensa_emit_branch (bool immed, rtx *operands)
036a2b7a
BW
2127{
2128 static char result[64];
e1b193c1 2129 enum rtx_code code = GET_CODE (operands[3]);
036a2b7a
BW
2130 const char *op;
2131
036a2b7a
BW
2132 switch (code)
2133 {
e1b193c1
TJJS
2134 case EQ: op = "eq"; break;
2135 case NE: op = "ne"; break;
2136 case LT: op = "lt"; break;
2137 case GE: op = "ge"; break;
2138 case LTU: op = "ltu"; break;
2139 case GEU: op = "geu"; break;
036a2b7a
BW
2140 default: gcc_unreachable ();
2141 }
2142
2143 if (immed)
2144 {
2145 if (INTVAL (operands[1]) == 0)
2146 sprintf (result, "b%sz%s\t%%0, %%2", op,
2147 (TARGET_DENSITY && (code == EQ || code == NE)) ? ".n" : "");
2148 else
2149 sprintf (result, "b%si\t%%0, %%d1, %%2", op);
2150 }
2151 else
2152 sprintf (result, "b%s\t%%0, %%1, %%2", op);
2153
2154 return result;
2155}
2156
2157
036a2b7a
BW
2158char *
2159xtensa_emit_movcc (bool inverted, bool isfp, bool isbool, rtx *operands)
2160{
2161 static char result[64];
2162 enum rtx_code code;
2163 const char *op;
2164
2165 code = GET_CODE (operands[4]);
e1b193c1
TJJS
2166 if (inverted)
2167 code = reverse_condition (code);
036a2b7a
BW
2168 if (isbool)
2169 {
2170 switch (code)
2171 {
e1b193c1
TJJS
2172 case EQ: op = "f"; break;
2173 case NE: op = "t"; break;
036a2b7a
BW
2174 default: gcc_unreachable ();
2175 }
2176 }
2177 else
2178 {
2179 switch (code)
2180 {
e1b193c1
TJJS
2181 case EQ: op = "eqz"; break;
2182 case NE: op = "nez"; break;
2183 case LT: op = "ltz"; break;
2184 case GE: op = "gez"; break;
036a2b7a
BW
2185 default: gcc_unreachable ();
2186 }
2187 }
2188
2189 sprintf (result, "mov%s%s\t%%0, %%%d, %%1",
2190 op, isfp ? ".s" : "", inverted ? 3 : 2);
2191 return result;
2192}
2193
2194
43b0c56f
TJJS
2195void
2196xtensa_prepare_expand_call (int callop, rtx *operands)
2197{
2198 rtx addr = XEXP (operands[callop], 0);
2199
2200 if (flag_pic && SYMBOL_REF_P (addr)
2201 && (!SYMBOL_REF_LOCAL_P (addr) || SYMBOL_REF_EXTERNAL_P (addr)))
2202 addr = gen_sym_PLT (addr);
2203
2204 if (!call_insn_operand (addr, VOIDmode))
0bf60f68
MF
2205 {
2206 /* This may be called while generating MI thunk when we pretend
2207 that reload is over. Use a8 as a temporary register in that case. */
2208 rtx reg = can_create_pseudo_p ()
2209 ? copy_to_mode_reg (Pmode, addr)
2210 : copy_to_suggested_reg (addr,
2211 gen_rtx_REG (Pmode, A8_REG),
2212 Pmode);
2213 XEXP (operands[callop], 0) = reg;
2214 }
43b0c56f
TJJS
2215}
2216
2217
03984308 2218char *
ffbc8796 2219xtensa_emit_call (int callop, rtx *operands)
03984308 2220{
b64a1b53 2221 static char result[64];
03984308
BW
2222 rtx tgt = operands[callop];
2223
2224 if (GET_CODE (tgt) == CONST_INT)
3904010d
MF
2225 sprintf (result, "call%d\t" HOST_WIDE_INT_PRINT_HEX,
2226 WINDOW_SIZE, INTVAL (tgt));
03984308 2227 else if (register_operand (tgt, VOIDmode))
590e2636 2228 sprintf (result, "callx%d\t%%%d", WINDOW_SIZE, callop);
03984308 2229 else
590e2636 2230 sprintf (result, "call%d\t%%%d", WINDOW_SIZE, callop);
03984308
BW
2231
2232 return result;
2233}
2234
2235
43b0c56f
TJJS
2236char *
2237xtensa_emit_sibcall (int callop, rtx *operands)
2238{
2239 static char result[64];
2240 rtx tgt = operands[callop];
2241
75ab2f0e 2242 if (CONST_INT_P (tgt))
43b0c56f
TJJS
2243 sprintf (result, "j.l\t" HOST_WIDE_INT_PRINT_HEX ", a9",
2244 INTVAL (tgt));
2245 else if (register_operand (tgt, VOIDmode))
2246 sprintf (result, "jx\t%%%d", callop);
2247 else
2248 sprintf (result, "j.l\t%%%d, a9", callop);
2249
2250 return result;
2251}
2252
2253
da1f39e4 2254bool
ef4bddc2 2255xtensa_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
da1f39e4
BW
2256{
2257 /* Allow constant pool addresses. */
2258 if (mode != BLKmode && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
6a7a462c
BW
2259 && ! TARGET_CONST16 && constantpool_address_p (addr)
2260 && ! xtensa_tls_referenced_p (addr))
da1f39e4
BW
2261 return true;
2262
2263 while (GET_CODE (addr) == SUBREG)
2264 addr = SUBREG_REG (addr);
2265
2266 /* Allow base registers. */
2267 if (GET_CODE (addr) == REG && BASE_REG_P (addr, strict))
2268 return true;
2269
2270 /* Check for "register + offset" addressing. */
2271 if (GET_CODE (addr) == PLUS)
2272 {
2273 rtx xplus0 = XEXP (addr, 0);
2274 rtx xplus1 = XEXP (addr, 1);
2275 enum rtx_code code0;
2276 enum rtx_code code1;
2277
2278 while (GET_CODE (xplus0) == SUBREG)
2279 xplus0 = SUBREG_REG (xplus0);
2280 code0 = GET_CODE (xplus0);
2281
2282 while (GET_CODE (xplus1) == SUBREG)
2283 xplus1 = SUBREG_REG (xplus1);
2284 code1 = GET_CODE (xplus1);
2285
2286 /* Swap operands if necessary so the register is first. */
2287 if (code0 != REG && code1 == REG)
2288 {
2289 xplus0 = XEXP (addr, 1);
2290 xplus1 = XEXP (addr, 0);
2291 code0 = GET_CODE (xplus0);
2292 code1 = GET_CODE (xplus1);
2293 }
2294
2295 if (code0 == REG && BASE_REG_P (xplus0, strict)
2296 && code1 == CONST_INT
2297 && xtensa_mem_offset (INTVAL (xplus1), mode))
2298 return true;
2299 }
2300
2301 return false;
2302}
2303
2304
6a7a462c
BW
2305/* Construct the SYMBOL_REF for the _TLS_MODULE_BASE_ symbol. */
2306
2307static GTY(()) rtx xtensa_tls_module_base_symbol;
2308
2309static rtx
2310xtensa_tls_module_base (void)
2311{
2312 if (! xtensa_tls_module_base_symbol)
2313 {
2314 xtensa_tls_module_base_symbol =
2315 gen_rtx_SYMBOL_REF (Pmode, "_TLS_MODULE_BASE_");
2316 SYMBOL_REF_FLAGS (xtensa_tls_module_base_symbol)
89d5982b 2317 |= TLS_MODEL_GLOBAL_DYNAMIC << SYMBOL_FLAG_TLS_SHIFT;
6a7a462c
BW
2318 }
2319
2320 return xtensa_tls_module_base_symbol;
2321}
2322
2323
240a513f 2324static rtx_insn *
6a7a462c
BW
2325xtensa_call_tls_desc (rtx sym, rtx *retp)
2326{
e1b8828b 2327 rtx fn, arg, a_io;
240a513f 2328 rtx_insn *call_insn, *insns;
6a7a462c
BW
2329
2330 start_sequence ();
2331 fn = gen_reg_rtx (Pmode);
2332 arg = gen_reg_rtx (Pmode);
e1b8828b 2333 a_io = gen_rtx_REG (Pmode, WINDOW_SIZE + 2);
6a7a462c
BW
2334
2335 emit_insn (gen_tls_func (fn, sym));
2336 emit_insn (gen_tls_arg (arg, sym));
e1b8828b
MF
2337 emit_move_insn (a_io, arg);
2338 call_insn = emit_call_insn (gen_tls_call (a_io, fn, sym, const1_rtx));
2339 use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), a_io);
6a7a462c
BW
2340 insns = get_insns ();
2341 end_sequence ();
2342
e1b8828b 2343 *retp = a_io;
6a7a462c
BW
2344 return insns;
2345}
2346
2347
2348static rtx
2349xtensa_legitimize_tls_address (rtx x)
2350{
2351 unsigned int model = SYMBOL_REF_TLS_MODEL (x);
240a513f
DM
2352 rtx dest, tp, ret, modbase, base, addend;
2353 rtx_insn *insns;
6a7a462c
BW
2354
2355 dest = gen_reg_rtx (Pmode);
2356 switch (model)
2357 {
2358 case TLS_MODEL_GLOBAL_DYNAMIC:
2359 insns = xtensa_call_tls_desc (x, &ret);
2360 emit_libcall_block (insns, dest, ret, x);
2361 break;
2362
2363 case TLS_MODEL_LOCAL_DYNAMIC:
2364 base = gen_reg_rtx (Pmode);
2365 modbase = xtensa_tls_module_base ();
2366 insns = xtensa_call_tls_desc (modbase, &ret);
2367 emit_libcall_block (insns, base, ret, modbase);
2368 addend = force_reg (SImode, gen_sym_DTPOFF (x));
2369 emit_insn (gen_addsi3 (dest, base, addend));
2370 break;
2371
2372 case TLS_MODEL_INITIAL_EXEC:
2373 case TLS_MODEL_LOCAL_EXEC:
2374 tp = gen_reg_rtx (SImode);
f959607b 2375 emit_insn (gen_get_thread_pointersi (tp));
6a7a462c
BW
2376 addend = force_reg (SImode, gen_sym_TPOFF (x));
2377 emit_insn (gen_addsi3 (dest, tp, addend));
2378 break;
2379
2380 default:
2381 gcc_unreachable ();
2382 }
2383
2384 return dest;
2385}
2386
2387
da1f39e4
BW
2388rtx
2389xtensa_legitimize_address (rtx x,
2390 rtx oldx ATTRIBUTE_UNUSED,
ef4bddc2 2391 machine_mode mode)
da1f39e4 2392{
6a7a462c
BW
2393 if (xtensa_tls_symbol_p (x))
2394 return xtensa_legitimize_tls_address (x);
2395
da1f39e4
BW
2396 if (GET_CODE (x) == PLUS)
2397 {
2398 rtx plus0 = XEXP (x, 0);
2399 rtx plus1 = XEXP (x, 1);
2400
2401 if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG)
2402 {
2403 plus0 = XEXP (x, 1);
2404 plus1 = XEXP (x, 0);
2405 }
2406
2407 /* Try to split up the offset to use an ADDMI instruction. */
2408 if (GET_CODE (plus0) == REG
2409 && GET_CODE (plus1) == CONST_INT
2410 && !xtensa_mem_offset (INTVAL (plus1), mode)
2411 && !xtensa_simm8 (INTVAL (plus1))
2412 && xtensa_mem_offset (INTVAL (plus1) & 0xff, mode)
2413 && xtensa_simm8x256 (INTVAL (plus1) & ~0xff))
2414 {
2415 rtx temp = gen_reg_rtx (Pmode);
2416 rtx addmi_offset = GEN_INT (INTVAL (plus1) & ~0xff);
f7df4a84
RS
2417 emit_insn (gen_rtx_SET (temp, gen_rtx_PLUS (Pmode, plus0,
2418 addmi_offset)));
da1f39e4
BW
2419 return gen_rtx_PLUS (Pmode, temp, GEN_INT (INTVAL (plus1) & 0xff));
2420 }
2421 }
2422
506d7b68 2423 return x;
da1f39e4
BW
2424}
2425
a1a79768
AS
2426/* Worker function for TARGET_MODE_DEPENDENT_ADDRESS_P.
2427
2428 Treat constant-pool references as "mode dependent" since they can
2429 only be accessed with SImode loads. This works around a bug in the
2430 combiner where a constant pool reference is temporarily converted
2431 to an HImode load, which is then assumed to zero-extend based on
2432 our definition of LOAD_EXTEND_OP. This is wrong because the high
2433 bits of a 16-bit value in the constant pool are now sign-extended
2434 by default. */
2435
2436static bool
5bfed9a9
GJL
2437xtensa_mode_dependent_address_p (const_rtx addr,
2438 addr_space_t as ATTRIBUTE_UNUSED)
a1a79768
AS
2439{
2440 return constantpool_address_p (addr);
2441}
da1f39e4 2442
6a7a462c
BW
2443/* Return TRUE if X contains any TLS symbol references. */
2444
2445bool
2446xtensa_tls_referenced_p (rtx x)
2447{
e46dad5d 2448 if (! targetm.have_tls)
6a7a462c
BW
2449 return false;
2450
2f36a994
RS
2451 subrtx_iterator::array_type array;
2452 FOR_EACH_SUBRTX (iter, array, x, ALL)
2453 {
2454 const_rtx x = *iter;
2455 if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0)
2456 return true;
2457
2458 /* Ignore TLS references that have already been legitimized. */
2459 if (GET_CODE (x) == UNSPEC)
2460 switch (XINT (x, 1))
2461 {
2462 case UNSPEC_TPOFF:
2463 case UNSPEC_DTPOFF:
2464 case UNSPEC_TLS_FUNC:
2465 case UNSPEC_TLS_ARG:
2466 case UNSPEC_TLS_CALL:
2467 iter.skip_subrtxes ();
2468 break;
2469 default:
2470 break;
2471 }
2472 }
2473 return false;
6a7a462c
BW
2474}
2475
2476
1c68ec1f
TJJS
2477/* Helper function for "*shlrd_..." patterns. */
2478
2479enum rtx_code
2480xtensa_shlrd_which_direction (rtx op0, rtx op1)
2481{
2482 if (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
2483 return ASHIFT; /* shld */
2484 if (GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
2485 return LSHIFTRT; /* shrd */
2486
2487 return UNKNOWN;
2488}
2489
2490
4f3f0296
TJJS
2491/* Return true after "split1" pass has been finished. */
2492
2493bool
2494xtensa_split1_finished_p (void)
2495{
2496 return cfun && (cfun->curr_properties & PROP_rtl_split_insns);
2497}
2498
2499
2500/* Split a DImode pair of reg (operand[0]) and const_int (operand[1]) into
2501 two SImode pairs, the low-part (operands[0] and [1]) and the high-part
2502 (operands[2] and [3]). */
2503
2504void
2505xtensa_split_DI_reg_imm (rtx *operands)
2506{
2507 rtx lowpart, highpart;
2508
2509 if (WORDS_BIG_ENDIAN)
2510 split_double (operands[1], &highpart, &lowpart);
2511 else
2512 split_double (operands[1], &lowpart, &highpart);
2513
2514 operands[3] = highpart;
2515 operands[2] = gen_highpart (SImode, operands[0]);
2516 operands[1] = lowpart;
2517 operands[0] = gen_lowpart (SImode, operands[0]);
2518}
2519
2520
fbbf66e7
RS
2521/* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
2522
2523static bool
ef4bddc2 2524xtensa_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
fbbf66e7
RS
2525{
2526 return xtensa_tls_referenced_p (x);
2527}
2528
2529
b0c6e48f 2530/* Return the debugger register number to use for 'regno'. */
03984308
BW
2531
2532int
ca60bd93 2533xtensa_debugger_regno (int regno)
03984308
BW
2534{
2535 int first = -1;
633e4eb4
BW
2536
2537 if (GP_REG_P (regno))
2538 {
2539 regno -= GP_REG_FIRST;
2540 first = 0;
2541 }
2542 else if (BR_REG_P (regno))
2543 {
2544 regno -= BR_REG_FIRST;
2545 first = 16;
2546 }
2547 else if (FP_REG_P (regno))
2548 {
2549 regno -= FP_REG_FIRST;
b0c6e48f 2550 first = 48;
633e4eb4 2551 }
03984308
BW
2552 else if (ACC_REG_P (regno))
2553 {
b0c6e48f
BW
2554 first = 0x200; /* Start of Xtensa special registers. */
2555 regno = 16; /* ACCLO is special register 16. */
03984308
BW
2556 }
2557
2558 /* When optimizing, we sometimes get asked about pseudo-registers
638db43e 2559 that don't represent hard registers. Return 0 for these. */
03984308
BW
2560 if (first == -1)
2561 return 0;
2562
2563 return first + regno;
2564}
2565
2566
2567/* Argument support functions. */
2568
2569/* Initialize CUMULATIVE_ARGS for a function. */
2570
2571void
997b8b4d 2572init_cumulative_args (CUMULATIVE_ARGS *cum, int incoming)
03984308
BW
2573{
2574 cum->arg_words = 0;
997b8b4d 2575 cum->incoming = incoming;
03984308
BW
2576}
2577
ffbc8796 2578
03984308
BW
2579/* Advance the argument to the next argument position. */
2580
626a4b31 2581static void
6930c98c
RS
2582xtensa_function_arg_advance (cumulative_args_t cum,
2583 const function_arg_info &arg)
03984308
BW
2584{
2585 int words, max;
2586 int *arg_words;
2587
d5cc9181 2588 arg_words = &get_cumulative_args (cum)->arg_words;
03984308
BW
2589 max = MAX_ARGS_IN_REGISTERS;
2590
6930c98c
RS
2591 words = ((arg.promoted_size_in_bytes () + UNITS_PER_WORD - 1)
2592 / UNITS_PER_WORD);
03984308 2593
85d91d5b 2594 if (*arg_words < max
0ffef200 2595 && (targetm.calls.must_pass_in_stack (arg)
85d91d5b 2596 || *arg_words + words > max))
03984308
BW
2597 *arg_words = max;
2598
2599 *arg_words += words;
2600}
2601
2602
6783fdb7 2603/* Return an RTL expression containing the register for the given argument,
368ebcd6 2604 or 0 if the argument is to be passed on the stack. INCOMING_P is nonzero
ffbc8796 2605 if this is an incoming argument to the current function. */
03984308 2606
626a4b31 2607static rtx
6783fdb7
RS
2608xtensa_function_arg_1 (cumulative_args_t cum_v, const function_arg_info &arg,
2609 bool incoming_p)
03984308 2610{
d5cc9181 2611 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
03984308
BW
2612 int regbase, words, max;
2613 int *arg_words;
2614 int regno;
03984308
BW
2615
2616 arg_words = &cum->arg_words;
2617 regbase = (incoming_p ? GP_ARG_FIRST : GP_OUTGOING_ARG_FIRST);
2618 max = MAX_ARGS_IN_REGISTERS;
2619
6783fdb7
RS
2620 words = ((arg.promoted_size_in_bytes () + UNITS_PER_WORD - 1)
2621 / UNITS_PER_WORD);
03984308 2622
6783fdb7 2623 if (arg.type && (TYPE_ALIGN (arg.type) > BITS_PER_WORD))
822e895c 2624 {
6783fdb7 2625 int align = MIN (TYPE_ALIGN (arg.type), STACK_BOUNDARY) / BITS_PER_WORD;
822e895c
BW
2626 *arg_words = (*arg_words + align - 1) & -align;
2627 }
03984308
BW
2628
2629 if (*arg_words + words > max)
2630 return (rtx)0;
2631
2632 regno = regbase + *arg_words;
03984308 2633
997b8b4d 2634 if (cum->incoming && regno <= A7_REG && regno + words > A7_REG)
590e2636 2635 cfun->machine->need_a7_copy = TARGET_WINDOWED_ABI;
03984308 2636
6783fdb7 2637 return gen_rtx_REG (arg.mode, regno);
03984308
BW
2638}
2639
626a4b31
NF
2640/* Implement TARGET_FUNCTION_ARG. */
2641
2642static rtx
6783fdb7 2643xtensa_function_arg (cumulative_args_t cum, const function_arg_info &arg)
626a4b31 2644{
6783fdb7 2645 return xtensa_function_arg_1 (cum, arg, false);
626a4b31
NF
2646}
2647
2648/* Implement TARGET_FUNCTION_INCOMING_ARG. */
2649
2650static rtx
6783fdb7
RS
2651xtensa_function_incoming_arg (cumulative_args_t cum,
2652 const function_arg_info &arg)
626a4b31 2653{
6783fdb7 2654 return xtensa_function_arg_1 (cum, arg, true);
626a4b31 2655}
03984308 2656
c2ed6cf8 2657static unsigned int
ef4bddc2 2658xtensa_function_arg_boundary (machine_mode mode, const_tree type)
d2348985
BW
2659{
2660 unsigned int alignment;
2661
2662 alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode);
2663 if (alignment < PARM_BOUNDARY)
2664 alignment = PARM_BOUNDARY;
2665 if (alignment > STACK_BOUNDARY)
2666 alignment = STACK_BOUNDARY;
2667 return alignment;
2668}
2669
2670
6e5ff6e7 2671static bool
586de218 2672xtensa_return_in_msb (const_tree valtype)
6e5ff6e7
BW
2673{
2674 return (TARGET_BIG_ENDIAN
2675 && AGGREGATE_TYPE_P (valtype)
2676 && int_size_in_bytes (valtype) >= UNITS_PER_WORD);
2677}
2678
2679
c5387660
JM
2680static void
2681xtensa_option_override (void)
03984308
BW
2682{
2683 int regno;
ef4bddc2 2684 machine_mode mode;
03984308 2685
8c8eb949
MF
2686 if (xtensa_windowed_abi == -1)
2687 xtensa_windowed_abi = TARGET_WINDOWED_ABI_DEFAULT;
2688
e46dad5d
MF
2689 if (! TARGET_THREADPTR)
2690 targetm.have_tls = false;
2691
1a711a0b
MF
2692 /* Use CONST16 in the absence of L32R.
2693 Set it in the TARGET_OPTION_OVERRIDE to avoid dependency on xtensa
e53b6e56 2694 configuration in the xtensa-common.cc */
1a711a0b
MF
2695
2696 if (!TARGET_L32R)
2697 target_flags |= MASK_CONST16;
2698
03984308
BW
2699 if (!TARGET_BOOLEANS && TARGET_HARD_FLOAT)
2700 error ("boolean registers required for the floating-point option");
2701
638db43e 2702 /* Set up array giving whether a given register can hold a given mode. */
03984308
BW
2703 for (mode = VOIDmode;
2704 mode != MAX_MACHINE_MODE;
ef4bddc2 2705 mode = (machine_mode) ((int) mode + 1))
03984308
BW
2706 {
2707 int size = GET_MODE_SIZE (mode);
0a2aaacc 2708 enum mode_class mclass = GET_MODE_CLASS (mode);
03984308
BW
2709
2710 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
2711 {
2712 int temp;
2713
2714 if (ACC_REG_P (regno))
f42f5a1b 2715 temp = (TARGET_MAC16
0a2aaacc 2716 && (mclass == MODE_INT) && (size <= UNITS_PER_WORD));
03984308
BW
2717 else if (GP_REG_P (regno))
2718 temp = ((regno & 1) == 0 || (size <= UNITS_PER_WORD));
2719 else if (FP_REG_P (regno))
2720 temp = (TARGET_HARD_FLOAT && (mode == SFmode));
2721 else if (BR_REG_P (regno))
2722 temp = (TARGET_BOOLEANS && (mode == CCmode));
2723 else
2724 temp = FALSE;
2725
f939c3e6 2726 xtensa_hard_regno_mode_ok_p[(int) mode][regno] = temp;
03984308
BW
2727 }
2728 }
2729
2730 init_machine_status = xtensa_init_machine_status;
03984308 2731
f42f5a1b
BW
2732 /* Check PIC settings. PIC is only supported when using L32R
2733 instructions, and some targets need to always use PIC. */
2734 if (flag_pic && TARGET_CONST16)
a3f9f006 2735 error ("%<-f%s%> is not supported with CONST16 instructions",
f42f5a1b 2736 (flag_pic > 1 ? "PIC" : "pic"));
1b408ba1
SA
2737 else if (TARGET_FORCE_NO_PIC)
2738 flag_pic = 0;
f42f5a1b
BW
2739 else if (XTENSA_ALWAYS_PIC)
2740 {
2741 if (TARGET_CONST16)
2742 error ("PIC is required but not supported with CONST16 instructions");
2743 flag_pic = 1;
2744 }
2745 /* There's no need for -fPIC (as opposed to -fpic) on Xtensa. */
2746 if (flag_pic > 1)
03984308 2747 flag_pic = 1;
166b25dc
BW
2748 if (flag_pic && !flag_pie)
2749 flag_shlib = 1;
87c8b4be
CT
2750
2751 /* Hot/cold partitioning does not work on this architecture, because of
2752 constant pools (the load instruction cannot necessarily reach that far).
2753 Therefore disable it on this architecture. */
2754 if (flag_reorder_blocks_and_partition)
2755 {
2756 flag_reorder_blocks_and_partition = 0;
2757 flag_reorder_blocks = 1;
2758 }
03984308
BW
2759}
2760
c43f4279
RS
2761/* Implement TARGET_HARD_REGNO_NREGS. */
2762
2763static unsigned int
2764xtensa_hard_regno_nregs (unsigned int regno, machine_mode mode)
2765{
2766 if (FP_REG_P (regno))
2767 return CEIL (GET_MODE_SIZE (mode), UNITS_PER_FPREG);
2768 return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
2769}
2770
f939c3e6
RS
2771/* Implement TARGET_HARD_REGNO_MODE_OK. */
2772
2773static bool
2774xtensa_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
2775{
2776 return xtensa_hard_regno_mode_ok_p[mode][regno];
2777}
2778
99e1629f
RS
2779/* Implement TARGET_MODES_TIEABLE_P. */
2780
2781static bool
2782xtensa_modes_tieable_p (machine_mode mode1, machine_mode mode2)
2783{
2784 return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
2785 || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
2786 == (GET_MODE_CLASS (mode2) == MODE_FLOAT
2787 || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
2788}
2789
03984308
BW
2790/* A C compound statement to output to stdio stream STREAM the
2791 assembler syntax for an instruction operand X. X is an RTL
2792 expression.
2793
2794 CODE is a value that can be used to specify one of several ways
2795 of printing the operand. It is used when identical operands
2796 must be printed differently depending on the context. CODE
2797 comes from the '%' specification that was used to request
2798 printing of the operand. If the specification was just '%DIGIT'
2799 then CODE is 0; if the specification was '%LTR DIGIT' then CODE
2800 is the ASCII code for LTR.
2801
2802 If X is a register, this macro should print the register's name.
2803 The names can be found in an array 'reg_names' whose type is
2804 'char *[]'. 'reg_names' is initialized from 'REGISTER_NAMES'.
2805
2806 When the machine description has a specification '%PUNCT' (a '%'
2807 followed by a punctuation character), this macro is called with
2808 a null pointer for X and the punctuation character for CODE.
2809
2810 'a', 'c', 'l', and 'n' are reserved.
633e4eb4 2811
03984308
BW
2812 The Xtensa specific codes are:
2813
2814 'd' CONST_INT, print as signed decimal
2815 'x' CONST_INT, print as signed hexadecimal
2816 'K' CONST_INT, print number of bits in mask for EXTUI
2817 'R' CONST_INT, print (X & 0x1f)
2818 'L' CONST_INT, print ((32 - X) & 0x1f)
2819 'D' REG, print second register of double-word register operand
2820 'N' MEM, print address of next word following a memory operand
2821 'v' MEM, if memory reference is volatile, output a MEMW before it
f42f5a1b
BW
2822 't' any constant, add "@h" suffix for top 16 bits
2823 'b' any constant, add "@l" suffix for bottom 16 bits
03984308
BW
2824*/
2825
2826static void
ffbc8796 2827printx (FILE *file, signed int val)
03984308 2828{
ffbc8796 2829 /* Print a hexadecimal value in a nice way. */
9b251fe2 2830 if (IN_RANGE (val, -9, 9))
03984308
BW
2831 fprintf (file, "%d", val);
2832 else if (val < 0)
2833 fprintf (file, "-0x%x", -val);
2834 else
2835 fprintf (file, "0x%x", val);
2836}
2837
2838
2839void
ffbc8796 2840print_operand (FILE *file, rtx x, int letter)
03984308 2841{
f42f5a1b 2842 if (!x)
7e5baa7e 2843 error ("%<PRINT_OPERAND%> null pointer");
03984308 2844
f42f5a1b 2845 switch (letter)
03984308 2846 {
f42f5a1b
BW
2847 case 'D':
2848 if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
2849 fprintf (file, "%s", reg_names[xt_true_regnum (x) + 1]);
2850 else
2851 output_operand_lossage ("invalid %%D value");
2852 break;
03984308 2853
f42f5a1b
BW
2854 case 'v':
2855 if (GET_CODE (x) == MEM)
2856 {
2857 /* For a volatile memory reference, emit a MEMW before the
2858 load or store. */
66e58b33 2859 if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE)
f42f5a1b
BW
2860 fprintf (file, "memw\n\t");
2861 }
2862 else
2863 output_operand_lossage ("invalid %%v value");
2864 break;
03984308 2865
f42f5a1b
BW
2866 case 'N':
2867 if (GET_CODE (x) == MEM
2868 && (GET_MODE (x) == DFmode || GET_MODE (x) == DImode))
2869 {
0d4a1197
RS
2870 x = adjust_address (x, GET_MODE (x) == DFmode ? E_SFmode : E_SImode,
2871 4);
cc8ca59e 2872 output_address (GET_MODE (x), XEXP (x, 0));
f42f5a1b
BW
2873 }
2874 else
2875 output_operand_lossage ("invalid %%N value");
2876 break;
03984308 2877
f42f5a1b
BW
2878 case 'K':
2879 if (GET_CODE (x) == CONST_INT)
03984308 2880 {
f42f5a1b 2881 unsigned val = INTVAL (x);
b753405a 2882 if (!xtensa_mask_immediate (val))
f42f5a1b 2883 fatal_insn ("invalid mask", x);
03984308 2884
b753405a 2885 fprintf (file, "%d", floor_log2 (val + 1));
f42f5a1b
BW
2886 }
2887 else
2888 output_operand_lossage ("invalid %%K value");
2889 break;
03984308 2890
f42f5a1b
BW
2891 case 'L':
2892 if (GET_CODE (x) == CONST_INT)
3904010d 2893 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (32 - INTVAL (x)) & 0x1f);
f42f5a1b
BW
2894 else
2895 output_operand_lossage ("invalid %%L value");
2896 break;
03984308 2897
f42f5a1b
BW
2898 case 'R':
2899 if (GET_CODE (x) == CONST_INT)
3904010d 2900 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0x1f);
f42f5a1b
BW
2901 else
2902 output_operand_lossage ("invalid %%R value");
2903 break;
03984308 2904
f42f5a1b
BW
2905 case 'x':
2906 if (GET_CODE (x) == CONST_INT)
2907 printx (file, INTVAL (x));
2908 else
2909 output_operand_lossage ("invalid %%x value");
2910 break;
03984308 2911
f42f5a1b
BW
2912 case 'd':
2913 if (GET_CODE (x) == CONST_INT)
3904010d 2914 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
f42f5a1b
BW
2915 else
2916 output_operand_lossage ("invalid %%d value");
2917 break;
03984308 2918
f42f5a1b
BW
2919 case 't':
2920 case 'b':
2921 if (GET_CODE (x) == CONST_INT)
2922 {
2923 printx (file, INTVAL (x));
2924 fputs (letter == 't' ? "@h" : "@l", file);
2925 }
2926 else if (GET_CODE (x) == CONST_DOUBLE)
2927 {
f42f5a1b
BW
2928 if (GET_MODE (x) == SFmode)
2929 {
2930 long l;
34a72c33 2931 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), l);
f42f5a1b
BW
2932 fprintf (file, "0x%08lx@%c", l, letter == 't' ? 'h' : 'l');
2933 }
2934 else
2935 output_operand_lossage ("invalid %%t/%%b value");
2936 }
2937 else if (GET_CODE (x) == CONST)
2938 {
2939 /* X must be a symbolic constant on ELF. Write an expression
2940 suitable for 'const16' that sets the high or low 16 bits. */
2941 if (GET_CODE (XEXP (x, 0)) != PLUS
2942 || (GET_CODE (XEXP (XEXP (x, 0), 0)) != SYMBOL_REF
2943 && GET_CODE (XEXP (XEXP (x, 0), 0)) != LABEL_REF)
2944 || GET_CODE (XEXP (XEXP (x, 0), 1)) != CONST_INT)
2945 output_operand_lossage ("invalid %%t/%%b value");
2946 print_operand (file, XEXP (XEXP (x, 0), 0), 0);
2947 fputs (letter == 't' ? "@h" : "@l", file);
2948 /* There must be a non-alphanumeric character between 'h' or 'l'
2949 and the number. The '-' is added by print_operand() already. */
2950 if (INTVAL (XEXP (XEXP (x, 0), 1)) >= 0)
2951 fputs ("+", file);
2952 print_operand (file, XEXP (XEXP (x, 0), 1), 0);
2953 }
2954 else
633e4eb4 2955 {
f42f5a1b
BW
2956 output_addr_const (file, x);
2957 fputs (letter == 't' ? "@h" : "@l", file);
03984308
BW
2958 }
2959 break;
2960
a024f514
MF
2961 case 'y':
2962 if (GET_CODE (x) == CONST_DOUBLE &&
2963 GET_MODE (x) == SFmode)
2964 {
a024f514 2965 long l;
34a72c33 2966 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), l);
a024f514
MF
2967 fprintf (file, "0x%08lx", l);
2968 break;
2969 }
2970
2971 /* fall through */
2972
03984308 2973 default:
f42f5a1b
BW
2974 if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
2975 fprintf (file, "%s", reg_names[xt_true_regnum (x)]);
2976 else if (GET_CODE (x) == MEM)
cc8ca59e 2977 output_address (GET_MODE (x), XEXP (x, 0));
f42f5a1b 2978 else if (GET_CODE (x) == CONST_INT)
3904010d 2979 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
f42f5a1b
BW
2980 else
2981 output_addr_const (file, x);
03984308
BW
2982 }
2983}
2984
2985
2986/* A C compound statement to output to stdio stream STREAM the
2987 assembler syntax for an instruction operand that is a memory
fb49053f 2988 reference whose address is ADDR. ADDR is an RTL expression. */
03984308
BW
2989
2990void
ffbc8796 2991print_operand_address (FILE *file, rtx addr)
03984308
BW
2992{
2993 if (!addr)
7e5baa7e 2994 error ("%<PRINT_OPERAND_ADDRESS%>, null pointer");
03984308
BW
2995
2996 switch (GET_CODE (addr))
2997 {
2998 default:
2999 fatal_insn ("invalid address", addr);
3000 break;
3001
3002 case REG:
3003 fprintf (file, "%s, 0", reg_names [REGNO (addr)]);
3004 break;
3005
3006 case PLUS:
3007 {
3008 rtx reg = (rtx)0;
3009 rtx offset = (rtx)0;
3010 rtx arg0 = XEXP (addr, 0);
3011 rtx arg1 = XEXP (addr, 1);
3012
3013 if (GET_CODE (arg0) == REG)
3014 {
3015 reg = arg0;
3016 offset = arg1;
3017 }
3018 else if (GET_CODE (arg1) == REG)
3019 {
3020 reg = arg1;
3021 offset = arg0;
3022 }
3023 else
3024 fatal_insn ("no register in address", addr);
3025
3026 if (CONSTANT_P (offset))
3027 {
3028 fprintf (file, "%s, ", reg_names [REGNO (reg)]);
3029 output_addr_const (file, offset);
3030 }
3031 else
3032 fatal_insn ("address offset not a constant", addr);
3033 }
3034 break;
3035
3036 case LABEL_REF:
3037 case SYMBOL_REF:
3038 case CONST_INT:
3039 case CONST:
3040 output_addr_const (file, addr);
3041 break;
3042 }
3043}
3044
2ac6bb04 3045/* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */
03984308 3046
2ac6bb04 3047static bool
da1f39e4
BW
3048xtensa_output_addr_const_extra (FILE *fp, rtx x)
3049{
3050 if (GET_CODE (x) == UNSPEC && XVECLEN (x, 0) == 1)
3051 {
3052 switch (XINT (x, 1))
3053 {
6a7a462c
BW
3054 case UNSPEC_TPOFF:
3055 output_addr_const (fp, XVECEXP (x, 0, 0));
3056 fputs ("@TPOFF", fp);
3057 return true;
3058 case UNSPEC_DTPOFF:
3059 output_addr_const (fp, XVECEXP (x, 0, 0));
3060 fputs ("@DTPOFF", fp);
3061 return true;
da1f39e4
BW
3062 case UNSPEC_PLT:
3063 if (flag_pic)
3064 {
3065 output_addr_const (fp, XVECEXP (x, 0, 0));
3066 fputs ("@PLT", fp);
3067 return true;
3068 }
3069 break;
3070 default:
3071 break;
3072 }
3073 }
3074 return false;
3075}
3076
9ae4ef4c
MF
3077static void
3078xtensa_output_integer_literal_parts (FILE *file, rtx x, int size)
3079{
3080 if (size > 4 && !(size & (size - 1)))
3081 {
3082 rtx first, second;
3083
3084 split_double (x, &first, &second);
3085 xtensa_output_integer_literal_parts (file, first, size / 2);
3086 fputs (", ", file);
3087 xtensa_output_integer_literal_parts (file, second, size / 2);
3088 }
3089 else if (size == 4)
3090 {
3091 output_addr_const (file, x);
3092 }
3093 else
3094 {
3095 gcc_unreachable();
3096 }
3097}
da1f39e4 3098
03984308 3099void
ef4bddc2 3100xtensa_output_literal (FILE *file, rtx x, machine_mode mode, int labelno)
03984308
BW
3101{
3102 long value_long[2];
03984308
BW
3103
3104 fprintf (file, "\t.literal .LC%u, ", (unsigned) labelno);
3105
3106 switch (GET_MODE_CLASS (mode))
3107 {
3108 case MODE_FLOAT:
177b6be0 3109 gcc_assert (GET_CODE (x) == CONST_DOUBLE);
03984308 3110
03984308
BW
3111 switch (mode)
3112 {
4e10a5a7 3113 case E_SFmode:
34a72c33
RS
3114 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x),
3115 value_long[0]);
4575a800
BW
3116 if (HOST_BITS_PER_LONG > 32)
3117 value_long[0] &= 0xffffffff;
b216cd4a 3118 fprintf (file, "0x%08lx\n", value_long[0]);
03984308
BW
3119 break;
3120
4e10a5a7 3121 case E_DFmode:
34a72c33
RS
3122 REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (x),
3123 value_long);
4575a800
BW
3124 if (HOST_BITS_PER_LONG > 32)
3125 {
3126 value_long[0] &= 0xffffffff;
3127 value_long[1] &= 0xffffffff;
3128 }
b216cd4a
ZW
3129 fprintf (file, "0x%08lx, 0x%08lx\n",
3130 value_long[0], value_long[1]);
03984308
BW
3131 break;
3132
3133 default:
177b6be0 3134 gcc_unreachable ();
03984308
BW
3135 }
3136
3137 break;
3138
3139 case MODE_INT:
3140 case MODE_PARTIAL_INT:
9ae4ef4c
MF
3141 xtensa_output_integer_literal_parts (file, x, GET_MODE_SIZE (mode));
3142 fputs ("\n", file);
03984308
BW
3143 break;
3144
3145 default:
177b6be0 3146 gcc_unreachable ();
03984308
BW
3147 }
3148}
3149
590e2636 3150static bool
06c2756e 3151xtensa_call_save_reg (int regno)
590e2636
MF
3152{
3153 if (TARGET_WINDOWED_ABI)
3154 return false;
3155
3156 if (regno == A0_REG)
3157 return crtl->profile || !crtl->is_leaf || crtl->calls_eh_return ||
3158 df_regs_ever_live_p (regno);
3159
9b251fe2 3160 if (crtl->calls_eh_return && IN_RANGE (regno, 2, 3))
590e2636
MF
3161 return true;
3162
2e3d041b 3163 return !call_used_or_fixed_reg_p (regno) && df_regs_ever_live_p (regno);
590e2636 3164}
03984308
BW
3165
3166/* Return the bytes needed to compute the frame pointer from the current
638db43e 3167 stack pointer. */
03984308
BW
3168
3169#define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
3170#define XTENSA_STACK_ALIGN(LOC) (((LOC) + STACK_BYTES-1) & ~(STACK_BYTES-1))
3171
3172long
f075bd95 3173compute_frame_size (poly_int64 size)
03984308 3174{
590e2636
MF
3175 int regno;
3176
ad89d820
MF
3177 if (reload_completed && cfun->machine->frame_laid_out)
3178 return cfun->machine->current_frame_size;
3179
ffbc8796 3180 /* Add space for the incoming static chain value. */
6de9cd9a 3181 if (cfun->static_chain_decl != NULL)
03984308
BW
3182 size += (1 * UNITS_PER_WORD);
3183
ad89d820 3184 cfun->machine->callee_save_size = 0;
590e2636
MF
3185 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
3186 {
06c2756e 3187 if (xtensa_call_save_reg (regno))
ad89d820 3188 cfun->machine->callee_save_size += UNITS_PER_WORD;
590e2636
MF
3189 }
3190
ad89d820 3191 cfun->machine->current_frame_size =
03984308 3192 XTENSA_STACK_ALIGN (size
ad89d820 3193 + cfun->machine->callee_save_size
38173d38 3194 + crtl->outgoing_args_size
03984308 3195 + (WINDOW_SIZE * UNITS_PER_WORD));
ad89d820
MF
3196 cfun->machine->callee_save_size =
3197 XTENSA_STACK_ALIGN (cfun->machine->callee_save_size);
3198 cfun->machine->frame_laid_out = true;
3199 return cfun->machine->current_frame_size;
03984308
BW
3200}
3201
3202
b52b1749 3203bool
ffbc8796 3204xtensa_frame_pointer_required (void)
03984308
BW
3205{
3206 /* The code to expand builtin_frame_addr and builtin_return_addr
3207 currently uses the hard_frame_pointer instead of frame_pointer.
3208 This seems wrong but maybe it's necessary for other architectures.
638db43e 3209 This function is derived from the i386 code. */
03984308 3210
25403c41 3211 if (cfun->machine->accesses_prev_frame || cfun->has_nonlocal_label)
b52b1749 3212 return true;
03984308 3213
b52b1749 3214 return false;
03984308
BW
3215}
3216
5057f9e0 3217HOST_WIDE_INT
eced9b48 3218xtensa_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED)
5057f9e0
MF
3219{
3220 long frame_size = compute_frame_size (get_frame_size ());
3221 HOST_WIDE_INT offset;
3222
3223 switch (from)
3224 {
3225 case FRAME_POINTER_REGNUM:
3226 if (FRAME_GROWS_DOWNWARD)
3227 offset = frame_size - (WINDOW_SIZE * UNITS_PER_WORD)
3228 - cfun->machine->callee_save_size;
3229 else
3230 offset = 0;
3231 break;
3232 case ARG_POINTER_REGNUM:
3233 offset = frame_size;
3234 break;
3235 default:
3236 gcc_unreachable ();
3237 }
3238
3239 return offset;
3240}
03984308 3241
06c2756e
TJJS
3242#define ADJUST_SP_NONE 0x0
3243#define ADJUST_SP_NEED_NOTE 0x1
3244#define ADJUST_SP_FRAME_PTR 0x2
3245static void
3246xtensa_emit_adjust_stack_ptr (HOST_WIDE_INT offset, int flags)
3247{
3248 rtx_insn *insn;
3249 rtx ptr = (flags & ADJUST_SP_FRAME_PTR) ? hard_frame_pointer_rtx
3250 : stack_pointer_rtx;
3251
3252 if (cfun->machine->inhibit_logues_a1_adjusts)
3253 return;
3254
3255 if (xtensa_simm8 (offset)
3256 || xtensa_simm8x256 (offset))
3257 insn = emit_insn (gen_addsi3 (stack_pointer_rtx, ptr, GEN_INT (offset)));
3258 else
3259 {
3260 rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
3261
3262 if (offset < 0)
3263 {
3264 emit_move_insn (tmp_reg, GEN_INT (-offset));
3265 insn = emit_insn (gen_subsi3 (stack_pointer_rtx, ptr, tmp_reg));
3266 }
3267 else
3268 {
3269 emit_move_insn (tmp_reg, GEN_INT (offset));
3270 insn = emit_insn (gen_addsi3 (stack_pointer_rtx, ptr, tmp_reg));
3271 }
3272 }
3273
3274 if (flags & ADJUST_SP_NEED_NOTE)
3275 {
3276 rtx note_rtx = gen_rtx_SET (stack_pointer_rtx,
3277 plus_constant (Pmode, stack_pointer_rtx,
3278 offset));
3279
3280 RTX_FRAME_RELATED_P (insn) = 1;
3281 add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
3282 }
3283}
3284
7f0ee694
BW
3285/* minimum frame = reg save area (4 words) plus static chain (1 word)
3286 and the total number of words must be a multiple of 128 bits. */
3287#define MIN_FRAME_SIZE (8 * UNITS_PER_WORD)
3288
f42f5a1b 3289void
ffbc8796 3290xtensa_expand_prologue (void)
f42f5a1b
BW
3291{
3292 HOST_WIDE_INT total_size;
590e2636 3293 rtx_insn *insn = NULL;
240a513f 3294 rtx note_rtx;
18dbd950 3295
f42f5a1b 3296 total_size = compute_frame_size (get_frame_size ());
18dbd950 3297
7695d1e3
MF
3298 if (flag_stack_usage_info)
3299 current_function_static_stack_size = total_size;
3300
590e2636
MF
3301 if (TARGET_WINDOWED_ABI)
3302 {
3303 if (total_size < (1 << (12+3)))
3304 insn = emit_insn (gen_entry (GEN_INT (total_size)));
3305 else
3306 {
3307 /* Use a8 as a temporary since a0-a7 may be live. */
3308 rtx tmp_reg = gen_rtx_REG (Pmode, A8_REG);
3309 emit_insn (gen_entry (GEN_INT (MIN_FRAME_SIZE)));
3310 emit_move_insn (tmp_reg, GEN_INT (total_size - MIN_FRAME_SIZE));
3311 emit_insn (gen_subsi3 (tmp_reg, stack_pointer_rtx, tmp_reg));
3312 insn = emit_insn (gen_movsi (stack_pointer_rtx, tmp_reg));
3313 }
3314 }
03984308
BW
3315 else
3316 {
590e2636
MF
3317 int regno;
3318 HOST_WIDE_INT offset = 0;
ad89d820 3319 int callee_save_size = cfun->machine->callee_save_size;
06c2756e
TJJS
3320 df_ref ref;
3321 bool stack_pointer_needed = frame_pointer_needed
3322 || crtl->calls_eh_return;
3323
3324 /* Check if the function body really needs the stack pointer. */
65fed695 3325 if (!stack_pointer_needed && df)
06c2756e
TJJS
3326 for (ref = DF_REG_USE_CHAIN (A1_REG);
3327 ref; ref = DF_REF_NEXT_REG (ref))
3328 if (DF_REF_CLASS (ref) == DF_REF_REGULAR
3329 && NONJUMP_INSN_P (DF_REF_INSN (ref)))
b22f86ba
TJJS
3330 {
3331 stack_pointer_needed = true;
3332 break;
3333 }
06c2756e
TJJS
3334 /* Check if callee-saved registers really need saving to the stack. */
3335 if (!stack_pointer_needed)
3336 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
3337 if (xtensa_call_save_reg (regno))
b22f86ba
TJJS
3338 {
3339 stack_pointer_needed = true;
3340 break;
3341 }
06c2756e
TJJS
3342
3343 cfun->machine->inhibit_logues_a1_adjusts = !stack_pointer_needed;
590e2636
MF
3344
3345 /* -128 is a limit of single addi instruction. */
9b251fe2 3346 if (IN_RANGE (total_size, 1, 128))
590e2636 3347 {
06c2756e
TJJS
3348 xtensa_emit_adjust_stack_ptr (-total_size,
3349 ADJUST_SP_NEED_NOTE);
590e2636
MF
3350 offset = total_size - UNITS_PER_WORD;
3351 }
ad89d820 3352 else if (callee_save_size)
590e2636
MF
3353 {
3354 /* 1020 is maximal s32i offset, if the frame is bigger than that
3355 * we move sp to the end of callee-saved save area, save and then
3356 * move it to its final location. */
3357 if (total_size > 1024)
3358 {
06c2756e
TJJS
3359 xtensa_emit_adjust_stack_ptr (-callee_save_size,
3360 ADJUST_SP_NEED_NOTE);
ad89d820 3361 offset = callee_save_size - UNITS_PER_WORD;
590e2636
MF
3362 }
3363 else
3364 {
06c2756e
TJJS
3365 xtensa_emit_adjust_stack_ptr (-total_size,
3366 ADJUST_SP_NEED_NOTE);
590e2636
MF
3367 offset = total_size - UNITS_PER_WORD;
3368 }
3369 }
3370
3371 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
3372 {
3373 if (xtensa_call_save_reg(regno))
3374 {
3375 rtx x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
3376 rtx mem = gen_frame_mem (SImode, x);
3377 rtx reg = gen_rtx_REG (SImode, regno);
3378
3379 offset -= UNITS_PER_WORD;
3380 insn = emit_move_insn (mem, reg);
3381 RTX_FRAME_RELATED_P (insn) = 1;
3382 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
f7df4a84 3383 gen_rtx_SET (mem, reg));
590e2636
MF
3384 }
3385 }
1fe39f19
MF
3386 if (total_size > 1024
3387 || (!callee_save_size && total_size > 128))
06c2756e
TJJS
3388 xtensa_emit_adjust_stack_ptr (callee_save_size - total_size,
3389 ADJUST_SP_NEED_NOTE);
03984308
BW
3390 }
3391
f42f5a1b 3392 if (frame_pointer_needed)
03984308 3393 {
997b8b4d 3394 if (cfun->machine->set_frame_ptr_insn)
03984308 3395 {
240a513f 3396 rtx_insn *first;
03984308 3397
997b8b4d
BW
3398 push_topmost_sequence ();
3399 first = get_insns ();
3400 pop_topmost_sequence ();
03984308 3401
f42f5a1b
BW
3402 /* For all instructions prior to set_frame_ptr_insn, replace
3403 hard_frame_pointer references with stack_pointer. */
3404 for (insn = first;
997b8b4d 3405 insn != cfun->machine->set_frame_ptr_insn;
f42f5a1b
BW
3406 insn = NEXT_INSN (insn))
3407 {
3408 if (INSN_P (insn))
20dca97b
BW
3409 {
3410 PATTERN (insn) = replace_rtx (copy_rtx (PATTERN (insn)),
3411 hard_frame_pointer_rtx,
3412 stack_pointer_rtx);
3413 df_insn_rescan (insn);
3414 }
f42f5a1b
BW
3415 }
3416 }
3417 else
89d5982b 3418 {
590e2636
MF
3419 insn = emit_insn (gen_movsi (hard_frame_pointer_rtx,
3420 stack_pointer_rtx));
3421 if (!TARGET_WINDOWED_ABI)
3422 {
f7df4a84 3423 note_rtx = gen_rtx_SET (hard_frame_pointer_rtx,
590e2636
MF
3424 stack_pointer_rtx);
3425 RTX_FRAME_RELATED_P (insn) = 1;
3426 add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
3427 }
3428 }
3429 }
03984308 3430
590e2636
MF
3431 if (TARGET_WINDOWED_ABI)
3432 {
3433 /* Create a note to describe the CFA. Because this is only used to set
3434 DW_AT_frame_base for debug info, don't bother tracking changes through
3435 each instruction in the prologue. It just takes up space. */
f7df4a84
RS
3436 note_rtx = gen_rtx_SET ((frame_pointer_needed
3437 ? hard_frame_pointer_rtx
3438 : stack_pointer_rtx),
590e2636
MF
3439 plus_constant (Pmode, stack_pointer_rtx,
3440 -total_size));
3441 RTX_FRAME_RELATED_P (insn) = 1;
3442 add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
3443 }
3444}
03984308
BW
3445
3446void
43b0c56f 3447xtensa_expand_epilogue (bool sibcall_p)
03984308 3448{
590e2636
MF
3449 if (!TARGET_WINDOWED_ABI)
3450 {
3451 int regno;
3452 HOST_WIDE_INT offset;
3453
ad89d820 3454 if (cfun->machine->current_frame_size > (frame_pointer_needed ? 127 : 1024))
590e2636 3455 {
06c2756e
TJJS
3456 xtensa_emit_adjust_stack_ptr (cfun->machine->current_frame_size -
3457 cfun->machine->callee_save_size,
3458 frame_pointer_needed
3459 ? ADJUST_SP_FRAME_PTR
3460 : ADJUST_SP_NONE);
ad89d820 3461 offset = cfun->machine->callee_save_size - UNITS_PER_WORD;
590e2636
MF
3462 }
3463 else
3464 {
3465 if (frame_pointer_needed)
3466 emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
ad89d820 3467 offset = cfun->machine->current_frame_size - UNITS_PER_WORD;
590e2636
MF
3468 }
3469
3470 /* Prevent reordering of saved a0 update and loading it back from
3471 the save area. */
3472 if (crtl->calls_eh_return)
3473 emit_insn (gen_blockage ());
3474
3475 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
3476 {
3477 if (xtensa_call_save_reg(regno))
3478 {
3479 rtx x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
3480
3481 offset -= UNITS_PER_WORD;
e0927d7d 3482 emit_move_insn (gen_rtx_REG (SImode, regno),
590e2636
MF
3483 gen_frame_mem (SImode, x));
3484 }
3485 }
e0927d7d
TJJS
3486 if (sibcall_p)
3487 emit_use (gen_rtx_REG (SImode, A0_REG));
590e2636 3488
ad89d820 3489 if (cfun->machine->current_frame_size > 0)
590e2636
MF
3490 {
3491 if (frame_pointer_needed || /* always reachable with addi */
ad89d820
MF
3492 cfun->machine->current_frame_size > 1024 ||
3493 cfun->machine->current_frame_size <= 127)
590e2636 3494 {
ad89d820
MF
3495 if (cfun->machine->current_frame_size <= 127)
3496 offset = cfun->machine->current_frame_size;
590e2636 3497 else
ad89d820 3498 offset = cfun->machine->callee_save_size;
dca74793 3499 if (offset)
06c2756e 3500 xtensa_emit_adjust_stack_ptr (offset, ADJUST_SP_NONE);
590e2636
MF
3501 }
3502 else
06c2756e
TJJS
3503 xtensa_emit_adjust_stack_ptr (cfun->machine->current_frame_size,
3504 ADJUST_SP_NONE);
590e2636
MF
3505 }
3506
3507 if (crtl->calls_eh_return)
3508 emit_insn (gen_add3_insn (stack_pointer_rtx,
3509 stack_pointer_rtx,
3510 EH_RETURN_STACKADJ_RTX));
3511 }
ad89d820 3512 cfun->machine->epilogue_done = true;
43b0c56f
TJJS
3513 if (!sibcall_p)
3514 emit_jump_insn (gen_return ());
03984308
BW
3515}
3516
ad89d820
MF
3517bool
3518xtensa_use_return_instruction_p (void)
3519{
3520 if (!reload_completed)
3521 return false;
3522 if (TARGET_WINDOWED_ABI)
3523 return true;
3524 if (compute_frame_size (get_frame_size ()) == 0)
3525 return true;
3526 return cfun->machine->epilogue_done;
3527}
3528
590e2636
MF
3529void
3530xtensa_set_return_address (rtx address, rtx scratch)
3531{
3532 HOST_WIDE_INT total_size = compute_frame_size (get_frame_size ());
3533 rtx frame = frame_pointer_needed ?
3534 hard_frame_pointer_rtx : stack_pointer_rtx;
3535 rtx a0_addr = plus_constant (Pmode, frame,
3536 total_size - UNITS_PER_WORD);
f7df4a84 3537 rtx note = gen_rtx_SET (gen_frame_mem (SImode, a0_addr),
590e2636
MF
3538 gen_rtx_REG (SImode, A0_REG));
3539 rtx insn;
3540
89d5982b
TJJS
3541 if (total_size > 1024)
3542 {
3543 emit_move_insn (scratch, GEN_INT (total_size - UNITS_PER_WORD));
3544 emit_insn (gen_addsi3 (scratch, frame, scratch));
3545 a0_addr = scratch;
3546 }
590e2636
MF
3547
3548 insn = emit_move_insn (gen_frame_mem (SImode, a0_addr), address);
3549 RTX_FRAME_RELATED_P (insn) = 1;
3550 add_reg_note (insn, REG_FRAME_RELATED_EXPR, note);
3551}
03984308 3552
0c14a54d 3553rtx
ffbc8796 3554xtensa_return_addr (int count, rtx frame)
0c14a54d 3555{
7f0ee694 3556 rtx result, retaddr, curaddr, label;
0c14a54d 3557
590e2636
MF
3558 if (!TARGET_WINDOWED_ABI)
3559 {
3560 if (count != 0)
3561 return const0_rtx;
3562
3563 return get_hard_reg_initial_val (Pmode, A0_REG);
3564 }
3565
0c14a54d 3566 if (count == -1)
f42f5a1b 3567 retaddr = gen_rtx_REG (Pmode, A0_REG);
0c14a54d
BW
3568 else
3569 {
0a81f074 3570 rtx addr = plus_constant (Pmode, frame, -4 * UNITS_PER_WORD);
0c14a54d
BW
3571 addr = memory_address (Pmode, addr);
3572 retaddr = gen_reg_rtx (Pmode);
3573 emit_move_insn (retaddr, gen_rtx_MEM (Pmode, addr));
3574 }
3575
3576 /* The 2 most-significant bits of the return address on Xtensa hold
3577 the register window size. To get the real return address, these
7f0ee694
BW
3578 bits must be replaced with the high bits from some address in the
3579 code. */
3580
3581 /* Get the 2 high bits of a local label in the code. */
3582 curaddr = gen_reg_rtx (Pmode);
3583 label = gen_label_rtx ();
3584 emit_label (label);
3585 LABEL_PRESERVE_P (label) = 1;
3586 emit_move_insn (curaddr, gen_rtx_LABEL_REF (Pmode, label));
3587 emit_insn (gen_lshrsi3 (curaddr, curaddr, GEN_INT (30)));
3588 emit_insn (gen_ashlsi3 (curaddr, curaddr, GEN_INT (30)));
3589
3590 /* Clear the 2 high bits of the return address. */
0c14a54d 3591 result = gen_reg_rtx (Pmode);
7f0ee694
BW
3592 emit_insn (gen_ashlsi3 (result, retaddr, GEN_INT (2)));
3593 emit_insn (gen_lshrsi3 (result, result, GEN_INT (2)));
3594
3595 /* Combine them to get the result. */
3596 emit_insn (gen_iorsi3 (result, result, curaddr));
0c14a54d
BW
3597 return result;
3598}
3599
d9886a9e
L
3600/* Disable the use of word-sized or smaller complex modes for structures,
3601 and for function arguments in particular, where they cause problems with
3602 register a7. The xtensa_copy_incoming_a7 function assumes that there is
3603 a single reference to an argument in a7, but with small complex modes the
3604 real and imaginary components may be extracted separately, leading to two
3605 uses of the register, only one of which would be replaced. */
3606
3607static bool
ef4bddc2 3608xtensa_member_type_forces_blk (const_tree, machine_mode mode)
d9886a9e
L
3609{
3610 return mode == CQImode || mode == CHImode;
3611}
0c14a54d 3612
03984308 3613/* Create the va_list data type.
822e895c
BW
3614
3615 This structure is set up by __builtin_saveregs. The __va_reg field
3616 points to a stack-allocated region holding the contents of the
3617 incoming argument registers. The __va_ndx field is an index
3618 initialized to the position of the first unnamed (variable)
3619 argument. This same index is also used to address the arguments
3620 passed in memory. Thus, the __va_stk field is initialized to point
3621 to the position of the first argument in memory offset to account
3622 for the arguments passed in registers and to account for the size
3623 of the argument registers not being 16-byte aligned. E.G., there
3624 are 6 argument registers of 4 bytes each, but we want the __va_ndx
3625 for the first stack argument to have the maximal alignment of 16
3626 bytes, so we offset the __va_stk address by 32 bytes so that
3627 __va_stk[32] references the first argument on the stack. */
03984308 3628
c35d187f
RH
3629static tree
3630xtensa_build_builtin_va_list (void)
03984308 3631{
540eaea8 3632 tree f_stk, f_reg, f_ndx, record, type_decl;
03984308 3633
540eaea8 3634 record = (*lang_hooks.types.make_type) (RECORD_TYPE);
4c4bde29
AH
3635 type_decl = build_decl (BUILTINS_LOCATION,
3636 TYPE_DECL, get_identifier ("__va_list_tag"), record);
03984308 3637
4c4bde29
AH
3638 f_stk = build_decl (BUILTINS_LOCATION,
3639 FIELD_DECL, get_identifier ("__va_stk"),
03984308 3640 ptr_type_node);
4c4bde29
AH
3641 f_reg = build_decl (BUILTINS_LOCATION,
3642 FIELD_DECL, get_identifier ("__va_reg"),
03984308 3643 ptr_type_node);
4c4bde29
AH
3644 f_ndx = build_decl (BUILTINS_LOCATION,
3645 FIELD_DECL, get_identifier ("__va_ndx"),
03984308
BW
3646 integer_type_node);
3647
3648 DECL_FIELD_CONTEXT (f_stk) = record;
3649 DECL_FIELD_CONTEXT (f_reg) = record;
3650 DECL_FIELD_CONTEXT (f_ndx) = record;
3651
0fd2eac2 3652 TYPE_STUB_DECL (record) = type_decl;
540eaea8 3653 TYPE_NAME (record) = type_decl;
03984308 3654 TYPE_FIELDS (record) = f_stk;
910ad8de
NF
3655 DECL_CHAIN (f_stk) = f_reg;
3656 DECL_CHAIN (f_reg) = f_ndx;
03984308
BW
3657
3658 layout_type (record);
3659 return record;
3660}
3661
3662
3663/* Save the incoming argument registers on the stack. Returns the
638db43e 3664 address of the saved registers. */
03984308 3665
4c45af42 3666static rtx
ffbc8796 3667xtensa_builtin_saveregs (void)
03984308 3668{
e70312d4 3669 rtx gp_regs;
38173d38 3670 int arg_words = crtl->args.info.arg_words;
03984308 3671 int gp_left = MAX_ARGS_IN_REGISTERS - arg_words;
03984308 3672
997b8b4d 3673 if (gp_left <= 0)
03984308
BW
3674 return const0_rtx;
3675
3bbc2af6 3676 /* Allocate the general-purpose register space. */
03984308
BW
3677 gp_regs = assign_stack_local
3678 (BLKmode, MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD, -1);
540eaea8 3679 set_mem_alias_set (gp_regs, get_varargs_alias_set ());
03984308
BW
3680
3681 /* Now store the incoming registers. */
590e2636 3682 cfun->machine->need_a7_copy = TARGET_WINDOWED_ABI;
997b8b4d 3683 cfun->machine->vararg_a7 = true;
e70312d4
BW
3684 move_block_from_reg (GP_ARG_FIRST + arg_words,
3685 adjust_address (gp_regs, BLKmode,
3686 arg_words * UNITS_PER_WORD),
3687 gp_left);
590e2636
MF
3688 if (cfun->machine->vararg_a7_copy != 0)
3689 emit_insn_before (cfun->machine->vararg_a7_copy, get_insns ());
03984308
BW
3690
3691 return XEXP (gp_regs, 0);
3692}
3693
3694
3695/* Implement `va_start' for varargs and stdarg. We look at the
638db43e 3696 current function to fill in an initial va_list. */
03984308 3697
d7bd8aeb 3698static void
ffbc8796 3699xtensa_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
03984308
BW
3700{
3701 tree f_stk, stk;
3702 tree f_reg, reg;
3703 tree f_ndx, ndx;
3704 tree t, u;
3705 int arg_words;
3706
38173d38 3707 arg_words = crtl->args.info.arg_words;
03984308
BW
3708
3709 f_stk = TYPE_FIELDS (va_list_type_node);
910ad8de
NF
3710 f_reg = DECL_CHAIN (f_stk);
3711 f_ndx = DECL_CHAIN (f_reg);
03984308 3712
47a25a46 3713 stk = build3 (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk, NULL_TREE);
fa1615d7
BW
3714 reg = build3 (COMPONENT_REF, TREE_TYPE (f_reg), unshare_expr (valist),
3715 f_reg, NULL_TREE);
3716 ndx = build3 (COMPONENT_REF, TREE_TYPE (f_ndx), unshare_expr (valist),
3717 f_ndx, NULL_TREE);
03984308
BW
3718
3719 /* Call __builtin_saveregs; save the result in __va_reg */
e70312d4
BW
3720 u = make_tree (sizetype, expand_builtin_saveregs ());
3721 u = fold_convert (ptr_type_node, u);
726a989a 3722 t = build2 (MODIFY_EXPR, ptr_type_node, reg, u);
03984308
BW
3723 TREE_SIDE_EFFECTS (t) = 1;
3724 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3725
822e895c 3726 /* Set the __va_stk member to ($arg_ptr - 32). */
03984308 3727 u = make_tree (ptr_type_node, virtual_incoming_args_rtx);
5d49b6a7 3728 u = fold_build_pointer_plus_hwi (u, -32);
726a989a 3729 t = build2 (MODIFY_EXPR, ptr_type_node, stk, u);
03984308
BW
3730 TREE_SIDE_EFFECTS (t) = 1;
3731 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3732
822e895c
BW
3733 /* Set the __va_ndx member. If the first variable argument is on
3734 the stack, adjust __va_ndx by 2 words to account for the extra
3735 alignment offset for __va_stk. */
3736 if (arg_words >= MAX_ARGS_IN_REGISTERS)
3737 arg_words += 2;
726a989a 3738 t = build2 (MODIFY_EXPR, integer_type_node, ndx,
f4d3e7fd 3739 build_int_cst (integer_type_node, arg_words * UNITS_PER_WORD));
03984308
BW
3740 TREE_SIDE_EFFECTS (t) = 1;
3741 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3742}
3743
3744
3745/* Implement `va_arg'. */
3746
85d53c1d 3747static tree
726a989a
RB
3748xtensa_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
3749 gimple_seq *post_p ATTRIBUTE_UNUSED)
03984308
BW
3750{
3751 tree f_stk, stk;
3752 tree f_reg, reg;
3753 tree f_ndx, ndx;
85d53c1d
RH
3754 tree type_size, array, orig_ndx, addr, size, va_size, t;
3755 tree lab_false, lab_over, lab_false2;
08b0dc1b
RH
3756 bool indirect;
3757
fde65a89 3758 indirect = pass_va_arg_by_reference (type);
08b0dc1b
RH
3759 if (indirect)
3760 type = build_pointer_type (type);
03984308 3761
3712281f
BW
3762 /* Handle complex values as separate real and imaginary parts. */
3763 if (TREE_CODE (type) == COMPLEX_TYPE)
3764 {
85d53c1d 3765 tree real_part, imag_part;
3712281f 3766
85d53c1d
RH
3767 real_part = xtensa_gimplify_va_arg_expr (valist, TREE_TYPE (type),
3768 pre_p, NULL);
3769 real_part = get_initialized_tmp_var (real_part, pre_p, NULL);
3712281f 3770
fa1615d7
BW
3771 imag_part = xtensa_gimplify_va_arg_expr (unshare_expr (valist),
3772 TREE_TYPE (type),
85d53c1d
RH
3773 pre_p, NULL);
3774 imag_part = get_initialized_tmp_var (imag_part, pre_p, NULL);
3712281f 3775
47a25a46 3776 return build2 (COMPLEX_EXPR, type, real_part, imag_part);
3712281f
BW
3777 }
3778
03984308 3779 f_stk = TYPE_FIELDS (va_list_type_node);
910ad8de
NF
3780 f_reg = DECL_CHAIN (f_stk);
3781 f_ndx = DECL_CHAIN (f_reg);
03984308 3782
fa1615d7
BW
3783 stk = build3 (COMPONENT_REF, TREE_TYPE (f_stk), valist,
3784 f_stk, NULL_TREE);
3785 reg = build3 (COMPONENT_REF, TREE_TYPE (f_reg), unshare_expr (valist),
3786 f_reg, NULL_TREE);
3787 ndx = build3 (COMPONENT_REF, TREE_TYPE (f_ndx), unshare_expr (valist),
3788 f_ndx, NULL_TREE);
03984308 3789
85d53c1d
RH
3790 type_size = size_in_bytes (type);
3791 va_size = round_up (type_size, UNITS_PER_WORD);
3792 gimplify_expr (&va_size, pre_p, NULL, is_gimple_val, fb_rvalue);
8be56275 3793
03984308 3794
822e895c 3795 /* First align __va_ndx if necessary for this arg:
03984308 3796
85d53c1d 3797 orig_ndx = (AP).__va_ndx;
822e895c 3798 if (__alignof__ (TYPE) > 4 )
85d53c1d 3799 orig_ndx = ((orig_ndx + __alignof__ (TYPE) - 1)
822e895c 3800 & -__alignof__ (TYPE)); */
03984308 3801
85d53c1d
RH
3802 orig_ndx = get_initialized_tmp_var (ndx, pre_p, NULL);
3803
03984308
BW
3804 if (TYPE_ALIGN (type) > BITS_PER_WORD)
3805 {
d2348985 3806 int align = MIN (TYPE_ALIGN (type), STACK_BOUNDARY) / BITS_PER_UNIT;
85d53c1d 3807
fa1615d7 3808 t = build2 (PLUS_EXPR, integer_type_node, unshare_expr (orig_ndx),
f4d3e7fd
BW
3809 build_int_cst (integer_type_node, align - 1));
3810 t = build2 (BIT_AND_EXPR, integer_type_node, t,
3811 build_int_cst (integer_type_node, -align));
fa1615d7 3812 gimplify_assign (unshare_expr (orig_ndx), t, pre_p);
03984308
BW
3813 }
3814
3815
3816 /* Increment __va_ndx to point past the argument:
3817
85d53c1d 3818 (AP).__va_ndx = orig_ndx + __va_size (TYPE); */
03984308 3819
85d53c1d 3820 t = fold_convert (integer_type_node, va_size);
47a25a46 3821 t = build2 (PLUS_EXPR, integer_type_node, orig_ndx, t);
fa1615d7 3822 gimplify_assign (unshare_expr (ndx), t, pre_p);
03984308
BW
3823
3824
3825 /* Check if the argument is in registers:
3826
bcf88f9b 3827 if ((AP).__va_ndx <= __MAX_ARGS_IN_REGISTERS * 4
89d5982b
TJJS
3828 && !must_pass_in_stack (type))
3829 __array = (AP).__va_reg; */
03984308 3830
9b489f31 3831 array = create_tmp_var (ptr_type_node);
03984308 3832
85d53c1d 3833 lab_over = NULL;
4f53599c 3834 if (!must_pass_va_arg_in_stack (type))
bcf88f9b 3835 {
4c4bde29
AH
3836 lab_false = create_artificial_label (UNKNOWN_LOCATION);
3837 lab_over = create_artificial_label (UNKNOWN_LOCATION);
85d53c1d 3838
fa1615d7 3839 t = build2 (GT_EXPR, boolean_type_node, unshare_expr (ndx),
f4d3e7fd
BW
3840 build_int_cst (integer_type_node,
3841 MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD));
47a25a46
RG
3842 t = build3 (COND_EXPR, void_type_node, t,
3843 build1 (GOTO_EXPR, void_type_node, lab_false),
3844 NULL_TREE);
85d53c1d
RH
3845 gimplify_and_add (t, pre_p);
3846
fa1615d7 3847 gimplify_assign (unshare_expr (array), reg, pre_p);
85d53c1d 3848
47a25a46 3849 t = build1 (GOTO_EXPR, void_type_node, lab_over);
85d53c1d
RH
3850 gimplify_and_add (t, pre_p);
3851
47a25a46 3852 t = build1 (LABEL_EXPR, void_type_node, lab_false);
85d53c1d 3853 gimplify_and_add (t, pre_p);
bcf88f9b 3854 }
03984308 3855
85d53c1d 3856
03984308
BW
3857 /* ...otherwise, the argument is on the stack (never split between
3858 registers and the stack -- change __va_ndx if necessary):
3859
3860 else
3861 {
822e895c
BW
3862 if (orig_ndx <= __MAX_ARGS_IN_REGISTERS * 4)
3863 (AP).__va_ndx = 32 + __va_size (TYPE);
03984308 3864 __array = (AP).__va_stk;
ffbc8796 3865 } */
03984308 3866
4c4bde29 3867 lab_false2 = create_artificial_label (UNKNOWN_LOCATION);
03984308 3868
fa1615d7 3869 t = build2 (GT_EXPR, boolean_type_node, unshare_expr (orig_ndx),
f4d3e7fd
BW
3870 build_int_cst (integer_type_node,
3871 MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD));
47a25a46
RG
3872 t = build3 (COND_EXPR, void_type_node, t,
3873 build1 (GOTO_EXPR, void_type_node, lab_false2),
3874 NULL_TREE);
85d53c1d 3875 gimplify_and_add (t, pre_p);
03984308 3876
fa1615d7 3877 t = size_binop (PLUS_EXPR, unshare_expr (va_size), size_int (32));
85d53c1d 3878 t = fold_convert (integer_type_node, t);
fa1615d7 3879 gimplify_assign (unshare_expr (ndx), t, pre_p);
03984308 3880
47a25a46 3881 t = build1 (LABEL_EXPR, void_type_node, lab_false2);
85d53c1d 3882 gimplify_and_add (t, pre_p);
03984308 3883
726a989a 3884 gimplify_assign (array, stk, pre_p);
85d53c1d
RH
3885
3886 if (lab_over)
3887 {
47a25a46 3888 t = build1 (LABEL_EXPR, void_type_node, lab_over);
85d53c1d
RH
3889 gimplify_and_add (t, pre_p);
3890 }
8be56275 3891
03984308
BW
3892
3893 /* Given the base array pointer (__array) and index to the subsequent
3894 argument (__va_ndx), find the address:
3895
8be56275
BW
3896 __array + (AP).__va_ndx - (BYTES_BIG_ENDIAN && sizeof (TYPE) < 4
3897 ? sizeof (TYPE)
3898 : __va_size (TYPE))
03984308
BW
3899
3900 The results are endian-dependent because values smaller than one word
ffbc8796 3901 are aligned differently. */
03984308 3902
633e4eb4 3903
85d91d5b 3904 if (BYTES_BIG_ENDIAN && TREE_CODE (type_size) == INTEGER_CST)
8be56275 3905 {
fa1615d7 3906 t = fold_build2 (GE_EXPR, boolean_type_node, unshare_expr (type_size),
e70312d4 3907 size_int (PARM_BOUNDARY / BITS_PER_UNIT));
fa1615d7
BW
3908 t = fold_build3 (COND_EXPR, sizetype, t, unshare_expr (va_size),
3909 unshare_expr (type_size));
85d53c1d 3910 size = t;
8be56275 3911 }
85d53c1d 3912 else
fa1615d7 3913 size = unshare_expr (va_size);
85d53c1d 3914
fa1615d7 3915 t = fold_convert (sizetype, unshare_expr (ndx));
f4d3e7fd 3916 t = build2 (MINUS_EXPR, sizetype, t, size);
5d49b6a7 3917 addr = fold_build_pointer_plus (unshare_expr (array), t);
03984308 3918
85d53c1d 3919 addr = fold_convert (build_pointer_type (type), addr);
08b0dc1b 3920 if (indirect)
d6e9821f
RH
3921 addr = build_va_arg_indirect_ref (addr);
3922 return build_va_arg_indirect_ref (addr);
03984308
BW
3923}
3924
3925
09fa8841
BW
3926/* Builtins. */
3927
3928enum xtensa_builtin
3929{
3930 XTENSA_BUILTIN_UMULSIDI3,
3931 XTENSA_BUILTIN_max
3932};
3933
3934
3935static void
3936xtensa_init_builtins (void)
3937{
6a7a462c 3938 tree ftype, decl;
09fa8841
BW
3939
3940 ftype = build_function_type_list (unsigned_intDI_type_node,
3941 unsigned_intSI_type_node,
3942 unsigned_intSI_type_node, NULL_TREE);
3943
6a7a462c
BW
3944 decl = add_builtin_function ("__builtin_umulsidi3", ftype,
3945 XTENSA_BUILTIN_UMULSIDI3, BUILT_IN_MD,
3946 "__umulsidi3", NULL_TREE);
3947 TREE_NOTHROW (decl) = 1;
3948 TREE_READONLY (decl) = 1;
09fa8841
BW
3949}
3950
3951
3952static tree
f311c3b4
NF
3953xtensa_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *args,
3954 bool ignore ATTRIBUTE_UNUSED)
09fa8841 3955{
4d732405 3956 unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
09fa8841
BW
3957 tree arg0, arg1;
3958
6a7a462c 3959 switch (fcode)
09fa8841 3960 {
6a7a462c 3961 case XTENSA_BUILTIN_UMULSIDI3:
f311c3b4
NF
3962 arg0 = args[0];
3963 arg1 = args[1];
09fa8841
BW
3964 if ((TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
3965 || TARGET_MUL32_HIGH)
3966 return fold_build2 (MULT_EXPR, unsigned_intDI_type_node,
3967 fold_convert (unsigned_intDI_type_node, arg0),
3968 fold_convert (unsigned_intDI_type_node, arg1));
6a7a462c
BW
3969 break;
3970
6a7a462c
BW
3971 default:
3972 internal_error ("bad builtin code");
3973 break;
09fa8841
BW
3974 }
3975
09fa8841
BW
3976 return NULL;
3977}
3978
3979
3980static rtx
3981xtensa_expand_builtin (tree exp, rtx target,
3982 rtx subtarget ATTRIBUTE_UNUSED,
ef4bddc2 3983 machine_mode mode ATTRIBUTE_UNUSED,
09fa8841
BW
3984 int ignore)
3985{
ec3643e8 3986 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
4d732405 3987 unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
6a7a462c
BW
3988
3989 switch (fcode)
3990 {
3991 case XTENSA_BUILTIN_UMULSIDI3:
3992 /* The umulsidi3 builtin is just a mechanism to avoid calling the real
3993 __umulsidi3 function when the Xtensa configuration can directly
3994 implement it. If not, just call the function. */
3995 return expand_call (exp, target, ignore);
09fa8841 3996
6a7a462c
BW
3997 default:
3998 internal_error ("bad builtin code");
3999 }
09fa8841
BW
4000 return NULL_RTX;
4001}
4002
a6e508f9 4003/* Worker function for TARGET_PREFERRED_RELOAD_CLASS. */
09fa8841 4004
a6e508f9
AS
4005static reg_class_t
4006xtensa_preferred_reload_class (rtx x, reg_class_t rclass)
a8cacfd2 4007{
a6e508f9 4008 if (CONSTANT_P (x) && CONST_DOUBLE_P (x))
a8cacfd2
BW
4009 return NO_REGS;
4010
89f6025d
BW
4011 /* Don't use the stack pointer or hard frame pointer for reloads!
4012 The hard frame pointer would normally be OK except that it may
4013 briefly hold an incoming argument in the prologue, and reload
4014 won't know that it is live because the hard frame pointer is
4015 treated specially. */
4016
0a2aaacc 4017 if (rclass == AR_REGS || rclass == GR_REGS)
89f6025d 4018 return RL_REGS;
a8cacfd2 4019
0a2aaacc 4020 return rclass;
a8cacfd2
BW
4021}
4022
a6e508f9
AS
4023/* Worker function for TARGET_PREFERRED_OUTPUT_RELOAD_CLASS. */
4024
4025static reg_class_t
4026xtensa_preferred_output_reload_class (rtx x ATTRIBUTE_UNUSED,
4027 reg_class_t rclass)
4028{
4029 /* Don't use the stack pointer or hard frame pointer for reloads!
4030 The hard frame pointer would normally be OK except that it may
4031 briefly hold an incoming argument in the prologue, and reload
4032 won't know that it is live because the hard frame pointer is
4033 treated specially. */
4034
4035 if (rclass == AR_REGS || rclass == GR_REGS)
4036 return RL_REGS;
4037
4038 return rclass;
4039}
4040
4041/* Worker function for TARGET_SECONDARY_RELOAD. */
a8cacfd2 4042
a6e508f9 4043static reg_class_t
a87cf97e 4044xtensa_secondary_reload (bool in_p, rtx x, reg_class_t rclass,
ef4bddc2 4045 machine_mode mode, secondary_reload_info *sri)
03984308
BW
4046{
4047 int regno;
4048
37fbe8a3 4049 if (in_p && constantpool_mem_p (x))
03984308 4050 {
37fbe8a3 4051 if (rclass == FP_REGS)
89f6025d 4052 return RL_REGS;
37fbe8a3
BW
4053
4054 if (mode == QImode)
4055 sri->icode = CODE_FOR_reloadqi_literal;
4056 else if (mode == HImode)
4057 sri->icode = CODE_FOR_reloadhi_literal;
03984308
BW
4058 }
4059
37fbe8a3 4060 regno = xt_true_regnum (x);
03984308 4061 if (ACC_REG_P (regno))
0a2aaacc
KG
4062 return ((rclass == GR_REGS || rclass == RL_REGS) ? NO_REGS : RL_REGS);
4063 if (rclass == ACC_REG)
89f6025d 4064 return (GP_REG_P (regno) ? NO_REGS : RL_REGS);
03984308
BW
4065
4066 return NO_REGS;
4067}
4068
4069
4070void
ffbc8796 4071order_regs_for_local_alloc (void)
03984308
BW
4072{
4073 if (!leaf_function_p ())
4074 {
590e2636
MF
4075 static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
4076 REG_ALLOC_ORDER;
4077 static const int reg_nonleaf_alloc_order_call0[FIRST_PSEUDO_REGISTER] =
4078 {
4079 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 12, 13, 14, 15,
4080 18,
4081 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
4082 0, 1, 16, 17,
4083 35,
4084 };
4085
4086 memcpy (reg_alloc_order, TARGET_WINDOWED_ABI ?
4087 reg_nonleaf_alloc_order : reg_nonleaf_alloc_order_call0,
03984308
BW
4088 FIRST_PSEUDO_REGISTER * sizeof (int));
4089 }
4090 else
4091 {
4092 int i, num_arg_regs;
4093 int nxt = 0;
4094
3bbc2af6
KH
4095 /* Use the AR registers in increasing order (skipping a0 and a1)
4096 but save the incoming argument registers for a last resort. */
38173d38 4097 num_arg_regs = crtl->args.info.arg_words;
03984308
BW
4098 if (num_arg_regs > MAX_ARGS_IN_REGISTERS)
4099 num_arg_regs = MAX_ARGS_IN_REGISTERS;
4100 for (i = GP_ARG_FIRST; i < 16 - num_arg_regs; i++)
4101 reg_alloc_order[nxt++] = i + num_arg_regs;
4102 for (i = 0; i < num_arg_regs; i++)
4103 reg_alloc_order[nxt++] = GP_ARG_FIRST + i;
4104
3bbc2af6 4105 /* List the coprocessor registers in order. */
985d0d50
BW
4106 for (i = 0; i < BR_REG_NUM; i++)
4107 reg_alloc_order[nxt++] = BR_REG_FIRST + i;
4108
3bbc2af6 4109 /* List the FP registers in order for now. */
03984308
BW
4110 for (i = 0; i < 16; i++)
4111 reg_alloc_order[nxt++] = FP_REG_FIRST + i;
4112
638db43e 4113 /* GCC requires that we list *all* the registers.... */
03984308
BW
4114 reg_alloc_order[nxt++] = 0; /* a0 = return address */
4115 reg_alloc_order[nxt++] = 1; /* a1 = stack pointer */
4116 reg_alloc_order[nxt++] = 16; /* pseudo frame pointer */
4117 reg_alloc_order[nxt++] = 17; /* pseudo arg pointer */
4118
03984308
BW
4119 reg_alloc_order[nxt++] = ACC_REG_FIRST; /* MAC16 accumulator */
4120 }
4121}
4122
4123
01abf342
BW
4124/* Some Xtensa targets support multiple bss sections. If the section
4125 name ends with ".bss", add SECTION_BSS to the flags. */
4126
4127static unsigned int
ffbc8796 4128xtensa_multibss_section_type_flags (tree decl, const char *name, int reloc)
01abf342
BW
4129{
4130 unsigned int flags = default_section_type_flags (decl, name, reloc);
4131 const char *suffix;
4132
4133 suffix = strrchr (name, '.');
4134 if (suffix && strcmp (suffix, ".bss") == 0)
4135 {
4136 if (!decl || (TREE_CODE (decl) == VAR_DECL
4137 && DECL_INITIAL (decl) == NULL_TREE))
4138 flags |= SECTION_BSS; /* @nobits */
4139 else
d4ee4d25 4140 warning (0, "only uninitialized variables can be placed in a "
7e5baa7e 4141 "%<.bss%> section");
01abf342
BW
4142 }
4143
4144 return flags;
4145}
4146
4147
b64a1b53
RH
4148/* The literal pool stays with the function. */
4149
d6b5193b 4150static section *
ef4bddc2 4151xtensa_select_rtx_section (machine_mode mode ATTRIBUTE_UNUSED,
ffbc8796
BW
4152 rtx x ATTRIBUTE_UNUSED,
4153 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
b64a1b53 4154{
d6b5193b 4155 return function_section (current_function_decl);
b64a1b53 4156}
fb49053f 4157
5378dda2
AS
4158/* Worker function for TARGET_REGISTER_MOVE_COST. */
4159
4160static int
ef4bddc2 4161xtensa_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
5378dda2
AS
4162 reg_class_t from, reg_class_t to)
4163{
4164 if (from == to && from != BR_REGS && to != BR_REGS)
4165 return 2;
4166 else if (reg_class_subset_p (from, AR_REGS)
4167 && reg_class_subset_p (to, AR_REGS))
4168 return 2;
4169 else if (reg_class_subset_p (from, AR_REGS) && to == ACC_REG)
4170 return 3;
4171 else if (from == ACC_REG && reg_class_subset_p (to, AR_REGS))
4172 return 3;
4173 else
4174 return 10;
4175}
4176
4177/* Worker function for TARGET_MEMORY_MOVE_COST. */
4178
4179static int
ef4bddc2 4180xtensa_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
5378dda2
AS
4181 reg_class_t rclass ATTRIBUTE_UNUSED,
4182 bool in ATTRIBUTE_UNUSED)
4183{
4184 return 4;
4185}
ffbc8796 4186
3c50106f
RH
4187/* Compute a (partial) cost for rtx X. Return true if the complete
4188 cost has been computed, and false if subexpressions should be
4189 scanned. In either case, *TOTAL contains the cost result. */
4190
4191static bool
e548c9df
AM
4192xtensa_rtx_costs (rtx x, machine_mode mode, int outer_code,
4193 int opno ATTRIBUTE_UNUSED,
ccd02e73 4194 int *total, bool speed)
3c50106f 4195{
e548c9df
AM
4196 int code = GET_CODE (x);
4197
3c50106f
RH
4198 switch (code)
4199 {
4200 case CONST_INT:
4201 switch (outer_code)
4202 {
4203 case SET:
4204 if (xtensa_simm12b (INTVAL (x)))
4205 {
2180cdd8 4206 *total = speed ? COSTS_N_INSNS (1) : 0;
3c50106f
RH
4207 return true;
4208 }
4209 break;
4210 case PLUS:
4211 if (xtensa_simm8 (INTVAL (x))
4212 || xtensa_simm8x256 (INTVAL (x)))
4213 {
4214 *total = 0;
4215 return true;
4216 }
4217 break;
4218 case AND:
4219 if (xtensa_mask_immediate (INTVAL (x)))
4220 {
4221 *total = 0;
4222 return true;
4223 }
4224 break;
4225 case COMPARE:
4226 if ((INTVAL (x) == 0) || xtensa_b4const (INTVAL (x)))
4227 {
4228 *total = 0;
4229 return true;
4230 }
4231 break;
4232 case ASHIFT:
4233 case ASHIFTRT:
4234 case LSHIFTRT:
4235 case ROTATE:
4236 case ROTATERT:
3bbc2af6 4237 /* No way to tell if X is the 2nd operand so be conservative. */
3c50106f
RH
4238 default: break;
4239 }
4240 if (xtensa_simm12b (INTVAL (x)))
4241 *total = 5;
f42f5a1b
BW
4242 else if (TARGET_CONST16)
4243 *total = COSTS_N_INSNS (2);
3c50106f
RH
4244 else
4245 *total = 6;
4246 return true;
4247
4248 case CONST:
4249 case LABEL_REF:
4250 case SYMBOL_REF:
f42f5a1b
BW
4251 if (TARGET_CONST16)
4252 *total = COSTS_N_INSNS (2);
4253 else
4254 *total = 5;
3c50106f
RH
4255 return true;
4256
4257 case CONST_DOUBLE:
f42f5a1b
BW
4258 if (TARGET_CONST16)
4259 *total = COSTS_N_INSNS (4);
4260 else
4261 *total = 7;
3c50106f
RH
4262 return true;
4263
4264 case MEM:
4265 {
4266 int num_words =
e548c9df 4267 (GET_MODE_SIZE (mode) > UNITS_PER_WORD) ? 2 : 1;
3c50106f 4268
e548c9df 4269 if (memory_address_p (mode, XEXP ((x), 0)))
3c50106f
RH
4270 *total = COSTS_N_INSNS (num_words);
4271 else
4272 *total = COSTS_N_INSNS (2*num_words);
4273 return true;
4274 }
4275
4276 case FFS:
09fa8841 4277 case CTZ:
3c50106f
RH
4278 *total = COSTS_N_INSNS (TARGET_NSA ? 5 : 50);
4279 return true;
4280
09fa8841 4281 case CLZ:
ccd02e73 4282 case CLRSB:
09fa8841
BW
4283 *total = COSTS_N_INSNS (TARGET_NSA ? 1 : 50);
4284 return true;
4285
ccd02e73
TJJS
4286 case BSWAP:
4287 *total = COSTS_N_INSNS (mode == HImode ? 3 : 5);
4288 return true;
4289
3c50106f 4290 case NOT:
e548c9df 4291 *total = COSTS_N_INSNS (mode == DImode ? 3 : 2);
3c50106f
RH
4292 return true;
4293
4294 case AND:
4295 case IOR:
4296 case XOR:
e548c9df 4297 if (mode == DImode)
3c50106f
RH
4298 *total = COSTS_N_INSNS (2);
4299 else
4300 *total = COSTS_N_INSNS (1);
4301 return true;
4302
4303 case ASHIFT:
4304 case ASHIFTRT:
4305 case LSHIFTRT:
e548c9df 4306 if (mode == DImode)
3c50106f
RH
4307 *total = COSTS_N_INSNS (50);
4308 else
4309 *total = COSTS_N_INSNS (1);
4310 return true;
4311
4312 case ABS:
ccd02e73 4313 case NEG:
3c50106f 4314 {
e548c9df 4315 if (mode == SFmode)
3c50106f 4316 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
e548c9df 4317 else if (mode == DFmode)
3c50106f 4318 *total = COSTS_N_INSNS (50);
ccd02e73 4319 else if (mode == DImode)
3c50106f 4320 *total = COSTS_N_INSNS (4);
ccd02e73
TJJS
4321 else
4322 *total = COSTS_N_INSNS (1);
3c50106f
RH
4323 return true;
4324 }
4325
4326 case PLUS:
4327 case MINUS:
4328 {
e548c9df 4329 if (mode == SFmode)
3c50106f 4330 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
e548c9df 4331 else if (mode == DFmode || mode == DImode)
3c50106f
RH
4332 *total = COSTS_N_INSNS (50);
4333 else
4334 *total = COSTS_N_INSNS (1);
4335 return true;
4336 }
4337
3c50106f
RH
4338 case MULT:
4339 {
e548c9df 4340 if (mode == SFmode)
3c50106f 4341 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 4 : 50);
e548c9df 4342 else if (mode == DFmode)
3c50106f 4343 *total = COSTS_N_INSNS (50);
e548c9df 4344 else if (mode == DImode)
09fa8841 4345 *total = COSTS_N_INSNS (TARGET_MUL32_HIGH ? 10 : 50);
3c50106f
RH
4346 else if (TARGET_MUL32)
4347 *total = COSTS_N_INSNS (4);
4348 else if (TARGET_MAC16)
4349 *total = COSTS_N_INSNS (16);
4350 else if (TARGET_MUL16)
4351 *total = COSTS_N_INSNS (12);
4352 else
4353 *total = COSTS_N_INSNS (50);
4354 return true;
4355 }
4356
4357 case DIV:
4358 case MOD:
4359 {
e548c9df 4360 if (mode == SFmode)
3c50106f
RH
4361 {
4362 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT_DIV ? 8 : 50);
4363 return true;
4364 }
e548c9df 4365 else if (mode == DFmode)
3c50106f
RH
4366 {
4367 *total = COSTS_N_INSNS (50);
4368 return true;
4369 }
4370 }
3bbc2af6 4371 /* Fall through. */
3c50106f
RH
4372
4373 case UDIV:
4374 case UMOD:
4375 {
e548c9df 4376 if (mode == DImode)
ccd02e73 4377 *total = COSTS_N_INSNS (speed ? 100 : 50);
3c50106f
RH
4378 else if (TARGET_DIV32)
4379 *total = COSTS_N_INSNS (32);
4380 else
ccd02e73 4381 *total = COSTS_N_INSNS (speed ? 100 : 50);
3c50106f
RH
4382 return true;
4383 }
4384
4385 case SQRT:
e548c9df 4386 if (mode == SFmode)
3c50106f
RH
4387 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT_SQRT ? 8 : 50);
4388 else
4389 *total = COSTS_N_INSNS (50);
4390 return true;
4391
4392 case SMIN:
4393 case UMIN:
4394 case SMAX:
4395 case UMAX:
4396 *total = COSTS_N_INSNS (TARGET_MINMAX ? 1 : 50);
4397 return true;
4398
4399 case SIGN_EXTRACT:
4400 case SIGN_EXTEND:
4401 *total = COSTS_N_INSNS (TARGET_SEXT ? 1 : 2);
4402 return true;
4403
4404 case ZERO_EXTRACT:
4405 case ZERO_EXTEND:
48e9954d 4406 case IF_THEN_ELSE:
3c50106f
RH
4407 *total = COSTS_N_INSNS (1);
4408 return true;
4409
4410 default:
4411 return false;
4412 }
4413}
4414
ccd02e73 4415static bool
75ab2f0e 4416xtensa_is_insn_L32R_p (const rtx_insn *insn)
ccd02e73
TJJS
4417{
4418 rtx x = PATTERN (insn);
4419
46880cd8
TJJS
4420 if (GET_CODE (x) != SET)
4421 return false;
4422
4423 x = XEXP (x, 1);
4424 if (MEM_P (x))
ccd02e73 4425 {
46880cd8
TJJS
4426 x = XEXP (x, 0);
4427 return (SYMBOL_REF_P (x) || CONST_INT_P (x))
4428 && CONSTANT_POOL_ADDRESS_P (x);
ccd02e73
TJJS
4429 }
4430
46880cd8
TJJS
4431 /* relaxed MOVI instructions, that will be converted to L32R by the
4432 assembler. */
4433 if (CONST_INT_P (x)
4434 && ! xtensa_simm12b (INTVAL (x)))
4435 return true;
4436
ccd02e73
TJJS
4437 return false;
4438}
4439
4440/* Compute a relative costs of RTL insns. This is necessary in order to
4441 achieve better RTL insn splitting/combination result. */
4442
4443static int
4444xtensa_insn_cost (rtx_insn *insn, bool speed)
4445{
4446 if (!(recog_memoized (insn) < 0))
4447 {
4448 int len = get_attr_length (insn), n = (len + 2) / 3;
4449
4450 if (len == 0)
4451 return COSTS_N_INSNS (0);
4452
4453 if (speed) /* For speed cost. */
4454 {
4455 /* "L32R" may be particular slow (implementation-dependent). */
4456 if (xtensa_is_insn_L32R_p (insn))
4457 return COSTS_N_INSNS (1 + xtensa_extra_l32r_costs);
4458
4459 /* Cost based on the pipeline model. */
4460 switch (get_attr_type (insn))
4461 {
4462 case TYPE_STORE:
4463 case TYPE_MOVE:
4464 case TYPE_ARITH:
4465 case TYPE_MULTI:
4466 case TYPE_NOP:
4467 case TYPE_FSTORE:
4468 return COSTS_N_INSNS (n);
4469
4470 case TYPE_LOAD:
4471 return COSTS_N_INSNS (n - 1 + 2);
4472
4473 case TYPE_JUMP:
4474 case TYPE_CALL:
4475 return COSTS_N_INSNS (n - 1 + 3);
4476
4477 case TYPE_FCONV:
4478 case TYPE_FLOAD:
4479 case TYPE_MUL16:
4480 case TYPE_MUL32:
4481 case TYPE_RSR:
4482 return COSTS_N_INSNS (n * 2);
4483
4484 case TYPE_FMADD:
4485 return COSTS_N_INSNS (n * 4);
4486
4487 case TYPE_DIV32:
4488 return COSTS_N_INSNS (n * 16);
4489
4490 default:
4491 break;
4492 }
4493 }
4494 else /* For size cost. */
4495 {
4496 /* Cost based on the instruction length. */
4497 if (get_attr_type (insn) != TYPE_UNKNOWN)
4498 {
4499 /* "L32R" itself plus constant in litpool. */
4500 if (xtensa_is_insn_L32R_p (insn))
4501 return COSTS_N_INSNS (2) + 1;
4502
4503 /* Consider ".n" short instructions. */
4504 return COSTS_N_INSNS (n) - (n * 3 - len);
4505 }
4506 }
4507 }
4508
4509 /* Fall back. */
4510 return pattern_cost (PATTERN (insn), speed);
4511}
4512
bd5bd7ac
KH
4513/* Worker function for TARGET_RETURN_IN_MEMORY. */
4514
4c45af42 4515static bool
586de218 4516xtensa_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
4c45af42
KH
4517{
4518 return ((unsigned HOST_WIDE_INT) int_size_in_bytes (type)
da086e47 4519 > (unsigned) (GP_RETURN_LAST - GP_RETURN_FIRST + 1) * UNITS_PER_WORD);
4c45af42
KH
4520}
4521
e2b2d01e
AS
4522/* Worker function for TARGET_FUNCTION_VALUE. */
4523
4524rtx
89d5982b
TJJS
4525xtensa_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED,
4526 bool outgoing)
e2b2d01e
AS
4527{
4528 return gen_rtx_REG ((INTEGRAL_TYPE_P (valtype)
98a1b4d0
TJJS
4529 && TYPE_PRECISION (valtype) < BITS_PER_WORD)
4530 ? SImode : TYPE_MODE (valtype),
4531 outgoing ? GP_OUTGOING_RETURN : GP_RETURN_FIRST);
e2b2d01e 4532}
7f0ee694 4533
dde8a3a4
AS
4534/* Worker function for TARGET_LIBCALL_VALUE. */
4535
4536static rtx
ef4bddc2 4537xtensa_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
dde8a3a4
AS
4538{
4539 return gen_rtx_REG ((GET_MODE_CLASS (mode) == MODE_INT
4540 && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
98a1b4d0 4541 ? SImode : mode, GP_RETURN_FIRST);
dde8a3a4
AS
4542}
4543
4544/* Worker function TARGET_FUNCTION_VALUE_REGNO_P. */
4545
4546static bool
4547xtensa_function_value_regno_p (const unsigned int regno)
4548{
98a1b4d0 4549 return IN_RANGE (regno, GP_RETURN_FIRST, GP_RETURN_LAST);
dde8a3a4
AS
4550}
4551
2b4fa409
RH
4552/* The static chain is passed in memory. Provide rtx giving 'mem'
4553 expressions that denote where they are stored. */
4554
4555static rtx
c21df29b 4556xtensa_static_chain (const_tree ARG_UNUSED (fndecl_or_type), bool incoming_p)
2b4fa409 4557{
590e2636
MF
4558 if (TARGET_WINDOWED_ABI)
4559 {
4560 rtx base = incoming_p ? arg_pointer_rtx : stack_pointer_rtx;
4561 return gen_frame_mem (Pmode, plus_constant (Pmode, base,
4562 -5 * UNITS_PER_WORD));
4563 }
4564 else
4565 return gen_rtx_REG (Pmode, A8_REG);
2b4fa409
RH
4566}
4567
4568
7f0ee694
BW
4569/* TRAMPOLINE_TEMPLATE: For Xtensa, the trampoline must perform an ENTRY
4570 instruction with a minimal stack frame in order to get some free
4571 registers. Once the actual call target is known, the proper stack frame
4572 size is extracted from the ENTRY instruction at the target and the
4573 current frame is adjusted to match. The trampoline then transfers
4574 control to the instruction following the ENTRY at the target. Note:
4575 this assumes that the target begins with an ENTRY instruction. */
4576
3c1229cb
RH
4577static void
4578xtensa_asm_trampoline_template (FILE *stream)
7f0ee694
BW
4579{
4580 bool use_call0 = (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS);
4581
4582 fprintf (stream, "\t.begin no-transform\n");
7f0ee694 4583
590e2636 4584 if (TARGET_WINDOWED_ABI)
7f0ee694 4585 {
590e2636 4586 fprintf (stream, "\tentry\tsp, %d\n", MIN_FRAME_SIZE);
7f0ee694 4587
590e2636
MF
4588 if (use_call0)
4589 {
4590 /* Save the return address. */
4591 fprintf (stream, "\tmov\ta10, a0\n");
7f0ee694 4592
590e2636
MF
4593 /* Use a CALL0 instruction to skip past the constants and in the
4594 process get the PC into A0. This allows PC-relative access to
4595 the constants without relying on L32R. */
4596 fprintf (stream, "\tcall0\t.Lskipconsts\n");
4597 }
4598 else
4599 fprintf (stream, "\tj\t.Lskipconsts\n");
7f0ee694 4600
590e2636
MF
4601 fprintf (stream, "\t.align\t4\n");
4602 fprintf (stream, ".Lchainval:%s0\n", integer_asm_op (4, TRUE));
4603 fprintf (stream, ".Lfnaddr:%s0\n", integer_asm_op (4, TRUE));
4604 fprintf (stream, ".Lskipconsts:\n");
4605
4606 /* Load the static chain and function address from the trampoline. */
4607 if (use_call0)
4608 {
4609 fprintf (stream, "\taddi\ta0, a0, 3\n");
4610 fprintf (stream, "\tl32i\ta9, a0, 0\n");
4611 fprintf (stream, "\tl32i\ta8, a0, 4\n");
4612 }
4613 else
4614 {
4615 fprintf (stream, "\tl32r\ta9, .Lchainval\n");
4616 fprintf (stream, "\tl32r\ta8, .Lfnaddr\n");
4617 }
4618
4619 /* Store the static chain. */
4620 fprintf (stream, "\ts32i\ta9, sp, %d\n", MIN_FRAME_SIZE - 20);
4621
4622 /* Set the proper stack pointer value. */
4623 fprintf (stream, "\tl32i\ta9, a8, 0\n");
4624 fprintf (stream, "\textui\ta9, a9, %d, 12\n",
4625 TARGET_BIG_ENDIAN ? 8 : 12);
4626 fprintf (stream, "\tslli\ta9, a9, 3\n");
4627 fprintf (stream, "\taddi\ta9, a9, %d\n", -MIN_FRAME_SIZE);
4628 fprintf (stream, "\tsub\ta9, sp, a9\n");
4629 fprintf (stream, "\tmovsp\tsp, a9\n");
4630
4631 if (use_call0)
4632 /* Restore the return address. */
4633 fprintf (stream, "\tmov\ta0, a10\n");
4634
4635 /* Jump to the instruction following the ENTRY. */
4636 fprintf (stream, "\taddi\ta8, a8, 3\n");
4637 fprintf (stream, "\tjx\ta8\n");
4638
4639 /* Pad size to a multiple of TRAMPOLINE_ALIGNMENT. */
4640 if (use_call0)
4641 fprintf (stream, "\t.byte\t0\n");
4642 else
4643 fprintf (stream, "\tnop\n");
7f0ee694
BW
4644 }
4645 else
4646 {
590e2636
MF
4647 if (use_call0)
4648 {
4649 /* Save the return address. */
4650 fprintf (stream, "\tmov\ta10, a0\n");
7f0ee694 4651
590e2636
MF
4652 /* Use a CALL0 instruction to skip past the constants and in the
4653 process get the PC into A0. This allows PC-relative access to
4654 the constants without relying on L32R. */
4655 fprintf (stream, "\tcall0\t.Lskipconsts\n");
4656 }
4657 else
4658 fprintf (stream, "\tj\t.Lskipconsts\n");
7f0ee694 4659
590e2636
MF
4660 fprintf (stream, "\t.align\t4\n");
4661 fprintf (stream, ".Lchainval:%s0\n", integer_asm_op (4, TRUE));
4662 fprintf (stream, ".Lfnaddr:%s0\n", integer_asm_op (4, TRUE));
4663 fprintf (stream, ".Lskipconsts:\n");
7f0ee694 4664
590e2636
MF
4665 /* Load the static chain and function address from the trampoline. */
4666 if (use_call0)
4667 {
4668 fprintf (stream, "\taddi\ta0, a0, 3\n");
4669 fprintf (stream, "\tl32i\ta8, a0, 0\n");
4670 fprintf (stream, "\tl32i\ta9, a0, 4\n");
4671 fprintf (stream, "\tmov\ta0, a10\n");
4672 }
4673 else
4674 {
4675 fprintf (stream, "\tl32r\ta8, .Lchainval\n");
4676 fprintf (stream, "\tl32r\ta9, .Lfnaddr\n");
4677 }
4678 fprintf (stream, "\tjx\ta9\n");
7f0ee694 4679
590e2636
MF
4680 /* Pad size to a multiple of TRAMPOLINE_ALIGNMENT. */
4681 if (use_call0)
4682 fprintf (stream, "\t.byte\t0\n");
4683 else
4684 fprintf (stream, "\tnop\n");
4685 }
7f0ee694
BW
4686 fprintf (stream, "\t.end no-transform\n");
4687}
4688
3c1229cb
RH
4689static void
4690xtensa_trampoline_init (rtx m_tramp, tree fndecl, rtx chain)
7f0ee694 4691{
3c1229cb 4692 rtx func = XEXP (DECL_RTL (fndecl), 0);
7f0ee694 4693 bool use_call0 = (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS);
590e2636
MF
4694 int chain_off;
4695 int func_off;
4696
4697 if (TARGET_WINDOWED_ABI)
4698 {
4699 chain_off = use_call0 ? 12 : 8;
4700 func_off = use_call0 ? 16 : 12;
4701 }
4702 else
4703 {
4704 chain_off = use_call0 ? 8 : 4;
4705 func_off = use_call0 ? 12 : 8;
4706 }
3c1229cb
RH
4707
4708 emit_block_move (m_tramp, assemble_trampoline_template (),
4709 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
4710
4711 emit_move_insn (adjust_address (m_tramp, SImode, chain_off), chain);
4712 emit_move_insn (adjust_address (m_tramp, SImode, func_off), func);
7f0ee694 4713 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_sync_caches"),
db69559b 4714 LCT_NORMAL, VOIDmode, XEXP (m_tramp, 0), Pmode);
7f0ee694
BW
4715}
4716
1a627b35
RS
4717/* Implement TARGET_LEGITIMATE_CONSTANT_P. */
4718
4719static bool
ef4bddc2 4720xtensa_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1a627b35
RS
4721{
4722 return !xtensa_tls_referenced_p (x);
4723}
7f0ee694 4724
6383386a
FY
4725/* Implement TARGET_CAN_USE_DOLOOP_P. */
4726
4727static bool
4728xtensa_can_use_doloop_p (const widest_int &, const widest_int &,
89d5982b 4729 unsigned int loop_depth, bool entered_at_top)
6383386a
FY
4730{
4731 /* Considering limitations in the hardware, only use doloop
4732 for innermost loops which must be entered from the top. */
4733 if (loop_depth > 1 || !entered_at_top)
4734 return false;
4735
4736 return true;
4737}
4738
4739/* NULL if INSN insn is valid within a low-overhead loop.
4740 Otherwise return why doloop cannot be applied. */
4741
4742static const char *
4743xtensa_invalid_within_doloop (const rtx_insn *insn)
4744{
4745 if (CALL_P (insn))
4746 return "Function call in the loop.";
4747
4748 if (JUMP_P (insn) && INSN_CODE (insn) == CODE_FOR_return)
4749 return "Return from a call instruction in the loop.";
4750
4751 return NULL;
4752}
4753
4754/* Optimize LOOP. */
4755
4756static bool
4757hwloop_optimize (hwloop_info loop)
4758{
4759 int i;
4760 edge entry_edge;
4761 basic_block entry_bb;
4762 rtx iter_reg;
4763 rtx_insn *insn, *seq, *entry_after;
4764
4765 if (loop->depth > 1)
4766 {
4767 if (dump_file)
89d5982b
TJJS
4768 fprintf (dump_file, ";; loop %d is not innermost\n",
4769 loop->loop_no);
6383386a
FY
4770 return false;
4771 }
4772
4773 if (!loop->incoming_dest)
4774 {
4775 if (dump_file)
89d5982b
TJJS
4776 fprintf (dump_file, ";; loop %d has more than one entry\n",
4777 loop->loop_no);
6383386a
FY
4778 return false;
4779 }
4780
4781 if (loop->incoming_dest != loop->head)
4782 {
4783 if (dump_file)
89d5982b
TJJS
4784 fprintf (dump_file, ";; loop %d is not entered from head\n",
4785 loop->loop_no);
6383386a
FY
4786 return false;
4787 }
4788
4789 if (loop->has_call || loop->has_asm)
4790 {
4791 if (dump_file)
89d5982b
TJJS
4792 fprintf (dump_file, ";; loop %d has invalid insn\n",
4793 loop->loop_no);
6383386a
FY
4794 return false;
4795 }
4796
4797 /* Scan all the blocks to make sure they don't use iter_reg. */
4798 if (loop->iter_reg_used || loop->iter_reg_used_outside)
4799 {
4800 if (dump_file)
89d5982b
TJJS
4801 fprintf (dump_file, ";; loop %d uses iterator\n",
4802 loop->loop_no);
6383386a
FY
4803 return false;
4804 }
4805
4806 /* Check if start_label appears before doloop_end. */
4807 insn = loop->start_label;
4808 while (insn && insn != loop->loop_end)
4809 insn = NEXT_INSN (insn);
4810
4811 if (!insn)
4812 {
4813 if (dump_file)
89d5982b
TJJS
4814 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
4815 loop->loop_no);
6383386a
FY
4816 return false;
4817 }
4818
4819 /* Get the loop iteration register. */
4820 iter_reg = loop->iter_reg;
4821
4822 gcc_assert (REG_P (iter_reg));
4823
4824 entry_edge = NULL;
4825
4826 FOR_EACH_VEC_SAFE_ELT (loop->incoming, i, entry_edge)
4827 if (entry_edge->flags & EDGE_FALLTHRU)
4828 break;
4829
4830 if (entry_edge == NULL)
4831 return false;
4832
4833 /* Place the zero_cost_loop_start instruction before the loop. */
4834 entry_bb = entry_edge->src;
4835
4836 start_sequence ();
4837
4838 insn = emit_insn (gen_zero_cost_loop_start (loop->iter_reg,
89d5982b
TJJS
4839 loop->start_label,
4840 loop->iter_reg));
6383386a
FY
4841
4842 seq = get_insns ();
4843
d7326aaf
MF
4844 entry_after = BB_END (entry_bb);
4845 if (!single_succ_p (entry_bb) || vec_safe_length (loop->incoming) > 1
4846 || !entry_after)
6383386a
FY
4847 {
4848 basic_block new_bb;
4849 edge e;
4850 edge_iterator ei;
4851
4852 emit_insn_before (seq, BB_HEAD (loop->head));
4853 seq = emit_label_before (gen_label_rtx (), seq);
4854 new_bb = create_basic_block (seq, insn, entry_bb);
4855 FOR_EACH_EDGE (e, ei, loop->incoming)
89d5982b
TJJS
4856 {
4857 if (!(e->flags & EDGE_FALLTHRU))
4858 redirect_edge_and_branch_force (e, new_bb);
4859 else
4860 redirect_edge_succ (e, new_bb);
4861 }
6383386a
FY
4862
4863 make_edge (new_bb, loop->head, 0);
4864 }
4865 else
4866 {
6383386a 4867 while (DEBUG_INSN_P (entry_after)
89d5982b 4868 || (NOTE_P (entry_after)
00b94487 4869 && NOTE_KIND (entry_after) != NOTE_INSN_BASIC_BLOCK))
89d5982b 4870 entry_after = PREV_INSN (entry_after);
6383386a
FY
4871
4872 emit_insn_after (seq, entry_after);
4873 }
4874
4875 end_sequence ();
4876
4877 return true;
4878}
4879
4880/* A callback for the hw-doloop pass. Called when a loop we have discovered
4881 turns out not to be optimizable; we have to split the loop_end pattern into
4882 a subtract and a test. */
4883
4884static void
4885hwloop_fail (hwloop_info loop)
4886{
4887 rtx test;
4888 rtx_insn *insn = loop->loop_end;
4889
4890 emit_insn_before (gen_addsi3 (loop->iter_reg,
89d5982b
TJJS
4891 loop->iter_reg,
4892 constm1_rtx),
4893 loop->loop_end);
6383386a
FY
4894
4895 test = gen_rtx_NE (VOIDmode, loop->iter_reg, const0_rtx);
4896 insn = emit_jump_insn_before (gen_cbranchsi4 (test,
89d5982b
TJJS
4897 loop->iter_reg, const0_rtx,
4898 loop->start_label),
4899 loop->loop_end);
6383386a
FY
4900
4901 JUMP_LABEL (insn) = loop->start_label;
4902 LABEL_NUSES (loop->start_label)++;
4903 delete_insn (loop->loop_end);
4904}
4905
4906/* A callback for the hw-doloop pass. This function examines INSN; if
4907 it is a doloop_end pattern we recognize, return the reg rtx for the
4908 loop counter. Otherwise, return NULL_RTX. */
4909
4910static rtx
4911hwloop_pattern_reg (rtx_insn *insn)
4912{
4913 rtx reg;
4914
4915 if (!JUMP_P (insn) || recog_memoized (insn) != CODE_FOR_loop_end)
4916 return NULL_RTX;
4917
4918 reg = SET_DEST (XVECEXP (PATTERN (insn), 0, 1));
4919 if (!REG_P (reg))
4920 return NULL_RTX;
4921
4922 return reg;
4923}
4924
4925
4926static struct hw_doloop_hooks xtensa_doloop_hooks =
4927{
4928 hwloop_pattern_reg,
4929 hwloop_optimize,
4930 hwloop_fail
4931};
4932
4933/* Run from machine_dependent_reorg, this pass looks for doloop_end insns
4934 and tries to rewrite the RTL of these loops so that proper Xtensa
4935 hardware loops are generated. */
4936
4937static void
4938xtensa_reorg_loops (void)
4939{
1a711a0b
MF
4940 if (TARGET_LOOPS)
4941 reorg_loops (false, &xtensa_doloop_hooks);
c6836000 4942}
6383386a
FY
4943
4944/* Implement the TARGET_MACHINE_DEPENDENT_REORG pass. */
4945
4946static void
4947xtensa_reorg (void)
4948{
4949 /* We are freeing block_for_insn in the toplev to keep compatibility
4950 with old MDEP_REORGS that are not CFG based. Recompute it now. */
4951 compute_bb_for_insn ();
4952
4953 df_analyze ();
4954
4955 /* Doloop optimization. */
4956 xtensa_reorg_loops ();
4957}
4958
590e2636
MF
4959/* Update register usage after having seen the compiler flags. */
4960
4961static void
4962xtensa_conditional_register_usage (void)
4963{
4964 unsigned i, c_mask;
4965
4966 c_mask = TARGET_WINDOWED_ABI ? (1 << 1) : (1 << 2);
4967
4968 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4969 {
4970 /* Set/reset conditionally defined registers from
4971 CALL_USED_REGISTERS initializer. */
4972 if (call_used_regs[i] > 1)
4973 call_used_regs[i] = !!(call_used_regs[i] & c_mask);
4974 }
4975
4976 /* Remove hard FP register from the preferred reload registers set. */
4977 CLEAR_HARD_REG_BIT (reg_class_contents[(int)RL_REGS],
4978 HARD_FRAME_POINTER_REGNUM);
e0927d7d
TJJS
4979
4980 /* Register A0 holds the return address upon entry to a function
4981 for the CALL0 ABI, but unlike the windowed register ABI, it is
4982 not reserved for this purpose and may hold other values after
4983 the return address has been saved. */
4984 if (!TARGET_WINDOWED_ABI)
4985 fixed_regs[A0_REG] = 0;
590e2636
MF
4986}
4987
4988/* Map hard register number to register class */
4989
4990enum reg_class xtensa_regno_to_class (int regno)
4991{
4992 static const enum reg_class regno_to_class[FIRST_PSEUDO_REGISTER] =
4993 {
4994 RL_REGS, SP_REG, RL_REGS, RL_REGS,
4995 RL_REGS, RL_REGS, RL_REGS, RL_REGS,
4996 RL_REGS, RL_REGS, RL_REGS, RL_REGS,
4997 RL_REGS, RL_REGS, RL_REGS, RL_REGS,
4998 AR_REGS, AR_REGS, BR_REGS,
4999 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
5000 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
5001 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
5002 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
5003 ACC_REG,
5004 };
5005
5006 if (regno == HARD_FRAME_POINTER_REGNUM)
5007 return GR_REGS;
5008 else
5009 return regno_to_class[regno];
5010}
5011
58e17cf8
RS
5012/* Implement TARGET_CONSTANT_ALIGNMENT. Align string constants and
5013 constructors to at least a word boundary. The typical use of this
5014 macro is to increase alignment for string constants to be word
5015 aligned so that 'strcpy' calls that copy constants can be done
5016 inline. */
5017
5018static HOST_WIDE_INT
5019xtensa_constant_alignment (const_tree exp, HOST_WIDE_INT align)
5020{
5021 if ((TREE_CODE (exp) == STRING_CST || TREE_CODE (exp) == CONSTRUCTOR)
5022 && !optimize_size)
5023 return MAX (align, BITS_PER_WORD);
5024 return align;
5025}
5026
f50c32fa
MF
5027static bool
5028xtensa_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
5029{
5030 gcc_assert (from == ARG_POINTER_REGNUM || from == FRAME_POINTER_REGNUM);
5031
5032 /* If we need a frame pointer, ARG_POINTER_REGNUM and FRAME_POINTER_REGNUM
5033 can only eliminate to HARD_FRAME_POINTER_REGNUM. */
5034 return to == HARD_FRAME_POINTER_REGNUM
5035 || (!frame_pointer_needed && to == STACK_POINTER_REGNUM);
5036}
5037
2a31c321
RS
5038/* Implement TARGET_STARTING_FRAME_OFFSET. */
5039
5040static HOST_WIDE_INT
5041xtensa_starting_frame_offset (void)
5042{
5043 if (FRAME_GROWS_DOWNWARD)
5044 return 0;
5045 return crtl->outgoing_args_size;
5046}
5047
8c9ee176
MF
5048/* Implement TARGET_ASAN_SHADOW_OFFSET. */
5049
5050static unsigned HOST_WIDE_INT
5051xtensa_asan_shadow_offset (void)
5052{
5053 return HOST_WIDE_INT_UC (0x10000000);
5054}
5055
43b0c56f
TJJS
5056/* Implement TARGET_FUNCTION_OK_FOR_SIBCALL. */
5057static bool
5058xtensa_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED, tree exp ATTRIBUTE_UNUSED)
5059{
5060 /* Do not allow sibcalls when windowed registers ABI is in effect. */
5061 if (TARGET_WINDOWED_ABI)
5062 return false;
5063
5064 return true;
5065}
5066
0bf60f68
MF
5067static bool
5068xtensa_can_output_mi_thunk (const_tree thunk_fndecl ATTRIBUTE_UNUSED,
5069 HOST_WIDE_INT delta ATTRIBUTE_UNUSED,
5070 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
5071 const_tree function ATTRIBUTE_UNUSED)
5072{
5073 if (TARGET_WINDOWED_ABI)
5074 return false;
5075
5076 return true;
5077}
5078
5079/* Output code to add DELTA to the first argument, and then jump
5080 to FUNCTION. Used for C++ multiple inheritance. */
5081static void
5082xtensa_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
5083 HOST_WIDE_INT delta,
5084 HOST_WIDE_INT vcall_offset,
5085 tree function)
5086{
5087 rtx this_rtx;
5088 rtx funexp;
5089 rtx_insn *insn;
5090 int this_reg_no;
5091 rtx temp0 = gen_rtx_REG (Pmode, A9_REG);
5092 const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
5093
5094 reload_completed = 1;
5095
5096 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
5097 this_reg_no = 3;
5098 else
5099 this_reg_no = 2;
5100
5101 this_rtx = gen_rtx_REG (Pmode, A0_REG + this_reg_no);
5102
5103 if (delta)
5104 {
5105 if (xtensa_simm8 (delta))
5106 emit_insn (gen_addsi3 (this_rtx, this_rtx, GEN_INT (delta)));
5107 else
5108 {
5109 emit_move_insn (temp0, GEN_INT (delta));
5110 emit_insn (gen_addsi3 (this_rtx, this_rtx, temp0));
5111 }
5112 }
5113
5114 if (vcall_offset)
5115 {
5116 rtx temp1 = gen_rtx_REG (Pmode, A0_REG + 10);
5117 rtx addr = temp1;
5118
5119 emit_move_insn (temp0, gen_rtx_MEM (Pmode, this_rtx));
5120 if (xtensa_uimm8x4 (vcall_offset))
5121 addr = plus_constant (Pmode, temp0, vcall_offset);
5122 else if (xtensa_simm8 (vcall_offset))
5123 emit_insn (gen_addsi3 (temp1, temp0, GEN_INT (vcall_offset)));
5124 else
5125 {
5126 emit_move_insn (temp1, GEN_INT (vcall_offset));
5127 emit_insn (gen_addsi3 (temp1, temp0, temp1));
5128 }
5129 emit_move_insn (temp1, gen_rtx_MEM (Pmode, addr));
5130 emit_insn (gen_add2_insn (this_rtx, temp1));
5131 }
5132
5133 /* Generate a tail call to the target function. */
5134 if (!TREE_USED (function))
5135 {
5136 assemble_external (function);
5137 TREE_USED (function) = 1;
5138 }
5139
5140 funexp = XEXP (DECL_RTL (function), 0);
5141 funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
5142 insn = emit_call_insn (gen_sibcall (funexp, const0_rtx));
5143 SIBLING_CALL_P (insn) = 1;
5144
5145 insn = get_insns ();
5146 shorten_branches (insn);
5147 assemble_start_function (thunk, fnname);
5148 final_start_function (insn, file, 1);
5149 final (insn, file, 1);
5150 final_end_function ();
5151 assemble_end_function (thunk, fnname);
5152
5153 /* Stop pretending to be a post-reload pass. */
5154 reload_completed = 0;
5155}
5156
b7641550
MF
5157static rtx
5158xtensa_delegitimize_address (rtx op)
5159{
5160 switch (GET_CODE (op))
5161 {
5162 case CONST:
5163 return xtensa_delegitimize_address (XEXP (op, 0));
5164
5165 case UNSPEC:
5166 if (XINT (op, 1) == UNSPEC_PLT)
5167 return XVECEXP(op, 0, 0);
5168 break;
5169
5170 default:
5171 break;
5172 }
5173 return op;
5174}
5175
4f3f0296
TJJS
5176/* Implement TARGET_LRA_P. */
5177
5178static bool
5179xtensa_lra_p (void)
5180{
5181 return TARGET_LRA;
5182}
5183
e2500fed 5184#include "gt-xtensa.h"