X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-i386.c;h=80a1ac836683601914fb350358dc3b363e951eaf;hb=192dc9c6fdb23ca962c3be3053dda8753dc0b065;hp=fd79330487de15bc58c0977aa6201e788488055a;hpb=9a04903eea44cbc4642f10d2a8f8db416a694737;p=platform%2Fupstream%2Fbinutils.git diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index fd79330..80a1ac8 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -1,6 +1,6 @@ /* tc-i386.c -- Assemble code for the Intel 80386 Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -55,9 +55,132 @@ #endif #endif +/* Prefixes will be emitted in the order defined below. + WAIT_PREFIX must be the first prefix since FWAIT is really is an + instruction, and so must come before any prefixes. + The preferred prefix order is SEG_PREFIX, ADDR_PREFIX, DATA_PREFIX, + LOCKREP_PREFIX. */ +#define WAIT_PREFIX 0 +#define SEG_PREFIX 1 +#define ADDR_PREFIX 2 +#define DATA_PREFIX 3 +#define LOCKREP_PREFIX 4 +#define REX_PREFIX 5 /* must come last. */ +#define MAX_PREFIXES 6 /* max prefixes per opcode */ + +/* we define the syntax here (modulo base,index,scale syntax) */ +#define REGISTER_PREFIX '%' +#define IMMEDIATE_PREFIX '$' +#define ABSOLUTE_PREFIX '*' + +/* these are the instruction mnemonic suffixes in AT&T syntax or + memory operand size in Intel syntax. */ +#define WORD_MNEM_SUFFIX 'w' +#define BYTE_MNEM_SUFFIX 'b' +#define SHORT_MNEM_SUFFIX 's' +#define LONG_MNEM_SUFFIX 'l' +#define QWORD_MNEM_SUFFIX 'q' +#define XMMWORD_MNEM_SUFFIX 'x' +/* Intel Syntax. Use a non-ascii letter since since it never appears + in instructions. */ +#define LONG_DOUBLE_MNEM_SUFFIX '\1' + +#define END_OF_INSN '\0' + +/* + 'templates' is for grouping together 'template' structures for opcodes + of the same name. This is only used for storing the insns in the grand + ole hash table of insns. + The templates themselves start at START and range up to (but not including) + END. + */ +typedef struct +{ + const template *start; + const template *end; +} +templates; + +/* 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 */ +} +modrm_byte; + +/* x86-64 extension prefix. */ +typedef int rex_byte; + +/* The SSE5 instructions have a two bit instruction modifier (OC) that + is stored in two separate bytes in the instruction. Pick apart OC + into the 2 separate bits for instruction. */ +#define DREX_OC0(x) (((x) & 1) != 0) +#define DREX_OC1(x) (((x) & 2) != 0) + +#define DREX_OC0_MASK (1 << 3) /* set OC0 in byte 4 */ +#define DREX_OC1_MASK (1 << 2) /* set OC1 in byte 3 */ + +/* OC mappings */ +#define DREX_XMEM_X1_X2_X2 0 /* 4 op insn, dest = src3, src1 = reg/mem */ +#define DREX_X1_XMEM_X2_X2 1 /* 4 op insn, dest = src3, src2 = reg/mem */ +#define DREX_X1_XMEM_X2_X1 2 /* 4 op insn, dest = src1, src2 = reg/mem */ +#define DREX_X1_X2_XMEM_X1 3 /* 4 op insn, dest = src1, src3 = reg/mem */ + +#define DREX_XMEM_X1_X2 0 /* 3 op insn, src1 = reg/mem */ +#define DREX_X1_XMEM_X2 1 /* 3 op insn, src1 = reg/mem */ + +/* Information needed to create the DREX byte in SSE5 instructions. */ +typedef struct +{ + unsigned int reg; /* register */ + unsigned int rex; /* REX flags */ + unsigned int modrm_reg; /* which arg goes in the modrm.reg field */ + unsigned int modrm_regmem; /* which arg goes in the modrm.regmem field */ +} drex_byte; + +/* 386 opcode byte to code indirect addressing. */ +typedef struct +{ + unsigned base; + unsigned index; + unsigned scale; +} +sib_byte; + +enum processor_type +{ + PROCESSOR_UNKNOWN, + PROCESSOR_I386, + PROCESSOR_I486, + PROCESSOR_PENTIUM, + PROCESSOR_PENTIUMPRO, + PROCESSOR_PENTIUM4, + PROCESSOR_NOCONA, + PROCESSOR_CORE, + PROCESSOR_CORE2, + PROCESSOR_K6, + PROCESSOR_ATHLON, + PROCESSOR_K8, + PROCESSOR_GENERIC32, + PROCESSOR_GENERIC64, + PROCESSOR_AMDFAM10 +}; + +/* x86 arch names, types and features */ +typedef struct +{ + const char *name; /* arch name */ + enum processor_type type; /* arch type */ + i386_cpu_flags flags; /* cpu feature flags */ +} +arch_entry; + static void set_code_flag (int); static void set_16bit_gcc_code_flag (int); static void set_intel_syntax (int); +static void set_intel_mnemonic (int); static void set_allow_index_reg (int); static void set_cpu_arch (int); #ifdef TE_PE @@ -65,7 +188,7 @@ static void pe_directive_secrel (int); #endif static void signed_cons (int); static char *output_invalid (int c); -static int i386_operand (char *); +static int i386_att_operand (char *); static int i386_intel_operand (char *, int); static const reg_entry *parse_register (char *, char **); static char *parse_insn (char *, char *); @@ -112,8 +235,8 @@ struct _i386_insn /* TM holds the template for the insn were currently assembling. */ template tm; - /* SUFFIX holds the instruction mnemonic suffix if given. - (e.g. 'l' for 'movl') */ + /* SUFFIX holds the instruction size suffix for byte, word, dword + or qword, if given. */ char suffix; /* OPERANDS gives the number of given operands. */ @@ -283,10 +406,20 @@ static const char *flag_code_names[] = 0 if att syntax. */ static int intel_syntax = 0; +/* 1 for intel mnemonic, + 0 if att mnemonic. */ +static int intel_mnemonic = !SYSV386_COMPAT; + +/* 1 if support old (<= 2.8.1) versions of gcc. */ +static int old_gcc = OLDGCC_COMPAT; + +/* 1 if pseudo registers are permitted. */ +static int allow_pseudo_reg = 0; + /* 1 if register prefix % not required. */ static int allow_naked_reg = 0; -/* 1 if fake index register, eiz/riz, is allowed . */ +/* 1 if pseudo index register, eiz/riz, is allowed . */ static int allow_index_reg = 0; /* Register prefix used for error message. */ @@ -305,14 +438,11 @@ static int quiet_warnings = 0; /* CPU name. */ static const char *cpu_arch_name = NULL; -static const char *cpu_sub_arch_name = NULL; +static char *cpu_sub_arch_name = NULL; /* CPU feature flags. */ static i386_cpu_flags cpu_arch_flags = CPU_UNKNOWN_FLAGS; -/* Bitwise NOT of cpu_arch_flags. */ -static i386_cpu_flags cpu_arch_flags_not; - /* If we have selected a cpu we are generating instructions for. */ static int cpu_arch_tune_set = 0; @@ -422,92 +552,98 @@ const relax_typeS md_relax_table[] = static const arch_entry cpu_arch[] = { - {"generic32", PROCESSOR_GENERIC32, - CPU_GENERIC32_FLAGS }, - {"generic64", PROCESSOR_GENERIC64, - CPU_GENERIC64_FLAGS }, - {"i8086", PROCESSOR_UNKNOWN, - CPU_NONE_FLAGS }, - {"i186", PROCESSOR_UNKNOWN, - CPU_I186_FLAGS }, - {"i286", PROCESSOR_UNKNOWN, - CPU_I286_FLAGS }, - {"i386", PROCESSOR_I386, - CPU_I386_FLAGS }, - {"i486", PROCESSOR_I486, - CPU_I486_FLAGS }, - {"i586", PROCESSOR_PENTIUM, - CPU_I586_FLAGS }, - {"i686", PROCESSOR_PENTIUMPRO, - CPU_I686_FLAGS }, - {"pentium", PROCESSOR_PENTIUM, - CPU_I586_FLAGS }, - {"pentiumpro",PROCESSOR_PENTIUMPRO, - CPU_I686_FLAGS }, - {"pentiumii", PROCESSOR_PENTIUMPRO, - CPU_P2_FLAGS }, - {"pentiumiii",PROCESSOR_PENTIUMPRO, - CPU_P3_FLAGS }, - {"pentium4", PROCESSOR_PENTIUM4, - CPU_P4_FLAGS }, - {"prescott", PROCESSOR_NOCONA, - CPU_CORE_FLAGS }, - {"nocona", PROCESSOR_NOCONA, - CPU_NOCONA_FLAGS }, - {"yonah", PROCESSOR_CORE, - CPU_CORE_FLAGS }, - {"core", PROCESSOR_CORE, - CPU_CORE_FLAGS }, - {"merom", PROCESSOR_CORE2, - CPU_CORE2_FLAGS }, - {"core2", PROCESSOR_CORE2, - CPU_CORE2_FLAGS }, - {"k6", PROCESSOR_K6, - CPU_K6_FLAGS }, - {"k6_2", PROCESSOR_K6, - CPU_K6_2_FLAGS }, - {"athlon", PROCESSOR_ATHLON, - CPU_ATHLON_FLAGS }, - {"sledgehammer", PROCESSOR_K8, - CPU_K8_FLAGS }, - {"opteron", PROCESSOR_K8, - CPU_K8_FLAGS }, - {"k8", PROCESSOR_K8, - CPU_K8_FLAGS }, - {"amdfam10", PROCESSOR_AMDFAM10, - CPU_AMDFAM10_FLAGS }, - {".mmx", PROCESSOR_UNKNOWN, - CPU_MMX_FLAGS }, - {".sse", PROCESSOR_UNKNOWN, - CPU_SSE_FLAGS }, - {".sse2", PROCESSOR_UNKNOWN, - CPU_SSE2_FLAGS }, - {".sse3", PROCESSOR_UNKNOWN, - CPU_SSE3_FLAGS }, - {".ssse3", PROCESSOR_UNKNOWN, - CPU_SSSE3_FLAGS }, - {".sse4.1", PROCESSOR_UNKNOWN, - CPU_SSE4_1_FLAGS }, - {".sse4.2", PROCESSOR_UNKNOWN, - CPU_SSE4_2_FLAGS }, - {".sse4", PROCESSOR_UNKNOWN, - CPU_SSE4_2_FLAGS }, - {".3dnow", PROCESSOR_UNKNOWN, - CPU_3DNOW_FLAGS }, - {".3dnowa", PROCESSOR_UNKNOWN, - CPU_3DNOWA_FLAGS }, - {".padlock", PROCESSOR_UNKNOWN, - CPU_PADLOCK_FLAGS }, - {".pacifica", PROCESSOR_UNKNOWN, - CPU_SVME_FLAGS }, - {".svme", PROCESSOR_UNKNOWN, - CPU_SVME_FLAGS }, - {".sse4a", PROCESSOR_UNKNOWN, - CPU_SSE4A_FLAGS }, - {".abm", PROCESSOR_UNKNOWN, - CPU_ABM_FLAGS }, - {".sse5", PROCESSOR_UNKNOWN, - CPU_SSE5_FLAGS }, + { "generic32", PROCESSOR_GENERIC32, + CPU_GENERIC32_FLAGS }, + { "generic64", PROCESSOR_GENERIC64, + CPU_GENERIC64_FLAGS }, + { "i8086", PROCESSOR_UNKNOWN, + CPU_NONE_FLAGS }, + { "i186", PROCESSOR_UNKNOWN, + CPU_I186_FLAGS }, + { "i286", PROCESSOR_UNKNOWN, + CPU_I286_FLAGS }, + { "i386", PROCESSOR_I386, + CPU_I386_FLAGS }, + { "i486", PROCESSOR_I486, + CPU_I486_FLAGS }, + { "i586", PROCESSOR_PENTIUM, + CPU_I586_FLAGS }, + { "i686", PROCESSOR_PENTIUMPRO, + CPU_I686_FLAGS }, + { "pentium", PROCESSOR_PENTIUM, + CPU_I586_FLAGS }, + { "pentiumpro", PROCESSOR_PENTIUMPRO, + CPU_I686_FLAGS }, + { "pentiumii", PROCESSOR_PENTIUMPRO, + CPU_P2_FLAGS }, + { "pentiumiii",PROCESSOR_PENTIUMPRO, + CPU_P3_FLAGS }, + { "pentium4", PROCESSOR_PENTIUM4, + CPU_P4_FLAGS }, + { "prescott", PROCESSOR_NOCONA, + CPU_CORE_FLAGS }, + { "nocona", PROCESSOR_NOCONA, + CPU_NOCONA_FLAGS }, + { "yonah", PROCESSOR_CORE, + CPU_CORE_FLAGS }, + { "core", PROCESSOR_CORE, + CPU_CORE_FLAGS }, + { "merom", PROCESSOR_CORE2, + CPU_CORE2_FLAGS }, + { "core2", PROCESSOR_CORE2, + CPU_CORE2_FLAGS }, + { "k6", PROCESSOR_K6, + CPU_K6_FLAGS }, + { "k6_2", PROCESSOR_K6, + CPU_K6_2_FLAGS }, + { "athlon", PROCESSOR_ATHLON, + CPU_ATHLON_FLAGS }, + { "sledgehammer", PROCESSOR_K8, + CPU_K8_FLAGS }, + { "opteron", PROCESSOR_K8, + CPU_K8_FLAGS }, + { "k8", PROCESSOR_K8, + CPU_K8_FLAGS }, + { "amdfam10", PROCESSOR_AMDFAM10, + CPU_AMDFAM10_FLAGS }, + { ".mmx", PROCESSOR_UNKNOWN, + CPU_MMX_FLAGS }, + { ".sse", PROCESSOR_UNKNOWN, + CPU_SSE_FLAGS }, + { ".sse2", PROCESSOR_UNKNOWN, + CPU_SSE2_FLAGS }, + { ".sse3", PROCESSOR_UNKNOWN, + CPU_SSE3_FLAGS }, + { ".ssse3", PROCESSOR_UNKNOWN, + CPU_SSSE3_FLAGS }, + { ".sse4.1", PROCESSOR_UNKNOWN, + CPU_SSE4_1_FLAGS }, + { ".sse4.2", PROCESSOR_UNKNOWN, + CPU_SSE4_2_FLAGS }, + { ".sse4", PROCESSOR_UNKNOWN, + CPU_SSE4_2_FLAGS }, + { ".vmx", PROCESSOR_UNKNOWN, + CPU_VMX_FLAGS }, + { ".smx", PROCESSOR_UNKNOWN, + CPU_SMX_FLAGS }, + { ".xsave", PROCESSOR_UNKNOWN, + CPU_XSAVE_FLAGS }, + { ".3dnow", PROCESSOR_UNKNOWN, + CPU_3DNOW_FLAGS }, + { ".3dnowa", PROCESSOR_UNKNOWN, + CPU_3DNOWA_FLAGS }, + { ".padlock", PROCESSOR_UNKNOWN, + CPU_PADLOCK_FLAGS }, + { ".pacifica", PROCESSOR_UNKNOWN, + CPU_SVME_FLAGS }, + { ".svme", PROCESSOR_UNKNOWN, + CPU_SVME_FLAGS }, + { ".sse4a", PROCESSOR_UNKNOWN, + CPU_SSE4A_FLAGS }, + { ".abm", PROCESSOR_UNKNOWN, + CPU_ABM_FLAGS }, + { ".sse5", PROCESSOR_UNKNOWN, + CPU_SSE5_FLAGS }, }; const pseudo_typeS md_pseudo_table[] = @@ -534,6 +670,8 @@ const pseudo_typeS md_pseudo_table[] = {"code64", set_code_flag, CODE_64BIT}, {"intel_syntax", set_intel_syntax, 1}, {"att_syntax", set_intel_syntax, 0}, + {"intel_mnemonic", set_intel_mnemonic, 1}, + {"att_mnemonic", set_intel_mnemonic, 0}, {"allow_index_reg", set_allow_index_reg, 1}, {"disallow_index_reg", set_allow_index_reg, 0}, #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) @@ -886,34 +1024,34 @@ i386_align_code (fragS *fragP, int count) } static INLINE int -uints_all_zero (const unsigned int *x, unsigned int size) +operand_type_all_zero (const union i386_operand_type *x) { - switch (size) + switch (ARRAY_SIZE(x->array)) { case 3: - if (x[2]) + if (x->array[2]) return 0; case 2: - if (x[1]) + if (x->array[1]) return 0; case 1: - return !x[0]; + return !x->array[0]; default: abort (); } } static INLINE void -uints_set (unsigned int *x, unsigned int v, unsigned int size) +operand_type_set (union i386_operand_type *x, unsigned int v) { - switch (size) + switch (ARRAY_SIZE(x->array)) { case 3: - x[2] = v; + x->array[2] = v; case 2: - x[1] = v; + x->array[1] = v; case 1: - x[0] = v; + x->array[0] = v; break; default: abort (); @@ -921,62 +1059,85 @@ uints_set (unsigned int *x, unsigned int v, unsigned int size) } static INLINE int -uints_equal (const unsigned int *x, const unsigned int *y, - unsigned int size) +operand_type_equal (const union i386_operand_type *x, + const union i386_operand_type *y) { - switch (size) + switch (ARRAY_SIZE(x->array)) { case 3: - if (x[2] != y [2]) + if (x->array[2] != y->array[2]) return 0; case 2: - if (x[1] != y [1]) + if (x->array[1] != y->array[1]) return 0; case 1: - return x[0] == y [0]; + return x->array[0] == y->array[0]; break; default: abort (); } } -#define UINTS_ALL_ZERO(x) \ - uints_all_zero ((x).array, ARRAY_SIZE ((x).array)) -#define UINTS_SET(x, v) \ - uints_set ((x).array, v, ARRAY_SIZE ((x).array)) -#define UINTS_CLEAR(x) \ - uints_set ((x).array, 0, ARRAY_SIZE ((x).array)) -#define UINTS_EQUAL(x, y) \ - uints_equal ((x).array, (y).array, ARRAY_SIZE ((x).array)) - static INLINE int -cpu_flags_check_cpu64 (i386_cpu_flags f) +cpu_flags_all_zero (const union i386_cpu_flags *x) { - return !((flag_code == CODE_64BIT && f.bitfield.cpuno64) - || (flag_code != CODE_64BIT && f.bitfield.cpu64)); + switch (ARRAY_SIZE(x->array)) + { + case 3: + if (x->array[2]) + return 0; + case 2: + if (x->array[1]) + return 0; + case 1: + return !x->array[0]; + default: + abort (); + } } -static INLINE i386_cpu_flags -cpu_flags_not (i386_cpu_flags x) +static INLINE void +cpu_flags_set (union i386_cpu_flags *x, unsigned int v) { - switch (ARRAY_SIZE (x.array)) + switch (ARRAY_SIZE(x->array)) { case 3: - x.array [2] = ~x.array [2]; + x->array[2] = v; case 2: - x.array [1] = ~x.array [1]; + x->array[1] = v; case 1: - x.array [0] = ~x.array [0]; + x->array[0] = v; break; default: abort (); } +} -#ifdef CpuUnused - x.bitfield.unused = 0; -#endif +static INLINE int +cpu_flags_equal (const union i386_cpu_flags *x, + const union i386_cpu_flags *y) +{ + switch (ARRAY_SIZE(x->array)) + { + case 3: + if (x->array[2] != y->array[2]) + return 0; + case 2: + if (x->array[1] != y->array[1]) + return 0; + case 1: + return x->array[0] == y->array[0]; + break; + default: + abort (); + } +} - return x; +static INLINE int +cpu_flags_check_cpu64 (i386_cpu_flags f) +{ + return !((flag_code == CODE_64BIT && f.bitfield.cpuno64) + || (flag_code != CODE_64BIT && f.bitfield.cpu64)); } static INLINE i386_cpu_flags @@ -1015,19 +1176,29 @@ cpu_flags_or (i386_cpu_flags x, i386_cpu_flags y) return x; } +/* Return 3 if there is a perfect match, 2 if compatible with 64bit, + 1 if compatible with arch, 0 if there is no match. */ + static int cpu_flags_match (i386_cpu_flags x) { - i386_cpu_flags not = cpu_arch_flags_not; - - not.bitfield.cpu64 = 1; - not.bitfield.cpuno64 = 1; + int overlap = cpu_flags_check_cpu64 (x) ? 2 : 0; x.bitfield.cpu64 = 0; x.bitfield.cpuno64 = 0; - not = cpu_flags_and (x, not); - return UINTS_ALL_ZERO (not); + if (cpu_flags_all_zero (&x)) + overlap |= 1; + else + { + i386_cpu_flags cpu = cpu_arch_flags; + + cpu.bitfield.cpu64 = 0; + cpu.bitfield.cpuno64 = 0; + cpu = cpu_flags_and (x, cpu); + overlap |= cpu_flags_all_zero (&cpu) ? 0 : 1; + } + return overlap; } static INLINE i386_operand_type @@ -1087,6 +1258,8 @@ operand_type_xor (i386_operand_type x, i386_operand_type y) static const i386_operand_type acc32 = OPERAND_TYPE_ACC32; static const i386_operand_type acc64 = OPERAND_TYPE_ACC64; static const i386_operand_type control = OPERAND_TYPE_CONTROL; +static const i386_operand_type inoutportreg + = OPERAND_TYPE_INOUTPORTREG; static const i386_operand_type reg16_inoutportreg = OPERAND_TYPE_REG16_INOUTPORTREG; static const i386_operand_type disp16 = OPERAND_TYPE_DISP16; @@ -1153,6 +1326,102 @@ operand_type_check (i386_operand_type t, enum operand_type c) } } +/* Return 1 if there is no conflict in 8bit/16bit/32bit/64bit on + operand J for instruction template T. */ + +static INLINE int +match_reg_size (const template *t, unsigned int j) +{ + return !((i.types[j].bitfield.byte + && !t->operand_types[j].bitfield.byte) + || (i.types[j].bitfield.word + && !t->operand_types[j].bitfield.word) + || (i.types[j].bitfield.dword + && !t->operand_types[j].bitfield.dword) + || (i.types[j].bitfield.qword + && !t->operand_types[j].bitfield.qword)); +} + +/* Return 1 if there is no conflict in any size on operand J for + instruction template T. */ + +static INLINE int +match_mem_size (const template *t, unsigned int j) +{ + return (match_reg_size (t, j) + && !((i.types[j].bitfield.unspecified + && !t->operand_types[j].bitfield.unspecified) + || (i.types[j].bitfield.fword + && !t->operand_types[j].bitfield.fword) + || (i.types[j].bitfield.tbyte + && !t->operand_types[j].bitfield.tbyte) + || (i.types[j].bitfield.xmmword + && !t->operand_types[j].bitfield.xmmword))); +} + +/* Return 1 if there is no size conflict on any operands for + instruction template T. */ + +static INLINE int +operand_size_match (const template *t) +{ + unsigned int j; + int match = 1; + + /* Don't check jump instructions. */ + if (t->opcode_modifier.jump + || t->opcode_modifier.jumpbyte + || t->opcode_modifier.jumpdword + || t->opcode_modifier.jumpintersegment) + return match; + + /* Check memory and accumulator operand size. */ + for (j = 0; j < i.operands; j++) + { + if (t->operand_types[j].bitfield.anysize) + continue; + + if (t->operand_types[j].bitfield.acc && !match_reg_size (t, j)) + { + match = 0; + break; + } + + if (i.types[j].bitfield.mem && !match_mem_size (t, j)) + { + match = 0; + break; + } + } + + if (match + || (!t->opcode_modifier.d && !t->opcode_modifier.floatd)) + return match; + + /* Check reverse. */ + assert (i.operands == 2); + + match = 1; + for (j = 0; j < 2; j++) + { + if (t->operand_types[j].bitfield.acc + && !match_reg_size (t, j ? 0 : 1)) + { + match = 0; + break; + } + + if (i.types[j].bitfield.mem + && !match_mem_size (t, j ? 0 : 1)) + { + match = 0; + break; + } + } + + return match; +} + static INLINE int operand_type_match (i386_operand_type overlap, i386_operand_type given) @@ -1160,14 +1429,22 @@ operand_type_match (i386_operand_type overlap, i386_operand_type temp = overlap; temp.bitfield.jumpabsolute = 0; - if (UINTS_ALL_ZERO (temp)) + temp.bitfield.unspecified = 0; + temp.bitfield.byte = 0; + temp.bitfield.word = 0; + temp.bitfield.dword = 0; + temp.bitfield.fword = 0; + temp.bitfield.qword = 0; + temp.bitfield.tbyte = 0; + temp.bitfield.xmmword = 0; + if (operand_type_all_zero (&temp)) return 0; return (given.bitfield.baseindex == overlap.bitfield.baseindex && given.bitfield.jumpabsolute == overlap.bitfield.jumpabsolute); } -/* If given types r0 and r1 are registers they must be of the same type +/* If given types g0 and g1 are registers they must be of the same type unless the expected operand type register overlap is null. Note that Acc in a template matches every size of reg. */ @@ -1276,7 +1553,7 @@ smallest_imm_type (offsetT num) { i386_operand_type t; - UINTS_CLEAR (t); + operand_type_set (&t, 0); t.bitfield.imm64 = 1; if (cpu_arch_tune != PROCESSOR_I486 && num == 1) @@ -1435,15 +1712,11 @@ set_code_flag (int value) { cpu_arch_flags.bitfield.cpu64 = 1; cpu_arch_flags.bitfield.cpuno64 = 0; - cpu_arch_flags_not.bitfield.cpu64 = 0; - cpu_arch_flags_not.bitfield.cpuno64 = 1; } else { cpu_arch_flags.bitfield.cpu64 = 0; cpu_arch_flags.bitfield.cpuno64 = 1; - cpu_arch_flags_not.bitfield.cpu64 = 1; - cpu_arch_flags_not.bitfield.cpuno64 = 0; } if (value == CODE_64BIT && !cpu_arch_flags.bitfield.cpulm ) { @@ -1464,8 +1737,6 @@ set_16bit_gcc_code_flag (int new_code_flag) abort (); cpu_arch_flags.bitfield.cpu64 = 0; cpu_arch_flags.bitfield.cpuno64 = 1; - cpu_arch_flags_not.bitfield.cpu64 = 1; - cpu_arch_flags_not.bitfield.cpuno64 = 0; stackop_size = LONG_MNEM_SUFFIX; } @@ -1505,6 +1776,12 @@ set_intel_syntax (int syntax_flag) } static void +set_intel_mnemonic (int mnemonic_flag) +{ + intel_mnemonic = mnemonic_flag; +} + +static void set_allow_index_reg (int flag) { allow_index_reg = flag; @@ -1541,7 +1818,6 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED) cpu_arch_flags.bitfield.cpu64 = 0; cpu_arch_flags.bitfield.cpuno64 = 1; } - cpu_arch_flags_not = cpu_flags_not (cpu_arch_flags); cpu_arch_isa = cpu_arch[i].type; cpu_arch_isa_flags = cpu_arch[i].flags; if (!cpu_arch_tune_set) @@ -1554,11 +1830,19 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED) flags = cpu_flags_or (cpu_arch_flags, cpu_arch[i].flags); - if (!UINTS_EQUAL (flags, cpu_arch_flags)) + if (!cpu_flags_equal (&flags, &cpu_arch_flags)) { - cpu_sub_arch_name = cpu_arch[i].name; + if (cpu_sub_arch_name) + { + char *name = cpu_sub_arch_name; + cpu_sub_arch_name = concat (name, + cpu_arch[i].name, + (const char *) NULL); + free (name); + } + else + cpu_sub_arch_name = xstrdup (cpu_arch[i].name); cpu_arch_flags = flags; - cpu_arch_flags_not = cpu_flags_not (cpu_arch_flags); } *input_line_pointer = e; demand_empty_rest_of_line (); @@ -1609,8 +1893,6 @@ md_begin () { const char *hash_err; - cpu_arch_flags_not = cpu_flags_not (cpu_arch_flags); - /* Initialize op_hash hash table. */ op_hash = hash_new (); @@ -2113,13 +2395,56 @@ intel_float_operand (const char *mnemonic) return 1; } +static void +process_immext (void) +{ + expressionS *exp; + + if (i.tm.cpu_flags.bitfield.cpusse3 && i.operands > 0) + { + /* SSE3 Instructions have the fixed operands with an opcode + suffix which is coded in the same place as an 8-bit immediate + field would be. Here we check those operands and remove them + afterwards. */ + unsigned int x; + + for (x = 0; x < i.operands; x++) + if (i.op[x].regs->reg_num != x) + as_bad (_("can't use register '%s%s' as operand %d in '%s'."), + register_prefix, i.op[x].regs->reg_name, x + 1, + i.tm.name); + + i.operands = 0; + } + + /* These AMD 3DNow! and SSE2 Instructions have an opcode suffix + which is coded in the same place as an 8-bit immediate field + would be. Here we fake an 8-bit immediate operand from the + opcode suffix stored in tm.extension_opcode. + + SSE5 also uses this encoding, for some of its 3 argument + instructions. */ + + assert (i.imm_operands == 0 + && (i.operands <= 2 + || (i.tm.cpu_flags.bitfield.cpusse5 + && i.operands <= 3))); + + exp = &im_expressions[i.imm_operands++]; + i.op[i.operands].imms = exp; + i.types[i.operands] = imm8; + i.operands++; + exp->X_op = O_constant; + exp->X_add_number = i.tm.extension_opcode; + i.tm.extension_opcode = None; +} + /* This is the guts of the machine-dependent assembler. LINE points to a machine dependent instruction. This function is supposed to emit the frags/bytes it assembles to. */ void -md_assemble (line) - char *line; +md_assemble (char *line) { unsigned int j; char mnemonic[MAX_MNEM_SIZE]; @@ -2183,30 +2508,20 @@ md_assemble (line) if (!match_template ()) return; - if (intel_syntax) + /* Zap movzx and movsx suffix. The suffix has been set from + "word ptr" or "byte ptr" on the source operand in Intel syntax + or extracted from mnemonic in AT&T syntax. But we'll use + the destination register to choose the suffix for encoding. */ + if ((i.tm.base_opcode & ~9) == 0x0fb6) { - /* Undo SYSV386_COMPAT brokenness when in Intel mode. See i386.h */ - if (SYSV386_COMPAT - && (i.tm.base_opcode & 0xfffffde0) == 0xdce0) - i.tm.base_opcode ^= Opcode_FloatR; - - /* Zap movzx and movsx suffix. The suffix may have been set from - "word ptr" or "byte ptr" on the source operand, but we'll use - the suffix later to choose the destination register. */ - if ((i.tm.base_opcode & ~9) == 0x0fb6) - { - if (i.reg_operands < 2 - && !i.suffix - && (!i.tm.opcode_modifier.no_bsuf - || !i.tm.opcode_modifier.no_wsuf - || !i.tm.opcode_modifier.no_lsuf - || !i.tm.opcode_modifier.no_ssuf - || !i.tm.opcode_modifier.no_xsuf - || !i.tm.opcode_modifier.no_qsuf)) - as_bad (_("ambiguous operand size for `%s'"), i.tm.name); + /* In Intel syntax, there must be a suffix. In AT&T syntax, if + there is no suffix, the default will be byte extension. */ + if (i.reg_operands != 2 + && !i.suffix + && intel_syntax) + as_bad (_("ambiguous operand size for `%s'"), i.tm.name); - i.suffix = 0; - } + i.suffix = 0; } if (i.tm.opcode_modifier.fwait) @@ -2239,48 +2554,7 @@ md_assemble (line) i.reg_operands--; if (i.tm.opcode_modifier.immext) - { - expressionS *exp; - - if (i.tm.cpu_flags.bitfield.cpusse3 && i.operands > 0) - { - /* Streaming SIMD extensions 3 Instructions have the fixed - operands with an opcode suffix which is coded in the same - place as an 8-bit immediate field would be. Here we check - those operands and remove them afterwards. */ - unsigned int x; - - for (x = 0; x < i.operands; x++) - if (i.op[x].regs->reg_num != x) - as_bad (_("can't use register '%s%s' as operand %d in '%s'."), - register_prefix, - i.op[x].regs->reg_name, - x + 1, - i.tm.name); - i.operands = 0; - } - - /* These AMD 3DNow! and Intel Katmai New Instructions have an - opcode suffix which is coded in the same place as an 8-bit - immediate field would be. Here we fake an 8-bit immediate - operand from the opcode suffix stored in tm.extension_opcode. - SSE5 also uses this encoding, for some of its 3 argument - instructions. */ - - assert (i.imm_operands == 0 - && (i.operands <= 2 - || (i.tm.cpu_flags.bitfield.cpusse5 - && i.operands <= 3))); - - exp = &im_expressions[i.imm_operands++]; - i.op[i.operands].imms = exp; - UINTS_CLEAR (i.types[i.operands]); - i.types[i.operands].bitfield.imm8 = 1; - i.operands++; - exp->X_op = O_constant; - exp->X_add_number = i.tm.extension_opcode; - i.tm.extension_opcode = None; - } + process_immext (); /* For insns with operands there are more diddles to do to the opcode. */ if (i.operands) @@ -2536,11 +2810,11 @@ parse_insn (char *line, char *mnemonic) supported = 0; for (t = current_templates->start; t < current_templates->end; ++t) { - if (cpu_flags_match (t->cpu_flags)) - supported |= 1; - if (cpu_flags_check_cpu64 (t->cpu_flags)) - supported |= 2; + supported |= cpu_flags_match (t->cpu_flags); + if (supported == 3) + goto skip; } + if (!(supported & 2)) { as_bad (flag_code == CODE_64BIT @@ -2551,12 +2825,14 @@ parse_insn (char *line, char *mnemonic) } if (!(supported & 1)) { - as_warn (_("`%s' is not supported on `%s%s'"), - current_templates->start->name, - cpu_arch_name, - cpu_sub_arch_name ? cpu_sub_arch_name : ""); + as_bad (_("`%s' is not supported on `%s%s'"), + current_templates->start->name, cpu_arch_name, + cpu_sub_arch_name ? cpu_sub_arch_name : ""); + return NULL; } - else if (!cpu_arch_flags.bitfield.cpui386 + +skip: + if (!cpu_arch_flags.bitfield.cpui386 && (flag_code != CODE_16BIT)) { as_warn (_("use .code16 to ensure correct addressing mode")); @@ -2655,6 +2931,7 @@ parse_operands (char *l, const char *mnemonic) { /* Yes, we've read in another operand. */ unsigned int operand_ok; this_operand = i.operands++; + i.types[this_operand].bitfield.unspecified = 1; if (i.operands > MAX_OPERANDS) { as_bad (_("spurious operands; (%d operands/instruction max)"), @@ -2669,7 +2946,7 @@ parse_operands (char *l, const char *mnemonic) i386_intel_operand (token_start, intel_float_operand (mnemonic)); else - operand_ok = i386_operand (token_start); + operand_ok = i386_att_operand (token_start); RESTORE_END_STRING (l); if (!operand_ok) @@ -2858,8 +3135,8 @@ optimize_imm (void) i386_operand_type mask, allowed; const template *t; - UINTS_CLEAR (mask); - UINTS_CLEAR (allowed); + operand_type_set (&mask, 0); + operand_type_set (&allowed, 0); for (t = current_templates->start; t < current_templates->end; @@ -2885,7 +3162,7 @@ optimize_imm (void) break; } allowed = operand_type_and (mask, allowed); - if (!UINTS_ALL_ZERO (allowed)) + if (!operand_type_all_zero (&allowed)) i.types[op] = operand_type_and (i.types[op], mask); } break; @@ -2979,7 +3256,8 @@ match_template (void) i386_operand_type operand_types [MAX_OPERANDS]; int addr_prefix_disp; unsigned int j; - i386_cpu_flags overlap; + unsigned int found_cpu_match; + unsigned int check_register; #if MAX_OPERANDS != 4 # error "MAX_OPERANDS must be 4." @@ -3000,7 +3278,7 @@ match_template (void) else if (i.suffix == QWORD_MNEM_SUFFIX) suffix_check.no_qsuf = 1; else if (i.suffix == LONG_DOUBLE_MNEM_SUFFIX) - suffix_check.no_xsuf = 1; + suffix_check.no_ldsuf = 1; for (t = current_templates->start; t < current_templates->end; t++) { @@ -3010,18 +3288,39 @@ match_template (void) if (i.operands != t->operands) continue; + /* Check processor support. */ + found_cpu_match = cpu_flags_match (t->cpu_flags) == 3; + if (!found_cpu_match) + continue; + + /* Check old gcc support. */ + if (!old_gcc && t->opcode_modifier.oldgcc) + continue; + + /* Check AT&T mnemonic. */ + if (intel_mnemonic && t->opcode_modifier.attmnemonic) + continue; + + /* Check AT&T syntax Intel syntax. */ + if ((intel_syntax && t->opcode_modifier.attsyntax) + || (!intel_syntax && t->opcode_modifier.intelsyntax)) + continue; + /* Check the suffix, except for some instructions in intel mode. */ - if (((t->opcode_modifier.no_bsuf & suffix_check.no_bsuf) - || (t->opcode_modifier.no_wsuf & suffix_check.no_wsuf) - || (t->opcode_modifier.no_lsuf & suffix_check.no_lsuf) - || (t->opcode_modifier.no_ssuf & suffix_check.no_ssuf) - || (t->opcode_modifier.no_qsuf & suffix_check.no_qsuf) - || (t->opcode_modifier.no_xsuf & suffix_check.no_xsuf)) - && !(intel_syntax && t->opcode_modifier.ignoresize)) + if ((!intel_syntax || !t->opcode_modifier.ignoresize) + && ((t->opcode_modifier.no_bsuf && suffix_check.no_bsuf) + || (t->opcode_modifier.no_wsuf && suffix_check.no_wsuf) + || (t->opcode_modifier.no_lsuf && suffix_check.no_lsuf) + || (t->opcode_modifier.no_ssuf && suffix_check.no_ssuf) + || (t->opcode_modifier.no_qsuf && suffix_check.no_qsuf) + || (t->opcode_modifier.no_ldsuf && suffix_check.no_ldsuf))) + continue; + + if (!operand_size_match (t)) continue; for (j = 0; j < MAX_OPERANDS; j++) - operand_types [j] = t->operand_types [j]; + operand_types[j] = t->operand_types[j]; /* In general, don't allow 64-bit operands in 32-bit mode. */ if (i.suffix == QWORD_MNEM_SUFFIX @@ -3038,17 +3337,25 @@ match_template (void) || t->extension_opcode != 1 /* cmpxchg8b */)) continue; + /* In general, don't allow 32-bit operands on pre-386. */ + else if (i.suffix == LONG_MNEM_SUFFIX + && !cpu_arch_flags.bitfield.cpui386 + && (intel_syntax + ? (!t->opcode_modifier.ignoresize + && !intel_float_operand (t->name)) + : intel_float_operand (t->name) != 2) + && ((!operand_types[0].bitfield.regmmx + && !operand_types[0].bitfield.regxmm) + || (!operand_types[t->operands > 1].bitfield.regmmx + && !!operand_types[t->operands > 1].bitfield.regxmm))) + continue; + /* Do not verify operands when there are none. */ - else + else { - overlap = cpu_flags_and (t->cpu_flags, cpu_arch_flags_not); if (!t->operands) - { - if (!UINTS_ALL_ZERO (overlap)) - continue; - /* We've found a match; break out of loop. */ - break; - } + /* We've found a match; break out of loop. */ + break; } /* Address size prefix will turn Disp64/Disp32/Disp16 operand @@ -3097,6 +3404,9 @@ match_template (void) } } + /* We check register size only if size of operands can be + encoded the canonical way. */ + check_register = t->opcode_modifier.w; overlap0 = operand_type_and (i.types[0], operand_types[0]); switch (t->operands) { @@ -3111,27 +3421,16 @@ match_template (void) zero-extend %eax to %rax. */ if (flag_code == CODE_64BIT && t->base_opcode == 0x90 - && UINTS_EQUAL (i.types [0], acc32) - && UINTS_EQUAL (i.types [1], acc32)) + && operand_type_equal (&i.types [0], &acc32) + && operand_type_equal (&i.types [1], &acc32)) continue; case 3: case 4: overlap1 = operand_type_and (i.types[1], operand_types[1]); if (!operand_type_match (overlap0, i.types[0]) || !operand_type_match (overlap1, i.types[1]) - /* monitor in SSE3 is a very special case. The first - register and the second register may have different - sizes. The same applies to crc32 in SSE4.2. It is - also true for invlpga, vmload, vmrun and vmsave in - SVME. */ - || !((t->base_opcode == 0x0f01 - && (t->extension_opcode == 0xc8 - || t->extension_opcode == 0xd8 - || t->extension_opcode == 0xda - || t->extension_opcode == 0xdb - || t->extension_opcode == 0xdf)) - || t->base_opcode == 0xf20f38f1 - || operand_type_register_match (overlap0, i.types[0], + || (check_register + && !operand_type_register_match (overlap0, i.types[0], operand_types[0], overlap1, i.types[1], operand_types[1]))) @@ -3145,10 +3444,13 @@ match_template (void) overlap1 = operand_type_and (i.types[1], operand_types[0]); if (!operand_type_match (overlap0, i.types[0]) || !operand_type_match (overlap1, i.types[1]) - || !operand_type_register_match (overlap0, i.types[0], - operand_types[1], - overlap1, i.types[1], - operand_types[0])) + || (check_register + && !operand_type_register_match (overlap0, + i.types[0], + operand_types[1], + overlap1, + i.types[1], + operand_types[0]))) { /* Does not match either direction. */ continue; @@ -3182,12 +3484,13 @@ match_template (void) { case 4: if (!operand_type_match (overlap3, i.types[3]) - || !operand_type_register_match (overlap2, - i.types[2], - operand_types[2], - overlap3, - i.types[3], - operand_types[3])) + || (check_register + && !operand_type_register_match (overlap2, + i.types[2], + operand_types[2], + overlap3, + i.types[3], + operand_types[3]))) continue; case 3: /* Here we make use of the fact that there are no @@ -3195,12 +3498,13 @@ match_template (void) operand instructions only need to be checked for register consistency between operands 2 and 3. */ if (!operand_type_match (overlap2, i.types[2]) - || !operand_type_register_match (overlap1, - i.types[1], - operand_types[1], - overlap2, - i.types[2], - operand_types[2])) + || (check_register + && !operand_type_register_match (overlap1, + i.types[1], + operand_types[1], + overlap2, + i.types[2], + operand_types[2]))) continue; break; } @@ -3208,7 +3512,7 @@ match_template (void) /* Found either forward/reverse 2, 3 or 4 operand match here: slip through to break. */ } - if (!UINTS_ALL_ZERO (overlap)) + if (!found_cpu_match) { found_reverse_match = 0; continue; @@ -3384,7 +3688,11 @@ process_suffix (void) } else if (i.suffix == QWORD_MNEM_SUFFIX) { - if (!check_qword_reg ()) + if (intel_syntax + && i.tm.opcode_modifier.ignoresize + && i.tm.opcode_modifier.no_qsuf) + i.suffix = 0; + else if (!check_qword_reg ()) return 0; } else if (i.suffix == WORD_MNEM_SUFFIX) @@ -3392,6 +3700,11 @@ process_suffix (void) if (!check_word_reg ()) return 0; } + else if (i.suffix == XMMWORD_MNEM_SUFFIX) + { + /* Skip if the instruction has x suffix. match_template + should check if it is a valid suffix. */ + } else if (intel_syntax && i.tm.opcode_modifier.ignoresize) /* Do nothing if the instruction is going to ignore the prefix. */ ; @@ -3452,7 +3765,7 @@ process_suffix (void) suffixes |= 1 << 1; if (!i.tm.opcode_modifier.no_lsuf) suffixes |= 1 << 2; - if (!i.tm.opcode_modifier.no_lsuf) + if (!i.tm.opcode_modifier.no_ldsuf) suffixes |= 1 << 3; if (!i.tm.opcode_modifier.no_ssuf) suffixes |= 1 << 4; @@ -3474,7 +3787,9 @@ process_suffix (void) /* Change the opcode based on the operand size given by i.suffix; We don't need to change things for byte insns. */ - if (i.suffix && i.suffix != BYTE_MNEM_SUFFIX) + if (i.suffix + && i.suffix != BYTE_MNEM_SUFFIX + && i.suffix != XMMWORD_MNEM_SUFFIX) { /* It's not a byte, select word/dword operation. */ if (i.tm.opcode_modifier.w) @@ -3488,17 +3803,10 @@ process_suffix (void) /* Now select between word & dword operations via the operand size prefix, except for instructions that will ignore this prefix anyway. */ - if (i.tm.base_opcode == 0x0f01 - && (i.tm.extension_opcode == 0xc8 - || i.tm.extension_opcode == 0xd8 - || i.tm.extension_opcode == 0xda - || i.tm.extension_opcode == 0xdb - || i.tm.extension_opcode == 0xdf)) - { - /* monitor in SSE3 is a very special case. The default size - of AX is the size of mode. The address size override - prefix will change the size of AX. It is also true for - invlpga, vmload, vmrun and vmsave in SVME. */ + if (i.tm.opcode_modifier.addrprefixop0) + { + /* The address size override prefix changes the size of the + first operand. */ if ((flag_code == CODE_32BIT && i.op->regs[0].reg_type.bitfield.reg16) || (flag_code != CODE_32BIT @@ -3533,8 +3841,8 @@ process_suffix (void) if (! (i.operands == 2 && i.tm.base_opcode == 0x90 && i.tm.extension_opcode == None - && UINTS_EQUAL (i.types [0], acc64) - && UINTS_EQUAL (i.types [1], acc64)) + && operand_type_equal (&i.types [0], &acc64) + && operand_type_equal (&i.types [1], &acc64)) && ! (i.operands == 1 && i.tm.base_opcode == 0xfc7 && i.tm.extension_opcode == 1 @@ -3565,16 +3873,8 @@ check_byte_reg (void) if (i.types[op].bitfield.reg8) continue; - /* movzx, movsx, pextrb and pinsrb should not generate this - warning. */ - if (intel_syntax - && (i.tm.base_opcode == 0xfb7 - || i.tm.base_opcode == 0xfb6 - || i.tm.base_opcode == 0x63 - || i.tm.base_opcode == 0xfbe - || i.tm.base_opcode == 0xfbf - || i.tm.base_opcode == 0x660f3a14 - || i.tm.base_opcode == 0x660f3a20)) + /* Don't generate this warning if not needed. */ + if (intel_syntax && i.tm.opcode_modifier.byteokintel) continue; /* crc32 doesn't generate this warning. */ @@ -3686,11 +3986,10 @@ check_long_reg (void) || i.tm.operand_types[op].bitfield.acc)) { if (intel_syntax - && i.tm.base_opcode == 0xf30f2d + && i.tm.opcode_modifier.toqword && !i.types[0].bitfield.regxmm) { - /* cvtss2si converts DWORD memory to Reg64. We want - REX byte. */ + /* Convert to QWORD. We want REX byte. */ i.suffix = QWORD_MNEM_SUFFIX; } else @@ -3733,11 +4032,10 @@ check_qword_reg (void) /* Prohibit these changes in the 64bit mode, since the lowering is more complicated. */ if (intel_syntax - && i.tm.base_opcode == 0xf20f2d + && i.tm.opcode_modifier.todword && !i.types[0].bitfield.regxmm) { - /* cvtsd2si converts QWORD memory to Reg32. We don't want - REX byte. */ + /* Convert to DWORD. We don't want REX byte. */ i.suffix = LONG_MNEM_SUFFIX; } else @@ -3810,18 +4108,18 @@ update_imm (unsigned int j) || overlap.bitfield.imm32 || overlap.bitfield.imm32s || overlap.bitfield.imm64) - && !UINTS_EQUAL (overlap, imm8) - && !UINTS_EQUAL (overlap, imm8s) - && !UINTS_EQUAL (overlap, imm16) - && !UINTS_EQUAL (overlap, imm32) - && !UINTS_EQUAL (overlap, imm32s) - && !UINTS_EQUAL (overlap, imm64)) + && !operand_type_equal (&overlap, &imm8) + && !operand_type_equal (&overlap, &imm8s) + && !operand_type_equal (&overlap, &imm16) + && !operand_type_equal (&overlap, &imm32) + && !operand_type_equal (&overlap, &imm32s) + && !operand_type_equal (&overlap, &imm64)) { if (i.suffix) { i386_operand_type temp; - UINTS_CLEAR (temp); + operand_type_set (&temp, 0); if (i.suffix == BYTE_MNEM_SUFFIX) { temp.bitfield.imm8 = overlap.bitfield.imm8; @@ -3838,22 +4136,21 @@ update_imm (unsigned int j) temp.bitfield.imm32 = overlap.bitfield.imm32; overlap = temp; } - else if (UINTS_EQUAL (overlap, imm16_32_32s) - || UINTS_EQUAL (overlap, imm16_32) - || UINTS_EQUAL (overlap, imm16_32s)) + else if (operand_type_equal (&overlap, &imm16_32_32s) + || operand_type_equal (&overlap, &imm16_32) + || operand_type_equal (&overlap, &imm16_32s)) { - UINTS_CLEAR (overlap); if ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0)) - overlap.bitfield.imm16 = 1; + overlap = imm16; else - overlap.bitfield.imm32s = 1; + overlap = imm32s; } - if (!UINTS_EQUAL (overlap, imm8) - && !UINTS_EQUAL (overlap, imm8s) - && !UINTS_EQUAL (overlap, imm16) - && !UINTS_EQUAL (overlap, imm32) - && !UINTS_EQUAL (overlap, imm32s) - && !UINTS_EQUAL (overlap, imm64)) + if (!operand_type_equal (&overlap, &imm8) + && !operand_type_equal (&overlap, &imm8s) + && !operand_type_equal (&overlap, &imm16) + && !operand_type_equal (&overlap, &imm32) + && !operand_type_equal (&overlap, &imm32s) + && !operand_type_equal (&overlap, &imm64)) { as_bad (_("no instruction mnemonic suffix given; " "can't determine immediate size")); @@ -3883,8 +4180,8 @@ finalize_imm (void) static void process_drex (void) { - i.drex.modrm_reg = None; - i.drex.modrm_regmem = None; + i.drex.modrm_reg = 0; + i.drex.modrm_regmem = 0; /* SSE5 4 operand instructions must have the destination the same as one of the inputs. Figure out the destination register and cache @@ -3905,8 +4202,8 @@ process_drex (void) && i.op[0].regs->reg_flags == i.op[3].regs->reg_flags) { /* Clear the arguments that are stored in drex. */ - UINTS_CLEAR (i.types[0]); - UINTS_CLEAR (i.types[3]); + operand_type_set (&i.types[0], 0); + operand_type_set (&i.types[3], 0); i.reg_operands -= 2; /* There are two different ways to encode a 4 operand @@ -3933,8 +4230,8 @@ process_drex (void) && i.op[0].regs->reg_flags == i.op[3].regs->reg_flags) { /* clear the arguments that are stored in drex */ - UINTS_CLEAR (i.types[0]); - UINTS_CLEAR (i.types[3]); + operand_type_set (&i.types[0], 0); + operand_type_set (&i.types[3], 0); i.reg_operands -= 2; /* Specify the modrm encoding for memory addressing. Include @@ -3956,8 +4253,8 @@ process_drex (void) && i.op[0].regs->reg_flags == i.op[3].regs->reg_flags) { /* Clear the arguments that are stored in drex. */ - UINTS_CLEAR (i.types[0]); - UINTS_CLEAR (i.types[3]); + operand_type_set (&i.types[0], 0); + operand_type_set (&i.types[3], 0); i.reg_operands -= 2; /* Specify the modrm encoding for memory addressing. Include @@ -3979,8 +4276,8 @@ process_drex (void) && i.op[2].regs->reg_flags == i.op[3].regs->reg_flags) { /* clear the arguments that are stored in drex */ - UINTS_CLEAR (i.types[2]); - UINTS_CLEAR (i.types[3]); + operand_type_set (&i.types[2], 0); + operand_type_set (&i.types[3], 0); i.reg_operands -= 2; /* There are two different ways to encode a 4 operand @@ -4009,8 +4306,8 @@ process_drex (void) && i.op[2].regs->reg_flags == i.op[3].regs->reg_flags) { /* Clear the arguments that are stored in drex. */ - UINTS_CLEAR (i.types[2]); - UINTS_CLEAR (i.types[3]); + operand_type_set (&i.types[2], 0); + operand_type_set (&i.types[3], 0); i.reg_operands -= 2; /* Specify the modrm encoding and remember the register @@ -4031,8 +4328,8 @@ process_drex (void) && i.op[2].regs->reg_flags == i.op[3].regs->reg_flags) { /* clear the arguments that are stored in drex */ - UINTS_CLEAR (i.types[2]); - UINTS_CLEAR (i.types[3]); + operand_type_set (&i.types[2], 0); + operand_type_set (&i.types[3], 0); i.reg_operands -= 2; /* Specify the modrm encoding and remember the register @@ -4066,8 +4363,8 @@ process_drex (void) && i.op[0].regs->reg_flags == i.op[3].regs->reg_flags) { /* clear the arguments that are stored in drex */ - UINTS_CLEAR (i.types[0]); - UINTS_CLEAR (i.types[3]); + operand_type_set (&i.types[0], 0); + operand_type_set (&i.types[3], 0); i.reg_operands -= 2; /* Specify the modrm encoding and remember the register @@ -4099,7 +4396,7 @@ process_drex (void) && i.types[2].bitfield.regxmm != 0) { /* Clear the arguments that are stored in drex. */ - UINTS_CLEAR (i.types[2]); + operand_type_set (&i.types[2], 0); i.reg_operands--; /* Specify the modrm encoding and remember the register @@ -4117,7 +4414,7 @@ process_drex (void) && i.types[2].bitfield.regxmm != 0) { /* Clear the arguments that are stored in drex. */ - UINTS_CLEAR (i.types[2]); + operand_type_set (&i.types[2], 0); i.reg_operands--; /* Specify the modrm encoding and remember the register @@ -4136,7 +4433,7 @@ process_drex (void) && i.types[2].bitfield.regxmm != 0) { /* Clear the arguments that are stored in drex. */ - UINTS_CLEAR (i.types[2]); + operand_type_set (&i.types[2], 0); i.reg_operands--; /* Specify the modrm encoding and remember the register @@ -4166,7 +4463,7 @@ process_drex (void) && i.types[3].bitfield.regxmm != 0) { /* clear the arguments that are stored in drex */ - UINTS_CLEAR (i.types[3]); + operand_type_set (&i.types[3], 0); i.reg_operands--; /* Specify the modrm encoding and remember the register @@ -4188,7 +4485,7 @@ process_drex (void) && operand_type_check (i.types[3], imm) != 0) { /* clear the arguments that are stored in drex */ - UINTS_CLEAR (i.types[2]); + operand_type_set (&i.types[2], 0); i.reg_operands--; /* Specify the modrm encoding and remember the register @@ -4224,57 +4521,57 @@ process_operands (void) || i.tm.opcode_modifier.drexc) process_drex (); - /* The imul $imm, %reg instruction is converted into - imul $imm, %reg, %reg, and the clr %reg instruction - is converted into xor %reg, %reg. */ - if (i.tm.opcode_modifier.regkludge) - { - if (i.tm.cpu_flags.bitfield.cpusse4_1) - { - /* The first operand in instruction blendvpd, blendvps and - pblendvb in SSE4.1 is implicit and must be xmm0. */ - assert (i.operands == 3 - && i.reg_operands >= 2 - && UINTS_EQUAL (i.types[0], regxmm)); - if (i.op[0].regs->reg_num != 0) - { - if (intel_syntax) - as_bad (_("the last operand of `%s' must be `%sxmm0'"), - i.tm.name, register_prefix); - else - as_bad (_("the first operand of `%s' must be `%sxmm0'"), - i.tm.name, register_prefix); - return 0; - } - i.op[0] = i.op[1]; - i.op[1] = i.op[2]; - i.types[0] = i.types[1]; - i.types[1] = i.types[2]; - i.operands--; - i.reg_operands--; - - /* We need to adjust fields in i.tm since they are used by - build_modrm_byte. */ - i.tm.operand_types [0] = i.tm.operand_types [1]; - i.tm.operand_types [1] = i.tm.operand_types [2]; - i.tm.operands--; - } - else - { - unsigned int first_reg_op; - - if (operand_type_check (i.types[0], reg)) - first_reg_op = 0; - else - first_reg_op = 1; - /* Pretend we saw the extra register operand. */ - assert (i.reg_operands == 1 - && i.op[first_reg_op + 1].regs == 0); - i.op[first_reg_op + 1].regs = i.op[first_reg_op].regs; - i.types[first_reg_op + 1] = i.types[first_reg_op]; - i.operands++; - i.reg_operands++; - } + if (i.tm.opcode_modifier.firstxmm0) + { + unsigned int j; + + /* The first operand is implicit and must be xmm0. */ + assert (i.reg_operands + && operand_type_equal (&i.types[0], ®xmm)); + if (i.op[0].regs->reg_num != 0) + { + if (intel_syntax) + as_bad (_("the last operand of `%s' must be `%sxmm0'"), + i.tm.name, register_prefix); + else + as_bad (_("the first operand of `%s' must be `%sxmm0'"), + i.tm.name, register_prefix); + return 0; + } + + for (j = 1; j < i.operands; j++) + { + i.op[j - 1] = i.op[j]; + i.types[j - 1] = i.types[j]; + + /* We need to adjust fields in i.tm since they are used by + build_modrm_byte. */ + i.tm.operand_types [j - 1] = i.tm.operand_types [j]; + } + + i.operands--; + i.reg_operands--; + i.tm.operands--; + } + else if (i.tm.opcode_modifier.regkludge) + { + /* The imul $imm, %reg instruction is converted into + imul $imm, %reg, %reg, and the clr %reg instruction + is converted into xor %reg, %reg. */ + + unsigned int first_reg_op; + + if (operand_type_check (i.types[0], reg)) + first_reg_op = 0; + else + first_reg_op = 1; + /* Pretend we saw the extra register operand. */ + assert (i.reg_operands == 1 + && i.op[first_reg_op + 1].regs == 0); + i.op[first_reg_op + 1].regs = i.op[first_reg_op].regs; + i.types[first_reg_op + 1] = i.types[first_reg_op]; + i.operands++; + i.reg_operands++; } if (i.tm.opcode_modifier.shortform) @@ -4415,11 +4712,12 @@ build_modrm_byte (void) source = 0; break; case 4: - /* When there are 4 operands, the first two must be immediate - operands. The source operand will be the 3rd one. */ + /* When there are 4 operands, the first two must be 8bit + immediate operands. The source operand will be the 3rd + one. */ assert (i.imm_operands == 2 - && operand_type_check (i.types[0], imm) - && operand_type_check (i.types[1], imm)); + && i.types[0].bitfield.imm8 + && i.types[1].bitfield.imm8); source = 2; break; default: @@ -4596,7 +4894,7 @@ build_modrm_byte (void) && operand_type_check (i.types[op], disp)) { i386_operand_type temp; - UINTS_CLEAR (temp); + operand_type_set (&temp, 0); temp.bitfield.disp8 = i.types[op].bitfield.disp8; i.types[op] = temp; if (i.prefix[ADDR_PREFIX] == 0) @@ -4975,6 +5273,7 @@ output_insn (void) /* Output normal instructions here. */ char *p; unsigned char *q; + unsigned int j; unsigned int prefix; switch (i.tm.opcode_length) @@ -5008,16 +5307,9 @@ check_prefix: } /* The prefix bytes. */ - for (q = i.prefix; - q < i.prefix + sizeof (i.prefix) / sizeof (i.prefix[0]); - q++) - { - if (*q) - { - p = frag_more (1); - md_number_to_chars (p, (valueT) *q, 1); - } - } + for (j = ARRAY_SIZE (i.prefix), q = i.prefix; j > 0; j--, q++) + if (*q) + FRAG_APPEND_1_CHAR (*q); /* Now the opcode; be careful about word order here! */ if (i.tm.opcode_length == 1) @@ -5055,12 +5347,9 @@ check_prefix: /* Now the modrm byte and sib byte (if present). */ if (i.tm.opcode_modifier.modrm) { - p = frag_more (1); - md_number_to_chars (p, - (valueT) (i.rm.regmem << 0 - | i.rm.reg << 3 - | i.rm.mode << 6), - 1); + FRAG_APPEND_1_CHAR ((i.rm.regmem << 0 + | i.rm.reg << 3 + | i.rm.mode << 6)); /* If i.rm.regmem == ESP (4) && i.rm.mode != (Register mode) && not 16 bit @@ -5068,14 +5357,9 @@ check_prefix: if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING && i.rm.mode != 3 && !(i.base_reg && i.base_reg->reg_type.bitfield.reg16)) - { - p = frag_more (1); - md_number_to_chars (p, - (valueT) (i.sib.base << 0 - | i.sib.index << 3 - | i.sib.scale << 6), - 1); - } + FRAG_APPEND_1_CHAR ((i.sib.base << 0 + | i.sib.index << 3 + | i.sib.scale << 6)); } /* Write the DREX byte if needed. */ @@ -5475,7 +5759,7 @@ lex_got (enum bfd_reloc_code_real *reloc, if (is_end_of_line[(unsigned char) *cp] || *cp == ',') return NULL; - for (j = 0; j < sizeof (gotrel) / sizeof (gotrel[0]); j++) + for (j = 0; j < ARRAY_SIZE (gotrel); j++) { int len; @@ -5622,7 +5906,7 @@ i386_immediate (char *imm_start) expressionS *exp; i386_operand_type types; - UINTS_SET (types, ~0); + operand_type_set (&types, ~0); if (i.imm_operands == MAX_IMMEDIATE_OPERANDS) { @@ -5774,7 +6058,7 @@ i386_displacement (char *disp_start, char *disp_end) return 0; } - UINTS_CLEAR (bigdisp); + operand_type_set (&bigdisp, 0); if ((i.types[this_operand].bitfield.jumpabsolute) || (!current_templates->start->opcode_modifier.jump && !current_templates->start->opcode_modifier.jumpdword)) @@ -5955,7 +6239,7 @@ i386_displacement (char *disp_start, char *disp_end) bigdisp.bitfield.disp32 = 0; bigdisp.bitfield.disp32s = 0; bigdisp.bitfield.disp64 = 0; - if (UINTS_ALL_ZERO (bigdisp)) + if (operand_type_all_zero (&bigdisp)) i.types[this_operand] = operand_type_and (i.types[this_operand], types); @@ -6061,7 +6345,7 @@ i386_index_check (const char *operand_string) on error. */ static int -i386_operand (char *operand_string) +i386_att_operand (char *operand_string) { const reg_entry *r; char *end_op; @@ -6148,6 +6432,7 @@ i386_operand (char *operand_string) temp.bitfield.baseindex = 0; i.types[this_operand] = operand_type_or (i.types[this_operand], temp); + i.types[this_operand].bitfield.unspecified = 0; i.op[this_operand].regs = r; i.reg_operands++; } @@ -6327,19 +6612,20 @@ i386_operand (char *operand_string) /* Special case for (%dx) while doing input/output op. */ if (i.base_reg - && UINTS_EQUAL (i.base_reg->reg_type, reg16_inoutportreg) + && operand_type_equal (&i.base_reg->reg_type, + ®16_inoutportreg) && i.index_reg == 0 && i.log2_scale_factor == 0 && i.seg[i.mem_operands] == 0 && !operand_type_check (i.types[this_operand], disp)) { - UINTS_CLEAR (i.types[this_operand]); - i.types[this_operand].bitfield.inoutportreg = 1; + i.types[this_operand] = inoutportreg; return 1; } if (i386_index_check (operand_string) == 0) return 0; + i.types[this_operand].bitfield.mem = 1; i.mem_operands++; } else @@ -6587,41 +6873,6 @@ md_convert_frag (abfd, sec, fragP) fragP->fr_fix += extension; } -/* Size of byte displacement jmp. */ -int md_short_jump_size = 2; - -/* Size of dword displacement jmp. */ -int md_long_jump_size = 5; - -void -md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) - char *ptr; - addressT from_addr, to_addr; - fragS *frag ATTRIBUTE_UNUSED; - symbolS *to_symbol ATTRIBUTE_UNUSED; -{ - offsetT offset; - - offset = to_addr - (from_addr + 2); - /* Opcode for byte-disp jump. */ - md_number_to_chars (ptr, (valueT) 0xeb, 1); - md_number_to_chars (ptr + 1, (valueT) offset, 1); -} - -void -md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) - char *ptr; - addressT from_addr, to_addr; - fragS *frag ATTRIBUTE_UNUSED; - symbolS *to_symbol ATTRIBUTE_UNUSED; -{ - offsetT offset; - - offset = to_addr - (from_addr + 5); - md_number_to_chars (ptr, (valueT) 0xe9, 1); - md_number_to_chars (ptr + 1, (valueT) offset, 4); -} - /* Apply a fixup (fixS) to segment data, once it has been determined by our caller that we have all the info we need to fix it up. @@ -6784,58 +7035,12 @@ md_apply_fix (fixP, valP, seg) md_number_to_chars (p, value, fixP->fx_size); } -#define MAX_LITTLENUMS 6 - -/* Turn the string pointed to by litP into a floating point constant - of type TYPE, and emit the appropriate bytes. The number of - LITTLENUMS emitted is stored in *SIZEP. An error message is - returned, or NULL on OK. */ - char * -md_atof (type, litP, sizeP) - int type; - char *litP; - int *sizeP; +md_atof (int type, char *litP, int *sizeP) { - int prec; - LITTLENUM_TYPE words[MAX_LITTLENUMS]; - LITTLENUM_TYPE *wordP; - char *t; - - switch (type) - { - case 'f': - case 'F': - prec = 2; - break; - - case 'd': - case 'D': - prec = 4; - break; - - case 'x': - case 'X': - prec = 5; - break; - - default: - *sizeP = 0; - return _("Bad call to md_atof ()"); - } - t = atof_ieee (input_line_pointer, type, words); - if (t) - input_line_pointer = t; - - *sizeP = prec * sizeof (LITTLENUM_TYPE); - /* This loops outputs the LITTLENUMs in REVERSE order; in accord with - the bigendian 386. */ - for (wordP = words + prec - 1; prec--;) - { - md_number_to_chars (litP, (valueT) (*wordP--), sizeof (LITTLENUM_TYPE)); - litP += sizeof (LITTLENUM_TYPE); - } - return 0; + /* This outputs the LITTLENUMs in REVERSE order; + in accord with the bigendian 386. */ + return ieee_md_atof (type, litP, sizeP, FALSE); } static char output_invalid_buf[sizeof (unsigned char) * 2 + 6]; @@ -6916,20 +7121,41 @@ parse_real_register (char *reg_string, char **end_op) } } + if (r == NULL || allow_pseudo_reg) + return r; + + if (operand_type_all_zero (&r->reg_type)) + return (const reg_entry *) NULL; + + if ((r->reg_type.bitfield.reg32 + || r->reg_type.bitfield.sreg3 + || r->reg_type.bitfield.control + || r->reg_type.bitfield.debug + || r->reg_type.bitfield.test) + && !cpu_arch_flags.bitfield.cpui386) + return (const reg_entry *) NULL; + + if (r->reg_type.bitfield.regmmx && !cpu_arch_flags.bitfield.cpummx) + return (const reg_entry *) NULL; + + if (r->reg_type.bitfield.regxmm && !cpu_arch_flags.bitfield.cpusse) + return (const reg_entry *) NULL; + /* Don't allow fake index register unless allow_index_reg isn't 0. */ - if (r != NULL - && !allow_index_reg + if (!allow_index_reg && (r->reg_num == RegEiz || r->reg_num == RegRiz)) return (const reg_entry *) NULL; - if (r != NULL - && ((r->reg_flags & (RegRex64 | RegRex)) - || r->reg_type.bitfield.reg64) + if (((r->reg_flags & (RegRex64 | RegRex)) + || r->reg_type.bitfield.reg64) && (!cpu_arch_flags.bitfield.cpulm - || !UINTS_EQUAL (r->reg_type, control)) + || !operand_type_equal (&r->reg_type, &control)) && flag_code != CODE_64BIT) return (const reg_entry *) NULL; + if (r->reg_type.bitfield.sreg3 && r->reg_num == RegFlat && !intel_syntax) + return (const reg_entry *) NULL; + return r; } @@ -7019,6 +7245,11 @@ const char *md_shortopts = "qn"; #define OPTION_DIVIDE (OPTION_MD_BASE + 2) #define OPTION_MARCH (OPTION_MD_BASE + 3) #define OPTION_MTUNE (OPTION_MD_BASE + 4) +#define OPTION_MMNEMONIC (OPTION_MD_BASE + 5) +#define OPTION_MSYNTAX (OPTION_MD_BASE + 6) +#define OPTION_MINDEX_REG (OPTION_MD_BASE + 7) +#define OPTION_MNAKED_REG (OPTION_MD_BASE + 8) +#define OPTION_MOLD_GCC (OPTION_MD_BASE + 9) struct option md_longopts[] = { @@ -7029,6 +7260,11 @@ struct option md_longopts[] = {"divide", no_argument, NULL, OPTION_DIVIDE}, {"march", required_argument, NULL, OPTION_MARCH}, {"mtune", required_argument, NULL, OPTION_MTUNE}, + {"mmnemonic", required_argument, NULL, OPTION_MMNEMONIC}, + {"msyntax", required_argument, NULL, OPTION_MSYNTAX}, + {"mindex-reg", no_argument, NULL, OPTION_MINDEX_REG}, + {"mnaked-reg", no_argument, NULL, OPTION_MNAKED_REG}, + {"mold-gcc", no_argument, NULL, OPTION_MOLD_GCC}, {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof (md_longopts); @@ -7037,6 +7273,7 @@ int md_parse_option (int c, char *arg) { unsigned int i; + char *arch, *next; switch (c) { @@ -7112,24 +7349,62 @@ md_parse_option (int c, char *arg) break; case OPTION_MARCH: - if (*arg == '.') - as_fatal (_("Invalid -march= option: `%s'"), arg); - for (i = 0; i < ARRAY_SIZE (cpu_arch); i++) - { - if (strcmp (arg, cpu_arch [i].name) == 0) + arch = xstrdup (arg); + do + { + if (*arch == '.') + as_fatal (_("Invalid -march= option: `%s'"), arg); + next = strchr (arch, '+'); + if (next) + *next++ = '\0'; + for (i = 0; i < ARRAY_SIZE (cpu_arch); i++) { - cpu_arch_isa = cpu_arch[i].type; - cpu_arch_isa_flags = cpu_arch[i].flags; - if (!cpu_arch_tune_set) + if (strcmp (arch, cpu_arch [i].name) == 0) { - cpu_arch_tune = cpu_arch_isa; - cpu_arch_tune_flags = cpu_arch_isa_flags; + /* Processor. */ + cpu_arch_name = cpu_arch[i].name; + cpu_sub_arch_name = NULL; + cpu_arch_flags = cpu_arch[i].flags; + cpu_arch_isa = cpu_arch[i].type; + cpu_arch_isa_flags = cpu_arch[i].flags; + if (!cpu_arch_tune_set) + { + cpu_arch_tune = cpu_arch_isa; + cpu_arch_tune_flags = cpu_arch_isa_flags; + } + break; + } + else if (*cpu_arch [i].name == '.' + && strcmp (arch, cpu_arch [i].name + 1) == 0) + { + /* ISA entension. */ + i386_cpu_flags flags; + flags = cpu_flags_or (cpu_arch_flags, + cpu_arch[i].flags); + if (!cpu_flags_equal (&flags, &cpu_arch_flags)) + { + if (cpu_sub_arch_name) + { + char *name = cpu_sub_arch_name; + cpu_sub_arch_name = concat (name, + cpu_arch[i].name, + (const char *) NULL); + free (name); + } + else + cpu_sub_arch_name = xstrdup (cpu_arch[i].name); + cpu_arch_flags = flags; + } + break; } - break; } + + if (i >= ARRAY_SIZE (cpu_arch)) + as_fatal (_("Invalid -march= option: `%s'"), arg); + + arch = next; } - if (i >= ARRAY_SIZE (cpu_arch)) - as_fatal (_("Invalid -march= option: `%s'"), arg); + while (next != NULL ); break; case OPTION_MTUNE: @@ -7149,6 +7424,36 @@ md_parse_option (int c, char *arg) as_fatal (_("Invalid -mtune= option: `%s'"), arg); break; + case OPTION_MMNEMONIC: + if (strcasecmp (arg, "att") == 0) + intel_mnemonic = 0; + else if (strcasecmp (arg, "intel") == 0) + intel_mnemonic = 1; + else + as_fatal (_("Invalid -mmnemonic= option: `%s'"), arg); + break; + + case OPTION_MSYNTAX: + if (strcasecmp (arg, "att") == 0) + intel_syntax = 0; + else if (strcasecmp (arg, "intel") == 0) + intel_syntax = 1; + else + as_fatal (_("Invalid -msyntax= option: `%s'"), arg); + break; + + case OPTION_MINDEX_REG: + allow_index_reg = 1; + break; + + case OPTION_MNAKED_REG: + allow_naked_reg = 1; + break; + + case OPTION_MOLD_GCC: + old_gcc = 1; + break; + default: return 0; } @@ -7184,10 +7489,32 @@ md_show_usage (stream) --divide ignored\n")); #endif fprintf (stream, _("\ - -march=CPU/-mtune=CPU generate code/optimize for CPU, where CPU is one of:\n\ - i386, i486, pentium, pentiumpro, pentium4, nocona,\n\ - core, core2, k6, athlon, k8, generic32, generic64\n")); - + -march=CPU[,+EXTENSION...]\n\ + generate code for CPU and EXTENSION, CPU is one of:\n\ + i8086, i186, i286, i386, i486, pentium, pentiumpro,\n\ + pentiumii, pentiumiii, pentium4, prescott, nocona,\n\ + core, core2, k6, k6_2, athlon, k8, amdfam10,\n\ + generic32, generic64\n\ + EXTENSION is combination of:\n\ + mmx, sse, sse2, sse3, ssse3, sse4.1, sse4.2, sse4,\n\ + vmx, smx, xsave, 3dnow, 3dnowa, sse4a, sse5, svme,\n\ + abm, padlock\n")); + fprintf (stream, _("\ + -mtune=CPU optimize for CPU, CPU is one of:\n\ + i8086, i186, i286, i386, i486, pentium, pentiumpro,\n\ + pentiumii, pentiumiii, pentium4, prescott, nocona,\n\ + core, core2, k6, k6_2, athlon, k8, amdfam10,\n\ + generic32, generic64\n")); + fprintf (stream, _("\ + -mmnemonic=[att|intel] use AT&T/Intel mnemonic\n")); + fprintf (stream, _("\ + -msyntax=[att|intel] use AT&T/Intel syntax\n")); + fprintf (stream, _("\ + -mindex-reg support pseudo index registers\n")); + fprintf (stream, _("\ + -mnaked-reg don't require `%%' prefix for registers\n")); + fprintf (stream, _("\ + -mold-gcc support old (<= 2.8.1) versions of gcc\n")); } #if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \ @@ -7201,7 +7528,7 @@ i386_target_format (void) if (!strcmp (default_arch, "x86_64")) { set_code_flag (CODE_64BIT); - if (UINTS_ALL_ZERO (cpu_arch_isa_flags)) + if (cpu_flags_all_zero (&cpu_arch_isa_flags)) { cpu_arch_isa_flags.bitfield.cpui186 = 1; cpu_arch_isa_flags.bitfield.cpui286 = 1; @@ -7211,11 +7538,10 @@ i386_target_format (void) cpu_arch_isa_flags.bitfield.cpui686 = 1; cpu_arch_isa_flags.bitfield.cpup4 = 1; cpu_arch_isa_flags.bitfield.cpummx= 1; - cpu_arch_isa_flags.bitfield.cpummx2 = 1; cpu_arch_isa_flags.bitfield.cpusse = 1; cpu_arch_isa_flags.bitfield.cpusse2 = 1; } - if (UINTS_ALL_ZERO (cpu_arch_tune_flags)) + if (cpu_flags_all_zero (&cpu_arch_tune_flags)) { cpu_arch_tune_flags.bitfield.cpui186 = 1; cpu_arch_tune_flags.bitfield.cpui286 = 1; @@ -7225,7 +7551,6 @@ i386_target_format (void) cpu_arch_tune_flags.bitfield.cpui686 = 1; cpu_arch_tune_flags.bitfield.cpup4 = 1; cpu_arch_tune_flags.bitfield.cpummx= 1; - cpu_arch_tune_flags.bitfield.cpummx2 = 1; cpu_arch_tune_flags.bitfield.cpusse = 1; cpu_arch_tune_flags.bitfield.cpusse2 = 1; } @@ -7233,13 +7558,13 @@ i386_target_format (void) else if (!strcmp (default_arch, "i386")) { set_code_flag (CODE_32BIT); - if (UINTS_ALL_ZERO (cpu_arch_isa_flags)) + if (cpu_flags_all_zero (&cpu_arch_isa_flags)) { cpu_arch_isa_flags.bitfield.cpui186 = 1; cpu_arch_isa_flags.bitfield.cpui286 = 1; cpu_arch_isa_flags.bitfield.cpui386 = 1; } - if (UINTS_ALL_ZERO (cpu_arch_tune_flags)) + if (cpu_flags_all_zero (&cpu_arch_tune_flags)) { cpu_arch_tune_flags.bitfield.cpui186 = 1; cpu_arch_tune_flags.bitfield.cpui286 = 1; @@ -7853,6 +8178,7 @@ i386_intel_operand (char *operand_string, int got_a_float) else { char *s = intel_parser.disp; + i.types[this_operand].bitfield.mem = 1; i.mem_operands++; if (!quiet_warnings && intel_parser.is_mem < 0) @@ -7887,7 +8213,15 @@ i386_intel_operand (char *operand_string, int got_a_float) /* Constant and OFFSET expressions are handled by i386_immediate. */ else if ((intel_parser.op_modifier & (1 << T_OFFSET)) || intel_parser.reg == NULL) - ret = i386_immediate (intel_parser.disp); + { + if (i.mem_operands < 2 && i.seg[i.mem_operands]) + { + if (!(intel_parser.op_modifier & (1 << T_OFFSET))) + as_warn (_("Segment override ignored")); + i.seg[i.mem_operands] = NULL; + } + ret = i386_immediate (intel_parser.disp); + } if (intel_parser.next_operand && this_operand >= MAX_OPERANDS - 1) ret = 0; @@ -7895,6 +8229,7 @@ i386_intel_operand (char *operand_string, int got_a_float) break; intel_parser.op_string = intel_parser.next_operand; this_operand = i.operands++; + i.types[this_operand].bitfield.unspecified = 1; } free (p); @@ -8103,25 +8438,31 @@ intel_e09 (void) char suffix; if (prev_token.code == T_BYTE) - suffix = BYTE_MNEM_SUFFIX; + { + suffix = BYTE_MNEM_SUFFIX; + i.types[this_operand].bitfield.byte = 1; + } else if (prev_token.code == T_WORD) { - if (current_templates->start->name[0] == 'l' - && current_templates->start->name[2] == 's' - && current_templates->start->name[3] == 0) + if ((current_templates->start->name[0] == 'l' + && current_templates->start->name[2] == 's' + && current_templates->start->name[3] == 0) + || current_templates->start->base_opcode == 0x62 /* bound */) suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */ else if (intel_parser.got_a_float == 2) /* "fi..." */ suffix = SHORT_MNEM_SUFFIX; else suffix = WORD_MNEM_SUFFIX; + i.types[this_operand].bitfield.word = 1; } else if (prev_token.code == T_DWORD) { - if (current_templates->start->name[0] == 'l' - && current_templates->start->name[2] == 's' - && current_templates->start->name[3] == 0) + if ((current_templates->start->name[0] == 'l' + && current_templates->start->name[2] == 's' + && current_templates->start->name[3] == 0) + || current_templates->start->base_opcode == 0x62 /* bound */) suffix = WORD_MNEM_SUFFIX; else if (flag_code == CODE_16BIT && (current_templates->start->opcode_modifier.jump @@ -8131,6 +8472,7 @@ intel_e09 (void) suffix = SHORT_MNEM_SUFFIX; else suffix = LONG_MNEM_SUFFIX; + i.types[this_operand].bitfield.dword = 1; } else if (prev_token.code == T_FWORD) @@ -8147,14 +8489,17 @@ intel_e09 (void) } else suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */ + i.types[this_operand].bitfield.fword = 1; } else if (prev_token.code == T_QWORD) { - if (intel_parser.got_a_float == 1) /* "f..." */ + if (current_templates->start->base_opcode == 0x62 /* bound */ + || intel_parser.got_a_float == 1) /* "f..." */ suffix = LONG_MNEM_SUFFIX; else suffix = QWORD_MNEM_SUFFIX; + i.types[this_operand].bitfield.qword = 1; } else if (prev_token.code == T_TBYTE) @@ -8167,8 +8512,8 @@ intel_e09 (void) else if (prev_token.code == T_XMMWORD) { - /* XXX ignored for now, but accepted since gcc uses it */ - suffix = 0; + suffix = XMMWORD_MNEM_SUFFIX; + i.types[this_operand].bitfield.xmmword = 1; } else @@ -8177,6 +8522,8 @@ intel_e09 (void) return 0; } + i.types[this_operand].bitfield.unspecified = 0; + /* Operands for jump/call using 'ptr' notation denote absolute addresses. */ if (current_templates->start->opcode_modifier.jump @@ -8408,6 +8755,8 @@ intel_e11 (void) reg->reg_name); return 0; } + else if (i.mem_operands >= 2) + as_warn (_("Segment override ignored")); else if (i.seg[i.mem_operands]) as_warn (_("Extra segment override ignored")); else @@ -8438,6 +8787,12 @@ intel_e11 (void) } } + else if (reg->reg_type.bitfield.sreg3 && reg->reg_num == RegFlat) + { + as_bad (_("cannot use `FLAT' here")); + return 0; + } + /* Not a segment register. Check for register scaling. */ else if (cur_token.code == '*') { @@ -8507,6 +8862,7 @@ intel_e11 (void) temp.bitfield.baseindex = 0; i.types[this_operand] = operand_type_or (i.types[this_operand], temp); + i.types[this_operand].bitfield.unspecified = 0; i.op[this_operand].regs = reg; i.reg_operands++; } @@ -8828,16 +9184,6 @@ intel_get_token (void) strcat (new_token.str, " FLAT:"); } - /* ??? This is not mentioned in the MASM grammar. */ - else if (strcasecmp (new_token.str, "FLAT") == 0) - { - new_token.code = T_OFFSET; - if (*q == ':') - strcat (new_token.str, ":"); - else - as_bad (_("`:' expected")); - } - else new_token.code = T_ID; } @@ -8884,79 +9230,54 @@ intel_putback_token (void) prev_token.str = NULL; } -int -tc_x86_regname_to_dw2regnum (char *regname) -{ - unsigned int regnum; - unsigned int regnames_count; - static const char *const regnames_32[] = - { - "eax", "ecx", "edx", "ebx", - "esp", "ebp", "esi", "edi", - "eip", "eflags", NULL, - "st0", "st1", "st2", "st3", - "st4", "st5", "st6", "st7", - NULL, NULL, - "xmm0", "xmm1", "xmm2", "xmm3", - "xmm4", "xmm5", "xmm6", "xmm7", - "mm0", "mm1", "mm2", "mm3", - "mm4", "mm5", "mm6", "mm7", - "fcw", "fsw", "mxcsr", - "es", "cs", "ss", "ds", "fs", "gs", NULL, NULL, - "tr", "ldtr" - }; - static const char *const regnames_64[] = - { - "rax", "rdx", "rcx", "rbx", - "rsi", "rdi", "rbp", "rsp", - "r8", "r9", "r10", "r11", - "r12", "r13", "r14", "r15", - "rip", - "xmm0", "xmm1", "xmm2", "xmm3", - "xmm4", "xmm5", "xmm6", "xmm7", - "xmm8", "xmm9", "xmm10", "xmm11", - "xmm12", "xmm13", "xmm14", "xmm15", - "st0", "st1", "st2", "st3", - "st4", "st5", "st6", "st7", - "mm0", "mm1", "mm2", "mm3", - "mm4", "mm5", "mm6", "mm7", - "rflags", - "es", "cs", "ss", "ds", "fs", "gs", NULL, NULL, - "fs.base", "gs.base", NULL, NULL, - "tr", "ldtr", - "mxcsr", "fcw", "fsw" - }; - const char *const *regnames; +void +tc_x86_parse_to_dw2regnum (expressionS *exp) +{ + int saved_naked_reg; + char saved_register_dot; - if (flag_code == CODE_64BIT) - { - regnames = regnames_64; - regnames_count = ARRAY_SIZE (regnames_64); - } - else + saved_naked_reg = allow_naked_reg; + allow_naked_reg = 1; + saved_register_dot = register_chars['.']; + register_chars['.'] = '.'; + allow_pseudo_reg = 1; + expression_and_evaluate (exp); + allow_pseudo_reg = 0; + register_chars['.'] = saved_register_dot; + allow_naked_reg = saved_naked_reg; + + if (exp->X_op == O_register && exp->X_add_number >= 0) { - regnames = regnames_32; - regnames_count = ARRAY_SIZE (regnames_32); + if ((addressT) exp->X_add_number < i386_regtab_size) + { + exp->X_op = O_constant; + exp->X_add_number = i386_regtab[exp->X_add_number] + .dw2_regnum[flag_code >> 1]; + } + else + exp->X_op = O_illegal; } - - for (regnum = 0; regnum < regnames_count; regnum++) - if (regnames[regnum] != NULL - && strcmp (regname, regnames[regnum]) == 0) - return regnum; - - return -1; } void tc_x86_frame_initial_instructions (void) { - static unsigned int sp_regno; + static unsigned int sp_regno[2]; - if (!sp_regno) - sp_regno = tc_x86_regname_to_dw2regnum (flag_code == CODE_64BIT - ? "rsp" : "esp"); + if (!sp_regno[flag_code >> 1]) + { + char *saved_input = input_line_pointer; + char sp[][4] = {"esp", "rsp"}; + expressionS exp; + + input_line_pointer = sp[flag_code >> 1]; + tc_x86_parse_to_dw2regnum (&exp); + assert (exp.X_op == O_constant); + sp_regno[flag_code >> 1] = exp.X_add_number; + input_line_pointer = saved_input; + } - cfi_add_CFA_def_cfa (sp_regno, -x86_cie_data_alignment); + cfi_add_CFA_def_cfa (sp_regno[flag_code >> 1], -x86_cie_data_alignment); cfi_add_CFA_offset (x86_dwarf2_return_column, x86_cie_data_alignment); }