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