]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/xtensa/xtensa.c
Daily bump.
[thirdparty/gcc.git] / gcc / config / xtensa / xtensa.c
CommitLineData
03984308 1/* Subroutines for insn-output.c for Tensilica's Xtensa architecture.
cbe34bb5 2 Copyright (C) 2001-2017 Free Software Foundation, Inc.
03984308
BW
3 Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
2f83c7d6 9Software Foundation; either version 3, or (at your option) any later
03984308
BW
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
2f83c7d6
NC
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
03984308
BW
20
21#include "config.h"
22#include "system.h"
4977bab6 23#include "coretypes.h"
c7131fb2 24#include "backend.h"
e11c4407
AM
25#include "target.h"
26#include "rtl.h"
c7131fb2
AM
27#include "tree.h"
28#include "gimple.h"
e11c4407 29#include "cfghooks.h"
c7131fb2 30#include "df.h"
4d0cdd0c 31#include "memmodel.h"
e11c4407
AM
32#include "tm_p.h"
33#include "stringpool.h"
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)
3904010d
MF
1783 sprintf (result, "call%d\t" HOST_WIDE_INT_PRINT_HEX,
1784 WINDOW_SIZE, INTVAL (tgt));
03984308 1785 else if (register_operand (tgt, VOIDmode))
590e2636 1786 sprintf (result, "callx%d\t%%%d", WINDOW_SIZE, callop);
03984308 1787 else
590e2636 1788 sprintf (result, "call%d\t%%%d", WINDOW_SIZE, callop);
03984308
BW
1789
1790 return result;
1791}
1792
1793
da1f39e4 1794bool
ef4bddc2 1795xtensa_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
da1f39e4
BW
1796{
1797 /* Allow constant pool addresses. */
1798 if (mode != BLKmode && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
6a7a462c
BW
1799 && ! TARGET_CONST16 && constantpool_address_p (addr)
1800 && ! xtensa_tls_referenced_p (addr))
da1f39e4
BW
1801 return true;
1802
1803 while (GET_CODE (addr) == SUBREG)
1804 addr = SUBREG_REG (addr);
1805
1806 /* Allow base registers. */
1807 if (GET_CODE (addr) == REG && BASE_REG_P (addr, strict))
1808 return true;
1809
1810 /* Check for "register + offset" addressing. */
1811 if (GET_CODE (addr) == PLUS)
1812 {
1813 rtx xplus0 = XEXP (addr, 0);
1814 rtx xplus1 = XEXP (addr, 1);
1815 enum rtx_code code0;
1816 enum rtx_code code1;
1817
1818 while (GET_CODE (xplus0) == SUBREG)
1819 xplus0 = SUBREG_REG (xplus0);
1820 code0 = GET_CODE (xplus0);
1821
1822 while (GET_CODE (xplus1) == SUBREG)
1823 xplus1 = SUBREG_REG (xplus1);
1824 code1 = GET_CODE (xplus1);
1825
1826 /* Swap operands if necessary so the register is first. */
1827 if (code0 != REG && code1 == REG)
1828 {
1829 xplus0 = XEXP (addr, 1);
1830 xplus1 = XEXP (addr, 0);
1831 code0 = GET_CODE (xplus0);
1832 code1 = GET_CODE (xplus1);
1833 }
1834
1835 if (code0 == REG && BASE_REG_P (xplus0, strict)
1836 && code1 == CONST_INT
1837 && xtensa_mem_offset (INTVAL (xplus1), mode))
1838 return true;
1839 }
1840
1841 return false;
1842}
1843
1844
6a7a462c
BW
1845/* Construct the SYMBOL_REF for the _TLS_MODULE_BASE_ symbol. */
1846
1847static GTY(()) rtx xtensa_tls_module_base_symbol;
1848
1849static rtx
1850xtensa_tls_module_base (void)
1851{
1852 if (! xtensa_tls_module_base_symbol)
1853 {
1854 xtensa_tls_module_base_symbol =
1855 gen_rtx_SYMBOL_REF (Pmode, "_TLS_MODULE_BASE_");
1856 SYMBOL_REF_FLAGS (xtensa_tls_module_base_symbol)
1857 |= TLS_MODEL_GLOBAL_DYNAMIC << SYMBOL_FLAG_TLS_SHIFT;
1858 }
1859
1860 return xtensa_tls_module_base_symbol;
1861}
1862
1863
240a513f 1864static rtx_insn *
6a7a462c
BW
1865xtensa_call_tls_desc (rtx sym, rtx *retp)
1866{
e1b8828b 1867 rtx fn, arg, a_io;
240a513f 1868 rtx_insn *call_insn, *insns;
6a7a462c
BW
1869
1870 start_sequence ();
1871 fn = gen_reg_rtx (Pmode);
1872 arg = gen_reg_rtx (Pmode);
e1b8828b 1873 a_io = gen_rtx_REG (Pmode, WINDOW_SIZE + 2);
6a7a462c
BW
1874
1875 emit_insn (gen_tls_func (fn, sym));
1876 emit_insn (gen_tls_arg (arg, sym));
e1b8828b
MF
1877 emit_move_insn (a_io, arg);
1878 call_insn = emit_call_insn (gen_tls_call (a_io, fn, sym, const1_rtx));
1879 use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), a_io);
6a7a462c
BW
1880 insns = get_insns ();
1881 end_sequence ();
1882
e1b8828b 1883 *retp = a_io;
6a7a462c
BW
1884 return insns;
1885}
1886
1887
1888static rtx
1889xtensa_legitimize_tls_address (rtx x)
1890{
1891 unsigned int model = SYMBOL_REF_TLS_MODEL (x);
240a513f
DM
1892 rtx dest, tp, ret, modbase, base, addend;
1893 rtx_insn *insns;
6a7a462c
BW
1894
1895 dest = gen_reg_rtx (Pmode);
1896 switch (model)
1897 {
1898 case TLS_MODEL_GLOBAL_DYNAMIC:
1899 insns = xtensa_call_tls_desc (x, &ret);
1900 emit_libcall_block (insns, dest, ret, x);
1901 break;
1902
1903 case TLS_MODEL_LOCAL_DYNAMIC:
1904 base = gen_reg_rtx (Pmode);
1905 modbase = xtensa_tls_module_base ();
1906 insns = xtensa_call_tls_desc (modbase, &ret);
1907 emit_libcall_block (insns, base, ret, modbase);
1908 addend = force_reg (SImode, gen_sym_DTPOFF (x));
1909 emit_insn (gen_addsi3 (dest, base, addend));
1910 break;
1911
1912 case TLS_MODEL_INITIAL_EXEC:
1913 case TLS_MODEL_LOCAL_EXEC:
1914 tp = gen_reg_rtx (SImode);
f959607b 1915 emit_insn (gen_get_thread_pointersi (tp));
6a7a462c
BW
1916 addend = force_reg (SImode, gen_sym_TPOFF (x));
1917 emit_insn (gen_addsi3 (dest, tp, addend));
1918 break;
1919
1920 default:
1921 gcc_unreachable ();
1922 }
1923
1924 return dest;
1925}
1926
1927
da1f39e4
BW
1928rtx
1929xtensa_legitimize_address (rtx x,
1930 rtx oldx ATTRIBUTE_UNUSED,
ef4bddc2 1931 machine_mode mode)
da1f39e4 1932{
6a7a462c
BW
1933 if (xtensa_tls_symbol_p (x))
1934 return xtensa_legitimize_tls_address (x);
1935
da1f39e4
BW
1936 if (GET_CODE (x) == PLUS)
1937 {
1938 rtx plus0 = XEXP (x, 0);
1939 rtx plus1 = XEXP (x, 1);
1940
1941 if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG)
1942 {
1943 plus0 = XEXP (x, 1);
1944 plus1 = XEXP (x, 0);
1945 }
1946
1947 /* Try to split up the offset to use an ADDMI instruction. */
1948 if (GET_CODE (plus0) == REG
1949 && GET_CODE (plus1) == CONST_INT
1950 && !xtensa_mem_offset (INTVAL (plus1), mode)
1951 && !xtensa_simm8 (INTVAL (plus1))
1952 && xtensa_mem_offset (INTVAL (plus1) & 0xff, mode)
1953 && xtensa_simm8x256 (INTVAL (plus1) & ~0xff))
1954 {
1955 rtx temp = gen_reg_rtx (Pmode);
1956 rtx addmi_offset = GEN_INT (INTVAL (plus1) & ~0xff);
f7df4a84
RS
1957 emit_insn (gen_rtx_SET (temp, gen_rtx_PLUS (Pmode, plus0,
1958 addmi_offset)));
da1f39e4
BW
1959 return gen_rtx_PLUS (Pmode, temp, GEN_INT (INTVAL (plus1) & 0xff));
1960 }
1961 }
1962
506d7b68 1963 return x;
da1f39e4
BW
1964}
1965
a1a79768
AS
1966/* Worker function for TARGET_MODE_DEPENDENT_ADDRESS_P.
1967
1968 Treat constant-pool references as "mode dependent" since they can
1969 only be accessed with SImode loads. This works around a bug in the
1970 combiner where a constant pool reference is temporarily converted
1971 to an HImode load, which is then assumed to zero-extend based on
1972 our definition of LOAD_EXTEND_OP. This is wrong because the high
1973 bits of a 16-bit value in the constant pool are now sign-extended
1974 by default. */
1975
1976static bool
5bfed9a9
GJL
1977xtensa_mode_dependent_address_p (const_rtx addr,
1978 addr_space_t as ATTRIBUTE_UNUSED)
a1a79768
AS
1979{
1980 return constantpool_address_p (addr);
1981}
da1f39e4 1982
6a7a462c
BW
1983/* Return TRUE if X contains any TLS symbol references. */
1984
1985bool
1986xtensa_tls_referenced_p (rtx x)
1987{
1988 if (! TARGET_HAVE_TLS)
1989 return false;
1990
2f36a994
RS
1991 subrtx_iterator::array_type array;
1992 FOR_EACH_SUBRTX (iter, array, x, ALL)
1993 {
1994 const_rtx x = *iter;
1995 if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0)
1996 return true;
1997
1998 /* Ignore TLS references that have already been legitimized. */
1999 if (GET_CODE (x) == UNSPEC)
2000 switch (XINT (x, 1))
2001 {
2002 case UNSPEC_TPOFF:
2003 case UNSPEC_DTPOFF:
2004 case UNSPEC_TLS_FUNC:
2005 case UNSPEC_TLS_ARG:
2006 case UNSPEC_TLS_CALL:
2007 iter.skip_subrtxes ();
2008 break;
2009 default:
2010 break;
2011 }
2012 }
2013 return false;
6a7a462c
BW
2014}
2015
2016
fbbf66e7
RS
2017/* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
2018
2019static bool
ef4bddc2 2020xtensa_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
fbbf66e7
RS
2021{
2022 return xtensa_tls_referenced_p (x);
2023}
2024
2025
b0c6e48f 2026/* Return the debugger register number to use for 'regno'. */
03984308
BW
2027
2028int
ffbc8796 2029xtensa_dbx_register_number (int regno)
03984308
BW
2030{
2031 int first = -1;
633e4eb4
BW
2032
2033 if (GP_REG_P (regno))
2034 {
2035 regno -= GP_REG_FIRST;
2036 first = 0;
2037 }
2038 else if (BR_REG_P (regno))
2039 {
2040 regno -= BR_REG_FIRST;
2041 first = 16;
2042 }
2043 else if (FP_REG_P (regno))
2044 {
2045 regno -= FP_REG_FIRST;
b0c6e48f 2046 first = 48;
633e4eb4 2047 }
03984308
BW
2048 else if (ACC_REG_P (regno))
2049 {
b0c6e48f
BW
2050 first = 0x200; /* Start of Xtensa special registers. */
2051 regno = 16; /* ACCLO is special register 16. */
03984308
BW
2052 }
2053
2054 /* When optimizing, we sometimes get asked about pseudo-registers
638db43e 2055 that don't represent hard registers. Return 0 for these. */
03984308
BW
2056 if (first == -1)
2057 return 0;
2058
2059 return first + regno;
2060}
2061
2062
2063/* Argument support functions. */
2064
2065/* Initialize CUMULATIVE_ARGS for a function. */
2066
2067void
997b8b4d 2068init_cumulative_args (CUMULATIVE_ARGS *cum, int incoming)
03984308
BW
2069{
2070 cum->arg_words = 0;
997b8b4d 2071 cum->incoming = incoming;
03984308
BW
2072}
2073
ffbc8796 2074
03984308
BW
2075/* Advance the argument to the next argument position. */
2076
626a4b31 2077static void
ef4bddc2 2078xtensa_function_arg_advance (cumulative_args_t cum, machine_mode mode,
626a4b31 2079 const_tree type, bool named ATTRIBUTE_UNUSED)
03984308
BW
2080{
2081 int words, max;
2082 int *arg_words;
2083
d5cc9181 2084 arg_words = &get_cumulative_args (cum)->arg_words;
03984308
BW
2085 max = MAX_ARGS_IN_REGISTERS;
2086
2087 words = (((mode != BLKmode)
2088 ? (int) GET_MODE_SIZE (mode)
2089 : int_size_in_bytes (type)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
2090
85d91d5b
BW
2091 if (*arg_words < max
2092 && (targetm.calls.must_pass_in_stack (mode, type)
2093 || *arg_words + words > max))
03984308
BW
2094 *arg_words = max;
2095
2096 *arg_words += words;
2097}
2098
2099
2100/* Return an RTL expression containing the register for the given mode,
368ebcd6 2101 or 0 if the argument is to be passed on the stack. INCOMING_P is nonzero
ffbc8796 2102 if this is an incoming argument to the current function. */
03984308 2103
626a4b31 2104static rtx
ef4bddc2 2105xtensa_function_arg_1 (cumulative_args_t cum_v, machine_mode mode,
626a4b31 2106 const_tree type, bool incoming_p)
03984308 2107{
d5cc9181 2108 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
03984308
BW
2109 int regbase, words, max;
2110 int *arg_words;
2111 int regno;
03984308
BW
2112
2113 arg_words = &cum->arg_words;
2114 regbase = (incoming_p ? GP_ARG_FIRST : GP_OUTGOING_ARG_FIRST);
2115 max = MAX_ARGS_IN_REGISTERS;
2116
2117 words = (((mode != BLKmode)
2118 ? (int) GET_MODE_SIZE (mode)
2119 : int_size_in_bytes (type)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
2120
2121 if (type && (TYPE_ALIGN (type) > BITS_PER_WORD))
822e895c 2122 {
d2348985 2123 int align = MIN (TYPE_ALIGN (type), STACK_BOUNDARY) / BITS_PER_WORD;
822e895c
BW
2124 *arg_words = (*arg_words + align - 1) & -align;
2125 }
03984308
BW
2126
2127 if (*arg_words + words > max)
2128 return (rtx)0;
2129
2130 regno = regbase + *arg_words;
03984308 2131
997b8b4d 2132 if (cum->incoming && regno <= A7_REG && regno + words > A7_REG)
590e2636 2133 cfun->machine->need_a7_copy = TARGET_WINDOWED_ABI;
03984308 2134
997b8b4d 2135 return gen_rtx_REG (mode, regno);
03984308
BW
2136}
2137
626a4b31
NF
2138/* Implement TARGET_FUNCTION_ARG. */
2139
2140static rtx
ef4bddc2 2141xtensa_function_arg (cumulative_args_t cum, machine_mode mode,
626a4b31
NF
2142 const_tree type, bool named ATTRIBUTE_UNUSED)
2143{
2144 return xtensa_function_arg_1 (cum, mode, type, false);
2145}
2146
2147/* Implement TARGET_FUNCTION_INCOMING_ARG. */
2148
2149static rtx
ef4bddc2 2150xtensa_function_incoming_arg (cumulative_args_t cum, machine_mode mode,
626a4b31
NF
2151 const_tree type, bool named ATTRIBUTE_UNUSED)
2152{
2153 return xtensa_function_arg_1 (cum, mode, type, true);
2154}
03984308 2155
c2ed6cf8 2156static unsigned int
ef4bddc2 2157xtensa_function_arg_boundary (machine_mode mode, const_tree type)
d2348985
BW
2158{
2159 unsigned int alignment;
2160
2161 alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode);
2162 if (alignment < PARM_BOUNDARY)
2163 alignment = PARM_BOUNDARY;
2164 if (alignment > STACK_BOUNDARY)
2165 alignment = STACK_BOUNDARY;
2166 return alignment;
2167}
2168
2169
6e5ff6e7 2170static bool
586de218 2171xtensa_return_in_msb (const_tree valtype)
6e5ff6e7
BW
2172{
2173 return (TARGET_BIG_ENDIAN
2174 && AGGREGATE_TYPE_P (valtype)
2175 && int_size_in_bytes (valtype) >= UNITS_PER_WORD);
2176}
2177
2178
c5387660
JM
2179static void
2180xtensa_option_override (void)
03984308
BW
2181{
2182 int regno;
ef4bddc2 2183 machine_mode mode;
03984308 2184
1a711a0b
MF
2185 /* Use CONST16 in the absence of L32R.
2186 Set it in the TARGET_OPTION_OVERRIDE to avoid dependency on xtensa
2187 configuration in the xtensa-common.c */
2188
2189 if (!TARGET_L32R)
2190 target_flags |= MASK_CONST16;
2191
03984308
BW
2192 if (!TARGET_BOOLEANS && TARGET_HARD_FLOAT)
2193 error ("boolean registers required for the floating-point option");
2194
638db43e 2195 /* Set up array giving whether a given register can hold a given mode. */
03984308
BW
2196 for (mode = VOIDmode;
2197 mode != MAX_MACHINE_MODE;
ef4bddc2 2198 mode = (machine_mode) ((int) mode + 1))
03984308
BW
2199 {
2200 int size = GET_MODE_SIZE (mode);
0a2aaacc 2201 enum mode_class mclass = GET_MODE_CLASS (mode);
03984308
BW
2202
2203 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
2204 {
2205 int temp;
2206
2207 if (ACC_REG_P (regno))
f42f5a1b 2208 temp = (TARGET_MAC16
0a2aaacc 2209 && (mclass == MODE_INT) && (size <= UNITS_PER_WORD));
03984308
BW
2210 else if (GP_REG_P (regno))
2211 temp = ((regno & 1) == 0 || (size <= UNITS_PER_WORD));
2212 else if (FP_REG_P (regno))
2213 temp = (TARGET_HARD_FLOAT && (mode == SFmode));
2214 else if (BR_REG_P (regno))
2215 temp = (TARGET_BOOLEANS && (mode == CCmode));
2216 else
2217 temp = FALSE;
2218
2219 xtensa_hard_regno_mode_ok[(int) mode][regno] = temp;
2220 }
2221 }
2222
2223 init_machine_status = xtensa_init_machine_status;
03984308 2224
f42f5a1b
BW
2225 /* Check PIC settings. PIC is only supported when using L32R
2226 instructions, and some targets need to always use PIC. */
2227 if (flag_pic && TARGET_CONST16)
2228 error ("-f%s is not supported with CONST16 instructions",
2229 (flag_pic > 1 ? "PIC" : "pic"));
1b408ba1
SA
2230 else if (TARGET_FORCE_NO_PIC)
2231 flag_pic = 0;
f42f5a1b
BW
2232 else if (XTENSA_ALWAYS_PIC)
2233 {
2234 if (TARGET_CONST16)
2235 error ("PIC is required but not supported with CONST16 instructions");
2236 flag_pic = 1;
2237 }
2238 /* There's no need for -fPIC (as opposed to -fpic) on Xtensa. */
2239 if (flag_pic > 1)
03984308 2240 flag_pic = 1;
166b25dc
BW
2241 if (flag_pic && !flag_pie)
2242 flag_shlib = 1;
87c8b4be
CT
2243
2244 /* Hot/cold partitioning does not work on this architecture, because of
2245 constant pools (the load instruction cannot necessarily reach that far).
2246 Therefore disable it on this architecture. */
2247 if (flag_reorder_blocks_and_partition)
2248 {
2249 flag_reorder_blocks_and_partition = 0;
2250 flag_reorder_blocks = 1;
2251 }
03984308
BW
2252}
2253
03984308
BW
2254/* A C compound statement to output to stdio stream STREAM the
2255 assembler syntax for an instruction operand X. X is an RTL
2256 expression.
2257
2258 CODE is a value that can be used to specify one of several ways
2259 of printing the operand. It is used when identical operands
2260 must be printed differently depending on the context. CODE
2261 comes from the '%' specification that was used to request
2262 printing of the operand. If the specification was just '%DIGIT'
2263 then CODE is 0; if the specification was '%LTR DIGIT' then CODE
2264 is the ASCII code for LTR.
2265
2266 If X is a register, this macro should print the register's name.
2267 The names can be found in an array 'reg_names' whose type is
2268 'char *[]'. 'reg_names' is initialized from 'REGISTER_NAMES'.
2269
2270 When the machine description has a specification '%PUNCT' (a '%'
2271 followed by a punctuation character), this macro is called with
2272 a null pointer for X and the punctuation character for CODE.
2273
2274 'a', 'c', 'l', and 'n' are reserved.
633e4eb4 2275
03984308
BW
2276 The Xtensa specific codes are:
2277
2278 'd' CONST_INT, print as signed decimal
2279 'x' CONST_INT, print as signed hexadecimal
2280 'K' CONST_INT, print number of bits in mask for EXTUI
2281 'R' CONST_INT, print (X & 0x1f)
2282 'L' CONST_INT, print ((32 - X) & 0x1f)
2283 'D' REG, print second register of double-word register operand
2284 'N' MEM, print address of next word following a memory operand
2285 'v' MEM, if memory reference is volatile, output a MEMW before it
f42f5a1b
BW
2286 't' any constant, add "@h" suffix for top 16 bits
2287 'b' any constant, add "@l" suffix for bottom 16 bits
03984308
BW
2288*/
2289
2290static void
ffbc8796 2291printx (FILE *file, signed int val)
03984308 2292{
ffbc8796 2293 /* Print a hexadecimal value in a nice way. */
03984308
BW
2294 if ((val > -0xa) && (val < 0xa))
2295 fprintf (file, "%d", val);
2296 else if (val < 0)
2297 fprintf (file, "-0x%x", -val);
2298 else
2299 fprintf (file, "0x%x", val);
2300}
2301
2302
2303void
ffbc8796 2304print_operand (FILE *file, rtx x, int letter)
03984308 2305{
f42f5a1b 2306 if (!x)
03984308
BW
2307 error ("PRINT_OPERAND null pointer");
2308
f42f5a1b 2309 switch (letter)
03984308 2310 {
f42f5a1b
BW
2311 case 'D':
2312 if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
2313 fprintf (file, "%s", reg_names[xt_true_regnum (x) + 1]);
2314 else
2315 output_operand_lossage ("invalid %%D value");
2316 break;
03984308 2317
f42f5a1b
BW
2318 case 'v':
2319 if (GET_CODE (x) == MEM)
2320 {
2321 /* For a volatile memory reference, emit a MEMW before the
2322 load or store. */
66e58b33 2323 if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE)
f42f5a1b
BW
2324 fprintf (file, "memw\n\t");
2325 }
2326 else
2327 output_operand_lossage ("invalid %%v value");
2328 break;
03984308 2329
f42f5a1b
BW
2330 case 'N':
2331 if (GET_CODE (x) == MEM
2332 && (GET_MODE (x) == DFmode || GET_MODE (x) == DImode))
2333 {
2334 x = adjust_address (x, GET_MODE (x) == DFmode ? SFmode : SImode, 4);
cc8ca59e 2335 output_address (GET_MODE (x), XEXP (x, 0));
f42f5a1b
BW
2336 }
2337 else
2338 output_operand_lossage ("invalid %%N value");
2339 break;
03984308 2340
f42f5a1b
BW
2341 case 'K':
2342 if (GET_CODE (x) == CONST_INT)
03984308 2343 {
f42f5a1b
BW
2344 int num_bits = 0;
2345 unsigned val = INTVAL (x);
2346 while (val & 1)
2347 {
2348 num_bits += 1;
2349 val = val >> 1;
2350 }
2351 if ((val != 0) || (num_bits == 0) || (num_bits > 16))
2352 fatal_insn ("invalid mask", x);
03984308 2353
f42f5a1b
BW
2354 fprintf (file, "%d", num_bits);
2355 }
2356 else
2357 output_operand_lossage ("invalid %%K value");
2358 break;
03984308 2359
f42f5a1b
BW
2360 case 'L':
2361 if (GET_CODE (x) == CONST_INT)
3904010d 2362 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (32 - INTVAL (x)) & 0x1f);
f42f5a1b
BW
2363 else
2364 output_operand_lossage ("invalid %%L value");
2365 break;
03984308 2366
f42f5a1b
BW
2367 case 'R':
2368 if (GET_CODE (x) == CONST_INT)
3904010d 2369 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0x1f);
f42f5a1b
BW
2370 else
2371 output_operand_lossage ("invalid %%R value");
2372 break;
03984308 2373
f42f5a1b
BW
2374 case 'x':
2375 if (GET_CODE (x) == CONST_INT)
2376 printx (file, INTVAL (x));
2377 else
2378 output_operand_lossage ("invalid %%x value");
2379 break;
03984308 2380
f42f5a1b
BW
2381 case 'd':
2382 if (GET_CODE (x) == CONST_INT)
3904010d 2383 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
f42f5a1b
BW
2384 else
2385 output_operand_lossage ("invalid %%d value");
2386 break;
03984308 2387
f42f5a1b
BW
2388 case 't':
2389 case 'b':
2390 if (GET_CODE (x) == CONST_INT)
2391 {
2392 printx (file, INTVAL (x));
2393 fputs (letter == 't' ? "@h" : "@l", file);
2394 }
2395 else if (GET_CODE (x) == CONST_DOUBLE)
2396 {
f42f5a1b
BW
2397 if (GET_MODE (x) == SFmode)
2398 {
2399 long l;
34a72c33 2400 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), l);
f42f5a1b
BW
2401 fprintf (file, "0x%08lx@%c", l, letter == 't' ? 'h' : 'l');
2402 }
2403 else
2404 output_operand_lossage ("invalid %%t/%%b value");
2405 }
2406 else if (GET_CODE (x) == CONST)
2407 {
2408 /* X must be a symbolic constant on ELF. Write an expression
2409 suitable for 'const16' that sets the high or low 16 bits. */
2410 if (GET_CODE (XEXP (x, 0)) != PLUS
2411 || (GET_CODE (XEXP (XEXP (x, 0), 0)) != SYMBOL_REF
2412 && GET_CODE (XEXP (XEXP (x, 0), 0)) != LABEL_REF)
2413 || GET_CODE (XEXP (XEXP (x, 0), 1)) != CONST_INT)
2414 output_operand_lossage ("invalid %%t/%%b value");
2415 print_operand (file, XEXP (XEXP (x, 0), 0), 0);
2416 fputs (letter == 't' ? "@h" : "@l", file);
2417 /* There must be a non-alphanumeric character between 'h' or 'l'
2418 and the number. The '-' is added by print_operand() already. */
2419 if (INTVAL (XEXP (XEXP (x, 0), 1)) >= 0)
2420 fputs ("+", file);
2421 print_operand (file, XEXP (XEXP (x, 0), 1), 0);
2422 }
2423 else
633e4eb4 2424 {
f42f5a1b
BW
2425 output_addr_const (file, x);
2426 fputs (letter == 't' ? "@h" : "@l", file);
03984308
BW
2427 }
2428 break;
2429
a024f514
MF
2430 case 'y':
2431 if (GET_CODE (x) == CONST_DOUBLE &&
2432 GET_MODE (x) == SFmode)
2433 {
a024f514 2434 long l;
34a72c33 2435 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), l);
a024f514
MF
2436 fprintf (file, "0x%08lx", l);
2437 break;
2438 }
2439
2440 /* fall through */
2441
03984308 2442 default:
f42f5a1b
BW
2443 if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
2444 fprintf (file, "%s", reg_names[xt_true_regnum (x)]);
2445 else if (GET_CODE (x) == MEM)
cc8ca59e 2446 output_address (GET_MODE (x), XEXP (x, 0));
f42f5a1b 2447 else if (GET_CODE (x) == CONST_INT)
3904010d 2448 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
f42f5a1b
BW
2449 else
2450 output_addr_const (file, x);
03984308
BW
2451 }
2452}
2453
2454
2455/* A C compound statement to output to stdio stream STREAM the
2456 assembler syntax for an instruction operand that is a memory
fb49053f 2457 reference whose address is ADDR. ADDR is an RTL expression. */
03984308
BW
2458
2459void
ffbc8796 2460print_operand_address (FILE *file, rtx addr)
03984308
BW
2461{
2462 if (!addr)
2463 error ("PRINT_OPERAND_ADDRESS, null pointer");
2464
2465 switch (GET_CODE (addr))
2466 {
2467 default:
2468 fatal_insn ("invalid address", addr);
2469 break;
2470
2471 case REG:
2472 fprintf (file, "%s, 0", reg_names [REGNO (addr)]);
2473 break;
2474
2475 case PLUS:
2476 {
2477 rtx reg = (rtx)0;
2478 rtx offset = (rtx)0;
2479 rtx arg0 = XEXP (addr, 0);
2480 rtx arg1 = XEXP (addr, 1);
2481
2482 if (GET_CODE (arg0) == REG)
2483 {
2484 reg = arg0;
2485 offset = arg1;
2486 }
2487 else if (GET_CODE (arg1) == REG)
2488 {
2489 reg = arg1;
2490 offset = arg0;
2491 }
2492 else
2493 fatal_insn ("no register in address", addr);
2494
2495 if (CONSTANT_P (offset))
2496 {
2497 fprintf (file, "%s, ", reg_names [REGNO (reg)]);
2498 output_addr_const (file, offset);
2499 }
2500 else
2501 fatal_insn ("address offset not a constant", addr);
2502 }
2503 break;
2504
2505 case LABEL_REF:
2506 case SYMBOL_REF:
2507 case CONST_INT:
2508 case CONST:
2509 output_addr_const (file, addr);
2510 break;
2511 }
2512}
2513
2ac6bb04 2514/* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */
03984308 2515
2ac6bb04 2516static bool
da1f39e4
BW
2517xtensa_output_addr_const_extra (FILE *fp, rtx x)
2518{
2519 if (GET_CODE (x) == UNSPEC && XVECLEN (x, 0) == 1)
2520 {
2521 switch (XINT (x, 1))
2522 {
6a7a462c
BW
2523 case UNSPEC_TPOFF:
2524 output_addr_const (fp, XVECEXP (x, 0, 0));
2525 fputs ("@TPOFF", fp);
2526 return true;
2527 case UNSPEC_DTPOFF:
2528 output_addr_const (fp, XVECEXP (x, 0, 0));
2529 fputs ("@DTPOFF", fp);
2530 return true;
da1f39e4
BW
2531 case UNSPEC_PLT:
2532 if (flag_pic)
2533 {
2534 output_addr_const (fp, XVECEXP (x, 0, 0));
2535 fputs ("@PLT", fp);
2536 return true;
2537 }
2538 break;
2539 default:
2540 break;
2541 }
2542 }
2543 return false;
2544}
2545
9ae4ef4c
MF
2546static void
2547xtensa_output_integer_literal_parts (FILE *file, rtx x, int size)
2548{
2549 if (size > 4 && !(size & (size - 1)))
2550 {
2551 rtx first, second;
2552
2553 split_double (x, &first, &second);
2554 xtensa_output_integer_literal_parts (file, first, size / 2);
2555 fputs (", ", file);
2556 xtensa_output_integer_literal_parts (file, second, size / 2);
2557 }
2558 else if (size == 4)
2559 {
2560 output_addr_const (file, x);
2561 }
2562 else
2563 {
2564 gcc_unreachable();
2565 }
2566}
da1f39e4 2567
03984308 2568void
ef4bddc2 2569xtensa_output_literal (FILE *file, rtx x, machine_mode mode, int labelno)
03984308
BW
2570{
2571 long value_long[2];
03984308
BW
2572
2573 fprintf (file, "\t.literal .LC%u, ", (unsigned) labelno);
2574
2575 switch (GET_MODE_CLASS (mode))
2576 {
2577 case MODE_FLOAT:
177b6be0 2578 gcc_assert (GET_CODE (x) == CONST_DOUBLE);
03984308 2579
03984308
BW
2580 switch (mode)
2581 {
2582 case SFmode:
34a72c33
RS
2583 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x),
2584 value_long[0]);
4575a800
BW
2585 if (HOST_BITS_PER_LONG > 32)
2586 value_long[0] &= 0xffffffff;
b216cd4a 2587 fprintf (file, "0x%08lx\n", value_long[0]);
03984308
BW
2588 break;
2589
2590 case DFmode:
34a72c33
RS
2591 REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (x),
2592 value_long);
4575a800
BW
2593 if (HOST_BITS_PER_LONG > 32)
2594 {
2595 value_long[0] &= 0xffffffff;
2596 value_long[1] &= 0xffffffff;
2597 }
b216cd4a
ZW
2598 fprintf (file, "0x%08lx, 0x%08lx\n",
2599 value_long[0], value_long[1]);
03984308
BW
2600 break;
2601
2602 default:
177b6be0 2603 gcc_unreachable ();
03984308
BW
2604 }
2605
2606 break;
2607
2608 case MODE_INT:
2609 case MODE_PARTIAL_INT:
9ae4ef4c
MF
2610 xtensa_output_integer_literal_parts (file, x, GET_MODE_SIZE (mode));
2611 fputs ("\n", file);
03984308
BW
2612 break;
2613
2614 default:
177b6be0 2615 gcc_unreachable ();
03984308
BW
2616 }
2617}
2618
590e2636
MF
2619static bool
2620xtensa_call_save_reg(int regno)
2621{
2622 if (TARGET_WINDOWED_ABI)
2623 return false;
2624
2625 if (regno == A0_REG)
2626 return crtl->profile || !crtl->is_leaf || crtl->calls_eh_return ||
2627 df_regs_ever_live_p (regno);
2628
2629 if (crtl->calls_eh_return && regno >= 2 && regno < 4)
2630 return true;
2631
2632 return !fixed_regs[regno] && !call_used_regs[regno] &&
2633 df_regs_ever_live_p (regno);
2634}
03984308
BW
2635
2636/* Return the bytes needed to compute the frame pointer from the current
638db43e 2637 stack pointer. */
03984308
BW
2638
2639#define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
2640#define XTENSA_STACK_ALIGN(LOC) (((LOC) + STACK_BYTES-1) & ~(STACK_BYTES-1))
2641
2642long
ffbc8796 2643compute_frame_size (int size)
03984308 2644{
590e2636
MF
2645 int regno;
2646
ad89d820
MF
2647 if (reload_completed && cfun->machine->frame_laid_out)
2648 return cfun->machine->current_frame_size;
2649
ffbc8796 2650 /* Add space for the incoming static chain value. */
6de9cd9a 2651 if (cfun->static_chain_decl != NULL)
03984308
BW
2652 size += (1 * UNITS_PER_WORD);
2653
ad89d820 2654 cfun->machine->callee_save_size = 0;
590e2636
MF
2655 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
2656 {
2657 if (xtensa_call_save_reg(regno))
ad89d820 2658 cfun->machine->callee_save_size += UNITS_PER_WORD;
590e2636
MF
2659 }
2660
ad89d820 2661 cfun->machine->current_frame_size =
03984308 2662 XTENSA_STACK_ALIGN (size
ad89d820 2663 + cfun->machine->callee_save_size
38173d38 2664 + crtl->outgoing_args_size
03984308 2665 + (WINDOW_SIZE * UNITS_PER_WORD));
ad89d820
MF
2666 cfun->machine->callee_save_size =
2667 XTENSA_STACK_ALIGN (cfun->machine->callee_save_size);
2668 cfun->machine->frame_laid_out = true;
2669 return cfun->machine->current_frame_size;
03984308
BW
2670}
2671
2672
b52b1749 2673bool
ffbc8796 2674xtensa_frame_pointer_required (void)
03984308
BW
2675{
2676 /* The code to expand builtin_frame_addr and builtin_return_addr
2677 currently uses the hard_frame_pointer instead of frame_pointer.
2678 This seems wrong but maybe it's necessary for other architectures.
638db43e 2679 This function is derived from the i386 code. */
03984308
BW
2680
2681 if (cfun->machine->accesses_prev_frame)
b52b1749 2682 return true;
03984308 2683
b52b1749 2684 return false;
03984308
BW
2685}
2686
5057f9e0 2687HOST_WIDE_INT
eced9b48 2688xtensa_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED)
5057f9e0
MF
2689{
2690 long frame_size = compute_frame_size (get_frame_size ());
2691 HOST_WIDE_INT offset;
2692
2693 switch (from)
2694 {
2695 case FRAME_POINTER_REGNUM:
2696 if (FRAME_GROWS_DOWNWARD)
2697 offset = frame_size - (WINDOW_SIZE * UNITS_PER_WORD)
2698 - cfun->machine->callee_save_size;
2699 else
2700 offset = 0;
2701 break;
2702 case ARG_POINTER_REGNUM:
2703 offset = frame_size;
2704 break;
2705 default:
2706 gcc_unreachable ();
2707 }
2708
2709 return offset;
2710}
03984308 2711
7f0ee694
BW
2712/* minimum frame = reg save area (4 words) plus static chain (1 word)
2713 and the total number of words must be a multiple of 128 bits. */
2714#define MIN_FRAME_SIZE (8 * UNITS_PER_WORD)
2715
f42f5a1b 2716void
ffbc8796 2717xtensa_expand_prologue (void)
f42f5a1b
BW
2718{
2719 HOST_WIDE_INT total_size;
590e2636 2720 rtx_insn *insn = NULL;
240a513f 2721 rtx note_rtx;
18dbd950 2722
590e2636 2723
f42f5a1b 2724 total_size = compute_frame_size (get_frame_size ());
18dbd950 2725
7695d1e3
MF
2726 if (flag_stack_usage_info)
2727 current_function_static_stack_size = total_size;
2728
590e2636
MF
2729 if (TARGET_WINDOWED_ABI)
2730 {
2731 if (total_size < (1 << (12+3)))
2732 insn = emit_insn (gen_entry (GEN_INT (total_size)));
2733 else
2734 {
2735 /* Use a8 as a temporary since a0-a7 may be live. */
2736 rtx tmp_reg = gen_rtx_REG (Pmode, A8_REG);
2737 emit_insn (gen_entry (GEN_INT (MIN_FRAME_SIZE)));
2738 emit_move_insn (tmp_reg, GEN_INT (total_size - MIN_FRAME_SIZE));
2739 emit_insn (gen_subsi3 (tmp_reg, stack_pointer_rtx, tmp_reg));
2740 insn = emit_insn (gen_movsi (stack_pointer_rtx, tmp_reg));
2741 }
2742 }
03984308
BW
2743 else
2744 {
590e2636
MF
2745 int regno;
2746 HOST_WIDE_INT offset = 0;
ad89d820 2747 int callee_save_size = cfun->machine->callee_save_size;
590e2636
MF
2748
2749 /* -128 is a limit of single addi instruction. */
2750 if (total_size > 0 && total_size <= 128)
2751 {
2752 insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2753 GEN_INT (-total_size)));
2754 RTX_FRAME_RELATED_P (insn) = 1;
f7df4a84 2755 note_rtx = gen_rtx_SET (stack_pointer_rtx,
590e2636
MF
2756 plus_constant (Pmode, stack_pointer_rtx,
2757 -total_size));
2758 add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
2759 offset = total_size - UNITS_PER_WORD;
2760 }
ad89d820 2761 else if (callee_save_size)
590e2636
MF
2762 {
2763 /* 1020 is maximal s32i offset, if the frame is bigger than that
2764 * we move sp to the end of callee-saved save area, save and then
2765 * move it to its final location. */
2766 if (total_size > 1024)
2767 {
2768 insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
ad89d820 2769 GEN_INT (-callee_save_size)));
590e2636 2770 RTX_FRAME_RELATED_P (insn) = 1;
f7df4a84 2771 note_rtx = gen_rtx_SET (stack_pointer_rtx,
590e2636 2772 plus_constant (Pmode, stack_pointer_rtx,
ad89d820 2773 -callee_save_size));
590e2636 2774 add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
ad89d820 2775 offset = callee_save_size - UNITS_PER_WORD;
590e2636
MF
2776 }
2777 else
2778 {
2779 rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
2780 emit_move_insn (tmp_reg, GEN_INT (total_size));
2781 insn = emit_insn (gen_subsi3 (stack_pointer_rtx,
2782 stack_pointer_rtx, tmp_reg));
2783 RTX_FRAME_RELATED_P (insn) = 1;
f7df4a84 2784 note_rtx = gen_rtx_SET (stack_pointer_rtx,
590e2636
MF
2785 plus_constant (Pmode, stack_pointer_rtx,
2786 -total_size));
2787 add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
2788 offset = total_size - UNITS_PER_WORD;
2789 }
2790 }
2791
2792 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
2793 {
2794 if (xtensa_call_save_reg(regno))
2795 {
2796 rtx x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
2797 rtx mem = gen_frame_mem (SImode, x);
2798 rtx reg = gen_rtx_REG (SImode, regno);
2799
2800 offset -= UNITS_PER_WORD;
2801 insn = emit_move_insn (mem, reg);
2802 RTX_FRAME_RELATED_P (insn) = 1;
2803 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
f7df4a84 2804 gen_rtx_SET (mem, reg));
590e2636
MF
2805 }
2806 }
2807 if (total_size > 1024)
2808 {
2809 rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
2810 emit_move_insn (tmp_reg, GEN_INT (total_size -
ad89d820 2811 callee_save_size));
590e2636
MF
2812 insn = emit_insn (gen_subsi3 (stack_pointer_rtx,
2813 stack_pointer_rtx, tmp_reg));
2814 RTX_FRAME_RELATED_P (insn) = 1;
f7df4a84 2815 note_rtx = gen_rtx_SET (stack_pointer_rtx,
590e2636 2816 plus_constant (Pmode, stack_pointer_rtx,
ad89d820 2817 callee_save_size -
590e2636
MF
2818 total_size));
2819 add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
2820 }
03984308
BW
2821 }
2822
f42f5a1b 2823 if (frame_pointer_needed)
03984308 2824 {
997b8b4d 2825 if (cfun->machine->set_frame_ptr_insn)
03984308 2826 {
240a513f 2827 rtx_insn *first;
03984308 2828
997b8b4d
BW
2829 push_topmost_sequence ();
2830 first = get_insns ();
2831 pop_topmost_sequence ();
03984308 2832
f42f5a1b
BW
2833 /* For all instructions prior to set_frame_ptr_insn, replace
2834 hard_frame_pointer references with stack_pointer. */
2835 for (insn = first;
997b8b4d 2836 insn != cfun->machine->set_frame_ptr_insn;
f42f5a1b
BW
2837 insn = NEXT_INSN (insn))
2838 {
2839 if (INSN_P (insn))
20dca97b
BW
2840 {
2841 PATTERN (insn) = replace_rtx (copy_rtx (PATTERN (insn)),
2842 hard_frame_pointer_rtx,
2843 stack_pointer_rtx);
2844 df_insn_rescan (insn);
2845 }
f42f5a1b
BW
2846 }
2847 }
2848 else
590e2636
MF
2849 {
2850 insn = emit_insn (gen_movsi (hard_frame_pointer_rtx,
2851 stack_pointer_rtx));
2852 if (!TARGET_WINDOWED_ABI)
2853 {
f7df4a84 2854 note_rtx = gen_rtx_SET (hard_frame_pointer_rtx,
590e2636
MF
2855 stack_pointer_rtx);
2856 RTX_FRAME_RELATED_P (insn) = 1;
2857 add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
2858 }
2859 }
2860 }
03984308 2861
590e2636
MF
2862 if (TARGET_WINDOWED_ABI)
2863 {
2864 /* Create a note to describe the CFA. Because this is only used to set
2865 DW_AT_frame_base for debug info, don't bother tracking changes through
2866 each instruction in the prologue. It just takes up space. */
f7df4a84
RS
2867 note_rtx = gen_rtx_SET ((frame_pointer_needed
2868 ? hard_frame_pointer_rtx
2869 : stack_pointer_rtx),
590e2636
MF
2870 plus_constant (Pmode, stack_pointer_rtx,
2871 -total_size));
2872 RTX_FRAME_RELATED_P (insn) = 1;
2873 add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
2874 }
2875}
03984308
BW
2876
2877void
590e2636 2878xtensa_expand_epilogue (void)
03984308 2879{
590e2636
MF
2880 if (!TARGET_WINDOWED_ABI)
2881 {
2882 int regno;
2883 HOST_WIDE_INT offset;
2884
ad89d820 2885 if (cfun->machine->current_frame_size > (frame_pointer_needed ? 127 : 1024))
590e2636
MF
2886 {
2887 rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
ad89d820
MF
2888 emit_move_insn (tmp_reg, GEN_INT (cfun->machine->current_frame_size -
2889 cfun->machine->callee_save_size));
590e2636
MF
2890 emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_needed ?
2891 hard_frame_pointer_rtx : stack_pointer_rtx,
2892 tmp_reg));
ad89d820 2893 offset = cfun->machine->callee_save_size - UNITS_PER_WORD;
590e2636
MF
2894 }
2895 else
2896 {
2897 if (frame_pointer_needed)
2898 emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
ad89d820 2899 offset = cfun->machine->current_frame_size - UNITS_PER_WORD;
590e2636
MF
2900 }
2901
2902 /* Prevent reordering of saved a0 update and loading it back from
2903 the save area. */
2904 if (crtl->calls_eh_return)
2905 emit_insn (gen_blockage ());
2906
2907 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
2908 {
2909 if (xtensa_call_save_reg(regno))
2910 {
2911 rtx x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
2912
2913 offset -= UNITS_PER_WORD;
2914 emit_move_insn (gen_rtx_REG (SImode, regno),
2915 gen_frame_mem (SImode, x));
2916 }
2917 }
2918
ad89d820 2919 if (cfun->machine->current_frame_size > 0)
590e2636
MF
2920 {
2921 if (frame_pointer_needed || /* always reachable with addi */
ad89d820
MF
2922 cfun->machine->current_frame_size > 1024 ||
2923 cfun->machine->current_frame_size <= 127)
590e2636 2924 {
ad89d820
MF
2925 if (cfun->machine->current_frame_size <= 127)
2926 offset = cfun->machine->current_frame_size;
590e2636 2927 else
ad89d820 2928 offset = cfun->machine->callee_save_size;
590e2636
MF
2929
2930 emit_insn (gen_addsi3 (stack_pointer_rtx,
2931 stack_pointer_rtx,
2932 GEN_INT (offset)));
2933 }
2934 else
2935 {
2936 rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
ad89d820
MF
2937 emit_move_insn (tmp_reg,
2938 GEN_INT (cfun->machine->current_frame_size));
590e2636
MF
2939 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2940 tmp_reg));
2941 }
2942 }
2943
2944 if (crtl->calls_eh_return)
2945 emit_insn (gen_add3_insn (stack_pointer_rtx,
2946 stack_pointer_rtx,
2947 EH_RETURN_STACKADJ_RTX));
2948 }
ad89d820 2949 cfun->machine->epilogue_done = true;
590e2636 2950 emit_jump_insn (gen_return ());
03984308
BW
2951}
2952
ad89d820
MF
2953bool
2954xtensa_use_return_instruction_p (void)
2955{
2956 if (!reload_completed)
2957 return false;
2958 if (TARGET_WINDOWED_ABI)
2959 return true;
2960 if (compute_frame_size (get_frame_size ()) == 0)
2961 return true;
2962 return cfun->machine->epilogue_done;
2963}
2964
590e2636
MF
2965void
2966xtensa_set_return_address (rtx address, rtx scratch)
2967{
2968 HOST_WIDE_INT total_size = compute_frame_size (get_frame_size ());
2969 rtx frame = frame_pointer_needed ?
2970 hard_frame_pointer_rtx : stack_pointer_rtx;
2971 rtx a0_addr = plus_constant (Pmode, frame,
2972 total_size - UNITS_PER_WORD);
f7df4a84 2973 rtx note = gen_rtx_SET (gen_frame_mem (SImode, a0_addr),
590e2636
MF
2974 gen_rtx_REG (SImode, A0_REG));
2975 rtx insn;
2976
2977 if (total_size > 1024) {
2978 emit_move_insn (scratch, GEN_INT (total_size - UNITS_PER_WORD));
2979 emit_insn (gen_addsi3 (scratch, frame, scratch));
2980 a0_addr = scratch;
2981 }
2982
2983 insn = emit_move_insn (gen_frame_mem (SImode, a0_addr), address);
2984 RTX_FRAME_RELATED_P (insn) = 1;
2985 add_reg_note (insn, REG_FRAME_RELATED_EXPR, note);
2986}
03984308 2987
0c14a54d 2988rtx
ffbc8796 2989xtensa_return_addr (int count, rtx frame)
0c14a54d 2990{
7f0ee694 2991 rtx result, retaddr, curaddr, label;
0c14a54d 2992
590e2636
MF
2993 if (!TARGET_WINDOWED_ABI)
2994 {
2995 if (count != 0)
2996 return const0_rtx;
2997
2998 return get_hard_reg_initial_val (Pmode, A0_REG);
2999 }
3000
0c14a54d 3001 if (count == -1)
f42f5a1b 3002 retaddr = gen_rtx_REG (Pmode, A0_REG);
0c14a54d
BW
3003 else
3004 {
0a81f074 3005 rtx addr = plus_constant (Pmode, frame, -4 * UNITS_PER_WORD);
0c14a54d
BW
3006 addr = memory_address (Pmode, addr);
3007 retaddr = gen_reg_rtx (Pmode);
3008 emit_move_insn (retaddr, gen_rtx_MEM (Pmode, addr));
3009 }
3010
3011 /* The 2 most-significant bits of the return address on Xtensa hold
3012 the register window size. To get the real return address, these
7f0ee694
BW
3013 bits must be replaced with the high bits from some address in the
3014 code. */
3015
3016 /* Get the 2 high bits of a local label in the code. */
3017 curaddr = gen_reg_rtx (Pmode);
3018 label = gen_label_rtx ();
3019 emit_label (label);
3020 LABEL_PRESERVE_P (label) = 1;
3021 emit_move_insn (curaddr, gen_rtx_LABEL_REF (Pmode, label));
3022 emit_insn (gen_lshrsi3 (curaddr, curaddr, GEN_INT (30)));
3023 emit_insn (gen_ashlsi3 (curaddr, curaddr, GEN_INT (30)));
3024
3025 /* Clear the 2 high bits of the return address. */
0c14a54d 3026 result = gen_reg_rtx (Pmode);
7f0ee694
BW
3027 emit_insn (gen_ashlsi3 (result, retaddr, GEN_INT (2)));
3028 emit_insn (gen_lshrsi3 (result, result, GEN_INT (2)));
3029
3030 /* Combine them to get the result. */
3031 emit_insn (gen_iorsi3 (result, result, curaddr));
0c14a54d
BW
3032 return result;
3033}
3034
d9886a9e
L
3035/* Disable the use of word-sized or smaller complex modes for structures,
3036 and for function arguments in particular, where they cause problems with
3037 register a7. The xtensa_copy_incoming_a7 function assumes that there is
3038 a single reference to an argument in a7, but with small complex modes the
3039 real and imaginary components may be extracted separately, leading to two
3040 uses of the register, only one of which would be replaced. */
3041
3042static bool
ef4bddc2 3043xtensa_member_type_forces_blk (const_tree, machine_mode mode)
d9886a9e
L
3044{
3045 return mode == CQImode || mode == CHImode;
3046}
0c14a54d 3047
03984308 3048/* Create the va_list data type.
822e895c
BW
3049
3050 This structure is set up by __builtin_saveregs. The __va_reg field
3051 points to a stack-allocated region holding the contents of the
3052 incoming argument registers. The __va_ndx field is an index
3053 initialized to the position of the first unnamed (variable)
3054 argument. This same index is also used to address the arguments
3055 passed in memory. Thus, the __va_stk field is initialized to point
3056 to the position of the first argument in memory offset to account
3057 for the arguments passed in registers and to account for the size
3058 of the argument registers not being 16-byte aligned. E.G., there
3059 are 6 argument registers of 4 bytes each, but we want the __va_ndx
3060 for the first stack argument to have the maximal alignment of 16
3061 bytes, so we offset the __va_stk address by 32 bytes so that
3062 __va_stk[32] references the first argument on the stack. */
03984308 3063
c35d187f
RH
3064static tree
3065xtensa_build_builtin_va_list (void)
03984308 3066{
540eaea8 3067 tree f_stk, f_reg, f_ndx, record, type_decl;
03984308 3068
540eaea8 3069 record = (*lang_hooks.types.make_type) (RECORD_TYPE);
4c4bde29
AH
3070 type_decl = build_decl (BUILTINS_LOCATION,
3071 TYPE_DECL, get_identifier ("__va_list_tag"), record);
03984308 3072
4c4bde29
AH
3073 f_stk = build_decl (BUILTINS_LOCATION,
3074 FIELD_DECL, get_identifier ("__va_stk"),
03984308 3075 ptr_type_node);
4c4bde29
AH
3076 f_reg = build_decl (BUILTINS_LOCATION,
3077 FIELD_DECL, get_identifier ("__va_reg"),
03984308 3078 ptr_type_node);
4c4bde29
AH
3079 f_ndx = build_decl (BUILTINS_LOCATION,
3080 FIELD_DECL, get_identifier ("__va_ndx"),
03984308
BW
3081 integer_type_node);
3082
3083 DECL_FIELD_CONTEXT (f_stk) = record;
3084 DECL_FIELD_CONTEXT (f_reg) = record;
3085 DECL_FIELD_CONTEXT (f_ndx) = record;
3086
0fd2eac2 3087 TYPE_STUB_DECL (record) = type_decl;
540eaea8 3088 TYPE_NAME (record) = type_decl;
03984308 3089 TYPE_FIELDS (record) = f_stk;
910ad8de
NF
3090 DECL_CHAIN (f_stk) = f_reg;
3091 DECL_CHAIN (f_reg) = f_ndx;
03984308
BW
3092
3093 layout_type (record);
3094 return record;
3095}
3096
3097
3098/* Save the incoming argument registers on the stack. Returns the
638db43e 3099 address of the saved registers. */
03984308 3100
4c45af42 3101static rtx
ffbc8796 3102xtensa_builtin_saveregs (void)
03984308 3103{
e70312d4 3104 rtx gp_regs;
38173d38 3105 int arg_words = crtl->args.info.arg_words;
03984308 3106 int gp_left = MAX_ARGS_IN_REGISTERS - arg_words;
03984308 3107
997b8b4d 3108 if (gp_left <= 0)
03984308
BW
3109 return const0_rtx;
3110
3bbc2af6 3111 /* Allocate the general-purpose register space. */
03984308
BW
3112 gp_regs = assign_stack_local
3113 (BLKmode, MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD, -1);
540eaea8 3114 set_mem_alias_set (gp_regs, get_varargs_alias_set ());
03984308
BW
3115
3116 /* Now store the incoming registers. */
590e2636 3117 cfun->machine->need_a7_copy = TARGET_WINDOWED_ABI;
997b8b4d 3118 cfun->machine->vararg_a7 = true;
e70312d4
BW
3119 move_block_from_reg (GP_ARG_FIRST + arg_words,
3120 adjust_address (gp_regs, BLKmode,
3121 arg_words * UNITS_PER_WORD),
3122 gp_left);
590e2636
MF
3123 if (cfun->machine->vararg_a7_copy != 0)
3124 emit_insn_before (cfun->machine->vararg_a7_copy, get_insns ());
03984308
BW
3125
3126 return XEXP (gp_regs, 0);
3127}
3128
3129
3130/* Implement `va_start' for varargs and stdarg. We look at the
638db43e 3131 current function to fill in an initial va_list. */
03984308 3132
d7bd8aeb 3133static void
ffbc8796 3134xtensa_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
03984308
BW
3135{
3136 tree f_stk, stk;
3137 tree f_reg, reg;
3138 tree f_ndx, ndx;
3139 tree t, u;
3140 int arg_words;
3141
38173d38 3142 arg_words = crtl->args.info.arg_words;
03984308
BW
3143
3144 f_stk = TYPE_FIELDS (va_list_type_node);
910ad8de
NF
3145 f_reg = DECL_CHAIN (f_stk);
3146 f_ndx = DECL_CHAIN (f_reg);
03984308 3147
47a25a46 3148 stk = build3 (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk, NULL_TREE);
fa1615d7
BW
3149 reg = build3 (COMPONENT_REF, TREE_TYPE (f_reg), unshare_expr (valist),
3150 f_reg, NULL_TREE);
3151 ndx = build3 (COMPONENT_REF, TREE_TYPE (f_ndx), unshare_expr (valist),
3152 f_ndx, NULL_TREE);
03984308
BW
3153
3154 /* Call __builtin_saveregs; save the result in __va_reg */
e70312d4
BW
3155 u = make_tree (sizetype, expand_builtin_saveregs ());
3156 u = fold_convert (ptr_type_node, u);
726a989a 3157 t = build2 (MODIFY_EXPR, ptr_type_node, reg, u);
03984308
BW
3158 TREE_SIDE_EFFECTS (t) = 1;
3159 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3160
822e895c 3161 /* Set the __va_stk member to ($arg_ptr - 32). */
03984308 3162 u = make_tree (ptr_type_node, virtual_incoming_args_rtx);
5d49b6a7 3163 u = fold_build_pointer_plus_hwi (u, -32);
726a989a 3164 t = build2 (MODIFY_EXPR, ptr_type_node, stk, u);
03984308
BW
3165 TREE_SIDE_EFFECTS (t) = 1;
3166 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3167
822e895c
BW
3168 /* Set the __va_ndx member. If the first variable argument is on
3169 the stack, adjust __va_ndx by 2 words to account for the extra
3170 alignment offset for __va_stk. */
3171 if (arg_words >= MAX_ARGS_IN_REGISTERS)
3172 arg_words += 2;
726a989a 3173 t = build2 (MODIFY_EXPR, integer_type_node, ndx,
f4d3e7fd 3174 build_int_cst (integer_type_node, arg_words * UNITS_PER_WORD));
03984308
BW
3175 TREE_SIDE_EFFECTS (t) = 1;
3176 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3177}
3178
3179
3180/* Implement `va_arg'. */
3181
85d53c1d 3182static tree
726a989a
RB
3183xtensa_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
3184 gimple_seq *post_p ATTRIBUTE_UNUSED)
03984308
BW
3185{
3186 tree f_stk, stk;
3187 tree f_reg, reg;
3188 tree f_ndx, ndx;
85d53c1d
RH
3189 tree type_size, array, orig_ndx, addr, size, va_size, t;
3190 tree lab_false, lab_over, lab_false2;
08b0dc1b
RH
3191 bool indirect;
3192
3193 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
3194 if (indirect)
3195 type = build_pointer_type (type);
03984308 3196
3712281f
BW
3197 /* Handle complex values as separate real and imaginary parts. */
3198 if (TREE_CODE (type) == COMPLEX_TYPE)
3199 {
85d53c1d 3200 tree real_part, imag_part;
3712281f 3201
85d53c1d
RH
3202 real_part = xtensa_gimplify_va_arg_expr (valist, TREE_TYPE (type),
3203 pre_p, NULL);
3204 real_part = get_initialized_tmp_var (real_part, pre_p, NULL);
3712281f 3205
fa1615d7
BW
3206 imag_part = xtensa_gimplify_va_arg_expr (unshare_expr (valist),
3207 TREE_TYPE (type),
85d53c1d
RH
3208 pre_p, NULL);
3209 imag_part = get_initialized_tmp_var (imag_part, pre_p, NULL);
3712281f 3210
47a25a46 3211 return build2 (COMPLEX_EXPR, type, real_part, imag_part);
3712281f
BW
3212 }
3213
03984308 3214 f_stk = TYPE_FIELDS (va_list_type_node);
910ad8de
NF
3215 f_reg = DECL_CHAIN (f_stk);
3216 f_ndx = DECL_CHAIN (f_reg);
03984308 3217
fa1615d7
BW
3218 stk = build3 (COMPONENT_REF, TREE_TYPE (f_stk), valist,
3219 f_stk, NULL_TREE);
3220 reg = build3 (COMPONENT_REF, TREE_TYPE (f_reg), unshare_expr (valist),
3221 f_reg, NULL_TREE);
3222 ndx = build3 (COMPONENT_REF, TREE_TYPE (f_ndx), unshare_expr (valist),
3223 f_ndx, NULL_TREE);
03984308 3224
85d53c1d
RH
3225 type_size = size_in_bytes (type);
3226 va_size = round_up (type_size, UNITS_PER_WORD);
3227 gimplify_expr (&va_size, pre_p, NULL, is_gimple_val, fb_rvalue);
8be56275 3228
03984308 3229
822e895c 3230 /* First align __va_ndx if necessary for this arg:
03984308 3231
85d53c1d 3232 orig_ndx = (AP).__va_ndx;
822e895c 3233 if (__alignof__ (TYPE) > 4 )
85d53c1d 3234 orig_ndx = ((orig_ndx + __alignof__ (TYPE) - 1)
822e895c 3235 & -__alignof__ (TYPE)); */
03984308 3236
85d53c1d
RH
3237 orig_ndx = get_initialized_tmp_var (ndx, pre_p, NULL);
3238
03984308
BW
3239 if (TYPE_ALIGN (type) > BITS_PER_WORD)
3240 {
d2348985 3241 int align = MIN (TYPE_ALIGN (type), STACK_BOUNDARY) / BITS_PER_UNIT;
85d53c1d 3242
fa1615d7 3243 t = build2 (PLUS_EXPR, integer_type_node, unshare_expr (orig_ndx),
f4d3e7fd
BW
3244 build_int_cst (integer_type_node, align - 1));
3245 t = build2 (BIT_AND_EXPR, integer_type_node, t,
3246 build_int_cst (integer_type_node, -align));
fa1615d7 3247 gimplify_assign (unshare_expr (orig_ndx), t, pre_p);
03984308
BW
3248 }
3249
3250
3251 /* Increment __va_ndx to point past the argument:
3252
85d53c1d 3253 (AP).__va_ndx = orig_ndx + __va_size (TYPE); */
03984308 3254
85d53c1d 3255 t = fold_convert (integer_type_node, va_size);
47a25a46 3256 t = build2 (PLUS_EXPR, integer_type_node, orig_ndx, t);
fa1615d7 3257 gimplify_assign (unshare_expr (ndx), t, pre_p);
03984308
BW
3258
3259
3260 /* Check if the argument is in registers:
3261
bcf88f9b 3262 if ((AP).__va_ndx <= __MAX_ARGS_IN_REGISTERS * 4
fe984136 3263 && !must_pass_in_stack (type))
ffbc8796 3264 __array = (AP).__va_reg; */
03984308 3265
9b489f31 3266 array = create_tmp_var (ptr_type_node);
03984308 3267
85d53c1d 3268 lab_over = NULL;
fe984136 3269 if (!targetm.calls.must_pass_in_stack (TYPE_MODE (type), type))
bcf88f9b 3270 {
4c4bde29
AH
3271 lab_false = create_artificial_label (UNKNOWN_LOCATION);
3272 lab_over = create_artificial_label (UNKNOWN_LOCATION);
85d53c1d 3273
fa1615d7 3274 t = build2 (GT_EXPR, boolean_type_node, unshare_expr (ndx),
f4d3e7fd
BW
3275 build_int_cst (integer_type_node,
3276 MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD));
47a25a46
RG
3277 t = build3 (COND_EXPR, void_type_node, t,
3278 build1 (GOTO_EXPR, void_type_node, lab_false),
3279 NULL_TREE);
85d53c1d
RH
3280 gimplify_and_add (t, pre_p);
3281
fa1615d7 3282 gimplify_assign (unshare_expr (array), reg, pre_p);
85d53c1d 3283
47a25a46 3284 t = build1 (GOTO_EXPR, void_type_node, lab_over);
85d53c1d
RH
3285 gimplify_and_add (t, pre_p);
3286
47a25a46 3287 t = build1 (LABEL_EXPR, void_type_node, lab_false);
85d53c1d 3288 gimplify_and_add (t, pre_p);
bcf88f9b 3289 }
03984308 3290
85d53c1d 3291
03984308
BW
3292 /* ...otherwise, the argument is on the stack (never split between
3293 registers and the stack -- change __va_ndx if necessary):
3294
3295 else
3296 {
822e895c
BW
3297 if (orig_ndx <= __MAX_ARGS_IN_REGISTERS * 4)
3298 (AP).__va_ndx = 32 + __va_size (TYPE);
03984308 3299 __array = (AP).__va_stk;
ffbc8796 3300 } */
03984308 3301
4c4bde29 3302 lab_false2 = create_artificial_label (UNKNOWN_LOCATION);
03984308 3303
fa1615d7 3304 t = build2 (GT_EXPR, boolean_type_node, unshare_expr (orig_ndx),
f4d3e7fd
BW
3305 build_int_cst (integer_type_node,
3306 MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD));
47a25a46
RG
3307 t = build3 (COND_EXPR, void_type_node, t,
3308 build1 (GOTO_EXPR, void_type_node, lab_false2),
3309 NULL_TREE);
85d53c1d 3310 gimplify_and_add (t, pre_p);
03984308 3311
fa1615d7 3312 t = size_binop (PLUS_EXPR, unshare_expr (va_size), size_int (32));
85d53c1d 3313 t = fold_convert (integer_type_node, t);
fa1615d7 3314 gimplify_assign (unshare_expr (ndx), t, pre_p);
03984308 3315
47a25a46 3316 t = build1 (LABEL_EXPR, void_type_node, lab_false2);
85d53c1d 3317 gimplify_and_add (t, pre_p);
03984308 3318
726a989a 3319 gimplify_assign (array, stk, pre_p);
85d53c1d
RH
3320
3321 if (lab_over)
3322 {
47a25a46 3323 t = build1 (LABEL_EXPR, void_type_node, lab_over);
85d53c1d
RH
3324 gimplify_and_add (t, pre_p);
3325 }
8be56275 3326
03984308
BW
3327
3328 /* Given the base array pointer (__array) and index to the subsequent
3329 argument (__va_ndx), find the address:
3330
8be56275
BW
3331 __array + (AP).__va_ndx - (BYTES_BIG_ENDIAN && sizeof (TYPE) < 4
3332 ? sizeof (TYPE)
3333 : __va_size (TYPE))
03984308
BW
3334
3335 The results are endian-dependent because values smaller than one word
ffbc8796 3336 are aligned differently. */
03984308 3337
633e4eb4 3338
85d91d5b 3339 if (BYTES_BIG_ENDIAN && TREE_CODE (type_size) == INTEGER_CST)
8be56275 3340 {
fa1615d7 3341 t = fold_build2 (GE_EXPR, boolean_type_node, unshare_expr (type_size),
e70312d4 3342 size_int (PARM_BOUNDARY / BITS_PER_UNIT));
fa1615d7
BW
3343 t = fold_build3 (COND_EXPR, sizetype, t, unshare_expr (va_size),
3344 unshare_expr (type_size));
85d53c1d 3345 size = t;
8be56275 3346 }
85d53c1d 3347 else
fa1615d7 3348 size = unshare_expr (va_size);
85d53c1d 3349
fa1615d7 3350 t = fold_convert (sizetype, unshare_expr (ndx));
f4d3e7fd 3351 t = build2 (MINUS_EXPR, sizetype, t, size);
5d49b6a7 3352 addr = fold_build_pointer_plus (unshare_expr (array), t);
03984308 3353
85d53c1d 3354 addr = fold_convert (build_pointer_type (type), addr);
08b0dc1b 3355 if (indirect)
d6e9821f
RH
3356 addr = build_va_arg_indirect_ref (addr);
3357 return build_va_arg_indirect_ref (addr);
03984308
BW
3358}
3359
3360
09fa8841
BW
3361/* Builtins. */
3362
3363enum xtensa_builtin
3364{
3365 XTENSA_BUILTIN_UMULSIDI3,
3366 XTENSA_BUILTIN_max
3367};
3368
3369
3370static void
3371xtensa_init_builtins (void)
3372{
6a7a462c 3373 tree ftype, decl;
09fa8841
BW
3374
3375 ftype = build_function_type_list (unsigned_intDI_type_node,
3376 unsigned_intSI_type_node,
3377 unsigned_intSI_type_node, NULL_TREE);
3378
6a7a462c
BW
3379 decl = add_builtin_function ("__builtin_umulsidi3", ftype,
3380 XTENSA_BUILTIN_UMULSIDI3, BUILT_IN_MD,
3381 "__umulsidi3", NULL_TREE);
3382 TREE_NOTHROW (decl) = 1;
3383 TREE_READONLY (decl) = 1;
09fa8841
BW
3384}
3385
3386
3387static tree
f311c3b4
NF
3388xtensa_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *args,
3389 bool ignore ATTRIBUTE_UNUSED)
09fa8841
BW
3390{
3391 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
3392 tree arg0, arg1;
3393
6a7a462c 3394 switch (fcode)
09fa8841 3395 {
6a7a462c 3396 case XTENSA_BUILTIN_UMULSIDI3:
f311c3b4
NF
3397 arg0 = args[0];
3398 arg1 = args[1];
09fa8841
BW
3399 if ((TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
3400 || TARGET_MUL32_HIGH)
3401 return fold_build2 (MULT_EXPR, unsigned_intDI_type_node,
3402 fold_convert (unsigned_intDI_type_node, arg0),
3403 fold_convert (unsigned_intDI_type_node, arg1));
6a7a462c
BW
3404 break;
3405
6a7a462c
BW
3406 default:
3407 internal_error ("bad builtin code");
3408 break;
09fa8841
BW
3409 }
3410
09fa8841
BW
3411 return NULL;
3412}
3413
3414
3415static rtx
3416xtensa_expand_builtin (tree exp, rtx target,
3417 rtx subtarget ATTRIBUTE_UNUSED,
ef4bddc2 3418 machine_mode mode ATTRIBUTE_UNUSED,
09fa8841
BW
3419 int ignore)
3420{
ec3643e8 3421 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
09fa8841 3422 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
6a7a462c
BW
3423
3424 switch (fcode)
3425 {
3426 case XTENSA_BUILTIN_UMULSIDI3:
3427 /* The umulsidi3 builtin is just a mechanism to avoid calling the real
3428 __umulsidi3 function when the Xtensa configuration can directly
3429 implement it. If not, just call the function. */
3430 return expand_call (exp, target, ignore);
09fa8841 3431
6a7a462c
BW
3432 default:
3433 internal_error ("bad builtin code");
3434 }
09fa8841
BW
3435 return NULL_RTX;
3436}
3437
a6e508f9 3438/* Worker function for TARGET_PREFERRED_RELOAD_CLASS. */
09fa8841 3439
a6e508f9
AS
3440static reg_class_t
3441xtensa_preferred_reload_class (rtx x, reg_class_t rclass)
a8cacfd2 3442{
a6e508f9 3443 if (CONSTANT_P (x) && CONST_DOUBLE_P (x))
a8cacfd2
BW
3444 return NO_REGS;
3445
89f6025d
BW
3446 /* Don't use the stack pointer or hard frame pointer for reloads!
3447 The hard frame pointer would normally be OK except that it may
3448 briefly hold an incoming argument in the prologue, and reload
3449 won't know that it is live because the hard frame pointer is
3450 treated specially. */
3451
0a2aaacc 3452 if (rclass == AR_REGS || rclass == GR_REGS)
89f6025d 3453 return RL_REGS;
a8cacfd2 3454
0a2aaacc 3455 return rclass;
a8cacfd2
BW
3456}
3457
a6e508f9
AS
3458/* Worker function for TARGET_PREFERRED_OUTPUT_RELOAD_CLASS. */
3459
3460static reg_class_t
3461xtensa_preferred_output_reload_class (rtx x ATTRIBUTE_UNUSED,
3462 reg_class_t rclass)
3463{
3464 /* Don't use the stack pointer or hard frame pointer for reloads!
3465 The hard frame pointer would normally be OK except that it may
3466 briefly hold an incoming argument in the prologue, and reload
3467 won't know that it is live because the hard frame pointer is
3468 treated specially. */
3469
3470 if (rclass == AR_REGS || rclass == GR_REGS)
3471 return RL_REGS;
3472
3473 return rclass;
3474}
3475
3476/* Worker function for TARGET_SECONDARY_RELOAD. */
a8cacfd2 3477
a6e508f9 3478static reg_class_t
a87cf97e 3479xtensa_secondary_reload (bool in_p, rtx x, reg_class_t rclass,
ef4bddc2 3480 machine_mode mode, secondary_reload_info *sri)
03984308
BW
3481{
3482 int regno;
3483
37fbe8a3 3484 if (in_p && constantpool_mem_p (x))
03984308 3485 {
37fbe8a3 3486 if (rclass == FP_REGS)
89f6025d 3487 return RL_REGS;
37fbe8a3
BW
3488
3489 if (mode == QImode)
3490 sri->icode = CODE_FOR_reloadqi_literal;
3491 else if (mode == HImode)
3492 sri->icode = CODE_FOR_reloadhi_literal;
03984308
BW
3493 }
3494
37fbe8a3 3495 regno = xt_true_regnum (x);
03984308 3496 if (ACC_REG_P (regno))
0a2aaacc
KG
3497 return ((rclass == GR_REGS || rclass == RL_REGS) ? NO_REGS : RL_REGS);
3498 if (rclass == ACC_REG)
89f6025d 3499 return (GP_REG_P (regno) ? NO_REGS : RL_REGS);
03984308
BW
3500
3501 return NO_REGS;
3502}
3503
3504
3505void
ffbc8796 3506order_regs_for_local_alloc (void)
03984308
BW
3507{
3508 if (!leaf_function_p ())
3509 {
590e2636
MF
3510 static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
3511 REG_ALLOC_ORDER;
3512 static const int reg_nonleaf_alloc_order_call0[FIRST_PSEUDO_REGISTER] =
3513 {
3514 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 12, 13, 14, 15,
3515 18,
3516 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
3517 0, 1, 16, 17,
3518 35,
3519 };
3520
3521 memcpy (reg_alloc_order, TARGET_WINDOWED_ABI ?
3522 reg_nonleaf_alloc_order : reg_nonleaf_alloc_order_call0,
03984308
BW
3523 FIRST_PSEUDO_REGISTER * sizeof (int));
3524 }
3525 else
3526 {
3527 int i, num_arg_regs;
3528 int nxt = 0;
3529
3bbc2af6
KH
3530 /* Use the AR registers in increasing order (skipping a0 and a1)
3531 but save the incoming argument registers for a last resort. */
38173d38 3532 num_arg_regs = crtl->args.info.arg_words;
03984308
BW
3533 if (num_arg_regs > MAX_ARGS_IN_REGISTERS)
3534 num_arg_regs = MAX_ARGS_IN_REGISTERS;
3535 for (i = GP_ARG_FIRST; i < 16 - num_arg_regs; i++)
3536 reg_alloc_order[nxt++] = i + num_arg_regs;
3537 for (i = 0; i < num_arg_regs; i++)
3538 reg_alloc_order[nxt++] = GP_ARG_FIRST + i;
3539
3bbc2af6 3540 /* List the coprocessor registers in order. */
985d0d50
BW
3541 for (i = 0; i < BR_REG_NUM; i++)
3542 reg_alloc_order[nxt++] = BR_REG_FIRST + i;
3543
3bbc2af6 3544 /* List the FP registers in order for now. */
03984308
BW
3545 for (i = 0; i < 16; i++)
3546 reg_alloc_order[nxt++] = FP_REG_FIRST + i;
3547
638db43e 3548 /* GCC requires that we list *all* the registers.... */
03984308
BW
3549 reg_alloc_order[nxt++] = 0; /* a0 = return address */
3550 reg_alloc_order[nxt++] = 1; /* a1 = stack pointer */
3551 reg_alloc_order[nxt++] = 16; /* pseudo frame pointer */
3552 reg_alloc_order[nxt++] = 17; /* pseudo arg pointer */
3553
03984308
BW
3554 reg_alloc_order[nxt++] = ACC_REG_FIRST; /* MAC16 accumulator */
3555 }
3556}
3557
3558
01abf342
BW
3559/* Some Xtensa targets support multiple bss sections. If the section
3560 name ends with ".bss", add SECTION_BSS to the flags. */
3561
3562static unsigned int
ffbc8796 3563xtensa_multibss_section_type_flags (tree decl, const char *name, int reloc)
01abf342
BW
3564{
3565 unsigned int flags = default_section_type_flags (decl, name, reloc);
3566 const char *suffix;
3567
3568 suffix = strrchr (name, '.');
3569 if (suffix && strcmp (suffix, ".bss") == 0)
3570 {
3571 if (!decl || (TREE_CODE (decl) == VAR_DECL
3572 && DECL_INITIAL (decl) == NULL_TREE))
3573 flags |= SECTION_BSS; /* @nobits */
3574 else
d4ee4d25 3575 warning (0, "only uninitialized variables can be placed in a "
01abf342
BW
3576 ".bss section");
3577 }
3578
3579 return flags;
3580}
3581
3582
b64a1b53
RH
3583/* The literal pool stays with the function. */
3584
d6b5193b 3585static section *
ef4bddc2 3586xtensa_select_rtx_section (machine_mode mode ATTRIBUTE_UNUSED,
ffbc8796
BW
3587 rtx x ATTRIBUTE_UNUSED,
3588 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
b64a1b53 3589{
d6b5193b 3590 return function_section (current_function_decl);
b64a1b53 3591}
fb49053f 3592
5378dda2
AS
3593/* Worker function for TARGET_REGISTER_MOVE_COST. */
3594
3595static int
ef4bddc2 3596xtensa_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
5378dda2
AS
3597 reg_class_t from, reg_class_t to)
3598{
3599 if (from == to && from != BR_REGS && to != BR_REGS)
3600 return 2;
3601 else if (reg_class_subset_p (from, AR_REGS)
3602 && reg_class_subset_p (to, AR_REGS))
3603 return 2;
3604 else if (reg_class_subset_p (from, AR_REGS) && to == ACC_REG)
3605 return 3;
3606 else if (from == ACC_REG && reg_class_subset_p (to, AR_REGS))
3607 return 3;
3608 else
3609 return 10;
3610}
3611
3612/* Worker function for TARGET_MEMORY_MOVE_COST. */
3613
3614static int
ef4bddc2 3615xtensa_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
5378dda2
AS
3616 reg_class_t rclass ATTRIBUTE_UNUSED,
3617 bool in ATTRIBUTE_UNUSED)
3618{
3619 return 4;
3620}
ffbc8796 3621
3c50106f
RH
3622/* Compute a (partial) cost for rtx X. Return true if the complete
3623 cost has been computed, and false if subexpressions should be
3624 scanned. In either case, *TOTAL contains the cost result. */
3625
3626static bool
e548c9df
AM
3627xtensa_rtx_costs (rtx x, machine_mode mode, int outer_code,
3628 int opno ATTRIBUTE_UNUSED,
68f932c4 3629 int *total, bool speed ATTRIBUTE_UNUSED)
3c50106f 3630{
e548c9df
AM
3631 int code = GET_CODE (x);
3632
3c50106f
RH
3633 switch (code)
3634 {
3635 case CONST_INT:
3636 switch (outer_code)
3637 {
3638 case SET:
3639 if (xtensa_simm12b (INTVAL (x)))
3640 {
3641 *total = 4;
3642 return true;
3643 }
3644 break;
3645 case PLUS:
3646 if (xtensa_simm8 (INTVAL (x))
3647 || xtensa_simm8x256 (INTVAL (x)))
3648 {
3649 *total = 0;
3650 return true;
3651 }
3652 break;
3653 case AND:
3654 if (xtensa_mask_immediate (INTVAL (x)))
3655 {
3656 *total = 0;
3657 return true;
3658 }
3659 break;
3660 case COMPARE:
3661 if ((INTVAL (x) == 0) || xtensa_b4const (INTVAL (x)))
3662 {
3663 *total = 0;
3664 return true;
3665 }
3666 break;
3667 case ASHIFT:
3668 case ASHIFTRT:
3669 case LSHIFTRT:
3670 case ROTATE:
3671 case ROTATERT:
3bbc2af6 3672 /* No way to tell if X is the 2nd operand so be conservative. */
3c50106f
RH
3673 default: break;
3674 }
3675 if (xtensa_simm12b (INTVAL (x)))
3676 *total = 5;
f42f5a1b
BW
3677 else if (TARGET_CONST16)
3678 *total = COSTS_N_INSNS (2);
3c50106f
RH
3679 else
3680 *total = 6;
3681 return true;
3682
3683 case CONST:
3684 case LABEL_REF:
3685 case SYMBOL_REF:
f42f5a1b
BW
3686 if (TARGET_CONST16)
3687 *total = COSTS_N_INSNS (2);
3688 else
3689 *total = 5;
3c50106f
RH
3690 return true;
3691
3692 case CONST_DOUBLE:
f42f5a1b
BW
3693 if (TARGET_CONST16)
3694 *total = COSTS_N_INSNS (4);
3695 else
3696 *total = 7;
3c50106f
RH
3697 return true;
3698
3699 case MEM:
3700 {
3701 int num_words =
e548c9df 3702 (GET_MODE_SIZE (mode) > UNITS_PER_WORD) ? 2 : 1;
3c50106f 3703
e548c9df 3704 if (memory_address_p (mode, XEXP ((x), 0)))
3c50106f
RH
3705 *total = COSTS_N_INSNS (num_words);
3706 else
3707 *total = COSTS_N_INSNS (2*num_words);
3708 return true;
3709 }
3710
3711 case FFS:
09fa8841 3712 case CTZ:
3c50106f
RH
3713 *total = COSTS_N_INSNS (TARGET_NSA ? 5 : 50);
3714 return true;
3715
09fa8841
BW
3716 case CLZ:
3717 *total = COSTS_N_INSNS (TARGET_NSA ? 1 : 50);
3718 return true;
3719
3c50106f 3720 case NOT:
e548c9df 3721 *total = COSTS_N_INSNS (mode == DImode ? 3 : 2);
3c50106f
RH
3722 return true;
3723
3724 case AND:
3725 case IOR:
3726 case XOR:
e548c9df 3727 if (mode == DImode)
3c50106f
RH
3728 *total = COSTS_N_INSNS (2);
3729 else
3730 *total = COSTS_N_INSNS (1);
3731 return true;
3732
3733 case ASHIFT:
3734 case ASHIFTRT:
3735 case LSHIFTRT:
e548c9df 3736 if (mode == DImode)
3c50106f
RH
3737 *total = COSTS_N_INSNS (50);
3738 else
3739 *total = COSTS_N_INSNS (1);
3740 return true;
3741
3742 case ABS:
3743 {
e548c9df 3744 if (mode == SFmode)
3c50106f 3745 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
e548c9df 3746 else if (mode == DFmode)
3c50106f
RH
3747 *total = COSTS_N_INSNS (50);
3748 else
3749 *total = COSTS_N_INSNS (4);
3750 return true;
3751 }
3752
3753 case PLUS:
3754 case MINUS:
3755 {
e548c9df 3756 if (mode == SFmode)
3c50106f 3757 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
e548c9df 3758 else if (mode == DFmode || mode == DImode)
3c50106f
RH
3759 *total = COSTS_N_INSNS (50);
3760 else
3761 *total = COSTS_N_INSNS (1);
3762 return true;
3763 }
3764
3765 case NEG:
e548c9df 3766 *total = COSTS_N_INSNS (mode == DImode ? 4 : 2);
3c50106f
RH
3767 return true;
3768
3769 case MULT:
3770 {
e548c9df 3771 if (mode == SFmode)
3c50106f 3772 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 4 : 50);
e548c9df 3773 else if (mode == DFmode)
3c50106f 3774 *total = COSTS_N_INSNS (50);
e548c9df 3775 else if (mode == DImode)
09fa8841 3776 *total = COSTS_N_INSNS (TARGET_MUL32_HIGH ? 10 : 50);
3c50106f
RH
3777 else if (TARGET_MUL32)
3778 *total = COSTS_N_INSNS (4);
3779 else if (TARGET_MAC16)
3780 *total = COSTS_N_INSNS (16);
3781 else if (TARGET_MUL16)
3782 *total = COSTS_N_INSNS (12);
3783 else
3784 *total = COSTS_N_INSNS (50);
3785 return true;
3786 }
3787
3788 case DIV:
3789 case MOD:
3790 {
e548c9df 3791 if (mode == SFmode)
3c50106f
RH
3792 {
3793 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT_DIV ? 8 : 50);
3794 return true;
3795 }
e548c9df 3796 else if (mode == DFmode)
3c50106f
RH
3797 {
3798 *total = COSTS_N_INSNS (50);
3799 return true;
3800 }
3801 }
3bbc2af6 3802 /* Fall through. */
3c50106f
RH
3803
3804 case UDIV:
3805 case UMOD:
3806 {
e548c9df 3807 if (mode == DImode)
3c50106f
RH
3808 *total = COSTS_N_INSNS (50);
3809 else if (TARGET_DIV32)
3810 *total = COSTS_N_INSNS (32);
3811 else
3812 *total = COSTS_N_INSNS (50);
3813 return true;
3814 }
3815
3816 case SQRT:
e548c9df 3817 if (mode == SFmode)
3c50106f
RH
3818 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT_SQRT ? 8 : 50);
3819 else
3820 *total = COSTS_N_INSNS (50);
3821 return true;
3822
3823 case SMIN:
3824 case UMIN:
3825 case SMAX:
3826 case UMAX:
3827 *total = COSTS_N_INSNS (TARGET_MINMAX ? 1 : 50);
3828 return true;
3829
3830 case SIGN_EXTRACT:
3831 case SIGN_EXTEND:
3832 *total = COSTS_N_INSNS (TARGET_SEXT ? 1 : 2);
3833 return true;
3834
3835 case ZERO_EXTRACT:
3836 case ZERO_EXTEND:
3837 *total = COSTS_N_INSNS (1);
3838 return true;
3839
3840 default:
3841 return false;
3842 }
3843}
3844
bd5bd7ac
KH
3845/* Worker function for TARGET_RETURN_IN_MEMORY. */
3846
4c45af42 3847static bool
586de218 3848xtensa_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
4c45af42
KH
3849{
3850 return ((unsigned HOST_WIDE_INT) int_size_in_bytes (type)
3851 > 4 * UNITS_PER_WORD);
3852}
3853
e2b2d01e
AS
3854/* Worker function for TARGET_FUNCTION_VALUE. */
3855
3856rtx
3857xtensa_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED,
3858 bool outgoing)
3859{
3860 return gen_rtx_REG ((INTEGRAL_TYPE_P (valtype)
3861 && TYPE_PRECISION (valtype) < BITS_PER_WORD)
3862 ? SImode : TYPE_MODE (valtype),
3863 outgoing ? GP_OUTGOING_RETURN : GP_RETURN);
3864}
7f0ee694 3865
dde8a3a4
AS
3866/* Worker function for TARGET_LIBCALL_VALUE. */
3867
3868static rtx
ef4bddc2 3869xtensa_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
dde8a3a4
AS
3870{
3871 return gen_rtx_REG ((GET_MODE_CLASS (mode) == MODE_INT
3872 && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
3873 ? SImode : mode, GP_RETURN);
3874}
3875
3876/* Worker function TARGET_FUNCTION_VALUE_REGNO_P. */
3877
3878static bool
3879xtensa_function_value_regno_p (const unsigned int regno)
3880{
3881 return (regno == GP_RETURN);
3882}
3883
2b4fa409
RH
3884/* The static chain is passed in memory. Provide rtx giving 'mem'
3885 expressions that denote where they are stored. */
3886
3887static rtx
c21df29b 3888xtensa_static_chain (const_tree ARG_UNUSED (fndecl_or_type), bool incoming_p)
2b4fa409 3889{
590e2636
MF
3890 if (TARGET_WINDOWED_ABI)
3891 {
3892 rtx base = incoming_p ? arg_pointer_rtx : stack_pointer_rtx;
3893 return gen_frame_mem (Pmode, plus_constant (Pmode, base,
3894 -5 * UNITS_PER_WORD));
3895 }
3896 else
3897 return gen_rtx_REG (Pmode, A8_REG);
2b4fa409
RH
3898}
3899
3900
7f0ee694
BW
3901/* TRAMPOLINE_TEMPLATE: For Xtensa, the trampoline must perform an ENTRY
3902 instruction with a minimal stack frame in order to get some free
3903 registers. Once the actual call target is known, the proper stack frame
3904 size is extracted from the ENTRY instruction at the target and the
3905 current frame is adjusted to match. The trampoline then transfers
3906 control to the instruction following the ENTRY at the target. Note:
3907 this assumes that the target begins with an ENTRY instruction. */
3908
3c1229cb
RH
3909static void
3910xtensa_asm_trampoline_template (FILE *stream)
7f0ee694
BW
3911{
3912 bool use_call0 = (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS);
3913
3914 fprintf (stream, "\t.begin no-transform\n");
7f0ee694 3915
590e2636 3916 if (TARGET_WINDOWED_ABI)
7f0ee694 3917 {
590e2636 3918 fprintf (stream, "\tentry\tsp, %d\n", MIN_FRAME_SIZE);
7f0ee694 3919
590e2636
MF
3920 if (use_call0)
3921 {
3922 /* Save the return address. */
3923 fprintf (stream, "\tmov\ta10, a0\n");
7f0ee694 3924
590e2636
MF
3925 /* Use a CALL0 instruction to skip past the constants and in the
3926 process get the PC into A0. This allows PC-relative access to
3927 the constants without relying on L32R. */
3928 fprintf (stream, "\tcall0\t.Lskipconsts\n");
3929 }
3930 else
3931 fprintf (stream, "\tj\t.Lskipconsts\n");
7f0ee694 3932
590e2636
MF
3933 fprintf (stream, "\t.align\t4\n");
3934 fprintf (stream, ".Lchainval:%s0\n", integer_asm_op (4, TRUE));
3935 fprintf (stream, ".Lfnaddr:%s0\n", integer_asm_op (4, TRUE));
3936 fprintf (stream, ".Lskipconsts:\n");
3937
3938 /* Load the static chain and function address from the trampoline. */
3939 if (use_call0)
3940 {
3941 fprintf (stream, "\taddi\ta0, a0, 3\n");
3942 fprintf (stream, "\tl32i\ta9, a0, 0\n");
3943 fprintf (stream, "\tl32i\ta8, a0, 4\n");
3944 }
3945 else
3946 {
3947 fprintf (stream, "\tl32r\ta9, .Lchainval\n");
3948 fprintf (stream, "\tl32r\ta8, .Lfnaddr\n");
3949 }
3950
3951 /* Store the static chain. */
3952 fprintf (stream, "\ts32i\ta9, sp, %d\n", MIN_FRAME_SIZE - 20);
3953
3954 /* Set the proper stack pointer value. */
3955 fprintf (stream, "\tl32i\ta9, a8, 0\n");
3956 fprintf (stream, "\textui\ta9, a9, %d, 12\n",
3957 TARGET_BIG_ENDIAN ? 8 : 12);
3958 fprintf (stream, "\tslli\ta9, a9, 3\n");
3959 fprintf (stream, "\taddi\ta9, a9, %d\n", -MIN_FRAME_SIZE);
3960 fprintf (stream, "\tsub\ta9, sp, a9\n");
3961 fprintf (stream, "\tmovsp\tsp, a9\n");
3962
3963 if (use_call0)
3964 /* Restore the return address. */
3965 fprintf (stream, "\tmov\ta0, a10\n");
3966
3967 /* Jump to the instruction following the ENTRY. */
3968 fprintf (stream, "\taddi\ta8, a8, 3\n");
3969 fprintf (stream, "\tjx\ta8\n");
3970
3971 /* Pad size to a multiple of TRAMPOLINE_ALIGNMENT. */
3972 if (use_call0)
3973 fprintf (stream, "\t.byte\t0\n");
3974 else
3975 fprintf (stream, "\tnop\n");
7f0ee694
BW
3976 }
3977 else
3978 {
590e2636
MF
3979 if (use_call0)
3980 {
3981 /* Save the return address. */
3982 fprintf (stream, "\tmov\ta10, a0\n");
7f0ee694 3983
590e2636
MF
3984 /* Use a CALL0 instruction to skip past the constants and in the
3985 process get the PC into A0. This allows PC-relative access to
3986 the constants without relying on L32R. */
3987 fprintf (stream, "\tcall0\t.Lskipconsts\n");
3988 }
3989 else
3990 fprintf (stream, "\tj\t.Lskipconsts\n");
7f0ee694 3991
590e2636
MF
3992 fprintf (stream, "\t.align\t4\n");
3993 fprintf (stream, ".Lchainval:%s0\n", integer_asm_op (4, TRUE));
3994 fprintf (stream, ".Lfnaddr:%s0\n", integer_asm_op (4, TRUE));
3995 fprintf (stream, ".Lskipconsts:\n");
7f0ee694 3996
590e2636
MF
3997 /* Load the static chain and function address from the trampoline. */
3998 if (use_call0)
3999 {
4000 fprintf (stream, "\taddi\ta0, a0, 3\n");
4001 fprintf (stream, "\tl32i\ta8, a0, 0\n");
4002 fprintf (stream, "\tl32i\ta9, a0, 4\n");
4003 fprintf (stream, "\tmov\ta0, a10\n");
4004 }
4005 else
4006 {
4007 fprintf (stream, "\tl32r\ta8, .Lchainval\n");
4008 fprintf (stream, "\tl32r\ta9, .Lfnaddr\n");
4009 }
4010 fprintf (stream, "\tjx\ta9\n");
7f0ee694 4011
590e2636
MF
4012 /* Pad size to a multiple of TRAMPOLINE_ALIGNMENT. */
4013 if (use_call0)
4014 fprintf (stream, "\t.byte\t0\n");
4015 else
4016 fprintf (stream, "\tnop\n");
4017 }
7f0ee694
BW
4018 fprintf (stream, "\t.end no-transform\n");
4019}
4020
3c1229cb
RH
4021static void
4022xtensa_trampoline_init (rtx m_tramp, tree fndecl, rtx chain)
7f0ee694 4023{
3c1229cb 4024 rtx func = XEXP (DECL_RTL (fndecl), 0);
7f0ee694 4025 bool use_call0 = (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS);
590e2636
MF
4026 int chain_off;
4027 int func_off;
4028
4029 if (TARGET_WINDOWED_ABI)
4030 {
4031 chain_off = use_call0 ? 12 : 8;
4032 func_off = use_call0 ? 16 : 12;
4033 }
4034 else
4035 {
4036 chain_off = use_call0 ? 8 : 4;
4037 func_off = use_call0 ? 12 : 8;
4038 }
3c1229cb
RH
4039
4040 emit_block_move (m_tramp, assemble_trampoline_template (),
4041 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
4042
4043 emit_move_insn (adjust_address (m_tramp, SImode, chain_off), chain);
4044 emit_move_insn (adjust_address (m_tramp, SImode, func_off), func);
7f0ee694 4045 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_sync_caches"),
046845de 4046 LCT_NORMAL, VOIDmode, 1, XEXP (m_tramp, 0), Pmode);
7f0ee694
BW
4047}
4048
1a627b35
RS
4049/* Implement TARGET_LEGITIMATE_CONSTANT_P. */
4050
4051static bool
ef4bddc2 4052xtensa_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1a627b35
RS
4053{
4054 return !xtensa_tls_referenced_p (x);
4055}
7f0ee694 4056
6383386a
FY
4057/* Implement TARGET_CAN_USE_DOLOOP_P. */
4058
4059static bool
4060xtensa_can_use_doloop_p (const widest_int &, const widest_int &,
4061 unsigned int loop_depth, bool entered_at_top)
4062{
4063 /* Considering limitations in the hardware, only use doloop
4064 for innermost loops which must be entered from the top. */
4065 if (loop_depth > 1 || !entered_at_top)
4066 return false;
4067
4068 return true;
4069}
4070
4071/* NULL if INSN insn is valid within a low-overhead loop.
4072 Otherwise return why doloop cannot be applied. */
4073
4074static const char *
4075xtensa_invalid_within_doloop (const rtx_insn *insn)
4076{
4077 if (CALL_P (insn))
4078 return "Function call in the loop.";
4079
4080 if (JUMP_P (insn) && INSN_CODE (insn) == CODE_FOR_return)
4081 return "Return from a call instruction in the loop.";
4082
4083 return NULL;
4084}
4085
4086/* Optimize LOOP. */
4087
4088static bool
4089hwloop_optimize (hwloop_info loop)
4090{
4091 int i;
4092 edge entry_edge;
4093 basic_block entry_bb;
4094 rtx iter_reg;
4095 rtx_insn *insn, *seq, *entry_after;
4096
4097 if (loop->depth > 1)
4098 {
4099 if (dump_file)
4100 fprintf (dump_file, ";; loop %d is not innermost\n",
4101 loop->loop_no);
4102 return false;
4103 }
4104
4105 if (!loop->incoming_dest)
4106 {
4107 if (dump_file)
4108 fprintf (dump_file, ";; loop %d has more than one entry\n",
4109 loop->loop_no);
4110 return false;
4111 }
4112
4113 if (loop->incoming_dest != loop->head)
4114 {
4115 if (dump_file)
4116 fprintf (dump_file, ";; loop %d is not entered from head\n",
4117 loop->loop_no);
4118 return false;
4119 }
4120
4121 if (loop->has_call || loop->has_asm)
4122 {
4123 if (dump_file)
4124 fprintf (dump_file, ";; loop %d has invalid insn\n",
4125 loop->loop_no);
4126 return false;
4127 }
4128
4129 /* Scan all the blocks to make sure they don't use iter_reg. */
4130 if (loop->iter_reg_used || loop->iter_reg_used_outside)
4131 {
4132 if (dump_file)
4133 fprintf (dump_file, ";; loop %d uses iterator\n",
4134 loop->loop_no);
4135 return false;
4136 }
4137
4138 /* Check if start_label appears before doloop_end. */
4139 insn = loop->start_label;
4140 while (insn && insn != loop->loop_end)
4141 insn = NEXT_INSN (insn);
4142
4143 if (!insn)
4144 {
4145 if (dump_file)
4146 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
4147 loop->loop_no);
4148 return false;
4149 }
4150
4151 /* Get the loop iteration register. */
4152 iter_reg = loop->iter_reg;
4153
4154 gcc_assert (REG_P (iter_reg));
4155
4156 entry_edge = NULL;
4157
4158 FOR_EACH_VEC_SAFE_ELT (loop->incoming, i, entry_edge)
4159 if (entry_edge->flags & EDGE_FALLTHRU)
4160 break;
4161
4162 if (entry_edge == NULL)
4163 return false;
4164
4165 /* Place the zero_cost_loop_start instruction before the loop. */
4166 entry_bb = entry_edge->src;
4167
4168 start_sequence ();
4169
4170 insn = emit_insn (gen_zero_cost_loop_start (loop->iter_reg,
4171 loop->start_label,
4172 loop->iter_reg));
4173
4174 seq = get_insns ();
4175
4176 if (!single_succ_p (entry_bb) || vec_safe_length (loop->incoming) > 1)
4177 {
4178 basic_block new_bb;
4179 edge e;
4180 edge_iterator ei;
4181
4182 emit_insn_before (seq, BB_HEAD (loop->head));
4183 seq = emit_label_before (gen_label_rtx (), seq);
4184 new_bb = create_basic_block (seq, insn, entry_bb);
4185 FOR_EACH_EDGE (e, ei, loop->incoming)
4186 {
4187 if (!(e->flags & EDGE_FALLTHRU))
4188 redirect_edge_and_branch_force (e, new_bb);
4189 else
4190 redirect_edge_succ (e, new_bb);
4191 }
4192
4193 make_edge (new_bb, loop->head, 0);
4194 }
4195 else
4196 {
4197 entry_after = BB_END (entry_bb);
4198 while (DEBUG_INSN_P (entry_after)
4199 || (NOTE_P (entry_after)
464636c0
MF
4200 && NOTE_KIND (entry_after) != NOTE_INSN_BASIC_BLOCK
4201 /* Make sure we don't split a call and its corresponding
4202 CALL_ARG_LOCATION note. */
4203 && NOTE_KIND (entry_after) != NOTE_INSN_CALL_ARG_LOCATION))
6383386a
FY
4204 entry_after = PREV_INSN (entry_after);
4205
4206 emit_insn_after (seq, entry_after);
4207 }
4208
4209 end_sequence ();
4210
4211 return true;
4212}
4213
4214/* A callback for the hw-doloop pass. Called when a loop we have discovered
4215 turns out not to be optimizable; we have to split the loop_end pattern into
4216 a subtract and a test. */
4217
4218static void
4219hwloop_fail (hwloop_info loop)
4220{
4221 rtx test;
4222 rtx_insn *insn = loop->loop_end;
4223
4224 emit_insn_before (gen_addsi3 (loop->iter_reg,
4225 loop->iter_reg,
4226 constm1_rtx),
4227 loop->loop_end);
4228
4229 test = gen_rtx_NE (VOIDmode, loop->iter_reg, const0_rtx);
4230 insn = emit_jump_insn_before (gen_cbranchsi4 (test,
4231 loop->iter_reg, const0_rtx,
4232 loop->start_label),
4233 loop->loop_end);
4234
4235 JUMP_LABEL (insn) = loop->start_label;
4236 LABEL_NUSES (loop->start_label)++;
4237 delete_insn (loop->loop_end);
4238}
4239
4240/* A callback for the hw-doloop pass. This function examines INSN; if
4241 it is a doloop_end pattern we recognize, return the reg rtx for the
4242 loop counter. Otherwise, return NULL_RTX. */
4243
4244static rtx
4245hwloop_pattern_reg (rtx_insn *insn)
4246{
4247 rtx reg;
4248
4249 if (!JUMP_P (insn) || recog_memoized (insn) != CODE_FOR_loop_end)
4250 return NULL_RTX;
4251
4252 reg = SET_DEST (XVECEXP (PATTERN (insn), 0, 1));
4253 if (!REG_P (reg))
4254 return NULL_RTX;
4255
4256 return reg;
4257}
4258
4259
4260static struct hw_doloop_hooks xtensa_doloop_hooks =
4261{
4262 hwloop_pattern_reg,
4263 hwloop_optimize,
4264 hwloop_fail
4265};
4266
4267/* Run from machine_dependent_reorg, this pass looks for doloop_end insns
4268 and tries to rewrite the RTL of these loops so that proper Xtensa
4269 hardware loops are generated. */
4270
4271static void
4272xtensa_reorg_loops (void)
4273{
1a711a0b
MF
4274 if (TARGET_LOOPS)
4275 reorg_loops (false, &xtensa_doloop_hooks);
c6836000 4276}
6383386a
FY
4277
4278/* Implement the TARGET_MACHINE_DEPENDENT_REORG pass. */
4279
4280static void
4281xtensa_reorg (void)
4282{
4283 /* We are freeing block_for_insn in the toplev to keep compatibility
4284 with old MDEP_REORGS that are not CFG based. Recompute it now. */
4285 compute_bb_for_insn ();
4286
4287 df_analyze ();
4288
4289 /* Doloop optimization. */
4290 xtensa_reorg_loops ();
4291}
4292
590e2636
MF
4293/* Update register usage after having seen the compiler flags. */
4294
4295static void
4296xtensa_conditional_register_usage (void)
4297{
4298 unsigned i, c_mask;
4299
4300 c_mask = TARGET_WINDOWED_ABI ? (1 << 1) : (1 << 2);
4301
4302 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4303 {
4304 /* Set/reset conditionally defined registers from
4305 CALL_USED_REGISTERS initializer. */
4306 if (call_used_regs[i] > 1)
4307 call_used_regs[i] = !!(call_used_regs[i] & c_mask);
4308 }
4309
4310 /* Remove hard FP register from the preferred reload registers set. */
4311 CLEAR_HARD_REG_BIT (reg_class_contents[(int)RL_REGS],
4312 HARD_FRAME_POINTER_REGNUM);
4313}
4314
4315/* Map hard register number to register class */
4316
4317enum reg_class xtensa_regno_to_class (int regno)
4318{
4319 static const enum reg_class regno_to_class[FIRST_PSEUDO_REGISTER] =
4320 {
4321 RL_REGS, SP_REG, RL_REGS, RL_REGS,
4322 RL_REGS, RL_REGS, RL_REGS, RL_REGS,
4323 RL_REGS, RL_REGS, RL_REGS, RL_REGS,
4324 RL_REGS, RL_REGS, RL_REGS, RL_REGS,
4325 AR_REGS, AR_REGS, BR_REGS,
4326 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
4327 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
4328 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
4329 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
4330 ACC_REG,
4331 };
4332
4333 if (regno == HARD_FRAME_POINTER_REGNUM)
4334 return GR_REGS;
4335 else
4336 return regno_to_class[regno];
4337}
4338
e2500fed 4339#include "gt-xtensa.h"