|
|
|
@ -17,23 +17,118 @@
|
|
|
|
|
along with GAS; see the file COPYING. If not, write to
|
|
|
|
|
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|
|
|
|
|
|
|
|
|
#ifndef TC_I386
|
|
|
|
|
#define TC_I386 1
|
|
|
|
|
|
|
|
|
|
#define AOUT_MACHTYPE 100
|
|
|
|
|
#define REVERSE_SORT_RELOCS
|
|
|
|
|
#ifdef TE_LYNX
|
|
|
|
|
#define TARGET_FORMAT "coff-i386-lynx"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#define NO_LISTING
|
|
|
|
|
#ifdef BFD_ASSEMBLER
|
|
|
|
|
/* This is used to determine relocation types in tc-i386.c. The first
|
|
|
|
|
parameter is the current relocation type, the second one is the desired
|
|
|
|
|
type. The idea is that if the original type is already some kind of PIC
|
|
|
|
|
relocation, we leave it alone, otherwise we give it the desired type */
|
|
|
|
|
|
|
|
|
|
#define TC_RELOC(X,Y) (((X) != BFD_RELOC_386_PLT32 && \
|
|
|
|
|
(X) != BFD_RELOC_386_GOTOFF && \
|
|
|
|
|
(X) != BFD_RELOC_386_GOT32 && \
|
|
|
|
|
(X) != BFD_RELOC_386_GOTPC) ? Y : X)
|
|
|
|
|
|
|
|
|
|
#define tc_fix_adjustable(X) tc_i386_fix_adjustable(X)
|
|
|
|
|
|
|
|
|
|
/* This is the relocation type for direct references to GLOBAL_OFFSET_TABLE.
|
|
|
|
|
* It comes up in complicated expressions such as
|
|
|
|
|
* _GLOBAL_OFFSET_TABLE_+[.-.L284], which cannot be expressed normally with
|
|
|
|
|
* the regular expressions. The fixup specified here when used at runtime
|
|
|
|
|
* implies that we should add the address of the GOT to the specified location,
|
|
|
|
|
* and as a result we have simplified the expression into something we can use.
|
|
|
|
|
*/
|
|
|
|
|
#define TC_RELOC_GLOBAL_OFFSET_TABLE BFD_RELOC_386_GOTPC
|
|
|
|
|
|
|
|
|
|
/* This expression evaluates to false if the relocation is for a local object
|
|
|
|
|
for which we still want to do the relocation at runtime. True if we
|
|
|
|
|
are willing to perform this relocation while building the .o file.
|
|
|
|
|
This is only used for pcrel relocations, so GOTOFF does not need to be
|
|
|
|
|
checked here. I am not sure if some of the others are ever used with
|
|
|
|
|
pcrel, but it is easier to be safe than sorry. */
|
|
|
|
|
|
|
|
|
|
#define TC_RELOC_RTSYM_LOC_FIXUP(X) \
|
|
|
|
|
((X) != BFD_RELOC_386_PLT32 && \
|
|
|
|
|
(X) != BFD_RELOC_386_GOT32 && \
|
|
|
|
|
(X) != BFD_RELOC_386_GOTPC)
|
|
|
|
|
|
|
|
|
|
#define TARGET_ARCH bfd_arch_i386
|
|
|
|
|
#define TARGET_BYTES_BIG_ENDIAN 0
|
|
|
|
|
|
|
|
|
|
#ifdef OBJ_AOUT
|
|
|
|
|
#ifdef TE_NetBSD
|
|
|
|
|
#define TARGET_FORMAT "a.out-i386-netbsd"
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef TE_386BSD
|
|
|
|
|
#define TARGET_FORMAT "a.out-i386-bsd"
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef TE_LINUX
|
|
|
|
|
#define TARGET_FORMAT "a.out-i386-linux"
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef TE_Mach
|
|
|
|
|
#define TARGET_FORMAT "a.out-mach3"
|
|
|
|
|
#endif
|
|
|
|
|
#ifndef TARGET_FORMAT
|
|
|
|
|
#define TARGET_FORMAT "a.out-i386"
|
|
|
|
|
#endif
|
|
|
|
|
#endif /* OBJ_AOUT */
|
|
|
|
|
|
|
|
|
|
#ifdef OBJ_ELF
|
|
|
|
|
#define TARGET_FORMAT "elf32-i386"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#else /* ! BFD_ASSEMBLER */
|
|
|
|
|
|
|
|
|
|
/* COFF STUFF */
|
|
|
|
|
|
|
|
|
|
#define COFF_MAGIC I386MAGIC
|
|
|
|
|
#define BFD_ARCH bfd_arch_i386
|
|
|
|
|
#define COFF_FLAGS F_AR32WR
|
|
|
|
|
#define TC_COUNT_RELOC(x) ((x)->fx_addsy /* ||(x)->fx_subsy||(x)->fx_offset */)
|
|
|
|
|
#define TC_COFF_FIX2RTYPE(fixP) tc_coff_fix2rtype(fixP)
|
|
|
|
|
extern short tc_coff_fix2rtype ();
|
|
|
|
|
#define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep(frag)
|
|
|
|
|
extern int tc_coff_sizemachdep PARAMS ((fragS *frag));
|
|
|
|
|
#define SUB_SEGMENT_ALIGN(SEG) 2
|
|
|
|
|
|
|
|
|
|
/* Need this for PIC relocations */
|
|
|
|
|
#define NEED_FX_R_TYPE
|
|
|
|
|
|
|
|
|
|
#define AOUT_MACHTYPE /* 100 */ 0
|
|
|
|
|
#undef REVERSE_SORT_RELOCS
|
|
|
|
|
|
|
|
|
|
#endif /* ! BFD_ASSEMBLER */
|
|
|
|
|
|
|
|
|
|
#ifdef BFD_ASSEMBLER
|
|
|
|
|
#define NO_RELOC BFD_RELOC_NONE
|
|
|
|
|
#else
|
|
|
|
|
#define NO_RELOC 0
|
|
|
|
|
#endif
|
|
|
|
|
#define tc_coff_symbol_emit_hook(a) ; /* not used */
|
|
|
|
|
|
|
|
|
|
#ifndef OBJ_AOUT
|
|
|
|
|
/* Local labels starts with .L */
|
|
|
|
|
#define LOCAL_LABEL(name) (name[0] == '.' \
|
|
|
|
|
&& (name[1] == 'L' || name[1] == 'X' || name[1] == '.'))
|
|
|
|
|
#define FAKE_LABEL_NAME ".L0\001"
|
|
|
|
|
#endif
|
|
|
|
|
#define LOCAL_LABELS_FB
|
|
|
|
|
|
|
|
|
|
#define tc_aout_pre_write_hook(x) {;} /* not used */
|
|
|
|
|
#define tc_crawl_symbol_chain(a) {;} /* not used */
|
|
|
|
|
#define tc_headers_hook(a) {;} /* not used */
|
|
|
|
|
|
|
|
|
|
#define MAX_OPERANDS 3 /* max operands per insn */
|
|
|
|
|
#define MAX_PREFIXES 4 /* max prefixes per opcode */
|
|
|
|
|
#define MAX_PREFIXES 5 /* max prefixes per opcode */
|
|
|
|
|
#define MAX_IMMEDIATE_OPERANDS 2/* max immediates per insn */
|
|
|
|
|
#define MAX_MEMORY_OPERANDS 2 /* max memory ref per insn
|
|
|
|
|
* lcall uses 2
|
|
|
|
|
*/
|
|
|
|
|
#define MAX_MEMORY_OPERANDS 2 /* max memory ref per insn (lcall uses 2) */
|
|
|
|
|
|
|
|
|
|
/* we define the syntax here (modulo base,index,scale syntax) */
|
|
|
|
|
#define REGISTER_PREFIX '%'
|
|
|
|
|
#define IMMEDIATE_PREFIX '$'
|
|
|
|
@ -41,6 +136,7 @@
|
|
|
|
|
#define PREFIX_SEPERATOR '/'
|
|
|
|
|
|
|
|
|
|
#define TWO_BYTE_OPCODE_ESCAPE 0x0f
|
|
|
|
|
#define NOP_OPCODE (char) 0x90
|
|
|
|
|
|
|
|
|
|
/* register numbers */
|
|
|
|
|
#define EBP_REG_NUM 5
|
|
|
|
@ -125,7 +221,8 @@
|
|
|
|
|
#define SMALLEST_DISP_TYPE(num) \
|
|
|
|
|
fits_in_signed_byte(num) ? (Disp8|Disp32|Abs8|Abs32) : (Disp32|Abs32)
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
/* instruction name sans width suffix ("mov" for movl insns) */
|
|
|
|
|
char *name;
|
|
|
|
|
|
|
|
|
@ -166,6 +263,8 @@ typedef struct {
|
|
|
|
|
#define JumpByte 0x4000
|
|
|
|
|
#define JumpDword 0x8000
|
|
|
|
|
#define ReverseRegRegmem 0x10000
|
|
|
|
|
#define Data16 0x20000 /* needs data prefix if in 32-bit mode */
|
|
|
|
|
#define Data32 0x40000 /* needs data prefix if in 16-bit mode */
|
|
|
|
|
|
|
|
|
|
/* (opcode_modifier & COMES_IN_ALL_SIZES) is true if the
|
|
|
|
|
instuction comes in byte, word, and dword sizes and is encoded into
|
|
|
|
@ -183,7 +282,8 @@ typedef struct {
|
|
|
|
|
'operand_types[i] = Reg|Imm' specifies that operand i can be
|
|
|
|
|
either a register or an immediate operand */
|
|
|
|
|
unsigned int operand_types[3];
|
|
|
|
|
} template;
|
|
|
|
|
}
|
|
|
|
|
template;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
'templates' is for grouping together 'template' structures for opcodes
|
|
|
|
@ -192,41 +292,72 @@ typedef struct {
|
|
|
|
|
The templates themselves start at START and range up to (but not including)
|
|
|
|
|
END.
|
|
|
|
|
*/
|
|
|
|
|
typedef struct {
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
template *start;
|
|
|
|
|
template *end;
|
|
|
|
|
} templates;
|
|
|
|
|
|
|
|
|
|
/* these are for register name --> number & type hash lookup */
|
|
|
|
|
typedef struct {
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
char *reg_name;
|
|
|
|
|
unsigned int reg_type;
|
|
|
|
|
unsigned int reg_num;
|
|
|
|
|
} reg_entry;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
reg_entry;
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
char *seg_name;
|
|
|
|
|
unsigned int seg_prefix;
|
|
|
|
|
} seg_entry;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
seg_entry;
|
|
|
|
|
|
|
|
|
|
/* these are for prefix name --> prefix code hash lookup */
|
|
|
|
|
typedef struct {
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
char *prefix_name;
|
|
|
|
|
unsigned char prefix_code;
|
|
|
|
|
} prefix_entry;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prefix_entry;
|
|
|
|
|
|
|
|
|
|
/* 386 operand encoding bytes: see 386 book for details of this. */
|
|
|
|
|
typedef struct {
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
unsigned regmem:3; /* codes register or memory operand */
|
|
|
|
|
unsigned reg:3; /* codes register operand (or extended opcode) */
|
|
|
|
|
unsigned mode:2; /* how to interpret regmem & reg */
|
|
|
|
|
} modrm_byte;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
modrm_byte;
|
|
|
|
|
|
|
|
|
|
/* 386 opcode byte to code indirect addressing. */
|
|
|
|
|
typedef struct {
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
unsigned base:3;
|
|
|
|
|
unsigned index:3;
|
|
|
|
|
unsigned scale:2;
|
|
|
|
|
} base_index_byte;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
base_index_byte;
|
|
|
|
|
|
|
|
|
|
/* The name of the global offset table generated by the compiler. Allow
|
|
|
|
|
this to be overridden if need be. */
|
|
|
|
|
#ifndef GLOBAL_OFFSET_TABLE_NAME
|
|
|
|
|
#define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef BFD_ASSEMBLER
|
|
|
|
|
void i386_validate_fix ();
|
|
|
|
|
#define TC_VALIDATE_FIX(FIXP,SEGTYPE,SKIP) i386_validate_fix(FIXP)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#endif /* TC_I386 */
|
|
|
|
|
|
|
|
|
|
#define md_operand(x)
|
|
|
|
|
|
|
|
|
|
/* end of tc-i386.h */
|
|
|
|
|