* rtl.h (rtunion_def): Constify member `rtstr'.
[official-gcc.git] / gcc / config / arm / thumb.c
blob79de0b6ca2dd554bbf9fdec9205d6e7b4b1ce155
1 /* Output routines for GCC for ARM/Thumb
2 Copyright (C) 1996, 2000 Cygnus Software Technologies Ltd
3 The basis of this contribution was generated by
4 Richard Earnshaw, Advanced RISC Machines Ltd
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 #include "config.h"
24 #include "system.h"
25 #include "rtl.h"
26 #include "hard-reg-set.h"
27 #include "regs.h"
28 #include "output.h"
29 #include "insn-flags.h"
30 #include "insn-attr.h"
31 #include "flags.h"
32 #include "tree.h"
33 #include "function.h"
34 #include "expr.h"
35 #include "insn-config.h"
36 #include "recog.h"
37 #include "toplev.h"
38 #include "thumb-protos.h"
41 int current_function_anonymous_args = 0;
43 /* Used to parse -mstructure_size_boundary command line option. */
44 const char * structure_size_string = NULL;
45 int arm_structure_size_boundary = 32; /* Used to be 8 */
47 /* The register number to be used for the PIC offset register. */
48 const char * thumb_pic_register_string = NULL;
49 int thumb_pic_register = 10;
51 /* True if we are currently building a constant table. */
52 int making_const_table;
55 /* Predicates */
56 int
57 reload_memory_operand (op, mode)
58 rtx op;
59 enum machine_mode mode ATTRIBUTE_UNUSED ;
61 int regno = true_regnum (op);
63 return (! CONSTANT_P (op)
64 && (regno == -1
65 || (GET_CODE (op) == REG
66 && REGNO (op) >= FIRST_PSEUDO_REGISTER)));
69 /* Return nonzero if op is suitable for the RHS of a cmp instruction. */
70 int
71 thumb_cmp_operand (op, mode)
72 rtx op;
73 enum machine_mode mode;
75 return ((GET_CODE (op) == CONST_INT
76 && (unsigned HOST_WIDE_INT) (INTVAL (op)) < 256)
77 || register_operand (op, mode));
80 int
81 thumb_shiftable_const (val)
82 HOST_WIDE_INT val;
84 HOST_WIDE_INT mask = 0xff;
85 int i;
87 for (i = 0; i < 25; i++)
88 if ((val & (mask << i)) == val)
89 return 1;
91 return 0;
94 int
95 thumb_trivial_epilogue ()
97 /* ??? If this function ever returns 1, we get a function without any
98 epilogue at all. It appears that the intent was to cause a "return"
99 insn to be emitted, but that does not happen. */
100 return 0;
102 #if 0
103 if (get_frame_size ()
104 || current_function_outgoing_args_size
105 || current_function_pretend_args_size)
106 return 0;
108 for (regno = 8; regno < 13; regno++)
109 if (regs_ever_live[regno] && ! call_used_regs[regno])
110 return 0;
112 return 1;
113 #endif
117 /* Return TRUE if X references a SYMBOL_REF. */
119 thumb_symbol_mentioned_p (x)
120 rtx x;
122 register const char * fmt;
123 register int i;
125 if (GET_CODE (x) == SYMBOL_REF)
126 return 1;
128 fmt = GET_RTX_FORMAT (GET_CODE (x));
129 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
131 if (fmt[i] == 'E')
133 register int j;
135 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
136 if (thumb_symbol_mentioned_p (XVECEXP (x, i, j)))
137 return 1;
139 else if (fmt[i] == 'e' && thumb_symbol_mentioned_p (XEXP (x, i)))
140 return 1;
143 return 0;
146 /* Return TRUE if X references a LABEL_REF. */
148 label_mentioned_p (x)
149 rtx x;
151 register const char * fmt;
152 register int i;
154 if (GET_CODE (x) == LABEL_REF)
155 return 1;
157 fmt = GET_RTX_FORMAT (GET_CODE (x));
158 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
160 if (fmt[i] == 'E')
162 register int j;
164 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
165 if (label_mentioned_p (XVECEXP (x, i, j)))
166 return 1;
168 else if (fmt[i] == 'e' && label_mentioned_p (XEXP (x, i)))
169 return 1;
172 return 0;
176 legitimize_pic_address (orig, mode, reg)
177 rtx orig;
178 enum machine_mode mode;
179 rtx reg;
181 if (GET_CODE (orig) == SYMBOL_REF)
183 rtx pic_ref, address;
184 rtx insn;
185 int subregs = 0;
187 if (reg == 0)
189 if (reload_in_progress || reload_completed)
190 abort ();
191 else
192 reg = gen_reg_rtx (Pmode);
194 subregs = 1;
197 #ifdef AOF_ASSEMBLER
198 /* The AOF assembler can generate relocations for these directly, and
199 understands that the PIC register has to be added into the offset.
201 insn = emit_insn (gen_pic_load_addr_based (reg, orig));
202 #else
203 if (subregs)
204 address = gen_reg_rtx (Pmode);
205 else
206 address = reg;
208 emit_insn (gen_pic_load_addr (address, orig));
210 pic_ref = gen_rtx_MEM (Pmode,
211 gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
212 address));
213 RTX_UNCHANGING_P (pic_ref) = 1;
214 insn = emit_move_insn (reg, pic_ref);
215 #endif
216 current_function_uses_pic_offset_table = 1;
217 /* Put a REG_EQUAL note on this insn, so that it can be optimized
218 by loop. */
219 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
220 REG_NOTES (insn));
221 return reg;
223 else if (GET_CODE (orig) == CONST)
225 rtx base, offset;
227 if (GET_CODE (XEXP (orig, 0)) == PLUS
228 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
229 return orig;
231 if (reg == 0)
233 if (reload_in_progress || reload_completed)
234 abort ();
235 else
236 reg = gen_reg_rtx (Pmode);
239 if (GET_CODE (XEXP (orig, 0)) == PLUS)
241 base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
242 offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
243 base == reg ? 0 : reg);
245 else
246 abort ();
248 if (GET_CODE (offset) == CONST_INT)
250 /* The base register doesn't really matter, we only want to
251 test the index for the appropriate mode. */
252 if (INDEX_REGISTER_RTX_P (offset) && GET_MODE_SIZE (mode) <= 4)
253 goto win;
255 if (! reload_in_progress && ! reload_completed)
256 offset = force_reg (Pmode, offset);
257 else
258 abort ();
260 win:
261 if (GET_CODE (offset) == CONST_INT)
262 return plus_constant_for_output (base, INTVAL (offset));
265 if (GET_MODE_SIZE (mode) > 4)
267 emit_insn (gen_addsi3 (reg, base, offset));
268 return reg;
271 return gen_rtx_PLUS (Pmode, base, offset);
273 else if (GET_CODE (orig) == LABEL_REF)
274 current_function_uses_pic_offset_table = 1;
276 return orig;
279 static rtx pic_rtx;
282 is_pic (x)
283 rtx x;
285 if (x == pic_rtx)
286 return 1;
287 return 0;
290 void
291 thumb_finalize_pic ()
293 #ifndef AOF_ASSEMBLER
294 rtx l1, pic_tmp, pic_tmp2, seq;
295 rtx global_offset_table;
297 if (current_function_uses_pic_offset_table == 0 || TARGET_SINGLE_PIC_BASE)
298 return;
300 if (! flag_pic)
301 abort ();
303 start_sequence ();
304 l1 = gen_label_rtx ();
306 global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
307 /* On the Thumb the PC register contains 'dot + 4' at the time of the
308 addition. XXX Is this true? */
309 pic_tmp = plus_constant (gen_rtx_LABEL_REF (Pmode, l1), 4);
310 if (GOT_PCREL)
311 pic_tmp2 = gen_rtx_CONST (VOIDmode,
312 gen_rtx_PLUS (Pmode, global_offset_table, pc_rtx));
313 else
314 pic_tmp2 = gen_rtx_CONST (VOIDmode, global_offset_table);
316 pic_rtx = gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, pic_tmp2, pic_tmp));
318 emit_insn (gen_pic_load_addr (pic_offset_table_rtx, pic_rtx));
319 emit_insn (gen_pic_add_dot_plus_four (pic_offset_table_rtx, l1));
321 seq = gen_sequence ();
322 end_sequence ();
323 emit_insn_after (seq, get_insns ());
325 /* Need to emit this whether or not we obey regdecls,
326 since setjmp/longjmp can cause life info to screw up. */
327 emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
328 #endif /* AOF_ASSEMBLER */
332 /* Routines for handling the constant pool */
333 /* This is unashamedly hacked from the version in sh.c, since the problem is
334 extremely similar. */
336 /* Thumb instructions cannot load a large constant into a register,
337 constants have to come from a pc relative load. The reference of a pc
338 relative load instruction must be less than 1k infront of the instruction.
339 This means that we often have to dump a constant inside a function, and
340 generate code to branch around it.
342 It is important to minimize this, since the branches will slow things
343 down and make things bigger.
345 Worst case code looks like:
347 ldr rn, L1
348 b L2
349 align
350 L1: .long value
354 ldr rn, L3
355 b L4
356 align
357 L3: .long value
361 We fix this by performing a scan before scheduling, which notices which
362 instructions need to have their operands fetched from the constant table
363 and builds the table.
366 The algorithm is:
368 scan, find an instruction which needs a pcrel move. Look forward, find the
369 last barrier which is within MAX_COUNT bytes of the requirement.
370 If there isn't one, make one. Process all the instructions between
371 the find and the barrier.
373 In the above example, we can tell that L3 is within 1k of L1, so
374 the first move can be shrunk from the 2 insn+constant sequence into
375 just 1 insn, and the constant moved to L3 to make:
377 ldr rn, L1
379 ldr rn, L3
380 b L4
381 align
382 L1: .long value
383 L3: .long value
386 Then the second move becomes the target for the shortening process.
390 typedef struct
392 rtx value; /* Value in table */
393 HOST_WIDE_INT next_offset;
394 enum machine_mode mode; /* Mode of value */
395 } pool_node;
397 /* The maximum number of constants that can fit into one pool, since
398 the pc relative range is 0...1020 bytes and constants are at least 4
399 bytes long */
401 #define MAX_POOL_SIZE (1020/4)
402 static pool_node pool_vector[MAX_POOL_SIZE];
403 static int pool_size;
404 static rtx pool_vector_label;
406 /* Add a constant to the pool and return its label. */
408 static HOST_WIDE_INT
409 add_constant (x, mode)
410 rtx x;
411 enum machine_mode mode;
413 int i;
414 HOST_WIDE_INT offset;
416 if (mode == SImode && GET_CODE (x) == MEM && CONSTANT_P (XEXP (x, 0))
417 && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
418 x = get_pool_constant (XEXP (x, 0));
419 #ifndef AOF_ASSEMBLER
420 else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == 3)
421 x = XVECEXP (x, 0, 0);
422 #endif
424 /* First see if we've already got it */
426 for (i = 0; i < pool_size; i++)
428 if (x->code == pool_vector[i].value->code
429 && mode == pool_vector[i].mode)
431 if (x->code == CODE_LABEL)
433 if (XINT (x, 3) != XINT (pool_vector[i].value, 3))
434 continue;
436 if (rtx_equal_p (x, pool_vector[i].value))
437 return pool_vector[i].next_offset - GET_MODE_SIZE (mode);
441 /* Need a new one */
443 pool_vector[pool_size].next_offset = GET_MODE_SIZE (mode);
444 offset = 0;
445 if (pool_size == 0)
446 pool_vector_label = gen_label_rtx ();
447 else
448 pool_vector[pool_size].next_offset
449 += (offset = pool_vector[pool_size - 1].next_offset);
451 pool_vector[pool_size].value = x;
452 pool_vector[pool_size].mode = mode;
453 pool_size++;
454 return offset;
457 /* Output the literal table */
459 static void
460 dump_table (scan)
461 rtx scan;
463 int i;
465 scan = emit_label_after (gen_label_rtx (), scan);
466 scan = emit_insn_after (gen_align_4 (), scan);
467 scan = emit_label_after (pool_vector_label, scan);
469 for (i = 0; i < pool_size; i++)
471 pool_node *p = pool_vector + i;
473 switch (GET_MODE_SIZE (p->mode))
475 case 4:
476 scan = emit_insn_after (gen_consttable_4 (p->value), scan);
477 break;
479 case 8:
480 scan = emit_insn_after (gen_consttable_8 (p->value), scan);
481 break;
483 default:
484 abort ();
485 break;
489 scan = emit_insn_after (gen_consttable_end (), scan);
490 scan = emit_barrier_after (scan);
491 pool_size = 0;
494 /* Non zero if the src operand needs to be fixed up */
495 static int
496 fixit (src, mode)
497 rtx src;
498 enum machine_mode mode;
500 #ifndef AOF_ASSEMBLER
501 if (GET_CODE (src) == UNSPEC && XINT (src, 1) == 3)
502 return 1;
503 #endif
504 return ((CONSTANT_P (src)
505 && (GET_CODE (src) != CONST_INT
506 || ! (CONST_OK_FOR_LETTER_P (INTVAL (src), 'I')
507 || CONST_OK_FOR_LETTER_P (INTVAL (src), 'J')
508 || (mode != DImode
509 && CONST_OK_FOR_LETTER_P (INTVAL (src), 'K')))))
510 || (mode == SImode && GET_CODE (src) == MEM
511 && GET_CODE (XEXP (src, 0)) == SYMBOL_REF
512 && CONSTANT_POOL_ADDRESS_P (XEXP (src, 0))));
515 /* Find the last barrier less than MAX_COUNT bytes from FROM, or create one. */
516 #define MAX_COUNT_SI 1000
518 static rtx
519 find_barrier (from)
520 rtx from;
522 int count = 0;
523 rtx found_barrier = 0;
524 rtx label;
526 while (from && count < MAX_COUNT_SI)
528 if (GET_CODE (from) == BARRIER)
529 return from;
531 /* Count the length of this insn. */
532 if (GET_CODE (from) == INSN
533 && GET_CODE (PATTERN (from)) == SET
534 && CONSTANT_P (SET_SRC (PATTERN (from)))
535 && CONSTANT_POOL_ADDRESS_P (SET_SRC (PATTERN (from))))
536 count += 2;
537 else
538 count += get_attr_length (from);
540 from = NEXT_INSN (from);
543 /* We didn't find a barrier in time to
544 dump our stuff, so we'll make one. */
545 label = gen_label_rtx ();
547 if (from)
548 from = PREV_INSN (from);
549 else
550 from = get_last_insn ();
552 /* Walk back to be just before any jump. */
553 while (GET_CODE (from) == JUMP_INSN
554 || GET_CODE (from) == NOTE
555 || GET_CODE (from) == CODE_LABEL)
556 from = PREV_INSN (from);
558 from = emit_jump_insn_after (gen_jump (label), from);
559 JUMP_LABEL (from) = label;
560 found_barrier = emit_barrier_after (from);
561 emit_label_after (label, found_barrier);
563 return found_barrier;
566 /* Non zero if the insn is a move instruction which needs to be fixed. */
567 static int
568 broken_move (insn)
569 rtx insn;
571 if (!INSN_DELETED_P (insn)
572 && GET_CODE (insn) == INSN
573 && GET_CODE (PATTERN (insn)) == SET)
575 rtx pat = PATTERN (insn);
576 rtx src = SET_SRC (pat);
577 rtx dst = SET_DEST (pat);
578 enum machine_mode mode = GET_MODE (dst);
579 if (dst == pc_rtx)
580 return 0;
581 return fixit (src, mode);
583 return 0;
586 /* Recursively search through all of the blocks in a function
587 checking to see if any of the variables created in that
588 function match the RTX called 'orig'. If they do then
589 replace them with the RTX called 'new'. */
591 static void
592 replace_symbols_in_block (tree block, rtx orig, rtx new)
594 for (; block; block = BLOCK_CHAIN (block))
596 tree sym;
598 if (! TREE_USED (block))
599 continue;
601 for (sym = BLOCK_VARS (block); sym; sym = TREE_CHAIN (sym))
603 if ( (DECL_NAME (sym) == 0 && TREE_CODE (sym) != TYPE_DECL)
604 || DECL_IGNORED_P (sym)
605 || TREE_CODE (sym) != VAR_DECL
606 || DECL_EXTERNAL (sym)
607 || ! rtx_equal_p (DECL_RTL (sym), orig)
609 continue;
611 DECL_RTL (sym) = new;
614 replace_symbols_in_block (BLOCK_SUBBLOCKS (block), orig, new);
618 void
619 thumb_reorg (first)
620 rtx first;
622 rtx insn;
624 for (insn = first; insn; insn = NEXT_INSN (insn))
626 if (broken_move (insn))
628 /* This is a broken move instruction, scan ahead looking for
629 a barrier to stick the constant table behind. */
630 rtx scan;
631 rtx barrier = find_barrier (insn);
633 /* Now find all the moves between the points and modify them. */
634 for (scan = insn; scan != barrier; scan = NEXT_INSN (scan))
636 if (broken_move (scan))
638 /* This is a broken move instruction, add it to the pool. */
639 rtx pat = PATTERN (scan);
640 rtx src = SET_SRC (pat);
641 rtx dst = SET_DEST (pat);
642 enum machine_mode mode = GET_MODE (dst);
643 HOST_WIDE_INT offset;
644 rtx newinsn;
645 rtx newsrc;
647 /* If this is an HImode constant load, convert it into
648 an SImode constant load. Since the register is always
649 32 bits this is safe. We have to do this, since the
650 load pc-relative instruction only does a 32-bit load. */
651 if (mode == HImode)
653 mode = SImode;
654 if (GET_CODE (dst) != REG)
655 abort ();
656 PUT_MODE (dst, SImode);
659 offset = add_constant (src, mode);
660 newsrc = gen_rtx (MEM, mode,
661 plus_constant (gen_rtx (LABEL_REF,
662 VOIDmode,
663 pool_vector_label),
664 offset));
666 /* Build a jump insn wrapper around the move instead
667 of an ordinary insn, because we want to have room for
668 the target label rtx in fld[7], which an ordinary
669 insn doesn't have. */
670 newinsn = emit_jump_insn_after (gen_rtx (SET, VOIDmode,
671 dst, newsrc), scan);
672 JUMP_LABEL (newinsn) = pool_vector_label;
674 /* But it's still an ordinary insn. */
675 PUT_CODE (newinsn, INSN);
677 /* If debugging information is going to be emitted
678 then we must make sure that any refences to
679 symbols which are removed by the above code are
680 also removed in the descriptions of the
681 function's variables. Failure to do this means
682 that the debugging information emitted could
683 refer to symbols which are not emited by
684 output_constant_pool() because
685 mark_constant_pool() never sees them as being
686 used. */
688 /* These are the tests used in
689 output_constant_pool() to decide if the constant
690 pool will be marked. Only necessary if debugging
691 info is being emitted. Only necessary for
692 references to memory whose address is given by a
693 symbol. */
694 if (optimize > 0
695 && flag_expensive_optimizations
696 && write_symbols != NO_DEBUG
697 && GET_CODE (src) == MEM
698 && GET_CODE (XEXP (src, 0)) == SYMBOL_REF)
699 replace_symbols_in_block
700 (DECL_INITIAL (current_function_decl), src, newsrc);
702 /* Kill old insn. */
703 delete_insn (scan);
704 scan = newinsn;
708 dump_table (barrier);
714 /* Routines for generating rtl. */
715 void
716 thumb_expand_movstrqi (operands)
717 rtx *operands;
719 rtx out = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
720 rtx in = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
721 HOST_WIDE_INT len = INTVAL (operands[2]);
722 HOST_WIDE_INT offset = 0;
724 while (len >= 12)
726 emit_insn (gen_movmem12b (out, in));
727 len -= 12;
729 if (len >= 8)
731 emit_insn (gen_movmem8b (out, in));
732 len -= 8;
734 if (len >= 4)
736 rtx reg = gen_reg_rtx (SImode);
737 emit_insn (gen_movsi (reg, gen_rtx (MEM, SImode, in)));
738 emit_insn (gen_movsi (gen_rtx (MEM, SImode, out), reg));
739 len -= 4;
740 offset += 4;
742 if (len >= 2)
744 rtx reg = gen_reg_rtx (HImode);
745 emit_insn (gen_movhi (reg, gen_rtx (MEM, HImode,
746 plus_constant (in, offset))));
747 emit_insn (gen_movhi (gen_rtx (MEM, HImode, plus_constant (out, offset)),
748 reg));
749 len -= 2;
750 offset += 2;
752 if (len)
754 rtx reg = gen_reg_rtx (QImode);
755 emit_insn (gen_movqi (reg, gen_rtx (MEM, QImode,
756 plus_constant (in, offset))));
757 emit_insn (gen_movqi (gen_rtx (MEM, QImode, plus_constant (out, offset)),
758 reg));
763 /* Routines for reloading */
765 void
766 thumb_reload_out_si (operands)
767 rtx operands ATTRIBUTE_UNUSED;
769 abort ();
773 #ifdef THUMB_PE
774 /* Return non-zero if FUNC is a naked function. */
776 static int
777 arm_naked_function_p (func)
778 tree func;
780 tree a;
782 if (TREE_CODE (func) != FUNCTION_DECL)
783 abort ();
785 a = lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (func));
786 return a != NULL_TREE;
788 #endif
790 /* Return non-zero if FUNC must be entered in ARM mode. */
792 is_called_in_ARM_mode (func)
793 tree func;
795 if (TREE_CODE (func) != FUNCTION_DECL)
796 abort ();
798 /* Ignore the problem about functions whoes address is taken. */
799 if (TARGET_CALLEE_INTERWORKING && TREE_PUBLIC (func))
800 return TRUE;
802 #ifdef THUMB_PE
803 return lookup_attribute ("interfacearm", DECL_MACHINE_ATTRIBUTES (func)) != NULL_TREE;
804 #else
805 return FALSE;
806 #endif
810 /* Routines for emitting code */
812 void
813 thumb_final_prescan_insn (insn)
814 rtx insn;
816 extern int * insn_addresses;
818 if (flag_print_asm_name)
819 fprintf (asm_out_file, "%s 0x%04x\n", ASM_COMMENT_START,
820 insn_addresses[INSN_UID (insn)]);
824 static void thumb_pushpop ( FILE *, int, int ); /* Forward declaration. */
826 #ifdef __GNUC__
827 inline
828 #endif
829 static int
830 number_of_first_bit_set (mask)
831 int mask;
833 int bit;
835 for (bit = 0;
836 (mask & (1 << bit)) == 0;
837 ++ bit)
838 continue;
840 return bit;
843 #define ARG_1_REGISTER 0
844 #define ARG_2_REGISTER 1
845 #define ARG_3_REGISTER 2
846 #define ARG_4_REGISTER 3
847 #define WORK_REGISTER 7
848 #define FRAME_POINTER 11
849 #define IP_REGISTER 12
850 #define STACK_POINTER STACK_POINTER_REGNUM
851 #define LINK_REGISTER 14
852 #define PROGRAM_COUNTER 15
854 /* Generate code to return from a thumb function. If
855 'reg_containing_return_addr' is -1, then the return address is
856 actually on the stack, at the stack pointer. */
857 static void
858 thumb_exit (f, reg_containing_return_addr)
859 FILE * f;
860 int reg_containing_return_addr;
862 int regs_available_for_popping;
863 int regs_to_pop;
864 int pops_needed;
865 int available;
866 int required;
867 int mode;
868 int size;
869 int restore_a4 = FALSE;
871 /* Compute the registers we need to pop. */
872 regs_to_pop = 0;
873 pops_needed = 0;
875 if (reg_containing_return_addr == -1)
877 regs_to_pop |= 1 << LINK_REGISTER;
878 ++ pops_needed;
881 if (TARGET_BACKTRACE)
883 /* Restore frame pointer and stack pointer. */
884 regs_to_pop |= (1 << FRAME_POINTER) | (1 << STACK_POINTER);
885 pops_needed += 2;
888 /* If there is nothing to pop then just emit the BX instruction and return. */
889 if (pops_needed == 0)
891 asm_fprintf (f, "\tbx\t%s\n", reg_names [reg_containing_return_addr]);
893 return;
896 /* Otherwise if we are not supporting interworking and we have not created
897 a backtrace structure and the function was not entered in ARM mode then
898 just pop the return address straight into the PC. */
899 else if ( ! TARGET_THUMB_INTERWORK
900 && ! TARGET_BACKTRACE
901 && ! is_called_in_ARM_mode (current_function_decl))
903 asm_fprintf (f, "\tpop\t{pc}\n" );
905 return;
908 /* Find out how many of the (return) argument registers we can corrupt. */
909 regs_available_for_popping = 0;
911 #ifdef RTX_CODE
912 /* If we can deduce the registers used from the function's return value.
913 This is more reliable that examining regs_ever_live[] because that
914 will be set if the register is ever used in the function, not just if
915 the register is used to hold a return value. */
917 if (current_function_return_rtx != 0)
918 mode = GET_MODE (current_function_return_rtx);
919 else
920 #endif
921 mode = DECL_MODE (DECL_RESULT (current_function_decl));
923 size = GET_MODE_SIZE (mode);
925 if (size == 0)
927 /* In a void function we can use any argument register.
928 In a function that returns a structure on the stack
929 we can use the second and third argument registers. */
930 if (mode == VOIDmode)
931 regs_available_for_popping =
932 (1 << ARG_1_REGISTER)
933 | (1 << ARG_2_REGISTER)
934 | (1 << ARG_3_REGISTER);
935 else
936 regs_available_for_popping =
937 (1 << ARG_2_REGISTER)
938 | (1 << ARG_3_REGISTER);
940 else if (size <= 4) regs_available_for_popping =
941 (1 << ARG_2_REGISTER)
942 | (1 << ARG_3_REGISTER);
943 else if (size <= 8) regs_available_for_popping =
944 (1 << ARG_3_REGISTER);
946 /* Match registers to be popped with registers into which we pop them. */
947 for (available = regs_available_for_popping,
948 required = regs_to_pop;
949 required != 0 && available != 0;
950 available &= ~(available & - available),
951 required &= ~(required & - required))
952 -- pops_needed;
954 /* If we have any popping registers left over, remove them. */
955 if (available > 0)
956 regs_available_for_popping &= ~ available;
958 /* Otherwise if we need another popping register we can use
959 the fourth argument register. */
960 else if (pops_needed)
962 /* If we have not found any free argument registers and
963 reg a4 contains the return address, we must move it. */
964 if (regs_available_for_popping == 0
965 && reg_containing_return_addr == ARG_4_REGISTER)
967 asm_fprintf (f, "\tmov\t%s, %s\n",
968 reg_names [LINK_REGISTER], reg_names [ARG_4_REGISTER]);
969 reg_containing_return_addr = LINK_REGISTER;
971 else if (size > 12)
973 /* Register a4 is being used to hold part of the return value,
974 but we have dire need of a free, low register. */
975 restore_a4 = TRUE;
977 asm_fprintf (f, "\tmov\t%s, %s\n",
978 reg_names [IP_REGISTER], reg_names [ARG_4_REGISTER]);
981 if (reg_containing_return_addr != ARG_4_REGISTER)
983 /* The fourth argument register is available. */
984 regs_available_for_popping |= 1 << ARG_4_REGISTER;
986 -- pops_needed;
990 /* Pop as many registers as we can. */
991 thumb_pushpop (f, regs_available_for_popping, FALSE);
993 /* Process the registers we popped. */
994 if (reg_containing_return_addr == -1)
996 /* The return address was popped into the lowest numbered register. */
997 regs_to_pop &= ~ (1 << LINK_REGISTER);
999 reg_containing_return_addr =
1000 number_of_first_bit_set (regs_available_for_popping);
1002 /* Remove this register for the mask of available registers, so that
1003 the return address will not be corrupted by futher pops. */
1004 regs_available_for_popping &= ~ (1 << reg_containing_return_addr);
1007 /* If we popped other registers then handle them here. */
1008 if (regs_available_for_popping)
1010 int frame_pointer;
1012 /* Work out which register currently contains the frame pointer. */
1013 frame_pointer = number_of_first_bit_set (regs_available_for_popping);
1015 /* Move it into the correct place. */
1016 asm_fprintf (f, "\tmov\tfp, %s\n", reg_names [frame_pointer]);
1018 /* (Temporarily) remove it from the mask of popped registers. */
1019 regs_available_for_popping &= ~ (1 << frame_pointer);
1020 regs_to_pop &= ~ (1 << FRAME_POINTER);
1022 if (regs_available_for_popping)
1024 int stack_pointer;
1026 /* We popped the stack pointer as well, find the register that
1027 contains it.*/
1028 stack_pointer = number_of_first_bit_set (regs_available_for_popping);
1030 /* Move it into the stack register. */
1031 asm_fprintf (f, "\tmov\tsp, %s\n", reg_names [stack_pointer]);
1033 /* At this point we have popped all necessary registers, so
1034 do not worry about restoring regs_available_for_popping
1035 to its correct value:
1037 assert (pops_needed == 0)
1038 assert (regs_available_for_popping == (1 << frame_pointer))
1039 assert (regs_to_pop == (1 << STACK_POINTER)) */
1041 else
1043 /* Since we have just move the popped value into the frame
1044 pointer, the popping register is available for reuse, and
1045 we know that we still have the stack pointer left to pop. */
1046 regs_available_for_popping |= (1 << frame_pointer);
1050 /* If we still have registers left on the stack, but we no longer have
1051 any registers into which we can pop them, then we must move the return
1052 address into the link register and make available the register that
1053 contained it. */
1054 if (regs_available_for_popping == 0 && pops_needed > 0)
1056 regs_available_for_popping |= 1 << reg_containing_return_addr;
1058 asm_fprintf (f, "\tmov\t%s, %s\n",
1059 reg_names [LINK_REGISTER],
1060 reg_names [reg_containing_return_addr]);
1062 reg_containing_return_addr = LINK_REGISTER;
1065 /* If we have registers left on the stack then pop some more.
1066 We know that at most we will want to pop FP and SP. */
1067 if (pops_needed > 0)
1069 int popped_into;
1070 int move_to;
1072 thumb_pushpop (f, regs_available_for_popping, FALSE);
1074 /* We have popped either FP or SP.
1075 Move whichever one it is into the correct register. */
1076 popped_into = number_of_first_bit_set (regs_available_for_popping);
1077 move_to = number_of_first_bit_set (regs_to_pop);
1079 asm_fprintf (f, "\tmov\t%s, %s\n",
1080 reg_names [move_to], reg_names [popped_into]);
1082 regs_to_pop &= ~ (1 << move_to);
1084 -- pops_needed;
1087 /* If we still have not popped everything then we must have only
1088 had one register available to us and we are now popping the SP. */
1089 if (pops_needed > 0)
1091 int popped_into;
1093 thumb_pushpop (f, regs_available_for_popping, FALSE);
1095 popped_into = number_of_first_bit_set (regs_available_for_popping);
1097 asm_fprintf (f, "\tmov\tsp, %s\n", reg_names [popped_into]);
1100 assert (regs_to_pop == (1 << STACK_POINTER))
1101 assert (pops_needed == 1)
1105 /* If necessary restore the a4 register. */
1106 if (restore_a4)
1108 if (reg_containing_return_addr != LINK_REGISTER)
1110 asm_fprintf (f, "\tmov\t%s, %s\n",
1111 reg_names [LINK_REGISTER], reg_names [ARG_4_REGISTER]);
1112 reg_containing_return_addr = LINK_REGISTER;
1115 asm_fprintf (f, "\tmov\t%s, %s\n",
1116 reg_names [ARG_4_REGISTER], reg_names [IP_REGISTER]);
1119 /* Return to caller. */
1120 asm_fprintf (f, "\tbx\t%s\n", reg_names [reg_containing_return_addr]);
1123 /* Emit code to push or pop registers to or from the stack. */
1124 static void
1125 thumb_pushpop (f, mask, push)
1126 FILE * f;
1127 int mask;
1128 int push;
1130 int regno;
1131 int lo_mask = mask & 0xFF;
1133 if (lo_mask == 0 && ! push && (mask & (1 << 15)))
1135 /* Special case. Do not generate a POP PC statement here, do it in
1136 thumb_exit() */
1138 thumb_exit (f, -1);
1139 return;
1142 asm_fprintf (f, "\t%s\t{", push ? "push" : "pop");
1144 /* Look at the low registers first. */
1146 for (regno = 0; regno < 8; regno ++, lo_mask >>= 1)
1148 if (lo_mask & 1)
1150 asm_fprintf (f, reg_names[regno]);
1152 if ((lo_mask & ~1) != 0)
1153 asm_fprintf (f, ", ");
1157 if (push && (mask & (1 << 14)))
1159 /* Catch pushing the LR. */
1161 if (mask & 0xFF)
1162 asm_fprintf (f, ", ");
1164 asm_fprintf (f, reg_names[14]);
1166 else if (!push && (mask & (1 << 15)))
1168 /* Catch popping the PC. */
1170 if (TARGET_THUMB_INTERWORK || TARGET_BACKTRACE)
1172 /* The PC is never poped directly, instead
1173 it is popped into r3 and then BX is used. */
1175 asm_fprintf (f, "}\n");
1177 thumb_exit (f, -1);
1179 return;
1181 else
1183 if (mask & 0xFF)
1184 asm_fprintf (f, ", ");
1186 asm_fprintf (f, reg_names[15]);
1190 asm_fprintf (f, "}\n");
1193 /* Returns non-zero if the current function contains a far jump */
1196 far_jump_used_p (void)
1198 rtx insn;
1200 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
1202 if (GET_CODE (insn) == JUMP_INSN
1203 /* Ignore tablejump patterns. */
1204 && GET_CODE (PATTERN (insn)) != ADDR_VEC
1205 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
1206 && get_attr_far_jump (insn) == FAR_JUMP_YES)
1207 return 1;
1210 return 0;
1213 static int return_used_this_function = 0;
1215 char *
1216 output_return ()
1218 int regno;
1219 int live_regs_mask = 0;
1221 #ifdef THUMB_PE
1222 /* If a function is naked, don't use the "return" insn. */
1223 if (arm_naked_function_p (current_function_decl))
1224 return "";
1225 #endif
1227 return_used_this_function = 1;
1229 for (regno = 0; regno < 8; regno++)
1230 if (regs_ever_live[regno] && ! call_used_regs[regno]
1231 && ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
1232 live_regs_mask |= 1 << regno;
1234 if (live_regs_mask == 0)
1236 if (leaf_function_p () && ! far_jump_used_p())
1238 thumb_exit (asm_out_file, 14);
1240 else if ( TARGET_THUMB_INTERWORK
1241 || TARGET_BACKTRACE
1242 || is_called_in_ARM_mode (current_function_decl))
1244 thumb_exit (asm_out_file, -1);
1246 else
1247 asm_fprintf (asm_out_file, "\tpop\t{pc}\n");
1249 else
1251 asm_fprintf (asm_out_file, "\tpop\t{");
1253 for (regno = 0; live_regs_mask; regno ++, live_regs_mask >>= 1)
1254 if (live_regs_mask & 1)
1256 asm_fprintf (asm_out_file, reg_names[regno]);
1257 if (live_regs_mask & ~1)
1258 asm_fprintf (asm_out_file, ", ");
1261 if ( TARGET_THUMB_INTERWORK
1262 || TARGET_BACKTRACE
1263 || is_called_in_ARM_mode (current_function_decl))
1265 asm_fprintf (asm_out_file, "}\n");
1266 thumb_exit (asm_out_file, -1);
1268 else
1269 asm_fprintf (asm_out_file, ", pc}\n");
1272 return "";
1275 void
1276 thumb_function_prologue (f, frame_size)
1277 FILE * f;
1278 int frame_size ATTRIBUTE_UNUSED;
1280 int live_regs_mask = 0;
1281 int high_regs_pushed = 0;
1282 int store_arg_regs = 0;
1283 int regno;
1285 #ifdef THUMB_PE
1286 if (arm_naked_function_p (current_function_decl))
1287 return;
1288 #endif
1290 if (is_called_in_ARM_mode (current_function_decl))
1292 const char * name;
1294 if (GET_CODE (DECL_RTL (current_function_decl)) != MEM)
1295 abort();
1296 if (GET_CODE (XEXP (DECL_RTL (current_function_decl), 0)) != SYMBOL_REF)
1297 abort();
1298 name = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
1300 /* Generate code sequence to switch us into Thumb mode. */
1301 /* The .code 32 directive has already been emitted by
1302 ASM_DECLARE_FUNCITON_NAME */
1303 asm_fprintf (f, "\torr\tr12, pc, #1\n");
1304 asm_fprintf (f, "\tbx\tr12\n");
1306 /* Generate a label, so that the debugger will notice the
1307 change in instruction sets. This label is also used by
1308 the assembler to bypass the ARM code when this function
1309 is called from a Thumb encoded function elsewhere in the
1310 same file. Hence the definition of STUB_NAME here must
1311 agree with the definition in gas/config/tc-arm.c */
1313 #define STUB_NAME ".real_start_of"
1315 asm_fprintf (f, "\t.code\t16\n");
1317 #ifdef THUMB_PE
1318 if (arm_dllexport_name_p (name))
1319 name = ARM_STRIP_NAME_ENCODING (name);
1320 #endif
1322 asm_fprintf (f, "\t.globl %s%U%s\n", STUB_NAME, name);
1323 asm_fprintf (f, "\t.thumb_func\n");
1324 asm_fprintf (f, "%s%U%s:\n", STUB_NAME, name);
1327 if (current_function_anonymous_args && current_function_pretend_args_size)
1328 store_arg_regs = 1;
1330 if (current_function_pretend_args_size)
1332 if (store_arg_regs)
1334 asm_fprintf (f, "\tpush\t{");
1335 for (regno = 4 - current_function_pretend_args_size / 4 ; regno < 4;
1336 regno++)
1337 asm_fprintf (f, "%s%s", reg_names[regno], regno == 3 ? "" : ", ");
1338 asm_fprintf (f, "}\n");
1340 else
1341 asm_fprintf (f, "\tsub\t%Rsp, %Rsp, #%d\n",
1342 current_function_pretend_args_size);
1345 for (regno = 0; regno < 8; regno++)
1346 if (regs_ever_live[regno] && ! call_used_regs[regno]
1347 && ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
1348 live_regs_mask |= 1 << regno;
1350 if (live_regs_mask || ! leaf_function_p () || far_jump_used_p ())
1351 live_regs_mask |= 1 << 14;
1353 if (TARGET_BACKTRACE)
1355 const char * name;
1356 int offset;
1357 int work_register = 0;
1359 /* We have been asked to create a stack backtrace structure.
1360 The code looks like this:
1362 0 .align 2
1363 0 func:
1364 0 sub SP, #16 Reserve space for 4 registers.
1365 2 push {R7} Get a work register.
1366 4 add R7, SP, #20 Get the stack pointer before the push.
1367 6 str R7, [SP, #8] Store the stack pointer (before reserving the space).
1368 8 mov R7, PC Get hold of the start of this code plus 12.
1369 10 str R7, [SP, #16] Store it.
1370 12 mov R7, FP Get hold of the current frame pointer.
1371 14 str R7, [SP, #4] Store it.
1372 16 mov R7, LR Get hold of the current return address.
1373 18 str R7, [SP, #12] Store it.
1374 20 add R7, SP, #16 Point at the start of the backtrace structure.
1375 22 mov FP, R7 Put this value into the frame pointer. */
1377 if ((live_regs_mask & 0xFF) == 0)
1379 /* See if the a4 register is free. */
1381 if (regs_ever_live [3] == 0)
1382 work_register = 3;
1383 else /* We must push a register of our own */
1384 live_regs_mask |= (1 << 7);
1387 if (work_register == 0)
1389 /* Select a register from the list that will be pushed to use as our work register. */
1391 for (work_register = 8; work_register--;)
1392 if ((1 << work_register) & live_regs_mask)
1393 break;
1396 name = reg_names [work_register];
1398 asm_fprintf (f, "\tsub\tsp, sp, #16\t@ Create stack backtrace structure\n");
1400 if (live_regs_mask)
1401 thumb_pushpop (f, live_regs_mask, 1);
1403 for (offset = 0, work_register = 1 << 15; work_register; work_register >>= 1)
1404 if (work_register & live_regs_mask)
1405 offset += 4;
1407 asm_fprintf (f, "\tadd\t%s, sp, #%d\n",
1408 name, offset + 16 + current_function_pretend_args_size);
1410 asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 4);
1412 /* Make sure that the instruction fetching the PC is in the right place
1413 to calculate "start of backtrace creation code + 12". */
1415 if (live_regs_mask)
1417 asm_fprintf (f, "\tmov\t%s, pc\n", name);
1418 asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 12);
1419 asm_fprintf (f, "\tmov\t%s, fp\n", name);
1420 asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset);
1422 else
1424 asm_fprintf (f, "\tmov\t%s, fp\n", name);
1425 asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset);
1426 asm_fprintf (f, "\tmov\t%s, pc\n", name);
1427 asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 12);
1430 asm_fprintf (f, "\tmov\t%s, lr\n", name);
1431 asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 8);
1432 asm_fprintf (f, "\tadd\t%s, sp, #%d\n", name, offset + 12);
1433 asm_fprintf (f, "\tmov\tfp, %s\t\t@ Backtrace structure created\n", name);
1435 else if (live_regs_mask)
1436 thumb_pushpop (f, live_regs_mask, 1);
1438 for (regno = 8; regno < 13; regno++)
1440 if (regs_ever_live[regno] && ! call_used_regs[regno]
1441 && ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
1442 high_regs_pushed++;
1445 if (high_regs_pushed)
1447 int pushable_regs = 0;
1448 int mask = live_regs_mask & 0xff;
1449 int next_hi_reg;
1451 for (next_hi_reg = 12; next_hi_reg > 7; next_hi_reg--)
1453 if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg]
1454 && ! (TARGET_SINGLE_PIC_BASE && (next_hi_reg == thumb_pic_register)))
1455 break;
1458 pushable_regs = mask;
1460 if (pushable_regs == 0)
1462 /* desperation time -- this probably will never happen */
1463 if (regs_ever_live[3] || ! call_used_regs[3])
1464 asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[12], reg_names[3]);
1465 mask = 1 << 3;
1468 while (high_regs_pushed > 0)
1470 for (regno = 7; regno >= 0; regno--)
1472 if (mask & (1 << regno))
1474 asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[regno],
1475 reg_names[next_hi_reg]);
1476 high_regs_pushed--;
1477 if (high_regs_pushed)
1478 for (next_hi_reg--; next_hi_reg > 7; next_hi_reg--)
1480 if (regs_ever_live[next_hi_reg]
1481 && ! call_used_regs[next_hi_reg]
1482 && ! (TARGET_SINGLE_PIC_BASE
1483 && (next_hi_reg == thumb_pic_register)))
1484 break;
1486 else
1488 mask &= ~ ((1 << regno) - 1);
1489 break;
1493 thumb_pushpop (f, mask, 1);
1496 if (pushable_regs == 0 && (regs_ever_live[3] || ! call_used_regs[3]))
1497 asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[3], reg_names[12]);
1501 /* Functions to save and restore thumb_return_addr_rtx. */
1502 static rtx thumb_return_addr_rtx = NULL_RTX;
1504 struct machine_function
1506 rtx ra_rtx;
1509 static void
1510 thumb_save_machine_status (p)
1511 struct function * p;
1513 struct machine_function * machine =
1514 (struct machine_function *) xmalloc (sizeof (* machine));
1516 p->machine = machine;
1517 machine->ra_rtx = thumb_return_addr_rtx;
1520 static void
1521 thumb_restore_machine_status (p)
1522 struct function * p;
1524 struct machine_function * machine = p->machine;
1526 thumb_return_addr_rtx = machine->ra_rtx;
1528 free (machine);
1530 p->machine = (struct machine_function *) NULL;
1533 /* Return an RTX indicating where the return address to the
1534 calling function can be found. */
1536 thumb_return_addr (count)
1537 int count;
1539 if (count != 0)
1540 return NULL_RTX;
1542 if (thumb_return_addr_rtx == NULL_RTX)
1544 rtx init;
1546 thumb_return_addr_rtx = gen_reg_rtx (Pmode);
1548 init = gen_rtx_REG (Pmode, 14);
1550 init = gen_rtx_SET (VOIDmode, thumb_return_addr_rtx, init);
1552 /* Emit the insn to the prologue with the other argument copies. */
1553 push_topmost_sequence ();
1554 emit_insn_after (init, get_insns ());
1555 pop_topmost_sequence ();
1558 return thumb_return_addr_rtx;
1561 /* Do anything needed before RTL is emitted for each function. */
1562 void
1563 thumb_init_expanders ()
1565 thumb_return_addr_rtx = NULL_RTX;
1567 /* Arrange to save and restore machine status around nested functions. */
1568 save_machine_status = thumb_save_machine_status;
1569 restore_machine_status = thumb_restore_machine_status;
1572 void
1573 thumb_expand_prologue ()
1575 HOST_WIDE_INT amount = (get_frame_size ()
1576 + current_function_outgoing_args_size);
1577 #ifdef THUMB_PE
1578 /* Naked functions don't have prologues. */
1579 if (arm_naked_function_p (current_function_decl))
1580 return;
1581 #endif
1583 if (amount)
1585 if (amount < 512)
1586 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
1587 GEN_INT (- amount)));
1588 else
1590 int regno;
1591 rtx reg;
1593 /* The stack decrement is too big for an immediate value in a single
1594 insn. In theory we could issue multiple subtracts, but after
1595 three of them it becomes more space efficient to place the full
1596 value in the constant pool and load into a register. (Also the
1597 ARM debugger really likes to see only one stack decrement per
1598 function). So instead we look for a scratch register into which
1599 we can load the decrement, and then we subtract this from the
1600 stack pointer. Unfortunately on the thumb the only available
1601 scratch registers are the argument registers, and we cannot use
1602 these as they may hold arguments to the function. Instead we
1603 attempt to locate a call preserved register which is used by this
1604 function. If we can find one, then we know that it will have
1605 been pushed at the start of the prologue and so we can corrupt
1606 it now. */
1607 for (regno = 4; regno < 8; regno++)
1608 if (regs_ever_live[regno]
1609 && ! call_used_regs[regno] /* Paranoia */
1610 && ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
1611 break;
1613 if (regno == 8) /* Very unlikely */
1615 rtx spare = gen_rtx (REG, SImode, 12);
1617 /* Choose an arbitary, non-argument low register. */
1618 reg = gen_rtx (REG, SImode, 4);
1620 /* Save it by copying it into a high, scratch register. */
1621 emit_insn (gen_movsi (spare, reg));
1623 /* Decrement the stack. */
1624 emit_insn (gen_movsi (reg, GEN_INT (- amount)));
1625 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
1626 reg));
1628 /* Restore the low register's original value. */
1629 emit_insn (gen_movsi (reg, spare));
1631 /* Emit a USE of the restored scratch register, so that flow
1632 analysis will not consider the restore redundant. The
1633 register won't be used again in this function and isn't
1634 restored by the epilogue. */
1635 emit_insn (gen_rtx_USE (VOIDmode, reg));
1637 else
1639 reg = gen_rtx (REG, SImode, regno);
1641 emit_insn (gen_movsi (reg, GEN_INT (- amount)));
1642 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
1643 reg));
1648 /* This should only happen with optimisation disabled. Emit the copy
1649 *after* the stack adjust, as the unoptimised code will attempt to store
1650 local variables at positive offsets from the frame pointer. */
1651 if (frame_pointer_needed)
1653 if (current_function_outgoing_args_size)
1655 rtx offset = GEN_INT (current_function_outgoing_args_size);
1657 if (current_function_outgoing_args_size < 1024)
1658 emit_insn (gen_addsi3 (frame_pointer_rtx, stack_pointer_rtx,
1659 offset));
1660 else
1662 emit_insn (gen_movsi (frame_pointer_rtx, offset));
1663 emit_insn (gen_addsi3 (frame_pointer_rtx, frame_pointer_rtx,
1664 stack_pointer_rtx));
1667 else
1668 emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
1671 if (profile_flag || profile_block_flag)
1672 emit_insn (gen_blockage ());
1675 void
1676 thumb_expand_epilogue ()
1678 HOST_WIDE_INT amount = (get_frame_size ()
1679 + current_function_outgoing_args_size);
1680 #ifdef THUMB_PE
1681 /* Naked functions don't have epilogues. */
1682 if (arm_naked_function_p (current_function_decl))
1683 return;
1684 #endif
1686 if (amount)
1688 if (amount < 512)
1689 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
1690 GEN_INT (amount)));
1691 else
1693 rtx reg = gen_rtx (REG, SImode, 3); /* Always free in the epilogue */
1695 emit_insn (gen_movsi (reg, GEN_INT (amount)));
1696 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));
1700 /* Emit a USE (stack_pointer_rtx), so that
1701 the stack adjustment will not be deleted. */
1702 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
1704 if (profile_flag || profile_block_flag)
1705 emit_insn (gen_blockage ());
1708 void
1709 thumb_function_epilogue (f, frame_size)
1710 FILE * f ATTRIBUTE_UNUSED;
1711 int frame_size ATTRIBUTE_UNUSED;
1713 /* ??? Probably not safe to set this here, since it assumes that a
1714 function will be emitted as assembly immediately after we generate
1715 RTL for it. This does not happen for inline functions. */
1716 return_used_this_function = 0;
1717 #if 0 /* TODO : comment not really needed */
1718 fprintf (f, "%s THUMB Epilogue\n", ASM_COMMENT_START);
1719 #endif
1722 /* The bits which aren't usefully expanded as rtl. */
1723 char *
1724 thumb_unexpanded_epilogue ()
1726 int regno;
1727 int live_regs_mask = 0;
1728 int high_regs_pushed = 0;
1729 int leaf_function = leaf_function_p ();
1730 int had_to_push_lr;
1732 if (return_used_this_function)
1733 return "";
1735 for (regno = 0; regno < 8; regno++)
1736 if (regs_ever_live[regno] && ! call_used_regs[regno]
1737 && ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
1738 live_regs_mask |= 1 << regno;
1740 for (regno = 8; regno < 13; regno++)
1742 if (regs_ever_live[regno] && ! call_used_regs[regno]
1743 && ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
1744 high_regs_pushed ++;
1747 /* The prolog may have pushed some high registers to use as
1748 work registers. eg the testuite file:
1749 gcc/testsuite/gcc/gcc.c-torture/execute/complex-2.c
1750 compiles to produce:
1751 push {r4, r5, r6, r7, lr}
1752 mov r7, r9
1753 mov r6, r8
1754 push {r6, r7}
1755 as part of the prolog. We have to undo that pushing here. */
1757 if (high_regs_pushed)
1759 int mask = live_regs_mask;
1760 int next_hi_reg;
1761 int size;
1762 int mode;
1764 #ifdef RTX_CODE
1765 /* If we can deduce the registers used from the function's return value.
1766 This is more reliable that examining regs_ever_live[] because that
1767 will be set if the register is ever used in the function, not just if
1768 the register is used to hold a return value. */
1770 if (current_function_return_rtx != 0)
1771 mode = GET_MODE (current_function_return_rtx);
1772 else
1773 #endif
1774 mode = DECL_MODE (DECL_RESULT (current_function_decl));
1776 size = GET_MODE_SIZE (mode);
1778 /* Unless we are returning a type of size > 12 register r3 is available. */
1779 if (size < 13)
1780 mask |= 1 << 3;
1782 if (mask == 0)
1783 /* Oh dear! We have no low registers into which we can pop high registers! */
1784 fatal ("No low registers available for popping high registers");
1786 for (next_hi_reg = 8; next_hi_reg < 13; next_hi_reg++)
1787 if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg]
1788 && ! (TARGET_SINGLE_PIC_BASE && (next_hi_reg == thumb_pic_register)))
1789 break;
1791 while (high_regs_pushed)
1793 /* Find low register(s) into which the high register(s) can be popped. */
1794 for (regno = 0; regno < 8; regno++)
1796 if (mask & (1 << regno))
1797 high_regs_pushed--;
1798 if (high_regs_pushed == 0)
1799 break;
1802 mask &= (2 << regno) - 1; /* A noop if regno == 8 */
1804 /* Pop the values into the low register(s). */
1805 thumb_pushpop (asm_out_file, mask, 0);
1807 /* Move the value(s) into the high registers. */
1808 for (regno = 0; regno < 8; regno++)
1810 if (mask & (1 << regno))
1812 asm_fprintf (asm_out_file, "\tmov\t%s, %s\n",
1813 reg_names[next_hi_reg], reg_names[regno]);
1814 for (next_hi_reg++; next_hi_reg < 13; next_hi_reg++)
1815 if (regs_ever_live[next_hi_reg] &&
1816 ! call_used_regs[next_hi_reg]
1817 && ! (TARGET_SINGLE_PIC_BASE
1818 && (next_hi_reg == thumb_pic_register)))
1819 break;
1825 had_to_push_lr = (live_regs_mask || ! leaf_function || far_jump_used_p());
1827 if (TARGET_BACKTRACE && ((live_regs_mask & 0xFF) == 0) && regs_ever_live[ ARG_4_REGISTER ] != 0)
1828 /* The stack backtrace structure creation code had to
1829 push R7 in order to get a work register, so we pop
1830 it now. */
1831 live_regs_mask |= (1 << WORK_REGISTER);
1833 if (current_function_pretend_args_size == 0 || TARGET_BACKTRACE)
1835 if (had_to_push_lr
1836 && ! is_called_in_ARM_mode (current_function_decl))
1837 live_regs_mask |= 1 << PROGRAM_COUNTER;
1839 /* Either no argument registers were pushed or a backtrace
1840 structure was created which includes an adjusted stack
1841 pointer, so just pop everything. */
1842 if (live_regs_mask)
1843 thumb_pushpop (asm_out_file, live_regs_mask, FALSE);
1845 /* We have either just popped the return address into the
1846 PC or it is was kept in LR for the entire function or
1847 it is still on the stack because we do not want to
1848 return by doing a pop {pc}. */
1849 if ((live_regs_mask & (1 << PROGRAM_COUNTER)) == 0)
1850 thumb_exit (asm_out_file,
1851 (had_to_push_lr
1852 && is_called_in_ARM_mode (current_function_decl)) ?
1853 -1 : LINK_REGISTER);
1855 else
1857 /* Pop everything but the return address. */
1858 live_regs_mask &= ~ (1 << PROGRAM_COUNTER);
1860 if (live_regs_mask)
1861 thumb_pushpop (asm_out_file, live_regs_mask, FALSE);
1863 if (had_to_push_lr)
1864 /* Get the return address into a temporary register. */
1865 thumb_pushpop (asm_out_file, 1 << ARG_4_REGISTER, 0);
1867 /* Remove the argument registers that were pushed onto the stack. */
1868 asm_fprintf (asm_out_file, "\tadd\t%s, %s, #%d\n",
1869 reg_names [STACK_POINTER],
1870 reg_names [STACK_POINTER],
1871 current_function_pretend_args_size);
1873 thumb_exit (asm_out_file, had_to_push_lr ? ARG_4_REGISTER : LINK_REGISTER);
1876 return "";
1879 /* Handle the case of a double word load into a low register from
1880 a computed memory address. The computed address may involve a
1881 register which is overwritten by the load. */
1883 char *
1884 thumb_load_double_from_address (operands)
1885 rtx * operands;
1887 rtx addr;
1888 rtx base;
1889 rtx offset;
1890 rtx arg1;
1891 rtx arg2;
1893 if (GET_CODE (operands[0]) != REG)
1894 fatal ("thumb_load_double_from_address: destination is not a register");
1896 if (GET_CODE (operands[1]) != MEM)
1897 fatal ("thumb_load_double_from_address: source is not a computed memory address");
1899 /* Get the memory address. */
1901 addr = XEXP (operands[1], 0);
1903 /* Work out how the memory address is computed. */
1905 switch (GET_CODE (addr))
1907 case REG:
1908 operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
1910 if (REGNO (operands[0]) == REGNO (addr))
1912 output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
1913 output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
1915 else
1917 output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
1918 output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
1920 break;
1922 case CONST:
1923 /* Compute <address> + 4 for the high order load. */
1925 operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
1927 output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
1928 output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
1929 break;
1931 case PLUS:
1932 arg1 = XEXP (addr, 0);
1933 arg2 = XEXP (addr, 1);
1935 if (CONSTANT_P (arg1))
1936 base = arg2, offset = arg1;
1937 else
1938 base = arg1, offset = arg2;
1940 if (GET_CODE (base) != REG)
1941 fatal ("thumb_load_double_from_address: base is not a register");
1943 /* Catch the case of <address> = <reg> + <reg> */
1945 if (GET_CODE (offset) == REG)
1947 int reg_offset = REGNO (offset);
1948 int reg_base = REGNO (base);
1949 int reg_dest = REGNO (operands[0]);
1951 /* Add the base and offset registers together into the higher destination register. */
1953 fprintf (asm_out_file, "\tadd\t%s, %s, %s\t\t%s created by thumb_load_double_from_address",
1954 reg_names[ reg_dest + 1 ],
1955 reg_names[ reg_base ],
1956 reg_names[ reg_offset ],
1957 ASM_COMMENT_START);
1959 /* Load the lower destination register from the address in the higher destination register. */
1961 fprintf (asm_out_file, "\tldr\t%s, [%s, #0]\t\t%s created by thumb_load_double_from_address",
1962 reg_names[ reg_dest ],
1963 reg_names[ reg_dest + 1],
1964 ASM_COMMENT_START);
1966 /* Load the higher destination register from its own address plus 4. */
1968 fprintf (asm_out_file, "\tldr\t%s, [%s, #4]\t\t%s created by thumb_load_double_from_address",
1969 reg_names[ reg_dest + 1 ],
1970 reg_names[ reg_dest + 1 ],
1971 ASM_COMMENT_START);
1973 else
1975 /* Compute <address> + 4 for the high order load. */
1977 operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
1979 /* If the computed address is held in the low order register
1980 then load the high order register first, otherwise always
1981 load the low order register first. */
1983 if (REGNO (operands[0]) == REGNO (base))
1985 output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
1986 output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
1988 else
1990 output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
1991 output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
1994 break;
1996 case LABEL_REF:
1997 /* With no registers to worry about we can just load the value directly. */
1998 operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
2000 output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
2001 output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
2002 break;
2004 default:
2005 debug_rtx (operands[1]);
2006 fatal ("thumb_load_double_from_address: Unhandled address calculation");
2007 break;
2010 return "";
2013 char *
2014 output_move_mem_multiple (n, operands)
2015 int n;
2016 rtx *operands;
2018 rtx tmp;
2020 switch (n)
2022 case 2:
2023 if (REGNO (operands[2]) > REGNO (operands[3]))
2025 tmp = operands[2];
2026 operands[2] = operands[3];
2027 operands[3] = tmp;
2029 output_asm_insn ("ldmia\t%1!, {%2, %3}", operands);
2030 output_asm_insn ("stmia\t%0!, {%2, %3}", operands);
2031 break;
2033 case 3:
2034 if (REGNO (operands[2]) > REGNO (operands[3]))
2036 tmp = operands[2];
2037 operands[2] = operands[3];
2038 operands[3] = tmp;
2040 if (REGNO (operands[3]) > REGNO (operands[4]))
2042 tmp = operands[3];
2043 operands[3] = operands[4];
2044 operands[4] = tmp;
2046 if (REGNO (operands[2]) > REGNO (operands[3]))
2048 tmp = operands[2];
2049 operands[2] = operands[3];
2050 operands[3] = tmp;
2052 output_asm_insn ("ldmia\t%1!, {%2, %3, %4}", operands);
2053 output_asm_insn ("stmia\t%0!, {%2, %3, %4}", operands);
2054 break;
2056 default:
2057 abort ();
2060 return "";
2065 thumb_epilogue_size ()
2067 return 42; /* The answer to .... */
2070 static char *conds[] =
2072 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
2073 "hi", "ls", "ge", "lt", "gt", "le"
2076 static char *
2077 thumb_condition_code (x, invert)
2078 rtx x;
2079 int invert;
2081 int val;
2083 switch (GET_CODE (x))
2085 case EQ: val = 0; break;
2086 case NE: val = 1; break;
2087 case GEU: val = 2; break;
2088 case LTU: val = 3; break;
2089 case GTU: val = 8; break;
2090 case LEU: val = 9; break;
2091 case GE: val = 10; break;
2092 case LT: val = 11; break;
2093 case GT: val = 12; break;
2094 case LE: val = 13; break;
2095 default:
2096 abort ();
2099 return conds[val ^ invert];
2102 void
2103 thumb_print_operand (f, x, code)
2104 FILE *f;
2105 rtx x;
2106 int code;
2108 if (code)
2110 switch (code)
2112 case '@':
2113 fputs (ASM_COMMENT_START, f);
2114 return;
2116 case '|':
2117 /* fputs (REGISTER_PREFIX, f); */
2118 return;
2120 case '_':
2121 fputs (user_label_prefix, f);
2122 return;
2124 case 'D':
2125 if (x)
2126 fputs (thumb_condition_code (x, 1), f);
2127 return;
2129 case 'd':
2130 if (x)
2131 fputs (thumb_condition_code (x, 0), f);
2132 return;
2134 /* An explanation of the 'Q', 'R' and 'H' register operands:
2136 In a pair of registers containing a DI or DF value the 'Q'
2137 operand returns the register number of the register containing
2138 the least signficant part of the value. The 'R' operand returns
2139 the register number of the register containing the most
2140 significant part of the value.
2142 The 'H' operand returns the higher of the two register numbers.
2143 On a run where WORDS_BIG_ENDIAN is true the 'H' operand is the
2144 same as the 'Q' operand, since the most signficant part of the
2145 value is held in the lower number register. The reverse is true
2146 on systems where WORDS_BIG_ENDIAN is false.
2148 The purpose of these operands is to distinguish between cases
2149 where the endian-ness of the values is important (for example
2150 when they are added together), and cases where the endian-ness
2151 is irrelevant, but the order of register operations is important.
2152 For example when loading a value from memory into a register
2153 pair, the endian-ness does not matter. Provided that the value
2154 from the lower memory address is put into the lower numbered
2155 register, and the value from the higher address is put into the
2156 higher numbered register, the load will work regardless of whether
2157 the value being loaded is big-wordian or little-wordian. The
2158 order of the two register loads can matter however, if the address
2159 of the memory location is actually held in one of the registers
2160 being overwritten by the load. */
2161 case 'Q':
2162 if (REGNO (x) > 15)
2163 abort ();
2164 fputs (reg_names[REGNO (x) + (WORDS_BIG_ENDIAN ? 1 : 0)], f);
2165 return;
2167 case 'R':
2168 if (REGNO (x) > 15)
2169 abort ();
2170 fputs (reg_names[REGNO (x) + (WORDS_BIG_ENDIAN ? 0 : 1)], f);
2171 return;
2173 case 'H':
2174 if (REGNO (x) > 15)
2175 abort ();
2176 fputs (reg_names[REGNO (x) + 1], f);
2177 return;
2179 default:
2180 abort ();
2183 if (GET_CODE (x) == REG)
2184 fputs (reg_names[REGNO (x)], f);
2185 else if (GET_CODE (x) == MEM)
2186 output_address (XEXP (x, 0));
2187 else if (GET_CODE (x) == CONST_INT)
2189 fputc ('#', f);
2190 output_addr_const (f, x);
2192 else
2193 abort ();
2196 #ifdef AOF_ASSEMBLER
2197 int arm_text_section_count = 1;
2199 char *
2200 aof_text_section (in_readonly)
2201 int in_readonly;
2203 static char buf[100];
2204 if (in_readonly)
2205 return "";
2206 sprintf (buf, "\tCODE16\n\tAREA |C$$code%d|, CODE, READONLY",
2207 arm_text_section_count++);
2208 return buf;
2211 static int arm_data_section_count = 1;
2213 char *
2214 aof_data_section ()
2216 static char buf[100];
2217 sprintf (buf, "\tAREA |C$$data%d|, DATA", arm_data_section_count++);
2218 return buf;
2221 /* The AOF thumb assembler is religiously strict about declarations of
2222 imported and exported symbols, so that it is impossible to declare a
2223 function as imported near the begining of the file, and then to export
2224 it later on. It is, however, possible to delay the decision until all
2225 the functions in the file have been compiled. To get around this, we
2226 maintain a list of the imports and exports, and delete from it any that
2227 are subsequently defined. At the end of compilation we spit the
2228 remainder of the list out before the END directive. */
2230 struct import
2232 struct import *next;
2233 char *name;
2236 static struct import *imports_list = NULL;
2238 void
2239 thumb_aof_add_import (name)
2240 char *name;
2242 struct import *new;
2244 for (new = imports_list; new; new = new->next)
2245 if (new->name == name)
2246 return;
2248 new = (struct import *) xmalloc (sizeof (struct import));
2249 new->next = imports_list;
2250 imports_list = new;
2251 new->name = name;
2254 void
2255 thumb_aof_delete_import (name)
2256 char *name;
2258 struct import **old;
2260 for (old = &imports_list; *old; old = & (*old)->next)
2262 if ((*old)->name == name)
2264 *old = (*old)->next;
2265 return;
2270 void
2271 thumb_aof_dump_imports (f)
2272 FILE *f;
2274 while (imports_list)
2276 fprintf (f, "\tIMPORT\t");
2277 assemble_name (f, imports_list->name);
2278 fputc ('\n', f);
2279 imports_list = imports_list->next;
2282 #endif
2284 /* Decide whether a type should be returned in memory (true)
2285 or in a register (false). This is called by the macro
2286 RETURN_IN_MEMORY. */
2289 thumb_return_in_memory (type)
2290 tree type;
2292 if (! AGGREGATE_TYPE_P (type))
2294 /* All simple types are returned in registers. */
2296 return 0;
2298 else if (int_size_in_bytes (type) > 4)
2300 /* All structures/unions bigger than one word are returned in memory. */
2302 return 1;
2304 else if (TREE_CODE (type) == RECORD_TYPE)
2306 tree field;
2308 /* For a struct the APCS says that we must return in a register if
2309 every addressable element has an offset of zero. For practical
2310 purposes this means that the structure can have at most one non-
2311 bit-field element and that this element must be the first one in
2312 the structure. */
2314 /* Find the first field, ignoring non FIELD_DECL things which will
2315 have been created by C++. */
2316 for (field = TYPE_FIELDS (type);
2317 field && TREE_CODE (field) != FIELD_DECL;
2318 field = TREE_CHAIN (field))
2319 continue;
2321 if (field == NULL)
2322 return 0; /* An empty structure. Allowed by an extension to ANSI C. */
2324 /* Now check the remaining fields, if any. */
2325 for (field = TREE_CHAIN (field); field; field = TREE_CHAIN (field))
2327 if (TREE_CODE (field) != FIELD_DECL)
2328 continue;
2330 if (! DECL_BIT_FIELD_TYPE (field))
2331 return 1;
2334 return 0;
2336 else if (TREE_CODE (type) == UNION_TYPE)
2338 tree field;
2340 /* Unions can be returned in registers if every element is
2341 integral, or can be returned in an integer register. */
2343 for (field = TYPE_FIELDS (type);
2344 field;
2345 field = TREE_CHAIN (field))
2347 if (TREE_CODE (field) != FIELD_DECL)
2348 continue;
2350 if (RETURN_IN_MEMORY (TREE_TYPE (field)))
2351 return 1;
2354 return 0;
2356 /* XXX Not sure what should be done for other aggregates, so put them in
2357 memory. */
2358 return 1;
2361 void
2362 thumb_override_options ()
2364 if (structure_size_string != NULL)
2366 int size = strtol (structure_size_string, NULL, 0);
2368 if (size == 8 || size == 32)
2369 arm_structure_size_boundary = size;
2370 else
2371 warning ("Structure size boundary can only be set to 8 or 32");
2374 if (thumb_pic_register_string != NULL)
2376 int pic_register;
2378 if (! flag_pic)
2379 warning ("-mpic-register= is useless without -fpic");
2381 pic_register = decode_reg_name (thumb_pic_register_string);
2383 /* Prevent the user from choosing an obviously stupid PIC register. */
2384 if (pic_register < 0 || call_used_regs[pic_register]
2385 || pic_register == HARD_FRAME_POINTER_REGNUM
2386 || pic_register == STACK_POINTER_REGNUM
2387 || pic_register >= PC_REGNUM)
2388 error ("Unable to use '%s' for PIC register", thumb_pic_register_string);
2389 else
2390 thumb_pic_register = pic_register;
2394 #ifdef THUMB_PE
2395 /* Return nonzero if ATTR is a valid attribute for DECL.
2396 ATTRIBUTES are any existing attributes and ARGS are the arguments
2397 supplied with ATTR.
2399 Supported attributes:
2401 naked: don't output any prologue or epilogue code, the user is assumed
2402 to do the right thing.
2404 interfacearm: Always assume that this function will be entered in ARM
2405 mode, not Thumb mode, and that the caller wishes to be returned to in
2406 ARM mode. */
2408 arm_valid_machine_decl_attribute (decl, attr, args)
2409 tree decl;
2410 tree attr;
2411 tree args;
2413 if (args != NULL_TREE)
2414 return 0;
2416 if (is_attribute_p ("naked", attr))
2417 if (TREE_CODE (decl) == FUNCTION_DECL)
2418 return 1;
2420 if (is_attribute_p ("interfacearm", attr))
2421 return TREE_CODE (decl) == FUNCTION_DECL;
2423 return 0;
2425 #endif /* THUMB_PE */