]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/xtensa/xtensa.c
re PR target/26015 (ICE during bootstrap for vax architecture)
[thirdparty/gcc.git] / gcc / config / xtensa / xtensa.c
CommitLineData
03984308 1/* Subroutines for insn-output.c for Tensilica's Xtensa architecture.
da1f39e4
BW
2 Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007
3 Free Software Foundation, Inc.
03984308
BW
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
2f83c7d6 10Software Foundation; either version 3, or (at your option) any later
03984308
BW
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
2f83c7d6
NC
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
03984308
BW
21
22#include "config.h"
23#include "system.h"
4977bab6
ZW
24#include "coretypes.h"
25#include "tm.h"
03984308
BW
26#include "rtl.h"
27#include "regs.h"
03984308
BW
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"
07232638 47#include "ggc.h"
03984308
BW
48#include "target.h"
49#include "target-def.h"
540eaea8 50#include "langhooks.h"
85d53c1d 51#include "tree-gimple.h"
e70312d4 52#include "df.h"
85d53c1d 53
03984308
BW
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
638db43e 57 of EQ, NE, etc. */
03984308 58
ffbc8796
BW
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};
03984308
BW
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
a46bbb5a 88/* Largest block move to handle in-line. */
03984308
BW
89#define LARGEST_MOVE_RATIO 15
90
91/* Define the structure for the machine field in struct function. */
e2500fed 92struct machine_function GTY(())
03984308
BW
93{
94 int accesses_prev_frame;
997b8b4d
BW
95 bool need_a7_copy;
96 bool vararg_a7;
0d8442b8 97 rtx vararg_a7_copy;
997b8b4d 98 rtx set_frame_ptr_insn;
03984308
BW
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
638db43e 103 treatment. */
03984308
BW
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{
89f6025d
BW
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,
03984308
BW
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
ffbc8796
BW
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);
ffbc8796 133static struct machine_function * xtensa_init_machine_status (void);
586de218 134static bool xtensa_return_in_msb (const_tree);
ffbc8796
BW
135static void printx (FILE *, signed int);
136static void xtensa_function_epilogue (FILE *, HOST_WIDE_INT);
4c45af42 137static rtx xtensa_builtin_saveregs (void);
ffbc8796
BW
138static unsigned int xtensa_multibss_section_type_flags (tree, const char *,
139 int) ATTRIBUTE_UNUSED;
d6b5193b
RS
140static section *xtensa_select_rtx_section (enum machine_mode, rtx,
141 unsigned HOST_WIDE_INT);
ffbc8796 142static bool xtensa_rtx_costs (rtx, int, int, int *);
c35d187f 143static tree xtensa_build_builtin_va_list (void);
586de218 144static bool xtensa_return_in_memory (const_tree, const_tree);
85d53c1d 145static tree xtensa_gimplify_va_arg_expr (tree, tree, tree *, tree *);
09fa8841
BW
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);
9d0b1619 149static void xtensa_va_start (tree, rtx);
b64a1b53 150
b64a1b53
RH
151static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
152 REG_ALLOC_ORDER;
153\f
03984308
BW
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
b64a1b53
RH
169#undef TARGET_ASM_SELECT_RTX_SECTION
170#define TARGET_ASM_SELECT_RTX_SECTION xtensa_select_rtx_section
03984308 171
66beb87a
RS
172#undef TARGET_DEFAULT_TARGET_FLAGS
173#define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | MASK_FUSED_MADD)
174
3c50106f
RH
175#undef TARGET_RTX_COSTS
176#define TARGET_RTX_COSTS xtensa_rtx_costs
dcefdf67
RH
177#undef TARGET_ADDRESS_COST
178#define TARGET_ADDRESS_COST hook_int_rtx_0
3c50106f 179
c35d187f
RH
180#undef TARGET_BUILD_BUILTIN_VA_LIST
181#define TARGET_BUILD_BUILTIN_VA_LIST xtensa_build_builtin_va_list
182
d7bd8aeb
JJ
183#undef TARGET_EXPAND_BUILTIN_VA_START
184#define TARGET_EXPAND_BUILTIN_VA_START xtensa_va_start
185
4c45af42 186#undef TARGET_PROMOTE_FUNCTION_ARGS
586de218 187#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
4c45af42 188#undef TARGET_PROMOTE_FUNCTION_RETURN
586de218 189#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
4c45af42 190#undef TARGET_PROMOTE_PROTOTYPES
586de218 191#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
4c45af42 192
4c45af42
KH
193#undef TARGET_RETURN_IN_MEMORY
194#define TARGET_RETURN_IN_MEMORY xtensa_return_in_memory
42ba5130 195#undef TARGET_SPLIT_COMPLEX_ARG
3101faab 196#define TARGET_SPLIT_COMPLEX_ARG hook_bool_const_tree_true
fe984136
RH
197#undef TARGET_MUST_PASS_IN_STACK
198#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
4c45af42
KH
199
200#undef TARGET_EXPAND_BUILTIN_SAVEREGS
201#define TARGET_EXPAND_BUILTIN_SAVEREGS xtensa_builtin_saveregs
85d53c1d
RH
202#undef TARGET_GIMPLIFY_VA_ARG_EXPR
203#define TARGET_GIMPLIFY_VA_ARG_EXPR xtensa_gimplify_va_arg_expr
4c45af42 204
6e5ff6e7
BW
205#undef TARGET_RETURN_IN_MSB
206#define TARGET_RETURN_IN_MSB xtensa_return_in_msb
207
09fa8841
BW
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
b64a1b53 215struct gcc_target targetm = TARGET_INITIALIZER;
03984308 216
887af464
BW
217\f
218/* Functions to test Xtensa immediate operand validity. */
03984308 219
8eb1bc5c
BW
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)
03984308
BW
264{
265 switch (v)
266 {
8eb1bc5c
BW
267 case -1:
268 case 1:
03984308
BW
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:
8eb1bc5c 283 return true;
03984308 284 }
8eb1bc5c 285 return false;
03984308
BW
286}
287
03984308 288
8eb1bc5c
BW
289bool
290xtensa_b4const_or_zero (HOST_WIDE_INT v)
03984308 291{
8eb1bc5c
BW
292 if (v == 0)
293 return true;
294 return xtensa_b4const (v);
03984308
BW
295}
296
03984308 297
8eb1bc5c
BW
298bool
299xtensa_b4constu (HOST_WIDE_INT v)
03984308
BW
300{
301 switch (v)
302 {
8eb1bc5c
BW
303 case 32768:
304 case 65536:
03984308
BW
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:
8eb1bc5c 319 return true;
03984308 320 }
8eb1bc5c 321 return false;
03984308
BW
322}
323
03984308 324
8eb1bc5c
BW
325bool
326xtensa_mask_immediate (HOST_WIDE_INT v)
03984308 327{
8eb1bc5c
BW
328#define MAX_MASK_SIZE 16
329 int mask_size;
03984308 330
8eb1bc5c
BW
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 }
03984308 339
8eb1bc5c 340 return false;
03984308
BW
341}
342
03984308 343
03984308 344/* This is just like the standard true_regnum() function except that it
638db43e 345 works even when reg_renumber is not initialized. */
03984308
BW
346
347int
ffbc8796 348xt_true_regnum (rtx x)
03984308
BW
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
03984308 370int
ffbc8796 371xtensa_valid_move (enum machine_mode mode, rtx *operands)
03984308 372{
a8cacfd2
BW
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
638db43e 380 /* The stack pointer can only be assigned with a MOVSP opcode. */
a8cacfd2
BW
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 }
3437320b 389 if (register_operand (operands[1], mode))
a8cacfd2
BW
390 {
391 int src_regnum = xt_true_regnum (operands[1]);
392 if (!ACC_REG_P (src_regnum))
393 return true;
394 }
03984308
BW
395 return FALSE;
396}
397
398
03984308 399int
ffbc8796 400smalloffset_mem_p (rtx op)
03984308
BW
401{
402 if (GET_CODE (op) == MEM)
403 {
404 rtx addr = XEXP (op, 0);
405 if (GET_CODE (addr) == REG)
da1f39e4 406 return BASE_REG_P (addr, 0);
03984308
BW
407 if (GET_CODE (addr) == PLUS)
408 {
409 rtx offset = XEXP (addr, 0);
8eb1bc5c 410 HOST_WIDE_INT val;
03984308
BW
411 if (GET_CODE (offset) != CONST_INT)
412 offset = XEXP (addr, 1);
413 if (GET_CODE (offset) != CONST_INT)
414 return FALSE;
8eb1bc5c
BW
415
416 val = INTVAL (offset);
417 return (val & 3) == 0 && (val >= 0 && val <= 60);
03984308
BW
418 }
419 }
420 return FALSE;
421}
422
423
03984308 424int
ffbc8796 425constantpool_address_p (rtx addr)
03984308
BW
426{
427 rtx sym = addr;
428
429 if (GET_CODE (addr) == CONST)
430 {
431 rtx offset;
432
3bbc2af6 433 /* Only handle (PLUS (SYM, OFFSET)) form. */
03984308
BW
434 addr = XEXP (addr, 0);
435 if (GET_CODE (addr) != PLUS)
436 return FALSE;
437
3bbc2af6 438 /* Make sure the address is word aligned. */
03984308
BW
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
ffbc8796 455constantpool_mem_p (rtx op)
03984308 456{
63694bdd
BW
457 if (GET_CODE (op) == SUBREG)
458 op = SUBREG_REG (op);
03984308
BW
459 if (GET_CODE (op) == MEM)
460 return constantpool_address_p (XEXP (op, 0));
461 return FALSE;
462}
463
464
03984308 465void
ffbc8796 466xtensa_extend_reg (rtx dst, rtx src)
03984308
BW
467{
468 rtx temp = gen_reg_rtx (SImode);
469 rtx shift = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (GET_MODE (src)));
470
3bbc2af6 471 /* Generate paradoxical subregs as needed so that the modes match. */
03984308
BW
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
8eb1bc5c 480bool
ffbc8796 481xtensa_mem_offset (unsigned v, enum machine_mode mode)
03984308
BW
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
638db43e 490 last piece requires a byte load/store. */
f42f5a1b
BW
491 return (xtensa_uimm8 (v)
492 && xtensa_uimm8 (v + MOVE_MAX * LARGEST_MOVE_RATIO));
03984308
BW
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
ffbc8796 511/* Make normal rtx_code into something we can index from an array. */
03984308
BW
512
513static enum internal_test
ffbc8796 514map_test_to_internal_test (enum rtx_code test_code)
03984308
BW
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
638db43e 538 the comparison expression. */
03984308
BW
539
540static rtx
ffbc8796
BW
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 */)
03984308 545{
ffbc8796
BW
546 struct cmp_info
547 {
03984308 548 enum rtx_code test_code; /* test code to use in insn */
8eb1bc5c 549 bool (*const_range_p) (HOST_WIDE_INT); /* range check function */
03984308
BW
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
8eb1bc5c
BW
559 { EQ, xtensa_b4const_or_zero, 0, 0, 0, 0, 0 }, /* EQ */
560 { NE, xtensa_b4const_or_zero, 0, 0, 0, 0, 0 }, /* NE */
03984308 561
8eb1bc5c
BW
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 */
03984308
BW
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);
177b6be0 578 gcc_assert (test != ITEST_MAX);
03984308
BW
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
1c563bed 631 return gen_rtx_fmt_ee (p_info->test_code, VOIDmode, cmp0, cmp1);
03984308
BW
632}
633
634
635/* Generate the code to compare two float values. The return value is
638db43e 636 the comparison expression. */
03984308
BW
637
638static rtx
ffbc8796
BW
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 */)
03984308 642{
ffbc8796 643 rtx (*gen_fn) (rtx, rtx, rtx);
03984308
BW
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;
633e4eb4 655 default:
1c563bed 656 fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1));
03984308
BW
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
1c563bed 670 return gen_rtx_fmt_ee (invert ? EQ : NE, VOIDmode, brtmp, const0_rtx);
03984308
BW
671}
672
673
674void
ffbc8796 675xtensa_expand_conditional_branch (rtx *operands, enum rtx_code test_code)
03984308
BW
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:
1c563bed 688 fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1));
03984308
BW
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)
da1f39e4
BW
697 fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode,
698 cmp0, cmp1));
03984308
BW
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
ffbc8796 723gen_conditional_move (rtx cmp)
03984308
BW
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
638db43e 737 produce them. */
03984308
BW
738
739 if ((code == GT) && (op1 == constm1_rtx))
740 {
741 code = GE;
742 op1 = const0_rtx;
743 }
1c563bed 744 cmp = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
03984308
BW
745
746 if (boolean_operator (cmp, VOIDmode))
747 {
3bbc2af6 748 /* Swap the operands to make const0 second. */
03984308
BW
749 if (op0 == const0_rtx)
750 {
751 op0 = op1;
752 op1 = const0_rtx;
753 }
754
3bbc2af6 755 /* If not comparing against zero, emit a comparison (subtract). */
03984308
BW
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 {
3bbc2af6 765 /* Swap the operands to make const0 second. */
03984308
BW
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;
177b6be0 775 default: gcc_unreachable ();
03984308
BW
776 }
777 }
778
779 if (op1 != const0_rtx)
780 return 0;
781 }
782 else
783 return 0;
784
1c563bed 785 return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
03984308
BW
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
ffbc8796 796xtensa_expand_conditional_move (rtx *operands, int isflt)
03984308
BW
797{
798 rtx cmp;
ffbc8796 799 rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx);
03984308
BW
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
ffbc8796 820xtensa_expand_scc (rtx *operands)
03984308
BW
821{
822 rtx dest = operands[0];
823 rtx cmp = operands[1];
824 rtx one_tmp, zero_tmp;
ffbc8796 825 rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx);
03984308
BW
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
633e4eb4
BW
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
ffbc8796 847xtensa_split_operand_pair (rtx operands[4], enum machine_mode mode)
633e4eb4
BW
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:
177b6be0 867 gcc_unreachable ();
633e4eb4
BW
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:
177b6be0 883 gcc_unreachable ();
633e4eb4
BW
884 }
885}
886
887
03984308 888/* Emit insns to move operands[1] into operands[0].
03984308
BW
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
ffbc8796 894xtensa_emit_move_sequence (rtx *operands, enum machine_mode mode)
03984308
BW
895{
896 if (CONSTANT_P (operands[1])
03984308
BW
897 && (GET_CODE (operands[1]) != CONST_INT
898 || !xtensa_simm12b (INTVAL (operands[1]))))
899 {
f42f5a1b
BW
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 }
03984308
BW
921 }
922
997b8b4d
BW
923 if (!(reload_in_progress | reload_completed)
924 && !xtensa_valid_move (mode, operands))
925 operands[1] = force_reg (mode, operands[1]);
03984308 926
997b8b4d 927 operands[1] = xtensa_copy_incoming_a7 (operands[1]);
03984308
BW
928
929 /* During reload we don't want to emit (subreg:X (mem:Y)) since that
638db43e
BW
930 instruction won't be recognized after reload, so we remove the
931 subreg and adjust mem accordingly. */
03984308
BW
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
f42f5a1b 940
03984308 941static rtx
ffbc8796 942fixup_subreg_mem (rtx x)
03984308
BW
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
997b8b4d
BW
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. */
58db834b 975
997b8b4d
BW
976rtx
977xtensa_copy_incoming_a7 (rtx opnd)
58db834b 978{
997b8b4d
BW
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. */
177b6be0 987 gcc_assert (!cfun->machine->set_frame_ptr_insn);
997b8b4d
BW
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)
58db834b 995 {
177b6be0 996 gcc_assert (SUBREG_BYTE (reg) == 0);
997b8b4d
BW
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;
e6aecf8e 1003
997b8b4d 1004 /* 1-word args will always be in a7; 2-word args in a6/a7. */
177b6be0 1005 gcc_assert (REGNO (reg) + HARD_REGNO_NREGS (A7_REG, mode) - 1 == A7_REG);
58db834b 1006
997b8b4d 1007 cfun->machine->need_a7_copy = false;
58db834b 1008
997b8b4d
BW
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. */
58db834b 1011
0d8442b8 1012 start_sequence ();
997b8b4d 1013 tmp = gen_reg_rtx (mode);
58db834b 1014
997b8b4d
BW
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:
177b6be0 1037 gcc_unreachable ();
58db834b
BW
1038 }
1039
997b8b4d
BW
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 {
0d8442b8
BW
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;
997b8b4d
BW
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 ();
0d8442b8
BW
1059 /* Do not use entry_of_function() here. This is called from within
1060 expand_function_start, when the CFG still holds GIMPLE. */
997b8b4d
BW
1061 emit_insn_after (entry_insns, get_insns ());
1062 pop_topmost_sequence ();
1063 }
1064
1065 return tmp;
58db834b
BW
1066}
1067
1068
a46bbb5a
BW
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().
03984308
BW
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
ffbc8796 1080xtensa_expand_block_move (rtx *operands)
03984308 1081{
7eda7cda
RH
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;
03984308 1090 int num_pieces, move_ratio;
7eda7cda
RH
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;
03984308 1100
3bbc2af6 1101 /* If this is not a fixed size move, just call memcpy. */
03984308
BW
1102 if (!optimize || (GET_CODE (operands[2]) != CONST_INT))
1103 return 0;
1104
7eda7cda
RH
1105 bytes = INTVAL (operands[2]);
1106 align = INTVAL (operands[3]);
1107
3bbc2af6 1108 /* Anything to move? */
03984308 1109 if (bytes <= 0)
7eda7cda 1110 return 0;
03984308
BW
1111
1112 if (align > MOVE_MAX)
1113 align = MOVE_MAX;
1114
3bbc2af6 1115 /* Decide whether to expand inline based on the optimization level. */
03984308
BW
1116 move_ratio = 4;
1117 if (optimize > 2)
1118 move_ratio = LARGEST_MOVE_RATIO;
3bbc2af6 1119 num_pieces = (bytes / align) + (bytes % align); /* Close enough anyway. */
7eda7cda 1120 if (num_pieces > move_ratio)
03984308
BW
1121 return 0;
1122
7eda7cda
RH
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 }
03984308 1129
7eda7cda
RH
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 }
03984308 1136
7eda7cda 1137 active[0] = active[1] = false;
03984308 1138
7eda7cda 1139 do
03984308 1140 {
7eda7cda
RH
1141 next = phase;
1142 phase ^= 1;
03984308 1143
7eda7cda 1144 if (bytes > 0)
03984308 1145 {
7eda7cda 1146 int next_amount;
03984308 1147
7eda7cda
RH
1148 next_amount = (bytes >= 4 ? 4 : (bytes >= 2 ? 2 : 1));
1149 next_amount = MIN (next_amount, align);
03984308 1150
7eda7cda
RH
1151 amount[next] = next_amount;
1152 mode[next] = mode_from_align[next_amount];
1153 temp[next] = gen_reg_rtx (mode[next]);
03984308 1154
7eda7cda
RH
1155 x = adjust_address (src_mem, mode[next], offset_ld);
1156 emit_insn (gen_rtx_SET (VOIDmode, temp[next], x));
03984308 1157
7eda7cda
RH
1158 offset_ld += next_amount;
1159 bytes -= next_amount;
1160 active[next] = true;
1161 }
03984308 1162
7eda7cda
RH
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]));
03984308 1169
7eda7cda
RH
1170 offset_st += amount[phase];
1171 }
03984308 1172 }
7eda7cda 1173 while (active[next]);
03984308 1174
7eda7cda 1175 return 1;
03984308
BW
1176}
1177
1178
1179void
ffbc8796 1180xtensa_expand_nonlocal_goto (rtx *operands)
03984308
BW
1181{
1182 rtx goto_handler = operands[1];
1183 rtx containing_fp = operands[3];
1184
3bbc2af6
KH
1185 /* Generate a call to "__xtensa_nonlocal_goto" (in libgcc); the code
1186 is too big to generate in-line. */
03984308
BW
1187
1188 if (GET_CODE (containing_fp) != REG)
1189 containing_fp = force_reg (Pmode, containing_fp);
1190
03984308
BW
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
e2500fed 1198static struct machine_function *
ffbc8796 1199xtensa_init_machine_status (void)
03984308 1200{
e2500fed 1201 return ggc_alloc_cleared (sizeof (struct machine_function));
03984308
BW
1202}
1203
1204
2a48b790
BW
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
03984308 1462void
ffbc8796 1463xtensa_setup_frame_addresses (void)
03984308 1464{
638db43e 1465 /* Set flag to cause FRAME_POINTER_REQUIRED to be set. */
03984308
BW
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
638db43e
BW
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
03984308 1476 label or a branch at the end of the loop then we need to place a nop
638db43e 1477 there. If the loop ends with a label we need the nop so that branches
839a4992
KH
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
638db43e 1480 the loop). If the loop ends with a branch, we need the nop in case the
839a4992 1481 branch is targeting a location inside the loop. When the branch
03984308
BW
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
638db43e 1485 when the branch is taken. */
03984308
BW
1486
1487void
ffbc8796 1488xtensa_emit_loop_end (rtx insn, rtx *operands)
03984308
BW
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:
0bd0703d 1501 output_asm_insn (TARGET_DENSITY ? "nop.n" : "nop", operands);
03984308
BW
1502 done = 1;
1503 break;
1504
1505 default:
1506 {
1507 rtx body = PATTERN (insn);
1508
1509 if (GET_CODE (body) == JUMP_INSN)
1510 {
0bd0703d 1511 output_asm_insn (TARGET_DENSITY ? "nop.n" : "nop", operands);
03984308
BW
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
036a2b7a
BW
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
03984308 1621char *
ffbc8796 1622xtensa_emit_call (int callop, rtx *operands)
03984308 1623{
b64a1b53 1624 static char result[64];
03984308
BW
1625 rtx tgt = operands[callop];
1626
1627 if (GET_CODE (tgt) == CONST_INT)
1d0ea52e 1628 sprintf (result, "call8\t0x%lx", INTVAL (tgt));
03984308
BW
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
da1f39e4
BW
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
b0c6e48f 1724/* Return the debugger register number to use for 'regno'. */
03984308
BW
1725
1726int
ffbc8796 1727xtensa_dbx_register_number (int regno)
03984308
BW
1728{
1729 int first = -1;
633e4eb4
BW
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;
b0c6e48f 1744 first = 48;
633e4eb4 1745 }
03984308
BW
1746 else if (ACC_REG_P (regno))
1747 {
b0c6e48f
BW
1748 first = 0x200; /* Start of Xtensa special registers. */
1749 regno = 16; /* ACCLO is special register 16. */
03984308
BW
1750 }
1751
1752 /* When optimizing, we sometimes get asked about pseudo-registers
638db43e 1753 that don't represent hard registers. Return 0 for these. */
03984308
BW
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
997b8b4d 1766init_cumulative_args (CUMULATIVE_ARGS *cum, int incoming)
03984308
BW
1767{
1768 cum->arg_words = 0;
997b8b4d 1769 cum->incoming = incoming;
03984308
BW
1770}
1771
ffbc8796 1772
03984308
BW
1773/* Advance the argument to the next argument position. */
1774
1775void
ffbc8796 1776function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type)
03984308
BW
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
85d91d5b
BW
1788 if (*arg_words < max
1789 && (targetm.calls.must_pass_in_stack (mode, type)
1790 || *arg_words + words > max))
03984308
BW
1791 *arg_words = max;
1792
1793 *arg_words += words;
1794}
1795
1796
1797/* Return an RTL expression containing the register for the given mode,
368ebcd6 1798 or 0 if the argument is to be passed on the stack. INCOMING_P is nonzero
ffbc8796 1799 if this is an incoming argument to the current function. */
03984308
BW
1800
1801rtx
ffbc8796
BW
1802function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1803 int incoming_p)
03984308
BW
1804{
1805 int regbase, words, max;
1806 int *arg_words;
1807 int regno;
03984308
BW
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))
822e895c 1818 {
d2348985 1819 int align = MIN (TYPE_ALIGN (type), STACK_BOUNDARY) / BITS_PER_WORD;
822e895c
BW
1820 *arg_words = (*arg_words + align - 1) & -align;
1821 }
03984308
BW
1822
1823 if (*arg_words + words > max)
1824 return (rtx)0;
1825
1826 regno = regbase + *arg_words;
03984308 1827
997b8b4d
BW
1828 if (cum->incoming && regno <= A7_REG && regno + words > A7_REG)
1829 cfun->machine->need_a7_copy = true;
03984308 1830
997b8b4d 1831 return gen_rtx_REG (mode, regno);
03984308
BW
1832}
1833
1834
d2348985
BW
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
6e5ff6e7 1849static bool
586de218 1850xtensa_return_in_msb (const_tree valtype)
6e5ff6e7
BW
1851{
1852 return (TARGET_BIG_ENDIAN
1853 && AGGREGATE_TYPE_P (valtype)
1854 && int_size_in_bytes (valtype) >= UNITS_PER_WORD);
1855}
1856
1857
03984308 1858void
ffbc8796 1859override_options (void)
03984308
BW
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
638db43e 1867 /* Set up array giving whether a given register can hold a given mode. */
03984308
BW
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))
f42f5a1b
BW
1880 temp = (TARGET_MAC16
1881 && (class == MODE_INT) && (size <= UNITS_PER_WORD));
03984308
BW
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;
03984308 1896
f42f5a1b
BW
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)
03984308 1910 flag_pic = 1;
87c8b4be
CT
1911
1912 /* Hot/cold partitioning does not work on this architecture, because of
1913 constant pools (the load instruction cannot necessarily reach that far).
1914 Therefore disable it on this architecture. */
1915 if (flag_reorder_blocks_and_partition)
1916 {
1917 flag_reorder_blocks_and_partition = 0;
1918 flag_reorder_blocks = 1;
1919 }
03984308
BW
1920}
1921
1922
1923/* A C compound statement to output to stdio stream STREAM the
1924 assembler syntax for an instruction operand X. X is an RTL
1925 expression.
1926
1927 CODE is a value that can be used to specify one of several ways
1928 of printing the operand. It is used when identical operands
1929 must be printed differently depending on the context. CODE
1930 comes from the '%' specification that was used to request
1931 printing of the operand. If the specification was just '%DIGIT'
1932 then CODE is 0; if the specification was '%LTR DIGIT' then CODE
1933 is the ASCII code for LTR.
1934
1935 If X is a register, this macro should print the register's name.
1936 The names can be found in an array 'reg_names' whose type is
1937 'char *[]'. 'reg_names' is initialized from 'REGISTER_NAMES'.
1938
1939 When the machine description has a specification '%PUNCT' (a '%'
1940 followed by a punctuation character), this macro is called with
1941 a null pointer for X and the punctuation character for CODE.
1942
1943 'a', 'c', 'l', and 'n' are reserved.
633e4eb4 1944
03984308
BW
1945 The Xtensa specific codes are:
1946
1947 'd' CONST_INT, print as signed decimal
1948 'x' CONST_INT, print as signed hexadecimal
1949 'K' CONST_INT, print number of bits in mask for EXTUI
1950 'R' CONST_INT, print (X & 0x1f)
1951 'L' CONST_INT, print ((32 - X) & 0x1f)
1952 'D' REG, print second register of double-word register operand
1953 'N' MEM, print address of next word following a memory operand
1954 'v' MEM, if memory reference is volatile, output a MEMW before it
f42f5a1b
BW
1955 't' any constant, add "@h" suffix for top 16 bits
1956 'b' any constant, add "@l" suffix for bottom 16 bits
03984308
BW
1957*/
1958
1959static void
ffbc8796 1960printx (FILE *file, signed int val)
03984308 1961{
ffbc8796 1962 /* Print a hexadecimal value in a nice way. */
03984308
BW
1963 if ((val > -0xa) && (val < 0xa))
1964 fprintf (file, "%d", val);
1965 else if (val < 0)
1966 fprintf (file, "-0x%x", -val);
1967 else
1968 fprintf (file, "0x%x", val);
1969}
1970
1971
1972void
ffbc8796 1973print_operand (FILE *file, rtx x, int letter)
03984308 1974{
f42f5a1b 1975 if (!x)
03984308
BW
1976 error ("PRINT_OPERAND null pointer");
1977
f42f5a1b 1978 switch (letter)
03984308 1979 {
f42f5a1b
BW
1980 case 'D':
1981 if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
1982 fprintf (file, "%s", reg_names[xt_true_regnum (x) + 1]);
1983 else
1984 output_operand_lossage ("invalid %%D value");
1985 break;
03984308 1986
f42f5a1b
BW
1987 case 'v':
1988 if (GET_CODE (x) == MEM)
1989 {
1990 /* For a volatile memory reference, emit a MEMW before the
1991 load or store. */
7a29f483 1992 if (MEM_VOLATILE_P (x))
f42f5a1b
BW
1993 fprintf (file, "memw\n\t");
1994 }
1995 else
1996 output_operand_lossage ("invalid %%v value");
1997 break;
03984308 1998
f42f5a1b
BW
1999 case 'N':
2000 if (GET_CODE (x) == MEM
2001 && (GET_MODE (x) == DFmode || GET_MODE (x) == DImode))
2002 {
2003 x = adjust_address (x, GET_MODE (x) == DFmode ? SFmode : SImode, 4);
2004 output_address (XEXP (x, 0));
2005 }
2006 else
2007 output_operand_lossage ("invalid %%N value");
2008 break;
03984308 2009
f42f5a1b
BW
2010 case 'K':
2011 if (GET_CODE (x) == CONST_INT)
03984308 2012 {
f42f5a1b
BW
2013 int num_bits = 0;
2014 unsigned val = INTVAL (x);
2015 while (val & 1)
2016 {
2017 num_bits += 1;
2018 val = val >> 1;
2019 }
2020 if ((val != 0) || (num_bits == 0) || (num_bits > 16))
2021 fatal_insn ("invalid mask", x);
03984308 2022
f42f5a1b
BW
2023 fprintf (file, "%d", num_bits);
2024 }
2025 else
2026 output_operand_lossage ("invalid %%K value");
2027 break;
03984308 2028
f42f5a1b
BW
2029 case 'L':
2030 if (GET_CODE (x) == CONST_INT)
2031 fprintf (file, "%ld", (32 - INTVAL (x)) & 0x1f);
2032 else
2033 output_operand_lossage ("invalid %%L value");
2034 break;
03984308 2035
f42f5a1b
BW
2036 case 'R':
2037 if (GET_CODE (x) == CONST_INT)
2038 fprintf (file, "%ld", INTVAL (x) & 0x1f);
2039 else
2040 output_operand_lossage ("invalid %%R value");
2041 break;
03984308 2042
f42f5a1b
BW
2043 case 'x':
2044 if (GET_CODE (x) == CONST_INT)
2045 printx (file, INTVAL (x));
2046 else
2047 output_operand_lossage ("invalid %%x value");
2048 break;
03984308 2049
f42f5a1b
BW
2050 case 'd':
2051 if (GET_CODE (x) == CONST_INT)
2052 fprintf (file, "%ld", INTVAL (x));
2053 else
2054 output_operand_lossage ("invalid %%d value");
2055 break;
03984308 2056
f42f5a1b
BW
2057 case 't':
2058 case 'b':
2059 if (GET_CODE (x) == CONST_INT)
2060 {
2061 printx (file, INTVAL (x));
2062 fputs (letter == 't' ? "@h" : "@l", file);
2063 }
2064 else if (GET_CODE (x) == CONST_DOUBLE)
2065 {
2066 REAL_VALUE_TYPE r;
2067 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2068 if (GET_MODE (x) == SFmode)
2069 {
2070 long l;
2071 REAL_VALUE_TO_TARGET_SINGLE (r, l);
2072 fprintf (file, "0x%08lx@%c", l, letter == 't' ? 'h' : 'l');
2073 }
2074 else
2075 output_operand_lossage ("invalid %%t/%%b value");
2076 }
2077 else if (GET_CODE (x) == CONST)
2078 {
2079 /* X must be a symbolic constant on ELF. Write an expression
2080 suitable for 'const16' that sets the high or low 16 bits. */
2081 if (GET_CODE (XEXP (x, 0)) != PLUS
2082 || (GET_CODE (XEXP (XEXP (x, 0), 0)) != SYMBOL_REF
2083 && GET_CODE (XEXP (XEXP (x, 0), 0)) != LABEL_REF)
2084 || GET_CODE (XEXP (XEXP (x, 0), 1)) != CONST_INT)
2085 output_operand_lossage ("invalid %%t/%%b value");
2086 print_operand (file, XEXP (XEXP (x, 0), 0), 0);
2087 fputs (letter == 't' ? "@h" : "@l", file);
2088 /* There must be a non-alphanumeric character between 'h' or 'l'
2089 and the number. The '-' is added by print_operand() already. */
2090 if (INTVAL (XEXP (XEXP (x, 0), 1)) >= 0)
2091 fputs ("+", file);
2092 print_operand (file, XEXP (XEXP (x, 0), 1), 0);
2093 }
2094 else
633e4eb4 2095 {
f42f5a1b
BW
2096 output_addr_const (file, x);
2097 fputs (letter == 't' ? "@h" : "@l", file);
03984308
BW
2098 }
2099 break;
2100
2101 default:
f42f5a1b
BW
2102 if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
2103 fprintf (file, "%s", reg_names[xt_true_regnum (x)]);
2104 else if (GET_CODE (x) == MEM)
2105 output_address (XEXP (x, 0));
2106 else if (GET_CODE (x) == CONST_INT)
2107 fprintf (file, "%ld", INTVAL (x));
2108 else
2109 output_addr_const (file, x);
03984308
BW
2110 }
2111}
2112
2113
2114/* A C compound statement to output to stdio stream STREAM the
2115 assembler syntax for an instruction operand that is a memory
fb49053f 2116 reference whose address is ADDR. ADDR is an RTL expression. */
03984308
BW
2117
2118void
ffbc8796 2119print_operand_address (FILE *file, rtx addr)
03984308
BW
2120{
2121 if (!addr)
2122 error ("PRINT_OPERAND_ADDRESS, null pointer");
2123
2124 switch (GET_CODE (addr))
2125 {
2126 default:
2127 fatal_insn ("invalid address", addr);
2128 break;
2129
2130 case REG:
2131 fprintf (file, "%s, 0", reg_names [REGNO (addr)]);
2132 break;
2133
2134 case PLUS:
2135 {
2136 rtx reg = (rtx)0;
2137 rtx offset = (rtx)0;
2138 rtx arg0 = XEXP (addr, 0);
2139 rtx arg1 = XEXP (addr, 1);
2140
2141 if (GET_CODE (arg0) == REG)
2142 {
2143 reg = arg0;
2144 offset = arg1;
2145 }
2146 else if (GET_CODE (arg1) == REG)
2147 {
2148 reg = arg1;
2149 offset = arg0;
2150 }
2151 else
2152 fatal_insn ("no register in address", addr);
2153
2154 if (CONSTANT_P (offset))
2155 {
2156 fprintf (file, "%s, ", reg_names [REGNO (reg)]);
2157 output_addr_const (file, offset);
2158 }
2159 else
2160 fatal_insn ("address offset not a constant", addr);
2161 }
2162 break;
2163
2164 case LABEL_REF:
2165 case SYMBOL_REF:
2166 case CONST_INT:
2167 case CONST:
2168 output_addr_const (file, addr);
2169 break;
2170 }
2171}
2172
2173
da1f39e4
BW
2174bool
2175xtensa_output_addr_const_extra (FILE *fp, rtx x)
2176{
2177 if (GET_CODE (x) == UNSPEC && XVECLEN (x, 0) == 1)
2178 {
2179 switch (XINT (x, 1))
2180 {
2181 case UNSPEC_PLT:
2182 if (flag_pic)
2183 {
2184 output_addr_const (fp, XVECEXP (x, 0, 0));
2185 fputs ("@PLT", fp);
2186 return true;
2187 }
2188 break;
2189 default:
2190 break;
2191 }
2192 }
2193 return false;
2194}
2195
2196
03984308 2197void
ffbc8796 2198xtensa_output_literal (FILE *file, rtx x, enum machine_mode mode, int labelno)
03984308
BW
2199{
2200 long value_long[2];
b216cd4a 2201 REAL_VALUE_TYPE r;
03984308 2202 int size;
74ed13f5 2203 rtx first, second;
03984308
BW
2204
2205 fprintf (file, "\t.literal .LC%u, ", (unsigned) labelno);
2206
2207 switch (GET_MODE_CLASS (mode))
2208 {
2209 case MODE_FLOAT:
177b6be0 2210 gcc_assert (GET_CODE (x) == CONST_DOUBLE);
03984308 2211
b216cd4a 2212 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
03984308
BW
2213 switch (mode)
2214 {
2215 case SFmode:
b216cd4a 2216 REAL_VALUE_TO_TARGET_SINGLE (r, value_long[0]);
4575a800
BW
2217 if (HOST_BITS_PER_LONG > 32)
2218 value_long[0] &= 0xffffffff;
b216cd4a 2219 fprintf (file, "0x%08lx\n", value_long[0]);
03984308
BW
2220 break;
2221
2222 case DFmode:
b216cd4a 2223 REAL_VALUE_TO_TARGET_DOUBLE (r, value_long);
4575a800
BW
2224 if (HOST_BITS_PER_LONG > 32)
2225 {
2226 value_long[0] &= 0xffffffff;
2227 value_long[1] &= 0xffffffff;
2228 }
b216cd4a
ZW
2229 fprintf (file, "0x%08lx, 0x%08lx\n",
2230 value_long[0], value_long[1]);
03984308
BW
2231 break;
2232
2233 default:
177b6be0 2234 gcc_unreachable ();
03984308
BW
2235 }
2236
2237 break;
2238
2239 case MODE_INT:
2240 case MODE_PARTIAL_INT:
2241 size = GET_MODE_SIZE (mode);
177b6be0 2242 switch (size)
03984308 2243 {
177b6be0 2244 case 4:
03984308
BW
2245 output_addr_const (file, x);
2246 fputs ("\n", file);
177b6be0
NS
2247 break;
2248
2249 case 8:
74ed13f5
BW
2250 split_double (x, &first, &second);
2251 output_addr_const (file, first);
03984308 2252 fputs (", ", file);
74ed13f5 2253 output_addr_const (file, second);
03984308 2254 fputs ("\n", file);
177b6be0
NS
2255 break;
2256
2257 default:
2258 gcc_unreachable ();
03984308 2259 }
03984308
BW
2260 break;
2261
2262 default:
177b6be0 2263 gcc_unreachable ();
03984308
BW
2264 }
2265}
2266
2267
2268/* Return the bytes needed to compute the frame pointer from the current
638db43e 2269 stack pointer. */
03984308
BW
2270
2271#define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
2272#define XTENSA_STACK_ALIGN(LOC) (((LOC) + STACK_BYTES-1) & ~(STACK_BYTES-1))
2273
2274long
ffbc8796 2275compute_frame_size (int size)
03984308 2276{
ffbc8796 2277 /* Add space for the incoming static chain value. */
6de9cd9a 2278 if (cfun->static_chain_decl != NULL)
03984308
BW
2279 size += (1 * UNITS_PER_WORD);
2280
2281 xtensa_current_frame_size =
2282 XTENSA_STACK_ALIGN (size
2283 + current_function_outgoing_args_size
2284 + (WINDOW_SIZE * UNITS_PER_WORD));
2285 return xtensa_current_frame_size;
2286}
2287
2288
2289int
ffbc8796 2290xtensa_frame_pointer_required (void)
03984308
BW
2291{
2292 /* The code to expand builtin_frame_addr and builtin_return_addr
2293 currently uses the hard_frame_pointer instead of frame_pointer.
2294 This seems wrong but maybe it's necessary for other architectures.
638db43e 2295 This function is derived from the i386 code. */
03984308
BW
2296
2297 if (cfun->machine->accesses_prev_frame)
2298 return 1;
2299
2300 return 0;
2301}
2302
2303
7f0ee694
BW
2304/* minimum frame = reg save area (4 words) plus static chain (1 word)
2305 and the total number of words must be a multiple of 128 bits. */
2306#define MIN_FRAME_SIZE (8 * UNITS_PER_WORD)
2307
f42f5a1b 2308void
ffbc8796 2309xtensa_expand_prologue (void)
f42f5a1b
BW
2310{
2311 HOST_WIDE_INT total_size;
2312 rtx size_rtx;
4e6c2193 2313 rtx insn, note_rtx;
18dbd950 2314
f42f5a1b
BW
2315 total_size = compute_frame_size (get_frame_size ());
2316 size_rtx = GEN_INT (total_size);
18dbd950 2317
f42f5a1b 2318 if (total_size < (1 << (12+3)))
35a3be48 2319 insn = emit_insn (gen_entry (size_rtx));
03984308
BW
2320 else
2321 {
f42f5a1b
BW
2322 /* Use a8 as a temporary since a0-a7 may be live. */
2323 rtx tmp_reg = gen_rtx_REG (Pmode, A8_REG);
35a3be48 2324 emit_insn (gen_entry (GEN_INT (MIN_FRAME_SIZE)));
f42f5a1b
BW
2325 emit_move_insn (tmp_reg, GEN_INT (total_size - MIN_FRAME_SIZE));
2326 emit_insn (gen_subsi3 (tmp_reg, stack_pointer_rtx, tmp_reg));
4e6c2193 2327 insn = emit_insn (gen_movsi (stack_pointer_rtx, tmp_reg));
03984308
BW
2328 }
2329
f42f5a1b 2330 if (frame_pointer_needed)
03984308 2331 {
997b8b4d 2332 if (cfun->machine->set_frame_ptr_insn)
03984308 2333 {
4e6c2193 2334 rtx first;
03984308 2335
997b8b4d
BW
2336 push_topmost_sequence ();
2337 first = get_insns ();
2338 pop_topmost_sequence ();
03984308 2339
f42f5a1b
BW
2340 /* For all instructions prior to set_frame_ptr_insn, replace
2341 hard_frame_pointer references with stack_pointer. */
2342 for (insn = first;
997b8b4d 2343 insn != cfun->machine->set_frame_ptr_insn;
f42f5a1b
BW
2344 insn = NEXT_INSN (insn))
2345 {
2346 if (INSN_P (insn))
20dca97b
BW
2347 {
2348 PATTERN (insn) = replace_rtx (copy_rtx (PATTERN (insn)),
2349 hard_frame_pointer_rtx,
2350 stack_pointer_rtx);
2351 df_insn_rescan (insn);
2352 }
f42f5a1b
BW
2353 }
2354 }
2355 else
4e6c2193
BW
2356 insn = emit_insn (gen_movsi (hard_frame_pointer_rtx,
2357 stack_pointer_rtx));
03984308 2358 }
4e6c2193
BW
2359
2360 /* Create a note to describe the CFA. Because this is only used to set
2361 DW_AT_frame_base for debug info, don't bother tracking changes through
2362 each instruction in the prologue. It just takes up space. */
2363 note_rtx = gen_rtx_SET (VOIDmode, (frame_pointer_needed
2364 ? hard_frame_pointer_rtx
2365 : stack_pointer_rtx),
2366 plus_constant (stack_pointer_rtx, -total_size));
2367 RTX_FRAME_RELATED_P (insn) = 1;
2368 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
2369 note_rtx, REG_NOTES (insn));
03984308
BW
2370}
2371
2372
f42f5a1b 2373/* Clear variables at function end. */
03984308
BW
2374
2375void
ffbc8796
BW
2376xtensa_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
2377 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
03984308 2378{
03984308
BW
2379 xtensa_current_frame_size = 0;
2380}
2381
2382
0c14a54d 2383rtx
ffbc8796 2384xtensa_return_addr (int count, rtx frame)
0c14a54d 2385{
7f0ee694 2386 rtx result, retaddr, curaddr, label;
0c14a54d
BW
2387
2388 if (count == -1)
f42f5a1b 2389 retaddr = gen_rtx_REG (Pmode, A0_REG);
0c14a54d
BW
2390 else
2391 {
2392 rtx addr = plus_constant (frame, -4 * UNITS_PER_WORD);
2393 addr = memory_address (Pmode, addr);
2394 retaddr = gen_reg_rtx (Pmode);
2395 emit_move_insn (retaddr, gen_rtx_MEM (Pmode, addr));
2396 }
2397
2398 /* The 2 most-significant bits of the return address on Xtensa hold
2399 the register window size. To get the real return address, these
7f0ee694
BW
2400 bits must be replaced with the high bits from some address in the
2401 code. */
2402
2403 /* Get the 2 high bits of a local label in the code. */
2404 curaddr = gen_reg_rtx (Pmode);
2405 label = gen_label_rtx ();
2406 emit_label (label);
2407 LABEL_PRESERVE_P (label) = 1;
2408 emit_move_insn (curaddr, gen_rtx_LABEL_REF (Pmode, label));
2409 emit_insn (gen_lshrsi3 (curaddr, curaddr, GEN_INT (30)));
2410 emit_insn (gen_ashlsi3 (curaddr, curaddr, GEN_INT (30)));
2411
2412 /* Clear the 2 high bits of the return address. */
0c14a54d 2413 result = gen_reg_rtx (Pmode);
7f0ee694
BW
2414 emit_insn (gen_ashlsi3 (result, retaddr, GEN_INT (2)));
2415 emit_insn (gen_lshrsi3 (result, result, GEN_INT (2)));
2416
2417 /* Combine them to get the result. */
2418 emit_insn (gen_iorsi3 (result, result, curaddr));
0c14a54d
BW
2419 return result;
2420}
2421
2422
03984308 2423/* Create the va_list data type.
822e895c
BW
2424
2425 This structure is set up by __builtin_saveregs. The __va_reg field
2426 points to a stack-allocated region holding the contents of the
2427 incoming argument registers. The __va_ndx field is an index
2428 initialized to the position of the first unnamed (variable)
2429 argument. This same index is also used to address the arguments
2430 passed in memory. Thus, the __va_stk field is initialized to point
2431 to the position of the first argument in memory offset to account
2432 for the arguments passed in registers and to account for the size
2433 of the argument registers not being 16-byte aligned. E.G., there
2434 are 6 argument registers of 4 bytes each, but we want the __va_ndx
2435 for the first stack argument to have the maximal alignment of 16
2436 bytes, so we offset the __va_stk address by 32 bytes so that
2437 __va_stk[32] references the first argument on the stack. */
03984308 2438
c35d187f
RH
2439static tree
2440xtensa_build_builtin_va_list (void)
03984308 2441{
540eaea8 2442 tree f_stk, f_reg, f_ndx, record, type_decl;
03984308 2443
540eaea8
BW
2444 record = (*lang_hooks.types.make_type) (RECORD_TYPE);
2445 type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
03984308
BW
2446
2447 f_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),
2448 ptr_type_node);
2449 f_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
2450 ptr_type_node);
2451 f_ndx = build_decl (FIELD_DECL, get_identifier ("__va_ndx"),
2452 integer_type_node);
2453
2454 DECL_FIELD_CONTEXT (f_stk) = record;
2455 DECL_FIELD_CONTEXT (f_reg) = record;
2456 DECL_FIELD_CONTEXT (f_ndx) = record;
2457
540eaea8
BW
2458 TREE_CHAIN (record) = type_decl;
2459 TYPE_NAME (record) = type_decl;
03984308
BW
2460 TYPE_FIELDS (record) = f_stk;
2461 TREE_CHAIN (f_stk) = f_reg;
2462 TREE_CHAIN (f_reg) = f_ndx;
2463
2464 layout_type (record);
2465 return record;
2466}
2467
2468
2469/* Save the incoming argument registers on the stack. Returns the
638db43e 2470 address of the saved registers. */
03984308 2471
4c45af42 2472static rtx
ffbc8796 2473xtensa_builtin_saveregs (void)
03984308 2474{
e70312d4 2475 rtx gp_regs;
79e9ebdc 2476 int arg_words = current_function_args_info.arg_words;
03984308 2477 int gp_left = MAX_ARGS_IN_REGISTERS - arg_words;
03984308 2478
997b8b4d 2479 if (gp_left <= 0)
03984308
BW
2480 return const0_rtx;
2481
3bbc2af6 2482 /* Allocate the general-purpose register space. */
03984308
BW
2483 gp_regs = assign_stack_local
2484 (BLKmode, MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD, -1);
540eaea8 2485 set_mem_alias_set (gp_regs, get_varargs_alias_set ());
03984308
BW
2486
2487 /* Now store the incoming registers. */
997b8b4d
BW
2488 cfun->machine->need_a7_copy = true;
2489 cfun->machine->vararg_a7 = true;
e70312d4
BW
2490 move_block_from_reg (GP_ARG_FIRST + arg_words,
2491 adjust_address (gp_regs, BLKmode,
2492 arg_words * UNITS_PER_WORD),
2493 gp_left);
0d8442b8
BW
2494 gcc_assert (cfun->machine->vararg_a7_copy != 0);
2495 emit_insn_before (cfun->machine->vararg_a7_copy, get_insns ());
03984308
BW
2496
2497 return XEXP (gp_regs, 0);
2498}
2499
2500
2501/* Implement `va_start' for varargs and stdarg. We look at the
638db43e 2502 current function to fill in an initial va_list. */
03984308 2503
d7bd8aeb 2504static void
ffbc8796 2505xtensa_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
03984308
BW
2506{
2507 tree f_stk, stk;
2508 tree f_reg, reg;
2509 tree f_ndx, ndx;
2510 tree t, u;
2511 int arg_words;
2512
2513 arg_words = current_function_args_info.arg_words;
2514
2515 f_stk = TYPE_FIELDS (va_list_type_node);
2516 f_reg = TREE_CHAIN (f_stk);
2517 f_ndx = TREE_CHAIN (f_reg);
2518
47a25a46
RG
2519 stk = build3 (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk, NULL_TREE);
2520 reg = build3 (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg, NULL_TREE);
2521 ndx = build3 (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx, NULL_TREE);
03984308
BW
2522
2523 /* Call __builtin_saveregs; save the result in __va_reg */
e70312d4
BW
2524 u = make_tree (sizetype, expand_builtin_saveregs ());
2525 u = fold_convert (ptr_type_node, u);
07beea0d 2526 t = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, reg, u);
03984308
BW
2527 TREE_SIDE_EFFECTS (t) = 1;
2528 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2529
822e895c 2530 /* Set the __va_stk member to ($arg_ptr - 32). */
03984308 2531 u = make_tree (ptr_type_node, virtual_incoming_args_rtx);
e70312d4 2532 u = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, u, size_int (-32));
07beea0d 2533 t = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, stk, u);
03984308
BW
2534 TREE_SIDE_EFFECTS (t) = 1;
2535 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2536
822e895c
BW
2537 /* Set the __va_ndx member. If the first variable argument is on
2538 the stack, adjust __va_ndx by 2 words to account for the extra
2539 alignment offset for __va_stk. */
2540 if (arg_words >= MAX_ARGS_IN_REGISTERS)
2541 arg_words += 2;
e70312d4
BW
2542 t = build2 (GIMPLE_MODIFY_STMT, integer_type_node, ndx,
2543 size_int (arg_words * UNITS_PER_WORD));
03984308
BW
2544 TREE_SIDE_EFFECTS (t) = 1;
2545 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2546}
2547
2548
2549/* Implement `va_arg'. */
2550
85d53c1d
RH
2551static tree
2552xtensa_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p,
2553 tree *post_p ATTRIBUTE_UNUSED)
03984308
BW
2554{
2555 tree f_stk, stk;
2556 tree f_reg, reg;
2557 tree f_ndx, ndx;
85d53c1d
RH
2558 tree type_size, array, orig_ndx, addr, size, va_size, t;
2559 tree lab_false, lab_over, lab_false2;
08b0dc1b
RH
2560 bool indirect;
2561
2562 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
2563 if (indirect)
2564 type = build_pointer_type (type);
03984308 2565
3712281f
BW
2566 /* Handle complex values as separate real and imaginary parts. */
2567 if (TREE_CODE (type) == COMPLEX_TYPE)
2568 {
85d53c1d 2569 tree real_part, imag_part;
3712281f 2570
85d53c1d
RH
2571 real_part = xtensa_gimplify_va_arg_expr (valist, TREE_TYPE (type),
2572 pre_p, NULL);
2573 real_part = get_initialized_tmp_var (real_part, pre_p, NULL);
3712281f 2574
85d53c1d
RH
2575 imag_part = xtensa_gimplify_va_arg_expr (valist, TREE_TYPE (type),
2576 pre_p, NULL);
2577 imag_part = get_initialized_tmp_var (imag_part, pre_p, NULL);
3712281f 2578
47a25a46 2579 return build2 (COMPLEX_EXPR, type, real_part, imag_part);
3712281f
BW
2580 }
2581
03984308
BW
2582 f_stk = TYPE_FIELDS (va_list_type_node);
2583 f_reg = TREE_CHAIN (f_stk);
2584 f_ndx = TREE_CHAIN (f_reg);
2585
47a25a46
RG
2586 stk = build3 (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk, NULL_TREE);
2587 reg = build3 (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg, NULL_TREE);
2588 ndx = build3 (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx, NULL_TREE);
03984308 2589
85d53c1d
RH
2590 type_size = size_in_bytes (type);
2591 va_size = round_up (type_size, UNITS_PER_WORD);
2592 gimplify_expr (&va_size, pre_p, NULL, is_gimple_val, fb_rvalue);
8be56275 2593
03984308 2594
822e895c 2595 /* First align __va_ndx if necessary for this arg:
03984308 2596
85d53c1d 2597 orig_ndx = (AP).__va_ndx;
822e895c 2598 if (__alignof__ (TYPE) > 4 )
85d53c1d 2599 orig_ndx = ((orig_ndx + __alignof__ (TYPE) - 1)
822e895c 2600 & -__alignof__ (TYPE)); */
03984308 2601
85d53c1d
RH
2602 orig_ndx = get_initialized_tmp_var (ndx, pre_p, NULL);
2603
03984308
BW
2604 if (TYPE_ALIGN (type) > BITS_PER_WORD)
2605 {
d2348985 2606 int align = MIN (TYPE_ALIGN (type), STACK_BOUNDARY) / BITS_PER_UNIT;
85d53c1d 2607
e70312d4
BW
2608 t = build2 (PLUS_EXPR, integer_type_node, orig_ndx, size_int (align - 1));
2609 t = build2 (BIT_AND_EXPR, integer_type_node, t, size_int (-align));
07beea0d 2610 t = build2 (GIMPLE_MODIFY_STMT, integer_type_node, orig_ndx, t);
85d53c1d 2611 gimplify_and_add (t, pre_p);
03984308
BW
2612 }
2613
2614
2615 /* Increment __va_ndx to point past the argument:
2616
85d53c1d 2617 (AP).__va_ndx = orig_ndx + __va_size (TYPE); */
03984308 2618
85d53c1d 2619 t = fold_convert (integer_type_node, va_size);
47a25a46 2620 t = build2 (PLUS_EXPR, integer_type_node, orig_ndx, t);
07beea0d 2621 t = build2 (GIMPLE_MODIFY_STMT, integer_type_node, ndx, t);
85d53c1d 2622 gimplify_and_add (t, pre_p);
03984308
BW
2623
2624
2625 /* Check if the argument is in registers:
2626
bcf88f9b 2627 if ((AP).__va_ndx <= __MAX_ARGS_IN_REGISTERS * 4
fe984136 2628 && !must_pass_in_stack (type))
ffbc8796 2629 __array = (AP).__va_reg; */
03984308 2630
85d53c1d 2631 array = create_tmp_var (ptr_type_node, NULL);
03984308 2632
85d53c1d 2633 lab_over = NULL;
fe984136 2634 if (!targetm.calls.must_pass_in_stack (TYPE_MODE (type), type))
bcf88f9b 2635 {
85d53c1d
RH
2636 lab_false = create_artificial_label ();
2637 lab_over = create_artificial_label ();
2638
e70312d4
BW
2639 t = build2 (GT_EXPR, boolean_type_node, ndx,
2640 size_int (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD));
47a25a46
RG
2641 t = build3 (COND_EXPR, void_type_node, t,
2642 build1 (GOTO_EXPR, void_type_node, lab_false),
2643 NULL_TREE);
85d53c1d
RH
2644 gimplify_and_add (t, pre_p);
2645
07beea0d 2646 t = build2 (GIMPLE_MODIFY_STMT, void_type_node, array, reg);
85d53c1d
RH
2647 gimplify_and_add (t, pre_p);
2648
47a25a46 2649 t = build1 (GOTO_EXPR, void_type_node, lab_over);
85d53c1d
RH
2650 gimplify_and_add (t, pre_p);
2651
47a25a46 2652 t = build1 (LABEL_EXPR, void_type_node, lab_false);
85d53c1d 2653 gimplify_and_add (t, pre_p);
bcf88f9b 2654 }
03984308 2655
85d53c1d 2656
03984308
BW
2657 /* ...otherwise, the argument is on the stack (never split between
2658 registers and the stack -- change __va_ndx if necessary):
2659
2660 else
2661 {
822e895c
BW
2662 if (orig_ndx <= __MAX_ARGS_IN_REGISTERS * 4)
2663 (AP).__va_ndx = 32 + __va_size (TYPE);
03984308 2664 __array = (AP).__va_stk;
ffbc8796 2665 } */
03984308 2666
85d53c1d 2667 lab_false2 = create_artificial_label ();
03984308 2668
e70312d4
BW
2669 t = build2 (GT_EXPR, boolean_type_node, orig_ndx,
2670 size_int (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD));
47a25a46
RG
2671 t = build3 (COND_EXPR, void_type_node, t,
2672 build1 (GOTO_EXPR, void_type_node, lab_false2),
2673 NULL_TREE);
85d53c1d 2674 gimplify_and_add (t, pre_p);
03984308 2675
85d53c1d
RH
2676 t = size_binop (PLUS_EXPR, va_size, size_int (32));
2677 t = fold_convert (integer_type_node, t);
07beea0d 2678 t = build2 (GIMPLE_MODIFY_STMT, integer_type_node, ndx, t);
85d53c1d 2679 gimplify_and_add (t, pre_p);
03984308 2680
47a25a46 2681 t = build1 (LABEL_EXPR, void_type_node, lab_false2);
85d53c1d 2682 gimplify_and_add (t, pre_p);
03984308 2683
07beea0d 2684 t = build2 (GIMPLE_MODIFY_STMT, void_type_node, array, stk);
85d53c1d
RH
2685 gimplify_and_add (t, pre_p);
2686
2687 if (lab_over)
2688 {
47a25a46 2689 t = build1 (LABEL_EXPR, void_type_node, lab_over);
85d53c1d
RH
2690 gimplify_and_add (t, pre_p);
2691 }
8be56275 2692
03984308
BW
2693
2694 /* Given the base array pointer (__array) and index to the subsequent
2695 argument (__va_ndx), find the address:
2696
8be56275
BW
2697 __array + (AP).__va_ndx - (BYTES_BIG_ENDIAN && sizeof (TYPE) < 4
2698 ? sizeof (TYPE)
2699 : __va_size (TYPE))
03984308
BW
2700
2701 The results are endian-dependent because values smaller than one word
ffbc8796 2702 are aligned differently. */
03984308 2703
633e4eb4 2704
85d91d5b 2705 if (BYTES_BIG_ENDIAN && TREE_CODE (type_size) == INTEGER_CST)
8be56275 2706 {
e70312d4
BW
2707 t = fold_build2 (GE_EXPR, boolean_type_node, type_size,
2708 size_int (PARM_BOUNDARY / BITS_PER_UNIT));
47a25a46 2709 t = fold_build3 (COND_EXPR, sizetype, t, va_size, type_size);
85d53c1d 2710 size = t;
8be56275 2711 }
85d53c1d
RH
2712 else
2713 size = va_size;
2714
e70312d4
BW
2715 t = build2 (MINUS_EXPR, sizetype, ndx, size);
2716 addr = build2 (POINTER_PLUS_EXPR, ptr_type_node, array, t);
03984308 2717
85d53c1d 2718 addr = fold_convert (build_pointer_type (type), addr);
08b0dc1b 2719 if (indirect)
d6e9821f
RH
2720 addr = build_va_arg_indirect_ref (addr);
2721 return build_va_arg_indirect_ref (addr);
03984308
BW
2722}
2723
2724
09fa8841
BW
2725/* Builtins. */
2726
2727enum xtensa_builtin
2728{
2729 XTENSA_BUILTIN_UMULSIDI3,
2730 XTENSA_BUILTIN_max
2731};
2732
2733
2734static void
2735xtensa_init_builtins (void)
2736{
2737 tree ftype;
2738
2739 ftype = build_function_type_list (unsigned_intDI_type_node,
2740 unsigned_intSI_type_node,
2741 unsigned_intSI_type_node, NULL_TREE);
2742
2743 add_builtin_function ("__builtin_umulsidi3", ftype,
2744 XTENSA_BUILTIN_UMULSIDI3, BUILT_IN_MD,
2745 "__umulsidi3", NULL_TREE);
2746}
2747
2748
2749static tree
2750xtensa_fold_builtin (tree fndecl, tree arglist, bool ignore ATTRIBUTE_UNUSED)
2751{
2752 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2753 tree arg0, arg1;
2754
2755 if (fcode == XTENSA_BUILTIN_UMULSIDI3)
2756 {
2757 arg0 = TREE_VALUE (arglist);
2758 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
2759 if ((TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
2760 || TARGET_MUL32_HIGH)
2761 return fold_build2 (MULT_EXPR, unsigned_intDI_type_node,
2762 fold_convert (unsigned_intDI_type_node, arg0),
2763 fold_convert (unsigned_intDI_type_node, arg1));
2764 else
2765 return NULL;
2766 }
2767
2768 internal_error ("bad builtin code");
2769 return NULL;
2770}
2771
2772
2773static rtx
2774xtensa_expand_builtin (tree exp, rtx target,
2775 rtx subtarget ATTRIBUTE_UNUSED,
2776 enum machine_mode mode ATTRIBUTE_UNUSED,
2777 int ignore)
2778{
ec3643e8 2779 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
09fa8841
BW
2780 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2781
2782 /* The umulsidi3 builtin is just a mechanism to avoid calling the real
2783 __umulsidi3 function when the Xtensa configuration can directly
2784 implement it. If not, just call the function. */
2785 if (fcode == XTENSA_BUILTIN_UMULSIDI3)
2786 return expand_call (exp, target, ignore);
2787
2788 internal_error ("bad builtin code");
2789 return NULL_RTX;
2790}
2791
2792
a8cacfd2 2793enum reg_class
ffbc8796 2794xtensa_preferred_reload_class (rtx x, enum reg_class class, int isoutput)
a8cacfd2 2795{
89f6025d 2796 if (!isoutput && CONSTANT_P (x) && GET_CODE (x) == CONST_DOUBLE)
a8cacfd2
BW
2797 return NO_REGS;
2798
89f6025d
BW
2799 /* Don't use the stack pointer or hard frame pointer for reloads!
2800 The hard frame pointer would normally be OK except that it may
2801 briefly hold an incoming argument in the prologue, and reload
2802 won't know that it is live because the hard frame pointer is
2803 treated specially. */
2804
2805 if (class == AR_REGS || class == GR_REGS)
2806 return RL_REGS;
a8cacfd2
BW
2807
2808 return class;
2809}
2810
2811
03984308 2812enum reg_class
ffbc8796
BW
2813xtensa_secondary_reload_class (enum reg_class class,
2814 enum machine_mode mode ATTRIBUTE_UNUSED,
2815 rtx x, int isoutput)
03984308
BW
2816{
2817 int regno;
2818
2819 if (GET_CODE (x) == SIGN_EXTEND)
2820 x = XEXP (x, 0);
2821 regno = xt_true_regnum (x);
2822
2823 if (!isoutput)
2824 {
2825 if (class == FP_REGS && constantpool_mem_p (x))
89f6025d 2826 return RL_REGS;
03984308
BW
2827 }
2828
2829 if (ACC_REG_P (regno))
89f6025d 2830 return ((class == GR_REGS || class == RL_REGS) ? NO_REGS : RL_REGS);
03984308 2831 if (class == ACC_REG)
89f6025d 2832 return (GP_REG_P (regno) ? NO_REGS : RL_REGS);
03984308
BW
2833
2834 return NO_REGS;
2835}
2836
2837
2838void
ffbc8796 2839order_regs_for_local_alloc (void)
03984308
BW
2840{
2841 if (!leaf_function_p ())
2842 {
2843 memcpy (reg_alloc_order, reg_nonleaf_alloc_order,
2844 FIRST_PSEUDO_REGISTER * sizeof (int));
2845 }
2846 else
2847 {
2848 int i, num_arg_regs;
2849 int nxt = 0;
2850
3bbc2af6
KH
2851 /* Use the AR registers in increasing order (skipping a0 and a1)
2852 but save the incoming argument registers for a last resort. */
03984308
BW
2853 num_arg_regs = current_function_args_info.arg_words;
2854 if (num_arg_regs > MAX_ARGS_IN_REGISTERS)
2855 num_arg_regs = MAX_ARGS_IN_REGISTERS;
2856 for (i = GP_ARG_FIRST; i < 16 - num_arg_regs; i++)
2857 reg_alloc_order[nxt++] = i + num_arg_regs;
2858 for (i = 0; i < num_arg_regs; i++)
2859 reg_alloc_order[nxt++] = GP_ARG_FIRST + i;
2860
3bbc2af6 2861 /* List the coprocessor registers in order. */
985d0d50
BW
2862 for (i = 0; i < BR_REG_NUM; i++)
2863 reg_alloc_order[nxt++] = BR_REG_FIRST + i;
2864
3bbc2af6 2865 /* List the FP registers in order for now. */
03984308
BW
2866 for (i = 0; i < 16; i++)
2867 reg_alloc_order[nxt++] = FP_REG_FIRST + i;
2868
638db43e 2869 /* GCC requires that we list *all* the registers.... */
03984308
BW
2870 reg_alloc_order[nxt++] = 0; /* a0 = return address */
2871 reg_alloc_order[nxt++] = 1; /* a1 = stack pointer */
2872 reg_alloc_order[nxt++] = 16; /* pseudo frame pointer */
2873 reg_alloc_order[nxt++] = 17; /* pseudo arg pointer */
2874
03984308
BW
2875 reg_alloc_order[nxt++] = ACC_REG_FIRST; /* MAC16 accumulator */
2876 }
2877}
2878
2879
01abf342
BW
2880/* Some Xtensa targets support multiple bss sections. If the section
2881 name ends with ".bss", add SECTION_BSS to the flags. */
2882
2883static unsigned int
ffbc8796 2884xtensa_multibss_section_type_flags (tree decl, const char *name, int reloc)
01abf342
BW
2885{
2886 unsigned int flags = default_section_type_flags (decl, name, reloc);
2887 const char *suffix;
2888
2889 suffix = strrchr (name, '.');
2890 if (suffix && strcmp (suffix, ".bss") == 0)
2891 {
2892 if (!decl || (TREE_CODE (decl) == VAR_DECL
2893 && DECL_INITIAL (decl) == NULL_TREE))
2894 flags |= SECTION_BSS; /* @nobits */
2895 else
d4ee4d25 2896 warning (0, "only uninitialized variables can be placed in a "
01abf342
BW
2897 ".bss section");
2898 }
2899
2900 return flags;
2901}
2902
2903
b64a1b53
RH
2904/* The literal pool stays with the function. */
2905
d6b5193b 2906static section *
ffbc8796
BW
2907xtensa_select_rtx_section (enum machine_mode mode ATTRIBUTE_UNUSED,
2908 rtx x ATTRIBUTE_UNUSED,
2909 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
b64a1b53 2910{
d6b5193b 2911 return function_section (current_function_decl);
b64a1b53 2912}
fb49053f 2913
ffbc8796 2914
3c50106f
RH
2915/* Compute a (partial) cost for rtx X. Return true if the complete
2916 cost has been computed, and false if subexpressions should be
2917 scanned. In either case, *TOTAL contains the cost result. */
2918
2919static bool
ffbc8796 2920xtensa_rtx_costs (rtx x, int code, int outer_code, int *total)
3c50106f
RH
2921{
2922 switch (code)
2923 {
2924 case CONST_INT:
2925 switch (outer_code)
2926 {
2927 case SET:
2928 if (xtensa_simm12b (INTVAL (x)))
2929 {
2930 *total = 4;
2931 return true;
2932 }
2933 break;
2934 case PLUS:
2935 if (xtensa_simm8 (INTVAL (x))
2936 || xtensa_simm8x256 (INTVAL (x)))
2937 {
2938 *total = 0;
2939 return true;
2940 }
2941 break;
2942 case AND:
2943 if (xtensa_mask_immediate (INTVAL (x)))
2944 {
2945 *total = 0;
2946 return true;
2947 }
2948 break;
2949 case COMPARE:
2950 if ((INTVAL (x) == 0) || xtensa_b4const (INTVAL (x)))
2951 {
2952 *total = 0;
2953 return true;
2954 }
2955 break;
2956 case ASHIFT:
2957 case ASHIFTRT:
2958 case LSHIFTRT:
2959 case ROTATE:
2960 case ROTATERT:
3bbc2af6 2961 /* No way to tell if X is the 2nd operand so be conservative. */
3c50106f
RH
2962 default: break;
2963 }
2964 if (xtensa_simm12b (INTVAL (x)))
2965 *total = 5;
f42f5a1b
BW
2966 else if (TARGET_CONST16)
2967 *total = COSTS_N_INSNS (2);
3c50106f
RH
2968 else
2969 *total = 6;
2970 return true;
2971
2972 case CONST:
2973 case LABEL_REF:
2974 case SYMBOL_REF:
f42f5a1b
BW
2975 if (TARGET_CONST16)
2976 *total = COSTS_N_INSNS (2);
2977 else
2978 *total = 5;
3c50106f
RH
2979 return true;
2980
2981 case CONST_DOUBLE:
f42f5a1b
BW
2982 if (TARGET_CONST16)
2983 *total = COSTS_N_INSNS (4);
2984 else
2985 *total = 7;
3c50106f
RH
2986 return true;
2987
2988 case MEM:
2989 {
2990 int num_words =
2991 (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD) ? 2 : 1;
2992
2993 if (memory_address_p (GET_MODE (x), XEXP ((x), 0)))
2994 *total = COSTS_N_INSNS (num_words);
2995 else
2996 *total = COSTS_N_INSNS (2*num_words);
2997 return true;
2998 }
2999
3000 case FFS:
09fa8841 3001 case CTZ:
3c50106f
RH
3002 *total = COSTS_N_INSNS (TARGET_NSA ? 5 : 50);
3003 return true;
3004
09fa8841
BW
3005 case CLZ:
3006 *total = COSTS_N_INSNS (TARGET_NSA ? 1 : 50);
3007 return true;
3008
3c50106f
RH
3009 case NOT:
3010 *total = COSTS_N_INSNS ((GET_MODE (x) == DImode) ? 3 : 2);
3011 return true;
3012
3013 case AND:
3014 case IOR:
3015 case XOR:
3016 if (GET_MODE (x) == DImode)
3017 *total = COSTS_N_INSNS (2);
3018 else
3019 *total = COSTS_N_INSNS (1);
3020 return true;
3021
3022 case ASHIFT:
3023 case ASHIFTRT:
3024 case LSHIFTRT:
3025 if (GET_MODE (x) == DImode)
3026 *total = COSTS_N_INSNS (50);
3027 else
3028 *total = COSTS_N_INSNS (1);
3029 return true;
3030
3031 case ABS:
3032 {
3033 enum machine_mode xmode = GET_MODE (x);
3034 if (xmode == SFmode)
3035 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
3036 else if (xmode == DFmode)
3037 *total = COSTS_N_INSNS (50);
3038 else
3039 *total = COSTS_N_INSNS (4);
3040 return true;
3041 }
3042
3043 case PLUS:
3044 case MINUS:
3045 {
3046 enum machine_mode xmode = GET_MODE (x);
3047 if (xmode == SFmode)
3048 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
3049 else if (xmode == DFmode || xmode == DImode)
3050 *total = COSTS_N_INSNS (50);
3051 else
3052 *total = COSTS_N_INSNS (1);
3053 return true;
3054 }
3055
3056 case NEG:
3057 *total = COSTS_N_INSNS ((GET_MODE (x) == DImode) ? 4 : 2);
3058 return true;
3059
3060 case MULT:
3061 {
3062 enum machine_mode xmode = GET_MODE (x);
3063 if (xmode == SFmode)
3064 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 4 : 50);
09fa8841 3065 else if (xmode == DFmode)
3c50106f 3066 *total = COSTS_N_INSNS (50);
09fa8841
BW
3067 else if (xmode == DImode)
3068 *total = COSTS_N_INSNS (TARGET_MUL32_HIGH ? 10 : 50);
3c50106f
RH
3069 else if (TARGET_MUL32)
3070 *total = COSTS_N_INSNS (4);
3071 else if (TARGET_MAC16)
3072 *total = COSTS_N_INSNS (16);
3073 else if (TARGET_MUL16)
3074 *total = COSTS_N_INSNS (12);
3075 else
3076 *total = COSTS_N_INSNS (50);
3077 return true;
3078 }
3079
3080 case DIV:
3081 case MOD:
3082 {
3083 enum machine_mode xmode = GET_MODE (x);
3084 if (xmode == SFmode)
3085 {
3086 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT_DIV ? 8 : 50);
3087 return true;
3088 }
3089 else if (xmode == DFmode)
3090 {
3091 *total = COSTS_N_INSNS (50);
3092 return true;
3093 }
3094 }
3bbc2af6 3095 /* Fall through. */
3c50106f
RH
3096
3097 case UDIV:
3098 case UMOD:
3099 {
3100 enum machine_mode xmode = GET_MODE (x);
3101 if (xmode == DImode)
3102 *total = COSTS_N_INSNS (50);
3103 else if (TARGET_DIV32)
3104 *total = COSTS_N_INSNS (32);
3105 else
3106 *total = COSTS_N_INSNS (50);
3107 return true;
3108 }
3109
3110 case SQRT:
3111 if (GET_MODE (x) == SFmode)
3112 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT_SQRT ? 8 : 50);
3113 else
3114 *total = COSTS_N_INSNS (50);
3115 return true;
3116
3117 case SMIN:
3118 case UMIN:
3119 case SMAX:
3120 case UMAX:
3121 *total = COSTS_N_INSNS (TARGET_MINMAX ? 1 : 50);
3122 return true;
3123
3124 case SIGN_EXTRACT:
3125 case SIGN_EXTEND:
3126 *total = COSTS_N_INSNS (TARGET_SEXT ? 1 : 2);
3127 return true;
3128
3129 case ZERO_EXTRACT:
3130 case ZERO_EXTEND:
3131 *total = COSTS_N_INSNS (1);
3132 return true;
3133
3134 default:
3135 return false;
3136 }
3137}
3138
bd5bd7ac
KH
3139/* Worker function for TARGET_RETURN_IN_MEMORY. */
3140
4c45af42 3141static bool
586de218 3142xtensa_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
4c45af42
KH
3143{
3144 return ((unsigned HOST_WIDE_INT) int_size_in_bytes (type)
3145 > 4 * UNITS_PER_WORD);
3146}
3147
7f0ee694
BW
3148
3149/* TRAMPOLINE_TEMPLATE: For Xtensa, the trampoline must perform an ENTRY
3150 instruction with a minimal stack frame in order to get some free
3151 registers. Once the actual call target is known, the proper stack frame
3152 size is extracted from the ENTRY instruction at the target and the
3153 current frame is adjusted to match. The trampoline then transfers
3154 control to the instruction following the ENTRY at the target. Note:
3155 this assumes that the target begins with an ENTRY instruction. */
3156
3157void
3158xtensa_trampoline_template (FILE *stream)
3159{
3160 bool use_call0 = (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS);
3161
3162 fprintf (stream, "\t.begin no-transform\n");
3163 fprintf (stream, "\tentry\tsp, %d\n", MIN_FRAME_SIZE);
3164
3165 if (use_call0)
3166 {
3167 /* Save the return address. */
3168 fprintf (stream, "\tmov\ta10, a0\n");
3169
3170 /* Use a CALL0 instruction to skip past the constants and in the
3171 process get the PC into A0. This allows PC-relative access to
3172 the constants without relying on L32R. */
3173 fprintf (stream, "\tcall0\t.Lskipconsts\n");
3174 }
3175 else
3176 fprintf (stream, "\tj\t.Lskipconsts\n");
3177
3178 fprintf (stream, "\t.align\t4\n");
3179 fprintf (stream, ".Lchainval:%s0\n", integer_asm_op (4, TRUE));
3180 fprintf (stream, ".Lfnaddr:%s0\n", integer_asm_op (4, TRUE));
3181 fprintf (stream, ".Lskipconsts:\n");
3182
3183 /* Load the static chain and function address from the trampoline. */
3184 if (use_call0)
3185 {
3186 fprintf (stream, "\taddi\ta0, a0, 3\n");
3187 fprintf (stream, "\tl32i\ta9, a0, 0\n");
3188 fprintf (stream, "\tl32i\ta8, a0, 4\n");
3189 }
3190 else
3191 {
3192 fprintf (stream, "\tl32r\ta9, .Lchainval\n");
3193 fprintf (stream, "\tl32r\ta8, .Lfnaddr\n");
3194 }
3195
3196 /* Store the static chain. */
3197 fprintf (stream, "\ts32i\ta9, sp, %d\n", MIN_FRAME_SIZE - 20);
3198
3199 /* Set the proper stack pointer value. */
3200 fprintf (stream, "\tl32i\ta9, a8, 0\n");
3201 fprintf (stream, "\textui\ta9, a9, %d, 12\n",
3202 TARGET_BIG_ENDIAN ? 8 : 12);
3203 fprintf (stream, "\tslli\ta9, a9, 3\n");
3204 fprintf (stream, "\taddi\ta9, a9, %d\n", -MIN_FRAME_SIZE);
3205 fprintf (stream, "\tsub\ta9, sp, a9\n");
3206 fprintf (stream, "\tmovsp\tsp, a9\n");
3207
3208 if (use_call0)
3209 /* Restore the return address. */
3210 fprintf (stream, "\tmov\ta0, a10\n");
3211
3212 /* Jump to the instruction following the ENTRY. */
3213 fprintf (stream, "\taddi\ta8, a8, 3\n");
3214 fprintf (stream, "\tjx\ta8\n");
3215
3216 /* Pad size to a multiple of TRAMPOLINE_ALIGNMENT. */
3217 if (use_call0)
3218 fprintf (stream, "\t.byte\t0\n");
3219 else
3220 fprintf (stream, "\tnop\n");
3221
3222 fprintf (stream, "\t.end no-transform\n");
3223}
3224
3225
3226void
3227xtensa_initialize_trampoline (rtx addr, rtx func, rtx chain)
3228{
3229 bool use_call0 = (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS);
3230 int chain_off = use_call0 ? 12 : 8;
3231 int func_off = use_call0 ? 16 : 12;
3232 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (addr, chain_off)), chain);
3233 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (addr, func_off)), func);
3234 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_sync_caches"),
3235 0, VOIDmode, 1, addr, Pmode);
3236}
3237
3238
e2500fed 3239#include "gt-xtensa.h"