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