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