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