aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorChris Demetriou <cgd@google.com>2001-11-01 01:33:47 +0000
committerChris Demetriou <cgd@google.com>2001-11-01 01:33:47 +0000
commitafdbd6d03b32209a99c57bfe2ee96e87a58a25bc (patch)
tree60c1b65cbc1e9743b1eea0d03fb250c7bf0a3129 /gas/config
parentd45fc520b151732db6a0e87a8684fa6c4f7d9b7a (diff)
downloadgdb-afdbd6d03b32209a99c57bfe2ee96e87a58a25bc.zip
gdb-afdbd6d03b32209a99c57bfe2ee96e87a58a25bc.tar.gz
gdb-afdbd6d03b32209a99c57bfe2ee96e87a58a25bc.tar.bz2
[ bfd/ChangeLog ]
2001-10-31 Chris Demetriou <cgd@demetriou.com> * elf32-mips.c (_bfd_mips_elf_hi16_reloc): Handle PC-relative relocations properly. [ gas/ChangeLog ] 2001-10-31 Chris Demetriou <cgd@broadcom.com> * config/tc-mips.c (HAVE_32BIT_ADDRESSES): If compiling embedded PIC code, assume pointers the same size as GPRs. (macro): In M_LA_AB handling for embedded PIC code, support "la $treg,foo-bar($breg)". In load/store handling (label ld_st) support "<op> $treg,<sym>-<local_sym>($breg)" which is used by the compiler for switch statements. In load/store double multi-instruction macro handling (label ldd_std) add a comment that no special handling is currently done for embedded PIC. (mips_ip): In 'o' (16-bit offset) case, only accept 16 bit offsets. [ gas/testsuite/ChangeLog ] 2001-10-31 Chris Demetriou <cgd@broadcom.com> * gas/mips/empic.s: Undo damage inflicted on 2000-12-02. * gas/mips/empic.d: Likewise. * gas/mips/elempic.d: Likewise (it was copied into other files). * gas/mips/telempic.d: Likewise. * gas/mips/tempic.d: Likewise. * gas/mips/empic2.s: New test to check new 'la' and 'lw' (and related ops) syntax, test loads with large offsets. * gas/mips/emcic2.d: Likewise. * gas/mips/mips.exp: Run the new test on ELF platforms.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-mips.c119
1 files changed, 84 insertions, 35 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 96f13a0..c6a9e0d 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -246,10 +246,11 @@ static int mips_fp32 = 0;
/* We can only have 64bit addresses if the object file format
supports it. */
-#define HAVE_32BIT_ADDRESSES \
- (HAVE_32BIT_GPRS \
- || bfd_arch_bits_per_address (stdoutput) == 32 \
- || ! HAVE_64BIT_OBJECTS)
+#define HAVE_32BIT_ADDRESSES \
+ (HAVE_32BIT_GPRS \
+ || ((bfd_arch_bits_per_address (stdoutput) == 32 \
+ || ! HAVE_64BIT_OBJECTS) \
+ && mips_pic != EMBEDDED_PIC))
#define HAVE_64BIT_ADDRESSES (! HAVE_32BIT_ADDRESSES)
@@ -4447,9 +4448,21 @@ macro (ip)
/* Load the address of a symbol into a register. If breg is not
zero, we then add a base register to it. */
+ if (treg == breg)
+ {
+ tempreg = AT;
+ used_at = 1;
+ }
+ else
+ {
+ tempreg = treg;
+ used_at = 0;
+ }
+
/* When generating embedded PIC code, we permit expressions of
the form
- la $4,foo-bar
+ la $treg,foo-bar
+ la $treg,foo-bar($breg)
where bar is an address in the current section. These are used
when getting the addresses of functions. We don't permit
X_add_number to be non-zero, because if the symbol is
@@ -4464,16 +4477,30 @@ macro (ip)
(symbol_get_value_expression (offset_expr.X_op_symbol)
->X_add_symbol)
== now_seg)))
- && breg == 0
&& (offset_expr.X_add_number == 0
|| OUTPUT_FLAVOR == bfd_target_elf_flavour))
{
- macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
- treg, (int) BFD_RELOC_PCREL_HI16_S);
+ if (breg == 0)
+ {
+ tempreg = treg;
+ used_at = 0;
+ macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
+ tempreg, (int) BFD_RELOC_PCREL_HI16_S);
+ }
+ else
+ {
+ macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
+ tempreg, (int) BFD_RELOC_PCREL_HI16_S);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
+ "d,v,t", tempreg, tempreg, breg);
+ }
macro_build ((char *) NULL, &icnt, &offset_expr,
HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu",
- "t,r,j", treg, treg, (int) BFD_RELOC_PCREL_LO16);
- return;
+ "t,r,j", treg, tempreg, (int) BFD_RELOC_PCREL_LO16);
+ if (! used_at)
+ return;
+ break;
}
if (offset_expr.X_op != O_symbol
@@ -4483,17 +4510,6 @@ macro (ip)
offset_expr.X_op = O_constant;
}
- if (treg == breg)
- {
- tempreg = AT;
- used_at = 1;
- }
- else
- {
- tempreg = treg;
- used_at = 0;
- }
-
if (offset_expr.X_op == O_constant)
load_register (&icnt, tempreg, &offset_expr, dbl);
else if (mips_pic == NO_PIC)
@@ -5289,6 +5305,46 @@ macro (ip)
else
fmt = "t,o(b)";
+ /* For embedded PIC, we allow loads where the offset is calculated
+ by subtracting a symbol in the current segment from an unknown
+ symbol, relative to a base register, e.g.:
+ <op> $treg, <sym>-<localsym>($breg)
+ This is used by the compiler for switch statements. */
+ if (mips_pic == EMBEDDED_PIC
+ && offset_expr.X_op == O_subtract
+ && (symbol_constant_p (offset_expr.X_op_symbol)
+ ? S_GET_SEGMENT (offset_expr.X_op_symbol) == now_seg
+ : (symbol_equated_p (offset_expr.X_op_symbol)
+ && (S_GET_SEGMENT
+ (symbol_get_value_expression (offset_expr.X_op_symbol)
+ ->X_add_symbol)
+ == now_seg)))
+ && breg != 0
+ && (offset_expr.X_add_number == 0
+ || OUTPUT_FLAVOR == bfd_target_elf_flavour))
+ {
+ /* For this case, we output the instructions:
+ lui $tempreg,<sym> (BFD_RELOC_PCREL_HI16_S)
+ addiu $tempreg,$tempreg,$breg
+ <op> $treg,<sym>($tempreg) (BFD_RELOC_PCREL_LO16)
+ If the relocation would fit entirely in 16 bits, it would be
+ nice to emit:
+ <op> $treg,<sym>($breg) (BFD_RELOC_PCREL_LO16)
+ instead, but that seems quite difficult. */
+ macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
+ tempreg, (int) BFD_RELOC_PCREL_HI16_S);
+ macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
+ ((bfd_arch_bits_per_address (stdoutput) == 32
+ || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
+ ? "addu" : "daddu"),
+ "d,v,t", tempreg, tempreg, breg);
+ macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt, treg,
+ (int) BFD_RELOC_PCREL_LO16, tempreg);
+ if (! used_at)
+ return;
+ break;
+ }
+
if (offset_expr.X_op != O_constant
&& offset_expr.X_op != O_symbol)
{
@@ -5893,6 +5949,11 @@ macro (ip)
fmt = "t,o(b)";
ldd_std:
+ /* We do _not_ bother to allow embedded PIC (symbol-local_symbol)
+ loads for the case of doing a pair of loads to simulate an 'ld'.
+ This is not currently done by the compiler, and assembly coders
+ writing embedded-pic code can cope. */
+
if (offset_expr.X_op != O_symbol
&& offset_expr.X_op != O_constant)
{
@@ -8216,23 +8277,11 @@ mips_ip (str, ip)
/* If this value won't fit into a 16 bit offset, then go
find a macro that will generate the 32 bit offset
- code pattern. As a special hack, we accept the
- difference of two local symbols as a constant. This
- is required to suppose embedded PIC switches, which
- use an instruction which looks like
- lw $4,$L12-$LS12($4)
- The problem with handling this in a more general
- fashion is that the macro function doesn't expect to
- see anything which can be handled in a single
- constant instruction. */
+ code pattern. */
if (c == S_EX_NONE
&& (offset_expr.X_op != O_constant
|| offset_expr.X_add_number >= 0x8000
- || offset_expr.X_add_number < -0x8000)
- && (mips_pic != EMBEDDED_PIC
- || offset_expr.X_op != O_subtract
- || (S_GET_SEGMENT (offset_expr.X_add_symbol)
- != S_GET_SEGMENT (offset_expr.X_op_symbol))))
+ || offset_expr.X_add_number < -0x8000))
break;
if (c == S_EX_HI)