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