update copyrights in config dir.
[official-gcc.git] / gcc / config / arm / thumb.c
blobfcc84418b11f1aa355c8345d5542824f7c2c3801
1 /* Output routines for GCC for ARM/Thumb
2 Copyright (C) 1996 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 <stdio.h>
24 #include <string.h>
25 #include "config.h"
26 #include "rtl.h"
27 #include "hard-reg-set.h"
28 #include "regs.h"
29 #include "output.h"
30 #include "insn-flags.h"
31 #include "insn-attr.h"
32 #include "flags.h"
33 #include "tree.h"
34 #include "function.h"
35 #include "expr.h"
36 #include "insn-config.h"
37 #include "recog.h"
38 #include "toplev.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
497 fixit (src, mode)
498 rtx src;
499 enum machine_mode mode;
501 #ifndef AOF_ASSEMBLER
502 if (GET_CODE (src) == UNSPEC && XINT (src, 1) == 3)
503 return 1;
504 #endif
505 return ((CONSTANT_P (src)
506 && (GET_CODE (src) != CONST_INT
507 || ! (CONST_OK_FOR_LETTER_P (INTVAL (src), 'I')
508 || CONST_OK_FOR_LETTER_P (INTVAL (src), 'J')
509 || (mode != DImode
510 && CONST_OK_FOR_LETTER_P (INTVAL (src), 'K')))))
511 || (mode == SImode && GET_CODE (src) == MEM
512 && GET_CODE (XEXP (src, 0)) == SYMBOL_REF
513 && CONSTANT_POOL_ADDRESS_P (XEXP (src, 0))));
516 /* Find the last barrier less than MAX_COUNT bytes from FROM, or create one. */
518 #define MAX_COUNT_SI 1000
520 static rtx
521 find_barrier (from)
522 rtx from;
524 int count = 0;
525 rtx found_barrier = 0;
526 rtx label;
528 while (from && count < MAX_COUNT_SI)
530 if (GET_CODE (from) == BARRIER)
531 return from;
533 /* Count the length of this insn */
534 if (GET_CODE (from) == INSN
535 && GET_CODE (PATTERN (from)) == SET
536 && CONSTANT_P (SET_SRC (PATTERN (from)))
537 && CONSTANT_POOL_ADDRESS_P (SET_SRC (PATTERN (from))))
538 count += 2;
539 else
540 count += get_attr_length (from);
542 from = NEXT_INSN (from);
545 /* We didn't find a barrier in time to
546 dump our stuff, so we'll make one */
547 label = gen_label_rtx ();
549 if (from)
550 from = PREV_INSN (from);
551 else
552 from = get_last_insn ();
554 /* Walk back to be just before any jump */
555 while (GET_CODE (from) == JUMP_INSN
556 || GET_CODE (from) == NOTE
557 || GET_CODE (from) == CODE_LABEL)
558 from = PREV_INSN (from);
560 from = emit_jump_insn_after (gen_jump (label), from);
561 JUMP_LABEL (from) = label;
562 found_barrier = emit_barrier_after (from);
563 emit_label_after (label, found_barrier);
564 return found_barrier;
567 /* Non zero if the insn is a move instruction which needs to be fixed. */
569 static int
570 broken_move (insn)
571 rtx insn;
573 if (!INSN_DELETED_P (insn)
574 && GET_CODE (insn) == INSN
575 && GET_CODE (PATTERN (insn)) == SET)
577 rtx pat = PATTERN (insn);
578 rtx src = SET_SRC (pat);
579 rtx dst = SET_DEST (pat);
580 enum machine_mode mode = GET_MODE (dst);
581 if (dst == pc_rtx)
582 return 0;
583 return fixit (src, mode);
585 return 0;
588 /* Recursively search through all of the blocks in a function
589 checking to see if any of the variables created in that
590 function match the RTX called 'orig'. If they do then
591 replace them with the RTX called 'new'. */
593 static void
594 replace_symbols_in_block (tree block, rtx orig, rtx new)
596 for (; block; block = BLOCK_CHAIN (block))
598 tree sym;
600 if (! TREE_USED (block))
601 continue;
603 for (sym = BLOCK_VARS (block); sym; sym = TREE_CHAIN (sym))
605 if ( (DECL_NAME (sym) == 0 && TREE_CODE (sym) != TYPE_DECL)
606 || DECL_IGNORED_P (sym)
607 || TREE_CODE (sym) != VAR_DECL
608 || DECL_EXTERNAL (sym)
609 || ! rtx_equal_p (DECL_RTL (sym), orig)
611 continue;
613 DECL_RTL (sym) = new;
616 replace_symbols_in_block (BLOCK_SUBBLOCKS (block), orig, new);
620 void
621 thumb_reorg (first)
622 rtx first;
624 rtx insn;
626 for (insn = first; insn; insn = NEXT_INSN (insn))
628 if (broken_move (insn))
630 /* This is a broken move instruction, scan ahead looking for
631 a barrier to stick the constant table behind */
632 rtx scan;
633 rtx barrier = find_barrier (insn);
635 /* Now find all the moves between the points and modify them */
636 for (scan = insn; scan != barrier; scan = NEXT_INSN (scan))
638 if (broken_move (scan))
640 /* This is a broken move instruction, add it to the pool */
641 rtx pat = PATTERN (scan);
642 rtx src = SET_SRC (pat);
643 rtx dst = SET_DEST (pat);
644 enum machine_mode mode = GET_MODE (dst);
645 HOST_WIDE_INT offset;
646 rtx newinsn;
647 rtx newsrc;
649 /* If this is an HImode constant load, convert it into
650 an SImode constant load. Since the register is always
651 32 bits this is safe. We have to do this, since the
652 load pc-relative instruction only does a 32-bit load. */
653 if (mode == HImode)
655 mode = SImode;
656 if (GET_CODE (dst) != REG)
657 abort ();
658 PUT_MODE (dst, SImode);
661 offset = add_constant (src, mode);
662 newsrc = gen_rtx (MEM, mode,
663 plus_constant (gen_rtx (LABEL_REF,
664 VOIDmode,
665 pool_vector_label),
666 offset));
668 /* Build a jump insn wrapper around the move instead
669 of an ordinary insn, because we want to have room for
670 the target label rtx in fld[7], which an ordinary
671 insn doesn't have. */
672 newinsn = emit_jump_insn_after (gen_rtx (SET, VOIDmode,
673 dst, newsrc), scan);
674 JUMP_LABEL (newinsn) = pool_vector_label;
676 /* But it's still an ordinary insn */
677 PUT_CODE (newinsn, INSN);
679 /* If debugging information is going to be emitted
680 then we must make sure that any refences to
681 symbols which are removed by the above code are
682 also removed in the descriptions of the
683 function's variables. Failure to do this means
684 that the debugging information emitted could
685 refer to symbols which are not emited by
686 output_constant_pool() because
687 mark_constant_pool() never sees them as being
688 used. */
690 /* These are the tests used in
691 output_constant_pool() to decide if the constant
692 pool will be marked. Only necessary if debugging
693 info is being emitted. Only necessary for
694 references to memory whose address is given by a
695 symbol. */
697 if (optimize > 0
698 && flag_expensive_optimizations
699 && write_symbols != NO_DEBUG
700 && GET_CODE (src) == MEM
701 && GET_CODE (XEXP (src, 0)) == SYMBOL_REF)
702 replace_symbols_in_block
703 (DECL_INITIAL (current_function_decl), src, newsrc);
705 /* Kill old insn */
706 delete_insn (scan);
707 scan = newinsn;
710 dump_table (barrier);
716 /* Routines for generating rtl */
718 void
719 thumb_expand_movstrqi (operands)
720 rtx *operands;
722 rtx out = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
723 rtx in = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
724 HOST_WIDE_INT len = INTVAL (operands[2]);
725 HOST_WIDE_INT offset = 0;
727 while (len >= 12)
729 emit_insn (gen_movmem12b (out, in));
730 len -= 12;
732 if (len >= 8)
734 emit_insn (gen_movmem8b (out, in));
735 len -= 8;
737 if (len >= 4)
739 rtx reg = gen_reg_rtx (SImode);
740 emit_insn (gen_movsi (reg, gen_rtx (MEM, SImode, in)));
741 emit_insn (gen_movsi (gen_rtx (MEM, SImode, out), reg));
742 len -= 4;
743 offset += 4;
745 if (len >= 2)
747 rtx reg = gen_reg_rtx (HImode);
748 emit_insn (gen_movhi (reg, gen_rtx (MEM, HImode,
749 plus_constant (in, offset))));
750 emit_insn (gen_movhi (gen_rtx (MEM, HImode, plus_constant (out, offset)),
751 reg));
752 len -= 2;
753 offset += 2;
755 if (len)
757 rtx reg = gen_reg_rtx (QImode);
758 emit_insn (gen_movqi (reg, gen_rtx (MEM, QImode,
759 plus_constant (in, offset))));
760 emit_insn (gen_movqi (gen_rtx (MEM, QImode, plus_constant (out, offset)),
761 reg));
766 /* Routines for reloading */
768 void
769 thumb_reload_out_si (operands)
770 rtx operands ATTRIBUTE_UNUSED;
772 abort ();
776 #ifdef THUMB_PE
777 /* Return non-zero if FUNC is a naked function. */
779 static int
780 arm_naked_function_p (func)
781 tree func;
783 tree a;
785 if (TREE_CODE (func) != FUNCTION_DECL)
786 abort ();
788 a = lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (func));
789 return a != NULL_TREE;
791 #endif
793 /* Return non-zero if FUNC must be entered in ARM mode. */
795 is_called_in_ARM_mode (func)
796 tree func;
798 if (TREE_CODE (func) != FUNCTION_DECL)
799 abort ();
801 /* Ignore the problem about functions whoes address is taken. */
802 if (TARGET_CALLEE_INTERWORKING && TREE_PUBLIC (func))
803 return TRUE;
805 #ifdef THUMB_PE
806 return lookup_attribute ("interfacearm", DECL_MACHINE_ATTRIBUTES (func)) != NULL_TREE;
807 #else
808 return FALSE;
809 #endif
813 /* Routines for emitting code */
815 void
816 thumb_final_prescan_insn (insn)
817 rtx insn;
819 extern int * insn_addresses;
821 if (flag_print_asm_name)
822 fprintf (asm_out_file, "%s 0x%04x\n", ASM_COMMENT_START,
823 insn_addresses[INSN_UID (insn)]);
827 static void thumb_pushpop ( FILE *, int, int ); /* Forward declaration. */
829 #ifdef __GNUC__
830 inline
831 #endif
832 static int
833 number_of_first_bit_set (mask)
834 int mask;
836 int bit;
838 for (bit = 0;
839 (mask & (1 << bit)) == 0;
840 ++ bit)
841 continue;
843 return bit;
846 #define ARG_1_REGISTER 0
847 #define ARG_2_REGISTER 1
848 #define ARG_3_REGISTER 2
849 #define ARG_4_REGISTER 3
850 #define WORK_REGISTER 7
851 #define FRAME_POINTER 11
852 #define IP_REGISTER 12
853 #define STACK_POINTER STACK_POINTER_REGNUM
854 #define LINK_REGISTER 14
855 #define PROGRAM_COUNTER 15
857 /* Generate code to return from a thumb function. If
858 'reg_containing_return_addr' is -1, then the return address is
859 actually on the stack, at the stack pointer. */
860 static void
861 thumb_exit (f, reg_containing_return_addr)
862 FILE * f;
863 int reg_containing_return_addr;
865 int regs_available_for_popping;
866 int regs_to_pop;
867 int pops_needed;
868 int available;
869 int required;
870 int mode;
871 int size;
872 int restore_a4 = FALSE;
874 /* Compute the registers we need to pop. */
875 regs_to_pop = 0;
876 pops_needed = 0;
878 if (reg_containing_return_addr == -1)
880 regs_to_pop |= 1 << LINK_REGISTER;
881 ++ pops_needed;
884 if (TARGET_BACKTRACE)
886 /* Restore frame pointer and stack pointer. */
887 regs_to_pop |= (1 << FRAME_POINTER) | (1 << STACK_POINTER);
888 pops_needed += 2;
891 /* If there is nothing to pop then just emit the BX instruction and return.*/
892 if (pops_needed == 0)
894 asm_fprintf (f, "\tbx\t%s\n", reg_names [reg_containing_return_addr]);
896 return;
899 /* Otherwise if we are not supporting interworking and we have not created
900 a backtrace structure and the function was not entered in ARM mode then
901 just pop the return address straight into the PC. */
902 else if ( ! TARGET_THUMB_INTERWORK
903 && ! TARGET_BACKTRACE
904 && ! is_called_in_ARM_mode (current_function_decl))
906 asm_fprintf (f, "\tpop\t{pc}\n" );
908 return;
911 /* Find out how many of the (return) argument registers we can corrupt. */
912 regs_available_for_popping = 0;
914 #ifdef RTX_CODE
915 /* If we can deduce the registers used from the function's return value.
916 This is more reliable that examining regs_ever_live[] because that
917 will be set if the register is ever used in the function, not just if
918 the register is used to hold a return value. */
920 if (current_function_return_rtx != 0)
921 mode = GET_MODE (current_function_return_rtx);
922 else
923 #endif
924 mode = DECL_MODE (DECL_RESULT (current_function_decl));
926 size = GET_MODE_SIZE (mode);
928 if (size == 0)
930 /* In a void function we can use any argument register.
931 In a function that returns a structure on the stack
932 we can use the second and third argument registers. */
933 if (mode == VOIDmode)
934 regs_available_for_popping =
935 (1 << ARG_1_REGISTER)
936 | (1 << ARG_2_REGISTER)
937 | (1 << ARG_3_REGISTER);
938 else
939 regs_available_for_popping =
940 (1 << ARG_2_REGISTER)
941 | (1 << ARG_3_REGISTER);
943 else if (size <= 4) regs_available_for_popping =
944 (1 << ARG_2_REGISTER)
945 | (1 << ARG_3_REGISTER);
946 else if (size <= 8) regs_available_for_popping =
947 (1 << ARG_3_REGISTER);
949 /* Match registers to be popped with registers into which we pop them. */
950 for (available = regs_available_for_popping,
951 required = regs_to_pop;
952 required != 0 && available != 0;
953 available &= ~(available & - available),
954 required &= ~(required & - required))
955 -- pops_needed;
957 /* If we have any popping registers left over, remove them. */
958 if (available > 0)
959 regs_available_for_popping &= ~ available;
961 /* Otherwise if we need another popping register we can use
962 the fourth argument register. */
963 else if (pops_needed)
965 /* If we have not found any free argument registers and
966 reg a4 contains the return address, we must move it. */
967 if (regs_available_for_popping == 0
968 && reg_containing_return_addr == ARG_4_REGISTER)
970 asm_fprintf (f, "\tmov\t%s, %s\n",
971 reg_names [LINK_REGISTER], reg_names [ARG_4_REGISTER]);
972 reg_containing_return_addr = LINK_REGISTER;
974 else if (size > 12)
976 /* Register a4 is being used to hold part of the return value,
977 but we have dire need of a free, low register. */
978 restore_a4 = TRUE;
980 asm_fprintf (f, "\tmov\t%s, %s\n",
981 reg_names [IP_REGISTER], reg_names [ARG_4_REGISTER]);
984 if (reg_containing_return_addr != ARG_4_REGISTER)
986 /* The fourth argument register is available. */
987 regs_available_for_popping |= 1 << ARG_4_REGISTER;
989 -- pops_needed;
993 /* Pop as many registers as we can. */
994 thumb_pushpop (f, regs_available_for_popping, FALSE);
996 /* Process the registers we popped. */
997 if (reg_containing_return_addr == -1)
999 /* The return address was popped into the lowest numbered register. */
1000 regs_to_pop &= ~ (1 << LINK_REGISTER);
1002 reg_containing_return_addr =
1003 number_of_first_bit_set (regs_available_for_popping);
1005 /* Remove this register for the mask of available registers, so that
1006 the return address will not be corrupted by futher pops. */
1007 regs_available_for_popping &= ~ (1 << reg_containing_return_addr);
1010 /* If we popped other registers then handle them here. */
1011 if (regs_available_for_popping)
1013 int frame_pointer;
1015 /* Work out which register currently contains the frame pointer. */
1016 frame_pointer = number_of_first_bit_set (regs_available_for_popping);
1018 /* Move it into the correct place. */
1019 asm_fprintf (f, "\tmov\tfp, %s\n", reg_names [frame_pointer]);
1021 /* (Temporarily) remove it from the mask of popped registers. */
1022 regs_available_for_popping &= ~ (1 << frame_pointer);
1023 regs_to_pop &= ~ (1 << FRAME_POINTER);
1025 if (regs_available_for_popping)
1027 int stack_pointer;
1029 /* We popped the stack pointer as well, find the register that
1030 contains it.*/
1031 stack_pointer = number_of_first_bit_set (regs_available_for_popping);
1033 /* Move it into the stack register. */
1034 asm_fprintf (f, "\tmov\tsp, %s\n", reg_names [stack_pointer]);
1036 /* At this point we have popped all necessary registers, so
1037 do not worry about restoring regs_available_for_popping
1038 to its correct value:
1040 assert (pops_needed == 0)
1041 assert (regs_available_for_popping == (1 << frame_pointer))
1042 assert (regs_to_pop == (1 << STACK_POINTER)) */
1044 else
1046 /* Since we have just move the popped value into the frame
1047 pointer, the popping register is available for reuse, and
1048 we know that we still have the stack pointer left to pop. */
1049 regs_available_for_popping |= (1 << frame_pointer);
1053 /* If we still have registers left on the stack, but we no longer have
1054 any registers into which we can pop them, then we must move the return
1055 address into the link register and make available the register that
1056 contained it. */
1057 if (regs_available_for_popping == 0 && pops_needed > 0)
1059 regs_available_for_popping |= 1 << reg_containing_return_addr;
1061 asm_fprintf (f, "\tmov\t%s, %s\n",
1062 reg_names [LINK_REGISTER],
1063 reg_names [reg_containing_return_addr]);
1065 reg_containing_return_addr = LINK_REGISTER;
1068 /* If we have registers left on the stack then pop some more.
1069 We know that at most we will want to pop FP and SP. */
1070 if (pops_needed > 0)
1072 int popped_into;
1073 int move_to;
1075 thumb_pushpop (f, regs_available_for_popping, FALSE);
1077 /* We have popped either FP or SP.
1078 Move whichever one it is into the correct register. */
1079 popped_into = number_of_first_bit_set (regs_available_for_popping);
1080 move_to = number_of_first_bit_set (regs_to_pop);
1082 asm_fprintf (f, "\tmov\t%s, %s\n",
1083 reg_names [move_to], reg_names [popped_into]);
1085 regs_to_pop &= ~ (1 << move_to);
1087 -- pops_needed;
1090 /* If we still have not popped everything then we must have only
1091 had one register available to us and we are now popping the SP. */
1092 if (pops_needed > 0)
1094 int popped_into;
1096 thumb_pushpop (f, regs_available_for_popping, FALSE);
1098 popped_into = number_of_first_bit_set (regs_available_for_popping);
1100 asm_fprintf (f, "\tmov\tsp, %s\n", reg_names [popped_into]);
1103 assert (regs_to_pop == (1 << STACK_POINTER))
1104 assert (pops_needed == 1)
1108 /* If necessary restore the a4 register. */
1109 if (restore_a4)
1111 if (reg_containing_return_addr != LINK_REGISTER)
1113 asm_fprintf (f, "\tmov\t%s, %s\n",
1114 reg_names [LINK_REGISTER], reg_names [ARG_4_REGISTER]);
1115 reg_containing_return_addr = LINK_REGISTER;
1118 asm_fprintf (f, "\tmov\t%s, %s\n",
1119 reg_names [ARG_4_REGISTER], reg_names [IP_REGISTER]);
1122 /* Return to caller. */
1123 asm_fprintf (f, "\tbx\t%s\n", reg_names [reg_containing_return_addr]);
1126 /* Emit code to push or pop registers to or from the stack. */
1127 static void
1128 thumb_pushpop (f, mask, push)
1129 FILE * f;
1130 int mask;
1131 int push;
1133 int regno;
1134 int lo_mask = mask & 0xFF;
1136 if (lo_mask == 0 && ! push && (mask & (1 << 15)))
1138 /* Special case. Do not generate a POP PC statement here, do it in
1139 thumb_exit() */
1141 thumb_exit (f, -1);
1142 return;
1145 asm_fprintf (f, "\t%s\t{", push ? "push" : "pop");
1147 /* Look at the low registers first. */
1149 for (regno = 0; regno < 8; regno ++, lo_mask >>= 1)
1151 if (lo_mask & 1)
1153 asm_fprintf (f, reg_names[regno]);
1155 if ((lo_mask & ~1) != 0)
1156 asm_fprintf (f, ", ");
1160 if (push && (mask & (1 << 14)))
1162 /* Catch pushing the LR. */
1164 if (mask & 0xFF)
1165 asm_fprintf (f, ", ");
1167 asm_fprintf (f, reg_names[14]);
1169 else if (!push && (mask & (1 << 15)))
1171 /* Catch popping the PC. */
1173 if (TARGET_THUMB_INTERWORK || TARGET_BACKTRACE)
1175 /* The PC is never poped directly, instead
1176 it is popped into r3 and then BX is used. */
1178 asm_fprintf (f, "}\n");
1180 thumb_exit (f, -1);
1182 return;
1184 else
1186 if (mask & 0xFF)
1187 asm_fprintf (f, ", ");
1189 asm_fprintf (f, reg_names[15]);
1193 asm_fprintf (f, "}\n");
1196 /* Returns non-zero if the current function contains a far jump */
1199 far_jump_used_p (void)
1201 rtx insn;
1203 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
1205 if (GET_CODE (insn) == JUMP_INSN
1206 /* Ignore tablejump patterns. */
1207 && GET_CODE (PATTERN (insn)) != ADDR_VEC
1208 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
1209 && get_attr_far_jump (insn) == FAR_JUMP_YES)
1210 return 1;
1213 return 0;
1216 static int return_used_this_function = 0;
1218 char *
1219 output_return ()
1221 int regno;
1222 int live_regs_mask = 0;
1224 #ifdef THUMB_PE
1225 /* If a function is naked, don't use the "return" insn. */
1226 if (arm_naked_function_p (current_function_decl))
1227 return "";
1228 #endif
1230 return_used_this_function = 1;
1232 for (regno = 0; regno < 8; regno++)
1233 if (regs_ever_live[regno] && ! call_used_regs[regno]
1234 && ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
1235 live_regs_mask |= 1 << regno;
1237 if (live_regs_mask == 0)
1239 if (leaf_function_p () && ! far_jump_used_p())
1241 thumb_exit (asm_out_file, 14);
1243 else if ( TARGET_THUMB_INTERWORK
1244 || TARGET_BACKTRACE
1245 || is_called_in_ARM_mode (current_function_decl))
1247 thumb_exit (asm_out_file, -1);
1249 else
1250 asm_fprintf (asm_out_file, "\tpop\t{pc}\n");
1252 else
1254 asm_fprintf (asm_out_file, "\tpop\t{");
1256 for (regno = 0; live_regs_mask; regno ++, live_regs_mask >>= 1)
1257 if (live_regs_mask & 1)
1259 asm_fprintf (asm_out_file, reg_names[regno]);
1260 if (live_regs_mask & ~1)
1261 asm_fprintf (asm_out_file, ", ");
1264 if ( TARGET_THUMB_INTERWORK
1265 || TARGET_BACKTRACE
1266 || is_called_in_ARM_mode (current_function_decl))
1268 asm_fprintf (asm_out_file, "}\n");
1269 thumb_exit (asm_out_file, -1);
1271 else
1272 asm_fprintf (asm_out_file, ", pc}\n");
1275 return "";
1278 void
1279 thumb_function_prologue (f, frame_size)
1280 FILE * f;
1281 int frame_size ATTRIBUTE_UNUSED;
1283 int live_regs_mask = 0;
1284 int high_regs_pushed = 0;
1285 int store_arg_regs = 0;
1286 int regno;
1288 #ifdef THUMB_PE
1289 if (arm_naked_function_p (current_function_decl))
1290 return;
1291 #endif
1293 if (is_called_in_ARM_mode (current_function_decl))
1295 char * name;
1297 if (GET_CODE (DECL_RTL (current_function_decl)) != MEM)
1298 abort();
1299 if (GET_CODE (XEXP (DECL_RTL (current_function_decl), 0)) != SYMBOL_REF)
1300 abort();
1301 name = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
1303 /* Generate code sequence to switch us into Thumb mode. */
1304 /* The .code 32 directive has already been emitted by
1305 ASM_DECLARE_FUNCITON_NAME */
1306 asm_fprintf (f, "\torr\tr12, pc, #1\n");
1307 asm_fprintf (f, "\tbx\tr12\n");
1309 /* Generate a label, so that the debugger will notice the
1310 change in instruction sets. This label is also used by
1311 the assembler to bypass the ARM code when this function
1312 is called from a Thumb encoded function elsewhere in the
1313 same file. Hence the definition of STUB_NAME here must
1314 agree with the definition in gas/config/tc-arm.c */
1316 #define STUB_NAME ".real_start_of"
1318 asm_fprintf (f, "\t.code\t16\n");
1320 #ifdef THUMB_PE
1321 if (arm_dllexport_name_p (name))
1322 name = ARM_STRIP_NAME_ENCODING (name);
1323 #endif
1325 asm_fprintf (f, "\t.globl %s%U%s\n", STUB_NAME, name);
1326 asm_fprintf (f, "\t.thumb_func\n");
1327 asm_fprintf (f, "%s%U%s:\n", STUB_NAME, name);
1330 if (current_function_anonymous_args && current_function_pretend_args_size)
1331 store_arg_regs = 1;
1333 if (current_function_pretend_args_size)
1335 if (store_arg_regs)
1337 asm_fprintf (f, "\tpush\t{");
1338 for (regno = 4 - current_function_pretend_args_size / 4 ; regno < 4;
1339 regno++)
1340 asm_fprintf (f, "%s%s", reg_names[regno], regno == 3 ? "" : ", ");
1341 asm_fprintf (f, "}\n");
1343 else
1344 asm_fprintf (f, "\tsub\t%Rsp, %Rsp, #%d\n",
1345 current_function_pretend_args_size);
1348 for (regno = 0; regno < 8; regno++)
1349 if (regs_ever_live[regno] && ! call_used_regs[regno]
1350 && ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
1351 live_regs_mask |= 1 << regno;
1353 if (live_regs_mask || ! leaf_function_p () || far_jump_used_p ())
1354 live_regs_mask |= 1 << 14;
1356 if (TARGET_BACKTRACE)
1358 char * name;
1359 int offset;
1360 int work_register = 0;
1362 /* We have been asked to create a stack backtrace structure.
1363 The code looks like this:
1365 0 .align 2
1366 0 func:
1367 0 sub SP, #16 Reserve space for 4 registers.
1368 2 push {R7} Get a work register.
1369 4 add R7, SP, #20 Get the stack pointer before the push.
1370 6 str R7, [SP, #8] Store the stack pointer (before reserving the space).
1371 8 mov R7, PC Get hold of the start of this code plus 12.
1372 10 str R7, [SP, #16] Store it.
1373 12 mov R7, FP Get hold of the current frame pointer.
1374 14 str R7, [SP, #4] Store it.
1375 16 mov R7, LR Get hold of the current return address.
1376 18 str R7, [SP, #12] Store it.
1377 20 add R7, SP, #16 Point at the start of the backtrace structure.
1378 22 mov FP, R7 Put this value into the frame pointer. */
1380 if ((live_regs_mask & 0xFF) == 0)
1382 /* See if the a4 register is free. */
1384 if (regs_ever_live [3] == 0)
1385 work_register = 3;
1386 else /* We must push a register of our own */
1387 live_regs_mask |= (1 << 7);
1390 if (work_register == 0)
1392 /* Select a register from the list that will be pushed to use as our work register. */
1394 for (work_register = 8; work_register--;)
1395 if ((1 << work_register) & live_regs_mask)
1396 break;
1399 name = reg_names[ work_register ];
1401 asm_fprintf (f, "\tsub\tsp, sp, #16\t@ Create stack backtrace structure\n");
1403 if (live_regs_mask)
1404 thumb_pushpop (f, live_regs_mask, 1);
1406 for (offset = 0, work_register = 1 << 15; work_register; work_register >>= 1)
1407 if (work_register & live_regs_mask)
1408 offset += 4;
1410 asm_fprintf (f, "\tadd\t%s, sp, #%d\n",
1411 name, offset + 16 + current_function_pretend_args_size);
1413 asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 4);
1415 /* Make sure that the instruction fetching the PC is in the right place
1416 to calculate "start of backtrace creation code + 12". */
1418 if (live_regs_mask)
1420 asm_fprintf (f, "\tmov\t%s, pc\n", name);
1421 asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 12);
1422 asm_fprintf (f, "\tmov\t%s, fp\n", name);
1423 asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset);
1425 else
1427 asm_fprintf (f, "\tmov\t%s, fp\n", name);
1428 asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset);
1429 asm_fprintf (f, "\tmov\t%s, pc\n", name);
1430 asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 12);
1433 asm_fprintf (f, "\tmov\t%s, lr\n", name);
1434 asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 8);
1435 asm_fprintf (f, "\tadd\t%s, sp, #%d\n", name, offset + 12);
1436 asm_fprintf (f, "\tmov\tfp, %s\t\t@ Backtrace structure created\n", name);
1438 else if (live_regs_mask)
1439 thumb_pushpop (f, live_regs_mask, 1);
1441 for (regno = 8; regno < 13; regno++)
1443 if (regs_ever_live[regno] && ! call_used_regs[regno]
1444 && ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
1445 high_regs_pushed++;
1448 if (high_regs_pushed)
1450 int pushable_regs = 0;
1451 int mask = live_regs_mask & 0xff;
1452 int next_hi_reg;
1454 for (next_hi_reg = 12; next_hi_reg > 7; next_hi_reg--)
1456 if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg]
1457 && ! (TARGET_SINGLE_PIC_BASE && (next_hi_reg == thumb_pic_register)))
1458 break;
1461 pushable_regs = mask;
1463 if (pushable_regs == 0)
1465 /* desperation time -- this probably will never happen */
1466 if (regs_ever_live[3] || ! call_used_regs[3])
1467 asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[12], reg_names[3]);
1468 mask = 1 << 3;
1471 while (high_regs_pushed > 0)
1473 for (regno = 7; regno >= 0; regno--)
1475 if (mask & (1 << regno))
1477 asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[regno],
1478 reg_names[next_hi_reg]);
1479 high_regs_pushed--;
1480 if (high_regs_pushed)
1481 for (next_hi_reg--; next_hi_reg > 7; next_hi_reg--)
1483 if (regs_ever_live[next_hi_reg]
1484 && ! call_used_regs[next_hi_reg]
1485 && ! (TARGET_SINGLE_PIC_BASE
1486 && (next_hi_reg == thumb_pic_register)))
1487 break;
1489 else
1491 mask &= ~ ((1 << regno) - 1);
1492 break;
1496 thumb_pushpop (f, mask, 1);
1499 if (pushable_regs == 0 && (regs_ever_live[3] || ! call_used_regs[3]))
1500 asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[3], reg_names[12]);
1504 /* Functions to save and restore thumb_return_addr_rtx. */
1505 static rtx thumb_return_addr_rtx = NULL_RTX;
1507 struct machine_function
1509 rtx ra_rtx;
1512 static void
1513 thumb_save_machine_status (p)
1514 struct function * p;
1516 struct machine_function * machine =
1517 (struct machine_function *) xmalloc (sizeof (* machine));
1519 p->machine = machine;
1520 machine->ra_rtx = thumb_return_addr_rtx;
1523 static void
1524 thumb_restore_machine_status (p)
1525 struct function * p;
1527 struct machine_function * machine = p->machine;
1529 thumb_return_addr_rtx = machine->ra_rtx;
1531 free (machine);
1533 p->machine = (struct machine_function *) NULL;
1536 /* Return an RTX indicating where the return address to the
1537 calling function can be found. */
1539 thumb_return_addr (count)
1540 int count;
1542 if (count != 0)
1543 return NULL_RTX;
1545 if (thumb_return_addr_rtx == NULL_RTX)
1547 rtx init;
1549 thumb_return_addr_rtx = gen_reg_rtx (Pmode);
1551 init = gen_rtx_REG (Pmode, 14);
1553 init = gen_rtx_SET (VOIDmode, thumb_return_addr_rtx, init);
1555 /* Emit the insn to the prologue with the other argument copies. */
1556 push_topmost_sequence ();
1557 emit_insn_after (init, get_insns ());
1558 pop_topmost_sequence ();
1561 return thumb_return_addr_rtx;
1564 /* Do anything needed before RTL is emitted for each function. */
1565 void
1566 thumb_init_expanders ()
1568 thumb_return_addr_rtx = NULL_RTX;
1570 /* Arrange to save and restore machine status around nested functions. */
1571 save_machine_status = thumb_save_machine_status;
1572 restore_machine_status = thumb_restore_machine_status;
1575 void
1576 thumb_expand_prologue ()
1578 HOST_WIDE_INT amount = (get_frame_size ()
1579 + current_function_outgoing_args_size);
1580 #ifdef THUMB_PE
1581 /* Naked functions don't have prologues. */
1582 if (arm_naked_function_p (current_function_decl))
1583 return;
1584 #endif
1586 if (amount)
1588 if (amount < 512)
1589 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
1590 GEN_INT (- amount)));
1591 else
1593 int regno;
1594 rtx reg;
1596 /* The stack decrement is too big for an immediate value in a single
1597 insn. In theory we could issue multiple subtracts, but after
1598 three of them it becomes more space efficient to place the full
1599 value in the constant pool and load into a register. (Also the
1600 ARM debugger really likes to see only one stack decrement per
1601 function). So instead we look for a scratch register into which
1602 we can load the decrement, and then we subtract this from the
1603 stack pointer. Unfortunately on the thumb the only available
1604 scratch registers are the argument registers, and we cannot use
1605 these as they may hold arguments to the function. Instead we
1606 attempt to locate a call preserved register which is used by this
1607 function. If we can find one, then we know that it will have
1608 been pushed at the start of the prologue and so we can corrupt
1609 it now. */
1610 for (regno = 4; regno < 8; regno++)
1611 if (regs_ever_live[regno]
1612 && ! call_used_regs[regno] /* Paranoia */
1613 && ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
1614 break;
1616 if (regno == 8) /* Very unlikely */
1618 rtx spare = gen_rtx (REG, SImode, 12);
1620 /* Choose an arbitary, non-argument low register. */
1621 reg = gen_rtx (REG, SImode, 4);
1623 /* Save it by copying it into a high, scratch register. */
1624 emit_insn (gen_movsi (spare, reg));
1626 /* Decrement the stack. */
1627 emit_insn (gen_movsi (reg, GEN_INT (- amount)));
1628 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
1629 reg));
1631 /* Restore the low register's original value. */
1632 emit_insn (gen_movsi (reg, spare));
1634 /* Emit a USE of the restored scratch register, so that flow
1635 analysis will not consider the restore redundant. The
1636 register won't be used again in this function and isn't
1637 restored by the epilogue. */
1638 emit_insn (gen_rtx_USE (VOIDmode, reg));
1640 else
1642 reg = gen_rtx (REG, SImode, regno);
1644 emit_insn (gen_movsi (reg, GEN_INT (- amount)));
1645 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
1646 reg));
1651 /* This should only happen with optimisation disabled. Emit the copy
1652 *after* the stack adjust, as the unoptimised code will attempt to store
1653 local variables at positive offsets from the frame pointer. */
1654 if (frame_pointer_needed)
1656 if (current_function_outgoing_args_size)
1658 rtx offset = GEN_INT (current_function_outgoing_args_size);
1660 if (current_function_outgoing_args_size < 1024)
1661 emit_insn (gen_addsi3 (frame_pointer_rtx, stack_pointer_rtx,
1662 offset));
1663 else
1665 emit_insn (gen_movsi (frame_pointer_rtx, offset));
1666 emit_insn (gen_addsi3 (frame_pointer_rtx, frame_pointer_rtx,
1667 stack_pointer_rtx));
1670 else
1671 emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
1674 if (profile_flag || profile_block_flag)
1675 emit_insn (gen_blockage ());
1678 void
1679 thumb_expand_epilogue ()
1681 HOST_WIDE_INT amount = (get_frame_size ()
1682 + current_function_outgoing_args_size);
1683 #ifdef THUMB_PE
1684 /* Naked functions don't have epilogues. */
1685 if (arm_naked_function_p (current_function_decl))
1686 return;
1687 #endif
1689 if (amount)
1691 if (amount < 512)
1692 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
1693 GEN_INT (amount)));
1694 else
1696 rtx reg = gen_rtx (REG, SImode, 3); /* Always free in the epilogue */
1698 emit_insn (gen_movsi (reg, GEN_INT (amount)));
1699 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));
1703 /* Emit a USE (stack_pointer_rtx), so that
1704 the stack adjustment will not be deleted. */
1705 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
1707 if (profile_flag || profile_block_flag)
1708 emit_insn (gen_blockage ());
1711 void
1712 thumb_function_epilogue (f, frame_size)
1713 FILE * f ATTRIBUTE_UNUSED;
1714 int frame_size ATTRIBUTE_UNUSED;
1716 /* ??? Probably not safe to set this here, since it assumes that a
1717 function will be emitted as assembly immediately after we generate
1718 RTL for it. This does not happen for inline functions. */
1719 return_used_this_function = 0;
1720 #if 0 /* TODO : comment not really needed */
1721 fprintf (f, "%s THUMB Epilogue\n", ASM_COMMENT_START);
1722 #endif
1725 /* The bits which aren't usefully expanded as rtl. */
1726 char *
1727 thumb_unexpanded_epilogue ()
1729 int regno;
1730 int live_regs_mask = 0;
1731 int high_regs_pushed = 0;
1732 int leaf_function = leaf_function_p ();
1733 int had_to_push_lr;
1735 if (return_used_this_function)
1736 return "";
1738 for (regno = 0; regno < 8; regno++)
1739 if (regs_ever_live[regno] && ! call_used_regs[regno]
1740 && ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
1741 live_regs_mask |= 1 << regno;
1743 for (regno = 8; regno < 13; regno++)
1745 if (regs_ever_live[regno] && ! call_used_regs[regno]
1746 && ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
1747 high_regs_pushed ++;
1750 /* The prolog may have pushed some high registers to use as
1751 work registers. eg the testuite file:
1752 gcc/testsuite/gcc/gcc.c-torture/execute/complex-2.c
1753 compiles to produce:
1754 push {r4, r5, r6, r7, lr}
1755 mov r7, r9
1756 mov r6, r8
1757 push {r6, r7}
1758 as part of the prolog. We have to undo that pushing here. */
1760 if (high_regs_pushed)
1762 int mask = live_regs_mask;
1763 int next_hi_reg;
1764 int size;
1765 int mode;
1767 #ifdef RTX_CODE
1768 /* If we can deduce the registers used from the function's return value.
1769 This is more reliable that examining regs_ever_live[] because that
1770 will be set if the register is ever used in the function, not just if
1771 the register is used to hold a return value. */
1773 if (current_function_return_rtx != 0)
1775 mode = GET_MODE (current_function_return_rtx);
1777 else
1778 #endif
1780 mode = DECL_MODE (DECL_RESULT (current_function_decl));
1783 size = GET_MODE_SIZE (mode);
1785 /* Unless we are returning a type of size > 12 register r3 is available. */
1786 if (size < 13)
1787 mask |= 1 << 3;
1789 if (mask == 0)
1791 /* Oh dear! We have no low registers into which we can pop high registers! */
1793 fatal ("No low registers available for popping high registers");
1796 for (next_hi_reg = 8; next_hi_reg < 13; next_hi_reg++)
1797 if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg]
1798 && ! (TARGET_SINGLE_PIC_BASE && (next_hi_reg == thumb_pic_register)))
1799 break;
1801 while (high_regs_pushed)
1803 /* Find low register(s) into which the high register(s) can be popped. */
1804 for (regno = 0; regno < 8; regno++)
1806 if (mask & (1 << regno))
1807 high_regs_pushed--;
1808 if (high_regs_pushed == 0)
1809 break;
1812 mask &= (2 << regno) - 1; /* A noop if regno == 8 */
1814 /* Pop the values into the low register(s). */
1815 thumb_pushpop (asm_out_file, mask, 0);
1817 /* Move the value(s) into the high registers. */
1818 for (regno = 0; regno < 8; regno++)
1820 if (mask & (1 << regno))
1822 asm_fprintf (asm_out_file, "\tmov\t%s, %s\n",
1823 reg_names[next_hi_reg], reg_names[regno]);
1824 for (next_hi_reg++; next_hi_reg < 13; next_hi_reg++)
1825 if (regs_ever_live[next_hi_reg] &&
1826 ! call_used_regs[next_hi_reg]
1827 && ! (TARGET_SINGLE_PIC_BASE
1828 && (next_hi_reg == thumb_pic_register)))
1829 break;
1835 had_to_push_lr = (live_regs_mask || ! leaf_function || far_jump_used_p());
1837 if (TARGET_BACKTRACE && ((live_regs_mask & 0xFF) == 0) && regs_ever_live[ ARG_4_REGISTER ] != 0)
1839 /* The stack backtrace structure creation code had to
1840 push R7 in order to get a work register, so we pop
1841 it now. */
1843 live_regs_mask |= (1 << WORK_REGISTER);
1846 if (current_function_pretend_args_size == 0 || TARGET_BACKTRACE)
1848 if (had_to_push_lr
1849 && ! is_called_in_ARM_mode (current_function_decl))
1850 live_regs_mask |= 1 << PROGRAM_COUNTER;
1852 /* Either no argument registers were pushed or a backtrace
1853 structure was created which includes an adjusted stack
1854 pointer, so just pop everything. */
1856 if (live_regs_mask)
1857 thumb_pushpop (asm_out_file, live_regs_mask, FALSE);
1859 /* We have either just popped the return address into the
1860 PC or it is was kept in LR for the entire function or
1861 it is still on the stack because we do not want to
1862 return by doing a pop {pc}. */
1864 if ((live_regs_mask & (1 << PROGRAM_COUNTER)) == 0)
1865 thumb_exit (asm_out_file,
1866 (had_to_push_lr
1867 && is_called_in_ARM_mode (current_function_decl)) ?
1868 -1 : LINK_REGISTER);
1870 else
1872 /* Pop everything but the return address. */
1873 live_regs_mask &= ~ (1 << PROGRAM_COUNTER);
1875 if (live_regs_mask)
1876 thumb_pushpop (asm_out_file, live_regs_mask, FALSE);
1878 if (had_to_push_lr)
1880 /* Get the return address into a temporary register. */
1881 thumb_pushpop (asm_out_file, 1 << ARG_4_REGISTER, 0);
1884 /* Remove the argument registers that were pushed onto the stack. */
1885 asm_fprintf (asm_out_file, "\tadd\t%s, %s, #%d\n",
1886 reg_names [STACK_POINTER],
1887 reg_names [STACK_POINTER],
1888 current_function_pretend_args_size);
1890 thumb_exit (asm_out_file, had_to_push_lr ? ARG_4_REGISTER : LINK_REGISTER);
1893 return "";
1896 /* Handle the case of a double word load into a low register from
1897 a computed memory address. The computed address may involve a
1898 register which is overwritten by the load. */
1900 char *
1901 thumb_load_double_from_address (operands)
1902 rtx * operands;
1904 rtx addr;
1905 rtx base;
1906 rtx offset;
1907 rtx arg1;
1908 rtx arg2;
1910 if (GET_CODE (operands[0]) != REG)
1911 fatal ("thumb_load_double_from_address: destination is not a register");
1913 if (GET_CODE (operands[1]) != MEM)
1914 fatal ("thumb_load_double_from_address: source is not a computed memory address");
1916 /* Get the memory address. */
1918 addr = XEXP (operands[1], 0);
1920 /* Work out how the memory address is computed. */
1922 switch (GET_CODE (addr))
1924 case REG:
1925 operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
1927 if (REGNO (operands[0]) == REGNO (addr))
1929 output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
1930 output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
1932 else
1934 output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
1935 output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
1937 break;
1939 case CONST:
1940 /* Compute <address> + 4 for the high order load. */
1942 operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
1944 output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
1945 output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
1946 break;
1948 case PLUS:
1949 arg1 = XEXP (addr, 0);
1950 arg2 = XEXP (addr, 1);
1952 if (CONSTANT_P (arg1))
1953 base = arg2, offset = arg1;
1954 else
1955 base = arg1, offset = arg2;
1957 if (GET_CODE (base) != REG)
1958 fatal ("thumb_load_double_from_address: base is not a register");
1960 /* Catch the case of <address> = <reg> + <reg> */
1962 if (GET_CODE (offset) == REG)
1964 int reg_offset = REGNO (offset);
1965 int reg_base = REGNO (base);
1966 int reg_dest = REGNO (operands[0]);
1968 /* Add the base and offset registers together into the higher destination register. */
1970 fprintf (asm_out_file, "\tadd\t%s, %s, %s\t\t%s created by thumb_load_double_from_address",
1971 reg_names[ reg_dest + 1 ],
1972 reg_names[ reg_base ],
1973 reg_names[ reg_offset ],
1974 ASM_COMMENT_START);
1976 /* Load the lower destination register from the address in the higher destination register. */
1978 fprintf (asm_out_file, "\tldr\t%s, [%s, #0]\t\t%s created by thumb_load_double_from_address",
1979 reg_names[ reg_dest ],
1980 reg_names[ reg_dest + 1],
1981 ASM_COMMENT_START);
1983 /* Load the higher destination register from its own address plus 4. */
1985 fprintf (asm_out_file, "\tldr\t%s, [%s, #4]\t\t%s created by thumb_load_double_from_address",
1986 reg_names[ reg_dest + 1 ],
1987 reg_names[ reg_dest + 1 ],
1988 ASM_COMMENT_START);
1990 else
1992 /* Compute <address> + 4 for the high order load. */
1994 operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
1996 /* If the computed address is held in the low order register
1997 then load the high order register first, otherwise always
1998 load the low order register first. */
2000 if (REGNO (operands[0]) == REGNO (base))
2002 output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
2003 output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
2005 else
2007 output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
2008 output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
2011 break;
2013 case LABEL_REF:
2014 /* With no registers to worry about we can just load the value directly. */
2015 operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
2017 output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
2018 output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
2019 break;
2021 default:
2022 debug_rtx (operands[1]);
2023 fatal ("thumb_load_double_from_address: Unhandled address calculation");
2024 break;
2027 return "";
2030 char *
2031 output_move_mem_multiple (n, operands)
2032 int n;
2033 rtx *operands;
2035 rtx tmp;
2037 switch (n)
2039 case 2:
2040 if (REGNO (operands[2]) > REGNO (operands[3]))
2042 tmp = operands[2];
2043 operands[2] = operands[3];
2044 operands[3] = tmp;
2046 output_asm_insn ("ldmia\t%1!, {%2, %3}", operands);
2047 output_asm_insn ("stmia\t%0!, {%2, %3}", operands);
2048 break;
2050 case 3:
2051 if (REGNO (operands[2]) > REGNO (operands[3]))
2053 tmp = operands[2];
2054 operands[2] = operands[3];
2055 operands[3] = tmp;
2057 if (REGNO (operands[3]) > REGNO (operands[4]))
2059 tmp = operands[3];
2060 operands[3] = operands[4];
2061 operands[4] = tmp;
2063 if (REGNO (operands[2]) > REGNO (operands[3]))
2065 tmp = operands[2];
2066 operands[2] = operands[3];
2067 operands[3] = tmp;
2069 output_asm_insn ("ldmia\t%1!, {%2, %3, %4}", operands);
2070 output_asm_insn ("stmia\t%0!, {%2, %3, %4}", operands);
2071 break;
2073 default:
2074 abort ();
2077 return "";
2082 thumb_epilogue_size ()
2084 return 42; /* The answer to .... */
2087 static char *conds[] =
2089 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
2090 "hi", "ls", "ge", "lt", "gt", "le"
2093 static char *
2094 thumb_condition_code (x, invert)
2095 rtx x;
2096 int invert;
2098 int val;
2100 switch (GET_CODE (x))
2102 case EQ: val = 0; break;
2103 case NE: val = 1; break;
2104 case GEU: val = 2; break;
2105 case LTU: val = 3; break;
2106 case GTU: val = 8; break;
2107 case LEU: val = 9; break;
2108 case GE: val = 10; break;
2109 case LT: val = 11; break;
2110 case GT: val = 12; break;
2111 case LE: val = 13; break;
2112 default:
2113 abort ();
2116 return conds[val ^ invert];
2119 void
2120 thumb_print_operand (f, x, code)
2121 FILE *f;
2122 rtx x;
2123 int code;
2125 if (code)
2127 switch (code)
2129 case '@':
2130 fputs (ASM_COMMENT_START, f);
2131 return;
2133 case '|':
2134 /* fputs (REGISTER_PREFIX, f); */
2135 return;
2137 case '_':
2138 fputs (user_label_prefix, f);
2139 return;
2141 case 'D':
2142 if (x)
2143 fputs (thumb_condition_code (x, 1), f);
2144 return;
2146 case 'd':
2147 if (x)
2148 fputs (thumb_condition_code (x, 0), f);
2149 return;
2151 /* An explanation of the 'Q', 'R' and 'H' register operands:
2153 In a pair of registers containing a DI or DF value the 'Q'
2154 operand returns the register number of the register containing
2155 the least signficant part of the value. The 'R' operand returns
2156 the register number of the register containing the most
2157 significant part of the value.
2159 The 'H' operand returns the higher of the two register numbers.
2160 On a run where WORDS_BIG_ENDIAN is true the 'H' operand is the
2161 same as the 'Q' operand, since the most signficant part of the
2162 value is held in the lower number register. The reverse is true
2163 on systems where WORDS_BIG_ENDIAN is false.
2165 The purpose of these operands is to distinguish between cases
2166 where the endian-ness of the values is important (for example
2167 when they are added together), and cases where the endian-ness
2168 is irrelevant, but the order of register operations is important.
2169 For example when loading a value from memory into a register
2170 pair, the endian-ness does not matter. Provided that the value
2171 from the lower memory address is put into the lower numbered
2172 register, and the value from the higher address is put into the
2173 higher numbered register, the load will work regardless of whether
2174 the value being loaded is big-wordian or little-wordian. The
2175 order of the two register loads can matter however, if the address
2176 of the memory location is actually held in one of the registers
2177 being overwritten by the load. */
2178 case 'Q':
2179 if (REGNO (x) > 15)
2180 abort ();
2181 fputs (reg_names[REGNO (x) + (WORDS_BIG_ENDIAN ? 1 : 0)], f);
2182 return;
2184 case 'R':
2185 if (REGNO (x) > 15)
2186 abort ();
2187 fputs (reg_names[REGNO (x) + (WORDS_BIG_ENDIAN ? 0 : 1)], f);
2188 return;
2190 case 'H':
2191 if (REGNO (x) > 15)
2192 abort ();
2193 fputs (reg_names[REGNO (x) + 1], f);
2194 return;
2196 default:
2197 abort ();
2200 if (GET_CODE (x) == REG)
2201 fputs (reg_names[REGNO (x)], f);
2202 else if (GET_CODE (x) == MEM)
2203 output_address (XEXP (x, 0));
2204 else if (GET_CODE (x) == CONST_INT)
2206 fputc ('#', f);
2207 output_addr_const (f, x);
2209 else
2210 abort ();
2213 #ifdef AOF_ASSEMBLER
2214 int arm_text_section_count = 1;
2216 char *
2217 aof_text_section (in_readonly)
2218 int in_readonly;
2220 static char buf[100];
2221 if (in_readonly)
2222 return "";
2223 sprintf (buf, "\tCODE16\n\tAREA |C$$code%d|, CODE, READONLY",
2224 arm_text_section_count++);
2225 return buf;
2228 static int arm_data_section_count = 1;
2230 char *
2231 aof_data_section ()
2233 static char buf[100];
2234 sprintf (buf, "\tAREA |C$$data%d|, DATA", arm_data_section_count++);
2235 return buf;
2238 /* The AOF thumb assembler is religiously strict about declarations of
2239 imported and exported symbols, so that it is impossible to declare a
2240 function as imported near the begining of the file, and then to export
2241 it later on. It is, however, possible to delay the decision until all
2242 the functions in the file have been compiled. To get around this, we
2243 maintain a list of the imports and exports, and delete from it any that
2244 are subsequently defined. At the end of compilation we spit the
2245 remainder of the list out before the END directive. */
2247 struct import
2249 struct import *next;
2250 char *name;
2253 static struct import *imports_list = NULL;
2255 void
2256 thumb_aof_add_import (name)
2257 char *name;
2259 struct import *new;
2261 for (new = imports_list; new; new = new->next)
2262 if (new->name == name)
2263 return;
2265 new = (struct import *) xmalloc (sizeof (struct import));
2266 new->next = imports_list;
2267 imports_list = new;
2268 new->name = name;
2271 void
2272 thumb_aof_delete_import (name)
2273 char *name;
2275 struct import **old;
2277 for (old = &imports_list; *old; old = & (*old)->next)
2279 if ((*old)->name == name)
2281 *old = (*old)->next;
2282 return;
2287 void
2288 thumb_aof_dump_imports (f)
2289 FILE *f;
2291 while (imports_list)
2293 fprintf (f, "\tIMPORT\t");
2294 assemble_name (f, imports_list->name);
2295 fputc ('\n', f);
2296 imports_list = imports_list->next;
2299 #endif
2301 /* Decide whether a type should be returned in memory (true)
2302 or in a register (false). This is called by the macro
2303 RETURN_IN_MEMORY. */
2306 thumb_return_in_memory (type)
2307 tree type;
2309 if (! AGGREGATE_TYPE_P (type))
2311 /* All simple types are returned in registers. */
2313 return 0;
2315 else if (int_size_in_bytes (type) > 4)
2317 /* All structures/unions bigger than one word are returned in memory. */
2319 return 1;
2321 else if (TREE_CODE (type) == RECORD_TYPE)
2323 tree field;
2325 /* For a struct the APCS says that we must return in a register if
2326 every addressable element has an offset of zero. For practical
2327 purposes this means that the structure can have at most one non-
2328 bit-field element and that this element must be the first one in
2329 the structure. */
2331 /* Find the first field, ignoring non FIELD_DECL things which will
2332 have been created by C++. */
2333 for (field = TYPE_FIELDS (type);
2334 field && TREE_CODE (field) != FIELD_DECL;
2335 field = TREE_CHAIN (field))
2336 continue;
2338 if (field == NULL)
2339 return 0; /* An empty structure. Allowed by an extension to ANSI C. */
2341 /* Now check the remaining fields, if any. */
2342 for (field = TREE_CHAIN (field); field; field = TREE_CHAIN (field))
2344 if (TREE_CODE (field) != FIELD_DECL)
2345 continue;
2347 if (! DECL_BIT_FIELD_TYPE (field))
2348 return 1;
2351 return 0;
2353 else if (TREE_CODE (type) == UNION_TYPE)
2355 tree field;
2357 /* Unions can be returned in registers if every element is
2358 integral, or can be returned in an integer register. */
2360 for (field = TYPE_FIELDS (type);
2361 field;
2362 field = TREE_CHAIN (field))
2364 if (TREE_CODE (field) != FIELD_DECL)
2365 continue;
2367 if (RETURN_IN_MEMORY (TREE_TYPE (field)))
2368 return 1;
2371 return 0;
2373 /* XXX Not sure what should be done for other aggregates, so put them in
2374 memory. */
2375 return 1;
2378 void
2379 thumb_override_options ()
2381 if (structure_size_string != NULL)
2383 int size = strtol (structure_size_string, NULL, 0);
2385 if (size == 8 || size == 32)
2386 arm_structure_size_boundary = size;
2387 else
2388 warning ("Structure size boundary can only be set to 8 or 32");
2391 if (thumb_pic_register_string != NULL)
2393 int pic_register;
2395 if (! flag_pic)
2396 warning ("-mpic-register= is useless without -fpic");
2398 pic_register = decode_reg_name (thumb_pic_register_string);
2400 /* Prevent the user from choosing an obviously stupid PIC register. */
2401 if (pic_register < 0 || call_used_regs[pic_register]
2402 || pic_register == HARD_FRAME_POINTER_REGNUM
2403 || pic_register == STACK_POINTER_REGNUM
2404 || pic_register >= PC_REGNUM)
2405 error ("Unable to use '%s' for PIC register", thumb_pic_register_string);
2406 else
2407 thumb_pic_register = pic_register;
2411 #ifdef THUMB_PE
2412 /* Return nonzero if ATTR is a valid attribute for DECL.
2413 ATTRIBUTES are any existing attributes and ARGS are the arguments
2414 supplied with ATTR.
2416 Supported attributes:
2418 naked: don't output any prologue or epilogue code, the user is assumed
2419 to do the right thing.
2421 interfacearm: Always assume that this function will be entered in ARM
2422 mode, not Thumb mode, and that the caller wishes to be returned to in
2423 ARM mode. */
2425 arm_valid_machine_decl_attribute (decl, attr, args)
2426 tree decl;
2427 tree attr;
2428 tree args;
2430 if (args != NULL_TREE)
2431 return 0;
2433 if (is_attribute_p ("naked", attr))
2434 if (TREE_CODE (decl) == FUNCTION_DECL)
2435 return 1;
2437 if (is_attribute_p ("interfacearm", attr))
2438 return TREE_CODE (decl) == FUNCTION_DECL;
2440 return 0;
2442 #endif /* THUMB_PE */