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