From 5b63f465fceee4d74e9450c91497d33d0f900fa6 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 25 Mar 1994 22:40:44 +0000 Subject: [PATCH] * config/tc-mips.c (append_insn): If EMBEDDED_PIC, don't swap a branch with an instruction that uses $at, in case the branch is later expanded. (macro): If EMBEDDED_PIC, case M_JAL_A may use $at. (md_pcrel_from): If not OBJ_AOUT, return 4 for an undefined symbol to make it pcrel_offset. (tc_gen_reloc): If not OBJ_AOUT, set the reloc addend to reloc->address; another gruesome hack to get gas reloc handling to do the right thing. --- gas/ChangeLog | 12 ++++++++ gas/config/tc-mips.c | 66 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 457b34f2682..e81f66a95bb 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,15 @@ +Fri Mar 25 17:35:49 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * config/tc-mips.c (append_insn): If EMBEDDED_PIC, don't swap a + branch with an instruction that uses $at, in case the branch is + later expanded. + (macro): If EMBEDDED_PIC, case M_JAL_A may use $at. + (md_pcrel_from): If not OBJ_AOUT, return 4 for an undefined symbol + to make it pcrel_offset. + (tc_gen_reloc): If not OBJ_AOUT, set the reloc addend to + reloc->address; another gruesome hack to get gas reloc handling to + do the right thing. + Thu Mar 24 21:29:29 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * config/tc-alpha.c (alpha_ip): Only set GP prolog size if using diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index ffc034ee441..08c5bb600a1 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -1067,6 +1067,11 @@ append_insn (place, ip, address_expr, reloc_type) 0)) || ((pinfo & INSN_WRITE_GPR_31) && insn_uses_reg (&prev_insn, 31, 0)) + /* If we are generating embedded PIC code, the branch + might be expanded into a sequence which uses $at, so + we can't swap with an instruction which reads it. */ + || (mips_pic == EMBEDDED_PIC + && insn_uses_reg (&prev_insn, AT, 0)) /* If the previous previous instruction has a load delay, and sets a register that the branch reads, we can not swap. */ @@ -2613,7 +2618,12 @@ macro (ip) } } else if (mips_pic == EMBEDDED_PIC) - macro_build ((char *) NULL, &icnt, &offset_expr, "bal", "p"); + { + macro_build ((char *) NULL, &icnt, &offset_expr, "bal", "p"); + /* The linker may expand the call to a longer sequence which + uses $at, so we must break rather than return. */ + break; + } else abort (); @@ -4917,6 +4927,11 @@ md_parse_option (argP, cntP, vecP) if (strcmp (*argP, "membedded-pic") == 0) { mips_pic = EMBEDDED_PIC; +#ifdef GPOPT + if (g_switch_seen) + as_warn ("-G may not be used with embedded PIC code"); + g_switch_value = 0x7fffffff; +#endif *argP = ""; return 1; } @@ -4932,7 +4947,6 @@ md_parse_option (argP, cntP, vecP) if (g_switch_seen && g_switch_value != 0) as_warn ("-G may not be used with SVR4 PIC code"); g_switch_value = 0; - bfd_set_gp_size (stdoutput, 0); *argP = ""; return 1; } @@ -4947,8 +4961,8 @@ md_parse_option (argP, cntP, vecP) #ifdef GPOPT if (**argP == 'G') { - if (mips_pic == SVR4_PIC) - as_warn ("-G may not be used with SVR4 PIC code"); + if (mips_pic == SVR4_PIC || mips_pic == EMBEDDED_PIC) + as_warn ("-G may not be used with SVR4 or embedded PIC code"); else if ((*argP)[1] != '\0') g_switch_value = atoi (*argP + 1); else if (*cntP) @@ -4995,6 +5009,16 @@ long md_pcrel_from (fixP) fixS *fixP; { +#ifndef OBJ_AOUT + if (fixP->fx_addsy != (symbolS *) NULL + && ! S_IS_DEFINED (fixP->fx_addsy)) + { + /* This makes a branch to an undefined symbol be a branch to the + current location. */ + return 4; + } +#endif + /* return the address of the delay slot */ return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address; } @@ -5028,6 +5052,19 @@ cons_fix_new_mips (frag, where, nbytes, exp) nbytes == 2 ? BFD_RELOC_16 : BFD_RELOC_32); } +/* When generating embedded PIC code we must keep all PC relative + relocations, in case the linker has to relax a call. */ + +/*ARGSUSED*/ +int +mips_force_relocation (fixp) + fixS *fixp; +{ + return mips_pic == EMBEDDED_PIC; +} + +/* Apply a fixup to the object file. */ + int md_apply_fix (fixP, valueP) fixS *fixP; @@ -5041,6 +5078,9 @@ md_apply_fix (fixP, valueP) value = *valueP; fixP->fx_addnumber = value; /* Remember value for tc_gen_reloc */ + if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel) + fixP->fx_done = 1; + switch (fixP->fx_r_type) { case BFD_RELOC_32: @@ -5054,7 +5094,7 @@ md_apply_fix (fixP, valueP) case BFD_RELOC_MIPS_GOT16: case BFD_RELOC_MIPS_GPREL32: /* Nothing needed to do. The value comes from the reloc entry */ - return 1; + break; case BFD_RELOC_16_PCREL_S2: /* @@ -5091,6 +5131,7 @@ md_apply_fix (fixP, valueP) default: internalError (); } + return 1; } @@ -5287,6 +5328,13 @@ s_change_sec (sec) segT seg; #endif + /* When generating embedded PIC code, we only use the .text, .lit8, + .sdata and .sbss sections. We change the .data and .rdata + pseudo-ops to use .sdata. */ + if (mips_pic == EMBEDDED_PIC + && (sec == 'd' || sec == 'r')) + sec = 's'; + mips_emit_delays (); switch (sec) { @@ -5858,11 +5906,15 @@ tc_gen_reloc (section, fixp) if (fixp->fx_pcrel == 0) reloc->addend = fixp->fx_addnumber; else + { #ifndef OBJ_AOUT - reloc->addend = 0; + /* A gruesome hack which is a result of the gruesome gas reloc + handling. */ + reloc->addend = reloc->address; #else - reloc->addend = -reloc->address; + reloc->addend = -reloc->address; #endif + } /* If this is a variant frag, we may need to adjust the existing reloc and generate a new one. */ -- 2.30.2