X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-i386.c;h=ecf48bd6b582975d02ae1a2503c2c7d413bb8fed;hb=599121aa77fb254f0e96538de58619cf6415baed;hp=0669c03542cc2879c11d0139f309d14fe4ebe8e0;hpb=07e8d93c1c9b260b004cbaa61a02cfd4b15e5936;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 0669c03542..ecf48bd6b5 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,17 @@ 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 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 +435,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 +549,96 @@ 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 }, + { ".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 +665,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) @@ -956,29 +1089,6 @@ cpu_flags_check_cpu64 (i386_cpu_flags f) || (flag_code != CODE_64BIT && f.bitfield.cpu64)); } -static INLINE i386_cpu_flags -cpu_flags_not (i386_cpu_flags x) -{ - switch (ARRAY_SIZE (x.array)) - { - case 3: - x.array [2] = ~x.array [2]; - case 2: - x.array [1] = ~x.array [1]; - case 1: - x.array [0] = ~x.array [0]; - break; - default: - abort (); - } - -#ifdef CpuUnused - x.bitfield.unused = 0; -#endif - - return x; -} - static INLINE i386_cpu_flags cpu_flags_and (i386_cpu_flags x, i386_cpu_flags y) { @@ -1015,19 +1125,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 (UINTS_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 |= UINTS_ALL_ZERO (cpu) ? 0 : 1; + } + return overlap; } static INLINE i386_operand_type @@ -1153,6 +1273,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,6 +1376,14 @@ operand_type_match (i386_operand_type overlap, i386_operand_type temp = overlap; temp.bitfield.jumpabsolute = 0; + 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 (UINTS_ALL_ZERO (temp)) return 0; @@ -1167,7 +1391,7 @@ operand_type_match (i386_operand_type overlap, && 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. */ @@ -1435,15 +1659,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 +1684,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; } @@ -1504,6 +1722,12 @@ set_intel_syntax (int syntax_flag) register_prefix = allow_naked_reg ? "" : "%"; } +static void +set_intel_mnemonic (int mnemonic_flag) +{ + intel_mnemonic = mnemonic_flag; +} + static void set_allow_index_reg (int flag) { @@ -1541,7 +1765,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) @@ -1556,9 +1779,17 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED) cpu_arch[i].flags); if (!UINTS_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, + 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 +1840,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 (); @@ -2183,30 +2412,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) @@ -2536,11 +2755,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 +2770,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 +2876,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 +2891,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) @@ -2979,7 +3201,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 +3223,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 +3233,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 @@ -3039,16 +3283,11 @@ match_template (void) 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 +3336,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) { @@ -3119,19 +3361,8 @@ match_template (void) 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 +3376,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 +3416,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 +3430,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 +3444,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 +3620,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 +3632,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 +3697,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 +3719,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 +3735,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 @@ -3565,16 +3805,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,12 +3918,10 @@ check_long_reg (void) || i.tm.operand_types[op].bitfield.acc)) { if (intel_syntax - && (i.tm.base_opcode == 0xf30f2d - || i.tm.base_opcode == 0xf30f2c) + && i.tm.opcode_modifier.toqword && !i.types[0].bitfield.regxmm) { - /* cvtss2si/cvttss2si convert DWORD memory to Reg64. We - want REX byte. */ + /* Convert to QWORD. We want REX byte. */ i.suffix = QWORD_MNEM_SUFFIX; } else @@ -3734,12 +3964,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.base_opcode == 0xf20f2c) + && i.tm.opcode_modifier.todword && !i.types[0].bitfield.regxmm) { - /* cvtsd2si/cvttsd2si convert 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 @@ -3885,8 +4113,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 @@ -4226,57 +4454,56 @@ 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 && 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; + } + + 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) @@ -4417,11 +4644,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: @@ -4977,6 +5205,7 @@ output_insn (void) /* Output normal instructions here. */ char *p; unsigned char *q; + unsigned int j; unsigned int prefix; switch (i.tm.opcode_length) @@ -5010,16 +5239,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) @@ -5057,12 +5279,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 @@ -5070,14 +5289,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. */ @@ -5477,7 +5691,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; @@ -6063,7 +6277,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; @@ -6150,6 +6364,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++; } @@ -6342,6 +6557,7 @@ i386_operand (char *operand_string) if (i386_index_check (operand_string) == 0) return 0; + i.types[this_operand].bitfield.mem = 1; i.mem_operands++; } else @@ -6589,41 +6805,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. @@ -6786,58 +6967,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]; @@ -7021,6 +7156,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[] = { @@ -7031,6 +7171,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); @@ -7039,6 +7184,7 @@ int md_parse_option (int c, char *arg) { unsigned int i; + char *arch, *next; switch (c) { @@ -7114,24 +7260,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 (!UINTS_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, + 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: @@ -7151,6 +7335,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; } @@ -7186,10 +7400,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, 3dnow, 3dnowa, sse4a, sse5, svme, abm,\n\ + 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)) \ @@ -7213,7 +7449,6 @@ 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; } @@ -7227,7 +7462,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; } @@ -7855,6 +8089,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) @@ -7897,6 +8132,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); @@ -8105,7 +8341,10 @@ 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) { @@ -8117,6 +8356,7 @@ intel_e09 (void) suffix = SHORT_MNEM_SUFFIX; else suffix = WORD_MNEM_SUFFIX; + i.types[this_operand].bitfield.word = 1; } else if (prev_token.code == T_DWORD) @@ -8133,6 +8373,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) @@ -8149,6 +8390,7 @@ 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) @@ -8156,7 +8398,8 @@ intel_e09 (void) if (intel_parser.got_a_float == 1) /* "f..." */ suffix = LONG_MNEM_SUFFIX; else - suffix = QWORD_MNEM_SUFFIX; + suffix = QWORD_MNEM_SUFFIX; + i.types[this_operand].bitfield.qword = 1; } else if (prev_token.code == T_TBYTE) @@ -8169,8 +8412,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 @@ -8179,6 +8422,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 @@ -8509,6 +8754,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++; }