mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-28 14:30:48 +00:00
`.arch cpu_type' pseudo for x86.
This commit is contained in:
parent
5ee1baa27d
commit
e413e4e996
@ -1,3 +1,23 @@
|
||||
2000-05-13 Alan Modra <alan@linuxcare.com.au>
|
||||
Alexander Sokolov <robocop@netlink.ru>
|
||||
|
||||
* doc/c-i386.texi (i386-Arch): New section.
|
||||
(i386-Syntax): Mention .intel_syntax and .att_syntax.
|
||||
|
||||
* config/tc-i386.c (cpu_arch_name, cpu_arch_flags): New.
|
||||
(smallest_imm_type): Use smallest opcode for shift by one if cpu
|
||||
architecture has been given and is not 486.
|
||||
(set_cpu_arch): New.
|
||||
(md_pseudo_table): Add .arch.
|
||||
(md_assemble): Warn if cpu architecture has been given and an
|
||||
unsupported instruction.
|
||||
|
||||
* config/tc-i386.h (SMALLEST_DISP_TYPE): Delete.
|
||||
Move operand_types bit defines after relevant template field.
|
||||
(template): Add cpu_flags.
|
||||
(Cpu*): Define.
|
||||
(arch_entry): New.
|
||||
|
||||
2000-05-12 Alexandre Oliva <aoliva@cygnus.com>
|
||||
|
||||
* config/tc-mn10300.h (md_end): Define.
|
||||
|
@ -62,6 +62,7 @@ static int add_prefix PARAMS ((unsigned int));
|
||||
static void set_16bit_code_flag PARAMS ((int));
|
||||
static void set_16bit_gcc_code_flag PARAMS((int));
|
||||
static void set_intel_syntax PARAMS ((int));
|
||||
static void set_cpu_arch PARAMS ((int));
|
||||
|
||||
#ifdef BFD_ASSEMBLER
|
||||
static bfd_reloc_code_real_type reloc
|
||||
@ -216,15 +217,20 @@ static const templates *current_templates;
|
||||
/* Per instruction expressionS buffers: 2 displacements & 2 immediate max. */
|
||||
static expressionS disp_expressions[2], im_expressions[2];
|
||||
|
||||
static int this_operand; /* current operand we are working on */
|
||||
static int this_operand; /* Current operand we are working on. */
|
||||
|
||||
static int flag_do_long_jump; /* FIXME what does this do? */
|
||||
static int flag_do_long_jump; /* FIXME what does this do? */
|
||||
|
||||
static int flag_16bit_code; /* 1 if we're writing 16-bit code, 0 if 32-bit */
|
||||
static int flag_16bit_code; /* 1 if we're writing 16-bit code,
|
||||
0 if 32-bit. */
|
||||
|
||||
static int intel_syntax = 0; /* 1 for intel syntax, 0 if att syntax */
|
||||
static int intel_syntax = 0; /* 1 for intel syntax, 0 if att syntax. */
|
||||
|
||||
static int allow_naked_reg = 0; /* 1 if register prefix % not required */
|
||||
static const char *cpu_arch_name = NULL; /* cpu name */
|
||||
|
||||
static unsigned int cpu_arch_flags = 0; /* cpu feature flags */
|
||||
|
||||
static int allow_naked_reg = 0; /* 1 if register prefix % not required */
|
||||
|
||||
static char stackop_size = '\0'; /* Used in 16 bit gcc mode to add an l
|
||||
suffix to call, ret, enter, leave, push,
|
||||
@ -301,6 +307,21 @@ const relax_typeS md_relax_table[] =
|
||||
|
||||
};
|
||||
|
||||
static const arch_entry cpu_arch[] = {
|
||||
{"i8086", Cpu086 },
|
||||
{"i186", Cpu086|Cpu186 },
|
||||
{"i286", Cpu086|Cpu186|Cpu286 },
|
||||
{"i386", Cpu086|Cpu186|Cpu286|Cpu386 },
|
||||
{"i486", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486 },
|
||||
{"i586", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuMMX },
|
||||
{"i686", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX|CpuSSE },
|
||||
{"pentium", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuMMX },
|
||||
{"pentiumpro",Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX|CpuSSE },
|
||||
{"k6", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuMMX|Cpu3dnow },
|
||||
{"athlon", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX|Cpu3dnow },
|
||||
{NULL, 0 }
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
i386_align_code (fragP, count)
|
||||
@ -441,16 +462,17 @@ static int
|
||||
smallest_imm_type (num)
|
||||
offsetT num;
|
||||
{
|
||||
#if 0
|
||||
/* This code is disabled because all the Imm1 forms in the opcode table
|
||||
are slower on the i486, and they're the versions with the implicitly
|
||||
specified single-position displacement, which has another syntax if
|
||||
you really want to use that form. If you really prefer to have the
|
||||
one-byte-shorter Imm1 form despite these problems, re-enable this
|
||||
code. */
|
||||
if (num == 1)
|
||||
return Imm1 | Imm8 | Imm8S | Imm16 | Imm32;
|
||||
#endif
|
||||
if (cpu_arch_flags != 0
|
||||
&& cpu_arch_flags != (Cpu086|Cpu186|Cpu286|Cpu386|Cpu486))
|
||||
{
|
||||
/* This code is disabled on the 486 because all the Imm1 forms
|
||||
in the opcode table are slower on the i486. They're the
|
||||
versions with the implicitly specified single-position
|
||||
displacement, which has another syntax if you really want to
|
||||
use that form. */
|
||||
if (num == 1)
|
||||
return Imm1 | Imm8 | Imm8S | Imm16 | Imm32;
|
||||
}
|
||||
return (fits_in_signed_byte (num)
|
||||
? (Imm8S | Imm8 | Imm16 | Imm32)
|
||||
: fits_in_unsigned_byte (num)
|
||||
@ -600,15 +622,48 @@ set_intel_syntax (syntax_flag)
|
||||
allow_naked_reg = (ask_naked_reg < 0);
|
||||
}
|
||||
|
||||
static void
|
||||
set_cpu_arch (dummy)
|
||||
int dummy ATTRIBUTE_UNUSED;
|
||||
{
|
||||
SKIP_WHITESPACE();
|
||||
|
||||
if (! is_end_of_line[(unsigned char) *input_line_pointer])
|
||||
{
|
||||
char *string = input_line_pointer;
|
||||
int e = get_symbol_end ();
|
||||
int i;
|
||||
|
||||
for (i = 0; cpu_arch[i].name; i++)
|
||||
{
|
||||
if (strcmp (string, cpu_arch[i].name) == 0)
|
||||
{
|
||||
cpu_arch_name = cpu_arch[i].name;
|
||||
cpu_arch_flags = cpu_arch[i].flags;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!cpu_arch[i].name)
|
||||
as_bad (_("no such architecture: `%s'"), string);
|
||||
|
||||
*input_line_pointer = e;
|
||||
}
|
||||
else
|
||||
as_bad (_("missing cpu architecture"));
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
const pseudo_typeS md_pseudo_table[] =
|
||||
{
|
||||
#ifndef I386COFF
|
||||
{"bss", s_bss, 0},
|
||||
#endif
|
||||
#if !defined(OBJ_AOUT) && !defined(USE_ALIGN_PTWO)
|
||||
{"align", s_align_bytes, 0},
|
||||
#else
|
||||
{"align", s_align_ptwo, 0},
|
||||
#endif
|
||||
{"arch", set_cpu_arch, 0},
|
||||
#ifndef I386COFF
|
||||
{"bss", s_bss, 0},
|
||||
#endif
|
||||
{"ffloat", float_cons, 'f'},
|
||||
{"dfloat", float_cons, 'd'},
|
||||
@ -1058,7 +1113,7 @@ md_assemble (line)
|
||||
mnem_p++;
|
||||
if (mnem_p >= mnemonic + sizeof (mnemonic))
|
||||
{
|
||||
as_bad (_("no such 386 instruction: `%s'"), token_start);
|
||||
as_bad (_("no such instruction: `%s'"), token_start);
|
||||
return;
|
||||
}
|
||||
l++;
|
||||
@ -1141,11 +1196,25 @@ md_assemble (line)
|
||||
}
|
||||
if (!current_templates)
|
||||
{
|
||||
as_bad (_("no such 386 instruction: `%s'"), token_start);
|
||||
as_bad (_("no such instruction: `%s'"), token_start);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if instruction is supported on specified architecture. */
|
||||
if (cpu_arch_flags != 0)
|
||||
{
|
||||
if (current_templates->start->cpu_flags & ~ cpu_arch_flags)
|
||||
{
|
||||
as_warn (_("`%s' is not supported on `%s'"),
|
||||
current_templates->start->name, cpu_arch_name);
|
||||
}
|
||||
else if ((Cpu386 & ~ cpu_arch_flags) && !flag_16bit_code)
|
||||
{
|
||||
as_warn (_("use .code16 to ensure correct addressing mode"));
|
||||
}
|
||||
}
|
||||
|
||||
/* check for rep/repne without a string instruction */
|
||||
if (expecting_string_instruction
|
||||
&& !(current_templates->start->opcode_modifier & IsString))
|
||||
|
@ -239,77 +239,7 @@ extern const char extra_symbol_chars[];
|
||||
#define OFFSET_FLAT 6
|
||||
#define FLAT 7
|
||||
#define NONE_FOUND 8
|
||||
/*
|
||||
When an operand is read in it is classified by its type. This type includes
|
||||
all the possible ways an operand can be used. Thus, '%eax' is both 'register
|
||||
# 0' and 'The Accumulator'. In our language this is expressed by OR'ing
|
||||
'Reg32' (any 32 bit register) and 'Acc' (the accumulator).
|
||||
Operands are classified so that we can match given operand types with
|
||||
the opcode table in opcode/i386.h.
|
||||
*/
|
||||
/* register */
|
||||
#define Reg8 0x1 /* 8 bit reg */
|
||||
#define Reg16 0x2 /* 16 bit reg */
|
||||
#define Reg32 0x4 /* 32 bit reg */
|
||||
/* immediate */
|
||||
#define Imm8 0x8 /* 8 bit immediate */
|
||||
#define Imm8S 0x10 /* 8 bit immediate sign extended */
|
||||
#define Imm16 0x20 /* 16 bit immediate */
|
||||
#define Imm32 0x40 /* 32 bit immediate */
|
||||
#define Imm1 0x80 /* 1 bit immediate */
|
||||
/* memory */
|
||||
#define BaseIndex 0x100
|
||||
/* Disp8,16,32 are used in different ways, depending on the
|
||||
instruction. For jumps, they specify the size of the PC relative
|
||||
displacement, for baseindex type instructions, they specify the
|
||||
size of the offset relative to the base register, and for memory
|
||||
offset instructions such as `mov 1234,%al' they specify the size of
|
||||
the offset relative to the segment base. */
|
||||
#define Disp8 0x200 /* 8 bit displacement */
|
||||
#define Disp16 0x400 /* 16 bit displacement */
|
||||
#define Disp32 0x800 /* 32 bit displacement */
|
||||
/* specials */
|
||||
#define InOutPortReg 0x1000 /* register to hold in/out port addr = dx */
|
||||
#define ShiftCount 0x2000 /* register to hold shift cound = cl */
|
||||
#define Control 0x4000 /* Control register */
|
||||
#define Debug 0x8000 /* Debug register */
|
||||
#define Test 0x10000 /* Test register */
|
||||
#define FloatReg 0x20000 /* Float register */
|
||||
#define FloatAcc 0x40000 /* Float stack top %st(0) */
|
||||
#define SReg2 0x80000 /* 2 bit segment register */
|
||||
#define SReg3 0x100000 /* 3 bit segment register */
|
||||
#define Acc 0x200000 /* Accumulator %al or %ax or %eax */
|
||||
#define JumpAbsolute 0x400000
|
||||
#define RegMMX 0x800000 /* MMX register */
|
||||
#define RegXMM 0x1000000 /* XMM registers in PIII */
|
||||
#define EsSeg 0x2000000 /* String insn operand with fixed es segment */
|
||||
/* InvMem is for instructions with a modrm byte that only allow a
|
||||
general register encoding in the i.tm.mode and i.tm.regmem fields,
|
||||
eg. control reg moves. They really ought to support a memory form,
|
||||
but don't, so we add an InvMem flag to the register operand to
|
||||
indicate that it should be encoded in the i.tm.regmem field. */
|
||||
#define InvMem 0x4000000
|
||||
|
||||
#define Reg (Reg8|Reg16|Reg32) /* gen'l register */
|
||||
#define WordReg (Reg16|Reg32)
|
||||
#define ImplicitRegister (InOutPortReg|ShiftCount|Acc|FloatAcc)
|
||||
#define Imm (Imm8|Imm8S|Imm16|Imm32) /* gen'l immediate */
|
||||
#define Disp (Disp8|Disp16|Disp32) /* General displacement */
|
||||
#define AnyMem (Disp|BaseIndex|InvMem) /* General memory */
|
||||
/* The following aliases are defined because the opcode table
|
||||
carefully specifies the allowed memory types for each instruction.
|
||||
At the moment we can only tell a memory reference size by the
|
||||
instruction suffix, so there's not much point in defining Mem8,
|
||||
Mem16, Mem32 and Mem64 opcode modifiers - We might as well just use
|
||||
the suffix directly to check memory operands. */
|
||||
#define LLongMem AnyMem /* 64 bits (or more) */
|
||||
#define LongMem AnyMem /* 32 bit memory ref */
|
||||
#define ShortMem AnyMem /* 16 bit memory ref */
|
||||
#define WordMem AnyMem /* 16 or 32 bit memory ref */
|
||||
#define ByteMem AnyMem /* 8 bit memory ref */
|
||||
|
||||
#define SMALLEST_DISP_TYPE(num) \
|
||||
(fits_in_signed_byte(num) ? (Disp8|Disp32) : Disp32)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -330,6 +260,19 @@ typedef struct
|
||||
unsigned int extension_opcode;
|
||||
#define None 0xffff /* If no extension_opcode is possible. */
|
||||
|
||||
/* cpu feature flags */
|
||||
unsigned int cpu_flags;
|
||||
#define Cpu086 0x1 /* Any old cpu will do, 0 does the same */
|
||||
#define Cpu186 0x2 /* i186 or better required */
|
||||
#define Cpu286 0x4 /* i286 or better required */
|
||||
#define Cpu386 0x8 /* i386 or better required */
|
||||
#define Cpu486 0x10 /* i486 or better required */
|
||||
#define Cpu586 0x20 /* i585 or better required */
|
||||
#define Cpu686 0x40 /* i686 or better required */
|
||||
#define CpuMMX 0x80 /* MMX support required */
|
||||
#define CpuSSE 0x100 /* Streaming SIMD extensions required */
|
||||
#define Cpu3dnow 0x200 /* 3dnow! support required */
|
||||
|
||||
/* the bits in opcode_modifier are used to generate the final opcode from
|
||||
the base_opcode. These bits also are used to detect alternate forms of
|
||||
the same instruction */
|
||||
@ -371,8 +314,70 @@ typedef struct
|
||||
/* operand_types[i] describes the type of operand i. This is made
|
||||
by OR'ing together all of the possible type masks. (e.g.
|
||||
'operand_types[i] = Reg|Imm' specifies that operand i can be
|
||||
either a register or an immediate operand */
|
||||
either a register or an immediate operand. */
|
||||
unsigned int operand_types[3];
|
||||
|
||||
/* operand_types[i] bits */
|
||||
/* register */
|
||||
#define Reg8 0x1 /* 8 bit reg */
|
||||
#define Reg16 0x2 /* 16 bit reg */
|
||||
#define Reg32 0x4 /* 32 bit reg */
|
||||
/* immediate */
|
||||
#define Imm8 0x8 /* 8 bit immediate */
|
||||
#define Imm8S 0x10 /* 8 bit immediate sign extended */
|
||||
#define Imm16 0x20 /* 16 bit immediate */
|
||||
#define Imm32 0x40 /* 32 bit immediate */
|
||||
#define Imm1 0x80 /* 1 bit immediate */
|
||||
/* memory */
|
||||
#define BaseIndex 0x100
|
||||
/* Disp8,16,32 are used in different ways, depending on the
|
||||
instruction. For jumps, they specify the size of the PC relative
|
||||
displacement, for baseindex type instructions, they specify the
|
||||
size of the offset relative to the base register, and for memory
|
||||
offset instructions such as `mov 1234,%al' they specify the size of
|
||||
the offset relative to the segment base. */
|
||||
#define Disp8 0x200 /* 8 bit displacement */
|
||||
#define Disp16 0x400 /* 16 bit displacement */
|
||||
#define Disp32 0x800 /* 32 bit displacement */
|
||||
/* specials */
|
||||
#define InOutPortReg 0x1000 /* register to hold in/out port addr = dx */
|
||||
#define ShiftCount 0x2000 /* register to hold shift cound = cl */
|
||||
#define Control 0x4000 /* Control register */
|
||||
#define Debug 0x8000 /* Debug register */
|
||||
#define Test 0x10000 /* Test register */
|
||||
#define FloatReg 0x20000 /* Float register */
|
||||
#define FloatAcc 0x40000 /* Float stack top %st(0) */
|
||||
#define SReg2 0x80000 /* 2 bit segment register */
|
||||
#define SReg3 0x100000 /* 3 bit segment register */
|
||||
#define Acc 0x200000 /* Accumulator %al or %ax or %eax */
|
||||
#define JumpAbsolute 0x400000
|
||||
#define RegMMX 0x800000 /* MMX register */
|
||||
#define RegXMM 0x1000000 /* XMM registers in PIII */
|
||||
#define EsSeg 0x2000000 /* String insn operand with fixed es segment */
|
||||
/* InvMem is for instructions with a modrm byte that only allow a
|
||||
general register encoding in the i.tm.mode and i.tm.regmem fields,
|
||||
eg. control reg moves. They really ought to support a memory form,
|
||||
but don't, so we add an InvMem flag to the register operand to
|
||||
indicate that it should be encoded in the i.tm.regmem field. */
|
||||
#define InvMem 0x4000000
|
||||
|
||||
#define Reg (Reg8|Reg16|Reg32) /* gen'l register */
|
||||
#define WordReg (Reg16|Reg32)
|
||||
#define ImplicitRegister (InOutPortReg|ShiftCount|Acc|FloatAcc)
|
||||
#define Imm (Imm8|Imm8S|Imm16|Imm32) /* gen'l immediate */
|
||||
#define Disp (Disp8|Disp16|Disp32) /* General displacement */
|
||||
#define AnyMem (Disp|BaseIndex|InvMem) /* General memory */
|
||||
/* The following aliases are defined because the opcode table
|
||||
carefully specifies the allowed memory types for each instruction.
|
||||
At the moment we can only tell a memory reference size by the
|
||||
instruction suffix, so there's not much point in defining Mem8,
|
||||
Mem16, Mem32 and Mem64 opcode modifiers - We might as well just use
|
||||
the suffix directly to check memory operands. */
|
||||
#define LLongMem AnyMem /* 64 bits (or more) */
|
||||
#define LongMem AnyMem /* 32 bit memory ref */
|
||||
#define ShortMem AnyMem /* 16 bit memory ref */
|
||||
#define WordMem AnyMem /* 16 or 32 bit memory ref */
|
||||
#define ByteMem AnyMem /* 8 bit memory ref */
|
||||
}
|
||||
template;
|
||||
|
||||
@ -384,45 +389,54 @@ template;
|
||||
END.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const template *start;
|
||||
const template *end;
|
||||
} templates;
|
||||
{
|
||||
const template *start;
|
||||
const template *end;
|
||||
}
|
||||
templates;
|
||||
|
||||
/* these are for register name --> number & type hash lookup */
|
||||
typedef struct
|
||||
{
|
||||
char *reg_name;
|
||||
unsigned int reg_type;
|
||||
unsigned int reg_num;
|
||||
}
|
||||
{
|
||||
char *reg_name;
|
||||
unsigned int reg_type;
|
||||
unsigned int reg_num;
|
||||
}
|
||||
reg_entry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *seg_name;
|
||||
unsigned int seg_prefix;
|
||||
}
|
||||
{
|
||||
char *seg_name;
|
||||
unsigned int seg_prefix;
|
||||
}
|
||||
seg_entry;
|
||||
|
||||
/* 386 operand encoding bytes: see 386 book for details of this. */
|
||||
typedef struct
|
||||
{
|
||||
unsigned int regmem; /* codes register or memory operand */
|
||||
unsigned int reg; /* codes register operand (or extended opcode) */
|
||||
unsigned int mode; /* how to interpret regmem & reg */
|
||||
}
|
||||
{
|
||||
unsigned int regmem; /* codes register or memory operand */
|
||||
unsigned int reg; /* codes register operand (or extended opcode) */
|
||||
unsigned int mode; /* how to interpret regmem & reg */
|
||||
}
|
||||
modrm_byte;
|
||||
|
||||
/* 386 opcode byte to code indirect addressing. */
|
||||
typedef struct
|
||||
{
|
||||
unsigned base;
|
||||
unsigned index;
|
||||
unsigned scale;
|
||||
}
|
||||
{
|
||||
unsigned base;
|
||||
unsigned index;
|
||||
unsigned scale;
|
||||
}
|
||||
sib_byte;
|
||||
|
||||
/* x86 arch names and features */
|
||||
typedef struct
|
||||
{
|
||||
const char *name; /* arch name */
|
||||
unsigned int flags; /* cpu feature flags */
|
||||
}
|
||||
arch_entry;
|
||||
|
||||
/* The name of the global offset table generated by the compiler. Allow
|
||||
this to be overridden if need be. */
|
||||
#ifndef GLOBAL_OFFSET_TABLE_NAME
|
||||
|
@ -24,6 +24,7 @@
|
||||
* i386-Float:: Floating Point
|
||||
* i386-SIMD:: Intel's MMX and AMD's 3DNow! SIMD Operations
|
||||
* i386-16bit:: Writing 16-bit Code
|
||||
* i386-Arch:: Specifying an x86 CPU architecture
|
||||
* i386-Bugs:: AT&T Syntax bugs
|
||||
* i386-Notes:: Notes
|
||||
@end menu
|
||||
@ -35,13 +36,23 @@
|
||||
@cindex i386 options (none)
|
||||
The 80386 has no machine dependent options.
|
||||
|
||||
|
||||
@node i386-Syntax
|
||||
@section AT&T Syntax versus Intel Syntax
|
||||
|
||||
@cindex i386 intel_syntax pseudo op
|
||||
@cindex intel_syntax pseudo op, i386
|
||||
@cindex i386 att_syntax pseudo op
|
||||
@cindex att_syntax pseudo op, i386
|
||||
@cindex i386 syntax compatibility
|
||||
@cindex syntax compatibility, i386
|
||||
In order to maintain compatibility with the output of @code{@value{GCC}},
|
||||
@code{@value{AS}} supports AT&T System V/386 assembler syntax. This is quite
|
||||
|
||||
@code{@value{AS}} now supports assembly using Intel assembler syntax.
|
||||
@code{.intel_syntax} selects Intel mode, and @code{.att_syntax} switches
|
||||
back to the usual AT&T mode for compatibility with the output of
|
||||
@code{@value{GCC}}. Either of these directives may have an optional
|
||||
argument, @code{prefix}, or @code{noprefix} specifying whether registers
|
||||
require a @samp{%} prefix. AT&T System V/386 assembler syntax is quite
|
||||
different from Intel syntax. We mention these differences because
|
||||
almost all 80386 documents use Intel syntax. Notable differences
|
||||
between the two syntaxes are:
|
||||
@ -506,6 +517,31 @@ non-commutative arithmetic floating point operations with two register
|
||||
operands where the source register is @samp{%st} and the destination
|
||||
register is @samp{%st(i)}.
|
||||
|
||||
@node i386-Arch
|
||||
@section Specifying CPU Architecture
|
||||
|
||||
@cindex arch directive, i386
|
||||
@cindex i386 arch directive
|
||||
|
||||
@code{@value{AS}} may be told to assemble for a particular CPU
|
||||
architecture with the @code{.arch @var{cpu_type}} directive. This
|
||||
directive enables a warning when gas detects an instruction that is not
|
||||
supported on the CPU specified. The choices for @var{cpu_type} are:
|
||||
|
||||
@multitable @columnfractions .20 .20 .20 .20
|
||||
@item @samp{i8086} @tab @samp{i186} @tab @samp{i286} @tab @samp{i386}
|
||||
@item @samp{i486} @tab @samp{i586} @tab @samp{i686} @tab @samp{pentium}
|
||||
@item @samp{pentiumpro} @tab @samp{k6} @tab @samp{athlon}
|
||||
@end multitable
|
||||
|
||||
Apart from the warning, there is only one other effect on
|
||||
@code{@value{AS}} operation; If you specify a CPU other than
|
||||
@samp{i486}, then shift by one instructions such as @samp{sarl $1, %eax}
|
||||
will automatically use a two byte opcode sequence. The larger three
|
||||
byte opcode sequence is used on the 486 (and when no architecture is
|
||||
specified) because it executes faster on the 486. Note that you can
|
||||
explicitly request the two byte opcode by writing @samp{sarl %eax}.
|
||||
|
||||
@node i386-Notes
|
||||
@section Notes
|
||||
|
||||
|
@ -1,3 +1,13 @@
|
||||
2000-05-13 Alan Modra <alan@linuxcare.com.au>,
|
||||
Alexander Sokolov <robocop@netlink.ru>
|
||||
|
||||
* i386.h (i386_optab): Add cpu_flags for all instructions.
|
||||
|
||||
2000-05-13 Alan Modra <alan@linuxcare.com.au>
|
||||
|
||||
From Gavin Romig-Koch <gavin@cygnus.com>
|
||||
* i386.h (wld_Suf): Define. Use on pushf, popf, pusha, popa.
|
||||
|
||||
2000-05-04 Timothy Wall <twall@cygnus.com>
|
||||
|
||||
* tic54x.h: New.
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user