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