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