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