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