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