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