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