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