]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/xtensa/xtensa.c
* config/xtensa/xtensa.md (tstsi): Delete
[thirdparty/gcc.git] / gcc / config / xtensa / xtensa.c
CommitLineData
f6b7ba2b 1/* Subroutines for insn-output.c for Tensilica's Xtensa architecture.
81c44390 2 Copyright 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
f6b7ba2b 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
dbddc6c4 19Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2002110-1301, USA. */
f6b7ba2b 21
22#include "config.h"
23#include "system.h"
805e22b2 24#include "coretypes.h"
25#include "tm.h"
f6b7ba2b 26#include "rtl.h"
27#include "regs.h"
f6b7ba2b 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"
160b2123 47#include "ggc.h"
f6b7ba2b 48#include "target.h"
49#include "target-def.h"
049d6666 50#include "langhooks.h"
ae79166b 51#include "tree-gimple.h"
52
f6b7ba2b 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
c821cf9c 56 of EQ, NE, etc. */
f6b7ba2b 57
fd63fcf8 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};
f6b7ba2b 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
a80259b6 87/* Largest block move to handle in-line. */
f6b7ba2b 88#define LARGEST_MOVE_RATIO 15
89
90/* Define the structure for the machine field in struct function. */
1f3233d1 91struct machine_function GTY(())
f6b7ba2b 92{
93 int accesses_prev_frame;
e060c9df 94 bool need_a7_copy;
95 bool vararg_a7;
96 rtx set_frame_ptr_insn;
f6b7ba2b 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
c821cf9c 101 treatment. */
f6b7ba2b 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{
a8332086 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,
f6b7ba2b 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
fd63fcf8 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);
fd63fcf8 200static struct machine_function * xtensa_init_machine_status (void);
110f993e 201static bool xtensa_return_in_msb (tree);
fd63fcf8 202static void printx (FILE *, signed int);
203static void xtensa_function_epilogue (FILE *, HOST_WIDE_INT);
4fe4af61 204static rtx xtensa_builtin_saveregs (void);
fd63fcf8 205static unsigned int xtensa_multibss_section_type_flags (tree, const char *,
206 int) ATTRIBUTE_UNUSED;
2f14b1f9 207static section *xtensa_select_rtx_section (enum machine_mode, rtx,
208 unsigned HOST_WIDE_INT);
fd63fcf8 209static bool xtensa_rtx_costs (rtx, int, int, int *);
2e15d750 210static tree xtensa_build_builtin_va_list (void);
4fe4af61 211static bool xtensa_return_in_memory (tree, tree);
ae79166b 212static tree xtensa_gimplify_va_arg_expr (tree, tree, tree *, tree *);
8e8c0c04 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);
bbfbe351 216
bbfbe351 217static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
218 REG_ALLOC_ORDER;
219\f
f6b7ba2b 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
bbfbe351 235#undef TARGET_ASM_SELECT_RTX_SECTION
236#define TARGET_ASM_SELECT_RTX_SECTION xtensa_select_rtx_section
f6b7ba2b 237
03ea9d8a 238#undef TARGET_DEFAULT_TARGET_FLAGS
239#define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | MASK_FUSED_MADD)
240
fab7adbf 241#undef TARGET_RTX_COSTS
242#define TARGET_RTX_COSTS xtensa_rtx_costs
ec0457a8 243#undef TARGET_ADDRESS_COST
244#define TARGET_ADDRESS_COST hook_int_rtx_0
fab7adbf 245
2e15d750 246#undef TARGET_BUILD_BUILTIN_VA_LIST
247#define TARGET_BUILD_BUILTIN_VA_LIST xtensa_build_builtin_va_list
248
4fe4af61 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
4fe4af61 256#undef TARGET_RETURN_IN_MEMORY
257#define TARGET_RETURN_IN_MEMORY xtensa_return_in_memory
92d40bc4 258#undef TARGET_SPLIT_COMPLEX_ARG
259#define TARGET_SPLIT_COMPLEX_ARG hook_bool_tree_true
0336f0f0 260#undef TARGET_MUST_PASS_IN_STACK
261#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
4fe4af61 262
263#undef TARGET_EXPAND_BUILTIN_SAVEREGS
264#define TARGET_EXPAND_BUILTIN_SAVEREGS xtensa_builtin_saveregs
ae79166b 265#undef TARGET_GIMPLIFY_VA_ARG_EXPR
266#define TARGET_GIMPLIFY_VA_ARG_EXPR xtensa_gimplify_va_arg_expr
4fe4af61 267
110f993e 268#undef TARGET_RETURN_IN_MSB
269#define TARGET_RETURN_IN_MSB xtensa_return_in_msb
270
8e8c0c04 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
bbfbe351 278struct gcc_target targetm = TARGET_INITIALIZER;
279\f
f6b7ba2b 280
281/*
282 * Functions to test Xtensa immediate operand validity.
283 */
284
7d0f7bf8 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)
f6b7ba2b 329{
330 switch (v)
331 {
7d0f7bf8 332 case -1:
333 case 1:
f6b7ba2b 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:
7d0f7bf8 348 return true;
f6b7ba2b 349 }
7d0f7bf8 350 return false;
f6b7ba2b 351}
352
f6b7ba2b 353
7d0f7bf8 354bool
355xtensa_b4const_or_zero (HOST_WIDE_INT v)
f6b7ba2b 356{
7d0f7bf8 357 if (v == 0)
358 return true;
359 return xtensa_b4const (v);
f6b7ba2b 360}
361
f6b7ba2b 362
7d0f7bf8 363bool
364xtensa_b4constu (HOST_WIDE_INT v)
f6b7ba2b 365{
366 switch (v)
367 {
7d0f7bf8 368 case 32768:
369 case 65536:
f6b7ba2b 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:
7d0f7bf8 384 return true;
f6b7ba2b 385 }
7d0f7bf8 386 return false;
f6b7ba2b 387}
388
f6b7ba2b 389
7d0f7bf8 390bool
391xtensa_mask_immediate (HOST_WIDE_INT v)
f6b7ba2b 392{
7d0f7bf8 393#define MAX_MASK_SIZE 16
394 int mask_size;
f6b7ba2b 395
7d0f7bf8 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 }
f6b7ba2b 404
7d0f7bf8 405 return false;
f6b7ba2b 406}
407
f6b7ba2b 408
7d0f7bf8 409bool
410xtensa_const_ok_for_letter_p (HOST_WIDE_INT v, int c)
f6b7ba2b 411{
7d0f7bf8 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;
f6b7ba2b 425}
426
427
428/* This is just like the standard true_regnum() function except that it
c821cf9c 429 works even when reg_renumber is not initialized. */
f6b7ba2b 430
431int
fd63fcf8 432xt_true_regnum (rtx x)
f6b7ba2b 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
f6b7ba2b 454int
fd63fcf8 455xtensa_valid_move (enum machine_mode mode, rtx *operands)
f6b7ba2b 456{
fc12fa10 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
c821cf9c 464 /* The stack pointer can only be assigned with a MOVSP opcode. */
fc12fa10 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 }
141e2ef6 473 if (register_operand (operands[1], mode))
fc12fa10 474 {
475 int src_regnum = xt_true_regnum (operands[1]);
476 if (!ACC_REG_P (src_regnum))
477 return true;
478 }
f6b7ba2b 479 return FALSE;
480}
481
482
f6b7ba2b 483int
fd63fcf8 484smalloffset_mem_p (rtx op)
f6b7ba2b 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);
7d0f7bf8 494 HOST_WIDE_INT val;
f6b7ba2b 495 if (GET_CODE (offset) != CONST_INT)
496 offset = XEXP (addr, 1);
497 if (GET_CODE (offset) != CONST_INT)
498 return FALSE;
7d0f7bf8 499
500 val = INTVAL (offset);
501 return (val & 3) == 0 && (val >= 0 && val <= 60);
f6b7ba2b 502 }
503 }
504 return FALSE;
505}
506
507
f6b7ba2b 508int
fd63fcf8 509constantpool_address_p (rtx addr)
f6b7ba2b 510{
511 rtx sym = addr;
512
513 if (GET_CODE (addr) == CONST)
514 {
515 rtx offset;
516
dafa59bd 517 /* Only handle (PLUS (SYM, OFFSET)) form. */
f6b7ba2b 518 addr = XEXP (addr, 0);
519 if (GET_CODE (addr) != PLUS)
520 return FALSE;
521
dafa59bd 522 /* Make sure the address is word aligned. */
f6b7ba2b 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
fd63fcf8 539constantpool_mem_p (rtx op)
f6b7ba2b 540{
541 if (GET_CODE (op) == MEM)
542 return constantpool_address_p (XEXP (op, 0));
543 return FALSE;
544}
545
546
f6b7ba2b 547void
fd63fcf8 548xtensa_extend_reg (rtx dst, rtx src)
f6b7ba2b 549{
550 rtx temp = gen_reg_rtx (SImode);
551 rtx shift = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (GET_MODE (src)));
552
dafa59bd 553 /* Generate paradoxical subregs as needed so that the modes match. */
f6b7ba2b 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
7d0f7bf8 562bool
fd63fcf8 563xtensa_mem_offset (unsigned v, enum machine_mode mode)
f6b7ba2b 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
c821cf9c 572 last piece requires a byte load/store. */
afb26b4b 573 return (xtensa_uimm8 (v)
574 && xtensa_uimm8 (v + MOVE_MAX * LARGEST_MOVE_RATIO));
f6b7ba2b 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
7d0f7bf8 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
fd63fcf8 613/* Make normal rtx_code into something we can index from an array. */
f6b7ba2b 614
615static enum internal_test
fd63fcf8 616map_test_to_internal_test (enum rtx_code test_code)
f6b7ba2b 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
c821cf9c 640 the comparison expression. */
f6b7ba2b 641
642static rtx
fd63fcf8 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 */)
f6b7ba2b 647{
fd63fcf8 648 struct cmp_info
649 {
f6b7ba2b 650 enum rtx_code test_code; /* test code to use in insn */
7d0f7bf8 651 bool (*const_range_p) (HOST_WIDE_INT); /* range check function */
f6b7ba2b 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
7d0f7bf8 661 { EQ, xtensa_b4const_or_zero, 0, 0, 0, 0, 0 }, /* EQ */
662 { NE, xtensa_b4const_or_zero, 0, 0, 0, 0, 0 }, /* NE */
f6b7ba2b 663
7d0f7bf8 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 */
f6b7ba2b 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);
cd3d4fe0 680 gcc_assert (test != ITEST_MAX);
f6b7ba2b 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
29bb088d 733 return gen_rtx_fmt_ee (p_info->test_code, VOIDmode, cmp0, cmp1);
f6b7ba2b 734}
735
736
737/* Generate the code to compare two float values. The return value is
c821cf9c 738 the comparison expression. */
f6b7ba2b 739
740static rtx
fd63fcf8 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 */)
f6b7ba2b 744{
fd63fcf8 745 rtx (*gen_fn) (rtx, rtx, rtx);
f6b7ba2b 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;
de071186 757 default:
29bb088d 758 fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1));
f6b7ba2b 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
29bb088d 772 return gen_rtx_fmt_ee (invert ? EQ : NE, VOIDmode, brtmp, const0_rtx);
f6b7ba2b 773}
774
775
776void
fd63fcf8 777xtensa_expand_conditional_branch (rtx *operands, enum rtx_code test_code)
f6b7ba2b 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:
29bb088d 790 fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1));
f6b7ba2b 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)
29bb088d 799 fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1));
f6b7ba2b 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
fd63fcf8 824gen_conditional_move (rtx cmp)
f6b7ba2b 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
c821cf9c 838 produce them. */
f6b7ba2b 839
840 if ((code == GT) && (op1 == constm1_rtx))
841 {
842 code = GE;
843 op1 = const0_rtx;
844 }
29bb088d 845 cmp = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
f6b7ba2b 846
847 if (boolean_operator (cmp, VOIDmode))
848 {
dafa59bd 849 /* Swap the operands to make const0 second. */
f6b7ba2b 850 if (op0 == const0_rtx)
851 {
852 op0 = op1;
853 op1 = const0_rtx;
854 }
855
dafa59bd 856 /* If not comparing against zero, emit a comparison (subtract). */
f6b7ba2b 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 {
dafa59bd 866 /* Swap the operands to make const0 second. */
f6b7ba2b 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;
cd3d4fe0 876 default: gcc_unreachable ();
f6b7ba2b 877 }
878 }
879
880 if (op1 != const0_rtx)
881 return 0;
882 }
883 else
884 return 0;
885
29bb088d 886 return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
f6b7ba2b 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
fd63fcf8 897xtensa_expand_conditional_move (rtx *operands, int isflt)
f6b7ba2b 898{
899 rtx cmp;
fd63fcf8 900 rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx);
f6b7ba2b 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
fd63fcf8 921xtensa_expand_scc (rtx *operands)
f6b7ba2b 922{
923 rtx dest = operands[0];
924 rtx cmp = operands[1];
925 rtx one_tmp, zero_tmp;
fd63fcf8 926 rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx);
f6b7ba2b 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
de071186 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
fd63fcf8 948xtensa_split_operand_pair (rtx operands[4], enum machine_mode mode)
de071186 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:
cd3d4fe0 968 gcc_unreachable ();
de071186 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:
cd3d4fe0 984 gcc_unreachable ();
de071186 985 }
986}
987
988
f6b7ba2b 989/* Emit insns to move operands[1] into operands[0].
f6b7ba2b 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
fd63fcf8 995xtensa_emit_move_sequence (rtx *operands, enum machine_mode mode)
f6b7ba2b 996{
997 if (CONSTANT_P (operands[1])
f6b7ba2b 998 && (GET_CODE (operands[1]) != CONST_INT
999 || !xtensa_simm12b (INTVAL (operands[1]))))
1000 {
afb26b4b 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 }
f6b7ba2b 1022 }
1023
e060c9df 1024 if (!(reload_in_progress | reload_completed)
1025 && !xtensa_valid_move (mode, operands))
1026 operands[1] = force_reg (mode, operands[1]);
f6b7ba2b 1027
e060c9df 1028 operands[1] = xtensa_copy_incoming_a7 (operands[1]);
f6b7ba2b 1029
1030 /* During reload we don't want to emit (subreg:X (mem:Y)) since that
c821cf9c 1031 instruction won't be recognized after reload, so we remove the
1032 subreg and adjust mem accordingly. */
f6b7ba2b 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
afb26b4b 1041
f6b7ba2b 1042static rtx
fd63fcf8 1043fixup_subreg_mem (rtx x)
f6b7ba2b 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
e060c9df 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. */
78d6a4ed 1076
e060c9df 1077rtx
1078xtensa_copy_incoming_a7 (rtx opnd)
78d6a4ed 1079{
e060c9df 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. */
cd3d4fe0 1088 gcc_assert (!cfun->machine->set_frame_ptr_insn);
e060c9df 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)
78d6a4ed 1096 {
cd3d4fe0 1097 gcc_assert (SUBREG_BYTE (reg) == 0);
e060c9df 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;
2aac53ce 1104
e060c9df 1105 /* 1-word args will always be in a7; 2-word args in a6/a7. */
cd3d4fe0 1106 gcc_assert (REGNO (reg) + HARD_REGNO_NREGS (A7_REG, mode) - 1 == A7_REG);
78d6a4ed 1107
e060c9df 1108 cfun->machine->need_a7_copy = false;
78d6a4ed 1109
e060c9df 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. */
78d6a4ed 1112
e060c9df 1113 push_to_sequence (entry_insns);
1114 tmp = gen_reg_rtx (mode);
78d6a4ed 1115
e060c9df 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:
cd3d4fe0 1138 gcc_unreachable ();
78d6a4ed 1139 }
1140
e060c9df 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;
78d6a4ed 1164}
1165
1166
a80259b6 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().
f6b7ba2b 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
fd63fcf8 1178xtensa_expand_block_move (rtx *operands)
f6b7ba2b 1179{
986ef67a 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;
f6b7ba2b 1188 int num_pieces, move_ratio;
986ef67a 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;
f6b7ba2b 1198
dafa59bd 1199 /* If this is not a fixed size move, just call memcpy. */
f6b7ba2b 1200 if (!optimize || (GET_CODE (operands[2]) != CONST_INT))
1201 return 0;
1202
986ef67a 1203 bytes = INTVAL (operands[2]);
1204 align = INTVAL (operands[3]);
1205
dafa59bd 1206 /* Anything to move? */
f6b7ba2b 1207 if (bytes <= 0)
986ef67a 1208 return 0;
f6b7ba2b 1209
1210 if (align > MOVE_MAX)
1211 align = MOVE_MAX;
1212
dafa59bd 1213 /* Decide whether to expand inline based on the optimization level. */
f6b7ba2b 1214 move_ratio = 4;
1215 if (optimize > 2)
1216 move_ratio = LARGEST_MOVE_RATIO;
dafa59bd 1217 num_pieces = (bytes / align) + (bytes % align); /* Close enough anyway. */
986ef67a 1218 if (num_pieces > move_ratio)
f6b7ba2b 1219 return 0;
1220
986ef67a 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 }
f6b7ba2b 1227
986ef67a 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 }
f6b7ba2b 1234
986ef67a 1235 active[0] = active[1] = false;
f6b7ba2b 1236
986ef67a 1237 do
f6b7ba2b 1238 {
986ef67a 1239 next = phase;
1240 phase ^= 1;
f6b7ba2b 1241
986ef67a 1242 if (bytes > 0)
f6b7ba2b 1243 {
986ef67a 1244 int next_amount;
f6b7ba2b 1245
986ef67a 1246 next_amount = (bytes >= 4 ? 4 : (bytes >= 2 ? 2 : 1));
1247 next_amount = MIN (next_amount, align);
f6b7ba2b 1248
986ef67a 1249 amount[next] = next_amount;
1250 mode[next] = mode_from_align[next_amount];
1251 temp[next] = gen_reg_rtx (mode[next]);
f6b7ba2b 1252
986ef67a 1253 x = adjust_address (src_mem, mode[next], offset_ld);
1254 emit_insn (gen_rtx_SET (VOIDmode, temp[next], x));
f6b7ba2b 1255
986ef67a 1256 offset_ld += next_amount;
1257 bytes -= next_amount;
1258 active[next] = true;
1259 }
f6b7ba2b 1260
986ef67a 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]));
f6b7ba2b 1267
986ef67a 1268 offset_st += amount[phase];
1269 }
f6b7ba2b 1270 }
986ef67a 1271 while (active[next]);
f6b7ba2b 1272
986ef67a 1273 return 1;
f6b7ba2b 1274}
1275
1276
1277void
fd63fcf8 1278xtensa_expand_nonlocal_goto (rtx *operands)
f6b7ba2b 1279{
1280 rtx goto_handler = operands[1];
1281 rtx containing_fp = operands[3];
1282
dafa59bd 1283 /* Generate a call to "__xtensa_nonlocal_goto" (in libgcc); the code
1284 is too big to generate in-line. */
f6b7ba2b 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
1f3233d1 1300static struct machine_function *
fd63fcf8 1301xtensa_init_machine_status (void)
f6b7ba2b 1302{
1f3233d1 1303 return ggc_alloc_cleared (sizeof (struct machine_function));
f6b7ba2b 1304}
1305
1306
1307void
fd63fcf8 1308xtensa_setup_frame_addresses (void)
f6b7ba2b 1309{
c821cf9c 1310 /* Set flag to cause FRAME_POINTER_REQUIRED to be set. */
f6b7ba2b 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
c821cf9c 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
f6b7ba2b 1321 label or a branch at the end of the loop then we need to place a nop
c821cf9c 1322 there. If the loop ends with a label we need the nop so that branches
efee20da 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
c821cf9c 1325 the loop). If the loop ends with a branch, we need the nop in case the
efee20da 1326 branch is targeting a location inside the loop. When the branch
f6b7ba2b 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
c821cf9c 1330 when the branch is taken. */
f6b7ba2b 1331
1332void
fd63fcf8 1333xtensa_emit_loop_end (rtx insn, rtx *operands)
f6b7ba2b 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:
2af1591e 1346 output_asm_insn (TARGET_DENSITY ? "nop.n" : "nop", operands);
f6b7ba2b 1347 done = 1;
1348 break;
1349
1350 default:
1351 {
1352 rtx body = PATTERN (insn);
1353
1354 if (GET_CODE (body) == JUMP_INSN)
1355 {
2af1591e 1356 output_asm_insn (TARGET_DENSITY ? "nop.n" : "nop", operands);
f6b7ba2b 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
1371char *
fd63fcf8 1372xtensa_emit_call (int callop, rtx *operands)
f6b7ba2b 1373{
bbfbe351 1374 static char result[64];
f6b7ba2b 1375 rtx tgt = operands[callop];
1376
1377 if (GET_CODE (tgt) == CONST_INT)
a6169f06 1378 sprintf (result, "call8\t0x%lx", INTVAL (tgt));
f6b7ba2b 1379 else if (register_operand (tgt, VOIDmode))
1380 sprintf (result, "callx8\t%%%d", callop);
1381 else
1382 sprintf (result, "call8\t%%%d", callop);
1383
1384 return result;
1385}
1386
1387
b68eeca9 1388/* Return the debugger register number to use for 'regno'. */
f6b7ba2b 1389
1390int
fd63fcf8 1391xtensa_dbx_register_number (int regno)
f6b7ba2b 1392{
1393 int first = -1;
de071186 1394
1395 if (GP_REG_P (regno))
1396 {
1397 regno -= GP_REG_FIRST;
1398 first = 0;
1399 }
1400 else if (BR_REG_P (regno))
1401 {
1402 regno -= BR_REG_FIRST;
1403 first = 16;
1404 }
1405 else if (FP_REG_P (regno))
1406 {
1407 regno -= FP_REG_FIRST;
b68eeca9 1408 first = 48;
de071186 1409 }
f6b7ba2b 1410 else if (ACC_REG_P (regno))
1411 {
b68eeca9 1412 first = 0x200; /* Start of Xtensa special registers. */
1413 regno = 16; /* ACCLO is special register 16. */
f6b7ba2b 1414 }
1415
1416 /* When optimizing, we sometimes get asked about pseudo-registers
c821cf9c 1417 that don't represent hard registers. Return 0 for these. */
f6b7ba2b 1418 if (first == -1)
1419 return 0;
1420
1421 return first + regno;
1422}
1423
1424
1425/* Argument support functions. */
1426
1427/* Initialize CUMULATIVE_ARGS for a function. */
1428
1429void
e060c9df 1430init_cumulative_args (CUMULATIVE_ARGS *cum, int incoming)
f6b7ba2b 1431{
1432 cum->arg_words = 0;
e060c9df 1433 cum->incoming = incoming;
f6b7ba2b 1434}
1435
fd63fcf8 1436
f6b7ba2b 1437/* Advance the argument to the next argument position. */
1438
1439void
fd63fcf8 1440function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type)
f6b7ba2b 1441{
1442 int words, max;
1443 int *arg_words;
1444
1445 arg_words = &cum->arg_words;
1446 max = MAX_ARGS_IN_REGISTERS;
1447
1448 words = (((mode != BLKmode)
1449 ? (int) GET_MODE_SIZE (mode)
1450 : int_size_in_bytes (type)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1451
ea2981b9 1452 if (*arg_words < max
1453 && (targetm.calls.must_pass_in_stack (mode, type)
1454 || *arg_words + words > max))
f6b7ba2b 1455 *arg_words = max;
1456
1457 *arg_words += words;
1458}
1459
1460
1461/* Return an RTL expression containing the register for the given mode,
751e10d1 1462 or 0 if the argument is to be passed on the stack. INCOMING_P is nonzero
fd63fcf8 1463 if this is an incoming argument to the current function. */
f6b7ba2b 1464
1465rtx
fd63fcf8 1466function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1467 int incoming_p)
f6b7ba2b 1468{
1469 int regbase, words, max;
1470 int *arg_words;
1471 int regno;
f6b7ba2b 1472
1473 arg_words = &cum->arg_words;
1474 regbase = (incoming_p ? GP_ARG_FIRST : GP_OUTGOING_ARG_FIRST);
1475 max = MAX_ARGS_IN_REGISTERS;
1476
1477 words = (((mode != BLKmode)
1478 ? (int) GET_MODE_SIZE (mode)
1479 : int_size_in_bytes (type)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1480
1481 if (type && (TYPE_ALIGN (type) > BITS_PER_WORD))
9276fdff 1482 {
81c44390 1483 int align = MIN (TYPE_ALIGN (type), STACK_BOUNDARY) / BITS_PER_WORD;
9276fdff 1484 *arg_words = (*arg_words + align - 1) & -align;
1485 }
f6b7ba2b 1486
1487 if (*arg_words + words > max)
1488 return (rtx)0;
1489
1490 regno = regbase + *arg_words;
f6b7ba2b 1491
e060c9df 1492 if (cum->incoming && regno <= A7_REG && regno + words > A7_REG)
1493 cfun->machine->need_a7_copy = true;
f6b7ba2b 1494
e060c9df 1495 return gen_rtx_REG (mode, regno);
f6b7ba2b 1496}
1497
1498
81c44390 1499int
1500function_arg_boundary (enum machine_mode mode, tree type)
1501{
1502 unsigned int alignment;
1503
1504 alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode);
1505 if (alignment < PARM_BOUNDARY)
1506 alignment = PARM_BOUNDARY;
1507 if (alignment > STACK_BOUNDARY)
1508 alignment = STACK_BOUNDARY;
1509 return alignment;
1510}
1511
1512
110f993e 1513static bool
1514xtensa_return_in_msb (tree valtype)
1515{
1516 return (TARGET_BIG_ENDIAN
1517 && AGGREGATE_TYPE_P (valtype)
1518 && int_size_in_bytes (valtype) >= UNITS_PER_WORD);
1519}
1520
1521
f6b7ba2b 1522void
fd63fcf8 1523override_options (void)
f6b7ba2b 1524{
1525 int regno;
1526 enum machine_mode mode;
1527
1528 if (!TARGET_BOOLEANS && TARGET_HARD_FLOAT)
1529 error ("boolean registers required for the floating-point option");
1530
f6b7ba2b 1531 xtensa_char_to_class['q'] = SP_REG;
1532 xtensa_char_to_class['a'] = GR_REGS;
1533 xtensa_char_to_class['b'] = ((TARGET_BOOLEANS) ? BR_REGS : NO_REGS);
1534 xtensa_char_to_class['f'] = ((TARGET_HARD_FLOAT) ? FP_REGS : NO_REGS);
1535 xtensa_char_to_class['A'] = ((TARGET_MAC16) ? ACC_REG : NO_REGS);
1536 xtensa_char_to_class['B'] = ((TARGET_SEXT) ? GR_REGS : NO_REGS);
1537 xtensa_char_to_class['C'] = ((TARGET_MUL16) ? GR_REGS: NO_REGS);
1538 xtensa_char_to_class['D'] = ((TARGET_DENSITY) ? GR_REGS: NO_REGS);
1539 xtensa_char_to_class['d'] = ((TARGET_DENSITY) ? AR_REGS: NO_REGS);
afb26b4b 1540 xtensa_char_to_class['W'] = ((TARGET_CONST16) ? GR_REGS: NO_REGS);
f6b7ba2b 1541
c821cf9c 1542 /* Set up array giving whether a given register can hold a given mode. */
f6b7ba2b 1543 for (mode = VOIDmode;
1544 mode != MAX_MACHINE_MODE;
1545 mode = (enum machine_mode) ((int) mode + 1))
1546 {
1547 int size = GET_MODE_SIZE (mode);
1548 enum mode_class class = GET_MODE_CLASS (mode);
1549
1550 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1551 {
1552 int temp;
1553
1554 if (ACC_REG_P (regno))
afb26b4b 1555 temp = (TARGET_MAC16
1556 && (class == MODE_INT) && (size <= UNITS_PER_WORD));
f6b7ba2b 1557 else if (GP_REG_P (regno))
1558 temp = ((regno & 1) == 0 || (size <= UNITS_PER_WORD));
1559 else if (FP_REG_P (regno))
1560 temp = (TARGET_HARD_FLOAT && (mode == SFmode));
1561 else if (BR_REG_P (regno))
1562 temp = (TARGET_BOOLEANS && (mode == CCmode));
1563 else
1564 temp = FALSE;
1565
1566 xtensa_hard_regno_mode_ok[(int) mode][regno] = temp;
1567 }
1568 }
1569
1570 init_machine_status = xtensa_init_machine_status;
f6b7ba2b 1571
afb26b4b 1572 /* Check PIC settings. PIC is only supported when using L32R
1573 instructions, and some targets need to always use PIC. */
1574 if (flag_pic && TARGET_CONST16)
1575 error ("-f%s is not supported with CONST16 instructions",
1576 (flag_pic > 1 ? "PIC" : "pic"));
1577 else if (XTENSA_ALWAYS_PIC)
1578 {
1579 if (TARGET_CONST16)
1580 error ("PIC is required but not supported with CONST16 instructions");
1581 flag_pic = 1;
1582 }
1583 /* There's no need for -fPIC (as opposed to -fpic) on Xtensa. */
1584 if (flag_pic > 1)
f6b7ba2b 1585 flag_pic = 1;
1897b881 1586
1587 /* Hot/cold partitioning does not work on this architecture, because of
1588 constant pools (the load instruction cannot necessarily reach that far).
1589 Therefore disable it on this architecture. */
1590 if (flag_reorder_blocks_and_partition)
1591 {
1592 flag_reorder_blocks_and_partition = 0;
1593 flag_reorder_blocks = 1;
1594 }
f6b7ba2b 1595}
1596
1597
1598/* A C compound statement to output to stdio stream STREAM the
1599 assembler syntax for an instruction operand X. X is an RTL
1600 expression.
1601
1602 CODE is a value that can be used to specify one of several ways
1603 of printing the operand. It is used when identical operands
1604 must be printed differently depending on the context. CODE
1605 comes from the '%' specification that was used to request
1606 printing of the operand. If the specification was just '%DIGIT'
1607 then CODE is 0; if the specification was '%LTR DIGIT' then CODE
1608 is the ASCII code for LTR.
1609
1610 If X is a register, this macro should print the register's name.
1611 The names can be found in an array 'reg_names' whose type is
1612 'char *[]'. 'reg_names' is initialized from 'REGISTER_NAMES'.
1613
1614 When the machine description has a specification '%PUNCT' (a '%'
1615 followed by a punctuation character), this macro is called with
1616 a null pointer for X and the punctuation character for CODE.
1617
1618 'a', 'c', 'l', and 'n' are reserved.
de071186 1619
f6b7ba2b 1620 The Xtensa specific codes are:
1621
1622 'd' CONST_INT, print as signed decimal
1623 'x' CONST_INT, print as signed hexadecimal
1624 'K' CONST_INT, print number of bits in mask for EXTUI
1625 'R' CONST_INT, print (X & 0x1f)
1626 'L' CONST_INT, print ((32 - X) & 0x1f)
1627 'D' REG, print second register of double-word register operand
1628 'N' MEM, print address of next word following a memory operand
1629 'v' MEM, if memory reference is volatile, output a MEMW before it
afb26b4b 1630 't' any constant, add "@h" suffix for top 16 bits
1631 'b' any constant, add "@l" suffix for bottom 16 bits
f6b7ba2b 1632*/
1633
1634static void
fd63fcf8 1635printx (FILE *file, signed int val)
f6b7ba2b 1636{
fd63fcf8 1637 /* Print a hexadecimal value in a nice way. */
f6b7ba2b 1638 if ((val > -0xa) && (val < 0xa))
1639 fprintf (file, "%d", val);
1640 else if (val < 0)
1641 fprintf (file, "-0x%x", -val);
1642 else
1643 fprintf (file, "0x%x", val);
1644}
1645
1646
1647void
fd63fcf8 1648print_operand (FILE *file, rtx x, int letter)
f6b7ba2b 1649{
afb26b4b 1650 if (!x)
f6b7ba2b 1651 error ("PRINT_OPERAND null pointer");
1652
afb26b4b 1653 switch (letter)
f6b7ba2b 1654 {
afb26b4b 1655 case 'D':
1656 if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
1657 fprintf (file, "%s", reg_names[xt_true_regnum (x) + 1]);
1658 else
1659 output_operand_lossage ("invalid %%D value");
1660 break;
f6b7ba2b 1661
afb26b4b 1662 case 'v':
1663 if (GET_CODE (x) == MEM)
1664 {
1665 /* For a volatile memory reference, emit a MEMW before the
1666 load or store. */
d8ad0757 1667 if (MEM_VOLATILE_P (x))
afb26b4b 1668 fprintf (file, "memw\n\t");
1669 }
1670 else
1671 output_operand_lossage ("invalid %%v value");
1672 break;
f6b7ba2b 1673
afb26b4b 1674 case 'N':
1675 if (GET_CODE (x) == MEM
1676 && (GET_MODE (x) == DFmode || GET_MODE (x) == DImode))
1677 {
1678 x = adjust_address (x, GET_MODE (x) == DFmode ? SFmode : SImode, 4);
1679 output_address (XEXP (x, 0));
1680 }
1681 else
1682 output_operand_lossage ("invalid %%N value");
1683 break;
f6b7ba2b 1684
afb26b4b 1685 case 'K':
1686 if (GET_CODE (x) == CONST_INT)
f6b7ba2b 1687 {
afb26b4b 1688 int num_bits = 0;
1689 unsigned val = INTVAL (x);
1690 while (val & 1)
1691 {
1692 num_bits += 1;
1693 val = val >> 1;
1694 }
1695 if ((val != 0) || (num_bits == 0) || (num_bits > 16))
1696 fatal_insn ("invalid mask", x);
f6b7ba2b 1697
afb26b4b 1698 fprintf (file, "%d", num_bits);
1699 }
1700 else
1701 output_operand_lossage ("invalid %%K value");
1702 break;
f6b7ba2b 1703
afb26b4b 1704 case 'L':
1705 if (GET_CODE (x) == CONST_INT)
1706 fprintf (file, "%ld", (32 - INTVAL (x)) & 0x1f);
1707 else
1708 output_operand_lossage ("invalid %%L value");
1709 break;
f6b7ba2b 1710
afb26b4b 1711 case 'R':
1712 if (GET_CODE (x) == CONST_INT)
1713 fprintf (file, "%ld", INTVAL (x) & 0x1f);
1714 else
1715 output_operand_lossage ("invalid %%R value");
1716 break;
f6b7ba2b 1717
afb26b4b 1718 case 'x':
1719 if (GET_CODE (x) == CONST_INT)
1720 printx (file, INTVAL (x));
1721 else
1722 output_operand_lossage ("invalid %%x value");
1723 break;
f6b7ba2b 1724
afb26b4b 1725 case 'd':
1726 if (GET_CODE (x) == CONST_INT)
1727 fprintf (file, "%ld", INTVAL (x));
1728 else
1729 output_operand_lossage ("invalid %%d value");
1730 break;
f6b7ba2b 1731
afb26b4b 1732 case 't':
1733 case 'b':
1734 if (GET_CODE (x) == CONST_INT)
1735 {
1736 printx (file, INTVAL (x));
1737 fputs (letter == 't' ? "@h" : "@l", file);
1738 }
1739 else if (GET_CODE (x) == CONST_DOUBLE)
1740 {
1741 REAL_VALUE_TYPE r;
1742 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1743 if (GET_MODE (x) == SFmode)
1744 {
1745 long l;
1746 REAL_VALUE_TO_TARGET_SINGLE (r, l);
1747 fprintf (file, "0x%08lx@%c", l, letter == 't' ? 'h' : 'l');
1748 }
1749 else
1750 output_operand_lossage ("invalid %%t/%%b value");
1751 }
1752 else if (GET_CODE (x) == CONST)
1753 {
1754 /* X must be a symbolic constant on ELF. Write an expression
1755 suitable for 'const16' that sets the high or low 16 bits. */
1756 if (GET_CODE (XEXP (x, 0)) != PLUS
1757 || (GET_CODE (XEXP (XEXP (x, 0), 0)) != SYMBOL_REF
1758 && GET_CODE (XEXP (XEXP (x, 0), 0)) != LABEL_REF)
1759 || GET_CODE (XEXP (XEXP (x, 0), 1)) != CONST_INT)
1760 output_operand_lossage ("invalid %%t/%%b value");
1761 print_operand (file, XEXP (XEXP (x, 0), 0), 0);
1762 fputs (letter == 't' ? "@h" : "@l", file);
1763 /* There must be a non-alphanumeric character between 'h' or 'l'
1764 and the number. The '-' is added by print_operand() already. */
1765 if (INTVAL (XEXP (XEXP (x, 0), 1)) >= 0)
1766 fputs ("+", file);
1767 print_operand (file, XEXP (XEXP (x, 0), 1), 0);
1768 }
1769 else
de071186 1770 {
afb26b4b 1771 output_addr_const (file, x);
1772 fputs (letter == 't' ? "@h" : "@l", file);
f6b7ba2b 1773 }
1774 break;
1775
1776 default:
afb26b4b 1777 if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
1778 fprintf (file, "%s", reg_names[xt_true_regnum (x)]);
1779 else if (GET_CODE (x) == MEM)
1780 output_address (XEXP (x, 0));
1781 else if (GET_CODE (x) == CONST_INT)
1782 fprintf (file, "%ld", INTVAL (x));
1783 else
1784 output_addr_const (file, x);
f6b7ba2b 1785 }
1786}
1787
1788
1789/* A C compound statement to output to stdio stream STREAM the
1790 assembler syntax for an instruction operand that is a memory
7811991d 1791 reference whose address is ADDR. ADDR is an RTL expression. */
f6b7ba2b 1792
1793void
fd63fcf8 1794print_operand_address (FILE *file, rtx addr)
f6b7ba2b 1795{
1796 if (!addr)
1797 error ("PRINT_OPERAND_ADDRESS, null pointer");
1798
1799 switch (GET_CODE (addr))
1800 {
1801 default:
1802 fatal_insn ("invalid address", addr);
1803 break;
1804
1805 case REG:
1806 fprintf (file, "%s, 0", reg_names [REGNO (addr)]);
1807 break;
1808
1809 case PLUS:
1810 {
1811 rtx reg = (rtx)0;
1812 rtx offset = (rtx)0;
1813 rtx arg0 = XEXP (addr, 0);
1814 rtx arg1 = XEXP (addr, 1);
1815
1816 if (GET_CODE (arg0) == REG)
1817 {
1818 reg = arg0;
1819 offset = arg1;
1820 }
1821 else if (GET_CODE (arg1) == REG)
1822 {
1823 reg = arg1;
1824 offset = arg0;
1825 }
1826 else
1827 fatal_insn ("no register in address", addr);
1828
1829 if (CONSTANT_P (offset))
1830 {
1831 fprintf (file, "%s, ", reg_names [REGNO (reg)]);
1832 output_addr_const (file, offset);
1833 }
1834 else
1835 fatal_insn ("address offset not a constant", addr);
1836 }
1837 break;
1838
1839 case LABEL_REF:
1840 case SYMBOL_REF:
1841 case CONST_INT:
1842 case CONST:
1843 output_addr_const (file, addr);
1844 break;
1845 }
1846}
1847
1848
f6b7ba2b 1849void
fd63fcf8 1850xtensa_output_literal (FILE *file, rtx x, enum machine_mode mode, int labelno)
f6b7ba2b 1851{
1852 long value_long[2];
badfe841 1853 REAL_VALUE_TYPE r;
f6b7ba2b 1854 int size;
1855
1856 fprintf (file, "\t.literal .LC%u, ", (unsigned) labelno);
1857
1858 switch (GET_MODE_CLASS (mode))
1859 {
1860 case MODE_FLOAT:
cd3d4fe0 1861 gcc_assert (GET_CODE (x) == CONST_DOUBLE);
f6b7ba2b 1862
badfe841 1863 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
f6b7ba2b 1864 switch (mode)
1865 {
1866 case SFmode:
badfe841 1867 REAL_VALUE_TO_TARGET_SINGLE (r, value_long[0]);
1868 fprintf (file, "0x%08lx\n", value_long[0]);
f6b7ba2b 1869 break;
1870
1871 case DFmode:
badfe841 1872 REAL_VALUE_TO_TARGET_DOUBLE (r, value_long);
1873 fprintf (file, "0x%08lx, 0x%08lx\n",
1874 value_long[0], value_long[1]);
f6b7ba2b 1875 break;
1876
1877 default:
cd3d4fe0 1878 gcc_unreachable ();
f6b7ba2b 1879 }
1880
1881 break;
1882
1883 case MODE_INT:
1884 case MODE_PARTIAL_INT:
1885 size = GET_MODE_SIZE (mode);
cd3d4fe0 1886 switch (size)
f6b7ba2b 1887 {
cd3d4fe0 1888 case 4:
f6b7ba2b 1889 output_addr_const (file, x);
1890 fputs ("\n", file);
cd3d4fe0 1891 break;
1892
1893 case 8:
f6b7ba2b 1894 output_addr_const (file, operand_subword (x, 0, 0, DImode));
1895 fputs (", ", file);
1896 output_addr_const (file, operand_subword (x, 1, 0, DImode));
1897 fputs ("\n", file);
cd3d4fe0 1898 break;
1899
1900 default:
1901 gcc_unreachable ();
f6b7ba2b 1902 }
f6b7ba2b 1903 break;
1904
1905 default:
cd3d4fe0 1906 gcc_unreachable ();
f6b7ba2b 1907 }
1908}
1909
1910
1911/* Return the bytes needed to compute the frame pointer from the current
c821cf9c 1912 stack pointer. */
f6b7ba2b 1913
1914#define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
1915#define XTENSA_STACK_ALIGN(LOC) (((LOC) + STACK_BYTES-1) & ~(STACK_BYTES-1))
1916
1917long
fd63fcf8 1918compute_frame_size (int size)
f6b7ba2b 1919{
fd63fcf8 1920 /* Add space for the incoming static chain value. */
4ee9c684 1921 if (cfun->static_chain_decl != NULL)
f6b7ba2b 1922 size += (1 * UNITS_PER_WORD);
1923
1924 xtensa_current_frame_size =
1925 XTENSA_STACK_ALIGN (size
1926 + current_function_outgoing_args_size
1927 + (WINDOW_SIZE * UNITS_PER_WORD));
1928 return xtensa_current_frame_size;
1929}
1930
1931
1932int
fd63fcf8 1933xtensa_frame_pointer_required (void)
f6b7ba2b 1934{
1935 /* The code to expand builtin_frame_addr and builtin_return_addr
1936 currently uses the hard_frame_pointer instead of frame_pointer.
1937 This seems wrong but maybe it's necessary for other architectures.
c821cf9c 1938 This function is derived from the i386 code. */
f6b7ba2b 1939
1940 if (cfun->machine->accesses_prev_frame)
1941 return 1;
1942
1943 return 0;
1944}
1945
1946
afb26b4b 1947void
fd63fcf8 1948xtensa_expand_prologue (void)
afb26b4b 1949{
1950 HOST_WIDE_INT total_size;
1951 rtx size_rtx;
2efea8c0 1952
afb26b4b 1953 total_size = compute_frame_size (get_frame_size ());
1954 size_rtx = GEN_INT (total_size);
2efea8c0 1955
afb26b4b 1956 if (total_size < (1 << (12+3)))
1957 emit_insn (gen_entry (size_rtx, size_rtx));
f6b7ba2b 1958 else
1959 {
afb26b4b 1960 /* Use a8 as a temporary since a0-a7 may be live. */
1961 rtx tmp_reg = gen_rtx_REG (Pmode, A8_REG);
1962 emit_insn (gen_entry (size_rtx, GEN_INT (MIN_FRAME_SIZE)));
1963 emit_move_insn (tmp_reg, GEN_INT (total_size - MIN_FRAME_SIZE));
1964 emit_insn (gen_subsi3 (tmp_reg, stack_pointer_rtx, tmp_reg));
1965 emit_move_insn (stack_pointer_rtx, tmp_reg);
f6b7ba2b 1966 }
1967
afb26b4b 1968 if (frame_pointer_needed)
f6b7ba2b 1969 {
e060c9df 1970 if (cfun->machine->set_frame_ptr_insn)
f6b7ba2b 1971 {
e060c9df 1972 rtx first, insn;
f6b7ba2b 1973
e060c9df 1974 push_topmost_sequence ();
1975 first = get_insns ();
1976 pop_topmost_sequence ();
f6b7ba2b 1977
afb26b4b 1978 /* For all instructions prior to set_frame_ptr_insn, replace
1979 hard_frame_pointer references with stack_pointer. */
1980 for (insn = first;
e060c9df 1981 insn != cfun->machine->set_frame_ptr_insn;
afb26b4b 1982 insn = NEXT_INSN (insn))
1983 {
1984 if (INSN_P (insn))
1985 PATTERN (insn) = replace_rtx (copy_rtx (PATTERN (insn)),
1986 hard_frame_pointer_rtx,
1987 stack_pointer_rtx);
1988 }
1989 }
1990 else
1991 emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
f6b7ba2b 1992 }
1993}
1994
1995
afb26b4b 1996/* Clear variables at function end. */
f6b7ba2b 1997
1998void
fd63fcf8 1999xtensa_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
2000 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
f6b7ba2b 2001{
f6b7ba2b 2002 xtensa_current_frame_size = 0;
2003}
2004
2005
43326cf7 2006rtx
fd63fcf8 2007xtensa_return_addr (int count, rtx frame)
43326cf7 2008{
2009 rtx result, retaddr;
2010
2011 if (count == -1)
afb26b4b 2012 retaddr = gen_rtx_REG (Pmode, A0_REG);
43326cf7 2013 else
2014 {
2015 rtx addr = plus_constant (frame, -4 * UNITS_PER_WORD);
2016 addr = memory_address (Pmode, addr);
2017 retaddr = gen_reg_rtx (Pmode);
2018 emit_move_insn (retaddr, gen_rtx_MEM (Pmode, addr));
2019 }
2020
2021 /* The 2 most-significant bits of the return address on Xtensa hold
2022 the register window size. To get the real return address, these
2023 bits must be replaced with the high bits from the current PC. */
2024
2025 result = gen_reg_rtx (Pmode);
2026 emit_insn (gen_fix_return_addr (result, retaddr));
2027 return result;
2028}
2029
2030
f6b7ba2b 2031/* Create the va_list data type.
9276fdff 2032
2033 This structure is set up by __builtin_saveregs. The __va_reg field
2034 points to a stack-allocated region holding the contents of the
2035 incoming argument registers. The __va_ndx field is an index
2036 initialized to the position of the first unnamed (variable)
2037 argument. This same index is also used to address the arguments
2038 passed in memory. Thus, the __va_stk field is initialized to point
2039 to the position of the first argument in memory offset to account
2040 for the arguments passed in registers and to account for the size
2041 of the argument registers not being 16-byte aligned. E.G., there
2042 are 6 argument registers of 4 bytes each, but we want the __va_ndx
2043 for the first stack argument to have the maximal alignment of 16
2044 bytes, so we offset the __va_stk address by 32 bytes so that
2045 __va_stk[32] references the first argument on the stack. */
f6b7ba2b 2046
2e15d750 2047static tree
2048xtensa_build_builtin_va_list (void)
f6b7ba2b 2049{
049d6666 2050 tree f_stk, f_reg, f_ndx, record, type_decl;
f6b7ba2b 2051
049d6666 2052 record = (*lang_hooks.types.make_type) (RECORD_TYPE);
2053 type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
f6b7ba2b 2054
2055 f_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),
2056 ptr_type_node);
2057 f_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
2058 ptr_type_node);
2059 f_ndx = build_decl (FIELD_DECL, get_identifier ("__va_ndx"),
2060 integer_type_node);
2061
2062 DECL_FIELD_CONTEXT (f_stk) = record;
2063 DECL_FIELD_CONTEXT (f_reg) = record;
2064 DECL_FIELD_CONTEXT (f_ndx) = record;
2065
049d6666 2066 TREE_CHAIN (record) = type_decl;
2067 TYPE_NAME (record) = type_decl;
f6b7ba2b 2068 TYPE_FIELDS (record) = f_stk;
2069 TREE_CHAIN (f_stk) = f_reg;
2070 TREE_CHAIN (f_reg) = f_ndx;
2071
2072 layout_type (record);
2073 return record;
2074}
2075
2076
2077/* Save the incoming argument registers on the stack. Returns the
c821cf9c 2078 address of the saved registers. */
f6b7ba2b 2079
4fe4af61 2080static rtx
fd63fcf8 2081xtensa_builtin_saveregs (void)
f6b7ba2b 2082{
2083 rtx gp_regs, dest;
bef77716 2084 int arg_words = current_function_args_info.arg_words;
f6b7ba2b 2085 int gp_left = MAX_ARGS_IN_REGISTERS - arg_words;
f6b7ba2b 2086
e060c9df 2087 if (gp_left <= 0)
f6b7ba2b 2088 return const0_rtx;
2089
dafa59bd 2090 /* Allocate the general-purpose register space. */
f6b7ba2b 2091 gp_regs = assign_stack_local
2092 (BLKmode, MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD, -1);
049d6666 2093 set_mem_alias_set (gp_regs, get_varargs_alias_set ());
f6b7ba2b 2094
2095 /* Now store the incoming registers. */
2096 dest = change_address (gp_regs, SImode,
2097 plus_constant (XEXP (gp_regs, 0),
2098 arg_words * UNITS_PER_WORD));
e060c9df 2099 cfun->machine->need_a7_copy = true;
2100 cfun->machine->vararg_a7 = true;
2101 move_block_from_reg (GP_ARG_FIRST + arg_words, dest, gp_left);
f6b7ba2b 2102
2103 return XEXP (gp_regs, 0);
2104}
2105
2106
2107/* Implement `va_start' for varargs and stdarg. We look at the
c821cf9c 2108 current function to fill in an initial va_list. */
f6b7ba2b 2109
2110void
fd63fcf8 2111xtensa_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
f6b7ba2b 2112{
2113 tree f_stk, stk;
2114 tree f_reg, reg;
2115 tree f_ndx, ndx;
2116 tree t, u;
2117 int arg_words;
2118
2119 arg_words = current_function_args_info.arg_words;
2120
2121 f_stk = TYPE_FIELDS (va_list_type_node);
2122 f_reg = TREE_CHAIN (f_stk);
2123 f_ndx = TREE_CHAIN (f_reg);
2124
ed03eadb 2125 stk = build3 (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk, NULL_TREE);
2126 reg = build3 (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg, NULL_TREE);
2127 ndx = build3 (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx, NULL_TREE);
f6b7ba2b 2128
2129 /* Call __builtin_saveregs; save the result in __va_reg */
f6b7ba2b 2130 u = make_tree (ptr_type_node, expand_builtin_saveregs ());
ed03eadb 2131 t = build2 (MODIFY_EXPR, ptr_type_node, reg, u);
f6b7ba2b 2132 TREE_SIDE_EFFECTS (t) = 1;
2133 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2134
9276fdff 2135 /* Set the __va_stk member to ($arg_ptr - 32). */
f6b7ba2b 2136 u = make_tree (ptr_type_node, virtual_incoming_args_rtx);
ed03eadb 2137 u = fold_build2 (PLUS_EXPR, ptr_type_node, u,
2138 build_int_cst (NULL_TREE, -32));
2139 t = build2 (MODIFY_EXPR, ptr_type_node, stk, u);
f6b7ba2b 2140 TREE_SIDE_EFFECTS (t) = 1;
2141 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2142
9276fdff 2143 /* Set the __va_ndx member. If the first variable argument is on
2144 the stack, adjust __va_ndx by 2 words to account for the extra
2145 alignment offset for __va_stk. */
2146 if (arg_words >= MAX_ARGS_IN_REGISTERS)
2147 arg_words += 2;
7016c612 2148 u = build_int_cst (NULL_TREE, arg_words * UNITS_PER_WORD);
ed03eadb 2149 t = build2 (MODIFY_EXPR, integer_type_node, ndx, u);
f6b7ba2b 2150 TREE_SIDE_EFFECTS (t) = 1;
2151 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2152}
2153
2154
2155/* Implement `va_arg'. */
2156
ae79166b 2157static tree
2158xtensa_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p,
2159 tree *post_p ATTRIBUTE_UNUSED)
f6b7ba2b 2160{
2161 tree f_stk, stk;
2162 tree f_reg, reg;
2163 tree f_ndx, ndx;
ae79166b 2164 tree type_size, array, orig_ndx, addr, size, va_size, t;
2165 tree lab_false, lab_over, lab_false2;
2cd7bb84 2166 bool indirect;
2167
2168 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
2169 if (indirect)
2170 type = build_pointer_type (type);
f6b7ba2b 2171
abeadffe 2172 /* Handle complex values as separate real and imaginary parts. */
2173 if (TREE_CODE (type) == COMPLEX_TYPE)
2174 {
ae79166b 2175 tree real_part, imag_part;
abeadffe 2176
ae79166b 2177 real_part = xtensa_gimplify_va_arg_expr (valist, TREE_TYPE (type),
2178 pre_p, NULL);
2179 real_part = get_initialized_tmp_var (real_part, pre_p, NULL);
abeadffe 2180
ae79166b 2181 imag_part = xtensa_gimplify_va_arg_expr (valist, TREE_TYPE (type),
2182 pre_p, NULL);
2183 imag_part = get_initialized_tmp_var (imag_part, pre_p, NULL);
abeadffe 2184
ed03eadb 2185 return build2 (COMPLEX_EXPR, type, real_part, imag_part);
abeadffe 2186 }
2187
f6b7ba2b 2188 f_stk = TYPE_FIELDS (va_list_type_node);
2189 f_reg = TREE_CHAIN (f_stk);
2190 f_ndx = TREE_CHAIN (f_reg);
2191
ed03eadb 2192 stk = build3 (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk, NULL_TREE);
2193 reg = build3 (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg, NULL_TREE);
2194 ndx = build3 (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx, NULL_TREE);
f6b7ba2b 2195
ae79166b 2196 type_size = size_in_bytes (type);
2197 va_size = round_up (type_size, UNITS_PER_WORD);
2198 gimplify_expr (&va_size, pre_p, NULL, is_gimple_val, fb_rvalue);
dd52a190 2199
f6b7ba2b 2200
9276fdff 2201 /* First align __va_ndx if necessary for this arg:
f6b7ba2b 2202
ae79166b 2203 orig_ndx = (AP).__va_ndx;
9276fdff 2204 if (__alignof__ (TYPE) > 4 )
ae79166b 2205 orig_ndx = ((orig_ndx + __alignof__ (TYPE) - 1)
9276fdff 2206 & -__alignof__ (TYPE)); */
f6b7ba2b 2207
ae79166b 2208 orig_ndx = get_initialized_tmp_var (ndx, pre_p, NULL);
2209
f6b7ba2b 2210 if (TYPE_ALIGN (type) > BITS_PER_WORD)
2211 {
81c44390 2212 int align = MIN (TYPE_ALIGN (type), STACK_BOUNDARY) / BITS_PER_UNIT;
ae79166b 2213
ed03eadb 2214 t = build2 (PLUS_EXPR, integer_type_node, orig_ndx,
2215 build_int_cst (NULL_TREE, align - 1));
2216 t = build2 (BIT_AND_EXPR, integer_type_node, t,
2217 build_int_cst (NULL_TREE, -align));
2218 t = build2 (MODIFY_EXPR, integer_type_node, orig_ndx, t);
ae79166b 2219 gimplify_and_add (t, pre_p);
f6b7ba2b 2220 }
2221
2222
2223 /* Increment __va_ndx to point past the argument:
2224
ae79166b 2225 (AP).__va_ndx = orig_ndx + __va_size (TYPE); */
f6b7ba2b 2226
ae79166b 2227 t = fold_convert (integer_type_node, va_size);
ed03eadb 2228 t = build2 (PLUS_EXPR, integer_type_node, orig_ndx, t);
2229 t = build2 (MODIFY_EXPR, integer_type_node, ndx, t);
ae79166b 2230 gimplify_and_add (t, pre_p);
f6b7ba2b 2231
2232
2233 /* Check if the argument is in registers:
2234
89d4bc5e 2235 if ((AP).__va_ndx <= __MAX_ARGS_IN_REGISTERS * 4
0336f0f0 2236 && !must_pass_in_stack (type))
fd63fcf8 2237 __array = (AP).__va_reg; */
f6b7ba2b 2238
ae79166b 2239 array = create_tmp_var (ptr_type_node, NULL);
f6b7ba2b 2240
ae79166b 2241 lab_over = NULL;
0336f0f0 2242 if (!targetm.calls.must_pass_in_stack (TYPE_MODE (type), type))
89d4bc5e 2243 {
ae79166b 2244 lab_false = create_artificial_label ();
2245 lab_over = create_artificial_label ();
2246
7016c612 2247 t = build_int_cst (NULL_TREE, MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD);
ed03eadb 2248 t = build2 (GT_EXPR, boolean_type_node, ndx, t);
2249 t = build3 (COND_EXPR, void_type_node, t,
2250 build1 (GOTO_EXPR, void_type_node, lab_false),
2251 NULL_TREE);
ae79166b 2252 gimplify_and_add (t, pre_p);
2253
ed03eadb 2254 t = build2 (MODIFY_EXPR, void_type_node, array, reg);
ae79166b 2255 gimplify_and_add (t, pre_p);
2256
ed03eadb 2257 t = build1 (GOTO_EXPR, void_type_node, lab_over);
ae79166b 2258 gimplify_and_add (t, pre_p);
2259
ed03eadb 2260 t = build1 (LABEL_EXPR, void_type_node, lab_false);
ae79166b 2261 gimplify_and_add (t, pre_p);
89d4bc5e 2262 }
f6b7ba2b 2263
ae79166b 2264
f6b7ba2b 2265 /* ...otherwise, the argument is on the stack (never split between
2266 registers and the stack -- change __va_ndx if necessary):
2267
2268 else
2269 {
9276fdff 2270 if (orig_ndx <= __MAX_ARGS_IN_REGISTERS * 4)
2271 (AP).__va_ndx = 32 + __va_size (TYPE);
f6b7ba2b 2272 __array = (AP).__va_stk;
fd63fcf8 2273 } */
f6b7ba2b 2274
ae79166b 2275 lab_false2 = create_artificial_label ();
f6b7ba2b 2276
7016c612 2277 t = build_int_cst (NULL_TREE, MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD);
ed03eadb 2278 t = build2 (GT_EXPR, boolean_type_node, orig_ndx, t);
2279 t = build3 (COND_EXPR, void_type_node, t,
2280 build1 (GOTO_EXPR, void_type_node, lab_false2),
2281 NULL_TREE);
ae79166b 2282 gimplify_and_add (t, pre_p);
f6b7ba2b 2283
ae79166b 2284 t = size_binop (PLUS_EXPR, va_size, size_int (32));
2285 t = fold_convert (integer_type_node, t);
ed03eadb 2286 t = build2 (MODIFY_EXPR, integer_type_node, ndx, t);
ae79166b 2287 gimplify_and_add (t, pre_p);
f6b7ba2b 2288
ed03eadb 2289 t = build1 (LABEL_EXPR, void_type_node, lab_false2);
ae79166b 2290 gimplify_and_add (t, pre_p);
f6b7ba2b 2291
ed03eadb 2292 t = build2 (MODIFY_EXPR, void_type_node, array, stk);
ae79166b 2293 gimplify_and_add (t, pre_p);
2294
2295 if (lab_over)
2296 {
ed03eadb 2297 t = build1 (LABEL_EXPR, void_type_node, lab_over);
ae79166b 2298 gimplify_and_add (t, pre_p);
2299 }
dd52a190 2300
f6b7ba2b 2301
2302 /* Given the base array pointer (__array) and index to the subsequent
2303 argument (__va_ndx), find the address:
2304
dd52a190 2305 __array + (AP).__va_ndx - (BYTES_BIG_ENDIAN && sizeof (TYPE) < 4
2306 ? sizeof (TYPE)
2307 : __va_size (TYPE))
f6b7ba2b 2308
2309 The results are endian-dependent because values smaller than one word
fd63fcf8 2310 are aligned differently. */
f6b7ba2b 2311
de071186 2312
ea2981b9 2313 if (BYTES_BIG_ENDIAN && TREE_CODE (type_size) == INTEGER_CST)
dd52a190 2314 {
ae79166b 2315 t = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
ed03eadb 2316 t = fold_build2 (GE_EXPR, boolean_type_node, type_size, t);
2317 t = fold_build3 (COND_EXPR, sizetype, t, va_size, type_size);
ae79166b 2318 size = t;
dd52a190 2319 }
ae79166b 2320 else
2321 size = va_size;
2322
2323 t = fold_convert (ptr_type_node, ndx);
ed03eadb 2324 addr = build2 (PLUS_EXPR, ptr_type_node, array, t);
ae79166b 2325 t = fold_convert (ptr_type_node, size);
ed03eadb 2326 addr = build2 (MINUS_EXPR, ptr_type_node, addr, t);
f6b7ba2b 2327
ae79166b 2328 addr = fold_convert (build_pointer_type (type), addr);
2cd7bb84 2329 if (indirect)
063f5fdd 2330 addr = build_va_arg_indirect_ref (addr);
2331 return build_va_arg_indirect_ref (addr);
f6b7ba2b 2332}
2333
2334
8e8c0c04 2335/* Builtins. */
2336
2337enum xtensa_builtin
2338{
2339 XTENSA_BUILTIN_UMULSIDI3,
2340 XTENSA_BUILTIN_max
2341};
2342
2343
2344static void
2345xtensa_init_builtins (void)
2346{
2347 tree ftype;
2348
2349 ftype = build_function_type_list (unsigned_intDI_type_node,
2350 unsigned_intSI_type_node,
2351 unsigned_intSI_type_node, NULL_TREE);
2352
2353 add_builtin_function ("__builtin_umulsidi3", ftype,
2354 XTENSA_BUILTIN_UMULSIDI3, BUILT_IN_MD,
2355 "__umulsidi3", NULL_TREE);
2356}
2357
2358
2359static tree
2360xtensa_fold_builtin (tree fndecl, tree arglist, bool ignore ATTRIBUTE_UNUSED)
2361{
2362 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2363 tree arg0, arg1;
2364
2365 if (fcode == XTENSA_BUILTIN_UMULSIDI3)
2366 {
2367 arg0 = TREE_VALUE (arglist);
2368 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
2369 if ((TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
2370 || TARGET_MUL32_HIGH)
2371 return fold_build2 (MULT_EXPR, unsigned_intDI_type_node,
2372 fold_convert (unsigned_intDI_type_node, arg0),
2373 fold_convert (unsigned_intDI_type_node, arg1));
2374 else
2375 return NULL;
2376 }
2377
2378 internal_error ("bad builtin code");
2379 return NULL;
2380}
2381
2382
2383static rtx
2384xtensa_expand_builtin (tree exp, rtx target,
2385 rtx subtarget ATTRIBUTE_UNUSED,
2386 enum machine_mode mode ATTRIBUTE_UNUSED,
2387 int ignore)
2388{
2389 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
2390 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2391
2392 /* The umulsidi3 builtin is just a mechanism to avoid calling the real
2393 __umulsidi3 function when the Xtensa configuration can directly
2394 implement it. If not, just call the function. */
2395 if (fcode == XTENSA_BUILTIN_UMULSIDI3)
2396 return expand_call (exp, target, ignore);
2397
2398 internal_error ("bad builtin code");
2399 return NULL_RTX;
2400}
2401
2402
fc12fa10 2403enum reg_class
fd63fcf8 2404xtensa_preferred_reload_class (rtx x, enum reg_class class, int isoutput)
fc12fa10 2405{
a8332086 2406 if (!isoutput && CONSTANT_P (x) && GET_CODE (x) == CONST_DOUBLE)
fc12fa10 2407 return NO_REGS;
2408
a8332086 2409 /* Don't use the stack pointer or hard frame pointer for reloads!
2410 The hard frame pointer would normally be OK except that it may
2411 briefly hold an incoming argument in the prologue, and reload
2412 won't know that it is live because the hard frame pointer is
2413 treated specially. */
2414
2415 if (class == AR_REGS || class == GR_REGS)
2416 return RL_REGS;
fc12fa10 2417
2418 return class;
2419}
2420
2421
f6b7ba2b 2422enum reg_class
fd63fcf8 2423xtensa_secondary_reload_class (enum reg_class class,
2424 enum machine_mode mode ATTRIBUTE_UNUSED,
2425 rtx x, int isoutput)
f6b7ba2b 2426{
2427 int regno;
2428
2429 if (GET_CODE (x) == SIGN_EXTEND)
2430 x = XEXP (x, 0);
2431 regno = xt_true_regnum (x);
2432
2433 if (!isoutput)
2434 {
2435 if (class == FP_REGS && constantpool_mem_p (x))
a8332086 2436 return RL_REGS;
f6b7ba2b 2437 }
2438
2439 if (ACC_REG_P (regno))
a8332086 2440 return ((class == GR_REGS || class == RL_REGS) ? NO_REGS : RL_REGS);
f6b7ba2b 2441 if (class == ACC_REG)
a8332086 2442 return (GP_REG_P (regno) ? NO_REGS : RL_REGS);
f6b7ba2b 2443
2444 return NO_REGS;
2445}
2446
2447
2448void
fd63fcf8 2449order_regs_for_local_alloc (void)
f6b7ba2b 2450{
2451 if (!leaf_function_p ())
2452 {
2453 memcpy (reg_alloc_order, reg_nonleaf_alloc_order,
2454 FIRST_PSEUDO_REGISTER * sizeof (int));
2455 }
2456 else
2457 {
2458 int i, num_arg_regs;
2459 int nxt = 0;
2460
dafa59bd 2461 /* Use the AR registers in increasing order (skipping a0 and a1)
2462 but save the incoming argument registers for a last resort. */
f6b7ba2b 2463 num_arg_regs = current_function_args_info.arg_words;
2464 if (num_arg_regs > MAX_ARGS_IN_REGISTERS)
2465 num_arg_regs = MAX_ARGS_IN_REGISTERS;
2466 for (i = GP_ARG_FIRST; i < 16 - num_arg_regs; i++)
2467 reg_alloc_order[nxt++] = i + num_arg_regs;
2468 for (i = 0; i < num_arg_regs; i++)
2469 reg_alloc_order[nxt++] = GP_ARG_FIRST + i;
2470
dafa59bd 2471 /* List the coprocessor registers in order. */
bef09eef 2472 for (i = 0; i < BR_REG_NUM; i++)
2473 reg_alloc_order[nxt++] = BR_REG_FIRST + i;
2474
dafa59bd 2475 /* List the FP registers in order for now. */
f6b7ba2b 2476 for (i = 0; i < 16; i++)
2477 reg_alloc_order[nxt++] = FP_REG_FIRST + i;
2478
c821cf9c 2479 /* GCC requires that we list *all* the registers.... */
f6b7ba2b 2480 reg_alloc_order[nxt++] = 0; /* a0 = return address */
2481 reg_alloc_order[nxt++] = 1; /* a1 = stack pointer */
2482 reg_alloc_order[nxt++] = 16; /* pseudo frame pointer */
2483 reg_alloc_order[nxt++] = 17; /* pseudo arg pointer */
2484
f6b7ba2b 2485 reg_alloc_order[nxt++] = ACC_REG_FIRST; /* MAC16 accumulator */
2486 }
2487}
2488
2489
5f4442bc 2490/* Some Xtensa targets support multiple bss sections. If the section
2491 name ends with ".bss", add SECTION_BSS to the flags. */
2492
2493static unsigned int
fd63fcf8 2494xtensa_multibss_section_type_flags (tree decl, const char *name, int reloc)
5f4442bc 2495{
2496 unsigned int flags = default_section_type_flags (decl, name, reloc);
2497 const char *suffix;
2498
2499 suffix = strrchr (name, '.');
2500 if (suffix && strcmp (suffix, ".bss") == 0)
2501 {
2502 if (!decl || (TREE_CODE (decl) == VAR_DECL
2503 && DECL_INITIAL (decl) == NULL_TREE))
2504 flags |= SECTION_BSS; /* @nobits */
2505 else
c3ceba8e 2506 warning (0, "only uninitialized variables can be placed in a "
5f4442bc 2507 ".bss section");
2508 }
2509
2510 return flags;
2511}
2512
2513
bbfbe351 2514/* The literal pool stays with the function. */
2515
2f14b1f9 2516static section *
fd63fcf8 2517xtensa_select_rtx_section (enum machine_mode mode ATTRIBUTE_UNUSED,
2518 rtx x ATTRIBUTE_UNUSED,
2519 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
bbfbe351 2520{
2f14b1f9 2521 return function_section (current_function_decl);
bbfbe351 2522}
7811991d 2523
fd63fcf8 2524
fab7adbf 2525/* Compute a (partial) cost for rtx X. Return true if the complete
2526 cost has been computed, and false if subexpressions should be
2527 scanned. In either case, *TOTAL contains the cost result. */
2528
2529static bool
fd63fcf8 2530xtensa_rtx_costs (rtx x, int code, int outer_code, int *total)
fab7adbf 2531{
2532 switch (code)
2533 {
2534 case CONST_INT:
2535 switch (outer_code)
2536 {
2537 case SET:
2538 if (xtensa_simm12b (INTVAL (x)))
2539 {
2540 *total = 4;
2541 return true;
2542 }
2543 break;
2544 case PLUS:
2545 if (xtensa_simm8 (INTVAL (x))
2546 || xtensa_simm8x256 (INTVAL (x)))
2547 {
2548 *total = 0;
2549 return true;
2550 }
2551 break;
2552 case AND:
2553 if (xtensa_mask_immediate (INTVAL (x)))
2554 {
2555 *total = 0;
2556 return true;
2557 }
2558 break;
2559 case COMPARE:
2560 if ((INTVAL (x) == 0) || xtensa_b4const (INTVAL (x)))
2561 {
2562 *total = 0;
2563 return true;
2564 }
2565 break;
2566 case ASHIFT:
2567 case ASHIFTRT:
2568 case LSHIFTRT:
2569 case ROTATE:
2570 case ROTATERT:
dafa59bd 2571 /* No way to tell if X is the 2nd operand so be conservative. */
fab7adbf 2572 default: break;
2573 }
2574 if (xtensa_simm12b (INTVAL (x)))
2575 *total = 5;
afb26b4b 2576 else if (TARGET_CONST16)
2577 *total = COSTS_N_INSNS (2);
fab7adbf 2578 else
2579 *total = 6;
2580 return true;
2581
2582 case CONST:
2583 case LABEL_REF:
2584 case SYMBOL_REF:
afb26b4b 2585 if (TARGET_CONST16)
2586 *total = COSTS_N_INSNS (2);
2587 else
2588 *total = 5;
fab7adbf 2589 return true;
2590
2591 case CONST_DOUBLE:
afb26b4b 2592 if (TARGET_CONST16)
2593 *total = COSTS_N_INSNS (4);
2594 else
2595 *total = 7;
fab7adbf 2596 return true;
2597
2598 case MEM:
2599 {
2600 int num_words =
2601 (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD) ? 2 : 1;
2602
2603 if (memory_address_p (GET_MODE (x), XEXP ((x), 0)))
2604 *total = COSTS_N_INSNS (num_words);
2605 else
2606 *total = COSTS_N_INSNS (2*num_words);
2607 return true;
2608 }
2609
2610 case FFS:
8e8c0c04 2611 case CTZ:
fab7adbf 2612 *total = COSTS_N_INSNS (TARGET_NSA ? 5 : 50);
2613 return true;
2614
8e8c0c04 2615 case CLZ:
2616 *total = COSTS_N_INSNS (TARGET_NSA ? 1 : 50);
2617 return true;
2618
fab7adbf 2619 case NOT:
2620 *total = COSTS_N_INSNS ((GET_MODE (x) == DImode) ? 3 : 2);
2621 return true;
2622
2623 case AND:
2624 case IOR:
2625 case XOR:
2626 if (GET_MODE (x) == DImode)
2627 *total = COSTS_N_INSNS (2);
2628 else
2629 *total = COSTS_N_INSNS (1);
2630 return true;
2631
2632 case ASHIFT:
2633 case ASHIFTRT:
2634 case LSHIFTRT:
2635 if (GET_MODE (x) == DImode)
2636 *total = COSTS_N_INSNS (50);
2637 else
2638 *total = COSTS_N_INSNS (1);
2639 return true;
2640
2641 case ABS:
2642 {
2643 enum machine_mode xmode = GET_MODE (x);
2644 if (xmode == SFmode)
2645 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
2646 else if (xmode == DFmode)
2647 *total = COSTS_N_INSNS (50);
2648 else
2649 *total = COSTS_N_INSNS (4);
2650 return true;
2651 }
2652
2653 case PLUS:
2654 case MINUS:
2655 {
2656 enum machine_mode xmode = GET_MODE (x);
2657 if (xmode == SFmode)
2658 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
2659 else if (xmode == DFmode || xmode == DImode)
2660 *total = COSTS_N_INSNS (50);
2661 else
2662 *total = COSTS_N_INSNS (1);
2663 return true;
2664 }
2665
2666 case NEG:
2667 *total = COSTS_N_INSNS ((GET_MODE (x) == DImode) ? 4 : 2);
2668 return true;
2669
2670 case MULT:
2671 {
2672 enum machine_mode xmode = GET_MODE (x);
2673 if (xmode == SFmode)
2674 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 4 : 50);
8e8c0c04 2675 else if (xmode == DFmode)
fab7adbf 2676 *total = COSTS_N_INSNS (50);
8e8c0c04 2677 else if (xmode == DImode)
2678 *total = COSTS_N_INSNS (TARGET_MUL32_HIGH ? 10 : 50);
fab7adbf 2679 else if (TARGET_MUL32)
2680 *total = COSTS_N_INSNS (4);
2681 else if (TARGET_MAC16)
2682 *total = COSTS_N_INSNS (16);
2683 else if (TARGET_MUL16)
2684 *total = COSTS_N_INSNS (12);
2685 else
2686 *total = COSTS_N_INSNS (50);
2687 return true;
2688 }
2689
2690 case DIV:
2691 case MOD:
2692 {
2693 enum machine_mode xmode = GET_MODE (x);
2694 if (xmode == SFmode)
2695 {
2696 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT_DIV ? 8 : 50);
2697 return true;
2698 }
2699 else if (xmode == DFmode)
2700 {
2701 *total = COSTS_N_INSNS (50);
2702 return true;
2703 }
2704 }
dafa59bd 2705 /* Fall through. */
fab7adbf 2706
2707 case UDIV:
2708 case UMOD:
2709 {
2710 enum machine_mode xmode = GET_MODE (x);
2711 if (xmode == DImode)
2712 *total = COSTS_N_INSNS (50);
2713 else if (TARGET_DIV32)
2714 *total = COSTS_N_INSNS (32);
2715 else
2716 *total = COSTS_N_INSNS (50);
2717 return true;
2718 }
2719
2720 case SQRT:
2721 if (GET_MODE (x) == SFmode)
2722 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT_SQRT ? 8 : 50);
2723 else
2724 *total = COSTS_N_INSNS (50);
2725 return true;
2726
2727 case SMIN:
2728 case UMIN:
2729 case SMAX:
2730 case UMAX:
2731 *total = COSTS_N_INSNS (TARGET_MINMAX ? 1 : 50);
2732 return true;
2733
2734 case SIGN_EXTRACT:
2735 case SIGN_EXTEND:
2736 *total = COSTS_N_INSNS (TARGET_SEXT ? 1 : 2);
2737 return true;
2738
2739 case ZERO_EXTRACT:
2740 case ZERO_EXTEND:
2741 *total = COSTS_N_INSNS (1);
2742 return true;
2743
2744 default:
2745 return false;
2746 }
2747}
2748
6644435d 2749/* Worker function for TARGET_RETURN_IN_MEMORY. */
2750
4fe4af61 2751static bool
2752xtensa_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
2753{
2754 return ((unsigned HOST_WIDE_INT) int_size_in_bytes (type)
2755 > 4 * UNITS_PER_WORD);
2756}
2757
1f3233d1 2758#include "gt-xtensa.h"