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