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