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