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