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