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