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