diff options
Diffstat (limited to 'binutils-2.24/gas/config/tc-i386.c')
-rw-r--r-- | binutils-2.24/gas/config/tc-i386.c | 10565 |
1 files changed, 0 insertions, 10565 deletions
diff --git a/binutils-2.24/gas/config/tc-i386.c b/binutils-2.24/gas/config/tc-i386.c deleted file mode 100644 index 3c423da7..00000000 --- a/binutils-2.24/gas/config/tc-i386.c +++ /dev/null @@ -1,10565 +0,0 @@ -/* 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, 2008, 2009, 2010, 2011, - 2012 - Free Software Foundation, Inc. - - This file is part of GAS, the GNU Assembler. - - GAS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GAS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GAS; see the file COPYING. If not, write to the Free - Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA - 02110-1301, USA. */ - -/* Intel 80386 machine specific gas. - Written by Eliot Dresselhaus (eliot@mgm.mit.edu). - x86_64 support by Jan Hubicka (jh@suse.cz) - VIA PadLock support by Michal Ludvig (mludvig@suse.cz) - Bugs & suggestions are completely welcome. This is free software. - Please help us make it better. */ - -#include "as.h" -#include "safe-ctype.h" -#include "subsegs.h" -#include "dwarf2dbg.h" -#include "dw2gencfi.h" -#include "elf/x86-64.h" -#include "opcodes/i386-init.h" - -#ifndef REGISTER_WARNINGS -#define REGISTER_WARNINGS 1 -#endif - -#ifndef INFER_ADDR_PREFIX -#define INFER_ADDR_PREFIX 1 -#endif - -#ifndef DEFAULT_ARCH -#define DEFAULT_ARCH "i386" -#endif - -#ifndef INLINE -#if __GNUC__ >= 2 -#define INLINE __inline__ -#else -#define INLINE -#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, - REP_PREFIX/HLE_PREFIX, LOCK_PREFIX. */ -#define WAIT_PREFIX 0 -#define SEG_PREFIX 1 -#define ADDR_PREFIX 2 -#define DATA_PREFIX 3 -#define REP_PREFIX 4 -#define HLE_PREFIX REP_PREFIX -#define BND_PREFIX REP_PREFIX -#define LOCK_PREFIX 5 -#define REX_PREFIX 6 /* must come last. */ -#define MAX_PREFIXES 7 /* 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' -#define YMMWORD_MNEM_SUFFIX 'y' -#define ZMMWORD_MNEM_SUFFIX 'z' -/* 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 insn_template *start; - const insn_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; - -/* 386 opcode byte to code indirect addressing. */ -typedef struct -{ - unsigned base; - unsigned index; - unsigned scale; -} -sib_byte; - -/* x86 arch names, types and features */ -typedef struct -{ - const char *name; /* arch name */ - unsigned int len; /* arch string length */ - enum processor_type type; /* arch type */ - i386_cpu_flags flags; /* cpu feature flags */ - unsigned int skip; /* show_arch should skip this. */ - unsigned int negated; /* turn off indicated flags. */ -} -arch_entry; - -static void update_code_flag (int, int); -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_check (int); -static void set_cpu_arch (int); -#ifdef TE_PE -static void pe_directive_secrel (int); -#endif -static void signed_cons (int); -static char *output_invalid (int c); -static int i386_finalize_immediate (segT, expressionS *, i386_operand_type, - const char *); -static int i386_finalize_displacement (segT, expressionS *, i386_operand_type, - const char *); -static int i386_att_operand (char *); -static int i386_intel_operand (char *, int); -static int i386_intel_simplify (expressionS *); -static int i386_intel_parse_name (const char *, expressionS *); -static const reg_entry *parse_register (char *, char **); -static char *parse_insn (char *, char *); -static char *parse_operands (char *, const char *); -static void swap_operands (void); -static void swap_2_operands (int, int); -static void optimize_imm (void); -static void optimize_disp (void); -static const insn_template *match_template (void); -static int check_string (void); -static int process_suffix (void); -static int check_byte_reg (void); -static int check_long_reg (void); -static int check_qword_reg (void); -static int check_word_reg (void); -static int finalize_imm (void); -static int process_operands (void); -static const seg_entry *build_modrm_byte (void); -static void output_insn (void); -static void output_imm (fragS *, offsetT); -static void output_disp (fragS *, offsetT); -#ifndef I386COFF -static void s_bss (int); -#endif -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) -static void handle_large_common (int small ATTRIBUTE_UNUSED); -#endif - -static const char *default_arch = DEFAULT_ARCH; - -/* This struct describes rounding control and SAE in the instruction. */ -struct RC_Operation -{ - enum rc_type - { - rne = 0, - rd, - ru, - rz, - saeonly - } type; - int operand; -}; - -static struct RC_Operation rc_op; - -/* The struct describes masking, applied to OPERAND in the instruction. - MASK is a pointer to the corresponding mask register. ZEROING tells - whether merging or zeroing mask is used. */ -struct Mask_Operation -{ - const reg_entry *mask; - unsigned int zeroing; - /* The operand where this operation is associated. */ - int operand; -}; - -static struct Mask_Operation mask_op; - -/* The struct describes broadcasting, applied to OPERAND. FACTOR is - broadcast factor. */ -struct Broadcast_Operation -{ - /* Type of broadcast: no broadcast, {1to8}, or {1to16}. */ - int type; - - /* Index of broadcasted operand. */ - int operand; -}; - -static struct Broadcast_Operation broadcast_op; - -/* VEX prefix. */ -typedef struct -{ - /* VEX prefix is either 2 byte or 3 byte. EVEX is 4 byte. */ - unsigned char bytes[4]; - unsigned int length; - /* Destination or source register specifier. */ - const reg_entry *register_specifier; -} vex_prefix; - -/* 'md_assemble ()' gathers together information and puts it into a - i386_insn. */ - -union i386_op - { - expressionS *disps; - expressionS *imms; - const reg_entry *regs; - }; - -enum i386_error - { - operand_size_mismatch, - operand_type_mismatch, - register_type_mismatch, - number_of_operands_mismatch, - invalid_instruction_suffix, - bad_imm4, - old_gcc_only, - unsupported_with_intel_mnemonic, - unsupported_syntax, - unsupported, - invalid_vsib_address, - invalid_vector_register_set, - unsupported_vector_index_register, - unsupported_broadcast, - broadcast_not_on_src_operand, - broadcast_needed, - unsupported_masking, - mask_not_on_destination, - no_default_mask, - unsupported_rc_sae, - rc_sae_operand_not_last_imm, - invalid_register_operand, - try_vector_disp8 - }; - -struct _i386_insn - { - /* TM holds the template for the insn were currently assembling. */ - insn_template tm; - - /* SUFFIX holds the instruction size suffix for byte, word, dword - or qword, if given. */ - char suffix; - - /* OPERANDS gives the number of given operands. */ - unsigned int operands; - - /* REG_OPERANDS, DISP_OPERANDS, MEM_OPERANDS, IMM_OPERANDS give the number - of given register, displacement, memory operands and immediate - operands. */ - unsigned int reg_operands, disp_operands, mem_operands, imm_operands; - - /* TYPES [i] is the type (see above #defines) which tells us how to - use OP[i] for the corresponding operand. */ - i386_operand_type types[MAX_OPERANDS]; - - /* Displacement expression, immediate expression, or register for each - operand. */ - union i386_op op[MAX_OPERANDS]; - - /* Flags for operands. */ - unsigned int flags[MAX_OPERANDS]; -#define Operand_PCrel 1 - - /* Relocation type for operand */ - enum bfd_reloc_code_real reloc[MAX_OPERANDS]; - - /* BASE_REG, INDEX_REG, and LOG2_SCALE_FACTOR are used to encode - the base index byte below. */ - const reg_entry *base_reg; - const reg_entry *index_reg; - unsigned int log2_scale_factor; - - /* SEG gives the seg_entries of this insn. They are zero unless - explicit segment overrides are given. */ - const seg_entry *seg[2]; - - /* PREFIX holds all the given prefix opcodes (usually null). - PREFIXES is the number of prefix opcodes. */ - unsigned int prefixes; - unsigned char prefix[MAX_PREFIXES]; - - /* RM and SIB are the modrm byte and the sib byte where the - addressing modes of this insn are encoded. */ - modrm_byte rm; - rex_byte rex; - rex_byte vrex; - sib_byte sib; - vex_prefix vex; - - /* Masking attributes. */ - struct Mask_Operation *mask; - - /* Rounding control and SAE attributes. */ - struct RC_Operation *rounding; - - /* Broadcasting attributes. */ - struct Broadcast_Operation *broadcast; - - /* Compressed disp8*N attribute. */ - unsigned int memshift; - - /* Swap operand in encoding. */ - unsigned int swap_operand; - - /* Prefer 8bit or 32bit displacement in encoding. */ - enum - { - disp_encoding_default = 0, - disp_encoding_8bit, - disp_encoding_32bit - } disp_encoding; - - /* REP prefix. */ - const char *rep_prefix; - - /* HLE prefix. */ - const char *hle_prefix; - - /* Have BND prefix. */ - const char *bnd_prefix; - - /* Need VREX to support upper 16 registers. */ - int need_vrex; - - /* Error message. */ - enum i386_error error; - }; - -typedef struct _i386_insn i386_insn; - -/* Link RC type with corresponding string, that'll be looked for in - asm. */ -struct RC_name -{ - enum rc_type type; - const char *name; - unsigned int len; -}; - -static const struct RC_name RC_NamesTable[] = -{ - { rne, STRING_COMMA_LEN ("rn-sae") }, - { rd, STRING_COMMA_LEN ("rd-sae") }, - { ru, STRING_COMMA_LEN ("ru-sae") }, - { rz, STRING_COMMA_LEN ("rz-sae") }, - { saeonly, STRING_COMMA_LEN ("sae") }, -}; - -/* List of chars besides those in app.c:symbol_chars that can start an - operand. Used to prevent the scrubber eating vital white-space. */ -const char extra_symbol_chars[] = "*%-([{" -#ifdef LEX_AT - "@" -#endif -#ifdef LEX_QM - "?" -#endif - ; - -#if (defined (TE_I386AIX) \ - || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) \ - && !defined (TE_GNU) \ - && !defined (TE_LINUX) \ - && !defined (TE_NACL) \ - && !defined (TE_NETWARE) \ - && !defined (TE_FreeBSD) \ - && !defined (TE_DragonFly) \ - && !defined (TE_NetBSD))) -/* This array holds the chars that always start a comment. If the - pre-processor is disabled, these aren't very useful. The option - --divide will remove '/' from this list. */ -const char *i386_comment_chars = "#/"; -#define SVR4_COMMENT_CHARS 1 -#define PREFIX_SEPARATOR '\\' - -#else -const char *i386_comment_chars = "#"; -#define PREFIX_SEPARATOR '/' -#endif - -/* This array holds the chars that only start a comment at the beginning of - a line. If the line seems to have the form '# 123 filename' - .line and .file directives will appear in the pre-processed output. - Note that input_file.c hand checks for '#' at the beginning of the - first line of the input file. This is because the compiler outputs - #NO_APP at the beginning of its output. - Also note that comments started like this one will always work if - '/' isn't otherwise defined. */ -const char line_comment_chars[] = "#/"; - -const char line_separator_chars[] = ";"; - -/* Chars that can be used to separate mant from exp in floating point - nums. */ -const char EXP_CHARS[] = "eE"; - -/* Chars that mean this number is a floating point constant - As in 0f12.456 - or 0d1.2345e12. */ -const char FLT_CHARS[] = "fFdDxX"; - -/* Tables for lexical analysis. */ -static char mnemonic_chars[256]; -static char register_chars[256]; -static char operand_chars[256]; -static char identifier_chars[256]; -static char digit_chars[256]; - -/* Lexical macros. */ -#define is_mnemonic_char(x) (mnemonic_chars[(unsigned char) x]) -#define is_operand_char(x) (operand_chars[(unsigned char) x]) -#define is_register_char(x) (register_chars[(unsigned char) x]) -#define is_space_char(x) ((x) == ' ') -#define is_identifier_char(x) (identifier_chars[(unsigned char) x]) -#define is_digit_char(x) (digit_chars[(unsigned char) x]) - -/* All non-digit non-letter characters that may occur in an operand. */ -static char operand_special_chars[] = "%$-+(,)*._~/<>|&^!:[@]"; - -/* md_assemble() always leaves the strings it's passed unaltered. To - effect this we maintain a stack of saved characters that we've smashed - with '\0's (indicating end of strings for various sub-fields of the - assembler instruction). */ -static char save_stack[32]; -static char *save_stack_p; -#define END_STRING_AND_SAVE(s) \ - do { *save_stack_p++ = *(s); *(s) = '\0'; } while (0) -#define RESTORE_END_STRING(s) \ - do { *(s) = *--save_stack_p; } while (0) - -/* The instruction we're assembling. */ -static i386_insn i; - -/* Possible templates for current insn. */ -static const templates *current_templates; - -/* Per instruction expressionS buffers: max displacements & immediates. */ -static expressionS disp_expressions[MAX_MEMORY_OPERANDS]; -static expressionS im_expressions[MAX_IMMEDIATE_OPERANDS]; - -/* Current operand we are working on. */ -static int this_operand = -1; - -/* We support four different modes. FLAG_CODE variable is used to distinguish - these. */ - -enum flag_code { - CODE_32BIT, - CODE_16BIT, - CODE_64BIT }; - -static enum flag_code flag_code; -static unsigned int object_64bit; -static unsigned int disallow_64bit_reloc; -static int use_rela_relocations = 0; - -#if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \ - || defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) \ - || defined (TE_PE) || defined (TE_PEP) || defined (OBJ_MACH_O)) - -/* The ELF ABI to use. */ -enum x86_elf_abi -{ - I386_ABI, - X86_64_ABI, - X86_64_X32_ABI -}; - -static enum x86_elf_abi x86_elf_abi = I386_ABI; -#endif - -/* 1 for intel syntax, - 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 the assembler should add BND prefix for all control-tranferring - instructions supporting it, even if this prefix wasn't specified - explicitly. */ -static int add_bnd_prefix = 0; - -/* 1 if pseudo index register, eiz/riz, is allowed . */ -static int allow_index_reg = 0; - -static enum check_kind - { - check_none = 0, - check_warning, - check_error - } -sse_check, operand_check = check_warning; - -/* Register prefix used for error message. */ -static const char *register_prefix = "%"; - -/* Used in 16 bit gcc mode to add an l suffix to call, ret, enter, - leave, push, and pop instructions so that gcc has the same stack - frame as in 32 bit mode. */ -static char stackop_size = '\0'; - -/* Non-zero to optimize code alignment. */ -int optimize_align_code = 1; - -/* Non-zero to quieten some warnings. */ -static int quiet_warnings = 0; - -/* CPU name. */ -static const char *cpu_arch_name = NULL; -static char *cpu_sub_arch_name = NULL; - -/* CPU feature flags. */ -static i386_cpu_flags cpu_arch_flags = CPU_UNKNOWN_FLAGS; - -/* If we have selected a cpu we are generating instructions for. */ -static int cpu_arch_tune_set = 0; - -/* Cpu we are generating instructions for. */ -enum processor_type cpu_arch_tune = PROCESSOR_UNKNOWN; - -/* CPU feature flags of cpu we are generating instructions for. */ -static i386_cpu_flags cpu_arch_tune_flags; - -/* CPU instruction set architecture used. */ -enum processor_type cpu_arch_isa = PROCESSOR_UNKNOWN; - -/* CPU feature flags of instruction set architecture used. */ -i386_cpu_flags cpu_arch_isa_flags; - -/* If set, conditional jumps are not automatically promoted to handle - larger than a byte offset. */ -static unsigned int no_cond_jump_promotion = 0; - -/* Encode SSE instructions with VEX prefix. */ -static unsigned int sse2avx; - -/* Encode scalar AVX instructions with specific vector length. */ -static enum - { - vex128 = 0, - vex256 - } avxscalar; - -/* Encode scalar EVEX LIG instructions with specific vector length. */ -static enum - { - evexl128 = 0, - evexl256, - evexl512 - } evexlig; - -/* Encode EVEX WIG instructions with specific evex.w. */ -static enum - { - evexw0 = 0, - evexw1 - } evexwig; - -/* Pre-defined "_GLOBAL_OFFSET_TABLE_". */ -static symbolS *GOT_symbol; - -/* The dwarf2 return column, adjusted for 32 or 64 bit. */ -unsigned int x86_dwarf2_return_column; - -/* The dwarf2 data alignment, adjusted for 32 or 64 bit. */ -int x86_cie_data_alignment; - -/* Interface to relax_segment. - There are 3 major relax states for 386 jump insns because the - different types of jumps add different sizes to frags when we're - figuring out what sort of jump to choose to reach a given label. */ - -/* Types. */ -#define UNCOND_JUMP 0 -#define COND_JUMP 1 -#define COND_JUMP86 2 - -/* Sizes. */ -#define CODE16 1 -#define SMALL 0 -#define SMALL16 (SMALL | CODE16) -#define BIG 2 -#define BIG16 (BIG | CODE16) - -#ifndef INLINE -#ifdef __GNUC__ -#define INLINE __inline__ -#else -#define INLINE -#endif -#endif - -#define ENCODE_RELAX_STATE(type, size) \ - ((relax_substateT) (((type) << 2) | (size))) -#define TYPE_FROM_RELAX_STATE(s) \ - ((s) >> 2) -#define DISP_SIZE_FROM_RELAX_STATE(s) \ - ((((s) & 3) == BIG ? 4 : (((s) & 3) == BIG16 ? 2 : 1))) - -/* This table is used by relax_frag to promote short jumps to long - ones where necessary. SMALL (short) jumps may be promoted to BIG - (32 bit long) ones, and SMALL16 jumps to BIG16 (16 bit long). We - don't allow a short jump in a 32 bit code segment to be promoted to - a 16 bit offset jump because it's slower (requires data size - prefix), and doesn't work, unless the destination is in the bottom - 64k of the code segment (The top 16 bits of eip are zeroed). */ - -const relax_typeS md_relax_table[] = -{ - /* The fields are: - 1) most positive reach of this state, - 2) most negative reach of this state, - 3) how many bytes this mode will have in the variable part of the frag - 4) which index into the table to try if we can't fit into this one. */ - - /* UNCOND_JUMP states. */ - {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG)}, - {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16)}, - /* dword jmp adds 4 bytes to frag: - 0 extra opcode bytes, 4 displacement bytes. */ - {0, 0, 4, 0}, - /* word jmp adds 2 byte2 to frag: - 0 extra opcode bytes, 2 displacement bytes. */ - {0, 0, 2, 0}, - - /* COND_JUMP states. */ - {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP, BIG)}, - {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP, BIG16)}, - /* dword conditionals adds 5 bytes to frag: - 1 extra opcode byte, 4 displacement bytes. */ - {0, 0, 5, 0}, - /* word conditionals add 3 bytes to frag: - 1 extra opcode byte, 2 displacement bytes. */ - {0, 0, 3, 0}, - - /* COND_JUMP86 states. */ - {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP86, BIG)}, - {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP86, BIG16)}, - /* dword conditionals adds 5 bytes to frag: - 1 extra opcode byte, 4 displacement bytes. */ - {0, 0, 5, 0}, - /* word conditionals add 4 bytes to frag: - 1 displacement byte and a 3 byte long branch insn. */ - {0, 0, 4, 0} -}; - -static const arch_entry cpu_arch[] = -{ - /* Do not replace the first two entries - i386_target_format() - relies on them being there in this order. */ - { STRING_COMMA_LEN ("generic32"), PROCESSOR_GENERIC32, - CPU_GENERIC32_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("generic64"), PROCESSOR_GENERIC64, - CPU_GENERIC64_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("i8086"), PROCESSOR_UNKNOWN, - CPU_NONE_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("i186"), PROCESSOR_UNKNOWN, - CPU_I186_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("i286"), PROCESSOR_UNKNOWN, - CPU_I286_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("i386"), PROCESSOR_I386, - CPU_I386_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("i486"), PROCESSOR_I486, - CPU_I486_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("i586"), PROCESSOR_PENTIUM, - CPU_I586_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("i686"), PROCESSOR_PENTIUMPRO, - CPU_I686_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("pentium"), PROCESSOR_PENTIUM, - CPU_I586_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("pentiumpro"), PROCESSOR_PENTIUMPRO, - CPU_PENTIUMPRO_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("pentiumii"), PROCESSOR_PENTIUMPRO, - CPU_P2_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("pentiumiii"),PROCESSOR_PENTIUMPRO, - CPU_P3_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("pentium4"), PROCESSOR_PENTIUM4, - CPU_P4_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("prescott"), PROCESSOR_NOCONA, - CPU_CORE_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("nocona"), PROCESSOR_NOCONA, - CPU_NOCONA_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("yonah"), PROCESSOR_CORE, - CPU_CORE_FLAGS, 1, 0 }, - { STRING_COMMA_LEN ("core"), PROCESSOR_CORE, - CPU_CORE_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("merom"), PROCESSOR_CORE2, - CPU_CORE2_FLAGS, 1, 0 }, - { STRING_COMMA_LEN ("core2"), PROCESSOR_CORE2, - CPU_CORE2_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("corei7"), PROCESSOR_COREI7, - CPU_COREI7_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("l1om"), PROCESSOR_L1OM, - CPU_L1OM_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("k1om"), PROCESSOR_K1OM, - CPU_K1OM_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("k6"), PROCESSOR_K6, - CPU_K6_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("k6_2"), PROCESSOR_K6, - CPU_K6_2_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("athlon"), PROCESSOR_ATHLON, - CPU_ATHLON_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("sledgehammer"), PROCESSOR_K8, - CPU_K8_FLAGS, 1, 0 }, - { STRING_COMMA_LEN ("opteron"), PROCESSOR_K8, - CPU_K8_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("k8"), PROCESSOR_K8, - CPU_K8_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("amdfam10"), PROCESSOR_AMDFAM10, - CPU_AMDFAM10_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("bdver1"), PROCESSOR_BD, - CPU_BDVER1_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("bdver2"), PROCESSOR_BD, - CPU_BDVER2_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("bdver3"), PROCESSOR_BD, - CPU_BDVER3_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("btver1"), PROCESSOR_BT, - CPU_BTVER1_FLAGS, 0, 0 }, - { STRING_COMMA_LEN ("btver2"), PROCESSOR_BT, - CPU_BTVER2_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".8087"), PROCESSOR_UNKNOWN, - CPU_8087_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".287"), PROCESSOR_UNKNOWN, - CPU_287_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".387"), PROCESSOR_UNKNOWN, - CPU_387_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".no87"), PROCESSOR_UNKNOWN, - CPU_ANY87_FLAGS, 0, 1 }, - { STRING_COMMA_LEN (".mmx"), PROCESSOR_UNKNOWN, - CPU_MMX_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".nommx"), PROCESSOR_UNKNOWN, - CPU_3DNOWA_FLAGS, 0, 1 }, - { STRING_COMMA_LEN (".sse"), PROCESSOR_UNKNOWN, - CPU_SSE_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".sse2"), PROCESSOR_UNKNOWN, - CPU_SSE2_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".sse3"), PROCESSOR_UNKNOWN, - CPU_SSE3_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".ssse3"), PROCESSOR_UNKNOWN, - CPU_SSSE3_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".sse4.1"), PROCESSOR_UNKNOWN, - CPU_SSE4_1_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".sse4.2"), PROCESSOR_UNKNOWN, - CPU_SSE4_2_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".sse4"), PROCESSOR_UNKNOWN, - CPU_SSE4_2_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".nosse"), PROCESSOR_UNKNOWN, - CPU_ANY_SSE_FLAGS, 0, 1 }, - { STRING_COMMA_LEN (".avx"), PROCESSOR_UNKNOWN, - CPU_AVX_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".avx2"), PROCESSOR_UNKNOWN, - CPU_AVX2_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".avx512f"), PROCESSOR_UNKNOWN, - CPU_AVX512F_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".avx512cd"), PROCESSOR_UNKNOWN, - CPU_AVX512CD_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".avx512er"), PROCESSOR_UNKNOWN, - CPU_AVX512ER_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".avx512pf"), PROCESSOR_UNKNOWN, - CPU_AVX512PF_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".noavx"), PROCESSOR_UNKNOWN, - CPU_ANY_AVX_FLAGS, 0, 1 }, - { STRING_COMMA_LEN (".vmx"), PROCESSOR_UNKNOWN, - CPU_VMX_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".vmfunc"), PROCESSOR_UNKNOWN, - CPU_VMFUNC_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".smx"), PROCESSOR_UNKNOWN, - CPU_SMX_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".xsave"), PROCESSOR_UNKNOWN, - CPU_XSAVE_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".xsaveopt"), PROCESSOR_UNKNOWN, - CPU_XSAVEOPT_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".aes"), PROCESSOR_UNKNOWN, - CPU_AES_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".pclmul"), PROCESSOR_UNKNOWN, - CPU_PCLMUL_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".clmul"), PROCESSOR_UNKNOWN, - CPU_PCLMUL_FLAGS, 1, 0 }, - { STRING_COMMA_LEN (".fsgsbase"), PROCESSOR_UNKNOWN, - CPU_FSGSBASE_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".rdrnd"), PROCESSOR_UNKNOWN, - CPU_RDRND_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".f16c"), PROCESSOR_UNKNOWN, - CPU_F16C_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".bmi2"), PROCESSOR_UNKNOWN, - CPU_BMI2_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".fma"), PROCESSOR_UNKNOWN, - CPU_FMA_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".fma4"), PROCESSOR_UNKNOWN, - CPU_FMA4_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".xop"), PROCESSOR_UNKNOWN, - CPU_XOP_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".lwp"), PROCESSOR_UNKNOWN, - CPU_LWP_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".movbe"), PROCESSOR_UNKNOWN, - CPU_MOVBE_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".cx16"), PROCESSOR_UNKNOWN, - CPU_CX16_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".ept"), PROCESSOR_UNKNOWN, - CPU_EPT_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".lzcnt"), PROCESSOR_UNKNOWN, - CPU_LZCNT_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".hle"), PROCESSOR_UNKNOWN, - CPU_HLE_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".rtm"), PROCESSOR_UNKNOWN, - CPU_RTM_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".invpcid"), PROCESSOR_UNKNOWN, - CPU_INVPCID_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".clflush"), PROCESSOR_UNKNOWN, - CPU_CLFLUSH_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".nop"), PROCESSOR_UNKNOWN, - CPU_NOP_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".syscall"), PROCESSOR_UNKNOWN, - CPU_SYSCALL_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".rdtscp"), PROCESSOR_UNKNOWN, - CPU_RDTSCP_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".3dnow"), PROCESSOR_UNKNOWN, - CPU_3DNOW_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".3dnowa"), PROCESSOR_UNKNOWN, - CPU_3DNOWA_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".padlock"), PROCESSOR_UNKNOWN, - CPU_PADLOCK_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".pacifica"), PROCESSOR_UNKNOWN, - CPU_SVME_FLAGS, 1, 0 }, - { STRING_COMMA_LEN (".svme"), PROCESSOR_UNKNOWN, - CPU_SVME_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".sse4a"), PROCESSOR_UNKNOWN, - CPU_SSE4A_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".abm"), PROCESSOR_UNKNOWN, - CPU_ABM_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".bmi"), PROCESSOR_UNKNOWN, - CPU_BMI_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".tbm"), PROCESSOR_UNKNOWN, - CPU_TBM_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".adx"), PROCESSOR_UNKNOWN, - CPU_ADX_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".rdseed"), PROCESSOR_UNKNOWN, - CPU_RDSEED_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".prfchw"), PROCESSOR_UNKNOWN, - CPU_PRFCHW_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".smap"), PROCESSOR_UNKNOWN, - CPU_SMAP_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".mpx"), PROCESSOR_UNKNOWN, - CPU_MPX_FLAGS, 0, 0 }, - { STRING_COMMA_LEN (".sha"), PROCESSOR_UNKNOWN, - CPU_SHA_FLAGS, 0, 0 }, -}; - -#ifdef I386COFF -/* Like s_lcomm_internal in gas/read.c but the alignment string - is allowed to be optional. */ - -static symbolS * -pe_lcomm_internal (int needs_align, symbolS *symbolP, addressT size) -{ - addressT align = 0; - - SKIP_WHITESPACE (); - - if (needs_align - && *input_line_pointer == ',') - { - align = parse_align (needs_align - 1); - - if (align == (addressT) -1) - return NULL; - } - else - { - if (size >= 8) - align = 3; - else if (size >= 4) - align = 2; - else if (size >= 2) - align = 1; - else - align = 0; - } - - bss_alloc (symbolP, size, align); - return symbolP; -} - -static void -pe_lcomm (int needs_align) -{ - s_comm_internal (needs_align * 2, pe_lcomm_internal); -} -#endif - -const pseudo_typeS md_pseudo_table[] = -{ -#if !defined(OBJ_AOUT) && !defined(USE_ALIGN_PTWO) - {"align", s_align_bytes, 0}, -#else - {"align", s_align_ptwo, 0}, -#endif - {"arch", set_cpu_arch, 0}, -#ifndef I386COFF - {"bss", s_bss, 0}, -#else - {"lcomm", pe_lcomm, 1}, -#endif - {"ffloat", float_cons, 'f'}, - {"dfloat", float_cons, 'd'}, - {"tfloat", float_cons, 'x'}, - {"value", cons, 2}, - {"slong", signed_cons, 4}, - {"noopt", s_ignore, 0}, - {"optim", s_ignore, 0}, - {"code16gcc", set_16bit_gcc_code_flag, CODE_16BIT}, - {"code16", set_code_flag, CODE_16BIT}, - {"code32", set_code_flag, CODE_32BIT}, - {"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}, - {"sse_check", set_check, 0}, - {"operand_check", set_check, 1}, -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - {"largecomm", handle_large_common, 0}, -#else - {"file", (void (*) (int)) dwarf2_directive_file, 0}, - {"loc", dwarf2_directive_loc, 0}, - {"loc_mark_labels", dwarf2_directive_loc_mark_labels, 0}, -#endif -#ifdef TE_PE - {"secrel32", pe_directive_secrel, 0}, -#endif - {0, 0, 0} -}; - -/* For interface with expression (). */ -extern char *input_line_pointer; - -/* Hash table for instruction mnemonic lookup. */ -static struct hash_control *op_hash; - -/* Hash table for register lookup. */ -static struct hash_control *reg_hash; - -void -i386_align_code (fragS *fragP, int count) -{ - /* Various efficient no-op patterns for aligning code labels. - Note: Don't try to assemble the instructions in the comments. - 0L and 0w are not legal. */ - static const char f32_1[] = - {0x90}; /* nop */ - static const char f32_2[] = - {0x66,0x90}; /* xchg %ax,%ax */ - static const char f32_3[] = - {0x8d,0x76,0x00}; /* leal 0(%esi),%esi */ - static const char f32_4[] = - {0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ - static const char f32_5[] = - {0x90, /* nop */ - 0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ - static const char f32_6[] = - {0x8d,0xb6,0x00,0x00,0x00,0x00}; /* leal 0L(%esi),%esi */ - static const char f32_7[] = - {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ - static const char f32_8[] = - {0x90, /* nop */ - 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ - static const char f32_9[] = - {0x89,0xf6, /* movl %esi,%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const char f32_10[] = - {0x8d,0x76,0x00, /* leal 0(%esi),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const char f32_11[] = - {0x8d,0x74,0x26,0x00, /* leal 0(%esi,1),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const char f32_12[] = - {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ - 0x8d,0xbf,0x00,0x00,0x00,0x00}; /* leal 0L(%edi),%edi */ - static const char f32_13[] = - {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const char f32_14[] = - {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00, /* leal 0L(%esi,1),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const char f16_3[] = - {0x8d,0x74,0x00}; /* lea 0(%esi),%esi */ - static const char f16_4[] = - {0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */ - static const char f16_5[] = - {0x90, /* nop */ - 0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */ - static const char f16_6[] = - {0x89,0xf6, /* mov %si,%si */ - 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ - static const char f16_7[] = - {0x8d,0x74,0x00, /* lea 0(%si),%si */ - 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ - static const char f16_8[] = - {0x8d,0xb4,0x00,0x00, /* lea 0w(%si),%si */ - 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ - static const char jump_31[] = - {0xeb,0x1d,0x90,0x90,0x90,0x90,0x90, /* jmp .+31; lotsa nops */ - 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, - 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, - 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90}; - static const char *const f32_patt[] = { - f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8, - f32_9, f32_10, f32_11, f32_12, f32_13, f32_14 - }; - static const char *const f16_patt[] = { - f32_1, f32_2, f16_3, f16_4, f16_5, f16_6, f16_7, f16_8 - }; - /* nopl (%[re]ax) */ - static const char alt_3[] = - {0x0f,0x1f,0x00}; - /* nopl 0(%[re]ax) */ - static const char alt_4[] = - {0x0f,0x1f,0x40,0x00}; - /* nopl 0(%[re]ax,%[re]ax,1) */ - static const char alt_5[] = - {0x0f,0x1f,0x44,0x00,0x00}; - /* nopw 0(%[re]ax,%[re]ax,1) */ - static const char alt_6[] = - {0x66,0x0f,0x1f,0x44,0x00,0x00}; - /* nopl 0L(%[re]ax) */ - static const char alt_7[] = - {0x0f,0x1f,0x80,0x00,0x00,0x00,0x00}; - /* nopl 0L(%[re]ax,%[re]ax,1) */ - static const char alt_8[] = - {0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; - /* nopw 0L(%[re]ax,%[re]ax,1) */ - static const char alt_9[] = - {0x66,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; - /* nopw %cs:0L(%[re]ax,%[re]ax,1) */ - static const char alt_10[] = - {0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; - /* data16 - nopw %cs:0L(%[re]ax,%[re]ax,1) */ - static const char alt_long_11[] = - {0x66, - 0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; - /* data16 - data16 - nopw %cs:0L(%[re]ax,%[re]ax,1) */ - static const char alt_long_12[] = - {0x66, - 0x66, - 0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; - /* data16 - data16 - data16 - nopw %cs:0L(%[re]ax,%[re]ax,1) */ - static const char alt_long_13[] = - {0x66, - 0x66, - 0x66, - 0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; - /* data16 - data16 - data16 - data16 - nopw %cs:0L(%[re]ax,%[re]ax,1) */ - static const char alt_long_14[] = - {0x66, - 0x66, - 0x66, - 0x66, - 0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; - /* data16 - data16 - data16 - data16 - data16 - nopw %cs:0L(%[re]ax,%[re]ax,1) */ - static const char alt_long_15[] = - {0x66, - 0x66, - 0x66, - 0x66, - 0x66, - 0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; - /* nopl 0(%[re]ax,%[re]ax,1) - nopw 0(%[re]ax,%[re]ax,1) */ - static const char alt_short_11[] = - {0x0f,0x1f,0x44,0x00,0x00, - 0x66,0x0f,0x1f,0x44,0x00,0x00}; - /* nopw 0(%[re]ax,%[re]ax,1) - nopw 0(%[re]ax,%[re]ax,1) */ - static const char alt_short_12[] = - {0x66,0x0f,0x1f,0x44,0x00,0x00, - 0x66,0x0f,0x1f,0x44,0x00,0x00}; - /* nopw 0(%[re]ax,%[re]ax,1) - nopl 0L(%[re]ax) */ - static const char alt_short_13[] = - {0x66,0x0f,0x1f,0x44,0x00,0x00, - 0x0f,0x1f,0x80,0x00,0x00,0x00,0x00}; - /* nopl 0L(%[re]ax) - nopl 0L(%[re]ax) */ - static const char alt_short_14[] = - {0x0f,0x1f,0x80,0x00,0x00,0x00,0x00, - 0x0f,0x1f,0x80,0x00,0x00,0x00,0x00}; - /* nopl 0L(%[re]ax) - nopl 0L(%[re]ax,%[re]ax,1) */ - static const char alt_short_15[] = - {0x0f,0x1f,0x80,0x00,0x00,0x00,0x00, - 0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; - static const char *const alt_short_patt[] = { - f32_1, f32_2, alt_3, alt_4, alt_5, alt_6, alt_7, alt_8, - alt_9, alt_10, alt_short_11, alt_short_12, alt_short_13, - alt_short_14, alt_short_15 - }; - static const char *const alt_long_patt[] = { - f32_1, f32_2, alt_3, alt_4, alt_5, alt_6, alt_7, alt_8, - alt_9, alt_10, alt_long_11, alt_long_12, alt_long_13, - alt_long_14, alt_long_15 - }; - - /* Only align for at least a positive non-zero boundary. */ - if (count <= 0 || count > MAX_MEM_FOR_RS_ALIGN_CODE) - return; - - /* We need to decide which NOP sequence to use for 32bit and - 64bit. When -mtune= is used: - - 1. For PROCESSOR_I386, PROCESSOR_I486, PROCESSOR_PENTIUM and - PROCESSOR_GENERIC32, f32_patt will be used. - 2. For PROCESSOR_PENTIUMPRO, PROCESSOR_PENTIUM4, PROCESSOR_NOCONA, - PROCESSOR_CORE, PROCESSOR_CORE2, PROCESSOR_COREI7, and - PROCESSOR_GENERIC64, alt_long_patt will be used. - 3. For PROCESSOR_ATHLON, PROCESSOR_K6, PROCESSOR_K8 and - PROCESSOR_AMDFAM10, PROCESSOR_BD and PROCESSOR_BT, alt_short_patt - will be used. - - When -mtune= isn't used, alt_long_patt will be used if - cpu_arch_isa_flags has CpuNop. Otherwise, f32_patt will - be used. - - When -march= or .arch is used, we can't use anything beyond - cpu_arch_isa_flags. */ - - if (flag_code == CODE_16BIT) - { - if (count > 8) - { - memcpy (fragP->fr_literal + fragP->fr_fix, - jump_31, count); - /* Adjust jump offset. */ - fragP->fr_literal[fragP->fr_fix + 1] = count - 2; - } - else - memcpy (fragP->fr_literal + fragP->fr_fix, - f16_patt[count - 1], count); - } - else - { - const char *const *patt = NULL; - - if (fragP->tc_frag_data.isa == PROCESSOR_UNKNOWN) - { - /* PROCESSOR_UNKNOWN means that all ISAs may be used. */ - switch (cpu_arch_tune) - { - case PROCESSOR_UNKNOWN: - /* We use cpu_arch_isa_flags to check if we SHOULD - optimize with nops. */ - if (fragP->tc_frag_data.isa_flags.bitfield.cpunop) - patt = alt_long_patt; - else - patt = f32_patt; - break; - case PROCESSOR_PENTIUM4: - case PROCESSOR_NOCONA: - case PROCESSOR_CORE: - case PROCESSOR_CORE2: - case PROCESSOR_COREI7: - case PROCESSOR_L1OM: - case PROCESSOR_K1OM: - case PROCESSOR_GENERIC64: - patt = alt_long_patt; - break; - case PROCESSOR_K6: - case PROCESSOR_ATHLON: - case PROCESSOR_K8: - case PROCESSOR_AMDFAM10: - case PROCESSOR_BD: - case PROCESSOR_BT: - patt = alt_short_patt; - break; - case PROCESSOR_I386: - case PROCESSOR_I486: - case PROCESSOR_PENTIUM: - case PROCESSOR_PENTIUMPRO: - case PROCESSOR_GENERIC32: - patt = f32_patt; - break; - } - } - else - { - switch (fragP->tc_frag_data.tune) - { - case PROCESSOR_UNKNOWN: - /* When cpu_arch_isa is set, cpu_arch_tune shouldn't be - PROCESSOR_UNKNOWN. */ - abort (); - break; - - case PROCESSOR_I386: - case PROCESSOR_I486: - case PROCESSOR_PENTIUM: - case PROCESSOR_K6: - case PROCESSOR_ATHLON: - case PROCESSOR_K8: - case PROCESSOR_AMDFAM10: - case PROCESSOR_BD: - case PROCESSOR_BT: - case PROCESSOR_GENERIC32: - /* We use cpu_arch_isa_flags to check if we CAN optimize - with nops. */ - if (fragP->tc_frag_data.isa_flags.bitfield.cpunop) - patt = alt_short_patt; - else - patt = f32_patt; - break; - case PROCESSOR_PENTIUMPRO: - case PROCESSOR_PENTIUM4: - case PROCESSOR_NOCONA: - case PROCESSOR_CORE: - case PROCESSOR_CORE2: - case PROCESSOR_COREI7: - case PROCESSOR_L1OM: - case PROCESSOR_K1OM: - if (fragP->tc_frag_data.isa_flags.bitfield.cpunop) - patt = alt_long_patt; - else - patt = f32_patt; - break; - case PROCESSOR_GENERIC64: - patt = alt_long_patt; - break; - } - } - - if (patt == f32_patt) - { - /* If the padding is less than 15 bytes, we use the normal - ones. Otherwise, we use a jump instruction and adjust - its offset. */ - int limit; - - /* For 64bit, the limit is 3 bytes. */ - if (flag_code == CODE_64BIT - && fragP->tc_frag_data.isa_flags.bitfield.cpulm) - limit = 3; - else - limit = 15; - if (count < limit) - memcpy (fragP->fr_literal + fragP->fr_fix, - patt[count - 1], count); - else - { - memcpy (fragP->fr_literal + fragP->fr_fix, - jump_31, count); - /* Adjust jump offset. */ - fragP->fr_literal[fragP->fr_fix + 1] = count - 2; - } - } - else - { - /* Maximum length of an instruction is 15 byte. If the - padding is greater than 15 bytes and we don't use jump, - we have to break it into smaller pieces. */ - int padding = count; - while (padding > 15) - { - padding -= 15; - memcpy (fragP->fr_literal + fragP->fr_fix + padding, - patt [14], 15); - } - - if (padding) - memcpy (fragP->fr_literal + fragP->fr_fix, - patt [padding - 1], padding); - } - } - fragP->fr_var = count; -} - -static INLINE int -operand_type_all_zero (const union i386_operand_type *x) -{ - 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 void -operand_type_set (union i386_operand_type *x, unsigned int v) -{ - switch (ARRAY_SIZE(x->array)) - { - case 3: - x->array[2] = v; - case 2: - x->array[1] = v; - case 1: - x->array[0] = v; - break; - default: - abort (); - } -} - -static INLINE int -operand_type_equal (const union i386_operand_type *x, - const union i386_operand_type *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 (); - } -} - -static INLINE int -cpu_flags_all_zero (const union i386_cpu_flags *x) -{ - 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 void -cpu_flags_set (union i386_cpu_flags *x, unsigned int v) -{ - switch (ARRAY_SIZE(x->array)) - { - case 3: - x->array[2] = v; - case 2: - x->array[1] = v; - case 1: - x->array[0] = v; - break; - default: - abort (); - } -} - -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 (); - } -} - -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 -cpu_flags_and (i386_cpu_flags x, i386_cpu_flags y) -{ - switch (ARRAY_SIZE (x.array)) - { - case 3: - x.array [2] &= y.array [2]; - case 2: - x.array [1] &= y.array [1]; - case 1: - x.array [0] &= y.array [0]; - break; - default: - abort (); - } - return x; -} - -static INLINE i386_cpu_flags -cpu_flags_or (i386_cpu_flags x, i386_cpu_flags y) -{ - switch (ARRAY_SIZE (x.array)) - { - case 3: - x.array [2] |= y.array [2]; - case 2: - x.array [1] |= y.array [1]; - case 1: - x.array [0] |= y.array [0]; - break; - default: - abort (); - } - return x; -} - -static INLINE i386_cpu_flags -cpu_flags_and_not (i386_cpu_flags x, i386_cpu_flags y) -{ - switch (ARRAY_SIZE (x.array)) - { - case 3: - x.array [2] &= ~y.array [2]; - case 2: - x.array [1] &= ~y.array [1]; - case 1: - x.array [0] &= ~y.array [0]; - break; - default: - abort (); - } - return x; -} - -#define CPU_FLAGS_ARCH_MATCH 0x1 -#define CPU_FLAGS_64BIT_MATCH 0x2 -#define CPU_FLAGS_AES_MATCH 0x4 -#define CPU_FLAGS_PCLMUL_MATCH 0x8 -#define CPU_FLAGS_AVX_MATCH 0x10 - -#define CPU_FLAGS_32BIT_MATCH \ - (CPU_FLAGS_ARCH_MATCH | CPU_FLAGS_AES_MATCH \ - | CPU_FLAGS_PCLMUL_MATCH | CPU_FLAGS_AVX_MATCH) -#define CPU_FLAGS_PERFECT_MATCH \ - (CPU_FLAGS_32BIT_MATCH | CPU_FLAGS_64BIT_MATCH) - -/* Return CPU flags match bits. */ - -static int -cpu_flags_match (const insn_template *t) -{ - i386_cpu_flags x = t->cpu_flags; - int match = cpu_flags_check_cpu64 (x) ? CPU_FLAGS_64BIT_MATCH : 0; - - x.bitfield.cpu64 = 0; - x.bitfield.cpuno64 = 0; - - if (cpu_flags_all_zero (&x)) - { - /* This instruction is available on all archs. */ - match |= CPU_FLAGS_32BIT_MATCH; - } - else - { - /* This instruction is available only on some archs. */ - i386_cpu_flags cpu = cpu_arch_flags; - - cpu.bitfield.cpu64 = 0; - cpu.bitfield.cpuno64 = 0; - cpu = cpu_flags_and (x, cpu); - if (!cpu_flags_all_zero (&cpu)) - { - if (x.bitfield.cpuavx) - { - /* We only need to check AES/PCLMUL/SSE2AVX with AVX. */ - if (cpu.bitfield.cpuavx) - { - /* Check SSE2AVX. */ - if (!t->opcode_modifier.sse2avx|| sse2avx) - { - match |= (CPU_FLAGS_ARCH_MATCH - | CPU_FLAGS_AVX_MATCH); - /* Check AES. */ - if (!x.bitfield.cpuaes || cpu.bitfield.cpuaes) - match |= CPU_FLAGS_AES_MATCH; - /* Check PCLMUL. */ - if (!x.bitfield.cpupclmul - || cpu.bitfield.cpupclmul) - match |= CPU_FLAGS_PCLMUL_MATCH; - } - } - else - match |= CPU_FLAGS_ARCH_MATCH; - } - else - match |= CPU_FLAGS_32BIT_MATCH; - } - } - return match; -} - -static INLINE i386_operand_type -operand_type_and (i386_operand_type x, i386_operand_type y) -{ - switch (ARRAY_SIZE (x.array)) - { - case 3: - x.array [2] &= y.array [2]; - case 2: - x.array [1] &= y.array [1]; - case 1: - x.array [0] &= y.array [0]; - break; - default: - abort (); - } - return x; -} - -static INLINE i386_operand_type -operand_type_or (i386_operand_type x, i386_operand_type y) -{ - switch (ARRAY_SIZE (x.array)) - { - case 3: - x.array [2] |= y.array [2]; - case 2: - x.array [1] |= y.array [1]; - case 1: - x.array [0] |= y.array [0]; - break; - default: - abort (); - } - return x; -} - -static INLINE i386_operand_type -operand_type_xor (i386_operand_type x, i386_operand_type y) -{ - switch (ARRAY_SIZE (x.array)) - { - case 3: - x.array [2] ^= y.array [2]; - case 2: - x.array [1] ^= y.array [1]; - case 1: - x.array [0] ^= y.array [0]; - break; - default: - abort (); - } - return x; -} - -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; -static const i386_operand_type disp32 = OPERAND_TYPE_DISP32; -static const i386_operand_type disp32s = OPERAND_TYPE_DISP32S; -static const i386_operand_type disp16_32 = OPERAND_TYPE_DISP16_32; -static const i386_operand_type anydisp - = OPERAND_TYPE_ANYDISP; -static const i386_operand_type regxmm = OPERAND_TYPE_REGXMM; -static const i386_operand_type regymm = OPERAND_TYPE_REGYMM; -static const i386_operand_type regzmm = OPERAND_TYPE_REGZMM; -static const i386_operand_type regmask = OPERAND_TYPE_REGMASK; -static const i386_operand_type imm8 = OPERAND_TYPE_IMM8; -static const i386_operand_type imm8s = OPERAND_TYPE_IMM8S; -static const i386_operand_type imm16 = OPERAND_TYPE_IMM16; -static const i386_operand_type imm32 = OPERAND_TYPE_IMM32; -static const i386_operand_type imm32s = OPERAND_TYPE_IMM32S; -static const i386_operand_type imm64 = OPERAND_TYPE_IMM64; -static const i386_operand_type imm16_32 = OPERAND_TYPE_IMM16_32; -static const i386_operand_type imm16_32s = OPERAND_TYPE_IMM16_32S; -static const i386_operand_type imm16_32_32s = OPERAND_TYPE_IMM16_32_32S; -static const i386_operand_type vec_imm4 = OPERAND_TYPE_VEC_IMM4; -static const i386_operand_type regbnd = OPERAND_TYPE_REGBND; -static const i386_operand_type vec_disp8 = OPERAND_TYPE_VEC_DISP8; - -enum operand_type -{ - reg, - imm, - disp, - anymem -}; - -static INLINE int -operand_type_check (i386_operand_type t, enum operand_type c) -{ - switch (c) - { - case reg: - return (t.bitfield.reg8 - || t.bitfield.reg16 - || t.bitfield.reg32 - || t.bitfield.reg64); - - case imm: - return (t.bitfield.imm8 - || t.bitfield.imm8s - || t.bitfield.imm16 - || t.bitfield.imm32 - || t.bitfield.imm32s - || t.bitfield.imm64); - - case disp: - return (t.bitfield.disp8 - || t.bitfield.disp16 - || t.bitfield.disp32 - || t.bitfield.disp32s - || t.bitfield.disp64); - - case anymem: - return (t.bitfield.disp8 - || t.bitfield.disp16 - || t.bitfield.disp32 - || t.bitfield.disp32s - || t.bitfield.disp64 - || t.bitfield.baseindex); - - default: - abort (); - } - - return 0; -} - -/* 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 insn_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 insn_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) - || (i.types[j].bitfield.ymmword - && !t->operand_types[j].bitfield.ymmword) - || (i.types[j].bitfield.zmmword - && !t->operand_types[j].bitfield.zmmword))); -} - -/* Return 1 if there is no size conflict on any operands for - instruction template T. */ - -static INLINE int -operand_size_match (const insn_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) - return match; - else if (!t->opcode_modifier.d && !t->opcode_modifier.floatd) - { -mismatch: - i.error = operand_size_mismatch; - return 0; - } - - /* Check reverse. */ - gas_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)) - goto mismatch; - - if (i.types[j].bitfield.mem - && !match_mem_size (t, j ? 0 : 1)) - goto mismatch; - } - - return match; -} - -static INLINE int -operand_type_match (i386_operand_type overlap, - i386_operand_type given) -{ - 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; - temp.bitfield.ymmword = 0; - temp.bitfield.zmmword = 0; - if (operand_type_all_zero (&temp)) - goto mismatch; - - if (given.bitfield.baseindex == overlap.bitfield.baseindex - && given.bitfield.jumpabsolute == overlap.bitfield.jumpabsolute) - return 1; - -mismatch: - i.error = operand_type_mismatch; - return 0; -} - -/* 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. */ - -static INLINE int -operand_type_register_match (i386_operand_type m0, - i386_operand_type g0, - i386_operand_type t0, - i386_operand_type m1, - i386_operand_type g1, - i386_operand_type t1) -{ - if (!operand_type_check (g0, reg)) - return 1; - - if (!operand_type_check (g1, reg)) - return 1; - - if (g0.bitfield.reg8 == g1.bitfield.reg8 - && g0.bitfield.reg16 == g1.bitfield.reg16 - && g0.bitfield.reg32 == g1.bitfield.reg32 - && g0.bitfield.reg64 == g1.bitfield.reg64) - return 1; - - if (m0.bitfield.acc) - { - t0.bitfield.reg8 = 1; - t0.bitfield.reg16 = 1; - t0.bitfield.reg32 = 1; - t0.bitfield.reg64 = 1; - } - - if (m1.bitfield.acc) - { - t1.bitfield.reg8 = 1; - t1.bitfield.reg16 = 1; - t1.bitfield.reg32 = 1; - t1.bitfield.reg64 = 1; - } - - if (!(t0.bitfield.reg8 & t1.bitfield.reg8) - && !(t0.bitfield.reg16 & t1.bitfield.reg16) - && !(t0.bitfield.reg32 & t1.bitfield.reg32) - && !(t0.bitfield.reg64 & t1.bitfield.reg64)) - return 1; - - i.error = register_type_mismatch; - - return 0; -} - -static INLINE unsigned int -register_number (const reg_entry *r) -{ - unsigned int nr = r->reg_num; - - if (r->reg_flags & RegRex) - nr += 8; - - return nr; -} - -static INLINE unsigned int -mode_from_disp_size (i386_operand_type t) -{ - if (t.bitfield.disp8 || t.bitfield.vec_disp8) - return 1; - else if (t.bitfield.disp16 - || t.bitfield.disp32 - || t.bitfield.disp32s) - return 2; - else - return 0; -} - -static INLINE int -fits_in_signed_byte (offsetT num) -{ - return (num >= -128) && (num <= 127); -} - -static INLINE int -fits_in_unsigned_byte (offsetT num) -{ - return (num & 0xff) == num; -} - -static INLINE int -fits_in_unsigned_word (offsetT num) -{ - return (num & 0xffff) == num; -} - -static INLINE int -fits_in_signed_word (offsetT num) -{ - return (-32768 <= num) && (num <= 32767); -} - -static INLINE int -fits_in_signed_long (offsetT num ATTRIBUTE_UNUSED) -{ -#ifndef BFD64 - return 1; -#else - return (!(((offsetT) -1 << 31) & num) - || (((offsetT) -1 << 31) & num) == ((offsetT) -1 << 31)); -#endif -} /* fits_in_signed_long() */ - -static INLINE int -fits_in_unsigned_long (offsetT num ATTRIBUTE_UNUSED) -{ -#ifndef BFD64 - return 1; -#else - return (num & (((offsetT) 2 << 31) - 1)) == num; -#endif -} /* fits_in_unsigned_long() */ - -static INLINE int -fits_in_vec_disp8 (offsetT num) -{ - int shift = i.memshift; - unsigned int mask; - - if (shift == -1) - abort (); - - mask = (1 << shift) - 1; - - /* Return 0 if NUM isn't properly aligned. */ - if ((num & mask)) - return 0; - - /* Check if NUM will fit in 8bit after shift. */ - return fits_in_signed_byte (num >> shift); -} - -static INLINE int -fits_in_imm4 (offsetT num) -{ - return (num & 0xf) == num; -} - -static i386_operand_type -smallest_imm_type (offsetT num) -{ - i386_operand_type t; - - operand_type_set (&t, 0); - t.bitfield.imm64 = 1; - - if (cpu_arch_tune != PROCESSOR_I486 && num == 1) - { - /* This code is disabled on the 486 because all the Imm1 forms - in the opcode table are slower on the i486. They're the - versions with the implicitly specified single-position - displacement, which has another syntax if you really want to - use that form. */ - t.bitfield.imm1 = 1; - t.bitfield.imm8 = 1; - t.bitfield.imm8s = 1; - t.bitfield.imm16 = 1; - t.bitfield.imm32 = 1; - t.bitfield.imm32s = 1; - } - else if (fits_in_signed_byte (num)) - { - t.bitfield.imm8 = 1; - t.bitfield.imm8s = 1; - t.bitfield.imm16 = 1; - t.bitfield.imm32 = 1; - t.bitfield.imm32s = 1; - } - else if (fits_in_unsigned_byte (num)) - { - t.bitfield.imm8 = 1; - t.bitfield.imm16 = 1; - t.bitfield.imm32 = 1; - t.bitfield.imm32s = 1; - } - else if (fits_in_signed_word (num) || fits_in_unsigned_word (num)) - { - t.bitfield.imm16 = 1; - t.bitfield.imm32 = 1; - t.bitfield.imm32s = 1; - } - else if (fits_in_signed_long (num)) - { - t.bitfield.imm32 = 1; - t.bitfield.imm32s = 1; - } - else if (fits_in_unsigned_long (num)) - t.bitfield.imm32 = 1; - - return t; -} - -static offsetT -offset_in_range (offsetT val, int size) -{ - addressT mask; - - switch (size) - { - case 1: mask = ((addressT) 1 << 8) - 1; break; - case 2: mask = ((addressT) 1 << 16) - 1; break; - case 4: mask = ((addressT) 2 << 31) - 1; break; -#ifdef BFD64 - case 8: mask = ((addressT) 2 << 63) - 1; break; -#endif - default: abort (); - } - -#ifdef BFD64 - /* If BFD64, sign extend val for 32bit address mode. */ - if (flag_code != CODE_64BIT - || i.prefix[ADDR_PREFIX]) - if ((val & ~(((addressT) 2 << 31) - 1)) == 0) - val = (val ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31); -#endif - - if ((val & ~mask) != 0 && (val & ~mask) != ~mask) - { - char buf1[40], buf2[40]; - - sprint_value (buf1, val); - sprint_value (buf2, val & mask); - as_warn (_("%s shortened to %s"), buf1, buf2); - } - return val & mask; -} - -enum PREFIX_GROUP -{ - PREFIX_EXIST = 0, - PREFIX_LOCK, - PREFIX_REP, - PREFIX_OTHER -}; - -/* Returns - a. PREFIX_EXIST if attempting to add a prefix where one from the - same class already exists. - b. PREFIX_LOCK if lock prefix is added. - c. PREFIX_REP if rep/repne prefix is added. - d. PREFIX_OTHER if other prefix is added. - */ - -static enum PREFIX_GROUP -add_prefix (unsigned int prefix) -{ - enum PREFIX_GROUP ret = PREFIX_OTHER; - unsigned int q; - - if (prefix >= REX_OPCODE && prefix < REX_OPCODE + 16 - && flag_code == CODE_64BIT) - { - if ((i.prefix[REX_PREFIX] & prefix & REX_W) - || ((i.prefix[REX_PREFIX] & (REX_R | REX_X | REX_B)) - && (prefix & (REX_R | REX_X | REX_B)))) - ret = PREFIX_EXIST; - q = REX_PREFIX; - } - else - { - switch (prefix) - { - default: - abort (); - - case CS_PREFIX_OPCODE: - case DS_PREFIX_OPCODE: - case ES_PREFIX_OPCODE: - case FS_PREFIX_OPCODE: - case GS_PREFIX_OPCODE: - case SS_PREFIX_OPCODE: - q = SEG_PREFIX; - break; - - case REPNE_PREFIX_OPCODE: - case REPE_PREFIX_OPCODE: - q = REP_PREFIX; - ret = PREFIX_REP; - break; - - case LOCK_PREFIX_OPCODE: - q = LOCK_PREFIX; - ret = PREFIX_LOCK; - break; - - case FWAIT_OPCODE: - q = WAIT_PREFIX; - break; - - case ADDR_PREFIX_OPCODE: - q = ADDR_PREFIX; - break; - - case DATA_PREFIX_OPCODE: - q = DATA_PREFIX; - break; - } - if (i.prefix[q] != 0) - ret = PREFIX_EXIST; - } - - if (ret) - { - if (!i.prefix[q]) - ++i.prefixes; - i.prefix[q] |= prefix; - } - else - as_bad (_("same type of prefix used twice")); - - return ret; -} - -static void -update_code_flag (int value, int check) -{ - PRINTF_LIKE ((*as_error)); - - flag_code = (enum flag_code) value; - if (flag_code == CODE_64BIT) - { - cpu_arch_flags.bitfield.cpu64 = 1; - cpu_arch_flags.bitfield.cpuno64 = 0; - } - else - { - cpu_arch_flags.bitfield.cpu64 = 0; - cpu_arch_flags.bitfield.cpuno64 = 1; - } - if (value == CODE_64BIT && !cpu_arch_flags.bitfield.cpulm ) - { - if (check) - as_error = as_fatal; - else - as_error = as_bad; - (*as_error) (_("64bit mode not supported on `%s'."), - cpu_arch_name ? cpu_arch_name : default_arch); - } - if (value == CODE_32BIT && !cpu_arch_flags.bitfield.cpui386) - { - if (check) - as_error = as_fatal; - else - as_error = as_bad; - (*as_error) (_("32bit mode not supported on `%s'."), - cpu_arch_name ? cpu_arch_name : default_arch); - } - stackop_size = '\0'; -} - -static void -set_code_flag (int value) -{ - update_code_flag (value, 0); -} - -static void -set_16bit_gcc_code_flag (int new_code_flag) -{ - flag_code = (enum flag_code) new_code_flag; - if (flag_code != CODE_16BIT) - abort (); - cpu_arch_flags.bitfield.cpu64 = 0; - cpu_arch_flags.bitfield.cpuno64 = 1; - stackop_size = LONG_MNEM_SUFFIX; -} - -static void -set_intel_syntax (int syntax_flag) -{ - /* Find out if register prefixing is specified. */ - int ask_naked_reg = 0; - - SKIP_WHITESPACE (); - if (!is_end_of_line[(unsigned char) *input_line_pointer]) - { - char *string = input_line_pointer; - int e = get_symbol_end (); - - if (strcmp (string, "prefix") == 0) - ask_naked_reg = 1; - else if (strcmp (string, "noprefix") == 0) - ask_naked_reg = -1; - else - as_bad (_("bad argument to syntax directive.")); - *input_line_pointer = e; - } - demand_empty_rest_of_line (); - - intel_syntax = syntax_flag; - - if (ask_naked_reg == 0) - allow_naked_reg = (intel_syntax - && (bfd_get_symbol_leading_char (stdoutput) != '\0')); - else - allow_naked_reg = (ask_naked_reg < 0); - - expr_set_rank (O_full_ptr, syntax_flag ? 10 : 0); - - identifier_chars['%'] = intel_syntax && allow_naked_reg ? '%' : 0; - identifier_chars['$'] = intel_syntax ? '$' : 0; - 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) -{ - allow_index_reg = flag; -} - -static void -set_check (int what) -{ - enum check_kind *kind; - const char *str; - - if (what) - { - kind = &operand_check; - str = "operand"; - } - else - { - kind = &sse_check; - str = "sse"; - } - - SKIP_WHITESPACE (); - - if (!is_end_of_line[(unsigned char) *input_line_pointer]) - { - char *string = input_line_pointer; - int e = get_symbol_end (); - - if (strcmp (string, "none") == 0) - *kind = check_none; - else if (strcmp (string, "warning") == 0) - *kind = check_warning; - else if (strcmp (string, "error") == 0) - *kind = check_error; - else - as_bad (_("bad argument to %s_check directive."), str); - *input_line_pointer = e; - } - else - as_bad (_("missing argument for %s_check directive"), str); - - demand_empty_rest_of_line (); -} - -static void -check_cpu_arch_compatible (const char *name ATTRIBUTE_UNUSED, - i386_cpu_flags new_flag ATTRIBUTE_UNUSED) -{ -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - static const char *arch; - - /* Intel LIOM is only supported on ELF. */ - if (!IS_ELF) - return; - - if (!arch) - { - /* Use cpu_arch_name if it is set in md_parse_option. Otherwise - use default_arch. */ - arch = cpu_arch_name; - if (!arch) - arch = default_arch; - } - - /* If we are targeting Intel L1OM, we must enable it. */ - if (get_elf_backend_data (stdoutput)->elf_machine_code != EM_L1OM - || new_flag.bitfield.cpul1om) - return; - - /* If we are targeting Intel K1OM, we must enable it. */ - if (get_elf_backend_data (stdoutput)->elf_machine_code != EM_K1OM - || new_flag.bitfield.cpuk1om) - return; - - as_bad (_("`%s' is not supported on `%s'"), name, arch); -#endif -} - -static void -set_cpu_arch (int dummy ATTRIBUTE_UNUSED) -{ - SKIP_WHITESPACE (); - - if (!is_end_of_line[(unsigned char) *input_line_pointer]) - { - char *string = input_line_pointer; - int e = get_symbol_end (); - unsigned int j; - i386_cpu_flags flags; - - for (j = 0; j < ARRAY_SIZE (cpu_arch); j++) - { - if (strcmp (string, cpu_arch[j].name) == 0) - { - check_cpu_arch_compatible (string, cpu_arch[j].flags); - - if (*string != '.') - { - cpu_arch_name = cpu_arch[j].name; - cpu_sub_arch_name = NULL; - cpu_arch_flags = cpu_arch[j].flags; - if (flag_code == CODE_64BIT) - { - cpu_arch_flags.bitfield.cpu64 = 1; - cpu_arch_flags.bitfield.cpuno64 = 0; - } - else - { - cpu_arch_flags.bitfield.cpu64 = 0; - cpu_arch_flags.bitfield.cpuno64 = 1; - } - cpu_arch_isa = cpu_arch[j].type; - cpu_arch_isa_flags = cpu_arch[j].flags; - if (!cpu_arch_tune_set) - { - cpu_arch_tune = cpu_arch_isa; - cpu_arch_tune_flags = cpu_arch_isa_flags; - } - break; - } - - if (!cpu_arch[j].negated) - flags = cpu_flags_or (cpu_arch_flags, - cpu_arch[j].flags); - else - flags = cpu_flags_and_not (cpu_arch_flags, - cpu_arch[j].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[j].name, - (const char *) NULL); - free (name); - } - else - cpu_sub_arch_name = xstrdup (cpu_arch[j].name); - cpu_arch_flags = flags; - cpu_arch_isa_flags = flags; - } - *input_line_pointer = e; - demand_empty_rest_of_line (); - return; - } - } - if (j >= ARRAY_SIZE (cpu_arch)) - as_bad (_("no such architecture: `%s'"), string); - - *input_line_pointer = e; - } - else - as_bad (_("missing cpu architecture")); - - no_cond_jump_promotion = 0; - if (*input_line_pointer == ',' - && !is_end_of_line[(unsigned char) input_line_pointer[1]]) - { - char *string = ++input_line_pointer; - int e = get_symbol_end (); - - if (strcmp (string, "nojumps") == 0) - no_cond_jump_promotion = 1; - else if (strcmp (string, "jumps") == 0) - ; - else - as_bad (_("no such architecture modifier: `%s'"), string); - - *input_line_pointer = e; - } - - demand_empty_rest_of_line (); -} - -enum bfd_architecture -i386_arch (void) -{ - if (cpu_arch_isa == PROCESSOR_L1OM) - { - if (OUTPUT_FLAVOR != bfd_target_elf_flavour - || flag_code != CODE_64BIT) - as_fatal (_("Intel L1OM is 64bit ELF only")); - return bfd_arch_l1om; - } - else if (cpu_arch_isa == PROCESSOR_K1OM) - { - if (OUTPUT_FLAVOR != bfd_target_elf_flavour - || flag_code != CODE_64BIT) - as_fatal (_("Intel K1OM is 64bit ELF only")); - return bfd_arch_k1om; - } - else - return bfd_arch_i386; -} - -unsigned long -i386_mach (void) -{ - if (!strncmp (default_arch, "x86_64", 6)) - { - if (cpu_arch_isa == PROCESSOR_L1OM) - { - if (OUTPUT_FLAVOR != bfd_target_elf_flavour - || default_arch[6] != '\0') - as_fatal (_("Intel L1OM is 64bit ELF only")); - return bfd_mach_l1om; - } - else if (cpu_arch_isa == PROCESSOR_K1OM) - { - if (OUTPUT_FLAVOR != bfd_target_elf_flavour - || default_arch[6] != '\0') - as_fatal (_("Intel K1OM is 64bit ELF only")); - return bfd_mach_k1om; - } - else if (default_arch[6] == '\0') - return bfd_mach_x86_64; - else - return bfd_mach_x64_32; - } - else if (!strcmp (default_arch, "i386")) - return bfd_mach_i386_i386; - else - as_fatal (_("unknown architecture")); -} - -void -md_begin (void) -{ - const char *hash_err; - - /* Initialize op_hash hash table. */ - op_hash = hash_new (); - - { - const insn_template *optab; - templates *core_optab; - - /* Setup for loop. */ - optab = i386_optab; - core_optab = (templates *) xmalloc (sizeof (templates)); - core_optab->start = optab; - - while (1) - { - ++optab; - if (optab->name == NULL - || strcmp (optab->name, (optab - 1)->name) != 0) - { - /* different name --> ship out current template list; - add to hash table; & begin anew. */ - core_optab->end = optab; - hash_err = hash_insert (op_hash, - (optab - 1)->name, - (void *) core_optab); - if (hash_err) - { - as_fatal (_("can't hash %s: %s"), - (optab - 1)->name, - hash_err); - } - if (optab->name == NULL) - break; - core_optab = (templates *) xmalloc (sizeof (templates)); - core_optab->start = optab; - } - } - } - - /* Initialize reg_hash hash table. */ - reg_hash = hash_new (); - { - const reg_entry *regtab; - unsigned int regtab_size = i386_regtab_size; - - for (regtab = i386_regtab; regtab_size--; regtab++) - { - hash_err = hash_insert (reg_hash, regtab->reg_name, (void *) regtab); - if (hash_err) - as_fatal (_("can't hash %s: %s"), - regtab->reg_name, - hash_err); - } - } - - /* Fill in lexical tables: mnemonic_chars, operand_chars. */ - { - int c; - char *p; - - for (c = 0; c < 256; c++) - { - if (ISDIGIT (c)) - { - digit_chars[c] = c; - mnemonic_chars[c] = c; - register_chars[c] = c; - operand_chars[c] = c; - } - else if (ISLOWER (c)) - { - mnemonic_chars[c] = c; - register_chars[c] = c; - operand_chars[c] = c; - } - else if (ISUPPER (c)) - { - mnemonic_chars[c] = TOLOWER (c); - register_chars[c] = mnemonic_chars[c]; - operand_chars[c] = c; - } - else if (c == '{' || c == '}') - operand_chars[c] = c; - - if (ISALPHA (c) || ISDIGIT (c)) - identifier_chars[c] = c; - else if (c >= 128) - { - identifier_chars[c] = c; - operand_chars[c] = c; - } - } - -#ifdef LEX_AT - identifier_chars['@'] = '@'; -#endif -#ifdef LEX_QM - identifier_chars['?'] = '?'; - operand_chars['?'] = '?'; -#endif - digit_chars['-'] = '-'; - mnemonic_chars['_'] = '_'; - mnemonic_chars['-'] = '-'; - mnemonic_chars['.'] = '.'; - identifier_chars['_'] = '_'; - identifier_chars['.'] = '.'; - - for (p = operand_special_chars; *p != '\0'; p++) - operand_chars[(unsigned char) *p] = *p; - } - - if (flag_code == CODE_64BIT) - { -#if defined (OBJ_COFF) && defined (TE_PE) - x86_dwarf2_return_column = (OUTPUT_FLAVOR == bfd_target_coff_flavour - ? 32 : 16); -#else - x86_dwarf2_return_column = 16; -#endif - x86_cie_data_alignment = -8; - } - else - { - x86_dwarf2_return_column = 8; - x86_cie_data_alignment = -4; - } -} - -void -i386_print_statistics (FILE *file) -{ - hash_print_statistics (file, "i386 opcode", op_hash); - hash_print_statistics (file, "i386 register", reg_hash); -} - -#ifdef DEBUG386 - -/* Debugging routines for md_assemble. */ -static void pte (insn_template *); -static void pt (i386_operand_type); -static void pe (expressionS *); -static void ps (symbolS *); - -static void -pi (char *line, i386_insn *x) -{ - unsigned int j; - - fprintf (stdout, "%s: template ", line); - pte (&x->tm); - fprintf (stdout, " address: base %s index %s scale %x\n", - x->base_reg ? x->base_reg->reg_name : "none", - x->index_reg ? x->index_reg->reg_name : "none", - x->log2_scale_factor); - fprintf (stdout, " modrm: mode %x reg %x reg/mem %x\n", - x->rm.mode, x->rm.reg, x->rm.regmem); - fprintf (stdout, " sib: base %x index %x scale %x\n", - x->sib.base, x->sib.index, x->sib.scale); - fprintf (stdout, " rex: 64bit %x extX %x extY %x extZ %x\n", - (x->rex & REX_W) != 0, - (x->rex & REX_R) != 0, - (x->rex & REX_X) != 0, - (x->rex & REX_B) != 0); - for (j = 0; j < x->operands; j++) - { - fprintf (stdout, " #%d: ", j + 1); - pt (x->types[j]); - fprintf (stdout, "\n"); - if (x->types[j].bitfield.reg8 - || x->types[j].bitfield.reg16 - || x->types[j].bitfield.reg32 - || x->types[j].bitfield.reg64 - || x->types[j].bitfield.regmmx - || x->types[j].bitfield.regxmm - || x->types[j].bitfield.regymm - || x->types[j].bitfield.regzmm - || x->types[j].bitfield.sreg2 - || x->types[j].bitfield.sreg3 - || x->types[j].bitfield.control - || x->types[j].bitfield.debug - || x->types[j].bitfield.test) - fprintf (stdout, "%s\n", x->op[j].regs->reg_name); - if (operand_type_check (x->types[j], imm)) - pe (x->op[j].imms); - if (operand_type_check (x->types[j], disp)) - pe (x->op[j].disps); - } -} - -static void -pte (insn_template *t) -{ - unsigned int j; - fprintf (stdout, " %d operands ", t->operands); - fprintf (stdout, "opcode %x ", t->base_opcode); - if (t->extension_opcode != None) - fprintf (stdout, "ext %x ", t->extension_opcode); - if (t->opcode_modifier.d) - fprintf (stdout, "D"); - if (t->opcode_modifier.w) - fprintf (stdout, "W"); - fprintf (stdout, "\n"); - for (j = 0; j < t->operands; j++) - { - fprintf (stdout, " #%d type ", j + 1); - pt (t->operand_types[j]); - fprintf (stdout, "\n"); - } -} - -static void -pe (expressionS *e) -{ - fprintf (stdout, " operation %d\n", e->X_op); - fprintf (stdout, " add_number %ld (%lx)\n", - (long) e->X_add_number, (long) e->X_add_number); - if (e->X_add_symbol) - { - fprintf (stdout, " add_symbol "); - ps (e->X_add_symbol); - fprintf (stdout, "\n"); - } - if (e->X_op_symbol) - { - fprintf (stdout, " op_symbol "); - ps (e->X_op_symbol); - fprintf (stdout, "\n"); - } -} - -static void -ps (symbolS *s) -{ - fprintf (stdout, "%s type %s%s", - S_GET_NAME (s), - S_IS_EXTERNAL (s) ? "EXTERNAL " : "", - segment_name (S_GET_SEGMENT (s))); -} - -static struct type_name - { - i386_operand_type mask; - const char *name; - } -const type_names[] = -{ - { OPERAND_TYPE_REG8, "r8" }, - { OPERAND_TYPE_REG16, "r16" }, - { OPERAND_TYPE_REG32, "r32" }, - { OPERAND_TYPE_REG64, "r64" }, - { OPERAND_TYPE_IMM8, "i8" }, - { OPERAND_TYPE_IMM8, "i8s" }, - { OPERAND_TYPE_IMM16, "i16" }, - { OPERAND_TYPE_IMM32, "i32" }, - { OPERAND_TYPE_IMM32S, "i32s" }, - { OPERAND_TYPE_IMM64, "i64" }, - { OPERAND_TYPE_IMM1, "i1" }, - { OPERAND_TYPE_BASEINDEX, "BaseIndex" }, - { OPERAND_TYPE_DISP8, "d8" }, - { OPERAND_TYPE_DISP16, "d16" }, - { OPERAND_TYPE_DISP32, "d32" }, - { OPERAND_TYPE_DISP32S, "d32s" }, - { OPERAND_TYPE_DISP64, "d64" }, - { OPERAND_TYPE_VEC_DISP8, "Vector d8" }, - { OPERAND_TYPE_INOUTPORTREG, "InOutPortReg" }, - { OPERAND_TYPE_SHIFTCOUNT, "ShiftCount" }, - { OPERAND_TYPE_CONTROL, "control reg" }, - { OPERAND_TYPE_TEST, "test reg" }, - { OPERAND_TYPE_DEBUG, "debug reg" }, - { OPERAND_TYPE_FLOATREG, "FReg" }, - { OPERAND_TYPE_FLOATACC, "FAcc" }, - { OPERAND_TYPE_SREG2, "SReg2" }, - { OPERAND_TYPE_SREG3, "SReg3" }, - { OPERAND_TYPE_ACC, "Acc" }, - { OPERAND_TYPE_JUMPABSOLUTE, "Jump Absolute" }, - { OPERAND_TYPE_REGMMX, "rMMX" }, - { OPERAND_TYPE_REGXMM, "rXMM" }, - { OPERAND_TYPE_REGYMM, "rYMM" }, - { OPERAND_TYPE_REGZMM, "rZMM" }, - { OPERAND_TYPE_REGMASK, "Mask reg" }, - { OPERAND_TYPE_ESSEG, "es" }, -}; - -static void -pt (i386_operand_type t) -{ - unsigned int j; - i386_operand_type a; - - for (j = 0; j < ARRAY_SIZE (type_names); j++) - { - a = operand_type_and (t, type_names[j].mask); - if (!operand_type_all_zero (&a)) - fprintf (stdout, "%s, ", type_names[j].name); - } - fflush (stdout); -} - -#endif /* DEBUG386 */ - -static bfd_reloc_code_real_type -reloc (unsigned int size, - int pcrel, - int sign, - int bnd_prefix, - bfd_reloc_code_real_type other) -{ - if (other != NO_RELOC) - { - reloc_howto_type *rel; - - if (size == 8) - switch (other) - { - case BFD_RELOC_X86_64_GOT32: - return BFD_RELOC_X86_64_GOT64; - break; - case BFD_RELOC_X86_64_PLTOFF64: - return BFD_RELOC_X86_64_PLTOFF64; - break; - case BFD_RELOC_X86_64_GOTPC32: - other = BFD_RELOC_X86_64_GOTPC64; - break; - case BFD_RELOC_X86_64_GOTPCREL: - other = BFD_RELOC_X86_64_GOTPCREL64; - break; - case BFD_RELOC_X86_64_TPOFF32: - other = BFD_RELOC_X86_64_TPOFF64; - break; - case BFD_RELOC_X86_64_DTPOFF32: - other = BFD_RELOC_X86_64_DTPOFF64; - break; - default: - break; - } - -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - if (other == BFD_RELOC_SIZE32) - { - if (size == 8) - return BFD_RELOC_SIZE64; - if (pcrel) - as_bad (_("there are no pc-relative size relocations")); - } -#endif - - /* Sign-checking 4-byte relocations in 16-/32-bit code is pointless. */ - if (size == 4 && (flag_code != CODE_64BIT || disallow_64bit_reloc)) - sign = -1; - - rel = bfd_reloc_type_lookup (stdoutput, other); - if (!rel) - as_bad (_("unknown relocation (%u)"), other); - else if (size != bfd_get_reloc_size (rel)) - as_bad (_("%u-byte relocation cannot be applied to %u-byte field"), - bfd_get_reloc_size (rel), - size); - else if (pcrel && !rel->pc_relative) - as_bad (_("non-pc-relative relocation for pc-relative field")); - else if ((rel->complain_on_overflow == complain_overflow_signed - && !sign) - || (rel->complain_on_overflow == complain_overflow_unsigned - && sign > 0)) - as_bad (_("relocated field and relocation type differ in signedness")); - else - return other; - return NO_RELOC; - } - - if (pcrel) - { - if (!sign) - as_bad (_("there are no unsigned pc-relative relocations")); - switch (size) - { - case 1: return BFD_RELOC_8_PCREL; - case 2: return BFD_RELOC_16_PCREL; - case 4: return (bnd_prefix && object_64bit - ? BFD_RELOC_X86_64_PC32_BND - : BFD_RELOC_32_PCREL); - case 8: return BFD_RELOC_64_PCREL; - } - as_bad (_("cannot do %u byte pc-relative relocation"), size); - } - else - { - if (sign > 0) - switch (size) - { - case 4: return BFD_RELOC_X86_64_32S; - } - else - switch (size) - { - case 1: return BFD_RELOC_8; - case 2: return BFD_RELOC_16; - case 4: return BFD_RELOC_32; - case 8: return BFD_RELOC_64; - } - as_bad (_("cannot do %s %u byte relocation"), - sign > 0 ? "signed" : "unsigned", size); - } - - return NO_RELOC; -} - -/* Here we decide which fixups can be adjusted to make them relative to - the beginning of the section instead of the symbol. Basically we need - to make sure that the dynamic relocations are done correctly, so in - some cases we force the original symbol to be used. */ - -int -tc_i386_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED) -{ -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - if (!IS_ELF) - return 1; - - /* Don't adjust pc-relative references to merge sections in 64-bit - mode. */ - if (use_rela_relocations - && (S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0 - && fixP->fx_pcrel) - return 0; - - /* The x86_64 GOTPCREL are represented as 32bit PCrel relocations - and changed later by validate_fix. */ - if (GOT_symbol && fixP->fx_subsy == GOT_symbol - && fixP->fx_r_type == BFD_RELOC_32_PCREL) - return 0; - - /* Adjust_reloc_syms doesn't know about the GOT. Need to keep symbol - for size relocations. */ - if (fixP->fx_r_type == BFD_RELOC_SIZE32 - || fixP->fx_r_type == BFD_RELOC_SIZE64 - || fixP->fx_r_type == BFD_RELOC_386_GOTOFF - || fixP->fx_r_type == BFD_RELOC_386_PLT32 - || fixP->fx_r_type == BFD_RELOC_386_GOT32 - || fixP->fx_r_type == BFD_RELOC_386_TLS_GD - || fixP->fx_r_type == BFD_RELOC_386_TLS_LDM - || fixP->fx_r_type == BFD_RELOC_386_TLS_LDO_32 - || fixP->fx_r_type == BFD_RELOC_386_TLS_IE_32 - || fixP->fx_r_type == BFD_RELOC_386_TLS_IE - || fixP->fx_r_type == BFD_RELOC_386_TLS_GOTIE - || fixP->fx_r_type == BFD_RELOC_386_TLS_LE_32 - || fixP->fx_r_type == BFD_RELOC_386_TLS_LE - || fixP->fx_r_type == BFD_RELOC_386_TLS_GOTDESC - || fixP->fx_r_type == BFD_RELOC_386_TLS_DESC_CALL - || fixP->fx_r_type == BFD_RELOC_X86_64_PLT32 - || fixP->fx_r_type == BFD_RELOC_X86_64_GOT32 - || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL - || fixP->fx_r_type == BFD_RELOC_X86_64_TLSGD - || fixP->fx_r_type == BFD_RELOC_X86_64_TLSLD - || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF32 - || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF64 - || fixP->fx_r_type == BFD_RELOC_X86_64_GOTTPOFF - || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF32 - || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF64 - || fixP->fx_r_type == BFD_RELOC_X86_64_GOTOFF64 - || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPC32_TLSDESC - || fixP->fx_r_type == BFD_RELOC_X86_64_TLSDESC_CALL - || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT - || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) - return 0; -#endif - return 1; -} - -static int -intel_float_operand (const char *mnemonic) -{ - /* Note that the value returned is meaningful only for opcodes with (memory) - operands, hence the code here is free to improperly handle opcodes that - have no operands (for better performance and smaller code). */ - - if (mnemonic[0] != 'f') - return 0; /* non-math */ - - switch (mnemonic[1]) - { - /* fclex, fdecstp, fdisi, femms, feni, fincstp, finit, fsetpm, and - the fs segment override prefix not currently handled because no - call path can make opcodes without operands get here */ - case 'i': - return 2 /* integer op */; - case 'l': - if (mnemonic[2] == 'd' && (mnemonic[3] == 'c' || mnemonic[3] == 'e')) - return 3; /* fldcw/fldenv */ - break; - case 'n': - if (mnemonic[2] != 'o' /* fnop */) - return 3; /* non-waiting control op */ - break; - case 'r': - if (mnemonic[2] == 's') - return 3; /* frstor/frstpm */ - break; - case 's': - if (mnemonic[2] == 'a') - return 3; /* fsave */ - if (mnemonic[2] == 't') - { - switch (mnemonic[3]) - { - case 'c': /* fstcw */ - case 'd': /* fstdw */ - case 'e': /* fstenv */ - case 's': /* fsts[gw] */ - return 3; - } - } - break; - case 'x': - if (mnemonic[2] == 'r' || mnemonic[2] == 's') - return 0; /* fxsave/fxrstor are not really math ops */ - break; - } - - return 1; -} - -/* Build the VEX prefix. */ - -static void -build_vex_prefix (const insn_template *t) -{ - unsigned int register_specifier; - unsigned int implied_prefix; - unsigned int vector_length; - - /* Check register specifier. */ - if (i.vex.register_specifier) - { - register_specifier = - ~register_number (i.vex.register_specifier) & 0xf; - gas_assert ((i.vex.register_specifier->reg_flags & RegVRex) == 0); - } - else - register_specifier = 0xf; - - /* Use 2-byte VEX prefix by swappping destination and source - operand. */ - if (!i.swap_operand - && i.operands == i.reg_operands - && i.tm.opcode_modifier.vexopcode == VEX0F - && i.tm.opcode_modifier.s - && i.rex == REX_B) - { - unsigned int xchg = i.operands - 1; - union i386_op temp_op; - i386_operand_type temp_type; - - temp_type = i.types[xchg]; - i.types[xchg] = i.types[0]; - i.types[0] = temp_type; - temp_op = i.op[xchg]; - i.op[xchg] = i.op[0]; - i.op[0] = temp_op; - - gas_assert (i.rm.mode == 3); - - i.rex = REX_R; - xchg = i.rm.regmem; - i.rm.regmem = i.rm.reg; - i.rm.reg = xchg; - - /* Use the next insn. */ - i.tm = t[1]; - } - - if (i.tm.opcode_modifier.vex == VEXScalar) - vector_length = avxscalar; - else - vector_length = i.tm.opcode_modifier.vex == VEX256 ? 1 : 0; - - switch ((i.tm.base_opcode >> 8) & 0xff) - { - case 0: - implied_prefix = 0; - break; - case DATA_PREFIX_OPCODE: - implied_prefix = 1; - break; - case REPE_PREFIX_OPCODE: - implied_prefix = 2; - break; - case REPNE_PREFIX_OPCODE: - implied_prefix = 3; - break; - default: - abort (); - } - - /* Use 2-byte VEX prefix if possible. */ - if (i.tm.opcode_modifier.vexopcode == VEX0F - && i.tm.opcode_modifier.vexw != VEXW1 - && (i.rex & (REX_W | REX_X | REX_B)) == 0) - { - /* 2-byte VEX prefix. */ - unsigned int r; - - i.vex.length = 2; - i.vex.bytes[0] = 0xc5; - - /* Check the REX.R bit. */ - r = (i.rex & REX_R) ? 0 : 1; - i.vex.bytes[1] = (r << 7 - | register_specifier << 3 - | vector_length << 2 - | implied_prefix); - } - else - { - /* 3-byte VEX prefix. */ - unsigned int m, w; - - i.vex.length = 3; - - switch (i.tm.opcode_modifier.vexopcode) - { - case VEX0F: - m = 0x1; - i.vex.bytes[0] = 0xc4; - break; - case VEX0F38: - m = 0x2; - i.vex.bytes[0] = 0xc4; - break; - case VEX0F3A: - m = 0x3; - i.vex.bytes[0] = 0xc4; - break; - case XOP08: - m = 0x8; - i.vex.bytes[0] = 0x8f; - break; - case XOP09: - m = 0x9; - i.vex.bytes[0] = 0x8f; - break; - case XOP0A: - m = 0xa; - i.vex.bytes[0] = 0x8f; - break; - default: - abort (); - } - - /* The high 3 bits of the second VEX byte are 1's compliment - of RXB bits from REX. */ - i.vex.bytes[1] = (~i.rex & 0x7) << 5 | m; - - /* Check the REX.W bit. */ - w = (i.rex & REX_W) ? 1 : 0; - if (i.tm.opcode_modifier.vexw) - { - if (w) - abort (); - - if (i.tm.opcode_modifier.vexw == VEXW1) - w = 1; - } - - i.vex.bytes[2] = (w << 7 - | register_specifier << 3 - | vector_length << 2 - | implied_prefix); - } -} - -/* Build the EVEX prefix. */ - -static void -build_evex_prefix (void) -{ - unsigned int register_specifier; - unsigned int implied_prefix; - unsigned int m, w; - rex_byte vrex_used = 0; - - /* Check register specifier. */ - if (i.vex.register_specifier) - { - gas_assert ((i.vrex & REX_X) == 0); - - register_specifier = i.vex.register_specifier->reg_num; - if ((i.vex.register_specifier->reg_flags & RegRex)) - register_specifier += 8; - /* The upper 16 registers are encoded in the fourth byte of the - EVEX prefix. */ - if (!(i.vex.register_specifier->reg_flags & RegVRex)) - i.vex.bytes[3] = 0x8; - register_specifier = ~register_specifier & 0xf; - } - else - { - register_specifier = 0xf; - - /* Encode upper 16 vector index register in the fourth byte of - the EVEX prefix. */ - if (!(i.vrex & REX_X)) - i.vex.bytes[3] = 0x8; - else - vrex_used |= REX_X; - } - - switch ((i.tm.base_opcode >> 8) & 0xff) - { - case 0: - implied_prefix = 0; - break; - case DATA_PREFIX_OPCODE: - implied_prefix = 1; - break; - case REPE_PREFIX_OPCODE: - implied_prefix = 2; - break; - case REPNE_PREFIX_OPCODE: - implied_prefix = 3; - break; - default: - abort (); - } - - /* 4 byte EVEX prefix. */ - i.vex.length = 4; - i.vex.bytes[0] = 0x62; - - /* mmmm bits. */ - switch (i.tm.opcode_modifier.vexopcode) - { - case VEX0F: - m = 1; - break; - case VEX0F38: - m = 2; - break; - case VEX0F3A: - m = 3; - break; - default: - abort (); - break; - } - - /* The high 3 bits of the second EVEX byte are 1's compliment of RXB - bits from REX. */ - i.vex.bytes[1] = (~i.rex & 0x7) << 5 | m; - - /* The fifth bit of the second EVEX byte is 1's compliment of the - REX_R bit in VREX. */ - if (!(i.vrex & REX_R)) - i.vex.bytes[1] |= 0x10; - else - vrex_used |= REX_R; - - if ((i.reg_operands + i.imm_operands) == i.operands) - { - /* When all operands are registers, the REX_X bit in REX is not - used. We reuse it to encode the upper 16 registers, which is - indicated by the REX_B bit in VREX. The REX_X bit is encoded - as 1's compliment. */ - if ((i.vrex & REX_B)) - { - vrex_used |= REX_B; - i.vex.bytes[1] &= ~0x40; - } - } - - /* EVEX instructions shouldn't need the REX prefix. */ - i.vrex &= ~vrex_used; - gas_assert (i.vrex == 0); - - /* Check the REX.W bit. */ - w = (i.rex & REX_W) ? 1 : 0; - if (i.tm.opcode_modifier.vexw) - { - if (i.tm.opcode_modifier.vexw == VEXW1) - w = 1; - } - /* If w is not set it means we are dealing with WIG instruction. */ - else if (!w) - { - if (evexwig == evexw1) - w = 1; - } - - /* Encode the U bit. */ - implied_prefix |= 0x4; - - /* The third byte of the EVEX prefix. */ - i.vex.bytes[2] = (w << 7 | register_specifier << 3 | implied_prefix); - - /* The fourth byte of the EVEX prefix. */ - /* The zeroing-masking bit. */ - if (i.mask && i.mask->zeroing) - i.vex.bytes[3] |= 0x80; - - /* Don't always set the broadcast bit if there is no RC. */ - if (!i.rounding) - { - /* Encode the vector length. */ - unsigned int vec_length; - - switch (i.tm.opcode_modifier.evex) - { - case EVEXLIG: /* LL' is ignored */ - vec_length = evexlig << 5; - break; - case EVEX128: - vec_length = 0 << 5; - break; - case EVEX256: - vec_length = 1 << 5; - break; - case EVEX512: - vec_length = 2 << 5; - break; - default: - abort (); - break; - } - i.vex.bytes[3] |= vec_length; - /* Encode the broadcast bit. */ - if (i.broadcast) - i.vex.bytes[3] |= 0x10; - } - else - { - if (i.rounding->type != saeonly) - i.vex.bytes[3] |= 0x10 | (i.rounding->type << 5); - else - i.vex.bytes[3] |= 0x10; - } - - if (i.mask && i.mask->mask) - i.vex.bytes[3] |= i.mask->mask->reg_num; -} - -static void -process_immext (void) -{ - expressionS *exp; - - if ((i.tm.cpu_flags.bitfield.cpusse3 || i.tm.cpu_flags.bitfield.cpusvme) - && i.operands > 0) - { - /* MONITOR/MWAIT as well as SVME instructions have 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 (register_number (i.op[x].regs) != 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. - - AVX instructions also use this encoding, for some of - 3 argument instructions. */ - - gas_assert (i.imm_operands <= 1 - && (i.operands <= 2 - || ((i.tm.opcode_modifier.vex - || i.tm.opcode_modifier.evex) - && i.operands <= 4))); - - 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; -} - - -static int -check_hle (void) -{ - switch (i.tm.opcode_modifier.hleprefixok) - { - default: - abort (); - case HLEPrefixNone: - as_bad (_("invalid instruction `%s' after `%s'"), - i.tm.name, i.hle_prefix); - return 0; - case HLEPrefixLock: - if (i.prefix[LOCK_PREFIX]) - return 1; - as_bad (_("missing `lock' with `%s'"), i.hle_prefix); - return 0; - case HLEPrefixAny: - return 1; - case HLEPrefixRelease: - if (i.prefix[HLE_PREFIX] != XRELEASE_PREFIX_OPCODE) - { - as_bad (_("instruction `%s' after `xacquire' not allowed"), - i.tm.name); - return 0; - } - if (i.mem_operands == 0 - || !operand_type_check (i.types[i.operands - 1], anymem)) - { - as_bad (_("memory destination needed for instruction `%s'" - " after `xrelease'"), i.tm.name); - return 0; - } - return 1; - } -} - -/* 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 (char *line) -{ - unsigned int j; - char mnemonic[MAX_MNEM_SIZE]; - const insn_template *t; - - /* Initialize globals. */ - memset (&i, '\0', sizeof (i)); - for (j = 0; j < MAX_OPERANDS; j++) - i.reloc[j] = NO_RELOC; - memset (disp_expressions, '\0', sizeof (disp_expressions)); - memset (im_expressions, '\0', sizeof (im_expressions)); - save_stack_p = save_stack; - - /* First parse an instruction mnemonic & call i386_operand for the operands. - We assume that the scrubber has arranged it so that line[0] is the valid - start of a (possibly prefixed) mnemonic. */ - - line = parse_insn (line, mnemonic); - if (line == NULL) - return; - - line = parse_operands (line, mnemonic); - this_operand = -1; - if (line == NULL) - return; - - /* Now we've parsed the mnemonic into a set of templates, and have the - operands at hand. */ - - /* All intel opcodes have reversed operands except for "bound" and - "enter". We also don't reverse intersegment "jmp" and "call" - instructions with 2 immediate operands so that the immediate segment - precedes the offset, as it does when in AT&T mode. */ - if (intel_syntax - && i.operands > 1 - && (strcmp (mnemonic, "bound") != 0) - && (strcmp (mnemonic, "invlpga") != 0) - && !(operand_type_check (i.types[0], imm) - && operand_type_check (i.types[1], imm))) - swap_operands (); - - /* The order of the immediates should be reversed - for 2 immediates extrq and insertq instructions */ - if (i.imm_operands == 2 - && (strcmp (mnemonic, "extrq") == 0 - || strcmp (mnemonic, "insertq") == 0)) - swap_2_operands (0, 1); - - if (i.imm_operands) - optimize_imm (); - - /* Don't optimize displacement for movabs since it only takes 64bit - displacement. */ - if (i.disp_operands - && i.disp_encoding != disp_encoding_32bit - && (flag_code != CODE_64BIT - || strcmp (mnemonic, "movabs") != 0)) - optimize_disp (); - - /* Next, we find a template that matches the given insn, - making sure the overlap of the given operands types is consistent - with the template operand types. */ - - if (!(t = match_template ())) - return; - - if (sse_check != check_none - && !i.tm.opcode_modifier.noavx - && (i.tm.cpu_flags.bitfield.cpusse - || i.tm.cpu_flags.bitfield.cpusse2 - || i.tm.cpu_flags.bitfield.cpusse3 - || i.tm.cpu_flags.bitfield.cpussse3 - || i.tm.cpu_flags.bitfield.cpusse4_1 - || i.tm.cpu_flags.bitfield.cpusse4_2)) - { - (sse_check == check_warning - ? as_warn - : as_bad) (_("SSE instruction `%s' is used"), i.tm.name); - } - - /* 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) - { - /* 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; - } - - if (i.tm.opcode_modifier.fwait) - if (!add_prefix (FWAIT_OPCODE)) - return; - - /* Check if REP prefix is OK. */ - if (i.rep_prefix && !i.tm.opcode_modifier.repprefixok) - { - as_bad (_("invalid instruction `%s' after `%s'"), - i.tm.name, i.rep_prefix); - return; - } - - /* Check for lock without a lockable instruction. Destination operand - must be memory unless it is xchg (0x86). */ - if (i.prefix[LOCK_PREFIX] - && (!i.tm.opcode_modifier.islockable - || i.mem_operands == 0 - || (i.tm.base_opcode != 0x86 - && !operand_type_check (i.types[i.operands - 1], anymem)))) - { - as_bad (_("expecting lockable instruction after `lock'")); - return; - } - - /* Check if HLE prefix is OK. */ - if (i.hle_prefix && !check_hle ()) - return; - - /* Check BND prefix. */ - if (i.bnd_prefix && !i.tm.opcode_modifier.bndprefixok) - as_bad (_("expecting valid branch instruction after `bnd'")); - - if (i.tm.cpu_flags.bitfield.cpumpx - && flag_code == CODE_64BIT - && i.prefix[ADDR_PREFIX]) - as_bad (_("32-bit address isn't allowed in 64-bit MPX instructions.")); - - /* Insert BND prefix. */ - if (add_bnd_prefix - && i.tm.opcode_modifier.bndprefixok - && !i.prefix[BND_PREFIX]) - add_prefix (BND_PREFIX_OPCODE); - - /* Check string instruction segment overrides. */ - if (i.tm.opcode_modifier.isstring && i.mem_operands != 0) - { - if (!check_string ()) - return; - i.disp_operands = 0; - } - - if (!process_suffix ()) - return; - - /* Update operand types. */ - for (j = 0; j < i.operands; j++) - i.types[j] = operand_type_and (i.types[j], i.tm.operand_types[j]); - - /* Make still unresolved immediate matches conform to size of immediate - given in i.suffix. */ - if (!finalize_imm ()) - return; - - if (i.types[0].bitfield.imm1) - i.imm_operands = 0; /* kludge for shift insns. */ - - /* We only need to check those implicit registers for instructions - with 3 operands or less. */ - if (i.operands <= 3) - for (j = 0; j < i.operands; j++) - if (i.types[j].bitfield.inoutportreg - || i.types[j].bitfield.shiftcount - || i.types[j].bitfield.acc - || i.types[j].bitfield.floatacc) - i.reg_operands--; - - /* ImmExt should be processed after SSE2AVX. */ - if (!i.tm.opcode_modifier.sse2avx - && i.tm.opcode_modifier.immext) - process_immext (); - - /* For insns with operands there are more diddles to do to the opcode. */ - if (i.operands) - { - if (!process_operands ()) - return; - } - else if (!quiet_warnings && i.tm.opcode_modifier.ugh) - { - /* UnixWare fsub no args is alias for fsubp, fadd -> faddp, etc. */ - as_warn (_("translating to `%sp'"), i.tm.name); - } - - if (i.tm.opcode_modifier.vex) - build_vex_prefix (t); - - if (i.tm.opcode_modifier.evex) - build_evex_prefix (); - - /* Handle conversion of 'int $3' --> special int3 insn. XOP or FMA4 - instructions may define INT_OPCODE as well, so avoid this corner - case for those instructions that use MODRM. */ - if (i.tm.base_opcode == INT_OPCODE - && !i.tm.opcode_modifier.modrm - && i.op[0].imms->X_add_number == 3) - { - i.tm.base_opcode = INT3_OPCODE; - i.imm_operands = 0; - } - - if ((i.tm.opcode_modifier.jump - || i.tm.opcode_modifier.jumpbyte - || i.tm.opcode_modifier.jumpdword) - && i.op[0].disps->X_op == O_constant) - { - /* Convert "jmp constant" (and "call constant") to a jump (call) to - the absolute address given by the constant. Since ix86 jumps and - calls are pc relative, we need to generate a reloc. */ - i.op[0].disps->X_add_symbol = &abs_symbol; - i.op[0].disps->X_op = O_symbol; - } - - if (i.tm.opcode_modifier.rex64) - i.rex |= REX_W; - - /* For 8 bit registers we need an empty rex prefix. Also if the - instruction already has a prefix, we need to convert old - registers to new ones. */ - - if ((i.types[0].bitfield.reg8 - && (i.op[0].regs->reg_flags & RegRex64) != 0) - || (i.types[1].bitfield.reg8 - && (i.op[1].regs->reg_flags & RegRex64) != 0) - || ((i.types[0].bitfield.reg8 - || i.types[1].bitfield.reg8) - && i.rex != 0)) - { - int x; - - i.rex |= REX_OPCODE; - for (x = 0; x < 2; x++) - { - /* Look for 8 bit operand that uses old registers. */ - if (i.types[x].bitfield.reg8 - && (i.op[x].regs->reg_flags & RegRex64) == 0) - { - /* In case it is "hi" register, give up. */ - if (i.op[x].regs->reg_num > 3) - as_bad (_("can't encode register '%s%s' in an " - "instruction requiring REX prefix."), - register_prefix, i.op[x].regs->reg_name); - - /* Otherwise it is equivalent to the extended register. - Since the encoding doesn't change this is merely - cosmetic cleanup for debug output. */ - - i.op[x].regs = i.op[x].regs + 8; - } - } - } - - if (i.rex != 0) - add_prefix (REX_OPCODE | i.rex); - - /* We are ready to output the insn. */ - output_insn (); -} - -static char * -parse_insn (char *line, char *mnemonic) -{ - char *l = line; - char *token_start = l; - char *mnem_p; - int supported; - const insn_template *t; - char *dot_p = NULL; - - while (1) - { - mnem_p = mnemonic; - while ((*mnem_p = mnemonic_chars[(unsigned char) *l]) != 0) - { - if (*mnem_p == '.') - dot_p = mnem_p; - mnem_p++; - if (mnem_p >= mnemonic + MAX_MNEM_SIZE) - { - as_bad (_("no such instruction: `%s'"), token_start); - return NULL; - } - l++; - } - if (!is_space_char (*l) - && *l != END_OF_INSN - && (intel_syntax - || (*l != PREFIX_SEPARATOR - && *l != ','))) - { - as_bad (_("invalid character %s in mnemonic"), - output_invalid (*l)); - return NULL; - } - if (token_start == l) - { - if (!intel_syntax && *l == PREFIX_SEPARATOR) - as_bad (_("expecting prefix; got nothing")); - else - as_bad (_("expecting mnemonic; got nothing")); - return NULL; - } - - /* Look up instruction (or prefix) via hash table. */ - current_templates = (const templates *) hash_find (op_hash, mnemonic); - - if (*l != END_OF_INSN - && (!is_space_char (*l) || l[1] != END_OF_INSN) - && current_templates - && current_templates->start->opcode_modifier.isprefix) - { - if (!cpu_flags_check_cpu64 (current_templates->start->cpu_flags)) - { - as_bad ((flag_code != CODE_64BIT - ? _("`%s' is only supported in 64-bit mode") - : _("`%s' is not supported in 64-bit mode")), - current_templates->start->name); - return NULL; - } - /* If we are in 16-bit mode, do not allow addr16 or data16. - Similarly, in 32-bit mode, do not allow addr32 or data32. */ - if ((current_templates->start->opcode_modifier.size16 - || current_templates->start->opcode_modifier.size32) - && flag_code != CODE_64BIT - && (current_templates->start->opcode_modifier.size32 - ^ (flag_code == CODE_16BIT))) - { - as_bad (_("redundant %s prefix"), - current_templates->start->name); - return NULL; - } - /* Add prefix, checking for repeated prefixes. */ - switch (add_prefix (current_templates->start->base_opcode)) - { - case PREFIX_EXIST: - return NULL; - case PREFIX_REP: - if (current_templates->start->cpu_flags.bitfield.cpuhle) - i.hle_prefix = current_templates->start->name; - else if (current_templates->start->cpu_flags.bitfield.cpumpx) - i.bnd_prefix = current_templates->start->name; - else - i.rep_prefix = current_templates->start->name; - break; - default: - break; - } - /* Skip past PREFIX_SEPARATOR and reset token_start. */ - token_start = ++l; - } - else - break; - } - - if (!current_templates) - { - /* Check if we should swap operand or force 32bit displacement in - encoding. */ - if (mnem_p - 2 == dot_p && dot_p[1] == 's') - i.swap_operand = 1; - else if (mnem_p - 3 == dot_p - && dot_p[1] == 'd' - && dot_p[2] == '8') - i.disp_encoding = disp_encoding_8bit; - else if (mnem_p - 4 == dot_p - && dot_p[1] == 'd' - && dot_p[2] == '3' - && dot_p[3] == '2') - i.disp_encoding = disp_encoding_32bit; - else - goto check_suffix; - mnem_p = dot_p; - *dot_p = '\0'; - current_templates = (const templates *) hash_find (op_hash, mnemonic); - } - - if (!current_templates) - { -check_suffix: - /* See if we can get a match by trimming off a suffix. */ - switch (mnem_p[-1]) - { - case WORD_MNEM_SUFFIX: - if (intel_syntax && (intel_float_operand (mnemonic) & 2)) - i.suffix = SHORT_MNEM_SUFFIX; - else - case BYTE_MNEM_SUFFIX: - case QWORD_MNEM_SUFFIX: - i.suffix = mnem_p[-1]; - mnem_p[-1] = '\0'; - current_templates = (const templates *) hash_find (op_hash, - mnemonic); - break; - case SHORT_MNEM_SUFFIX: - case LONG_MNEM_SUFFIX: - if (!intel_syntax) - { - i.suffix = mnem_p[-1]; - mnem_p[-1] = '\0'; - current_templates = (const templates *) hash_find (op_hash, - mnemonic); - } - break; - - /* Intel Syntax. */ - case 'd': - if (intel_syntax) - { - if (intel_float_operand (mnemonic) == 1) - i.suffix = SHORT_MNEM_SUFFIX; - else - i.suffix = LONG_MNEM_SUFFIX; - mnem_p[-1] = '\0'; - current_templates = (const templates *) hash_find (op_hash, - mnemonic); - } - break; - } - if (!current_templates) - { - as_bad (_("no such instruction: `%s'"), token_start); - return NULL; - } - } - - if (current_templates->start->opcode_modifier.jump - || current_templates->start->opcode_modifier.jumpbyte) - { - /* Check for a branch hint. We allow ",pt" and ",pn" for - predict taken and predict not taken respectively. - I'm not sure that branch hints actually do anything on loop - and jcxz insns (JumpByte) for current Pentium4 chips. They - may work in the future and it doesn't hurt to accept them - now. */ - if (l[0] == ',' && l[1] == 'p') - { - if (l[2] == 't') - { - if (!add_prefix (DS_PREFIX_OPCODE)) - return NULL; - l += 3; - } - else if (l[2] == 'n') - { - if (!add_prefix (CS_PREFIX_OPCODE)) - return NULL; - l += 3; - } - } - } - /* Any other comma loses. */ - if (*l == ',') - { - as_bad (_("invalid character %s in mnemonic"), - output_invalid (*l)); - return NULL; - } - - /* Check if instruction is supported on specified architecture. */ - supported = 0; - for (t = current_templates->start; t < current_templates->end; ++t) - { - supported |= cpu_flags_match (t); - if (supported == CPU_FLAGS_PERFECT_MATCH) - goto skip; - } - - if (!(supported & CPU_FLAGS_64BIT_MATCH)) - { - as_bad (flag_code == CODE_64BIT - ? _("`%s' is not supported in 64-bit mode") - : _("`%s' is only supported in 64-bit mode"), - current_templates->start->name); - return NULL; - } - if (supported != CPU_FLAGS_PERFECT_MATCH) - { - as_bad (_("`%s' is not supported on `%s%s'"), - current_templates->start->name, - cpu_arch_name ? cpu_arch_name : default_arch, - cpu_sub_arch_name ? cpu_sub_arch_name : ""); - return NULL; - } - -skip: - if (!cpu_arch_flags.bitfield.cpui386 - && (flag_code != CODE_16BIT)) - { - as_warn (_("use .code16 to ensure correct addressing mode")); - } - - return l; -} - -static char * -parse_operands (char *l, const char *mnemonic) -{ - char *token_start; - - /* 1 if operand is pending after ','. */ - unsigned int expecting_operand = 0; - - /* Non-zero if operand parens not balanced. */ - unsigned int paren_not_balanced; - - while (*l != END_OF_INSN) - { - /* Skip optional white space before operand. */ - if (is_space_char (*l)) - ++l; - if (!is_operand_char (*l) && *l != END_OF_INSN) - { - as_bad (_("invalid character %s before operand %d"), - output_invalid (*l), - i.operands + 1); - return NULL; - } - token_start = l; /* after white space */ - paren_not_balanced = 0; - while (paren_not_balanced || *l != ',') - { - if (*l == END_OF_INSN) - { - if (paren_not_balanced) - { - if (!intel_syntax) - as_bad (_("unbalanced parenthesis in operand %d."), - i.operands + 1); - else - as_bad (_("unbalanced brackets in operand %d."), - i.operands + 1); - return NULL; - } - else - break; /* we are done */ - } - else if (!is_operand_char (*l) && !is_space_char (*l)) - { - as_bad (_("invalid character %s in operand %d"), - output_invalid (*l), - i.operands + 1); - return NULL; - } - if (!intel_syntax) - { - if (*l == '(') - ++paren_not_balanced; - if (*l == ')') - --paren_not_balanced; - } - else - { - if (*l == '[') - ++paren_not_balanced; - if (*l == ']') - --paren_not_balanced; - } - l++; - } - if (l != token_start) - { /* 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)"), - MAX_OPERANDS); - return NULL; - } - /* Now parse operand adding info to 'i' as we go along. */ - END_STRING_AND_SAVE (l); - - if (intel_syntax) - operand_ok = - i386_intel_operand (token_start, - intel_float_operand (mnemonic)); - else - operand_ok = i386_att_operand (token_start); - - RESTORE_END_STRING (l); - if (!operand_ok) - return NULL; - } - else - { - if (expecting_operand) - { - expecting_operand_after_comma: - as_bad (_("expecting operand after ','; got nothing")); - return NULL; - } - if (*l == ',') - { - as_bad (_("expecting operand before ','; got nothing")); - return NULL; - } - } - - /* Now *l must be either ',' or END_OF_INSN. */ - if (*l == ',') - { - if (*++l == END_OF_INSN) - { - /* Just skip it, if it's \n complain. */ - goto expecting_operand_after_comma; - } - expecting_operand = 1; - } - } - return l; -} - -static void -swap_2_operands (int xchg1, int xchg2) -{ - union i386_op temp_op; - i386_operand_type temp_type; - enum bfd_reloc_code_real temp_reloc; - - temp_type = i.types[xchg2]; - i.types[xchg2] = i.types[xchg1]; - i.types[xchg1] = temp_type; - temp_op = i.op[xchg2]; - i.op[xchg2] = i.op[xchg1]; - i.op[xchg1] = temp_op; - temp_reloc = i.reloc[xchg2]; - i.reloc[xchg2] = i.reloc[xchg1]; - i.reloc[xchg1] = temp_reloc; - - if (i.mask) - { - if (i.mask->operand == xchg1) - i.mask->operand = xchg2; - else if (i.mask->operand == xchg2) - i.mask->operand = xchg1; - } - if (i.broadcast) - { - if (i.broadcast->operand == xchg1) - i.broadcast->operand = xchg2; - else if (i.broadcast->operand == xchg2) - i.broadcast->operand = xchg1; - } - if (i.rounding) - { - if (i.rounding->operand == xchg1) - i.rounding->operand = xchg2; - else if (i.rounding->operand == xchg2) - i.rounding->operand = xchg1; - } -} - -static void -swap_operands (void) -{ - switch (i.operands) - { - case 5: - case 4: - swap_2_operands (1, i.operands - 2); - case 3: - case 2: - swap_2_operands (0, i.operands - 1); - break; - default: - abort (); - } - - if (i.mem_operands == 2) - { - const seg_entry *temp_seg; - temp_seg = i.seg[0]; - i.seg[0] = i.seg[1]; - i.seg[1] = temp_seg; - } -} - -/* Try to ensure constant immediates are represented in the smallest - opcode possible. */ -static void -optimize_imm (void) -{ - char guess_suffix = 0; - int op; - - if (i.suffix) - guess_suffix = i.suffix; - else if (i.reg_operands) - { - /* Figure out a suffix from the last register operand specified. - We can't do this properly yet, ie. excluding InOutPortReg, - but the following works for instructions with immediates. - In any case, we can't set i.suffix yet. */ - for (op = i.operands; --op >= 0;) - if (i.types[op].bitfield.reg8) - { - guess_suffix = BYTE_MNEM_SUFFIX; - break; - } - else if (i.types[op].bitfield.reg16) - { - guess_suffix = WORD_MNEM_SUFFIX; - break; - } - else if (i.types[op].bitfield.reg32) - { - guess_suffix = LONG_MNEM_SUFFIX; - break; - } - else if (i.types[op].bitfield.reg64) - { - guess_suffix = QWORD_MNEM_SUFFIX; - break; - } - } - else if ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0)) - guess_suffix = WORD_MNEM_SUFFIX; - - for (op = i.operands; --op >= 0;) - if (operand_type_check (i.types[op], imm)) - { - switch (i.op[op].imms->X_op) - { - case O_constant: - /* If a suffix is given, this operand may be shortened. */ - switch (guess_suffix) - { - case LONG_MNEM_SUFFIX: - i.types[op].bitfield.imm32 = 1; - i.types[op].bitfield.imm64 = 1; - break; - case WORD_MNEM_SUFFIX: - i.types[op].bitfield.imm16 = 1; - i.types[op].bitfield.imm32 = 1; - i.types[op].bitfield.imm32s = 1; - i.types[op].bitfield.imm64 = 1; - break; - case BYTE_MNEM_SUFFIX: - i.types[op].bitfield.imm8 = 1; - i.types[op].bitfield.imm8s = 1; - i.types[op].bitfield.imm16 = 1; - i.types[op].bitfield.imm32 = 1; - i.types[op].bitfield.imm32s = 1; - i.types[op].bitfield.imm64 = 1; - break; - } - - /* If this operand is at most 16 bits, convert it - to a signed 16 bit number before trying to see - whether it will fit in an even smaller size. - This allows a 16-bit operand such as $0xffe0 to - be recognised as within Imm8S range. */ - if ((i.types[op].bitfield.imm16) - && (i.op[op].imms->X_add_number & ~(offsetT) 0xffff) == 0) - { - i.op[op].imms->X_add_number = - (((i.op[op].imms->X_add_number & 0xffff) ^ 0x8000) - 0x8000); - } - if ((i.types[op].bitfield.imm32) - && ((i.op[op].imms->X_add_number & ~(((offsetT) 2 << 31) - 1)) - == 0)) - { - i.op[op].imms->X_add_number = ((i.op[op].imms->X_add_number - ^ ((offsetT) 1 << 31)) - - ((offsetT) 1 << 31)); - } - i.types[op] - = operand_type_or (i.types[op], - smallest_imm_type (i.op[op].imms->X_add_number)); - - /* We must avoid matching of Imm32 templates when 64bit - only immediate is available. */ - if (guess_suffix == QWORD_MNEM_SUFFIX) - i.types[op].bitfield.imm32 = 0; - break; - - case O_absent: - case O_register: - abort (); - - /* Symbols and expressions. */ - default: - /* Convert symbolic operand to proper sizes for matching, but don't - prevent matching a set of insns that only supports sizes other - than those matching the insn suffix. */ - { - i386_operand_type mask, allowed; - const insn_template *t; - - operand_type_set (&mask, 0); - operand_type_set (&allowed, 0); - - for (t = current_templates->start; - t < current_templates->end; - ++t) - allowed = operand_type_or (allowed, - t->operand_types[op]); - switch (guess_suffix) - { - case QWORD_MNEM_SUFFIX: - mask.bitfield.imm64 = 1; - mask.bitfield.imm32s = 1; - break; - case LONG_MNEM_SUFFIX: - mask.bitfield.imm32 = 1; - break; - case WORD_MNEM_SUFFIX: - mask.bitfield.imm16 = 1; - break; - case BYTE_MNEM_SUFFIX: - mask.bitfield.imm8 = 1; - break; - default: - break; - } - allowed = operand_type_and (mask, allowed); - if (!operand_type_all_zero (&allowed)) - i.types[op] = operand_type_and (i.types[op], mask); - } - break; - } - } -} - -/* Try to use the smallest displacement type too. */ -static void -optimize_disp (void) -{ - int op; - - for (op = i.operands; --op >= 0;) - if (operand_type_check (i.types[op], disp)) - { - if (i.op[op].disps->X_op == O_constant) - { - offsetT op_disp = i.op[op].disps->X_add_number; - - if (i.types[op].bitfield.disp16 - && (op_disp & ~(offsetT) 0xffff) == 0) - { - /* If this operand is at most 16 bits, convert - to a signed 16 bit number and don't use 64bit - displacement. */ - op_disp = (((op_disp & 0xffff) ^ 0x8000) - 0x8000); - i.types[op].bitfield.disp64 = 0; - } - if (i.types[op].bitfield.disp32 - && (op_disp & ~(((offsetT) 2 << 31) - 1)) == 0) - { - /* If this operand is at most 32 bits, convert - to a signed 32 bit number and don't use 64bit - displacement. */ - op_disp &= (((offsetT) 2 << 31) - 1); - op_disp = (op_disp ^ ((offsetT) 1 << 31)) - ((addressT) 1 << 31); - i.types[op].bitfield.disp64 = 0; - } - if (!op_disp && i.types[op].bitfield.baseindex) - { - i.types[op].bitfield.disp8 = 0; - i.types[op].bitfield.disp16 = 0; - i.types[op].bitfield.disp32 = 0; - i.types[op].bitfield.disp32s = 0; - i.types[op].bitfield.disp64 = 0; - i.op[op].disps = 0; - i.disp_operands--; - } - else if (flag_code == CODE_64BIT) - { - if (fits_in_signed_long (op_disp)) - { - i.types[op].bitfield.disp64 = 0; - i.types[op].bitfield.disp32s = 1; - } - if (i.prefix[ADDR_PREFIX] - && fits_in_unsigned_long (op_disp)) - i.types[op].bitfield.disp32 = 1; - } - if ((i.types[op].bitfield.disp32 - || i.types[op].bitfield.disp32s - || i.types[op].bitfield.disp16) - && fits_in_signed_byte (op_disp)) - i.types[op].bitfield.disp8 = 1; - } - else if (i.reloc[op] == BFD_RELOC_386_TLS_DESC_CALL - || i.reloc[op] == BFD_RELOC_X86_64_TLSDESC_CALL) - { - fix_new_exp (frag_now, frag_more (0) - frag_now->fr_literal, 0, - i.op[op].disps, 0, i.reloc[op]); - i.types[op].bitfield.disp8 = 0; - i.types[op].bitfield.disp16 = 0; - i.types[op].bitfield.disp32 = 0; - i.types[op].bitfield.disp32s = 0; - i.types[op].bitfield.disp64 = 0; - } - else - /* We only support 64bit displacement on constants. */ - i.types[op].bitfield.disp64 = 0; - } -} - -/* Check if operands are valid for the instruction. */ - -static int -check_VecOperands (const insn_template *t) -{ - unsigned int op; - - /* Without VSIB byte, we can't have a vector register for index. */ - if (!t->opcode_modifier.vecsib - && i.index_reg - && (i.index_reg->reg_type.bitfield.regxmm - || i.index_reg->reg_type.bitfield.regymm - || i.index_reg->reg_type.bitfield.regzmm)) - { - i.error = unsupported_vector_index_register; - return 1; - } - - /* Check if default mask is allowed. */ - if (t->opcode_modifier.nodefmask - && (!i.mask || i.mask->mask->reg_num == 0)) - { - i.error = no_default_mask; - return 1; - } - - /* For VSIB byte, we need a vector register for index, and all vector - registers must be distinct. */ - if (t->opcode_modifier.vecsib) - { - if (!i.index_reg - || !((t->opcode_modifier.vecsib == VecSIB128 - && i.index_reg->reg_type.bitfield.regxmm) - || (t->opcode_modifier.vecsib == VecSIB256 - && i.index_reg->reg_type.bitfield.regymm) - || (t->opcode_modifier.vecsib == VecSIB512 - && i.index_reg->reg_type.bitfield.regzmm))) - { - i.error = invalid_vsib_address; - return 1; - } - - gas_assert (i.reg_operands == 2 || i.mask); - if (i.reg_operands == 2 && !i.mask) - { - gas_assert (i.types[0].bitfield.regxmm - || i.types[0].bitfield.regymm - || i.types[0].bitfield.regzmm); - gas_assert (i.types[2].bitfield.regxmm - || i.types[2].bitfield.regymm - || i.types[2].bitfield.regzmm); - if (operand_check == check_none) - return 0; - if (register_number (i.op[0].regs) - != register_number (i.index_reg) - && register_number (i.op[2].regs) - != register_number (i.index_reg) - && register_number (i.op[0].regs) - != register_number (i.op[2].regs)) - return 0; - if (operand_check == check_error) - { - i.error = invalid_vector_register_set; - return 1; - } - as_warn (_("mask, index, and destination registers should be distinct")); - } - } - - /* Check if broadcast is supported by the instruction and is applied - to the memory operand. */ - if (i.broadcast) - { - int broadcasted_opnd_size; - - /* Check if specified broadcast is supported in this instruction, - and it's applied to memory operand of DWORD or QWORD type, - depending on VecESize. */ - if (i.broadcast->type != t->opcode_modifier.broadcast - || !i.types[i.broadcast->operand].bitfield.mem - || (t->opcode_modifier.vecesize == 0 - && !i.types[i.broadcast->operand].bitfield.dword - && !i.types[i.broadcast->operand].bitfield.unspecified) - || (t->opcode_modifier.vecesize == 1 - && !i.types[i.broadcast->operand].bitfield.qword - && !i.types[i.broadcast->operand].bitfield.unspecified)) - goto bad_broadcast; - - broadcasted_opnd_size = t->opcode_modifier.vecesize ? 64 : 32; - if (i.broadcast->type == BROADCAST_1TO16) - broadcasted_opnd_size <<= 4; /* Broadcast 1to16. */ - else if (i.broadcast->type == BROADCAST_1TO8) - broadcasted_opnd_size <<= 3; /* Broadcast 1to8. */ - else - goto bad_broadcast; - - if ((broadcasted_opnd_size == 256 - && !t->operand_types[i.broadcast->operand].bitfield.ymmword) - || (broadcasted_opnd_size == 512 - && !t->operand_types[i.broadcast->operand].bitfield.zmmword)) - { - bad_broadcast: - i.error = unsupported_broadcast; - return 1; - } - } - /* If broadcast is supported in this instruction, we need to check if - operand of one-element size isn't specified without broadcast. */ - else if (t->opcode_modifier.broadcast && i.mem_operands) - { - /* Find memory operand. */ - for (op = 0; op < i.operands; op++) - if (operand_type_check (i.types[op], anymem)) - break; - gas_assert (op < i.operands); - /* Check size of the memory operand. */ - if ((t->opcode_modifier.vecesize == 0 - && i.types[op].bitfield.dword) - || (t->opcode_modifier.vecesize == 1 - && i.types[op].bitfield.qword)) - { - i.error = broadcast_needed; - return 1; - } - } - - /* Check if requested masking is supported. */ - if (i.mask - && (!t->opcode_modifier.masking - || (i.mask->zeroing - && t->opcode_modifier.masking == MERGING_MASKING))) - { - i.error = unsupported_masking; - return 1; - } - - /* Check if masking is applied to dest operand. */ - if (i.mask && (i.mask->operand != (int) (i.operands - 1))) - { - i.error = mask_not_on_destination; - return 1; - } - - /* Check RC/SAE. */ - if (i.rounding) - { - if ((i.rounding->type != saeonly - && !t->opcode_modifier.staticrounding) - || (i.rounding->type == saeonly - && (t->opcode_modifier.staticrounding - || !t->opcode_modifier.sae))) - { - i.error = unsupported_rc_sae; - return 1; - } - /* If the instruction has several immediate operands and one of - them is rounding, the rounding operand should be the last - immediate operand. */ - if (i.imm_operands > 1 - && i.rounding->operand != (int) (i.imm_operands - 1)) - { - i.error = rc_sae_operand_not_last_imm; - return 1; - } - } - - /* Check vector Disp8 operand. */ - if (t->opcode_modifier.disp8memshift) - { - if (i.broadcast) - i.memshift = t->opcode_modifier.vecesize ? 3 : 2; - else - i.memshift = t->opcode_modifier.disp8memshift; - - for (op = 0; op < i.operands; op++) - if (operand_type_check (i.types[op], disp) - && i.op[op].disps->X_op == O_constant) - { - offsetT value = i.op[op].disps->X_add_number; - int vec_disp8_ok = fits_in_vec_disp8 (value); - if (t->operand_types [op].bitfield.vec_disp8) - { - if (vec_disp8_ok) - i.types[op].bitfield.vec_disp8 = 1; - else - { - /* Vector insn can only have Vec_Disp8/Disp32 in - 32/64bit modes, and Vec_Disp8/Disp16 in 16bit - mode. */ - i.types[op].bitfield.disp8 = 0; - if (flag_code != CODE_16BIT) - i.types[op].bitfield.disp16 = 0; - } - } - else if (flag_code != CODE_16BIT) - { - /* One form of this instruction supports vector Disp8. - Try vector Disp8 if we need to use Disp32. */ - if (vec_disp8_ok && !fits_in_signed_byte (value)) - { - i.error = try_vector_disp8; - return 1; - } - } - } - } - else - i.memshift = -1; - - return 0; -} - -/* Check if operands are valid for the instruction. Update VEX - operand types. */ - -static int -VEX_check_operands (const insn_template *t) -{ - /* VREX is only valid with EVEX prefix. */ - if (i.need_vrex && !t->opcode_modifier.evex) - { - i.error = invalid_register_operand; - return 1; - } - - if (!t->opcode_modifier.vex) - return 0; - - /* Only check VEX_Imm4, which must be the first operand. */ - if (t->operand_types[0].bitfield.vec_imm4) - { - if (i.op[0].imms->X_op != O_constant - || !fits_in_imm4 (i.op[0].imms->X_add_number)) - { - i.error = bad_imm4; - return 1; - } - - /* Turn off Imm8 so that update_imm won't complain. */ - i.types[0] = vec_imm4; - } - - return 0; -} - -static const insn_template * -match_template (void) -{ - /* Points to template once we've found it. */ - const insn_template *t; - i386_operand_type overlap0, overlap1, overlap2, overlap3; - i386_operand_type overlap4; - unsigned int found_reverse_match; - i386_opcode_modifier suffix_check; - i386_operand_type operand_types [MAX_OPERANDS]; - int addr_prefix_disp; - unsigned int j; - unsigned int found_cpu_match; - unsigned int check_register; - enum i386_error specific_error = 0; - -#if MAX_OPERANDS != 5 -# error "MAX_OPERANDS must be 5." -#endif - - found_reverse_match = 0; - addr_prefix_disp = -1; - - memset (&suffix_check, 0, sizeof (suffix_check)); - if (i.suffix == BYTE_MNEM_SUFFIX) - suffix_check.no_bsuf = 1; - else if (i.suffix == WORD_MNEM_SUFFIX) - suffix_check.no_wsuf = 1; - else if (i.suffix == SHORT_MNEM_SUFFIX) - suffix_check.no_ssuf = 1; - else if (i.suffix == LONG_MNEM_SUFFIX) - suffix_check.no_lsuf = 1; - else if (i.suffix == QWORD_MNEM_SUFFIX) - suffix_check.no_qsuf = 1; - else if (i.suffix == LONG_DOUBLE_MNEM_SUFFIX) - suffix_check.no_ldsuf = 1; - - /* Must have right number of operands. */ - i.error = number_of_operands_mismatch; - - for (t = current_templates->start; t < current_templates->end; t++) - { - addr_prefix_disp = -1; - - if (i.operands != t->operands) - continue; - - /* Check processor support. */ - i.error = unsupported; - found_cpu_match = (cpu_flags_match (t) - == CPU_FLAGS_PERFECT_MATCH); - if (!found_cpu_match) - continue; - - /* Check old gcc support. */ - i.error = old_gcc_only; - if (!old_gcc && t->opcode_modifier.oldgcc) - continue; - - /* Check AT&T mnemonic. */ - i.error = unsupported_with_intel_mnemonic; - if (intel_mnemonic && t->opcode_modifier.attmnemonic) - continue; - - /* Check AT&T/Intel syntax. */ - i.error = unsupported_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. */ - i.error = invalid_instruction_suffix; - 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]; - - /* In general, don't allow 64-bit operands in 32-bit mode. */ - if (i.suffix == QWORD_MNEM_SUFFIX - && flag_code != CODE_64BIT - && (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[0].bitfield.regymm - && !operand_types[0].bitfield.regzmm) - || (!operand_types[t->operands > 1].bitfield.regmmx - && !!operand_types[t->operands > 1].bitfield.regxmm - && !!operand_types[t->operands > 1].bitfield.regymm - && !!operand_types[t->operands > 1].bitfield.regzmm)) - && (t->base_opcode != 0x0fc7 - || 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 - { - if (!t->operands) - /* We've found a match; break out of loop. */ - break; - } - - /* Address size prefix will turn Disp64/Disp32/Disp16 operand - into Disp32/Disp16/Disp32 operand. */ - if (i.prefix[ADDR_PREFIX] != 0) - { - /* There should be only one Disp operand. */ - switch (flag_code) - { - case CODE_16BIT: - for (j = 0; j < MAX_OPERANDS; j++) - { - if (operand_types[j].bitfield.disp16) - { - addr_prefix_disp = j; - operand_types[j].bitfield.disp32 = 1; - operand_types[j].bitfield.disp16 = 0; - break; - } - } - break; - case CODE_32BIT: - for (j = 0; j < MAX_OPERANDS; j++) - { - if (operand_types[j].bitfield.disp32) - { - addr_prefix_disp = j; - operand_types[j].bitfield.disp32 = 0; - operand_types[j].bitfield.disp16 = 1; - break; - } - } - break; - case CODE_64BIT: - for (j = 0; j < MAX_OPERANDS; j++) - { - if (operand_types[j].bitfield.disp64) - { - addr_prefix_disp = j; - operand_types[j].bitfield.disp64 = 0; - operand_types[j].bitfield.disp32 = 1; - break; - } - } - break; - } - } - - /* We check register size if needed. */ - check_register = t->opcode_modifier.checkregsize; - overlap0 = operand_type_and (i.types[0], operand_types[0]); - switch (t->operands) - { - case 1: - if (!operand_type_match (overlap0, i.types[0])) - continue; - break; - case 2: - /* xchg %eax, %eax is a special case. It is an aliase for nop - only in 32bit mode and we can use opcode 0x90. In 64bit - mode, we can't use 0x90 for xchg %eax, %eax since it should - zero-extend %eax to %rax. */ - if (flag_code == CODE_64BIT - && t->base_opcode == 0x90 - && operand_type_equal (&i.types [0], &acc32) - && operand_type_equal (&i.types [1], &acc32)) - continue; - if (i.swap_operand) - { - /* If we swap operand in encoding, we either match - the next one or reverse direction of operands. */ - if (t->opcode_modifier.s) - continue; - else if (t->opcode_modifier.d) - goto check_reverse; - } - - case 3: - /* If we swap operand in encoding, we match the next one. */ - if (i.swap_operand && t->opcode_modifier.s) - continue; - case 4: - case 5: - 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]) - || (check_register - && !operand_type_register_match (overlap0, i.types[0], - operand_types[0], - overlap1, i.types[1], - operand_types[1]))) - { - /* Check if other direction is valid ... */ - if (!t->opcode_modifier.d && !t->opcode_modifier.floatd) - continue; - -check_reverse: - /* Try reversing direction of operands. */ - overlap0 = operand_type_and (i.types[0], operand_types[1]); - 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]) - || (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; - } - /* found_reverse_match holds which of D or FloatDR - we've found. */ - if (t->opcode_modifier.d) - found_reverse_match = Opcode_D; - else if (t->opcode_modifier.floatd) - found_reverse_match = Opcode_FloatD; - else - found_reverse_match = 0; - if (t->opcode_modifier.floatr) - found_reverse_match |= Opcode_FloatR; - } - else - { - /* Found a forward 2 operand match here. */ - switch (t->operands) - { - case 5: - overlap4 = operand_type_and (i.types[4], - operand_types[4]); - case 4: - overlap3 = operand_type_and (i.types[3], - operand_types[3]); - case 3: - overlap2 = operand_type_and (i.types[2], - operand_types[2]); - break; - } - - switch (t->operands) - { - case 5: - if (!operand_type_match (overlap4, i.types[4]) - || !operand_type_register_match (overlap3, - i.types[3], - operand_types[3], - overlap4, - i.types[4], - operand_types[4])) - continue; - case 4: - if (!operand_type_match (overlap3, i.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 - reverse match 3 operand instructions, and all 3 - operand instructions only need to be checked for - register consistency between operands 2 and 3. */ - if (!operand_type_match (overlap2, i.types[2]) - || (check_register - && !operand_type_register_match (overlap1, - i.types[1], - operand_types[1], - overlap2, - i.types[2], - operand_types[2]))) - continue; - break; - } - } - /* Found either forward/reverse 2, 3 or 4 operand match here: - slip through to break. */ - } - if (!found_cpu_match) - { - found_reverse_match = 0; - continue; - } - - /* Check if vector and VEX operands are valid. */ - if (check_VecOperands (t) || VEX_check_operands (t)) - { - specific_error = i.error; - continue; - } - - /* We've found a match; break out of loop. */ - break; - } - - if (t == current_templates->end) - { - /* We found no match. */ - const char *err_msg; - switch (specific_error ? specific_error : i.error) - { - default: - abort (); - case operand_size_mismatch: - err_msg = _("operand size mismatch"); - break; - case operand_type_mismatch: - err_msg = _("operand type mismatch"); - break; - case register_type_mismatch: - err_msg = _("register type mismatch"); - break; - case number_of_operands_mismatch: - err_msg = _("number of operands mismatch"); - break; - case invalid_instruction_suffix: - err_msg = _("invalid instruction suffix"); - break; - case bad_imm4: - err_msg = _("constant doesn't fit in 4 bits"); - break; - case old_gcc_only: - err_msg = _("only supported with old gcc"); - break; - case unsupported_with_intel_mnemonic: - err_msg = _("unsupported with Intel mnemonic"); - break; - case unsupported_syntax: - err_msg = _("unsupported syntax"); - break; - case unsupported: - as_bad (_("unsupported instruction `%s'"), - current_templates->start->name); - return NULL; - case invalid_vsib_address: - err_msg = _("invalid VSIB address"); - break; - case invalid_vector_register_set: - err_msg = _("mask, index, and destination registers must be distinct"); - break; - case unsupported_vector_index_register: - err_msg = _("unsupported vector index register"); - break; - case unsupported_broadcast: - err_msg = _("unsupported broadcast"); - break; - case broadcast_not_on_src_operand: - err_msg = _("broadcast not on source memory operand"); - break; - case broadcast_needed: - err_msg = _("broadcast is needed for operand of such type"); - break; - case unsupported_masking: - err_msg = _("unsupported masking"); - break; - case mask_not_on_destination: - err_msg = _("mask not on destination operand"); - break; - case no_default_mask: - err_msg = _("default mask isn't allowed"); - break; - case unsupported_rc_sae: - err_msg = _("unsupported static rounding/sae"); - break; - case rc_sae_operand_not_last_imm: - if (intel_syntax) - err_msg = _("RC/SAE operand must precede immediate operands"); - else - err_msg = _("RC/SAE operand must follow immediate operands"); - break; - case invalid_register_operand: - err_msg = _("invalid register operand"); - break; - } - as_bad (_("%s for `%s'"), err_msg, - current_templates->start->name); - return NULL; - } - - if (!quiet_warnings) - { - if (!intel_syntax - && (i.types[0].bitfield.jumpabsolute - != operand_types[0].bitfield.jumpabsolute)) - { - as_warn (_("indirect %s without `*'"), t->name); - } - - if (t->opcode_modifier.isprefix - && t->opcode_modifier.ignoresize) - { - /* Warn them that a data or address size prefix doesn't - affect assembly of the next line of code. */ - as_warn (_("stand-alone `%s' prefix"), t->name); - } - } - - /* Copy the template we found. */ - i.tm = *t; - - if (addr_prefix_disp != -1) - i.tm.operand_types[addr_prefix_disp] - = operand_types[addr_prefix_disp]; - - if (found_reverse_match) - { - /* If we found a reverse match we must alter the opcode - direction bit. found_reverse_match holds bits to change - (different for int & float insns). */ - - i.tm.base_opcode ^= found_reverse_match; - - i.tm.operand_types[0] = operand_types[1]; - i.tm.operand_types[1] = operand_types[0]; - } - - return t; -} - -static int -check_string (void) -{ - int mem_op = operand_type_check (i.types[0], anymem) ? 0 : 1; - if (i.tm.operand_types[mem_op].bitfield.esseg) - { - if (i.seg[0] != NULL && i.seg[0] != &es) - { - as_bad (_("`%s' operand %d must use `%ses' segment"), - i.tm.name, - mem_op + 1, - register_prefix); - return 0; - } - /* There's only ever one segment override allowed per instruction. - This instruction possibly has a legal segment override on the - second operand, so copy the segment to where non-string - instructions store it, allowing common code. */ - i.seg[0] = i.seg[1]; - } - else if (i.tm.operand_types[mem_op + 1].bitfield.esseg) - { - if (i.seg[1] != NULL && i.seg[1] != &es) - { - as_bad (_("`%s' operand %d must use `%ses' segment"), - i.tm.name, - mem_op + 2, - register_prefix); - return 0; - } - } - return 1; -} - -static int -process_suffix (void) -{ - /* If matched instruction specifies an explicit instruction mnemonic - suffix, use it. */ - if (i.tm.opcode_modifier.size16) - i.suffix = WORD_MNEM_SUFFIX; - else if (i.tm.opcode_modifier.size32) - i.suffix = LONG_MNEM_SUFFIX; - else if (i.tm.opcode_modifier.size64) - i.suffix = QWORD_MNEM_SUFFIX; - else if (i.reg_operands) - { - /* If there's no instruction mnemonic suffix we try to invent one - based on register operands. */ - if (!i.suffix) - { - /* We take i.suffix from the last register operand specified, - Destination register type is more significant than source - register type. crc32 in SSE4.2 prefers source register - type. */ - if (i.tm.base_opcode == 0xf20f38f1) - { - if (i.types[0].bitfield.reg16) - i.suffix = WORD_MNEM_SUFFIX; - else if (i.types[0].bitfield.reg32) - i.suffix = LONG_MNEM_SUFFIX; - else if (i.types[0].bitfield.reg64) - i.suffix = QWORD_MNEM_SUFFIX; - } - else if (i.tm.base_opcode == 0xf20f38f0) - { - if (i.types[0].bitfield.reg8) - i.suffix = BYTE_MNEM_SUFFIX; - } - - if (!i.suffix) - { - int op; - - if (i.tm.base_opcode == 0xf20f38f1 - || i.tm.base_opcode == 0xf20f38f0) - { - /* We have to know the operand size for crc32. */ - as_bad (_("ambiguous memory operand size for `%s`"), - i.tm.name); - return 0; - } - - for (op = i.operands; --op >= 0;) - if (!i.tm.operand_types[op].bitfield.inoutportreg) - { - if (i.types[op].bitfield.reg8) - { - i.suffix = BYTE_MNEM_SUFFIX; - break; - } - else if (i.types[op].bitfield.reg16) - { - i.suffix = WORD_MNEM_SUFFIX; - break; - } - else if (i.types[op].bitfield.reg32) - { - i.suffix = LONG_MNEM_SUFFIX; - break; - } - else if (i.types[op].bitfield.reg64) - { - i.suffix = QWORD_MNEM_SUFFIX; - break; - } - } - } - } - else if (i.suffix == BYTE_MNEM_SUFFIX) - { - if (intel_syntax - && i.tm.opcode_modifier.ignoresize - && i.tm.opcode_modifier.no_bsuf) - i.suffix = 0; - else if (!check_byte_reg ()) - return 0; - } - else if (i.suffix == LONG_MNEM_SUFFIX) - { - if (intel_syntax - && i.tm.opcode_modifier.ignoresize - && i.tm.opcode_modifier.no_lsuf) - i.suffix = 0; - else if (!check_long_reg ()) - return 0; - } - else if (i.suffix == QWORD_MNEM_SUFFIX) - { - 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) - { - if (intel_syntax - && i.tm.opcode_modifier.ignoresize - && i.tm.opcode_modifier.no_wsuf) - i.suffix = 0; - else if (!check_word_reg ()) - return 0; - } - else if (i.suffix == XMMWORD_MNEM_SUFFIX - || i.suffix == YMMWORD_MNEM_SUFFIX - || i.suffix == ZMMWORD_MNEM_SUFFIX) - { - /* Skip if the instruction has x/y/z 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. */ - ; - else - abort (); - } - else if (i.tm.opcode_modifier.defaultsize - && !i.suffix - /* exclude fldenv/frstor/fsave/fstenv */ - && i.tm.opcode_modifier.no_ssuf) - { - i.suffix = stackop_size; - } - else if (intel_syntax - && !i.suffix - && (i.tm.operand_types[0].bitfield.jumpabsolute - || i.tm.opcode_modifier.jumpbyte - || i.tm.opcode_modifier.jumpintersegment - || (i.tm.base_opcode == 0x0f01 /* [ls][gi]dt */ - && i.tm.extension_opcode <= 3))) - { - switch (flag_code) - { - case CODE_64BIT: - if (!i.tm.opcode_modifier.no_qsuf) - { - i.suffix = QWORD_MNEM_SUFFIX; - break; - } - case CODE_32BIT: - if (!i.tm.opcode_modifier.no_lsuf) - i.suffix = LONG_MNEM_SUFFIX; - break; - case CODE_16BIT: - if (!i.tm.opcode_modifier.no_wsuf) - i.suffix = WORD_MNEM_SUFFIX; - break; - } - } - - if (!i.suffix) - { - if (!intel_syntax) - { - if (i.tm.opcode_modifier.w) - { - as_bad (_("no instruction mnemonic suffix given and " - "no register operands; can't size instruction")); - return 0; - } - } - else - { - unsigned int suffixes; - - suffixes = !i.tm.opcode_modifier.no_bsuf; - if (!i.tm.opcode_modifier.no_wsuf) - suffixes |= 1 << 1; - if (!i.tm.opcode_modifier.no_lsuf) - suffixes |= 1 << 2; - if (!i.tm.opcode_modifier.no_ldsuf) - suffixes |= 1 << 3; - if (!i.tm.opcode_modifier.no_ssuf) - suffixes |= 1 << 4; - if (!i.tm.opcode_modifier.no_qsuf) - suffixes |= 1 << 5; - - /* There are more than suffix matches. */ - if (i.tm.opcode_modifier.w - || ((suffixes & (suffixes - 1)) - && !i.tm.opcode_modifier.defaultsize - && !i.tm.opcode_modifier.ignoresize)) - { - as_bad (_("ambiguous operand size for `%s'"), i.tm.name); - return 0; - } - } - } - - /* 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 - && i.suffix != XMMWORD_MNEM_SUFFIX - && i.suffix != YMMWORD_MNEM_SUFFIX - && i.suffix != ZMMWORD_MNEM_SUFFIX) - { - /* It's not a byte, select word/dword operation. */ - if (i.tm.opcode_modifier.w) - { - if (i.tm.opcode_modifier.shortform) - i.tm.base_opcode |= 8; - else - i.tm.base_opcode |= 1; - } - - /* Now select between word & dword operations via the operand - size prefix, except for instructions that will ignore this - prefix anyway. */ - 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 - && i.op->regs[0].reg_type.bitfield.reg32)) - if (!add_prefix (ADDR_PREFIX_OPCODE)) - return 0; - } - else if (i.suffix != QWORD_MNEM_SUFFIX - && i.suffix != LONG_DOUBLE_MNEM_SUFFIX - && !i.tm.opcode_modifier.ignoresize - && !i.tm.opcode_modifier.floatmf - && ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT) - || (flag_code == CODE_64BIT - && i.tm.opcode_modifier.jumpbyte))) - { - unsigned int prefix = DATA_PREFIX_OPCODE; - - if (i.tm.opcode_modifier.jumpbyte) /* jcxz, loop */ - prefix = ADDR_PREFIX_OPCODE; - - if (!add_prefix (prefix)) - return 0; - } - - /* Set mode64 for an operand. */ - if (i.suffix == QWORD_MNEM_SUFFIX - && flag_code == CODE_64BIT - && !i.tm.opcode_modifier.norex64) - { - /* Special case for xchg %rax,%rax. It is NOP and doesn't - need rex64. cmpxchg8b is also a special case. */ - if (! (i.operands == 2 - && i.tm.base_opcode == 0x90 - && i.tm.extension_opcode == None - && 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 - && !operand_type_check (i.types [0], reg) - && operand_type_check (i.types [0], anymem))) - i.rex |= REX_W; - } - - /* Size floating point instruction. */ - if (i.suffix == LONG_MNEM_SUFFIX) - if (i.tm.opcode_modifier.floatmf) - i.tm.base_opcode ^= 4; - } - - return 1; -} - -static int -check_byte_reg (void) -{ - int op; - - for (op = i.operands; --op >= 0;) - { - /* If this is an eight bit register, it's OK. If it's the 16 or - 32 bit version of an eight bit register, we will just use the - low portion, and that's OK too. */ - if (i.types[op].bitfield.reg8) - continue; - - /* I/O port address operands are OK too. */ - if (i.tm.operand_types[op].bitfield.inoutportreg) - continue; - - /* crc32 doesn't generate this warning. */ - if (i.tm.base_opcode == 0xf20f38f0) - continue; - - if ((i.types[op].bitfield.reg16 - || i.types[op].bitfield.reg32 - || i.types[op].bitfield.reg64) - && i.op[op].regs->reg_num < 4 - /* Prohibit these changes in 64bit mode, since the lowering - would be more complicated. */ - && flag_code != CODE_64BIT) - { -#if REGISTER_WARNINGS - if (!quiet_warnings) - as_warn (_("using `%s%s' instead of `%s%s' due to `%c' suffix"), - register_prefix, - (i.op[op].regs + (i.types[op].bitfield.reg16 - ? REGNAM_AL - REGNAM_AX - : REGNAM_AL - REGNAM_EAX))->reg_name, - register_prefix, - i.op[op].regs->reg_name, - i.suffix); -#endif - continue; - } - /* Any other register is bad. */ - if (i.types[op].bitfield.reg16 - || i.types[op].bitfield.reg32 - || i.types[op].bitfield.reg64 - || i.types[op].bitfield.regmmx - || i.types[op].bitfield.regxmm - || i.types[op].bitfield.regymm - || i.types[op].bitfield.regzmm - || i.types[op].bitfield.sreg2 - || i.types[op].bitfield.sreg3 - || i.types[op].bitfield.control - || i.types[op].bitfield.debug - || i.types[op].bitfield.test - || i.types[op].bitfield.floatreg - || i.types[op].bitfield.floatacc) - { - as_bad (_("`%s%s' not allowed with `%s%c'"), - register_prefix, - i.op[op].regs->reg_name, - i.tm.name, - i.suffix); - return 0; - } - } - return 1; -} - -static int -check_long_reg (void) -{ - int op; - - for (op = i.operands; --op >= 0;) - /* Reject eight bit registers, except where the template requires - them. (eg. movzb) */ - if (i.types[op].bitfield.reg8 - && (i.tm.operand_types[op].bitfield.reg16 - || i.tm.operand_types[op].bitfield.reg32 - || i.tm.operand_types[op].bitfield.acc)) - { - as_bad (_("`%s%s' not allowed with `%s%c'"), - register_prefix, - i.op[op].regs->reg_name, - i.tm.name, - i.suffix); - return 0; - } - /* Warn if the e prefix on a general reg is missing. */ - else if ((!quiet_warnings || flag_code == CODE_64BIT) - && i.types[op].bitfield.reg16 - && (i.tm.operand_types[op].bitfield.reg32 - || i.tm.operand_types[op].bitfield.acc)) - { - /* Prohibit these changes in the 64bit mode, since the - lowering is more complicated. */ - if (flag_code == CODE_64BIT) - { - as_bad (_("incorrect register `%s%s' used with `%c' suffix"), - register_prefix, i.op[op].regs->reg_name, - i.suffix); - return 0; - } -#if REGISTER_WARNINGS - else - as_warn (_("using `%s%s' instead of `%s%s' due to `%c' suffix"), - register_prefix, - (i.op[op].regs + REGNAM_EAX - REGNAM_AX)->reg_name, - register_prefix, - i.op[op].regs->reg_name, - i.suffix); -#endif - } - /* Warn if the r prefix on a general reg is missing. */ - else if (i.types[op].bitfield.reg64 - && (i.tm.operand_types[op].bitfield.reg32 - || i.tm.operand_types[op].bitfield.acc)) - { - if (intel_syntax - && i.tm.opcode_modifier.toqword - && !i.types[0].bitfield.regxmm) - { - /* Convert to QWORD. We want REX byte. */ - i.suffix = QWORD_MNEM_SUFFIX; - } - else - { - as_bad (_("incorrect register `%s%s' used with `%c' suffix"), - register_prefix, i.op[op].regs->reg_name, - i.suffix); - return 0; - } - } - return 1; -} - -static int -check_qword_reg (void) -{ - int op; - - for (op = i.operands; --op >= 0; ) - /* Reject eight bit registers, except where the template requires - them. (eg. movzb) */ - if (i.types[op].bitfield.reg8 - && (i.tm.operand_types[op].bitfield.reg16 - || i.tm.operand_types[op].bitfield.reg32 - || i.tm.operand_types[op].bitfield.acc)) - { - as_bad (_("`%s%s' not allowed with `%s%c'"), - register_prefix, - i.op[op].regs->reg_name, - i.tm.name, - i.suffix); - return 0; - } - /* Warn if the e prefix on a general reg is missing. */ - else if ((i.types[op].bitfield.reg16 - || i.types[op].bitfield.reg32) - && (i.tm.operand_types[op].bitfield.reg32 - || i.tm.operand_types[op].bitfield.acc)) - { - /* Prohibit these changes in the 64bit mode, since the - lowering is more complicated. */ - if (intel_syntax - && i.tm.opcode_modifier.todword - && !i.types[0].bitfield.regxmm) - { - /* Convert to DWORD. We don't want REX byte. */ - i.suffix = LONG_MNEM_SUFFIX; - } - else - { - as_bad (_("incorrect register `%s%s' used with `%c' suffix"), - register_prefix, i.op[op].regs->reg_name, - i.suffix); - return 0; - } - } - return 1; -} - -static int -check_word_reg (void) -{ - int op; - for (op = i.operands; --op >= 0;) - /* Reject eight bit registers, except where the template requires - them. (eg. movzb) */ - if (i.types[op].bitfield.reg8 - && (i.tm.operand_types[op].bitfield.reg16 - || i.tm.operand_types[op].bitfield.reg32 - || i.tm.operand_types[op].bitfield.acc)) - { - as_bad (_("`%s%s' not allowed with `%s%c'"), - register_prefix, - i.op[op].regs->reg_name, - i.tm.name, - i.suffix); - return 0; - } - /* Warn if the e prefix on a general reg is present. */ - else if ((!quiet_warnings || flag_code == CODE_64BIT) - && i.types[op].bitfield.reg32 - && (i.tm.operand_types[op].bitfield.reg16 - || i.tm.operand_types[op].bitfield.acc)) - { - /* Prohibit these changes in the 64bit mode, since the - lowering is more complicated. */ - if (flag_code == CODE_64BIT) - { - as_bad (_("incorrect register `%s%s' used with `%c' suffix"), - register_prefix, i.op[op].regs->reg_name, - i.suffix); - return 0; - } - else -#if REGISTER_WARNINGS - as_warn (_("using `%s%s' instead of `%s%s' due to `%c' suffix"), - register_prefix, - (i.op[op].regs + REGNAM_AX - REGNAM_EAX)->reg_name, - register_prefix, - i.op[op].regs->reg_name, - i.suffix); -#endif - } - return 1; -} - -static int -update_imm (unsigned int j) -{ - i386_operand_type overlap = i.types[j]; - if ((overlap.bitfield.imm8 - || overlap.bitfield.imm8s - || overlap.bitfield.imm16 - || overlap.bitfield.imm32 - || overlap.bitfield.imm32s - || overlap.bitfield.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; - - operand_type_set (&temp, 0); - if (i.suffix == BYTE_MNEM_SUFFIX) - { - temp.bitfield.imm8 = overlap.bitfield.imm8; - temp.bitfield.imm8s = overlap.bitfield.imm8s; - } - else if (i.suffix == WORD_MNEM_SUFFIX) - temp.bitfield.imm16 = overlap.bitfield.imm16; - else if (i.suffix == QWORD_MNEM_SUFFIX) - { - temp.bitfield.imm64 = overlap.bitfield.imm64; - temp.bitfield.imm32s = overlap.bitfield.imm32s; - } - else - temp.bitfield.imm32 = overlap.bitfield.imm32; - overlap = temp; - } - else if (operand_type_equal (&overlap, &imm16_32_32s) - || operand_type_equal (&overlap, &imm16_32) - || operand_type_equal (&overlap, &imm16_32s)) - { - if ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0)) - overlap = imm16; - else - overlap = imm32s; - } - 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")); - return 0; - } - } - i.types[j] = overlap; - - return 1; -} - -static int -finalize_imm (void) -{ - unsigned int j, n; - - /* Update the first 2 immediate operands. */ - n = i.operands > 2 ? 2 : i.operands; - if (n) - { - for (j = 0; j < n; j++) - if (update_imm (j) == 0) - return 0; - - /* The 3rd operand can't be immediate operand. */ - gas_assert (operand_type_check (i.types[2], imm) == 0); - } - - return 1; -} - -static int -bad_implicit_operand (int xmm) -{ - const char *ireg = xmm ? "xmm0" : "ymm0"; - - if (intel_syntax) - as_bad (_("the last operand of `%s' must be `%s%s'"), - i.tm.name, register_prefix, ireg); - else - as_bad (_("the first operand of `%s' must be `%s%s'"), - i.tm.name, register_prefix, ireg); - return 0; -} - -static int -process_operands (void) -{ - /* Default segment register this instruction will use for memory - accesses. 0 means unknown. This is only for optimizing out - unnecessary segment overrides. */ - const seg_entry *default_seg = 0; - - if (i.tm.opcode_modifier.sse2avx && i.tm.opcode_modifier.vexvvvv) - { - unsigned int dupl = i.operands; - unsigned int dest = dupl - 1; - unsigned int j; - - /* The destination must be an xmm register. */ - gas_assert (i.reg_operands - && MAX_OPERANDS > dupl - && operand_type_equal (&i.types[dest], ®xmm)); - - if (i.tm.opcode_modifier.firstxmm0) - { - /* The first operand is implicit and must be xmm0. */ - gas_assert (operand_type_equal (&i.types[0], ®xmm)); - if (register_number (i.op[0].regs) != 0) - return bad_implicit_operand (1); - - if (i.tm.opcode_modifier.vexsources == VEX3SOURCES) - { - /* Keep xmm0 for instructions with VEX prefix and 3 - sources. */ - goto duplicate; - } - else - { - /* We remove the first xmm0 and keep the number of - operands unchanged, which in fact duplicates the - destination. */ - for (j = 1; j < i.operands; j++) - { - i.op[j - 1] = i.op[j]; - i.types[j - 1] = i.types[j]; - i.tm.operand_types[j - 1] = i.tm.operand_types[j]; - } - } - } - else if (i.tm.opcode_modifier.implicit1stxmm0) - { - gas_assert ((MAX_OPERANDS - 1) > dupl - && (i.tm.opcode_modifier.vexsources - == VEX3SOURCES)); - - /* Add the implicit xmm0 for instructions with VEX prefix - and 3 sources. */ - for (j = i.operands; j > 0; j--) - { - i.op[j] = i.op[j - 1]; - i.types[j] = i.types[j - 1]; - i.tm.operand_types[j] = i.tm.operand_types[j - 1]; - } - i.op[0].regs - = (const reg_entry *) hash_find (reg_hash, "xmm0"); - i.types[0] = regxmm; - i.tm.operand_types[0] = regxmm; - - i.operands += 2; - i.reg_operands += 2; - i.tm.operands += 2; - - dupl++; - dest++; - i.op[dupl] = i.op[dest]; - i.types[dupl] = i.types[dest]; - i.tm.operand_types[dupl] = i.tm.operand_types[dest]; - } - else - { -duplicate: - i.operands++; - i.reg_operands++; - i.tm.operands++; - - i.op[dupl] = i.op[dest]; - i.types[dupl] = i.types[dest]; - i.tm.operand_types[dupl] = i.tm.operand_types[dest]; - } - - if (i.tm.opcode_modifier.immext) - process_immext (); - } - else if (i.tm.opcode_modifier.firstxmm0) - { - unsigned int j; - - /* The first operand is implicit and must be xmm0/ymm0/zmm0. */ - gas_assert (i.reg_operands - && (operand_type_equal (&i.types[0], ®xmm) - || operand_type_equal (&i.types[0], ®ymm) - || operand_type_equal (&i.types[0], ®zmm))); - if (register_number (i.op[0].regs) != 0) - return bad_implicit_operand (i.types[0].bitfield.regxmm); - - 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. */ - gas_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) - { - if (i.types[0].bitfield.sreg2 - || i.types[0].bitfield.sreg3) - { - if (i.tm.base_opcode == POP_SEG_SHORT - && i.op[0].regs->reg_num == 1) - { - as_bad (_("you can't `pop %scs'"), register_prefix); - return 0; - } - i.tm.base_opcode |= (i.op[0].regs->reg_num << 3); - if ((i.op[0].regs->reg_flags & RegRex) != 0) - i.rex |= REX_B; - } - else - { - /* The register or float register operand is in operand - 0 or 1. */ - unsigned int op; - - if (i.types[0].bitfield.floatreg - || operand_type_check (i.types[0], reg)) - op = 0; - else - op = 1; - /* Register goes in low 3 bits of opcode. */ - i.tm.base_opcode |= i.op[op].regs->reg_num; - if ((i.op[op].regs->reg_flags & RegRex) != 0) - i.rex |= REX_B; - if (!quiet_warnings && i.tm.opcode_modifier.ugh) - { - /* Warn about some common errors, but press on regardless. - The first case can be generated by gcc (<= 2.8.1). */ - if (i.operands == 2) - { - /* Reversed arguments on faddp, fsubp, etc. */ - as_warn (_("translating to `%s %s%s,%s%s'"), i.tm.name, - register_prefix, i.op[!intel_syntax].regs->reg_name, - register_prefix, i.op[intel_syntax].regs->reg_name); - } - else - { - /* Extraneous `l' suffix on fp insn. */ - as_warn (_("translating to `%s %s%s'"), i.tm.name, - register_prefix, i.op[0].regs->reg_name); - } - } - } - } - else if (i.tm.opcode_modifier.modrm) - { - /* The opcode is completed (modulo i.tm.extension_opcode which - must be put into the modrm byte). Now, we make the modrm and - index base bytes based on all the info we've collected. */ - - default_seg = build_modrm_byte (); - } - else if ((i.tm.base_opcode & ~0x3) == MOV_AX_DISP32) - { - default_seg = &ds; - } - else if (i.tm.opcode_modifier.isstring) - { - /* For the string instructions that allow a segment override - on one of their operands, the default segment is ds. */ - default_seg = &ds; - } - - if (i.tm.base_opcode == 0x8d /* lea */ - && i.seg[0] - && !quiet_warnings) - as_warn (_("segment override on `%s' is ineffectual"), i.tm.name); - - /* If a segment was explicitly specified, and the specified segment - is not the default, use an opcode prefix to select it. If we - never figured out what the default segment is, then default_seg - will be zero at this point, and the specified segment prefix will - always be used. */ - if ((i.seg[0]) && (i.seg[0] != default_seg)) - { - if (!add_prefix (i.seg[0]->seg_prefix)) - return 0; - } - return 1; -} - -static const seg_entry * -build_modrm_byte (void) -{ - const seg_entry *default_seg = 0; - unsigned int source, dest; - int vex_3_sources; - - /* The first operand of instructions with VEX prefix and 3 sources - must be VEX_Imm4. */ - vex_3_sources = i.tm.opcode_modifier.vexsources == VEX3SOURCES; - if (vex_3_sources) - { - unsigned int nds, reg_slot; - expressionS *exp; - - if (i.tm.opcode_modifier.veximmext - && i.tm.opcode_modifier.immext) - { - dest = i.operands - 2; - gas_assert (dest == 3); - } - else - dest = i.operands - 1; - nds = dest - 1; - - /* There are 2 kinds of instructions: - 1. 5 operands: 4 register operands or 3 register operands - plus 1 memory operand plus one Vec_Imm4 operand, VexXDS, and - VexW0 or VexW1. The destination must be either XMM, YMM or - ZMM register. - 2. 4 operands: 4 register operands or 3 register operands - plus 1 memory operand, VexXDS, and VexImmExt */ - gas_assert ((i.reg_operands == 4 - || (i.reg_operands == 3 && i.mem_operands == 1)) - && i.tm.opcode_modifier.vexvvvv == VEXXDS - && (i.tm.opcode_modifier.veximmext - || (i.imm_operands == 1 - && i.types[0].bitfield.vec_imm4 - && (i.tm.opcode_modifier.vexw == VEXW0 - || i.tm.opcode_modifier.vexw == VEXW1) - && (operand_type_equal (&i.tm.operand_types[dest], ®xmm) - || operand_type_equal (&i.tm.operand_types[dest], ®ymm) - || operand_type_equal (&i.tm.operand_types[dest], ®zmm))))); - - if (i.imm_operands == 0) - { - /* When there is no immediate operand, generate an 8bit - immediate operand to encode the first operand. */ - exp = &im_expressions[i.imm_operands++]; - i.op[i.operands].imms = exp; - i.types[i.operands] = imm8; - i.operands++; - /* If VexW1 is set, the first operand is the source and - the second operand is encoded in the immediate operand. */ - if (i.tm.opcode_modifier.vexw == VEXW1) - { - source = 0; - reg_slot = 1; - } - else - { - source = 1; - reg_slot = 0; - } - - /* FMA swaps REG and NDS. */ - if (i.tm.cpu_flags.bitfield.cpufma) - { - unsigned int tmp; - tmp = reg_slot; - reg_slot = nds; - nds = tmp; - } - - gas_assert (operand_type_equal (&i.tm.operand_types[reg_slot], - ®xmm) - || operand_type_equal (&i.tm.operand_types[reg_slot], - ®ymm) - || operand_type_equal (&i.tm.operand_types[reg_slot], - ®zmm)); - exp->X_op = O_constant; - exp->X_add_number = register_number (i.op[reg_slot].regs) << 4; - gas_assert ((i.op[reg_slot].regs->reg_flags & RegVRex) == 0); - } - else - { - unsigned int imm_slot; - - if (i.tm.opcode_modifier.vexw == VEXW0) - { - /* If VexW0 is set, the third operand is the source and - the second operand is encoded in the immediate - operand. */ - source = 2; - reg_slot = 1; - } - else - { - /* VexW1 is set, the second operand is the source and - the third operand is encoded in the immediate - operand. */ - source = 1; - reg_slot = 2; - } - - if (i.tm.opcode_modifier.immext) - { - /* When ImmExt is set, the immdiate byte is the last - operand. */ - imm_slot = i.operands - 1; - source--; - reg_slot--; - } - else - { - imm_slot = 0; - - /* Turn on Imm8 so that output_imm will generate it. */ - i.types[imm_slot].bitfield.imm8 = 1; - } - - gas_assert (operand_type_equal (&i.tm.operand_types[reg_slot], - ®xmm) - || operand_type_equal (&i.tm.operand_types[reg_slot], - ®ymm) - || operand_type_equal (&i.tm.operand_types[reg_slot], - ®zmm)); - i.op[imm_slot].imms->X_add_number - |= register_number (i.op[reg_slot].regs) << 4; - gas_assert ((i.op[reg_slot].regs->reg_flags & RegVRex) == 0); - } - - gas_assert (operand_type_equal (&i.tm.operand_types[nds], ®xmm) - || operand_type_equal (&i.tm.operand_types[nds], - ®ymm) - || operand_type_equal (&i.tm.operand_types[nds], - ®zmm)); - i.vex.register_specifier = i.op[nds].regs; - } - else - source = dest = 0; - - /* i.reg_operands MUST be the number of real register operands; - implicit registers do not count. If there are 3 register - operands, it must be a instruction with VexNDS. For a - instruction with VexNDD, the destination register is encoded - in VEX prefix. If there are 4 register operands, it must be - a instruction with VEX prefix and 3 sources. */ - if (i.mem_operands == 0 - && ((i.reg_operands == 2 - && i.tm.opcode_modifier.vexvvvv <= VEXXDS) - || (i.reg_operands == 3 - && i.tm.opcode_modifier.vexvvvv == VEXXDS) - || (i.reg_operands == 4 && vex_3_sources))) - { - switch (i.operands) - { - case 2: - source = 0; - break; - case 3: - /* When there are 3 operands, one of them may be immediate, - which may be the first or the last operand. Otherwise, - the first operand must be shift count register (cl) or it - is an instruction with VexNDS. */ - gas_assert (i.imm_operands == 1 - || (i.imm_operands == 0 - && (i.tm.opcode_modifier.vexvvvv == VEXXDS - || i.types[0].bitfield.shiftcount))); - if (operand_type_check (i.types[0], imm) - || i.types[0].bitfield.shiftcount) - source = 1; - else - source = 0; - break; - case 4: - /* When there are 4 operands, the first two must be 8bit - immediate operands. The source operand will be the 3rd - one. - - For instructions with VexNDS, if the first operand - an imm8, the source operand is the 2nd one. If the last - operand is imm8, the source operand is the first one. */ - gas_assert ((i.imm_operands == 2 - && i.types[0].bitfield.imm8 - && i.types[1].bitfield.imm8) - || (i.tm.opcode_modifier.vexvvvv == VEXXDS - && i.imm_operands == 1 - && (i.types[0].bitfield.imm8 - || i.types[i.operands - 1].bitfield.imm8 - || i.rounding))); - if (i.imm_operands == 2) - source = 2; - else - { - if (i.types[0].bitfield.imm8) - source = 1; - else - source = 0; - } - break; - case 5: - if (i.tm.opcode_modifier.evex) - { - /* For EVEX instructions, when there are 5 operands, the - first one must be immediate operand. If the second one - is immediate operand, the source operand is the 3th - one. If the last one is immediate operand, the source - operand is the 2nd one. */ - gas_assert (i.imm_operands == 2 - && i.tm.opcode_modifier.sae - && operand_type_check (i.types[0], imm)); - if (operand_type_check (i.types[1], imm)) - source = 2; - else if (operand_type_check (i.types[4], imm)) - source = 1; - else - abort (); - } - break; - default: - abort (); - } - - if (!vex_3_sources) - { - dest = source + 1; - - /* RC/SAE operand could be between DEST and SRC. That happens - when one operand is GPR and the other one is XMM/YMM/ZMM - register. */ - if (i.rounding && i.rounding->operand == (int) dest) - dest++; - - if (i.tm.opcode_modifier.vexvvvv == VEXXDS) - { - /* For instructions with VexNDS, the register-only source - operand must be 32/64bit integer, XMM, YMM or ZMM - register. It is encoded in VEX prefix. We need to - clear RegMem bit before calling operand_type_equal. */ - - i386_operand_type op; - unsigned int vvvv; - - /* Check register-only source operand when two source - operands are swapped. */ - if (!i.tm.operand_types[source].bitfield.baseindex - && i.tm.operand_types[dest].bitfield.baseindex) - { - vvvv = source; - source = dest; - } - else - vvvv = dest; - - op = i.tm.operand_types[vvvv]; - op.bitfield.regmem = 0; - if ((dest + 1) >= i.operands - || (op.bitfield.reg32 != 1 - && !op.bitfield.reg64 != 1 - && !operand_type_equal (&op, ®xmm) - && !operand_type_equal (&op, ®ymm) - && !operand_type_equal (&op, ®zmm) - && !operand_type_equal (&op, ®mask))) - abort (); - i.vex.register_specifier = i.op[vvvv].regs; - dest++; - } - } - - i.rm.mode = 3; - /* One of the register operands will be encoded in the i.tm.reg - field, the other in the combined i.tm.mode and i.tm.regmem - fields. If no form of this instruction supports a memory - destination operand, then we assume the source operand may - sometimes be a memory operand and so we need to store the - destination in the i.rm.reg field. */ - if (!i.tm.operand_types[dest].bitfield.regmem - && operand_type_check (i.tm.operand_types[dest], anymem) == 0) - { - i.rm.reg = i.op[dest].regs->reg_num; - i.rm.regmem = i.op[source].regs->reg_num; - if ((i.op[dest].regs->reg_flags & RegRex) != 0) - i.rex |= REX_R; - if ((i.op[dest].regs->reg_flags & RegVRex) != 0) - i.vrex |= REX_R; - if ((i.op[source].regs->reg_flags & RegRex) != 0) - i.rex |= REX_B; - if ((i.op[source].regs->reg_flags & RegVRex) != 0) - i.vrex |= REX_B; - } - else - { - i.rm.reg = i.op[source].regs->reg_num; - i.rm.regmem = i.op[dest].regs->reg_num; - if ((i.op[dest].regs->reg_flags & RegRex) != 0) - i.rex |= REX_B; - if ((i.op[dest].regs->reg_flags & RegVRex) != 0) - i.vrex |= REX_B; - if ((i.op[source].regs->reg_flags & RegRex) != 0) - i.rex |= REX_R; - if ((i.op[source].regs->reg_flags & RegVRex) != 0) - i.vrex |= REX_R; - } - if (flag_code != CODE_64BIT && (i.rex & (REX_R | REX_B))) - { - if (!i.types[0].bitfield.control - && !i.types[1].bitfield.control) - abort (); - i.rex &= ~(REX_R | REX_B); - add_prefix (LOCK_PREFIX_OPCODE); - } - } - else - { /* If it's not 2 reg operands... */ - unsigned int mem; - - if (i.mem_operands) - { - unsigned int fake_zero_displacement = 0; - unsigned int op; - - for (op = 0; op < i.operands; op++) - if (operand_type_check (i.types[op], anymem)) - break; - gas_assert (op < i.operands); - - if (i.tm.opcode_modifier.vecsib) - { - if (i.index_reg->reg_num == RegEiz - || i.index_reg->reg_num == RegRiz) - abort (); - - i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; - if (!i.base_reg) - { - i.sib.base = NO_BASE_REGISTER; - i.sib.scale = i.log2_scale_factor; - /* No Vec_Disp8 if there is no base. */ - i.types[op].bitfield.vec_disp8 = 0; - i.types[op].bitfield.disp8 = 0; - i.types[op].bitfield.disp16 = 0; - i.types[op].bitfield.disp64 = 0; - if (flag_code != CODE_64BIT) - { - /* Must be 32 bit */ - i.types[op].bitfield.disp32 = 1; - i.types[op].bitfield.disp32s = 0; - } - else - { - i.types[op].bitfield.disp32 = 0; - i.types[op].bitfield.disp32s = 1; - } - } - i.sib.index = i.index_reg->reg_num; - if ((i.index_reg->reg_flags & RegRex) != 0) - i.rex |= REX_X; - if ((i.index_reg->reg_flags & RegVRex) != 0) - i.vrex |= REX_X; - } - - default_seg = &ds; - - if (i.base_reg == 0) - { - i.rm.mode = 0; - if (!i.disp_operands) - { - fake_zero_displacement = 1; - /* Instructions with VSIB byte need 32bit displacement - if there is no base register. */ - if (i.tm.opcode_modifier.vecsib) - i.types[op].bitfield.disp32 = 1; - } - if (i.index_reg == 0) - { - gas_assert (!i.tm.opcode_modifier.vecsib); - /* Operand is just <disp> */ - if (flag_code == CODE_64BIT) - { - /* 64bit mode overwrites the 32bit absolute - addressing by RIP relative addressing and - absolute addressing is encoded by one of the - redundant SIB forms. */ - i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; - i.sib.base = NO_BASE_REGISTER; - i.sib.index = NO_INDEX_REGISTER; - i.types[op] = ((i.prefix[ADDR_PREFIX] == 0) - ? disp32s : disp32); - } - else if ((flag_code == CODE_16BIT) - ^ (i.prefix[ADDR_PREFIX] != 0)) - { - i.rm.regmem = NO_BASE_REGISTER_16; - i.types[op] = disp16; - } - else - { - i.rm.regmem = NO_BASE_REGISTER; - i.types[op] = disp32; - } - } - else if (!i.tm.opcode_modifier.vecsib) - { - /* !i.base_reg && i.index_reg */ - if (i.index_reg->reg_num == RegEiz - || i.index_reg->reg_num == RegRiz) - i.sib.index = NO_INDEX_REGISTER; - else - i.sib.index = i.index_reg->reg_num; - i.sib.base = NO_BASE_REGISTER; - i.sib.scale = i.log2_scale_factor; - i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; - /* No Vec_Disp8 if there is no base. */ - i.types[op].bitfield.vec_disp8 = 0; - i.types[op].bitfield.disp8 = 0; - i.types[op].bitfield.disp16 = 0; - i.types[op].bitfield.disp64 = 0; - if (flag_code != CODE_64BIT) - { - /* Must be 32 bit */ - i.types[op].bitfield.disp32 = 1; - i.types[op].bitfield.disp32s = 0; - } - else - { - i.types[op].bitfield.disp32 = 0; - i.types[op].bitfield.disp32s = 1; - } - if ((i.index_reg->reg_flags & RegRex) != 0) - i.rex |= REX_X; - } - } - /* RIP addressing for 64bit mode. */ - else if (i.base_reg->reg_num == RegRip || - i.base_reg->reg_num == RegEip) - { - gas_assert (!i.tm.opcode_modifier.vecsib); - i.rm.regmem = NO_BASE_REGISTER; - i.types[op].bitfield.disp8 = 0; - i.types[op].bitfield.disp16 = 0; - i.types[op].bitfield.disp32 = 0; - i.types[op].bitfield.disp32s = 1; - i.types[op].bitfield.disp64 = 0; - i.types[op].bitfield.vec_disp8 = 0; - i.flags[op] |= Operand_PCrel; - if (! i.disp_operands) - fake_zero_displacement = 1; - } - else if (i.base_reg->reg_type.bitfield.reg16) - { - gas_assert (!i.tm.opcode_modifier.vecsib); - switch (i.base_reg->reg_num) - { - case 3: /* (%bx) */ - if (i.index_reg == 0) - i.rm.regmem = 7; - else /* (%bx,%si) -> 0, or (%bx,%di) -> 1 */ - i.rm.regmem = i.index_reg->reg_num - 6; - break; - case 5: /* (%bp) */ - default_seg = &ss; - if (i.index_reg == 0) - { - i.rm.regmem = 6; - if (operand_type_check (i.types[op], disp) == 0) - { - /* fake (%bp) into 0(%bp) */ - if (i.tm.operand_types[op].bitfield.vec_disp8) - i.types[op].bitfield.vec_disp8 = 1; - else - i.types[op].bitfield.disp8 = 1; - fake_zero_displacement = 1; - } - } - else /* (%bp,%si) -> 2, or (%bp,%di) -> 3 */ - i.rm.regmem = i.index_reg->reg_num - 6 + 2; - break; - default: /* (%si) -> 4 or (%di) -> 5 */ - i.rm.regmem = i.base_reg->reg_num - 6 + 4; - } - i.rm.mode = mode_from_disp_size (i.types[op]); - } - else /* i.base_reg and 32/64 bit mode */ - { - if (flag_code == CODE_64BIT - && operand_type_check (i.types[op], disp)) - { - i386_operand_type temp; - operand_type_set (&temp, 0); - temp.bitfield.disp8 = i.types[op].bitfield.disp8; - temp.bitfield.vec_disp8 - = i.types[op].bitfield.vec_disp8; - i.types[op] = temp; - if (i.prefix[ADDR_PREFIX] == 0) - i.types[op].bitfield.disp32s = 1; - else - i.types[op].bitfield.disp32 = 1; - } - - if (!i.tm.opcode_modifier.vecsib) - i.rm.regmem = i.base_reg->reg_num; - if ((i.base_reg->reg_flags & RegRex) != 0) - i.rex |= REX_B; - i.sib.base = i.base_reg->reg_num; - /* x86-64 ignores REX prefix bit here to avoid decoder - complications. */ - if (!(i.base_reg->reg_flags & RegRex) - && (i.base_reg->reg_num == EBP_REG_NUM - || i.base_reg->reg_num == ESP_REG_NUM)) - default_seg = &ss; - if (i.base_reg->reg_num == 5 && i.disp_operands == 0) - { - fake_zero_displacement = 1; - if (i.tm.operand_types [op].bitfield.vec_disp8) - i.types[op].bitfield.vec_disp8 = 1; - else - i.types[op].bitfield.disp8 = 1; - } - i.sib.scale = i.log2_scale_factor; - if (i.index_reg == 0) - { - gas_assert (!i.tm.opcode_modifier.vecsib); - /* <disp>(%esp) becomes two byte modrm with no index - register. We've already stored the code for esp - in i.rm.regmem ie. ESCAPE_TO_TWO_BYTE_ADDRESSING. - Any base register besides %esp will not use the - extra modrm byte. */ - i.sib.index = NO_INDEX_REGISTER; - } - else if (!i.tm.opcode_modifier.vecsib) - { - if (i.index_reg->reg_num == RegEiz - || i.index_reg->reg_num == RegRiz) - i.sib.index = NO_INDEX_REGISTER; - else - i.sib.index = i.index_reg->reg_num; - i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; - if ((i.index_reg->reg_flags & RegRex) != 0) - i.rex |= REX_X; - } - - if (i.disp_operands - && (i.reloc[op] == BFD_RELOC_386_TLS_DESC_CALL - || i.reloc[op] == BFD_RELOC_X86_64_TLSDESC_CALL)) - i.rm.mode = 0; - else - { - if (!fake_zero_displacement - && !i.disp_operands - && i.disp_encoding) - { - fake_zero_displacement = 1; - if (i.disp_encoding == disp_encoding_8bit) - i.types[op].bitfield.disp8 = 1; - else - i.types[op].bitfield.disp32 = 1; - } - i.rm.mode = mode_from_disp_size (i.types[op]); - } - } - - if (fake_zero_displacement) - { - /* Fakes a zero displacement assuming that i.types[op] - holds the correct displacement size. */ - expressionS *exp; - - gas_assert (i.op[op].disps == 0); - exp = &disp_expressions[i.disp_operands++]; - i.op[op].disps = exp; - exp->X_op = O_constant; - exp->X_add_number = 0; - exp->X_add_symbol = (symbolS *) 0; - exp->X_op_symbol = (symbolS *) 0; - } - - mem = op; - } - else - mem = ~0; - - if (i.tm.opcode_modifier.vexsources == XOP2SOURCES) - { - if (operand_type_check (i.types[0], imm)) - i.vex.register_specifier = NULL; - else - { - /* VEX.vvvv encodes one of the sources when the first - operand is not an immediate. */ - if (i.tm.opcode_modifier.vexw == VEXW0) - i.vex.register_specifier = i.op[0].regs; - else - i.vex.register_specifier = i.op[1].regs; - } - - /* Destination is a XMM register encoded in the ModRM.reg - and VEX.R bit. */ - i.rm.reg = i.op[2].regs->reg_num; - if ((i.op[2].regs->reg_flags & RegRex) != 0) - i.rex |= REX_R; - - /* ModRM.rm and VEX.B encodes the other source. */ - if (!i.mem_operands) - { - i.rm.mode = 3; - - if (i.tm.opcode_modifier.vexw == VEXW0) - i.rm.regmem = i.op[1].regs->reg_num; - else - i.rm.regmem = i.op[0].regs->reg_num; - - if ((i.op[1].regs->reg_flags & RegRex) != 0) - i.rex |= REX_B; - } - } - else if (i.tm.opcode_modifier.vexvvvv == VEXLWP) - { - i.vex.register_specifier = i.op[2].regs; - if (!i.mem_operands) - { - i.rm.mode = 3; - i.rm.regmem = i.op[1].regs->reg_num; - if ((i.op[1].regs->reg_flags & RegRex) != 0) - i.rex |= REX_B; - } - } - /* Fill in i.rm.reg or i.rm.regmem field with register operand - (if any) based on i.tm.extension_opcode. Again, we must be - careful to make sure that segment/control/debug/test/MMX - registers are coded into the i.rm.reg field. */ - else if (i.reg_operands) - { - unsigned int op; - unsigned int vex_reg = ~0; - - for (op = 0; op < i.operands; op++) - if (i.types[op].bitfield.reg8 - || i.types[op].bitfield.reg16 - || i.types[op].bitfield.reg32 - || i.types[op].bitfield.reg64 - || i.types[op].bitfield.regmmx - || i.types[op].bitfield.regxmm - || i.types[op].bitfield.regymm - || i.types[op].bitfield.regbnd - || i.types[op].bitfield.regzmm - || i.types[op].bitfield.regmask - || i.types[op].bitfield.sreg2 - || i.types[op].bitfield.sreg3 - || i.types[op].bitfield.control - || i.types[op].bitfield.debug - || i.types[op].bitfield.test) - break; - - if (vex_3_sources) - op = dest; - else if (i.tm.opcode_modifier.vexvvvv == VEXXDS) - { - /* For instructions with VexNDS, the register-only - source operand is encoded in VEX prefix. */ - gas_assert (mem != (unsigned int) ~0); - - if (op > mem) - { - vex_reg = op++; - gas_assert (op < i.operands); - } - else - { - /* Check register-only source operand when two source - operands are swapped. */ - if (!i.tm.operand_types[op].bitfield.baseindex - && i.tm.operand_types[op + 1].bitfield.baseindex) - { - vex_reg = op; - op += 2; - gas_assert (mem == (vex_reg + 1) - && op < i.operands); - } - else - { - vex_reg = op + 1; - gas_assert (vex_reg < i.operands); - } - } - } - else if (i.tm.opcode_modifier.vexvvvv == VEXNDD) - { - /* For instructions with VexNDD, the register destination - is encoded in VEX prefix. */ - if (i.mem_operands == 0) - { - /* There is no memory operand. */ - gas_assert ((op + 2) == i.operands); - vex_reg = op + 1; - } - else - { - /* There are only 2 operands. */ - gas_assert (op < 2 && i.operands == 2); - vex_reg = 1; - } - } - else - gas_assert (op < i.operands); - - if (vex_reg != (unsigned int) ~0) - { - i386_operand_type *type = &i.tm.operand_types[vex_reg]; - - if (type->bitfield.reg32 != 1 - && type->bitfield.reg64 != 1 - && !operand_type_equal (type, ®xmm) - && !operand_type_equal (type, ®ymm) - && !operand_type_equal (type, ®zmm) - && !operand_type_equal (type, ®mask)) - abort (); - - i.vex.register_specifier = i.op[vex_reg].regs; - } - - /* Don't set OP operand twice. */ - if (vex_reg != op) - { - /* If there is an extension opcode to put here, the - register number must be put into the regmem field. */ - if (i.tm.extension_opcode != None) - { - i.rm.regmem = i.op[op].regs->reg_num; - if ((i.op[op].regs->reg_flags & RegRex) != 0) - i.rex |= REX_B; - if ((i.op[op].regs->reg_flags & RegVRex) != 0) - i.vrex |= REX_B; - } - else - { - i.rm.reg = i.op[op].regs->reg_num; - if ((i.op[op].regs->reg_flags & RegRex) != 0) - i.rex |= REX_R; - if ((i.op[op].regs->reg_flags & RegVRex) != 0) - i.vrex |= REX_R; - } - } - - /* Now, if no memory operand has set i.rm.mode = 0, 1, 2 we - must set it to 3 to indicate this is a register operand - in the regmem field. */ - if (!i.mem_operands) - i.rm.mode = 3; - } - - /* Fill in i.rm.reg field with extension opcode (if any). */ - if (i.tm.extension_opcode != None) - i.rm.reg = i.tm.extension_opcode; - } - return default_seg; -} - -static void -output_branch (void) -{ - char *p; - int size; - int code16; - int prefix; - relax_substateT subtype; - symbolS *sym; - offsetT off; - - code16 = flag_code == CODE_16BIT ? CODE16 : 0; - size = i.disp_encoding == disp_encoding_32bit ? BIG : SMALL; - - prefix = 0; - if (i.prefix[DATA_PREFIX] != 0) - { - prefix = 1; - i.prefixes -= 1; - code16 ^= CODE16; - } - /* Pentium4 branch hints. */ - if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */ - || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE /* taken */) - { - prefix++; - i.prefixes--; - } - if (i.prefix[REX_PREFIX] != 0) - { - prefix++; - i.prefixes--; - } - - /* BND prefixed jump. */ - if (i.prefix[BND_PREFIX] != 0) - { - FRAG_APPEND_1_CHAR (i.prefix[BND_PREFIX]); - i.prefixes -= 1; - } - - if (i.prefixes != 0 && !intel_syntax) - as_warn (_("skipping prefixes on this instruction")); - - /* It's always a symbol; End frag & setup for relax. - Make sure there is enough room in this frag for the largest - instruction we may generate in md_convert_frag. This is 2 - bytes for the opcode and room for the prefix and largest - displacement. */ - frag_grow (prefix + 2 + 4); - /* Prefix and 1 opcode byte go in fr_fix. */ - p = frag_more (prefix + 1); - if (i.prefix[DATA_PREFIX] != 0) - *p++ = DATA_PREFIX_OPCODE; - if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE - || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE) - *p++ = i.prefix[SEG_PREFIX]; - if (i.prefix[REX_PREFIX] != 0) - *p++ = i.prefix[REX_PREFIX]; - *p = i.tm.base_opcode; - - if ((unsigned char) *p == JUMP_PC_RELATIVE) - subtype = ENCODE_RELAX_STATE (UNCOND_JUMP, size); - else if (cpu_arch_flags.bitfield.cpui386) - subtype = ENCODE_RELAX_STATE (COND_JUMP, size); - else - subtype = ENCODE_RELAX_STATE (COND_JUMP86, size); - subtype |= code16; - - sym = i.op[0].disps->X_add_symbol; - off = i.op[0].disps->X_add_number; - - if (i.op[0].disps->X_op != O_constant - && i.op[0].disps->X_op != O_symbol) - { - /* Handle complex expressions. */ - sym = make_expr_symbol (i.op[0].disps); - off = 0; - } - - /* 1 possible extra opcode + 4 byte displacement go in var part. - Pass reloc in fr_var. */ - frag_var (rs_machine_dependent, 5, - ((!object_64bit - || i.reloc[0] != NO_RELOC - || (i.bnd_prefix == NULL && !add_bnd_prefix)) - ? i.reloc[0] - : BFD_RELOC_X86_64_PC32_BND), - subtype, sym, off, p); -} - -static void -output_jump (void) -{ - char *p; - int size; - fixS *fixP; - - if (i.tm.opcode_modifier.jumpbyte) - { - /* This is a loop or jecxz type instruction. */ - size = 1; - if (i.prefix[ADDR_PREFIX] != 0) - { - FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE); - i.prefixes -= 1; - } - /* Pentium4 branch hints. */ - if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */ - || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE /* taken */) - { - FRAG_APPEND_1_CHAR (i.prefix[SEG_PREFIX]); - i.prefixes--; - } - } - else - { - int code16; - - code16 = 0; - if (flag_code == CODE_16BIT) - code16 = CODE16; - - if (i.prefix[DATA_PREFIX] != 0) - { - FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE); - i.prefixes -= 1; - code16 ^= CODE16; - } - - size = 4; - if (code16) - size = 2; - } - - if (i.prefix[REX_PREFIX] != 0) - { - FRAG_APPEND_1_CHAR (i.prefix[REX_PREFIX]); - i.prefixes -= 1; - } - - /* BND prefixed jump. */ - if (i.prefix[BND_PREFIX] != 0) - { - FRAG_APPEND_1_CHAR (i.prefix[BND_PREFIX]); - i.prefixes -= 1; - } - - if (i.prefixes != 0 && !intel_syntax) - as_warn (_("skipping prefixes on this instruction")); - - p = frag_more (i.tm.opcode_length + size); - switch (i.tm.opcode_length) - { - case 2: - *p++ = i.tm.base_opcode >> 8; - case 1: - *p++ = i.tm.base_opcode; - break; - default: - abort (); - } - - fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size, - i.op[0].disps, 1, reloc (size, 1, 1, - (i.bnd_prefix != NULL - || add_bnd_prefix), - i.reloc[0])); - - /* All jumps handled here are signed, but don't use a signed limit - check for 32 and 16 bit jumps as we want to allow wrap around at - 4G and 64k respectively. */ - if (size == 1) - fixP->fx_signed = 1; -} - -static void -output_interseg_jump (void) -{ - char *p; - int size; - int prefix; - int code16; - - code16 = 0; - if (flag_code == CODE_16BIT) - code16 = CODE16; - - prefix = 0; - if (i.prefix[DATA_PREFIX] != 0) - { - prefix = 1; - i.prefixes -= 1; - code16 ^= CODE16; - } - if (i.prefix[REX_PREFIX] != 0) - { - prefix++; - i.prefixes -= 1; - } - - size = 4; - if (code16) - size = 2; - - if (i.prefixes != 0 && !intel_syntax) - as_warn (_("skipping prefixes on this instruction")); - - /* 1 opcode; 2 segment; offset */ - p = frag_more (prefix + 1 + 2 + size); - - if (i.prefix[DATA_PREFIX] != 0) - *p++ = DATA_PREFIX_OPCODE; - - if (i.prefix[REX_PREFIX] != 0) - *p++ = i.prefix[REX_PREFIX]; - - *p++ = i.tm.base_opcode; - if (i.op[1].imms->X_op == O_constant) - { - offsetT n = i.op[1].imms->X_add_number; - - if (size == 2 - && !fits_in_unsigned_word (n) - && !fits_in_signed_word (n)) - { - as_bad (_("16-bit jump out of range")); - return; - } - md_number_to_chars (p, n, size); - } - else - fix_new_exp (frag_now, p - frag_now->fr_literal, size, - i.op[1].imms, 0, reloc (size, 0, 0, 0, i.reloc[1])); - if (i.op[0].imms->X_op != O_constant) - as_bad (_("can't handle non absolute segment in `%s'"), - i.tm.name); - md_number_to_chars (p + size, (valueT) i.op[0].imms->X_add_number, 2); -} - -static void -output_insn (void) -{ - fragS *insn_start_frag; - offsetT insn_start_off; - - /* Tie dwarf2 debug info to the address at the start of the insn. - We can't do this after the insn has been output as the current - frag may have been closed off. eg. by frag_var. */ - dwarf2_emit_insn (0); - - insn_start_frag = frag_now; - insn_start_off = frag_now_fix (); - - /* Output jumps. */ - if (i.tm.opcode_modifier.jump) - output_branch (); - else if (i.tm.opcode_modifier.jumpbyte - || i.tm.opcode_modifier.jumpdword) - output_jump (); - else if (i.tm.opcode_modifier.jumpintersegment) - output_interseg_jump (); - else - { - /* Output normal instructions here. */ - char *p; - unsigned char *q; - unsigned int j; - unsigned int prefix; - - /* Since the VEX/EVEX prefix contains the implicit prefix, we - don't need the explicit prefix. */ - if (!i.tm.opcode_modifier.vex && !i.tm.opcode_modifier.evex) - { - switch (i.tm.opcode_length) - { - case 3: - if (i.tm.base_opcode & 0xff000000) - { - prefix = (i.tm.base_opcode >> 24) & 0xff; - goto check_prefix; - } - break; - case 2: - if ((i.tm.base_opcode & 0xff0000) != 0) - { - prefix = (i.tm.base_opcode >> 16) & 0xff; - if (i.tm.cpu_flags.bitfield.cpupadlock) - { -check_prefix: - if (prefix != REPE_PREFIX_OPCODE - || (i.prefix[REP_PREFIX] - != REPE_PREFIX_OPCODE)) - add_prefix (prefix); - } - else - add_prefix (prefix); - } - break; - case 1: - break; - default: - abort (); - } - - /* The prefix bytes. */ - for (j = ARRAY_SIZE (i.prefix), q = i.prefix; j > 0; j--, q++) - if (*q) - FRAG_APPEND_1_CHAR (*q); - } - else - { - for (j = 0, q = i.prefix; j < ARRAY_SIZE (i.prefix); j++, q++) - if (*q) - switch (j) - { - case REX_PREFIX: - /* REX byte is encoded in VEX prefix. */ - break; - case SEG_PREFIX: - case ADDR_PREFIX: - FRAG_APPEND_1_CHAR (*q); - break; - default: - /* There should be no other prefixes for instructions - with VEX prefix. */ - abort (); - } - - /* For EVEX instructions i.vrex should become 0 after - build_evex_prefix. For VEX instructions upper 16 registers - aren't available, so VREX should be 0. */ - if (i.vrex) - abort (); - /* Now the VEX prefix. */ - p = frag_more (i.vex.length); - for (j = 0; j < i.vex.length; j++) - p[j] = i.vex.bytes[j]; - } - - /* Now the opcode; be careful about word order here! */ - if (i.tm.opcode_length == 1) - { - FRAG_APPEND_1_CHAR (i.tm.base_opcode); - } - else - { - switch (i.tm.opcode_length) - { - case 4: - p = frag_more (4); - *p++ = (i.tm.base_opcode >> 24) & 0xff; - *p++ = (i.tm.base_opcode >> 16) & 0xff; - break; - case 3: - p = frag_more (3); - *p++ = (i.tm.base_opcode >> 16) & 0xff; - break; - case 2: - p = frag_more (2); - break; - default: - abort (); - break; - } - - /* Put out high byte first: can't use md_number_to_chars! */ - *p++ = (i.tm.base_opcode >> 8) & 0xff; - *p = i.tm.base_opcode & 0xff; - } - - /* Now the modrm byte and sib byte (if present). */ - if (i.tm.opcode_modifier.modrm) - { - 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 - ==> need second modrm byte. */ - if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING - && i.rm.mode != 3 - && !(i.base_reg && i.base_reg->reg_type.bitfield.reg16)) - FRAG_APPEND_1_CHAR ((i.sib.base << 0 - | i.sib.index << 3 - | i.sib.scale << 6)); - } - - if (i.disp_operands) - output_disp (insn_start_frag, insn_start_off); - - if (i.imm_operands) - output_imm (insn_start_frag, insn_start_off); - } - -#ifdef DEBUG386 - if (flag_debug) - { - pi ("" /*line*/, &i); - } -#endif /* DEBUG386 */ -} - -/* Return the size of the displacement operand N. */ - -static int -disp_size (unsigned int n) -{ - int size = 4; - - /* Vec_Disp8 has to be 8bit. */ - if (i.types[n].bitfield.vec_disp8) - size = 1; - else if (i.types[n].bitfield.disp64) - size = 8; - else if (i.types[n].bitfield.disp8) - size = 1; - else if (i.types[n].bitfield.disp16) - size = 2; - return size; -} - -/* Return the size of the immediate operand N. */ - -static int -imm_size (unsigned int n) -{ - int size = 4; - if (i.types[n].bitfield.imm64) - size = 8; - else if (i.types[n].bitfield.imm8 || i.types[n].bitfield.imm8s) - size = 1; - else if (i.types[n].bitfield.imm16) - size = 2; - return size; -} - -static void -output_disp (fragS *insn_start_frag, offsetT insn_start_off) -{ - char *p; - unsigned int n; - - for (n = 0; n < i.operands; n++) - { - if (i.types[n].bitfield.vec_disp8 - || operand_type_check (i.types[n], disp)) - { - if (i.op[n].disps->X_op == O_constant) - { - int size = disp_size (n); - offsetT val = i.op[n].disps->X_add_number; - - if (i.types[n].bitfield.vec_disp8) - val >>= i.memshift; - val = offset_in_range (val, size); - p = frag_more (size); - md_number_to_chars (p, val, size); - } - else - { - enum bfd_reloc_code_real reloc_type; - int size = disp_size (n); - int sign = i.types[n].bitfield.disp32s; - int pcrel = (i.flags[n] & Operand_PCrel) != 0; - - /* We can't have 8 bit displacement here. */ - gas_assert (!i.types[n].bitfield.disp8); - - /* The PC relative address is computed relative - to the instruction boundary, so in case immediate - fields follows, we need to adjust the value. */ - if (pcrel && i.imm_operands) - { - unsigned int n1; - int sz = 0; - - for (n1 = 0; n1 < i.operands; n1++) - if (operand_type_check (i.types[n1], imm)) - { - /* Only one immediate is allowed for PC - relative address. */ - gas_assert (sz == 0); - sz = imm_size (n1); - i.op[n].disps->X_add_number -= sz; - } - /* We should find the immediate. */ - gas_assert (sz != 0); - } - - p = frag_more (size); - reloc_type = reloc (size, pcrel, sign, - (i.bnd_prefix != NULL - || add_bnd_prefix), - i.reloc[n]); - if (GOT_symbol - && GOT_symbol == i.op[n].disps->X_add_symbol - && (((reloc_type == BFD_RELOC_32 - || reloc_type == BFD_RELOC_X86_64_32S - || (reloc_type == BFD_RELOC_64 - && object_64bit)) - && (i.op[n].disps->X_op == O_symbol - || (i.op[n].disps->X_op == O_add - && ((symbol_get_value_expression - (i.op[n].disps->X_op_symbol)->X_op) - == O_subtract)))) - || reloc_type == BFD_RELOC_32_PCREL)) - { - offsetT add; - - if (insn_start_frag == frag_now) - add = (p - frag_now->fr_literal) - insn_start_off; - else - { - fragS *fr; - - add = insn_start_frag->fr_fix - insn_start_off; - for (fr = insn_start_frag->fr_next; - fr && fr != frag_now; fr = fr->fr_next) - add += fr->fr_fix; - add += p - frag_now->fr_literal; - } - - if (!object_64bit) - { - reloc_type = BFD_RELOC_386_GOTPC; - i.op[n].imms->X_add_number += add; - } - else if (reloc_type == BFD_RELOC_64) - reloc_type = BFD_RELOC_X86_64_GOTPC64; - else - /* Don't do the adjustment for x86-64, as there - the pcrel addressing is relative to the _next_ - insn, and that is taken care of in other code. */ - reloc_type = BFD_RELOC_X86_64_GOTPC32; - } - fix_new_exp (frag_now, p - frag_now->fr_literal, size, - i.op[n].disps, pcrel, reloc_type); - } - } - } -} - -static void -output_imm (fragS *insn_start_frag, offsetT insn_start_off) -{ - char *p; - unsigned int n; - - for (n = 0; n < i.operands; n++) - { - /* Skip SAE/RC Imm operand in EVEX. They are already handled. */ - if (i.rounding && (int) n == i.rounding->operand) - continue; - - if (operand_type_check (i.types[n], imm)) - { - if (i.op[n].imms->X_op == O_constant) - { - int size = imm_size (n); - offsetT val; - - val = offset_in_range (i.op[n].imms->X_add_number, - size); - p = frag_more (size); - md_number_to_chars (p, val, size); - } - else - { - /* Not absolute_section. - Need a 32-bit fixup (don't support 8bit - non-absolute imms). Try to support other - sizes ... */ - enum bfd_reloc_code_real reloc_type; - int size = imm_size (n); - int sign; - - if (i.types[n].bitfield.imm32s - && (i.suffix == QWORD_MNEM_SUFFIX - || (!i.suffix && i.tm.opcode_modifier.no_lsuf))) - sign = 1; - else - sign = 0; - - p = frag_more (size); - reloc_type = reloc (size, 0, sign, 0, i.reloc[n]); - - /* This is tough to explain. We end up with this one if we - * have operands that look like - * "_GLOBAL_OFFSET_TABLE_+[.-.L284]". The goal here is to - * obtain the absolute address of the GOT, and it is strongly - * preferable from a performance point of view to avoid using - * a runtime relocation for this. The actual sequence of - * instructions often look something like: - * - * call .L66 - * .L66: - * popl %ebx - * addl $_GLOBAL_OFFSET_TABLE_+[.-.L66],%ebx - * - * The call and pop essentially return the absolute address - * of the label .L66 and store it in %ebx. The linker itself - * will ultimately change the first operand of the addl so - * that %ebx points to the GOT, but to keep things simple, the - * .o file must have this operand set so that it generates not - * the absolute address of .L66, but the absolute address of - * itself. This allows the linker itself simply treat a GOTPC - * relocation as asking for a pcrel offset to the GOT to be - * added in, and the addend of the relocation is stored in the - * operand field for the instruction itself. - * - * Our job here is to fix the operand so that it would add - * the correct offset so that %ebx would point to itself. The - * thing that is tricky is that .-.L66 will point to the - * beginning of the instruction, so we need to further modify - * the operand so that it will point to itself. There are - * other cases where you have something like: - * - * .long $_GLOBAL_OFFSET_TABLE_+[.-.L66] - * - * and here no correction would be required. Internally in - * the assembler we treat operands of this form as not being - * pcrel since the '.' is explicitly mentioned, and I wonder - * whether it would simplify matters to do it this way. Who - * knows. In earlier versions of the PIC patches, the - * pcrel_adjust field was used to store the correction, but - * since the expression is not pcrel, I felt it would be - * confusing to do it this way. */ - - if ((reloc_type == BFD_RELOC_32 - || reloc_type == BFD_RELOC_X86_64_32S - || reloc_type == BFD_RELOC_64) - && GOT_symbol - && GOT_symbol == i.op[n].imms->X_add_symbol - && (i.op[n].imms->X_op == O_symbol - || (i.op[n].imms->X_op == O_add - && ((symbol_get_value_expression - (i.op[n].imms->X_op_symbol)->X_op) - == O_subtract)))) - { - offsetT add; - - if (insn_start_frag == frag_now) - add = (p - frag_now->fr_literal) - insn_start_off; - else - { - fragS *fr; - - add = insn_start_frag->fr_fix - insn_start_off; - for (fr = insn_start_frag->fr_next; - fr && fr != frag_now; fr = fr->fr_next) - add += fr->fr_fix; - add += p - frag_now->fr_literal; - } - - if (!object_64bit) - reloc_type = BFD_RELOC_386_GOTPC; - else if (size == 4) - reloc_type = BFD_RELOC_X86_64_GOTPC32; - else if (size == 8) - reloc_type = BFD_RELOC_X86_64_GOTPC64; - i.op[n].imms->X_add_number += add; - } - fix_new_exp (frag_now, p - frag_now->fr_literal, size, - i.op[n].imms, 0, reloc_type); - } - } - } -} - -/* x86_cons_fix_new is called via the expression parsing code when a - reloc is needed. We use this hook to get the correct .got reloc. */ -static enum bfd_reloc_code_real got_reloc = NO_RELOC; -static int cons_sign = -1; - -void -x86_cons_fix_new (fragS *frag, unsigned int off, unsigned int len, - expressionS *exp) -{ - enum bfd_reloc_code_real r = reloc (len, 0, cons_sign, 0, got_reloc); - - got_reloc = NO_RELOC; - -#ifdef TE_PE - if (exp->X_op == O_secrel) - { - exp->X_op = O_symbol; - r = BFD_RELOC_32_SECREL; - } -#endif - - fix_new_exp (frag, off, len, exp, 0, r); -} - -/* Export the ABI address size for use by TC_ADDRESS_BYTES for the - purpose of the `.dc.a' internal pseudo-op. */ - -int -x86_address_bytes (void) -{ - if ((stdoutput->arch_info->mach & bfd_mach_x64_32)) - return 4; - return stdoutput->arch_info->bits_per_address / 8; -} - -#if !(defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined (OBJ_MACH_O)) \ - || defined (LEX_AT) -# define lex_got(reloc, adjust, types, bnd_prefix) NULL -#else -/* Parse operands of the form - <symbol>@GOTOFF+<nnn> - and similar .plt or .got references. - - If we find one, set up the correct relocation in RELOC and copy the - input string, minus the `@GOTOFF' into a malloc'd buffer for - parsing by the calling routine. Return this buffer, and if ADJUST - is non-null set it to the length of the string we removed from the - input line. Otherwise return NULL. */ -static char * -lex_got (enum bfd_reloc_code_real *rel, - int *adjust, - i386_operand_type *types, - int bnd_prefix) -{ - /* Some of the relocations depend on the size of what field is to - be relocated. But in our callers i386_immediate and i386_displacement - we don't yet know the operand size (this will be set by insn - matching). Hence we record the word32 relocation here, - and adjust the reloc according to the real size in reloc(). */ - static const struct { - const char *str; - int len; - const enum bfd_reloc_code_real rel[2]; - const i386_operand_type types64; - } gotrel[] = { -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - { STRING_COMMA_LEN ("SIZE"), { BFD_RELOC_SIZE32, - BFD_RELOC_SIZE32 }, - OPERAND_TYPE_IMM32_64 }, -#endif - { STRING_COMMA_LEN ("PLTOFF"), { _dummy_first_bfd_reloc_code_real, - BFD_RELOC_X86_64_PLTOFF64 }, - OPERAND_TYPE_IMM64 }, - { STRING_COMMA_LEN ("PLT"), { BFD_RELOC_386_PLT32, - BFD_RELOC_X86_64_PLT32 }, - OPERAND_TYPE_IMM32_32S_DISP32 }, - { STRING_COMMA_LEN ("GOTPLT"), { _dummy_first_bfd_reloc_code_real, - BFD_RELOC_X86_64_GOTPLT64 }, - OPERAND_TYPE_IMM64_DISP64 }, - { STRING_COMMA_LEN ("GOTOFF"), { BFD_RELOC_386_GOTOFF, - BFD_RELOC_X86_64_GOTOFF64 }, - OPERAND_TYPE_IMM64_DISP64 }, - { STRING_COMMA_LEN ("GOTPCREL"), { _dummy_first_bfd_reloc_code_real, - BFD_RELOC_X86_64_GOTPCREL }, - OPERAND_TYPE_IMM32_32S_DISP32 }, - { STRING_COMMA_LEN ("TLSGD"), { BFD_RELOC_386_TLS_GD, - BFD_RELOC_X86_64_TLSGD }, - OPERAND_TYPE_IMM32_32S_DISP32 }, - { STRING_COMMA_LEN ("TLSLDM"), { BFD_RELOC_386_TLS_LDM, - _dummy_first_bfd_reloc_code_real }, - OPERAND_TYPE_NONE }, - { STRING_COMMA_LEN ("TLSLD"), { _dummy_first_bfd_reloc_code_real, - BFD_RELOC_X86_64_TLSLD }, - OPERAND_TYPE_IMM32_32S_DISP32 }, - { STRING_COMMA_LEN ("GOTTPOFF"), { BFD_RELOC_386_TLS_IE_32, - BFD_RELOC_X86_64_GOTTPOFF }, - OPERAND_TYPE_IMM32_32S_DISP32 }, - { STRING_COMMA_LEN ("TPOFF"), { BFD_RELOC_386_TLS_LE_32, - BFD_RELOC_X86_64_TPOFF32 }, - OPERAND_TYPE_IMM32_32S_64_DISP32_64 }, - { STRING_COMMA_LEN ("NTPOFF"), { BFD_RELOC_386_TLS_LE, - _dummy_first_bfd_reloc_code_real }, - OPERAND_TYPE_NONE }, - { STRING_COMMA_LEN ("DTPOFF"), { BFD_RELOC_386_TLS_LDO_32, - BFD_RELOC_X86_64_DTPOFF32 }, - OPERAND_TYPE_IMM32_32S_64_DISP32_64 }, - { STRING_COMMA_LEN ("GOTNTPOFF"),{ BFD_RELOC_386_TLS_GOTIE, - _dummy_first_bfd_reloc_code_real }, - OPERAND_TYPE_NONE }, - { STRING_COMMA_LEN ("INDNTPOFF"),{ BFD_RELOC_386_TLS_IE, - _dummy_first_bfd_reloc_code_real }, - OPERAND_TYPE_NONE }, - { STRING_COMMA_LEN ("GOT"), { BFD_RELOC_386_GOT32, - BFD_RELOC_X86_64_GOT32 }, - OPERAND_TYPE_IMM32_32S_64_DISP32 }, - { STRING_COMMA_LEN ("TLSDESC"), { BFD_RELOC_386_TLS_GOTDESC, - BFD_RELOC_X86_64_GOTPC32_TLSDESC }, - OPERAND_TYPE_IMM32_32S_DISP32 }, - { STRING_COMMA_LEN ("TLSCALL"), { BFD_RELOC_386_TLS_DESC_CALL, - BFD_RELOC_X86_64_TLSDESC_CALL }, - OPERAND_TYPE_IMM32_32S_DISP32 }, - }; - char *cp; - unsigned int j; - -#if defined (OBJ_MAYBE_ELF) - if (!IS_ELF) - return NULL; -#endif - - for (cp = input_line_pointer; *cp != '@'; cp++) - if (is_end_of_line[(unsigned char) *cp] || *cp == ',') - return NULL; - - for (j = 0; j < ARRAY_SIZE (gotrel); j++) - { - int len = gotrel[j].len; - if (strncasecmp (cp + 1, gotrel[j].str, len) == 0) - { - if (gotrel[j].rel[object_64bit] != 0) - { - int first, second; - char *tmpbuf, *past_reloc; - - *rel = gotrel[j].rel[object_64bit]; - - if (types) - { - if (flag_code != CODE_64BIT) - { - types->bitfield.imm32 = 1; - types->bitfield.disp32 = 1; - } - else - *types = gotrel[j].types64; - } - - if (j != 0 && GOT_symbol == NULL) - GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME); - - /* The length of the first part of our input line. */ - first = cp - input_line_pointer; - - /* The second part goes from after the reloc token until - (and including) an end_of_line char or comma. */ - past_reloc = cp + 1 + len; - cp = past_reloc; - while (!is_end_of_line[(unsigned char) *cp] && *cp != ',') - ++cp; - second = cp + 1 - past_reloc; - - /* Allocate and copy string. The trailing NUL shouldn't - be necessary, but be safe. */ - tmpbuf = (char *) xmalloc (first + second + 2); - memcpy (tmpbuf, input_line_pointer, first); - if (second != 0 && *past_reloc != ' ') - /* Replace the relocation token with ' ', so that - errors like foo@GOTOFF1 will be detected. */ - tmpbuf[first++] = ' '; - else - /* Increment length by 1 if the relocation token is - removed. */ - len++; - if (adjust) - *adjust = len; - memcpy (tmpbuf + first, past_reloc, second); - tmpbuf[first + second] = '\0'; - if (bnd_prefix && *rel == BFD_RELOC_X86_64_PLT32) - *rel = BFD_RELOC_X86_64_PLT32_BND; - return tmpbuf; - } - - as_bad (_("@%s reloc is not supported with %d-bit output format"), - gotrel[j].str, 1 << (5 + object_64bit)); - return NULL; - } - } - - /* Might be a symbol version string. Don't as_bad here. */ - return NULL; -} -#endif - -#ifdef TE_PE -#ifdef lex_got -#undef lex_got -#endif -/* Parse operands of the form - <symbol>@SECREL32+<nnn> - - If we find one, set up the correct relocation in RELOC and copy the - input string, minus the `@SECREL32' into a malloc'd buffer for - parsing by the calling routine. Return this buffer, and if ADJUST - is non-null set it to the length of the string we removed from the - input line. Otherwise return NULL. - - This function is copied from the ELF version above adjusted for PE targets. */ - -static char * -lex_got (enum bfd_reloc_code_real *rel ATTRIBUTE_UNUSED, - int *adjust ATTRIBUTE_UNUSED, - i386_operand_type *types, - int bnd_prefix ATTRIBUTE_UNUSED) -{ - static const struct - { - const char *str; - int len; - const enum bfd_reloc_code_real rel[2]; - const i386_operand_type types64; - } - gotrel[] = - { - { STRING_COMMA_LEN ("SECREL32"), { BFD_RELOC_32_SECREL, - BFD_RELOC_32_SECREL }, - OPERAND_TYPE_IMM32_32S_64_DISP32_64 }, - }; - - char *cp; - unsigned j; - - for (cp = input_line_pointer; *cp != '@'; cp++) - if (is_end_of_line[(unsigned char) *cp] || *cp == ',') - return NULL; - - for (j = 0; j < ARRAY_SIZE (gotrel); j++) - { - int len = gotrel[j].len; - - if (strncasecmp (cp + 1, gotrel[j].str, len) == 0) - { - if (gotrel[j].rel[object_64bit] != 0) - { - int first, second; - char *tmpbuf, *past_reloc; - - *rel = gotrel[j].rel[object_64bit]; - if (adjust) - *adjust = len; - - if (types) - { - if (flag_code != CODE_64BIT) - { - types->bitfield.imm32 = 1; - types->bitfield.disp32 = 1; - } - else - *types = gotrel[j].types64; - } - - /* The length of the first part of our input line. */ - first = cp - input_line_pointer; - - /* The second part goes from after the reloc token until - (and including) an end_of_line char or comma. */ - past_reloc = cp + 1 + len; - cp = past_reloc; - while (!is_end_of_line[(unsigned char) *cp] && *cp != ',') - ++cp; - second = cp + 1 - past_reloc; - - /* Allocate and copy string. The trailing NUL shouldn't - be necessary, but be safe. */ - tmpbuf = (char *) xmalloc (first + second + 2); - memcpy (tmpbuf, input_line_pointer, first); - if (second != 0 && *past_reloc != ' ') - /* Replace the relocation token with ' ', so that - errors like foo@SECLREL321 will be detected. */ - tmpbuf[first++] = ' '; - memcpy (tmpbuf + first, past_reloc, second); - tmpbuf[first + second] = '\0'; - return tmpbuf; - } - - as_bad (_("@%s reloc is not supported with %d-bit output format"), - gotrel[j].str, 1 << (5 + object_64bit)); - return NULL; - } - } - - /* Might be a symbol version string. Don't as_bad here. */ - return NULL; -} - -#endif /* TE_PE */ - -void -x86_cons (expressionS *exp, int size) -{ - intel_syntax = -intel_syntax; - - exp->X_md = 0; - if (size == 4 || (object_64bit && size == 8)) - { - /* Handle @GOTOFF and the like in an expression. */ - char *save; - char *gotfree_input_line; - int adjust = 0; - - save = input_line_pointer; - gotfree_input_line = lex_got (&got_reloc, &adjust, NULL, 0); - if (gotfree_input_line) - input_line_pointer = gotfree_input_line; - - expression (exp); - - if (gotfree_input_line) - { - /* expression () has merrily parsed up to the end of line, - or a comma - in the wrong buffer. Transfer how far - input_line_pointer has moved to the right buffer. */ - input_line_pointer = (save - + (input_line_pointer - gotfree_input_line) - + adjust); - free (gotfree_input_line); - if (exp->X_op == O_constant - || exp->X_op == O_absent - || exp->X_op == O_illegal - || exp->X_op == O_register - || exp->X_op == O_big) - { - char c = *input_line_pointer; - *input_line_pointer = 0; - as_bad (_("missing or invalid expression `%s'"), save); - *input_line_pointer = c; - } - } - } - else - expression (exp); - - intel_syntax = -intel_syntax; - - if (intel_syntax) - i386_intel_simplify (exp); -} - -static void -signed_cons (int size) -{ - if (flag_code == CODE_64BIT) - cons_sign = 1; - cons (size); - cons_sign = -1; -} - -#ifdef TE_PE -static void -pe_directive_secrel (int dummy ATTRIBUTE_UNUSED) -{ - expressionS exp; - - do - { - expression (&exp); - if (exp.X_op == O_symbol) - exp.X_op = O_secrel; - - emit_expr (&exp, 4); - } - while (*input_line_pointer++ == ','); - - input_line_pointer--; - demand_empty_rest_of_line (); -} -#endif - -/* Handle Vector operations. */ - -static char * -check_VecOperations (char *op_string, char *op_end) -{ - const reg_entry *mask; - const char *saved; - char *end_op; - - while (*op_string - && (op_end == NULL || op_string < op_end)) - { - saved = op_string; - if (*op_string == '{') - { - op_string++; - - /* Check broadcasts. */ - if (strncmp (op_string, "1to", 3) == 0) - { - int bcst_type; - - if (i.broadcast) - goto duplicated_vec_op; - - op_string += 3; - if (*op_string == '8') - bcst_type = BROADCAST_1TO8; - else if (*op_string == '1' - && *(op_string+1) == '6') - { - bcst_type = BROADCAST_1TO16; - op_string++; - } - else - { - as_bad (_("Unsupported broadcast: `%s'"), saved); - return NULL; - } - op_string++; - - broadcast_op.type = bcst_type; - broadcast_op.operand = this_operand; - i.broadcast = &broadcast_op; - } - /* Check masking operation. */ - else if ((mask = parse_register (op_string, &end_op)) != NULL) - { - /* k0 can't be used for write mask. */ - if (mask->reg_num == 0) - { - as_bad (_("`%s' can't be used for write mask"), - op_string); - return NULL; - } - - if (!i.mask) - { - mask_op.mask = mask; - mask_op.zeroing = 0; - mask_op.operand = this_operand; - i.mask = &mask_op; - } - else - { - if (i.mask->mask) - goto duplicated_vec_op; - - i.mask->mask = mask; - - /* Only "{z}" is allowed here. No need to check - zeroing mask explicitly. */ - if (i.mask->operand != this_operand) - { - as_bad (_("invalid write mask `%s'"), saved); - return NULL; - } - } - - op_string = end_op; - } - /* Check zeroing-flag for masking operation. */ - else if (*op_string == 'z') - { - if (!i.mask) - { - mask_op.mask = NULL; - mask_op.zeroing = 1; - mask_op.operand = this_operand; - i.mask = &mask_op; - } - else - { - if (i.mask->zeroing) - { - duplicated_vec_op: - as_bad (_("duplicated `%s'"), saved); - return NULL; - } - - i.mask->zeroing = 1; - - /* Only "{%k}" is allowed here. No need to check mask - register explicitly. */ - if (i.mask->operand != this_operand) - { - as_bad (_("invalid zeroing-masking `%s'"), - saved); - return NULL; - } - } - - op_string++; - } - else - goto unknown_vec_op; - - if (*op_string != '}') - { - as_bad (_("missing `}' in `%s'"), saved); - return NULL; - } - op_string++; - continue; - } - unknown_vec_op: - /* We don't know this one. */ - as_bad (_("unknown vector operation: `%s'"), saved); - return NULL; - } - - return op_string; -} - -static int -i386_immediate (char *imm_start) -{ - char *save_input_line_pointer; - char *gotfree_input_line; - segT exp_seg = 0; - expressionS *exp; - i386_operand_type types; - - operand_type_set (&types, ~0); - - if (i.imm_operands == MAX_IMMEDIATE_OPERANDS) - { - as_bad (_("at most %d immediate operands are allowed"), - MAX_IMMEDIATE_OPERANDS); - return 0; - } - - exp = &im_expressions[i.imm_operands++]; - i.op[this_operand].imms = exp; - - if (is_space_char (*imm_start)) - ++imm_start; - - save_input_line_pointer = input_line_pointer; - input_line_pointer = imm_start; - - gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types, - (i.bnd_prefix != NULL - || add_bnd_prefix)); - if (gotfree_input_line) - input_line_pointer = gotfree_input_line; - - exp_seg = expression (exp); - - SKIP_WHITESPACE (); - - /* Handle vector operations. */ - if (*input_line_pointer == '{') - { - input_line_pointer = check_VecOperations (input_line_pointer, - NULL); - if (input_line_pointer == NULL) - return 0; - } - - if (*input_line_pointer) - as_bad (_("junk `%s' after expression"), input_line_pointer); - - input_line_pointer = save_input_line_pointer; - if (gotfree_input_line) - { - free (gotfree_input_line); - - if (exp->X_op == O_constant || exp->X_op == O_register) - exp->X_op = O_illegal; - } - - return i386_finalize_immediate (exp_seg, exp, types, imm_start); -} - -static int -i386_finalize_immediate (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp, - i386_operand_type types, const char *imm_start) -{ - if (exp->X_op == O_absent || exp->X_op == O_illegal || exp->X_op == O_big) - { - if (imm_start) - as_bad (_("missing or invalid immediate expression `%s'"), - imm_start); - return 0; - } - else if (exp->X_op == O_constant) - { - /* Size it properly later. */ - i.types[this_operand].bitfield.imm64 = 1; - /* If not 64bit, sign extend val. */ - if (flag_code != CODE_64BIT - && (exp->X_add_number & ~(((addressT) 2 << 31) - 1)) == 0) - exp->X_add_number - = (exp->X_add_number ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31); - } -#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT)) - else if (OUTPUT_FLAVOR == bfd_target_aout_flavour - && exp_seg != absolute_section - && exp_seg != text_section - && exp_seg != data_section - && exp_seg != bss_section - && exp_seg != undefined_section - && !bfd_is_com_section (exp_seg)) - { - as_bad (_("unimplemented segment %s in operand"), exp_seg->name); - return 0; - } -#endif - else if (!intel_syntax && exp->X_op == O_register) - { - if (imm_start) - as_bad (_("illegal immediate register operand %s"), imm_start); - return 0; - } - else - { - /* This is an address. The size of the address will be - determined later, depending on destination register, - suffix, or the default for the section. */ - i.types[this_operand].bitfield.imm8 = 1; - i.types[this_operand].bitfield.imm16 = 1; - i.types[this_operand].bitfield.imm32 = 1; - i.types[this_operand].bitfield.imm32s = 1; - i.types[this_operand].bitfield.imm64 = 1; - i.types[this_operand] = operand_type_and (i.types[this_operand], - types); - } - - return 1; -} - -static char * -i386_scale (char *scale) -{ - offsetT val; - char *save = input_line_pointer; - - input_line_pointer = scale; - val = get_absolute_expression (); - - switch (val) - { - case 1: - i.log2_scale_factor = 0; - break; - case 2: - i.log2_scale_factor = 1; - break; - case 4: - i.log2_scale_factor = 2; - break; - case 8: - i.log2_scale_factor = 3; - break; - default: - { - char sep = *input_line_pointer; - - *input_line_pointer = '\0'; - as_bad (_("expecting scale factor of 1, 2, 4, or 8: got `%s'"), - scale); - *input_line_pointer = sep; - input_line_pointer = save; - return NULL; - } - } - if (i.log2_scale_factor != 0 && i.index_reg == 0) - { - as_warn (_("scale factor of %d without an index register"), - 1 << i.log2_scale_factor); - i.log2_scale_factor = 0; - } - scale = input_line_pointer; - input_line_pointer = save; - return scale; -} - -static int -i386_displacement (char *disp_start, char *disp_end) -{ - expressionS *exp; - segT exp_seg = 0; - char *save_input_line_pointer; - char *gotfree_input_line; - int override; - i386_operand_type bigdisp, types = anydisp; - int ret; - - if (i.disp_operands == MAX_MEMORY_OPERANDS) - { - as_bad (_("at most %d displacement operands are allowed"), - MAX_MEMORY_OPERANDS); - return 0; - } - - operand_type_set (&bigdisp, 0); - if ((i.types[this_operand].bitfield.jumpabsolute) - || (!current_templates->start->opcode_modifier.jump - && !current_templates->start->opcode_modifier.jumpdword)) - { - bigdisp.bitfield.disp32 = 1; - override = (i.prefix[ADDR_PREFIX] != 0); - if (flag_code == CODE_64BIT) - { - if (!override) - { - bigdisp.bitfield.disp32s = 1; - bigdisp.bitfield.disp64 = 1; - } - } - else if ((flag_code == CODE_16BIT) ^ override) - { - bigdisp.bitfield.disp32 = 0; - bigdisp.bitfield.disp16 = 1; - } - } - else - { - /* For PC-relative branches, the width of the displacement - is dependent upon data size, not address size. */ - override = (i.prefix[DATA_PREFIX] != 0); - if (flag_code == CODE_64BIT) - { - if (override || i.suffix == WORD_MNEM_SUFFIX) - bigdisp.bitfield.disp16 = 1; - else - { - bigdisp.bitfield.disp32 = 1; - bigdisp.bitfield.disp32s = 1; - } - } - else - { - if (!override) - override = (i.suffix == (flag_code != CODE_16BIT - ? WORD_MNEM_SUFFIX - : LONG_MNEM_SUFFIX)); - bigdisp.bitfield.disp32 = 1; - if ((flag_code == CODE_16BIT) ^ override) - { - bigdisp.bitfield.disp32 = 0; - bigdisp.bitfield.disp16 = 1; - } - } - } - i.types[this_operand] = operand_type_or (i.types[this_operand], - bigdisp); - - exp = &disp_expressions[i.disp_operands]; - i.op[this_operand].disps = exp; - i.disp_operands++; - save_input_line_pointer = input_line_pointer; - input_line_pointer = disp_start; - END_STRING_AND_SAVE (disp_end); - -#ifndef GCC_ASM_O_HACK -#define GCC_ASM_O_HACK 0 -#endif -#if GCC_ASM_O_HACK - END_STRING_AND_SAVE (disp_end + 1); - if (i.types[this_operand].bitfield.baseIndex - && displacement_string_end[-1] == '+') - { - /* This hack is to avoid a warning when using the "o" - constraint within gcc asm statements. - For instance: - - #define _set_tssldt_desc(n,addr,limit,type) \ - __asm__ __volatile__ ( \ - "movw %w2,%0\n\t" \ - "movw %w1,2+%0\n\t" \ - "rorl $16,%1\n\t" \ - "movb %b1,4+%0\n\t" \ - "movb %4,5+%0\n\t" \ - "movb $0,6+%0\n\t" \ - "movb %h1,7+%0\n\t" \ - "rorl $16,%1" \ - : "=o"(*(n)) : "q" (addr), "ri"(limit), "i"(type)) - - This works great except that the output assembler ends - up looking a bit weird if it turns out that there is - no offset. You end up producing code that looks like: - - #APP - movw $235,(%eax) - movw %dx,2+(%eax) - rorl $16,%edx - movb %dl,4+(%eax) - movb $137,5+(%eax) - movb $0,6+(%eax) - movb %dh,7+(%eax) - rorl $16,%edx - #NO_APP - - So here we provide the missing zero. */ - - *displacement_string_end = '0'; - } -#endif - gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types, - (i.bnd_prefix != NULL - || add_bnd_prefix)); - if (gotfree_input_line) - input_line_pointer = gotfree_input_line; - - exp_seg = expression (exp); - - SKIP_WHITESPACE (); - if (*input_line_pointer) - as_bad (_("junk `%s' after expression"), input_line_pointer); -#if GCC_ASM_O_HACK - RESTORE_END_STRING (disp_end + 1); -#endif - input_line_pointer = save_input_line_pointer; - if (gotfree_input_line) - { - free (gotfree_input_line); - - if (exp->X_op == O_constant || exp->X_op == O_register) - exp->X_op = O_illegal; - } - - ret = i386_finalize_displacement (exp_seg, exp, types, disp_start); - - RESTORE_END_STRING (disp_end); - - return ret; -} - -static int -i386_finalize_displacement (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp, - i386_operand_type types, const char *disp_start) -{ - i386_operand_type bigdisp; - int ret = 1; - - /* We do this to make sure that the section symbol is in - the symbol table. We will ultimately change the relocation - to be relative to the beginning of the section. */ - if (i.reloc[this_operand] == BFD_RELOC_386_GOTOFF - || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL - || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTOFF64) - { - if (exp->X_op != O_symbol) - goto inv_disp; - - if (S_IS_LOCAL (exp->X_add_symbol) - && S_GET_SEGMENT (exp->X_add_symbol) != undefined_section - && S_GET_SEGMENT (exp->X_add_symbol) != expr_section) - section_symbol (S_GET_SEGMENT (exp->X_add_symbol)); - exp->X_op = O_subtract; - exp->X_op_symbol = GOT_symbol; - if (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL) - i.reloc[this_operand] = BFD_RELOC_32_PCREL; - else if (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTOFF64) - i.reloc[this_operand] = BFD_RELOC_64; - else - i.reloc[this_operand] = BFD_RELOC_32; - } - - else if (exp->X_op == O_absent - || exp->X_op == O_illegal - || exp->X_op == O_big) - { - inv_disp: - as_bad (_("missing or invalid displacement expression `%s'"), - disp_start); - ret = 0; - } - - else if (flag_code == CODE_64BIT - && !i.prefix[ADDR_PREFIX] - && exp->X_op == O_constant) - { - /* Since displacement is signed extended to 64bit, don't allow - disp32 and turn off disp32s if they are out of range. */ - i.types[this_operand].bitfield.disp32 = 0; - if (!fits_in_signed_long (exp->X_add_number)) - { - i.types[this_operand].bitfield.disp32s = 0; - if (i.types[this_operand].bitfield.baseindex) - { - as_bad (_("0x%lx out range of signed 32bit displacement"), - (long) exp->X_add_number); - ret = 0; - } - } - } - -#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT)) - else if (exp->X_op != O_constant - && OUTPUT_FLAVOR == bfd_target_aout_flavour - && exp_seg != absolute_section - && exp_seg != text_section - && exp_seg != data_section - && exp_seg != bss_section - && exp_seg != undefined_section - && !bfd_is_com_section (exp_seg)) - { - as_bad (_("unimplemented segment %s in operand"), exp_seg->name); - ret = 0; - } -#endif - - /* Check if this is a displacement only operand. */ - bigdisp = i.types[this_operand]; - bigdisp.bitfield.disp8 = 0; - bigdisp.bitfield.disp16 = 0; - bigdisp.bitfield.disp32 = 0; - bigdisp.bitfield.disp32s = 0; - bigdisp.bitfield.disp64 = 0; - if (operand_type_all_zero (&bigdisp)) - i.types[this_operand] = operand_type_and (i.types[this_operand], - types); - - return ret; -} - -/* Make sure the memory operand we've been dealt is valid. - Return 1 on success, 0 on a failure. */ - -static int -i386_index_check (const char *operand_string) -{ - const char *kind = "base/index"; - enum flag_code addr_mode; - - if (i.prefix[ADDR_PREFIX]) - addr_mode = flag_code == CODE_32BIT ? CODE_16BIT : CODE_32BIT; - else - { - addr_mode = flag_code; - -#if INFER_ADDR_PREFIX - if (i.mem_operands == 0) - { - /* Infer address prefix from the first memory operand. */ - const reg_entry *addr_reg = i.base_reg; - - if (addr_reg == NULL) - addr_reg = i.index_reg; - - if (addr_reg) - { - if (addr_reg->reg_num == RegEip - || addr_reg->reg_num == RegEiz - || addr_reg->reg_type.bitfield.reg32) - addr_mode = CODE_32BIT; - else if (flag_code != CODE_64BIT - && addr_reg->reg_type.bitfield.reg16) - addr_mode = CODE_16BIT; - - if (addr_mode != flag_code) - { - i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE; - i.prefixes += 1; - /* Change the size of any displacement too. At most one - of Disp16 or Disp32 is set. - FIXME. There doesn't seem to be any real need for - separate Disp16 and Disp32 flags. The same goes for - Imm16 and Imm32. Removing them would probably clean - up the code quite a lot. */ - if (flag_code != CODE_64BIT - && (i.types[this_operand].bitfield.disp16 - || i.types[this_operand].bitfield.disp32)) - i.types[this_operand] - = operand_type_xor (i.types[this_operand], disp16_32); - } - } - } -#endif - } - - if (current_templates->start->opcode_modifier.isstring - && !current_templates->start->opcode_modifier.immext - && (current_templates->end[-1].opcode_modifier.isstring - || i.mem_operands)) - { - /* Memory operands of string insns are special in that they only allow - a single register (rDI, rSI, or rBX) as their memory address. */ - const reg_entry *expected_reg; - static const char *di_si[][2] = - { - { "esi", "edi" }, - { "si", "di" }, - { "rsi", "rdi" } - }; - static const char *bx[] = { "ebx", "bx", "rbx" }; - - kind = "string address"; - - if (current_templates->start->opcode_modifier.w) - { - i386_operand_type type = current_templates->end[-1].operand_types[0]; - - if (!type.bitfield.baseindex - || ((!i.mem_operands != !intel_syntax) - && current_templates->end[-1].operand_types[1] - .bitfield.baseindex)) - type = current_templates->end[-1].operand_types[1]; - expected_reg = hash_find (reg_hash, - di_si[addr_mode][type.bitfield.esseg]); - - } - else - expected_reg = hash_find (reg_hash, bx[addr_mode]); - - if (i.base_reg != expected_reg - || i.index_reg - || operand_type_check (i.types[this_operand], disp)) - { - /* The second memory operand must have the same size as - the first one. */ - if (i.mem_operands - && i.base_reg - && !((addr_mode == CODE_64BIT - && i.base_reg->reg_type.bitfield.reg64) - || (addr_mode == CODE_32BIT - ? i.base_reg->reg_type.bitfield.reg32 - : i.base_reg->reg_type.bitfield.reg16))) - goto bad_address; - - as_warn (_("`%s' is not valid here (expected `%c%s%s%c')"), - operand_string, - intel_syntax ? '[' : '(', - register_prefix, - expected_reg->reg_name, - intel_syntax ? ']' : ')'); - return 1; - } - else - return 1; - -bad_address: - as_bad (_("`%s' is not a valid %s expression"), - operand_string, kind); - return 0; - } - else - { - if (addr_mode != CODE_16BIT) - { - /* 32-bit/64-bit checks. */ - if ((i.base_reg - && (addr_mode == CODE_64BIT - ? !i.base_reg->reg_type.bitfield.reg64 - : !i.base_reg->reg_type.bitfield.reg32) - && (i.index_reg - || (i.base_reg->reg_num - != (addr_mode == CODE_64BIT ? RegRip : RegEip)))) - || (i.index_reg - && !i.index_reg->reg_type.bitfield.regxmm - && !i.index_reg->reg_type.bitfield.regymm - && !i.index_reg->reg_type.bitfield.regzmm - && ((addr_mode == CODE_64BIT - ? !(i.index_reg->reg_type.bitfield.reg64 - || i.index_reg->reg_num == RegRiz) - : !(i.index_reg->reg_type.bitfield.reg32 - || i.index_reg->reg_num == RegEiz)) - || !i.index_reg->reg_type.bitfield.baseindex))) - goto bad_address; - } - else - { - /* 16-bit checks. */ - if ((i.base_reg - && (!i.base_reg->reg_type.bitfield.reg16 - || !i.base_reg->reg_type.bitfield.baseindex)) - || (i.index_reg - && (!i.index_reg->reg_type.bitfield.reg16 - || !i.index_reg->reg_type.bitfield.baseindex - || !(i.base_reg - && i.base_reg->reg_num < 6 - && i.index_reg->reg_num >= 6 - && i.log2_scale_factor == 0)))) - goto bad_address; - } - } - return 1; -} - -/* Handle vector immediates. */ - -static int -RC_SAE_immediate (const char *imm_start) -{ - unsigned int match_found, j; - const char *pstr = imm_start; - expressionS *exp; - - if (*pstr != '{') - return 0; - - pstr++; - match_found = 0; - for (j = 0; j < ARRAY_SIZE (RC_NamesTable); j++) - { - if (!strncmp (pstr, RC_NamesTable[j].name, RC_NamesTable[j].len)) - { - if (!i.rounding) - { - rc_op.type = RC_NamesTable[j].type; - rc_op.operand = this_operand; - i.rounding = &rc_op; - } - else - { - as_bad (_("duplicated `%s'"), imm_start); - return 0; - } - pstr += RC_NamesTable[j].len; - match_found = 1; - break; - } - } - if (!match_found) - return 0; - - if (*pstr++ != '}') - { - as_bad (_("Missing '}': '%s'"), imm_start); - return 0; - } - /* RC/SAE immediate string should contain nothing more. */; - if (*pstr != 0) - { - as_bad (_("Junk after '}': '%s'"), imm_start); - return 0; - } - - exp = &im_expressions[i.imm_operands++]; - i.op[this_operand].imms = exp; - - exp->X_op = O_constant; - exp->X_add_number = 0; - exp->X_add_symbol = (symbolS *) 0; - exp->X_op_symbol = (symbolS *) 0; - - i.types[this_operand].bitfield.imm8 = 1; - return 1; -} - -/* Parse OPERAND_STRING into the i386_insn structure I. Returns zero - on error. */ - -static int -i386_att_operand (char *operand_string) -{ - const reg_entry *r; - char *end_op; - char *op_string = operand_string; - - if (is_space_char (*op_string)) - ++op_string; - - /* We check for an absolute prefix (differentiating, - for example, 'jmp pc_relative_label' from 'jmp *absolute_label'. */ - if (*op_string == ABSOLUTE_PREFIX) - { - ++op_string; - if (is_space_char (*op_string)) - ++op_string; - i.types[this_operand].bitfield.jumpabsolute = 1; - } - - /* Check if operand is a register. */ - if ((r = parse_register (op_string, &end_op)) != NULL) - { - i386_operand_type temp; - - /* Check for a segment override by searching for ':' after a - segment register. */ - op_string = end_op; - if (is_space_char (*op_string)) - ++op_string; - if (*op_string == ':' - && (r->reg_type.bitfield.sreg2 - || r->reg_type.bitfield.sreg3)) - { - switch (r->reg_num) - { - case 0: - i.seg[i.mem_operands] = &es; - break; - case 1: - i.seg[i.mem_operands] = &cs; - break; - case 2: - i.seg[i.mem_operands] = &ss; - break; - case 3: - i.seg[i.mem_operands] = &ds; - break; - case 4: - i.seg[i.mem_operands] = &fs; - break; - case 5: - i.seg[i.mem_operands] = &gs; - break; - } - - /* Skip the ':' and whitespace. */ - ++op_string; - if (is_space_char (*op_string)) - ++op_string; - - if (!is_digit_char (*op_string) - && !is_identifier_char (*op_string) - && *op_string != '(' - && *op_string != ABSOLUTE_PREFIX) - { - as_bad (_("bad memory operand `%s'"), op_string); - return 0; - } - /* Handle case of %es:*foo. */ - if (*op_string == ABSOLUTE_PREFIX) - { - ++op_string; - if (is_space_char (*op_string)) - ++op_string; - i.types[this_operand].bitfield.jumpabsolute = 1; - } - goto do_memory_reference; - } - - /* Handle vector operations. */ - if (*op_string == '{') - { - op_string = check_VecOperations (op_string, NULL); - if (op_string == NULL) - return 0; - } - - if (*op_string) - { - as_bad (_("junk `%s' after register"), op_string); - return 0; - } - temp = r->reg_type; - 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++; - } - else if (*op_string == REGISTER_PREFIX) - { - as_bad (_("bad register name `%s'"), op_string); - return 0; - } - else if (*op_string == IMMEDIATE_PREFIX) - { - ++op_string; - if (i.types[this_operand].bitfield.jumpabsolute) - { - as_bad (_("immediate operand illegal with absolute jump")); - return 0; - } - if (!i386_immediate (op_string)) - return 0; - } - else if (RC_SAE_immediate (operand_string)) - { - /* If it is a RC or SAE immediate, do nothing. */ - ; - } - else if (is_digit_char (*op_string) - || is_identifier_char (*op_string) - || *op_string == '(') - { - /* This is a memory reference of some sort. */ - char *base_string; - - /* Start and end of displacement string expression (if found). */ - char *displacement_string_start; - char *displacement_string_end; - char *vop_start; - - do_memory_reference: - if ((i.mem_operands == 1 - && !current_templates->start->opcode_modifier.isstring) - || i.mem_operands == 2) - { - as_bad (_("too many memory references for `%s'"), - current_templates->start->name); - return 0; - } - - /* Check for base index form. We detect the base index form by - looking for an ')' at the end of the operand, searching - for the '(' matching it, and finding a REGISTER_PREFIX or ',' - after the '('. */ - base_string = op_string + strlen (op_string); - - /* Handle vector operations. */ - vop_start = strchr (op_string, '{'); - if (vop_start && vop_start < base_string) - { - if (check_VecOperations (vop_start, base_string) == NULL) - return 0; - base_string = vop_start; - } - - --base_string; - if (is_space_char (*base_string)) - --base_string; - - /* If we only have a displacement, set-up for it to be parsed later. */ - displacement_string_start = op_string; - displacement_string_end = base_string + 1; - - if (*base_string == ')') - { - char *temp_string; - unsigned int parens_balanced = 1; - /* We've already checked that the number of left & right ()'s are - equal, so this loop will not be infinite. */ - do - { - base_string--; - if (*base_string == ')') - parens_balanced++; - if (*base_string == '(') - parens_balanced--; - } - while (parens_balanced); - - temp_string = base_string; - - /* Skip past '(' and whitespace. */ - ++base_string; - if (is_space_char (*base_string)) - ++base_string; - - if (*base_string == ',' - || ((i.base_reg = parse_register (base_string, &end_op)) - != NULL)) - { - displacement_string_end = temp_string; - - i.types[this_operand].bitfield.baseindex = 1; - - if (i.base_reg) - { - base_string = end_op; - if (is_space_char (*base_string)) - ++base_string; - } - - /* There may be an index reg or scale factor here. */ - if (*base_string == ',') - { - ++base_string; - if (is_space_char (*base_string)) - ++base_string; - - if ((i.index_reg = parse_register (base_string, &end_op)) - != NULL) - { - base_string = end_op; - if (is_space_char (*base_string)) - ++base_string; - if (*base_string == ',') - { - ++base_string; - if (is_space_char (*base_string)) - ++base_string; - } - else if (*base_string != ')') - { - as_bad (_("expecting `,' or `)' " - "after index register in `%s'"), - operand_string); - return 0; - } - } - else if (*base_string == REGISTER_PREFIX) - { - end_op = strchr (base_string, ','); - if (end_op) - *end_op = '\0'; - as_bad (_("bad register name `%s'"), base_string); - return 0; - } - - /* Check for scale factor. */ - if (*base_string != ')') - { - char *end_scale = i386_scale (base_string); - - if (!end_scale) - return 0; - - base_string = end_scale; - if (is_space_char (*base_string)) - ++base_string; - if (*base_string != ')') - { - as_bad (_("expecting `)' " - "after scale factor in `%s'"), - operand_string); - return 0; - } - } - else if (!i.index_reg) - { - as_bad (_("expecting index register or scale factor " - "after `,'; got '%c'"), - *base_string); - return 0; - } - } - else if (*base_string != ')') - { - as_bad (_("expecting `,' or `)' " - "after base register in `%s'"), - operand_string); - return 0; - } - } - else if (*base_string == REGISTER_PREFIX) - { - end_op = strchr (base_string, ','); - if (end_op) - *end_op = '\0'; - as_bad (_("bad register name `%s'"), base_string); - return 0; - } - } - - /* If there's an expression beginning the operand, parse it, - assuming displacement_string_start and - displacement_string_end are meaningful. */ - if (displacement_string_start != displacement_string_end) - { - if (!i386_displacement (displacement_string_start, - displacement_string_end)) - return 0; - } - - /* Special case for (%dx) while doing input/output op. */ - if (i.base_reg - && 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)) - { - 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 - { - /* It's not a memory operand; argh! */ - as_bad (_("invalid char %s beginning operand %d `%s'"), - output_invalid (*op_string), - this_operand + 1, - op_string); - return 0; - } - return 1; /* Normal return. */ -} - -/* Calculate the maximum variable size (i.e., excluding fr_fix) - that an rs_machine_dependent frag may reach. */ - -unsigned int -i386_frag_max_var (fragS *frag) -{ - /* The only relaxable frags are for jumps. - Unconditional jumps can grow by 4 bytes and others by 5 bytes. */ - gas_assert (frag->fr_type == rs_machine_dependent); - return TYPE_FROM_RELAX_STATE (frag->fr_subtype) == UNCOND_JUMP ? 4 : 5; -} - -/* md_estimate_size_before_relax() - - Called just before relax() for rs_machine_dependent frags. The x86 - assembler uses these frags to handle variable size jump - instructions. - - Any symbol that is now undefined will not become defined. - Return the correct fr_subtype in the frag. - Return the initial "guess for variable size of frag" to caller. - The guess is actually the growth beyond the fixed part. Whatever - we do to grow the fixed or variable part contributes to our - returned value. */ - -int -md_estimate_size_before_relax (fragS *fragP, segT segment) -{ - /* We've already got fragP->fr_subtype right; all we have to do is - check for un-relaxable symbols. On an ELF system, we can't relax - an externally visible symbol, because it may be overridden by a - shared library. */ - if (S_GET_SEGMENT (fragP->fr_symbol) != segment -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - || (IS_ELF - && (S_IS_EXTERNAL (fragP->fr_symbol) - || S_IS_WEAK (fragP->fr_symbol) - || ((symbol_get_bfdsym (fragP->fr_symbol)->flags - & BSF_GNU_INDIRECT_FUNCTION)))) -#endif -#if defined (OBJ_COFF) && defined (TE_PE) - || (OUTPUT_FLAVOR == bfd_target_coff_flavour - && S_IS_WEAK (fragP->fr_symbol)) -#endif - ) - { - /* Symbol is undefined in this segment, or we need to keep a - reloc so that weak symbols can be overridden. */ - int size = (fragP->fr_subtype & CODE16) ? 2 : 4; - enum bfd_reloc_code_real reloc_type; - unsigned char *opcode; - int old_fr_fix; - - if (fragP->fr_var != NO_RELOC) - reloc_type = (enum bfd_reloc_code_real) fragP->fr_var; - else if (size == 2) - reloc_type = BFD_RELOC_16_PCREL; - else - reloc_type = BFD_RELOC_32_PCREL; - - old_fr_fix = fragP->fr_fix; - opcode = (unsigned char *) fragP->fr_opcode; - - switch (TYPE_FROM_RELAX_STATE (fragP->fr_subtype)) - { - case UNCOND_JUMP: - /* Make jmp (0xeb) a (d)word displacement jump. */ - opcode[0] = 0xe9; - fragP->fr_fix += size; - fix_new (fragP, old_fr_fix, size, - fragP->fr_symbol, - fragP->fr_offset, 1, - reloc_type); - break; - - case COND_JUMP86: - if (size == 2 - && (!no_cond_jump_promotion || fragP->fr_var != NO_RELOC)) - { - /* Negate the condition, and branch past an - unconditional jump. */ - opcode[0] ^= 1; - opcode[1] = 3; - /* Insert an unconditional jump. */ - opcode[2] = 0xe9; - /* We added two extra opcode bytes, and have a two byte - offset. */ - fragP->fr_fix += 2 + 2; - fix_new (fragP, old_fr_fix + 2, 2, - fragP->fr_symbol, - fragP->fr_offset, 1, - reloc_type); - break; - } - /* Fall through. */ - - case COND_JUMP: - if (no_cond_jump_promotion && fragP->fr_var == NO_RELOC) - { - fixS *fixP; - - fragP->fr_fix += 1; - fixP = fix_new (fragP, old_fr_fix, 1, - fragP->fr_symbol, - fragP->fr_offset, 1, - BFD_RELOC_8_PCREL); - fixP->fx_signed = 1; - break; - } - - /* This changes the byte-displacement jump 0x7N - to the (d)word-displacement jump 0x0f,0x8N. */ - opcode[1] = opcode[0] + 0x10; - opcode[0] = TWO_BYTE_OPCODE_ESCAPE; - /* We've added an opcode byte. */ - fragP->fr_fix += 1 + size; - fix_new (fragP, old_fr_fix + 1, size, - fragP->fr_symbol, - fragP->fr_offset, 1, - reloc_type); - break; - - default: - BAD_CASE (fragP->fr_subtype); - break; - } - frag_wane (fragP); - return fragP->fr_fix - old_fr_fix; - } - - /* Guess size depending on current relax state. Initially the relax - state will correspond to a short jump and we return 1, because - the variable part of the frag (the branch offset) is one byte - long. However, we can relax a section more than once and in that - case we must either set fr_subtype back to the unrelaxed state, - or return the value for the appropriate branch. */ - return md_relax_table[fragP->fr_subtype].rlx_length; -} - -/* Called after relax() is finished. - - In: Address of frag. - fr_type == rs_machine_dependent. - fr_subtype is what the address relaxed to. - - Out: Any fixSs and constants are set up. - Caller will turn frag into a ".space 0". */ - -void -md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, - fragS *fragP) -{ - unsigned char *opcode; - unsigned char *where_to_put_displacement = NULL; - offsetT target_address; - offsetT opcode_address; - unsigned int extension = 0; - offsetT displacement_from_opcode_start; - - opcode = (unsigned char *) fragP->fr_opcode; - - /* Address we want to reach in file space. */ - target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset; - - /* Address opcode resides at in file space. */ - opcode_address = fragP->fr_address + fragP->fr_fix; - - /* Displacement from opcode start to fill into instruction. */ - displacement_from_opcode_start = target_address - opcode_address; - - if ((fragP->fr_subtype & BIG) == 0) - { - /* Don't have to change opcode. */ - extension = 1; /* 1 opcode + 1 displacement */ - where_to_put_displacement = &opcode[1]; - } - else - { - if (no_cond_jump_promotion - && TYPE_FROM_RELAX_STATE (fragP->fr_subtype) != UNCOND_JUMP) - as_warn_where (fragP->fr_file, fragP->fr_line, - _("long jump required")); - - switch (fragP->fr_subtype) - { - case ENCODE_RELAX_STATE (UNCOND_JUMP, BIG): - extension = 4; /* 1 opcode + 4 displacement */ - opcode[0] = 0xe9; - where_to_put_displacement = &opcode[1]; - break; - - case ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16): - extension = 2; /* 1 opcode + 2 displacement */ - opcode[0] = 0xe9; - where_to_put_displacement = &opcode[1]; - break; - - case ENCODE_RELAX_STATE (COND_JUMP, BIG): - case ENCODE_RELAX_STATE (COND_JUMP86, BIG): - extension = 5; /* 2 opcode + 4 displacement */ - opcode[1] = opcode[0] + 0x10; - opcode[0] = TWO_BYTE_OPCODE_ESCAPE; - where_to_put_displacement = &opcode[2]; - break; - - case ENCODE_RELAX_STATE (COND_JUMP, BIG16): - extension = 3; /* 2 opcode + 2 displacement */ - opcode[1] = opcode[0] + 0x10; - opcode[0] = TWO_BYTE_OPCODE_ESCAPE; - where_to_put_displacement = &opcode[2]; - break; - - case ENCODE_RELAX_STATE (COND_JUMP86, BIG16): - extension = 4; - opcode[0] ^= 1; - opcode[1] = 3; - opcode[2] = 0xe9; - where_to_put_displacement = &opcode[3]; - break; - - default: - BAD_CASE (fragP->fr_subtype); - break; - } - } - - /* If size if less then four we are sure that the operand fits, - but if it's 4, then it could be that the displacement is larger - then -/+ 2GB. */ - if (DISP_SIZE_FROM_RELAX_STATE (fragP->fr_subtype) == 4 - && object_64bit - && ((addressT) (displacement_from_opcode_start - extension - + ((addressT) 1 << 31)) - > (((addressT) 2 << 31) - 1))) - { - as_bad_where (fragP->fr_file, fragP->fr_line, - _("jump target out of range")); - /* Make us emit 0. */ - displacement_from_opcode_start = extension; - } - /* Now put displacement after opcode. */ - md_number_to_chars ((char *) where_to_put_displacement, - (valueT) (displacement_from_opcode_start - extension), - DISP_SIZE_FROM_RELAX_STATE (fragP->fr_subtype)); - fragP->fr_fix += extension; -} - -/* Apply a fixup (fixP) to segment data, once it has been determined - by our caller that we have all the info we need to fix it up. - - Parameter valP is the pointer to the value of the bits. - - On the 386, immediates, displacements, and data pointers are all in - the same (little-endian) format, so we don't need to care about which - we are handling. */ - -void -md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) -{ - char *p = fixP->fx_where + fixP->fx_frag->fr_literal; - valueT value = *valP; - -#if !defined (TE_Mach) - if (fixP->fx_pcrel) - { - switch (fixP->fx_r_type) - { - default: - break; - - case BFD_RELOC_64: - fixP->fx_r_type = BFD_RELOC_64_PCREL; - break; - case BFD_RELOC_32: - case BFD_RELOC_X86_64_32S: - fixP->fx_r_type = BFD_RELOC_32_PCREL; - break; - case BFD_RELOC_16: - fixP->fx_r_type = BFD_RELOC_16_PCREL; - break; - case BFD_RELOC_8: - fixP->fx_r_type = BFD_RELOC_8_PCREL; - break; - } - } - - if (fixP->fx_addsy != NULL - && (fixP->fx_r_type == BFD_RELOC_32_PCREL - || fixP->fx_r_type == BFD_RELOC_64_PCREL - || fixP->fx_r_type == BFD_RELOC_16_PCREL - || fixP->fx_r_type == BFD_RELOC_8_PCREL - || fixP->fx_r_type == BFD_RELOC_X86_64_PC32_BND) - && !use_rela_relocations) - { - /* This is a hack. There should be a better way to handle this. - This covers for the fact that bfd_install_relocation will - subtract the current location (for partial_inplace, PC relative - relocations); see more below. */ -#ifndef OBJ_AOUT - if (IS_ELF -#ifdef TE_PE - || OUTPUT_FLAVOR == bfd_target_coff_flavour -#endif - ) - value += fixP->fx_where + fixP->fx_frag->fr_address; -#endif -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - if (IS_ELF) - { - segT sym_seg = S_GET_SEGMENT (fixP->fx_addsy); - - if ((sym_seg == seg - || (symbol_section_p (fixP->fx_addsy) - && sym_seg != absolute_section)) - && !generic_force_reloc (fixP)) - { - /* Yes, we add the values in twice. This is because - bfd_install_relocation subtracts them out again. I think - bfd_install_relocation is broken, but I don't dare change - it. FIXME. */ - value += fixP->fx_where + fixP->fx_frag->fr_address; - } - } -#endif -#if defined (OBJ_COFF) && defined (TE_PE) - /* For some reason, the PE format does not store a - section address offset for a PC relative symbol. */ - if (S_GET_SEGMENT (fixP->fx_addsy) != seg - || S_IS_WEAK (fixP->fx_addsy)) - value += md_pcrel_from (fixP); -#endif - } -#if defined (OBJ_COFF) && defined (TE_PE) - if (fixP->fx_addsy != NULL && S_IS_WEAK (fixP->fx_addsy)) - { - value -= S_GET_VALUE (fixP->fx_addsy); - } -#endif - - /* Fix a few things - the dynamic linker expects certain values here, - and we must not disappoint it. */ -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - if (IS_ELF && fixP->fx_addsy) - switch (fixP->fx_r_type) - { - case BFD_RELOC_386_PLT32: - case BFD_RELOC_X86_64_PLT32: - case BFD_RELOC_X86_64_PLT32_BND: - /* Make the jump instruction point to the address of the operand. At - runtime we merely add the offset to the actual PLT entry. */ - value = -4; - break; - - case BFD_RELOC_386_TLS_GD: - case BFD_RELOC_386_TLS_LDM: - case BFD_RELOC_386_TLS_IE_32: - case BFD_RELOC_386_TLS_IE: - case BFD_RELOC_386_TLS_GOTIE: - case BFD_RELOC_386_TLS_GOTDESC: - case BFD_RELOC_X86_64_TLSGD: - case BFD_RELOC_X86_64_TLSLD: - case BFD_RELOC_X86_64_GOTTPOFF: - case BFD_RELOC_X86_64_GOTPC32_TLSDESC: - value = 0; /* Fully resolved at runtime. No addend. */ - /* Fallthrough */ - case BFD_RELOC_386_TLS_LE: - case BFD_RELOC_386_TLS_LDO_32: - case BFD_RELOC_386_TLS_LE_32: - case BFD_RELOC_X86_64_DTPOFF32: - case BFD_RELOC_X86_64_DTPOFF64: - case BFD_RELOC_X86_64_TPOFF32: - case BFD_RELOC_X86_64_TPOFF64: - S_SET_THREAD_LOCAL (fixP->fx_addsy); - break; - - case BFD_RELOC_386_TLS_DESC_CALL: - case BFD_RELOC_X86_64_TLSDESC_CALL: - value = 0; /* Fully resolved at runtime. No addend. */ - S_SET_THREAD_LOCAL (fixP->fx_addsy); - fixP->fx_done = 0; - return; - - case BFD_RELOC_386_GOT32: - case BFD_RELOC_X86_64_GOT32: - value = 0; /* Fully resolved at runtime. No addend. */ - break; - - case BFD_RELOC_VTABLE_INHERIT: - case BFD_RELOC_VTABLE_ENTRY: - fixP->fx_done = 0; - return; - - default: - break; - } -#endif /* defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) */ - *valP = value; -#endif /* !defined (TE_Mach) */ - - /* Are we finished with this relocation now? */ - if (fixP->fx_addsy == NULL) - fixP->fx_done = 1; -#if defined (OBJ_COFF) && defined (TE_PE) - else if (fixP->fx_addsy != NULL && S_IS_WEAK (fixP->fx_addsy)) - { - fixP->fx_done = 0; - /* Remember value for tc_gen_reloc. */ - fixP->fx_addnumber = value; - /* Clear out the frag for now. */ - value = 0; - } -#endif - else if (use_rela_relocations) - { - fixP->fx_no_overflow = 1; - /* Remember value for tc_gen_reloc. */ - fixP->fx_addnumber = value; - value = 0; - } - - md_number_to_chars (p, value, fixP->fx_size); -} - -char * -md_atof (int type, char *litP, int *sizeP) -{ - /* 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]; - -static char * -output_invalid (int c) -{ - if (ISPRINT (c)) - snprintf (output_invalid_buf, sizeof (output_invalid_buf), - "'%c'", c); - else - snprintf (output_invalid_buf, sizeof (output_invalid_buf), - "(0x%x)", (unsigned char) c); - return output_invalid_buf; -} - -/* REG_STRING starts *before* REGISTER_PREFIX. */ - -static const reg_entry * -parse_real_register (char *reg_string, char **end_op) -{ - char *s = reg_string; - char *p; - char reg_name_given[MAX_REG_NAME_SIZE + 1]; - const reg_entry *r; - - /* Skip possible REGISTER_PREFIX and possible whitespace. */ - if (*s == REGISTER_PREFIX) - ++s; - - if (is_space_char (*s)) - ++s; - - p = reg_name_given; - while ((*p++ = register_chars[(unsigned char) *s]) != '\0') - { - if (p >= reg_name_given + MAX_REG_NAME_SIZE) - return (const reg_entry *) NULL; - s++; - } - - /* For naked regs, make sure that we are not dealing with an identifier. - This prevents confusing an identifier like `eax_var' with register - `eax'. */ - if (allow_naked_reg && identifier_chars[(unsigned char) *s]) - return (const reg_entry *) NULL; - - *end_op = s; - - r = (const reg_entry *) hash_find (reg_hash, reg_name_given); - - /* Handle floating point regs, allowing spaces in the (i) part. */ - if (r == i386_regtab /* %st is first entry of table */) - { - if (is_space_char (*s)) - ++s; - if (*s == '(') - { - ++s; - if (is_space_char (*s)) - ++s; - if (*s >= '0' && *s <= '7') - { - int fpr = *s - '0'; - ++s; - if (is_space_char (*s)) - ++s; - if (*s == ')') - { - *end_op = s + 1; - r = (const reg_entry *) hash_find (reg_hash, "st(0)"); - know (r); - return r + fpr; - } - } - /* We have "%st(" then garbage. */ - return (const reg_entry *) NULL; - } - } - - 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.floatreg - && !cpu_arch_flags.bitfield.cpu8087 - && !cpu_arch_flags.bitfield.cpu287 - && !cpu_arch_flags.bitfield.cpu387) - 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; - - if (r->reg_type.bitfield.regymm && !cpu_arch_flags.bitfield.cpuavx) - return (const reg_entry *) NULL; - - if ((r->reg_type.bitfield.regzmm || r->reg_type.bitfield.regmask) - && !cpu_arch_flags.bitfield.cpuavx512f) - return (const reg_entry *) NULL; - - /* Don't allow fake index register unless allow_index_reg isn't 0. */ - if (!allow_index_reg - && (r->reg_num == RegEiz || r->reg_num == RegRiz)) - return (const reg_entry *) NULL; - - /* Upper 16 vector register is only available with VREX in 64bit - mode. */ - if ((r->reg_flags & RegVRex)) - { - if (!cpu_arch_flags.bitfield.cpuvrex - || flag_code != CODE_64BIT) - return (const reg_entry *) NULL; - - i.need_vrex = 1; - } - - if (((r->reg_flags & (RegRex64 | RegRex)) - || r->reg_type.bitfield.reg64) - && (!cpu_arch_flags.bitfield.cpulm - || !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; -} - -/* REG_STRING starts *before* REGISTER_PREFIX. */ - -static const reg_entry * -parse_register (char *reg_string, char **end_op) -{ - const reg_entry *r; - - if (*reg_string == REGISTER_PREFIX || allow_naked_reg) - r = parse_real_register (reg_string, end_op); - else - r = NULL; - if (!r) - { - char *save = input_line_pointer; - char c; - symbolS *symbolP; - - input_line_pointer = reg_string; - c = get_symbol_end (); - symbolP = symbol_find (reg_string); - if (symbolP && S_GET_SEGMENT (symbolP) == reg_section) - { - const expressionS *e = symbol_get_value_expression (symbolP); - - know (e->X_op == O_register); - know (e->X_add_number >= 0 - && (valueT) e->X_add_number < i386_regtab_size); - r = i386_regtab + e->X_add_number; - *end_op = input_line_pointer; - } - *input_line_pointer = c; - input_line_pointer = save; - } - return r; -} - -int -i386_parse_name (char *name, expressionS *e, char *nextcharP) -{ - const reg_entry *r; - char *end = input_line_pointer; - - *end = *nextcharP; - r = parse_register (name, &input_line_pointer); - if (r && end <= input_line_pointer) - { - *nextcharP = *input_line_pointer; - *input_line_pointer = 0; - e->X_op = O_register; - e->X_add_number = r - i386_regtab; - return 1; - } - input_line_pointer = end; - *end = 0; - return intel_syntax ? i386_intel_parse_name (name, e) : 0; -} - -void -md_operand (expressionS *e) -{ - char *end; - const reg_entry *r; - - switch (*input_line_pointer) - { - case REGISTER_PREFIX: - r = parse_real_register (input_line_pointer, &end); - if (r) - { - e->X_op = O_register; - e->X_add_number = r - i386_regtab; - input_line_pointer = end; - } - break; - - case '[': - gas_assert (intel_syntax); - end = input_line_pointer++; - expression (e); - if (*input_line_pointer == ']') - { - ++input_line_pointer; - e->X_op_symbol = make_expr_symbol (e); - e->X_add_symbol = NULL; - e->X_add_number = 0; - e->X_op = O_index; - } - else - { - e->X_op = O_absent; - input_line_pointer = end; - } - break; - } -} - - -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) -const char *md_shortopts = "kVQ:sqn"; -#else -const char *md_shortopts = "qn"; -#endif - -#define OPTION_32 (OPTION_MD_BASE + 0) -#define OPTION_64 (OPTION_MD_BASE + 1) -#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) -#define OPTION_MSSE2AVX (OPTION_MD_BASE + 10) -#define OPTION_MSSE_CHECK (OPTION_MD_BASE + 11) -#define OPTION_MOPERAND_CHECK (OPTION_MD_BASE + 12) -#define OPTION_MAVXSCALAR (OPTION_MD_BASE + 13) -#define OPTION_X32 (OPTION_MD_BASE + 14) -#define OPTION_MADD_BND_PREFIX (OPTION_MD_BASE + 15) -#define OPTION_MEVEXLIG (OPTION_MD_BASE + 16) -#define OPTION_MEVEXWIG (OPTION_MD_BASE + 17) - -struct option md_longopts[] = -{ - {"32", no_argument, NULL, OPTION_32}, -#if (defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) \ - || defined (TE_PE) || defined (TE_PEP) || defined (OBJ_MACH_O)) - {"64", no_argument, NULL, OPTION_64}, -#endif -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - {"x32", no_argument, NULL, OPTION_X32}, -#endif - {"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}, - {"msse2avx", no_argument, NULL, OPTION_MSSE2AVX}, - {"msse-check", required_argument, NULL, OPTION_MSSE_CHECK}, - {"moperand-check", required_argument, NULL, OPTION_MOPERAND_CHECK}, - {"mavxscalar", required_argument, NULL, OPTION_MAVXSCALAR}, - {"madd-bnd-prefix", no_argument, NULL, OPTION_MADD_BND_PREFIX}, - {"mevexlig", required_argument, NULL, OPTION_MEVEXLIG}, - {"mevexwig", required_argument, NULL, OPTION_MEVEXWIG}, - {NULL, no_argument, NULL, 0} -}; -size_t md_longopts_size = sizeof (md_longopts); - -int -md_parse_option (int c, char *arg) -{ - unsigned int j; - char *arch, *next; - - switch (c) - { - case 'n': - optimize_align_code = 0; - break; - - case 'q': - quiet_warnings = 1; - break; - -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section - should be emitted or not. FIXME: Not implemented. */ - case 'Q': - break; - - /* -V: SVR4 argument to print version ID. */ - case 'V': - print_version_id (); - break; - - /* -k: Ignore for FreeBSD compatibility. */ - case 'k': - break; - - case 's': - /* -s: On i386 Solaris, this tells the native assembler to use - .stab instead of .stab.excl. We always use .stab anyhow. */ - break; -#endif -#if (defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) \ - || defined (TE_PE) || defined (TE_PEP) || defined (OBJ_MACH_O)) - case OPTION_64: - { - const char **list, **l; - - list = bfd_target_list (); - for (l = list; *l != NULL; l++) - if (CONST_STRNEQ (*l, "elf64-x86-64") - || strcmp (*l, "coff-x86-64") == 0 - || strcmp (*l, "pe-x86-64") == 0 - || strcmp (*l, "pei-x86-64") == 0 - || strcmp (*l, "mach-o-x86-64") == 0) - { - default_arch = "x86_64"; - break; - } - if (*l == NULL) - as_fatal (_("no compiled in support for x86_64")); - free (list); - } - break; -#endif - -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - case OPTION_X32: - if (IS_ELF) - { - const char **list, **l; - - list = bfd_target_list (); - for (l = list; *l != NULL; l++) - if (CONST_STRNEQ (*l, "elf32-x86-64")) - { - default_arch = "x86_64:32"; - break; - } - if (*l == NULL) - as_fatal (_("no compiled in support for 32bit x86_64")); - free (list); - } - else - as_fatal (_("32bit x86_64 is only supported for ELF")); - break; -#endif - - case OPTION_32: - default_arch = "i386"; - break; - - case OPTION_DIVIDE: -#ifdef SVR4_COMMENT_CHARS - { - char *n, *t; - const char *s; - - n = (char *) xmalloc (strlen (i386_comment_chars) + 1); - t = n; - for (s = i386_comment_chars; *s != '\0'; s++) - if (*s != '/') - *t++ = *s; - *t = '\0'; - i386_comment_chars = n; - } -#endif - break; - - case OPTION_MARCH: - arch = xstrdup (arg); - do - { - if (*arch == '.') - as_fatal (_("invalid -march= option: `%s'"), arg); - next = strchr (arch, '+'); - if (next) - *next++ = '\0'; - for (j = 0; j < ARRAY_SIZE (cpu_arch); j++) - { - if (strcmp (arch, cpu_arch [j].name) == 0) - { - /* Processor. */ - if (! cpu_arch[j].flags.bitfield.cpui386) - continue; - - cpu_arch_name = cpu_arch[j].name; - cpu_sub_arch_name = NULL; - cpu_arch_flags = cpu_arch[j].flags; - cpu_arch_isa = cpu_arch[j].type; - cpu_arch_isa_flags = cpu_arch[j].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 [j].name == '.' - && strcmp (arch, cpu_arch [j].name + 1) == 0) - { - /* ISA entension. */ - i386_cpu_flags flags; - - if (!cpu_arch[j].negated) - flags = cpu_flags_or (cpu_arch_flags, - cpu_arch[j].flags); - else - flags = cpu_flags_and_not (cpu_arch_flags, - cpu_arch[j].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[j].name, - (const char *) NULL); - free (name); - } - else - cpu_sub_arch_name = xstrdup (cpu_arch[j].name); - cpu_arch_flags = flags; - cpu_arch_isa_flags = flags; - } - break; - } - } - - if (j >= ARRAY_SIZE (cpu_arch)) - as_fatal (_("invalid -march= option: `%s'"), arg); - - arch = next; - } - while (next != NULL ); - break; - - case OPTION_MTUNE: - if (*arg == '.') - as_fatal (_("invalid -mtune= option: `%s'"), arg); - for (j = 0; j < ARRAY_SIZE (cpu_arch); j++) - { - if (strcmp (arg, cpu_arch [j].name) == 0) - { - cpu_arch_tune_set = 1; - cpu_arch_tune = cpu_arch [j].type; - cpu_arch_tune_flags = cpu_arch[j].flags; - break; - } - } - if (j >= ARRAY_SIZE (cpu_arch)) - 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; - - case OPTION_MSSE2AVX: - sse2avx = 1; - break; - - case OPTION_MSSE_CHECK: - if (strcasecmp (arg, "error") == 0) - sse_check = check_error; - else if (strcasecmp (arg, "warning") == 0) - sse_check = check_warning; - else if (strcasecmp (arg, "none") == 0) - sse_check = check_none; - else - as_fatal (_("invalid -msse-check= option: `%s'"), arg); - break; - - case OPTION_MOPERAND_CHECK: - if (strcasecmp (arg, "error") == 0) - operand_check = check_error; - else if (strcasecmp (arg, "warning") == 0) - operand_check = check_warning; - else if (strcasecmp (arg, "none") == 0) - operand_check = check_none; - else - as_fatal (_("invalid -moperand-check= option: `%s'"), arg); - break; - - case OPTION_MAVXSCALAR: - if (strcasecmp (arg, "128") == 0) - avxscalar = vex128; - else if (strcasecmp (arg, "256") == 0) - avxscalar = vex256; - else - as_fatal (_("invalid -mavxscalar= option: `%s'"), arg); - break; - - case OPTION_MADD_BND_PREFIX: - add_bnd_prefix = 1; - break; - - case OPTION_MEVEXLIG: - if (strcmp (arg, "128") == 0) - evexlig = evexl128; - else if (strcmp (arg, "256") == 0) - evexlig = evexl256; - else if (strcmp (arg, "512") == 0) - evexlig = evexl512; - else - as_fatal (_("invalid -mevexlig= option: `%s'"), arg); - break; - - case OPTION_MEVEXWIG: - if (strcmp (arg, "0") == 0) - evexwig = evexw0; - else if (strcmp (arg, "1") == 0) - evexwig = evexw1; - else - as_fatal (_("invalid -mevexwig= option: `%s'"), arg); - break; - - default: - return 0; - } - return 1; -} - -#define MESSAGE_TEMPLATE \ -" " - -static void -show_arch (FILE *stream, int ext, int check) -{ - static char message[] = MESSAGE_TEMPLATE; - char *start = message + 27; - char *p; - int size = sizeof (MESSAGE_TEMPLATE); - int left; - const char *name; - int len; - unsigned int j; - - p = start; - left = size - (start - message); - for (j = 0; j < ARRAY_SIZE (cpu_arch); j++) - { - /* Should it be skipped? */ - if (cpu_arch [j].skip) - continue; - - name = cpu_arch [j].name; - len = cpu_arch [j].len; - if (*name == '.') - { - /* It is an extension. Skip if we aren't asked to show it. */ - if (ext) - { - name++; - len--; - } - else - continue; - } - else if (ext) - { - /* It is an processor. Skip if we show only extension. */ - continue; - } - else if (check && ! cpu_arch[j].flags.bitfield.cpui386) - { - /* It is an impossible processor - skip. */ - continue; - } - - /* Reserve 2 spaces for ", " or ",\0" */ - left -= len + 2; - - /* Check if there is any room. */ - if (left >= 0) - { - if (p != start) - { - *p++ = ','; - *p++ = ' '; - } - p = mempcpy (p, name, len); - } - else - { - /* Output the current message now and start a new one. */ - *p++ = ','; - *p = '\0'; - fprintf (stream, "%s\n", message); - p = start; - left = size - (start - message) - len - 2; - - gas_assert (left >= 0); - - p = mempcpy (p, name, len); - } - } - - *p = '\0'; - fprintf (stream, "%s\n", message); -} - -void -md_show_usage (FILE *stream) -{ -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - fprintf (stream, _("\ - -Q ignored\n\ - -V print assembler version number\n\ - -k ignored\n")); -#endif - fprintf (stream, _("\ - -n Do not optimize code alignment\n\ - -q quieten some warnings\n")); -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - fprintf (stream, _("\ - -s ignored\n")); -#endif -#if (defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) \ - || defined (TE_PE) || defined (TE_PEP)) - fprintf (stream, _("\ - --32/--64/--x32 generate 32bit/64bit/x32 code\n")); -#endif -#ifdef SVR4_COMMENT_CHARS - fprintf (stream, _("\ - --divide do not treat `/' as a comment character\n")); -#else - fprintf (stream, _("\ - --divide ignored\n")); -#endif - fprintf (stream, _("\ - -march=CPU[,+EXTENSION...]\n\ - generate code for CPU and EXTENSION, CPU is one of:\n")); - show_arch (stream, 0, 1); - fprintf (stream, _("\ - EXTENSION is combination of:\n")); - show_arch (stream, 1, 0); - fprintf (stream, _("\ - -mtune=CPU optimize for CPU, CPU is one of:\n")); - show_arch (stream, 0, 0); - fprintf (stream, _("\ - -msse2avx encode SSE instructions with VEX prefix\n")); - fprintf (stream, _("\ - -msse-check=[none|error|warning]\n\ - check SSE instructions\n")); - fprintf (stream, _("\ - -moperand-check=[none|error|warning]\n\ - check operand combinations for validity\n")); - fprintf (stream, _("\ - -mavxscalar=[128|256] encode scalar AVX instructions with specific vector\n\ - length\n")); - fprintf (stream, _("\ - -mevexlig=[128|256|512] encode scalar EVEX instructions with specific vector\n\ - length\n")); - fprintf (stream, _("\ - -mevexwig=[0|1] encode EVEX instructions with specific EVEX.W value\n\ - for EVEX.W bit ignored instructions\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")); - fprintf (stream, _("\ - -madd-bnd-prefix add BND prefix for all valid branches\n")); -} - -#if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \ - || defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) \ - || defined (TE_PE) || defined (TE_PEP) || defined (OBJ_MACH_O)) - -/* Pick the target format to use. */ - -const char * -i386_target_format (void) -{ - if (!strncmp (default_arch, "x86_64", 6)) - { - update_code_flag (CODE_64BIT, 1); - if (default_arch[6] == '\0') - x86_elf_abi = X86_64_ABI; - else - x86_elf_abi = X86_64_X32_ABI; - } - else if (!strcmp (default_arch, "i386")) - update_code_flag (CODE_32BIT, 1); - else - as_fatal (_("unknown architecture")); - - if (cpu_flags_all_zero (&cpu_arch_isa_flags)) - cpu_arch_isa_flags = cpu_arch[flag_code == CODE_64BIT].flags; - if (cpu_flags_all_zero (&cpu_arch_tune_flags)) - cpu_arch_tune_flags = cpu_arch[flag_code == CODE_64BIT].flags; - - switch (OUTPUT_FLAVOR) - { -#if defined (OBJ_MAYBE_AOUT) || defined (OBJ_AOUT) - case bfd_target_aout_flavour: - return AOUT_TARGET_FORMAT; -#endif -#if defined (OBJ_MAYBE_COFF) || defined (OBJ_COFF) -# if defined (TE_PE) || defined (TE_PEP) - case bfd_target_coff_flavour: - return flag_code == CODE_64BIT ? "pe-x86-64" : "pe-i386"; -# elif defined (TE_GO32) - case bfd_target_coff_flavour: - return "coff-go32"; -# else - case bfd_target_coff_flavour: - return "coff-i386"; -# endif -#endif -#if defined (OBJ_MAYBE_ELF) || defined (OBJ_ELF) - case bfd_target_elf_flavour: - { - const char *format; - - switch (x86_elf_abi) - { - default: - format = ELF_TARGET_FORMAT; - break; - case X86_64_ABI: - use_rela_relocations = 1; - object_64bit = 1; - format = ELF_TARGET_FORMAT64; - break; - case X86_64_X32_ABI: - use_rela_relocations = 1; - object_64bit = 1; - disallow_64bit_reloc = 1; - format = ELF_TARGET_FORMAT32; - break; - } - if (cpu_arch_isa == PROCESSOR_L1OM) - { - if (x86_elf_abi != X86_64_ABI) - as_fatal (_("Intel L1OM is 64bit only")); - return ELF_TARGET_L1OM_FORMAT; - } - if (cpu_arch_isa == PROCESSOR_K1OM) - { - if (x86_elf_abi != X86_64_ABI) - as_fatal (_("Intel K1OM is 64bit only")); - return ELF_TARGET_K1OM_FORMAT; - } - else - return format; - } -#endif -#if defined (OBJ_MACH_O) - case bfd_target_mach_o_flavour: - if (flag_code == CODE_64BIT) - { - use_rela_relocations = 1; - object_64bit = 1; - return "mach-o-x86-64"; - } - else - return "mach-o-i386"; -#endif - default: - abort (); - return NULL; - } -} - -#endif /* OBJ_MAYBE_ more than one */ - -#if (defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) -void -i386_elf_emit_arch_note (void) -{ - if (IS_ELF && cpu_arch_name != NULL) - { - char *p; - asection *seg = now_seg; - subsegT subseg = now_subseg; - Elf_Internal_Note i_note; - Elf_External_Note e_note; - asection *note_secp; - int len; - - /* Create the .note section. */ - note_secp = subseg_new (".note", 0); - bfd_set_section_flags (stdoutput, - note_secp, - SEC_HAS_CONTENTS | SEC_READONLY); - - /* Process the arch string. */ - len = strlen (cpu_arch_name); - - i_note.namesz = len + 1; - i_note.descsz = 0; - i_note.type = NT_ARCH; - p = frag_more (sizeof (e_note.namesz)); - md_number_to_chars (p, (valueT) i_note.namesz, sizeof (e_note.namesz)); - p = frag_more (sizeof (e_note.descsz)); - md_number_to_chars (p, (valueT) i_note.descsz, sizeof (e_note.descsz)); - p = frag_more (sizeof (e_note.type)); - md_number_to_chars (p, (valueT) i_note.type, sizeof (e_note.type)); - p = frag_more (len + 1); - strcpy (p, cpu_arch_name); - - frag_align (2, 0, 0); - - subseg_set (seg, subseg); - } -} -#endif - -symbolS * -md_undefined_symbol (char *name) -{ - if (name[0] == GLOBAL_OFFSET_TABLE_NAME[0] - && name[1] == GLOBAL_OFFSET_TABLE_NAME[1] - && name[2] == GLOBAL_OFFSET_TABLE_NAME[2] - && strcmp (name, GLOBAL_OFFSET_TABLE_NAME) == 0) - { - if (!GOT_symbol) - { - if (symbol_find (name)) - as_bad (_("GOT already in symbol table")); - GOT_symbol = symbol_new (name, undefined_section, - (valueT) 0, &zero_address_frag); - }; - return GOT_symbol; - } - return 0; -} - -/* Round up a section size to the appropriate boundary. */ - -valueT -md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) -{ -#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT)) - if (OUTPUT_FLAVOR == bfd_target_aout_flavour) - { - /* For a.out, force the section size to be aligned. If we don't do - this, BFD will align it for us, but it will not write out the - final bytes of the section. This may be a bug in BFD, but it is - easier to fix it here since that is how the other a.out targets - work. */ - int align; - - align = bfd_get_section_alignment (stdoutput, segment); - size = ((size + (1 << align) - 1) & ((valueT) -1 << align)); - } -#endif - - return size; -} - -/* On the i386, PC-relative offsets are relative to the start of the - next instruction. That is, the address of the offset, plus its - size, since the offset is always the last part of the insn. */ - -long -md_pcrel_from (fixS *fixP) -{ - return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address; -} - -#ifndef I386COFF - -static void -s_bss (int ignore ATTRIBUTE_UNUSED) -{ - int temp; - -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - if (IS_ELF) - obj_elf_section_change_hook (); -#endif - temp = get_absolute_expression (); - subseg_set (bss_section, (subsegT) temp); - demand_empty_rest_of_line (); -} - -#endif - -void -i386_validate_fix (fixS *fixp) -{ - if (fixp->fx_subsy && fixp->fx_subsy == GOT_symbol) - { - if (fixp->fx_r_type == BFD_RELOC_32_PCREL) - { - if (!object_64bit) - abort (); - fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL; - } - else - { - if (!object_64bit) - fixp->fx_r_type = BFD_RELOC_386_GOTOFF; - else - fixp->fx_r_type = BFD_RELOC_X86_64_GOTOFF64; - } - fixp->fx_subsy = 0; - } -} - -arelent * -tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) -{ - arelent *rel; - bfd_reloc_code_real_type code; - - switch (fixp->fx_r_type) - { -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - case BFD_RELOC_SIZE32: - case BFD_RELOC_SIZE64: - if (S_IS_DEFINED (fixp->fx_addsy) - && !S_IS_EXTERNAL (fixp->fx_addsy)) - { - /* Resolve size relocation against local symbol to size of - the symbol plus addend. */ - valueT value = S_GET_SIZE (fixp->fx_addsy) + fixp->fx_offset; - if (fixp->fx_r_type == BFD_RELOC_SIZE32 - && !fits_in_unsigned_long (value)) - as_bad_where (fixp->fx_file, fixp->fx_line, - _("symbol size computation overflow")); - fixp->fx_addsy = NULL; - fixp->fx_subsy = NULL; - md_apply_fix (fixp, (valueT *) &value, NULL); - return NULL; - } -#endif - - case BFD_RELOC_X86_64_PLT32: - case BFD_RELOC_X86_64_PLT32_BND: - case BFD_RELOC_X86_64_GOT32: - case BFD_RELOC_X86_64_GOTPCREL: - case BFD_RELOC_386_PLT32: - case BFD_RELOC_386_GOT32: - case BFD_RELOC_386_GOTOFF: - case BFD_RELOC_386_GOTPC: - case BFD_RELOC_386_TLS_GD: - case BFD_RELOC_386_TLS_LDM: - case BFD_RELOC_386_TLS_LDO_32: - case BFD_RELOC_386_TLS_IE_32: - case BFD_RELOC_386_TLS_IE: - case BFD_RELOC_386_TLS_GOTIE: - case BFD_RELOC_386_TLS_LE_32: - case BFD_RELOC_386_TLS_LE: - case BFD_RELOC_386_TLS_GOTDESC: - case BFD_RELOC_386_TLS_DESC_CALL: - case BFD_RELOC_X86_64_TLSGD: - case BFD_RELOC_X86_64_TLSLD: - case BFD_RELOC_X86_64_DTPOFF32: - case BFD_RELOC_X86_64_DTPOFF64: - case BFD_RELOC_X86_64_GOTTPOFF: - case BFD_RELOC_X86_64_TPOFF32: - case BFD_RELOC_X86_64_TPOFF64: - case BFD_RELOC_X86_64_GOTOFF64: - case BFD_RELOC_X86_64_GOTPC32: - case BFD_RELOC_X86_64_GOT64: - case BFD_RELOC_X86_64_GOTPCREL64: - case BFD_RELOC_X86_64_GOTPC64: - case BFD_RELOC_X86_64_GOTPLT64: - case BFD_RELOC_X86_64_PLTOFF64: - case BFD_RELOC_X86_64_GOTPC32_TLSDESC: - case BFD_RELOC_X86_64_TLSDESC_CALL: - case BFD_RELOC_RVA: - case BFD_RELOC_VTABLE_ENTRY: - case BFD_RELOC_VTABLE_INHERIT: -#ifdef TE_PE - case BFD_RELOC_32_SECREL: -#endif - code = fixp->fx_r_type; - break; - case BFD_RELOC_X86_64_32S: - if (!fixp->fx_pcrel) - { - /* Don't turn BFD_RELOC_X86_64_32S into BFD_RELOC_32. */ - code = fixp->fx_r_type; - break; - } - default: - if (fixp->fx_pcrel) - { - switch (fixp->fx_size) - { - default: - as_bad_where (fixp->fx_file, fixp->fx_line, - _("can not do %d byte pc-relative relocation"), - fixp->fx_size); - code = BFD_RELOC_32_PCREL; - break; - case 1: code = BFD_RELOC_8_PCREL; break; - case 2: code = BFD_RELOC_16_PCREL; break; - case 4: - code = (fixp->fx_r_type == BFD_RELOC_X86_64_PC32_BND - ? fixp-> fx_r_type : BFD_RELOC_32_PCREL); - break; -#ifdef BFD64 - case 8: code = BFD_RELOC_64_PCREL; break; -#endif - } - } - else - { - switch (fixp->fx_size) - { - default: - as_bad_where (fixp->fx_file, fixp->fx_line, - _("can not do %d byte relocation"), - fixp->fx_size); - code = BFD_RELOC_32; - break; - case 1: code = BFD_RELOC_8; break; - case 2: code = BFD_RELOC_16; break; - case 4: code = BFD_RELOC_32; break; -#ifdef BFD64 - case 8: code = BFD_RELOC_64; break; -#endif - } - } - break; - } - - if ((code == BFD_RELOC_32 - || code == BFD_RELOC_32_PCREL - || code == BFD_RELOC_X86_64_32S) - && GOT_symbol - && fixp->fx_addsy == GOT_symbol) - { - if (!object_64bit) - code = BFD_RELOC_386_GOTPC; - else - code = BFD_RELOC_X86_64_GOTPC32; - } - if ((code == BFD_RELOC_64 || code == BFD_RELOC_64_PCREL) - && GOT_symbol - && fixp->fx_addsy == GOT_symbol) - { - code = BFD_RELOC_X86_64_GOTPC64; - } - - rel = (arelent *) xmalloc (sizeof (arelent)); - rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); - *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); - - rel->address = fixp->fx_frag->fr_address + fixp->fx_where; - - if (!use_rela_relocations) - { - /* HACK: Since i386 ELF uses Rel instead of Rela, encode the - vtable entry to be used in the relocation's section offset. */ - if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) - rel->address = fixp->fx_offset; -#if defined (OBJ_COFF) && defined (TE_PE) - else if (fixp->fx_addsy && S_IS_WEAK (fixp->fx_addsy)) - rel->addend = fixp->fx_addnumber - (S_GET_VALUE (fixp->fx_addsy) * 2); - else -#endif - rel->addend = 0; - } - /* Use the rela in 64bit mode. */ - else - { - if (disallow_64bit_reloc) - switch (code) - { - case BFD_RELOC_X86_64_DTPOFF64: - case BFD_RELOC_X86_64_TPOFF64: - case BFD_RELOC_64_PCREL: - case BFD_RELOC_X86_64_GOTOFF64: - case BFD_RELOC_X86_64_GOT64: - case BFD_RELOC_X86_64_GOTPCREL64: - case BFD_RELOC_X86_64_GOTPC64: - case BFD_RELOC_X86_64_GOTPLT64: - case BFD_RELOC_X86_64_PLTOFF64: - as_bad_where (fixp->fx_file, fixp->fx_line, - _("cannot represent relocation type %s in x32 mode"), - bfd_get_reloc_code_name (code)); - break; - default: - break; - } - - if (!fixp->fx_pcrel) - rel->addend = fixp->fx_offset; - else - switch (code) - { - case BFD_RELOC_X86_64_PLT32: - case BFD_RELOC_X86_64_PLT32_BND: - case BFD_RELOC_X86_64_GOT32: - case BFD_RELOC_X86_64_GOTPCREL: - case BFD_RELOC_X86_64_TLSGD: - case BFD_RELOC_X86_64_TLSLD: - case BFD_RELOC_X86_64_GOTTPOFF: - case BFD_RELOC_X86_64_GOTPC32_TLSDESC: - case BFD_RELOC_X86_64_TLSDESC_CALL: - rel->addend = fixp->fx_offset - fixp->fx_size; - break; - default: - rel->addend = (section->vma - - fixp->fx_size - + fixp->fx_addnumber - + md_pcrel_from (fixp)); - break; - } - } - - rel->howto = bfd_reloc_type_lookup (stdoutput, code); - if (rel->howto == NULL) - { - as_bad_where (fixp->fx_file, fixp->fx_line, - _("cannot represent relocation type %s"), - bfd_get_reloc_code_name (code)); - /* Set howto to a garbage value so that we can keep going. */ - rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32); - gas_assert (rel->howto != NULL); - } - - return rel; -} - -#include "tc-i386-intel.c" - -void -tc_x86_parse_to_dw2regnum (expressionS *exp) -{ - int saved_naked_reg; - char saved_register_dot; - - 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) - { - 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; - } -} - -void -tc_x86_frame_initial_instructions (void) -{ - static unsigned int sp_regno[2]; - - 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); - gas_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[flag_code >> 1], -x86_cie_data_alignment); - cfi_add_CFA_offset (x86_dwarf2_return_column, x86_cie_data_alignment); -} - -int -x86_dwarf2_addr_size (void) -{ -#if defined (OBJ_MAYBE_ELF) || defined (OBJ_ELF) - if (x86_elf_abi == X86_64_X32_ABI) - return 4; -#endif - return bfd_arch_bits_per_address (stdoutput) / 8; -} - -int -i386_elf_section_type (const char *str, size_t len) -{ - if (flag_code == CODE_64BIT - && len == sizeof ("unwind") - 1 - && strncmp (str, "unwind", 6) == 0) - return SHT_X86_64_UNWIND; - - return -1; -} - -#ifdef TE_SOLARIS -void -i386_solaris_fix_up_eh_frame (segT sec) -{ - if (flag_code == CODE_64BIT) - elf_section_type (sec) = SHT_X86_64_UNWIND; -} -#endif - -#ifdef TE_PE -void -tc_pe_dwarf2_emit_offset (symbolS *symbol, unsigned int size) -{ - expressionS exp; - - exp.X_op = O_secrel; - exp.X_add_symbol = symbol; - exp.X_add_number = 0; - emit_expr (&exp, size); -} -#endif - -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) -/* For ELF on x86-64, add support for SHF_X86_64_LARGE. */ - -bfd_vma -x86_64_section_letter (int letter, char **ptr_msg) -{ - if (flag_code == CODE_64BIT) - { - if (letter == 'l') - return SHF_X86_64_LARGE; - - *ptr_msg = _("bad .section directive: want a,l,w,x,M,S,G,T in string"); - } - else - *ptr_msg = _("bad .section directive: want a,w,x,M,S,G,T in string"); - return -1; -} - -bfd_vma -x86_64_section_word (char *str, size_t len) -{ - if (len == 5 && flag_code == CODE_64BIT && CONST_STRNEQ (str, "large")) - return SHF_X86_64_LARGE; - - return -1; -} - -static void -handle_large_common (int small ATTRIBUTE_UNUSED) -{ - if (flag_code != CODE_64BIT) - { - s_comm_internal (0, elf_common_parse); - as_warn (_(".largecomm supported only in 64bit mode, producing .comm")); - } - else - { - static segT lbss_section; - asection *saved_com_section_ptr = elf_com_section_ptr; - asection *saved_bss_section = bss_section; - - if (lbss_section == NULL) - { - flagword applicable; - segT seg = now_seg; - subsegT subseg = now_subseg; - - /* The .lbss section is for local .largecomm symbols. */ - lbss_section = subseg_new (".lbss", 0); - applicable = bfd_applicable_section_flags (stdoutput); - bfd_set_section_flags (stdoutput, lbss_section, - applicable & SEC_ALLOC); - seg_info (lbss_section)->bss = 1; - - subseg_set (seg, subseg); - } - - elf_com_section_ptr = &_bfd_elf_large_com_section; - bss_section = lbss_section; - - s_comm_internal (0, elf_common_parse); - - elf_com_section_ptr = saved_com_section_ptr; - bss_section = saved_bss_section; - } -} -#endif /* OBJ_ELF || OBJ_MAYBE_ELF */ |