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