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