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