diff options
author | Richard Earnshaw <erich@gnu.org> | 1997-05-08 22:17:34 +0000 |
---|---|---|
committer | Richard Earnshaw <erich@gnu.org> | 1997-05-08 22:17:34 +0000 |
commit | 32de079ac5d2f7deea7a1cbd2422c1fb87016766 (patch) | |
tree | 36d8e7b4b4db6897642edd7a7658cfab46c19af3 | |
parent | 858a9ffcb70e7fbf3c28baee571ef2785d8b798f (diff) | |
download | gcc-32de079ac5d2f7deea7a1cbd2422c1fb87016766.zip gcc-32de079ac5d2f7deea7a1cbd2422c1fb87016766.tar.gz gcc-32de079ac5d2f7deea7a1cbd2422c1fb87016766.tar.bz2 |
(arm_increase_location, get_prologue_size): Delete.
(arm_naked_function_p): Add declaration.
(arm_pic_register): Define.
(all_procs): Delete entries for arm{60,620,70,7d,7di,700i,710c}; add
entries for arm{7m,7500fe,8}, strongarm and strongarm110.
(arm_override_options): Rework so that configure can properly set
the default processor type. Add a warning that PIC code is not yet
supported.
(legitimate_pic_operand_p, legitimize_pic_address): New functions.
(is_pic, arm_finalize_pic): New functions.
(arm_adjust_cost): New function.
(const_pool_offset, arm_backwards_branch, short_branch): Delete.
(arm_insn_not_targeted): Delete.
(add_constant): If generating AOF syntax, then handle pic specially.
(output_ascii_pseudo_op): Delete calls to arm_increase_location.
(function_really_clobbers_lr): Calls followed by a barrier don't
clobber the link register.
(output_func_prologue): Handle AOF syntax pic code.
(output_func_epilogue): Handle cases where lr_save_eliminated is set.
Delete call to arm_increase_location.
(arm_asm_output_label): Simplify, since we no-longer need to cache the
label's address.
(aof_pic_entry): New function to keep track of pic symbols.
(aof_dump_pic_table): New function.
From-SVN: r14049
-rw-r--r-- | gcc/config/arm/arm.c | 508 |
1 files changed, 363 insertions, 145 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index fb4705c..931a938 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -1,5 +1,5 @@ /* Output routines for GCC for ARM/RISCiX. - Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1991, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) and Martin Simmons (@harleqn.co.uk). More major hacks by Richard Earnshaw (rwe11@cl.cam.ac.uk) @@ -46,12 +46,11 @@ Boston, MA 02111-1307, USA. */ /* Some function declarations. */ extern FILE *asm_out_file; extern char *output_multi_immediate (); -extern void arm_increase_location (); HOST_WIDE_INT int_log2 PROTO ((HOST_WIDE_INT)); -static int get_prologue_size PROTO ((void)); static int arm_gen_constant PROTO ((enum rtx_code, enum machine_mode, HOST_WIDE_INT, rtx, rtx, int, int)); +static int arm_naked_function_p PROTO ((tree func)); /* Define the information needed to generate branch insns. This is stored from the compare operation. */ @@ -74,7 +73,7 @@ char *target_fpe_name = NULL; /* Nonzero if this is an "M" variant of the processor. */ int arm_fast_multiply = 0; -/* Nonzero if this chip support the ARM Architecture 4 extensions */ +/* Nonzero if this chip supports the ARM Architecture 4 extensions */ int arm_arch4 = 0; /* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference, we @@ -85,6 +84,9 @@ enum machine_mode output_memory_reference_mode; /* Nonzero if the prologue must setup `fp'. */ int current_function_anonymous_args; +/* The register number to be used for the PIC offset register. */ +int arm_pic_register = 9; + /* Location counter of .text segment. */ int arm_text_location = 0; @@ -92,19 +94,6 @@ int arm_text_location = 0; but all of these can be `put after' return insns */ int lr_save_eliminated; -/* A hash table is used to store text segment labels and their associated - offset from the start of the text segment. */ -struct label_offset -{ - char *name; - int offset; - struct label_offset *cdr; -}; - -#define LABEL_HASH_SIZE 257 - -static struct label_offset *offset_table[LABEL_HASH_SIZE]; - /* Set to 1 when a return insn is output, this means that the epilogue is not needed. */ @@ -144,6 +133,7 @@ struct arm_cpu_select arm_select[3] = #define FL_MODE32 0x08 /* 32-bit mode support */ #define FL_ARCH4 0x10 /* Architecture rel 4 */ #define FL_THUMB 0x20 /* Thumb aware */ + struct processors { char *name; @@ -159,26 +149,33 @@ static struct processors all_procs[] = {"arm250", PROCESSOR_ARM2, FL_CO_PROC | FL_MODE26}, {"arm3", PROCESSOR_ARM2, FL_CO_PROC | FL_MODE26}, {"arm6", PROCESSOR_ARM6, FL_CO_PROC | FL_MODE32 | FL_MODE26}, - {"arm60", PROCESSOR_ARM6, FL_CO_PROC | FL_MODE32 | FL_MODE26}, {"arm600", PROCESSOR_ARM6, FL_CO_PROC | FL_MODE32 | FL_MODE26}, {"arm610", PROCESSOR_ARM6, FL_MODE32 | FL_MODE26}, - {"arm620", PROCESSOR_ARM6, FL_CO_PROC | FL_MODE32 | FL_MODE26}, {"arm7", PROCESSOR_ARM7, FL_CO_PROC | FL_MODE32 | FL_MODE26}, - {"arm70", PROCESSOR_ARM7, FL_CO_PROC | FL_MODE32 | FL_MODE26}, - {"arm7d", PROCESSOR_ARM7, FL_CO_PROC | FL_MODE32 | FL_MODE26}, - {"arm7di", PROCESSOR_ARM7, FL_CO_PROC | FL_MODE32 | FL_MODE26}, + /* arm7m doesn't exist on its own, only in conjuction with D, (and I), but + those don't alter the code, so it is sometimes known as the arm7m */ + {"arm7m", PROCESSOR_ARM7, (FL_CO_PROC | FL_FAST_MULT | FL_MODE32 + | FL_MODE26)}, {"arm7dm", PROCESSOR_ARM7, (FL_CO_PROC | FL_FAST_MULT | FL_MODE32 | FL_MODE26)}, {"arm7dmi", PROCESSOR_ARM7, (FL_CO_PROC | FL_FAST_MULT | FL_MODE32 | FL_MODE26)}, {"arm700", PROCESSOR_ARM7, FL_CO_PROC | FL_MODE32 | FL_MODE26}, - {"arm700i", PROCESSOR_ARM7, FL_CO_PROC | FL_MODE32 | FL_MODE26}, {"arm710", PROCESSOR_ARM7, FL_MODE32 | FL_MODE26}, - {"arm710c", PROCESSOR_ARM7, FL_MODE32 | FL_MODE26}, {"arm7100", PROCESSOR_ARM7, FL_MODE32 | FL_MODE26}, {"arm7500", PROCESSOR_ARM7, FL_MODE32 | FL_MODE26}, + /* Doesn't really have an external co-proc, but does have embedded fpu */ + {"arm7500fe", PROCESSOR_ARM7, FL_CO_PROC | FL_MODE32 | FL_MODE26}, {"arm7tdmi", PROCESSOR_ARM7, (FL_CO_PROC | FL_FAST_MULT | FL_MODE32 | FL_ARCH4 | FL_THUMB)}, + {"arm8", PROCESSOR_ARM8, (FL_FAST_MULT | FL_MODE32 | FL_MODE26 + | FL_ARCH4)}, + {"arm810", PROCESSOR_ARM8, (FL_FAST_MULT | FL_MODE32 | FL_MODE26 + | FL_ARCH4)}, + {"strongarm", PROCESSOR_STARM, (FL_FAST_MULT | FL_MODE32 | FL_MODE26 + | FL_ARCH4)}, + {"strongarm110", PROCESSOR_STARM, (FL_FAST_MULT | FL_MODE32 | FL_MODE26 + | FL_ARCH4)}, {NULL, 0, 0} }; @@ -191,9 +188,31 @@ arm_override_options () int flags = 0; int i; struct arm_cpu_select *ptr; + static struct cpu_default { + int cpu; + char *name; + } cpu_defaults[] = { + { TARGET_CPU_arm2, "arm2" }, + { TARGET_CPU_arm6, "arm6" }, + { TARGET_CPU_arm610, "arm610" }, + { TARGET_CPU_arm7dm, "arm7dm" }, + { TARGET_CPU_arm7500fe, "arm7500fe" }, + { TARGET_CPU_arm7tdmi, "arm7tdmi" }, + { TARGET_CPU_arm8, "arm8" }, + { TARGET_CPU_arm810, "arm810" }, + { TARGET_CPU_strongarm, "strongarm" }, + { 0, 0 } + }; + struct cpu_default *def; + + /* Set the default. */ + for (def = &cpu_defaults[0]; def->name; ++def) + if (def->cpu == TARGET_CPU_DEFAULT) + break; + if (! def->name) + abort (); - arm_cpu = PROCESSOR_DEFAULT; - arm_select[0].string = TARGET_CPU_DEFAULT; + arm_select[0].string = def->name; for (i = 0; i < sizeof (arm_select) / sizeof (arm_select[0]); i++) { @@ -225,25 +244,26 @@ arm_override_options () target_flags |= ARM_FLAG_APCS_FRAME; if (TARGET_6) - { - warning ("Option '-m6' deprecated. Use: '-mapcs-32' or -mcpu=<proc>"); - target_flags |= ARM_FLAG_APCS_32; - arm_cpu = PROCESSOR_ARM6; - } + warning ("Option '-m6' deprecated. Use: '-mapcs-32' or -mcpu=<proc>"); if (TARGET_3) - { - warning ("Option '-m3' deprecated. Use: '-mapcs-26' or -mcpu=<proc>"); - target_flags &= ~ARM_FLAG_APCS_32; - arm_cpu = PROCESSOR_ARM2; - } + warning ("Option '-m3' deprecated. Use: '-mapcs-26' or -mcpu=<proc>"); if (TARGET_APCS_REENT && flag_pic) fatal ("-fpic and -mapcs-reent are incompatible"); if (TARGET_APCS_REENT) - warning ("APCS reentrant code not supported. Ignored"); + warning ("APCS reentrant code not supported."); + + /* If stack checking is disabled, we can use r10 as the PIC register, + which keeps r9 available. */ + if (flag_pic && ! TARGET_APCS_STACK) + arm_pic_register = 10; + /* Well, I'm about to have a go, but pic is NOT going to be compatible + with APCS reentrancy, since that requires too much support in the + assembler and linker, and the ARMASM assembler seems to lack some + required directives. */ if (flag_pic) warning ("Position independent code not supported. Ignored"); @@ -297,6 +317,7 @@ arm_override_options () arm_prog_mode = TARGET_APCS_32 ? PROG_MODE_PROG32 : PROG_MODE_PROG26; } + /* Return 1 if it is possible to return using a single instruction */ int @@ -1071,6 +1092,178 @@ arm_return_in_memory (type) return 1; } +int +legitimate_pic_operand_p (x) + rtx x; +{ + if (CONSTANT_P (x) && flag_pic + && (GET_CODE (x) == SYMBOL_REF + || (GET_CODE (x) == CONST + && GET_CODE (XEXP (x, 0)) == PLUS + && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF))) + return 0; + + return 1; +} + +rtx +legitimize_pic_address (orig, mode, reg) + rtx orig; + enum machine_mode mode; + rtx reg; +{ + if (GET_CODE (orig) == SYMBOL_REF) + { + rtx pic_ref, address; + rtx insn; + int subregs = 0; + + if (reg == 0) + { + if (reload_in_progress || reload_completed) + abort (); + else + reg = gen_reg_rtx (Pmode); + + subregs = 1; + } + +#ifdef AOF_ASSEMBLER + /* The AOF assembler can generate relocations for these directly, and + understands that the PIC register has to be added into the offset. + */ + insn = emit_insn (gen_pic_load_addr_based (reg, orig)); +#else + if (subregs) + address = gen_reg_rtx (Pmode); + else + address = reg; + + emit_insn (gen_pic_load_addr (address, orig)); + + pic_ref = gen_rtx (MEM, Pmode, + gen_rtx (PLUS, Pmode, pic_offset_table_rtx, address)); + RTX_UNCHANGING_P (pic_ref) = 1; + insn = emit_move_insn (reg, pic_ref); +#endif + current_function_uses_pic_offset_table = 1; + /* Put a REG_EQUAL note on this insn, so that it can be optimized + by loop. */ + REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, orig, + REG_NOTES (insn)); + return reg; + } + else if (GET_CODE (orig) == CONST) + { + rtx base, offset; + + if (GET_CODE (XEXP (orig, 0)) == PLUS + && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx) + return orig; + + if (reg == 0) + { + if (reload_in_progress || reload_completed) + abort (); + else + reg = gen_reg_rtx (Pmode); + } + + if (GET_CODE (XEXP (orig, 0)) == PLUS) + { + base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg); + offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode, + base == reg ? 0 : reg); + } + else + abort (); + + if (GET_CODE (offset) == CONST_INT) + { + /* The base register doesn't really matter, we only want to + test the index for the appropriate mode. */ + GO_IF_LEGITIMATE_INDEX (mode, 0, offset, win); + + if (! reload_in_progress && ! reload_completed) + offset = force_reg (Pmode, offset); + else + abort (); + + win: + if (GET_CODE (offset) == CONST_INT) + return plus_constant_for_output (base, INTVAL (offset)); + } + + if (GET_MODE_SIZE (mode) > 4 + && (GET_MODE_CLASS (mode) == MODE_INT + || TARGET_SOFT_FLOAT)) + { + emit_insn (gen_addsi3 (reg, base, offset)); + return reg; + } + + return gen_rtx (PLUS, Pmode, base, offset); + } + else if (GET_CODE (orig) == LABEL_REF) + current_function_uses_pic_offset_table = 1; + + return orig; +} + +static rtx pic_rtx; + +int +is_pic(x) + rtx x; +{ + if (x == pic_rtx) + return 1; + return 0; +} + +void +arm_finalize_pic () +{ +#ifndef AOF_ASSEMBLER + rtx l1, pic_tmp, pic_tmp2, seq; + rtx global_offset_table; + + if (current_function_uses_pic_offset_table == 0) + return; + + if (! flag_pic) + abort (); + + start_sequence (); + l1 = gen_label_rtx (); + + global_offset_table = gen_rtx (SYMBOL_REF, Pmode, "_GLOBAL_OFFSET_TABLE_"); + pic_tmp = gen_rtx (CONST, VOIDmode, + gen_rtx (PLUS, Pmode, + gen_rtx (LABEL_REF, VOIDmode, l1), + GEN_INT (8))); + pic_tmp2 = gen_rtx (CONST, VOIDmode, + gen_rtx (PLUS, Pmode, + global_offset_table, + pc_rtx)); + + pic_rtx = gen_rtx (CONST, Pmode, + gen_rtx (MINUS, Pmode, pic_tmp2, pic_tmp)); + + emit_insn (gen_pic_load_addr (pic_offset_table_rtx, pic_rtx)); + emit_jump_insn (gen_pic_add_dot_plus_eight(l1, pic_offset_table_rtx)); + emit_label (l1); + + seq = gen_sequence (); + end_sequence (); + emit_insn_after (seq, get_insns ()); + + /* Need to emit this whether or not we obey regdecls, + since setjmp/longjmp can cause life info to screw up. */ + emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx)); +#endif /* AOF_ASSEMBLER */ +} + #define REG_OR_SUBREG_REG(X) \ (GET_CODE (X) == REG \ || (GET_CODE (X) == SUBREG && GET_CODE (SUBREG_REG (X)) == REG)) @@ -1295,7 +1488,45 @@ arm_rtx_costs (x, code, outer_code) return 99; } } - + +int +arm_adjust_cost (insn, link, dep, cost) + rtx insn; + rtx link; + rtx dep; + int cost; +{ + rtx i_pat, d_pat; + + if ((i_pat = single_set (insn)) != NULL + && GET_CODE (SET_SRC (i_pat)) == MEM + && (d_pat = single_set (dep)) != NULL + && GET_CODE (SET_DEST (d_pat)) == MEM) + { + /* This is a load after a store, there is no conflict if the load reads + from a cached area. Assume that loads from the stack, and from the + constant pool are cached, and that others will miss. This is a + hack. */ + +/* debug_rtx (insn); + debug_rtx (dep); + debug_rtx (link); + fprintf (stderr, "costs %d\n", cost); */ + + if (CONSTANT_POOL_ADDRESS_P (XEXP (SET_SRC (i_pat), 0)) + || reg_mentioned_p (stack_pointer_rtx, XEXP (SET_SRC (i_pat), 0)) + || reg_mentioned_p (frame_pointer_rtx, XEXP (SET_SRC (i_pat), 0)) + || reg_mentioned_p (hard_frame_pointer_rtx, + XEXP (SET_SRC (i_pat), 0))) + { +/* fprintf (stderr, "***** Now 1\n"); */ + return 1; + } + } + + return cost; +} + /* This code has been fixed for cross compilation. */ static int fpa_consts_inited = 0; @@ -2409,13 +2640,6 @@ multi_register_push (op, mode) /* Routines for use with attributes */ -int -const_pool_offset (symbol) - rtx symbol; -{ - return get_pool_offset (symbol) - get_pool_size () - get_prologue_size (); -} - /* Return nonzero if ATTR is a valid attribute for DECL. ATTRIBUTES are any existing attributes and ARGS are the arguments supplied with ATTR. @@ -2948,37 +3172,6 @@ arm_reload_out_hi (operands) } } -/* Check to see if a branch is forwards or backwards. Return TRUE if it - is backwards. */ - -int -arm_backwards_branch (from, to) - int from, to; -{ - return insn_addresses[to] <= insn_addresses[from]; -} - -/* Check to see if a branch is within the distance that can be done using - an arithmetic expression. */ -int -short_branch (from, to) - int from, to; -{ - int delta = insn_addresses[from] + 8 - insn_addresses[to]; - - return abs (delta) < 980; /* A small margin for safety */ -} - -/* Check to see that the insn isn't the target of the conditionalizing - code */ -int -arm_insn_not_targeted (insn) - rtx insn; -{ - return insn != arm_target_insn; -} - - /* Routines for manipulation of the constant pool. */ /* This is unashamedly hacked from the version in sh.c, since the problem is extremely similar. */ @@ -3071,6 +3264,13 @@ add_constant (x, mode) x = XVECEXP (x, 0, 0); #endif +#ifdef AOF_ASSEMBLER + /* PIC Symbol references need to be converted into offsets into the + based area. */ + if (flag_pic && GET_CODE (x) == SYMBOL_REF) + x = aof_pic_entry (x); +#endif /* AOF_ASSEMBLER */ + /* First see if we've already got it */ for (i = 0; i < pool_size; i++) { @@ -4106,7 +4306,6 @@ output_ascii_pseudo_op (stream, p, len) fputs ("\"\n", stream); fputs ("\t.ascii\t\"", stream); len_so_far = 0; - arm_increase_location (chars_so_far); chars_so_far = 0; } @@ -4131,7 +4330,6 @@ output_ascii_pseudo_op (stream, p, len) } fputs ("\"\n", stream); - arm_increase_location (chars_so_far); } @@ -4255,6 +4453,10 @@ function_really_clobbers_lr (first) if ((next = next_nonnote_insn (insn)) == NULL) return 1; + /* No need to worry about lr if the call never returns */ + if (GET_CODE (next) == BARRIER) + break; + if (GET_CODE (next) == INSN && GET_CODE (PATTERN (next)) == USE && (GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET) && (REGNO (SET_DEST (XVECEXP (PATTERN (insn), 0, 0))) @@ -4380,15 +4582,6 @@ arm_volatile_func () return (optimize > 0 && TREE_THIS_VOLATILE (current_function_decl)); } -/* Return the size of the prologue. It's not too bad if we slightly - over-estimate. */ - -static int -get_prologue_size () -{ - return profile_flag ? 12 : 0; -} - /* The amount of stack adjustment that happens here, in output_return and in output_epilogue must be exactly the same as was calculated during reload, or things will point to the wrong place. The only time we can safely @@ -4464,6 +4657,12 @@ output_func_prologue (f, frame_size) if (lr_save_eliminated) fprintf (f,"\t%s I don't think this function clobbers lr\n", ASM_COMMENT_START); + +#ifdef AOF_ASSEMBLER + if (flag_pic) + fprintf (f, "\tmov\t%sip, %s%s\n", REGISTER_PREFIX, REGISTER_PREFIX, + reg_names[PIC_OFFSET_TABLE_REGNUM]); +#endif } @@ -4544,25 +4743,38 @@ output_func_epilogue (f, frame_size) } if (current_function_pretend_args_size == 0 && regs_ever_live[14]) { - print_multi_reg (f, "ldmfd\t%ssp!", live_regs_mask | 0x8000, - TARGET_APCS_32 ? FALSE : TRUE); + if (lr_save_eliminated) + fprintf (f, (TARGET_APCS_32 ? "\tmov\t%spc, %slr\n" + : "\tmovs\t%spc, %slr\n"), + REGISTER_PREFIX, REGISTER_PREFIX, f); + else + print_multi_reg (f, "ldmfd\t%ssp!", live_regs_mask | 0x8000, + TARGET_APCS_32 ? FALSE : TRUE); code_size += 4; } else { if (live_regs_mask || regs_ever_live[14]) { - live_regs_mask |= 0x4000; - print_multi_reg (f, "ldmfd\t%ssp!", live_regs_mask, FALSE); - code_size += 4; + /* Restore the integer regs, and the return address into lr */ + if (! lr_save_eliminated) + live_regs_mask |= 0x4000; + + if (live_regs_mask != 0) + { + print_multi_reg (f, "ldmfd\t%ssp!", live_regs_mask, FALSE); + code_size += 4; + } } if (current_function_pretend_args_size) { + /* Unwind the pre-pushed regs */ operands[0] = operands[1] = stack_pointer_rtx; operands[2] = gen_rtx (CONST_INT, VOIDmode, current_function_pretend_args_size); output_add_immediate (operands); } + /* And finally, go home */ fprintf (f, (TARGET_APCS_32 ? "\tmov\t%spc, %slr\n" : "\tmovs\t%spc, %slr\n"), REGISTER_PREFIX, REGISTER_PREFIX, f); @@ -4570,15 +4782,7 @@ output_func_epilogue (f, frame_size) } } - epilogue_done: - - /* insn_addresses isn't allocated when not optimizing */ - /* ??? The previous comment is incorrect. Clarify. */ - - if (optimize > 0) - arm_increase_location (code_size - + insn_addresses[INSN_UID (get_last_insn ())] - + get_prologue_size ()); +epilogue_done: current_function_anonymous_args = 0; } @@ -4868,57 +5072,14 @@ arm_print_operand (stream, x, code) } } -/* Increase the `arm_text_location' by AMOUNT if we're in the text - segment. */ - -void -arm_increase_location (amount) - int amount; -{ - if (in_text_section ()) - arm_text_location += amount; -} - - -/* Output a label definition. If this label is within the .text segment, it - is stored in OFFSET_TABLE, to be used when building `llc' instructions. - Maybe GCC remembers names not starting with a `*' for a long time, but this - is a minority anyway, so we just make a copy. Do not store the leading `*' - if the name starts with one. */ +/* Output a label definition. */ void arm_asm_output_label (stream, name) FILE *stream; char *name; { - char *real_name, *s; - struct label_offset *cur; - int hash = 0; - ARM_OUTPUT_LABEL (stream, name); - if (! in_text_section ()) - return; - - if (name[0] == '*') - { - real_name = xmalloc (1 + strlen (&name[1])); - strcpy (real_name, &name[1]); - } - else - { - real_name = xmalloc (2 + strlen (name)); - strcpy (real_name, USER_LABEL_PREFIX); - strcat (real_name, name); - } - for (s = real_name; *s; s++) - hash += *s; - - hash = hash % LABEL_HASH_SIZE; - cur = (struct label_offset *) xmalloc (sizeof (struct label_offset)); - cur->name = real_name; - cur->offset = arm_text_location; - cur->cdr = offset_table[hash]; - offset_table[hash] = cur; } /* Output code resembling an .lcomm directive. /bin/as doesn't have this @@ -5417,6 +5578,63 @@ final_prescan_insn (insn, opvec, noperands) #ifdef AOF_ASSEMBLER /* Special functions only needed when producing AOF syntax assembler. */ +rtx aof_pic_label = NULL_RTX; +struct pic_chain +{ + struct pic_chain *next; + char *symname; +}; + +static struct pic_chain *aof_pic_chain = NULL; + +rtx +aof_pic_entry (x) + rtx x; +{ + struct pic_chain **chainp; + int offset; + + if (aof_pic_label == NULL_RTX) + { + /* This needs to persist throughout the compilation. */ + end_temporary_allocation (); + aof_pic_label = gen_rtx (SYMBOL_REF, Pmode, "x$adcons"); + resume_temporary_allocation (); + } + + for (offset = 0, chainp = &aof_pic_chain; *chainp; + offset += 4, chainp = &(*chainp)->next) + if ((*chainp)->symname == XSTR (x, 0)) + return plus_constant (aof_pic_label, offset); + + *chainp = (struct pic_chain *) xmalloc (sizeof (struct pic_chain)); + (*chainp)->next = NULL; + (*chainp)->symname = XSTR (x, 0); + return plus_constant (aof_pic_label, offset); +} + +void +aof_dump_pic_table (f) + FILE *f; +{ + struct pic_chain *chain; + + if (aof_pic_chain == NULL) + return; + + fprintf (f, "\tAREA |%s$$adcons|, BASED %s%s\n", + reg_names[PIC_OFFSET_TABLE_REGNUM], REGISTER_PREFIX, + reg_names[PIC_OFFSET_TABLE_REGNUM]); + fputs ("|x$adcons|\n", f); + + for (chain = aof_pic_chain; chain; chain = chain->next) + { + fputs ("\tDCD\t", f); + assemble_name (f, chain->symname); + fputs ("\n", f); + } +} + int arm_text_section_count = 1; char * |