summaryrefslogtreecommitdiff
path: root/gas/config/tc-i386.c
diff options
context:
space:
mode:
Diffstat (limited to 'gas/config/tc-i386.c')
-rw-r--r--gas/config/tc-i386.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 72a4eb3820e..96d2e1e6a32 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -2934,6 +2934,7 @@ tc_i386_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED)
|| fixP->fx_r_type == BFD_RELOC_386_GOTOFF
|| fixP->fx_r_type == BFD_RELOC_386_PLT32
|| fixP->fx_r_type == BFD_RELOC_386_GOT32
+ || fixP->fx_r_type == BFD_RELOC_386_LOAD_GOT32
|| fixP->fx_r_type == BFD_RELOC_386_TLS_GD
|| fixP->fx_r_type == BFD_RELOC_386_TLS_LDM
|| fixP->fx_r_type == BFD_RELOC_386_TLS_LDO_32
@@ -3713,6 +3714,20 @@ md_assemble (char *line)
}
}
+ /* We don't check BFD_RELOC_X86_64_GOTPCREL here since it is set
+ by i386_validate_fix from BFD_RELOC_32_PCREL. */
+ if (i.reloc[0] == BFD_RELOC_386_GOT32)
+ {
+ if (i.operands == 1
+ && t->base_opcode == 0xff
+ && (t->extension_opcode == 2 || t->extension_opcode == 4))
+ /* call/jmp *foo@GOT[(%reg]) */
+ i.reloc[0] = BFD_RELOC_386_LOAD_GOT32;
+ else if (i.operands == 2 && i.tm.base_opcode == 0x8b)
+ /* mov foo@GOT[(%reg]), %reg */
+ i.reloc[0] = BFD_RELOC_386_LOAD_GOT32;
+ }
+
if (i.rex != 0)
add_prefix (REX_OPCODE | i.rex);
@@ -4798,6 +4813,10 @@ match_template (void)
}
}
+ /* Force 0x8b encoding for "mov foo@GOT, %eax". */
+ if (i.reloc[0] == BFD_RELOC_386_GOT32 && t->base_opcode == 0xa0)
+ continue;
+
/* We check register size if needed. */
check_register = t->opcode_modifier.checkregsize;
overlap0 = operand_type_and (i.types[0], operand_types[0]);
@@ -10396,6 +10415,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
case BFD_RELOC_X86_64_INDBR_GOTPCREL:
case BFD_RELOC_386_PLT32:
case BFD_RELOC_386_GOT32:
+ case BFD_RELOC_386_LOAD_GOT32:
case BFD_RELOC_386_GOTOFF:
case BFD_RELOC_386_GOTPC:
case BFD_RELOC_386_TLS_GD: