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