tc-i386.c revision 130570
133965Sjdp/* i386.c -- Assemble code for the Intel 80386 278840Sobrien Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 3130570Sobrien 2000, 2001, 2002, 2003, 2004 477311Sobrien Free Software Foundation, Inc. 533965Sjdp 633965Sjdp This file is part of GAS, the GNU Assembler. 733965Sjdp 833965Sjdp GAS is free software; you can redistribute it and/or modify 933965Sjdp it under the terms of the GNU General Public License as published by 1033965Sjdp the Free Software Foundation; either version 2, or (at your option) 1133965Sjdp any later version. 1233965Sjdp 1333965Sjdp GAS is distributed in the hope that it will be useful, 1433965Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1533965Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1633965Sjdp GNU General Public License for more details. 1733965Sjdp 1833965Sjdp You should have received a copy of the GNU General Public License 1933965Sjdp along with GAS; see the file COPYING. If not, write to the Free 2033965Sjdp Software Foundation, 59 Temple Place - Suite 330, Boston, MA 2133965Sjdp 02111-1307, USA. */ 2233965Sjdp 2377311Sobrien/* Intel 80386 machine specific gas. 2477311Sobrien Written by Eliot Dresselhaus (eliot@mgm.mit.edu). 2577311Sobrien x86_64 support by Jan Hubicka (jh@suse.cz) 26130570Sobrien VIA PadLock support by Michal Ludvig (mludvig@suse.cz) 2777311Sobrien Bugs & suggestions are completely welcome. This is free software. 2877311Sobrien Please help us make it better. */ 2977311Sobrien 3033965Sjdp#include "as.h" 3189867Sobrien#include "safe-ctype.h" 3233965Sjdp#include "subsegs.h" 3377311Sobrien#include "dwarf2dbg.h" 34130570Sobrien#include "dw2gencfi.h" 3533965Sjdp#include "opcode/i386.h" 3633965Sjdp 3760519Sobrien#ifndef REGISTER_WARNINGS 3860519Sobrien#define REGISTER_WARNINGS 1 3933965Sjdp#endif 4033965Sjdp 4160519Sobrien#ifndef INFER_ADDR_PREFIX 4260519Sobrien#define INFER_ADDR_PREFIX 1 4360519Sobrien#endif 4460519Sobrien 4560519Sobrien#ifndef SCALE1_WHEN_NO_INDEX 4660519Sobrien/* Specifying a scale factor besides 1 when there is no index is 4760519Sobrien futile. eg. `mov (%ebx,2),%al' does exactly the same as 4860519Sobrien `mov (%ebx),%al'. To slavishly follow what the programmer 4960519Sobrien specified, set SCALE1_WHEN_NO_INDEX to 0. */ 5060519Sobrien#define SCALE1_WHEN_NO_INDEX 1 5160519Sobrien#endif 5260519Sobrien 5394546Sobrien#ifndef DEFAULT_ARCH 5494546Sobrien#define DEFAULT_ARCH "i386" 5591054Sobrien#endif 5660519Sobrien 5794546Sobrien#ifndef INLINE 5894546Sobrien#if __GNUC__ >= 2 5994546Sobrien#define INLINE __inline__ 6094546Sobrien#else 6194546Sobrien#define INLINE 6294546Sobrien#endif 6394546Sobrien#endif 6494546Sobrien 6594546Sobrienstatic INLINE unsigned int mode_from_disp_size PARAMS ((unsigned int)); 6694546Sobrienstatic INLINE int fits_in_signed_byte PARAMS ((offsetT)); 6794546Sobrienstatic INLINE int fits_in_unsigned_byte PARAMS ((offsetT)); 6894546Sobrienstatic INLINE int fits_in_unsigned_word PARAMS ((offsetT)); 6994546Sobrienstatic INLINE int fits_in_signed_word PARAMS ((offsetT)); 7094546Sobrienstatic INLINE int fits_in_unsigned_long PARAMS ((offsetT)); 7194546Sobrienstatic INLINE int fits_in_signed_long PARAMS ((offsetT)); 7277311Sobrienstatic int smallest_imm_type PARAMS ((offsetT)); 7377311Sobrienstatic offsetT offset_in_range PARAMS ((offsetT, int)); 7460519Sobrienstatic int add_prefix PARAMS ((unsigned int)); 7577311Sobrienstatic void set_code_flag PARAMS ((int)); 7677311Sobrienstatic void set_16bit_gcc_code_flag PARAMS ((int)); 7760519Sobrienstatic void set_intel_syntax PARAMS ((int)); 7877311Sobrienstatic void set_cpu_arch PARAMS ((int)); 7994546Sobrienstatic char *output_invalid PARAMS ((int c)); 8094546Sobrienstatic int i386_operand PARAMS ((char *operand_string)); 8194546Sobrienstatic int i386_intel_operand PARAMS ((char *operand_string, int got_a_float)); 8294546Sobrienstatic const reg_entry *parse_register PARAMS ((char *reg_string, 8394546Sobrien char **end_op)); 8494546Sobrienstatic char *parse_insn PARAMS ((char *, char *)); 8594546Sobrienstatic char *parse_operands PARAMS ((char *, const char *)); 8694546Sobrienstatic void swap_operands PARAMS ((void)); 8794546Sobrienstatic void optimize_imm PARAMS ((void)); 8894546Sobrienstatic void optimize_disp PARAMS ((void)); 8994546Sobrienstatic int match_template PARAMS ((void)); 9094546Sobrienstatic int check_string PARAMS ((void)); 9194546Sobrienstatic int process_suffix PARAMS ((void)); 9294546Sobrienstatic int check_byte_reg PARAMS ((void)); 9394546Sobrienstatic int check_long_reg PARAMS ((void)); 9494546Sobrienstatic int check_qword_reg PARAMS ((void)); 9594546Sobrienstatic int check_word_reg PARAMS ((void)); 9694546Sobrienstatic int finalize_imm PARAMS ((void)); 9794546Sobrienstatic int process_operands PARAMS ((void)); 9894546Sobrienstatic const seg_entry *build_modrm_byte PARAMS ((void)); 9994546Sobrienstatic void output_insn PARAMS ((void)); 10094546Sobrienstatic void output_branch PARAMS ((void)); 10194546Sobrienstatic void output_jump PARAMS ((void)); 10294546Sobrienstatic void output_interseg_jump PARAMS ((void)); 103104848Sobrienstatic void output_imm PARAMS ((fragS *insn_start_frag, 104104848Sobrien offsetT insn_start_off)); 105104848Sobrienstatic void output_disp PARAMS ((fragS *insn_start_frag, 106104848Sobrien offsetT insn_start_off)); 10794546Sobrien#ifndef I386COFF 10894546Sobrienstatic void s_bss PARAMS ((int)); 10933965Sjdp#endif 11033965Sjdp 11189867Sobrienstatic const char *default_arch = DEFAULT_ARCH; 11277311Sobrien 11333965Sjdp/* 'md_assemble ()' gathers together information and puts it into a 11477311Sobrien i386_insn. */ 11533965Sjdp 11660519Sobrienunion i386_op 11760519Sobrien { 11860519Sobrien expressionS *disps; 11960519Sobrien expressionS *imms; 12060519Sobrien const reg_entry *regs; 12160519Sobrien }; 12260519Sobrien 12333965Sjdpstruct _i386_insn 12433965Sjdp { 12577311Sobrien /* TM holds the template for the insn were currently assembling. */ 12633965Sjdp template tm; 12760519Sobrien 12860519Sobrien /* SUFFIX holds the instruction mnemonic suffix if given. 12960519Sobrien (e.g. 'l' for 'movl') */ 13033965Sjdp char suffix; 13133965Sjdp 13277311Sobrien /* OPERANDS gives the number of given operands. */ 13333965Sjdp unsigned int operands; 13433965Sjdp 13533965Sjdp /* REG_OPERANDS, DISP_OPERANDS, MEM_OPERANDS, IMM_OPERANDS give the number 13633965Sjdp of given register, displacement, memory operands and immediate 13777311Sobrien operands. */ 13833965Sjdp unsigned int reg_operands, disp_operands, mem_operands, imm_operands; 13933965Sjdp 14033965Sjdp /* TYPES [i] is the type (see above #defines) which tells us how to 14160519Sobrien use OP[i] for the corresponding operand. */ 14233965Sjdp unsigned int types[MAX_OPERANDS]; 14333965Sjdp 14460519Sobrien /* Displacement expression, immediate expression, or register for each 14560519Sobrien operand. */ 14660519Sobrien union i386_op op[MAX_OPERANDS]; 14733965Sjdp 14877311Sobrien /* Flags for operands. */ 14977311Sobrien unsigned int flags[MAX_OPERANDS]; 15077311Sobrien#define Operand_PCrel 1 15177311Sobrien 15233965Sjdp /* Relocation type for operand */ 153130570Sobrien enum bfd_reloc_code_real reloc[MAX_OPERANDS]; 15433965Sjdp 15533965Sjdp /* BASE_REG, INDEX_REG, and LOG2_SCALE_FACTOR are used to encode 15633965Sjdp the base index byte below. */ 15760519Sobrien const reg_entry *base_reg; 15860519Sobrien const reg_entry *index_reg; 15933965Sjdp unsigned int log2_scale_factor; 16033965Sjdp 16160519Sobrien /* SEG gives the seg_entries of this insn. They are zero unless 16277311Sobrien explicit segment overrides are given. */ 16377311Sobrien const seg_entry *seg[2]; 16433965Sjdp 16533965Sjdp /* PREFIX holds all the given prefix opcodes (usually null). 16660519Sobrien PREFIXES is the number of prefix opcodes. */ 16760519Sobrien unsigned int prefixes; 16833965Sjdp unsigned char prefix[MAX_PREFIXES]; 16933965Sjdp 17060519Sobrien /* RM and SIB are the modrm byte and the sib byte where the 17160519Sobrien addressing modes of this insn are encoded. */ 17233965Sjdp 17333965Sjdp modrm_byte rm; 17477311Sobrien rex_byte rex; 17560519Sobrien sib_byte sib; 17633965Sjdp }; 17733965Sjdp 17833965Sjdptypedef struct _i386_insn i386_insn; 17933965Sjdp 18060519Sobrien/* List of chars besides those in app.c:symbol_chars that can start an 18160519Sobrien operand. Used to prevent the scrubber eating vital white-space. */ 18260519Sobrien#ifdef LEX_AT 18399468Sobrienconst char extra_symbol_chars[] = "*%-(@["; 18460519Sobrien#else 18599468Sobrienconst char extra_symbol_chars[] = "*%-(["; 18660519Sobrien#endif 18760519Sobrien 18894546Sobrien#if (defined (TE_I386AIX) \ 18994546Sobrien || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) \ 19094546Sobrien && !defined (TE_LINUX) \ 19194546Sobrien && !defined (TE_FreeBSD) \ 19294546Sobrien && !defined (TE_NetBSD))) 19333965Sjdp/* This array holds the chars that always start a comment. If the 19477311Sobrien pre-processor is disabled, these aren't very useful. */ 19533965Sjdpconst char comment_chars[] = "#/"; 19660519Sobrien#define PREFIX_SEPARATOR '\\' 19733965Sjdp 19833965Sjdp/* This array holds the chars that only start a comment at the beginning of 19933965Sjdp a line. If the line seems to have the form '# 123 filename' 20077311Sobrien .line and .file directives will appear in the pre-processed output. 20177311Sobrien Note that input_file.c hand checks for '#' at the beginning of the 20233965Sjdp first line of the input file. This is because the compiler outputs 20377311Sobrien #NO_APP at the beginning of its output. 20477311Sobrien Also note that comments started like this one will always work if 20533965Sjdp '/' isn't otherwise defined. */ 206130570Sobrienconst char line_comment_chars[] = "#"; 20794546Sobrien 20833965Sjdp#else 20994546Sobrien/* Putting '/' here makes it impossible to use the divide operator. 21094546Sobrien However, we need it for compatibility with SVR4 systems. */ 21194546Sobrienconst char comment_chars[] = "#"; 21294546Sobrien#define PREFIX_SEPARATOR '/' 21394546Sobrien 214130570Sobrienconst char line_comment_chars[] = "/#"; 21533965Sjdp#endif 21660519Sobrien 21777311Sobrienconst char line_separator_chars[] = ";"; 21833965Sjdp 21977311Sobrien/* Chars that can be used to separate mant from exp in floating point 22077311Sobrien nums. */ 22133965Sjdpconst char EXP_CHARS[] = "eE"; 22233965Sjdp 22377311Sobrien/* Chars that mean this number is a floating point constant 22477311Sobrien As in 0f12.456 22577311Sobrien or 0d1.2345e12. */ 22633965Sjdpconst char FLT_CHARS[] = "fFdDxX"; 22733965Sjdp 22877311Sobrien/* Tables for lexical analysis. */ 22960519Sobrienstatic char mnemonic_chars[256]; 23033965Sjdpstatic char register_chars[256]; 23133965Sjdpstatic char operand_chars[256]; 23233965Sjdpstatic char identifier_chars[256]; 23333965Sjdpstatic char digit_chars[256]; 23433965Sjdp 23577311Sobrien/* Lexical macros. */ 23660519Sobrien#define is_mnemonic_char(x) (mnemonic_chars[(unsigned char) x]) 23733965Sjdp#define is_operand_char(x) (operand_chars[(unsigned char) x]) 23833965Sjdp#define is_register_char(x) (register_chars[(unsigned char) x]) 23960519Sobrien#define is_space_char(x) ((x) == ' ') 24033965Sjdp#define is_identifier_char(x) (identifier_chars[(unsigned char) x]) 24133965Sjdp#define is_digit_char(x) (digit_chars[(unsigned char) x]) 24233965Sjdp 243130570Sobrien/* All non-digit non-letter characters that may occur in an operand. */ 24433965Sjdpstatic char operand_special_chars[] = "%$-+(,)*._~/<>|&^!:[@]"; 24533965Sjdp 24633965Sjdp/* md_assemble() always leaves the strings it's passed unaltered. To 24733965Sjdp effect this we maintain a stack of saved characters that we've smashed 24833965Sjdp with '\0's (indicating end of strings for various sub-fields of the 24977311Sobrien assembler instruction). */ 25033965Sjdpstatic char save_stack[32]; 25177311Sobrienstatic char *save_stack_p; 25260519Sobrien#define END_STRING_AND_SAVE(s) \ 25360519Sobrien do { *save_stack_p++ = *(s); *(s) = '\0'; } while (0) 25460519Sobrien#define RESTORE_END_STRING(s) \ 25560519Sobrien do { *(s) = *--save_stack_p; } while (0) 25633965Sjdp 25777311Sobrien/* The instruction we're assembling. */ 25833965Sjdpstatic i386_insn i; 25933965Sjdp 26060519Sobrien/* Possible templates for current insn. */ 26160519Sobrienstatic const templates *current_templates; 26260519Sobrien 26377311Sobrien/* Per instruction expressionS buffers: 2 displacements & 2 immediate max. */ 26433965Sjdpstatic expressionS disp_expressions[2], im_expressions[2]; 26533965Sjdp 26677311Sobrien/* Current operand we are working on. */ 26777311Sobrienstatic int this_operand; 26833965Sjdp 26977311Sobrien/* We support four different modes. FLAG_CODE variable is used to distinguish 27077311Sobrien these. */ 27133965Sjdp 27277311Sobrienenum flag_code { 27377311Sobrien CODE_32BIT, 27477311Sobrien CODE_16BIT, 27577311Sobrien CODE_64BIT }; 27678840Sobrien#define NUM_FLAG_CODE ((int) CODE_64BIT + 1) 27733965Sjdp 27877311Sobrienstatic enum flag_code flag_code; 27977311Sobrienstatic int use_rela_relocations = 0; 28060519Sobrien 28177311Sobrien/* The names used to print error messages. */ 28277311Sobrienstatic const char *flag_code_names[] = 28377311Sobrien { 28477311Sobrien "32", 28577311Sobrien "16", 28677311Sobrien "64" 28777311Sobrien }; 28860519Sobrien 28977311Sobrien/* 1 for intel syntax, 29077311Sobrien 0 if att syntax. */ 29177311Sobrienstatic int intel_syntax = 0; 29260519Sobrien 29377311Sobrien/* 1 if register prefix % not required. */ 29477311Sobrienstatic int allow_naked_reg = 0; 29577311Sobrien 29677311Sobrien/* Used in 16 bit gcc mode to add an l suffix to call, ret, enter, 29777311Sobrien leave, push, and pop instructions so that gcc has the same stack 29877311Sobrien frame as in 32 bit mode. */ 29977311Sobrienstatic char stackop_size = '\0'; 30077311Sobrien 301130570Sobrien/* Non-zero to optimize code alignment. */ 302130570Sobrienint optimize_align_code = 1; 303130570Sobrien 30477311Sobrien/* Non-zero to quieten some warnings. */ 30577311Sobrienstatic int quiet_warnings = 0; 30677311Sobrien 30777311Sobrien/* CPU name. */ 30877311Sobrienstatic const char *cpu_arch_name = NULL; 30977311Sobrien 31077311Sobrien/* CPU feature flags. */ 31194546Sobrienstatic unsigned int cpu_arch_flags = CpuUnknownFlags | CpuNo64; 31277311Sobrien 31378840Sobrien/* If set, conditional jumps are not automatically promoted to handle 31478840Sobrien larger than a byte offset. */ 31578840Sobrienstatic unsigned int no_cond_jump_promotion = 0; 31678840Sobrien 31794546Sobrien/* Pre-defined "_GLOBAL_OFFSET_TABLE_". */ 31894546SobriensymbolS *GOT_symbol; 31994546Sobrien 320130570Sobrien/* The dwarf2 return column, adjusted for 32 or 64 bit. */ 321130570Sobrienunsigned int x86_dwarf2_return_column; 322130570Sobrien 323130570Sobrien/* The dwarf2 data alignment, adjusted for 32 or 64 bit. */ 324130570Sobrienint x86_cie_data_alignment; 325130570Sobrien 32633965Sjdp/* Interface to relax_segment. 32778840Sobrien There are 3 major relax states for 386 jump insns because the 32878840Sobrien different types of jumps add different sizes to frags when we're 32978840Sobrien figuring out what sort of jump to choose to reach a given label. */ 33033965Sjdp 33177311Sobrien/* Types. */ 33278840Sobrien#define UNCOND_JUMP 0 33377311Sobrien#define COND_JUMP 1 33478840Sobrien#define COND_JUMP86 2 33578840Sobrien 33677311Sobrien/* Sizes. */ 33760519Sobrien#define CODE16 1 33860519Sobrien#define SMALL 0 33994546Sobrien#define SMALL16 (SMALL | CODE16) 34060519Sobrien#define BIG 2 34194546Sobrien#define BIG16 (BIG | CODE16) 34233965Sjdp 34333965Sjdp#ifndef INLINE 34433965Sjdp#ifdef __GNUC__ 34533965Sjdp#define INLINE __inline__ 34633965Sjdp#else 34733965Sjdp#define INLINE 34833965Sjdp#endif 34933965Sjdp#endif 35033965Sjdp 35178840Sobrien#define ENCODE_RELAX_STATE(type, size) \ 35278840Sobrien ((relax_substateT) (((type) << 2) | (size))) 35378840Sobrien#define TYPE_FROM_RELAX_STATE(s) \ 35478840Sobrien ((s) >> 2) 35578840Sobrien#define DISP_SIZE_FROM_RELAX_STATE(s) \ 35678840Sobrien ((((s) & 3) == BIG ? 4 : (((s) & 3) == BIG16 ? 2 : 1))) 35733965Sjdp 35860519Sobrien/* This table is used by relax_frag to promote short jumps to long 35960519Sobrien ones where necessary. SMALL (short) jumps may be promoted to BIG 36060519Sobrien (32 bit long) ones, and SMALL16 jumps to BIG16 (16 bit long). We 36160519Sobrien don't allow a short jump in a 32 bit code segment to be promoted to 36260519Sobrien a 16 bit offset jump because it's slower (requires data size 36360519Sobrien prefix), and doesn't work, unless the destination is in the bottom 36460519Sobrien 64k of the code segment (The top 16 bits of eip are zeroed). */ 36560519Sobrien 36633965Sjdpconst relax_typeS md_relax_table[] = 36733965Sjdp{ 36860519Sobrien /* The fields are: 36960519Sobrien 1) most positive reach of this state, 37060519Sobrien 2) most negative reach of this state, 37178840Sobrien 3) how many bytes this mode will have in the variable part of the frag 37277311Sobrien 4) which index into the table to try if we can't fit into this one. */ 37333965Sjdp 37478840Sobrien /* UNCOND_JUMP states. */ 37578840Sobrien {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG)}, 37678840Sobrien {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16)}, 37778840Sobrien /* dword jmp adds 4 bytes to frag: 37878840Sobrien 0 extra opcode bytes, 4 displacement bytes. */ 37933965Sjdp {0, 0, 4, 0}, 38078840Sobrien /* word jmp adds 2 byte2 to frag: 38178840Sobrien 0 extra opcode bytes, 2 displacement bytes. */ 38260519Sobrien {0, 0, 2, 0}, 38333965Sjdp 38478840Sobrien /* COND_JUMP states. */ 38578840Sobrien {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP, BIG)}, 38678840Sobrien {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP, BIG16)}, 38778840Sobrien /* dword conditionals adds 5 bytes to frag: 38878840Sobrien 1 extra opcode byte, 4 displacement bytes. */ 38978840Sobrien {0, 0, 5, 0}, 39078840Sobrien /* word conditionals add 3 bytes to frag: 39178840Sobrien 1 extra opcode byte, 2 displacement bytes. */ 39233965Sjdp {0, 0, 3, 0}, 39333965Sjdp 39478840Sobrien /* COND_JUMP86 states. */ 39578840Sobrien {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP86, BIG)}, 39678840Sobrien {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP86, BIG16)}, 39778840Sobrien /* dword conditionals adds 5 bytes to frag: 39878840Sobrien 1 extra opcode byte, 4 displacement bytes. */ 39978840Sobrien {0, 0, 5, 0}, 40078840Sobrien /* word conditionals add 4 bytes to frag: 40178840Sobrien 1 displacement byte and a 3 byte long branch insn. */ 40278840Sobrien {0, 0, 4, 0} 40333965Sjdp}; 40433965Sjdp 40577311Sobrienstatic const arch_entry cpu_arch[] = { 40677311Sobrien {"i8086", Cpu086 }, 40777311Sobrien {"i186", Cpu086|Cpu186 }, 40877311Sobrien {"i286", Cpu086|Cpu186|Cpu286 }, 40977311Sobrien {"i386", Cpu086|Cpu186|Cpu286|Cpu386 }, 41077311Sobrien {"i486", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486 }, 41177311Sobrien {"i586", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuMMX }, 41277311Sobrien {"i686", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX|CpuSSE }, 41377311Sobrien {"pentium", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuMMX }, 41477311Sobrien {"pentiumpro",Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX|CpuSSE }, 41577311Sobrien {"pentium4", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2 }, 41677311Sobrien {"k6", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuK6|CpuMMX|Cpu3dnow }, 41777311Sobrien {"athlon", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuAthlon|CpuMMX|Cpu3dnow }, 41877311Sobrien {"sledgehammer",Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuAthlon|CpuSledgehammer|CpuMMX|Cpu3dnow|CpuSSE|CpuSSE2 }, 41977311Sobrien {NULL, 0 } 42077311Sobrien}; 42133965Sjdp 42294546Sobrienconst pseudo_typeS md_pseudo_table[] = 42394546Sobrien{ 42494546Sobrien#if !defined(OBJ_AOUT) && !defined(USE_ALIGN_PTWO) 42594546Sobrien {"align", s_align_bytes, 0}, 42694546Sobrien#else 42794546Sobrien {"align", s_align_ptwo, 0}, 42894546Sobrien#endif 42994546Sobrien {"arch", set_cpu_arch, 0}, 43094546Sobrien#ifndef I386COFF 43194546Sobrien {"bss", s_bss, 0}, 43294546Sobrien#endif 43394546Sobrien {"ffloat", float_cons, 'f'}, 43494546Sobrien {"dfloat", float_cons, 'd'}, 43594546Sobrien {"tfloat", float_cons, 'x'}, 43694546Sobrien {"value", cons, 2}, 43794546Sobrien {"noopt", s_ignore, 0}, 43894546Sobrien {"optim", s_ignore, 0}, 43994546Sobrien {"code16gcc", set_16bit_gcc_code_flag, CODE_16BIT}, 44094546Sobrien {"code16", set_code_flag, CODE_16BIT}, 44194546Sobrien {"code32", set_code_flag, CODE_32BIT}, 44294546Sobrien {"code64", set_code_flag, CODE_64BIT}, 44394546Sobrien {"intel_syntax", set_intel_syntax, 1}, 44494546Sobrien {"att_syntax", set_intel_syntax, 0}, 445104848Sobrien {"file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0}, 44694546Sobrien {"loc", dwarf2_directive_loc, 0}, 44794546Sobrien {0, 0, 0} 44894546Sobrien}; 44994546Sobrien 45094546Sobrien/* For interface with expression (). */ 45194546Sobrienextern char *input_line_pointer; 45294546Sobrien 45394546Sobrien/* Hash table for instruction mnemonic lookup. */ 45494546Sobrienstatic struct hash_control *op_hash; 45594546Sobrien 45694546Sobrien/* Hash table for register lookup. */ 45794546Sobrienstatic struct hash_control *reg_hash; 45894546Sobrien 45933965Sjdpvoid 46033965Sjdpi386_align_code (fragP, count) 46133965Sjdp fragS *fragP; 46233965Sjdp int count; 46333965Sjdp{ 46477311Sobrien /* Various efficient no-op patterns for aligning code labels. 46577311Sobrien Note: Don't try to assemble the instructions in the comments. 46677311Sobrien 0L and 0w are not legal. */ 46733965Sjdp static const char f32_1[] = 46833965Sjdp {0x90}; /* nop */ 46933965Sjdp static const char f32_2[] = 47033965Sjdp {0x89,0xf6}; /* movl %esi,%esi */ 47133965Sjdp static const char f32_3[] = 47233965Sjdp {0x8d,0x76,0x00}; /* leal 0(%esi),%esi */ 47333965Sjdp static const char f32_4[] = 47433965Sjdp {0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ 47533965Sjdp static const char f32_5[] = 47633965Sjdp {0x90, /* nop */ 47733965Sjdp 0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ 47833965Sjdp static const char f32_6[] = 47933965Sjdp {0x8d,0xb6,0x00,0x00,0x00,0x00}; /* leal 0L(%esi),%esi */ 48033965Sjdp static const char f32_7[] = 48133965Sjdp {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ 48233965Sjdp static const char f32_8[] = 48333965Sjdp {0x90, /* nop */ 48433965Sjdp 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ 48533965Sjdp static const char f32_9[] = 48633965Sjdp {0x89,0xf6, /* movl %esi,%esi */ 48733965Sjdp 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ 48833965Sjdp static const char f32_10[] = 48933965Sjdp {0x8d,0x76,0x00, /* leal 0(%esi),%esi */ 49033965Sjdp 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ 49133965Sjdp static const char f32_11[] = 49233965Sjdp {0x8d,0x74,0x26,0x00, /* leal 0(%esi,1),%esi */ 49333965Sjdp 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ 49433965Sjdp static const char f32_12[] = 49533965Sjdp {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ 49633965Sjdp 0x8d,0xbf,0x00,0x00,0x00,0x00}; /* leal 0L(%edi),%edi */ 49733965Sjdp static const char f32_13[] = 49833965Sjdp {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ 49933965Sjdp 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ 50033965Sjdp static const char f32_14[] = 50133965Sjdp {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00, /* leal 0L(%esi,1),%esi */ 50233965Sjdp 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ 50333965Sjdp static const char f32_15[] = 50433965Sjdp {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */ 50533965Sjdp 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90}; 50660519Sobrien static const char f16_3[] = 50760519Sobrien {0x8d,0x74,0x00}; /* lea 0(%esi),%esi */ 50833965Sjdp static const char f16_4[] = 50938891Sjdp {0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */ 51033965Sjdp static const char f16_5[] = 51133965Sjdp {0x90, /* nop */ 51238891Sjdp 0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */ 51333965Sjdp static const char f16_6[] = 51433965Sjdp {0x89,0xf6, /* mov %si,%si */ 51533965Sjdp 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ 51633965Sjdp static const char f16_7[] = 51738891Sjdp {0x8d,0x74,0x00, /* lea 0(%si),%si */ 51833965Sjdp 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ 51933965Sjdp static const char f16_8[] = 52038891Sjdp {0x8d,0xb4,0x00,0x00, /* lea 0w(%si),%si */ 52133965Sjdp 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ 52233965Sjdp static const char *const f32_patt[] = { 52333965Sjdp f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8, 52433965Sjdp f32_9, f32_10, f32_11, f32_12, f32_13, f32_14, f32_15 52533965Sjdp }; 52633965Sjdp static const char *const f16_patt[] = { 52760519Sobrien f32_1, f32_2, f16_3, f16_4, f16_5, f16_6, f16_7, f16_8, 52833965Sjdp f32_15, f32_15, f32_15, f32_15, f32_15, f32_15, f32_15 52933965Sjdp }; 53033965Sjdp 531130570Sobrien if (count <= 0 || count > 15) 532130570Sobrien return; 533130570Sobrien 534130570Sobrien /* The recommended way to pad 64bit code is to use NOPs preceded by 535130570Sobrien maximally four 0x66 prefixes. Balance the size of nops. */ 53677311Sobrien if (flag_code == CODE_64BIT) 537130570Sobrien { 538130570Sobrien int i; 539130570Sobrien int nnops = (count + 3) / 4; 540130570Sobrien int len = count / nnops; 541130570Sobrien int remains = count - nnops * len; 542130570Sobrien int pos = 0; 54377311Sobrien 544130570Sobrien for (i = 0; i < remains; i++) 54533965Sjdp { 546130570Sobrien memset (fragP->fr_literal + fragP->fr_fix + pos, 0x66, len); 547130570Sobrien fragP->fr_literal[fragP->fr_fix + pos + len] = 0x90; 548130570Sobrien pos += len + 1; 54933965Sjdp } 550130570Sobrien for (; i < nnops; i++) 551130570Sobrien { 552130570Sobrien memset (fragP->fr_literal + fragP->fr_fix + pos, 0x66, len - 1); 553130570Sobrien fragP->fr_literal[fragP->fr_fix + pos + len - 1] = 0x90; 554130570Sobrien pos += len; 555130570Sobrien } 556130570Sobrien } 557130570Sobrien else 558130570Sobrien if (flag_code == CODE_16BIT) 559130570Sobrien { 56077311Sobrien memcpy (fragP->fr_literal + fragP->fr_fix, 561130570Sobrien f16_patt[count - 1], count); 562130570Sobrien if (count > 8) 563130570Sobrien /* Adjust jump offset. */ 564130570Sobrien fragP->fr_literal[fragP->fr_fix + 1] = count - 2; 565130570Sobrien } 566130570Sobrien else 567130570Sobrien memcpy (fragP->fr_literal + fragP->fr_fix, 568130570Sobrien f32_patt[count - 1], count); 569130570Sobrien fragP->fr_var = count; 57033965Sjdp} 57133965Sjdp 57260519Sobrienstatic INLINE unsigned int 57333965Sjdpmode_from_disp_size (t) 57460519Sobrien unsigned int t; 57533965Sjdp{ 57677311Sobrien return (t & Disp8) ? 1 : (t & (Disp16 | Disp32 | Disp32S)) ? 2 : 0; 57733965Sjdp} 57833965Sjdp 57933965Sjdpstatic INLINE int 58033965Sjdpfits_in_signed_byte (num) 58177311Sobrien offsetT num; 58233965Sjdp{ 58333965Sjdp return (num >= -128) && (num <= 127); 58477311Sobrien} 58533965Sjdp 58633965Sjdpstatic INLINE int 58733965Sjdpfits_in_unsigned_byte (num) 58877311Sobrien offsetT num; 58933965Sjdp{ 59033965Sjdp return (num & 0xff) == num; 59177311Sobrien} 59233965Sjdp 59333965Sjdpstatic INLINE int 59433965Sjdpfits_in_unsigned_word (num) 59577311Sobrien offsetT num; 59633965Sjdp{ 59733965Sjdp return (num & 0xffff) == num; 59877311Sobrien} 59933965Sjdp 60033965Sjdpstatic INLINE int 60133965Sjdpfits_in_signed_word (num) 60277311Sobrien offsetT num; 60333965Sjdp{ 60433965Sjdp return (-32768 <= num) && (num <= 32767); 60577311Sobrien} 60677311Sobrienstatic INLINE int 60777311Sobrienfits_in_signed_long (num) 60877311Sobrien offsetT num ATTRIBUTE_UNUSED; 60977311Sobrien{ 61077311Sobrien#ifndef BFD64 61177311Sobrien return 1; 61277311Sobrien#else 61377311Sobrien return (!(((offsetT) -1 << 31) & num) 61477311Sobrien || (((offsetT) -1 << 31) & num) == ((offsetT) -1 << 31)); 61577311Sobrien#endif 61677311Sobrien} /* fits_in_signed_long() */ 61777311Sobrienstatic INLINE int 61877311Sobrienfits_in_unsigned_long (num) 61977311Sobrien offsetT num ATTRIBUTE_UNUSED; 62077311Sobrien{ 62177311Sobrien#ifndef BFD64 62277311Sobrien return 1; 62377311Sobrien#else 62477311Sobrien return (num & (((offsetT) 2 << 31) - 1)) == num; 62577311Sobrien#endif 62677311Sobrien} /* fits_in_unsigned_long() */ 62733965Sjdp 62833965Sjdpstatic int 62933965Sjdpsmallest_imm_type (num) 63077311Sobrien offsetT num; 63133965Sjdp{ 63289867Sobrien if (cpu_arch_flags != (Cpu086 | Cpu186 | Cpu286 | Cpu386 | Cpu486 | CpuNo64)) 63377311Sobrien { 63477311Sobrien /* This code is disabled on the 486 because all the Imm1 forms 63577311Sobrien in the opcode table are slower on the i486. They're the 63677311Sobrien versions with the implicitly specified single-position 63777311Sobrien displacement, which has another syntax if you really want to 63877311Sobrien use that form. */ 63977311Sobrien if (num == 1) 64077311Sobrien return Imm1 | Imm8 | Imm8S | Imm16 | Imm32 | Imm32S | Imm64; 64177311Sobrien } 64233965Sjdp return (fits_in_signed_byte (num) 64377311Sobrien ? (Imm8S | Imm8 | Imm16 | Imm32 | Imm32S | Imm64) 64433965Sjdp : fits_in_unsigned_byte (num) 64577311Sobrien ? (Imm8 | Imm16 | Imm32 | Imm32S | Imm64) 64633965Sjdp : (fits_in_signed_word (num) || fits_in_unsigned_word (num)) 64777311Sobrien ? (Imm16 | Imm32 | Imm32S | Imm64) 64877311Sobrien : fits_in_signed_long (num) 64977311Sobrien ? (Imm32 | Imm32S | Imm64) 65077311Sobrien : fits_in_unsigned_long (num) 65177311Sobrien ? (Imm32 | Imm64) 65277311Sobrien : Imm64); 65377311Sobrien} 65433965Sjdp 65577311Sobrienstatic offsetT 65677311Sobrienoffset_in_range (val, size) 65777311Sobrien offsetT val; 65877311Sobrien int size; 65977311Sobrien{ 66077311Sobrien addressT mask; 66177311Sobrien 66277311Sobrien switch (size) 66377311Sobrien { 66477311Sobrien case 1: mask = ((addressT) 1 << 8) - 1; break; 66577311Sobrien case 2: mask = ((addressT) 1 << 16) - 1; break; 66677311Sobrien case 4: mask = ((addressT) 2 << 31) - 1; break; 66777311Sobrien#ifdef BFD64 66877311Sobrien case 8: mask = ((addressT) 2 << 63) - 1; break; 66977311Sobrien#endif 67077311Sobrien default: abort (); 67177311Sobrien } 67277311Sobrien 67377311Sobrien /* If BFD64, sign extend val. */ 67477311Sobrien if (!use_rela_relocations) 67577311Sobrien if ((val & ~(((addressT) 2 << 31) - 1)) == 0) 67677311Sobrien val = (val ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31); 67777311Sobrien 67877311Sobrien if ((val & ~mask) != 0 && (val & ~mask) != ~mask) 67977311Sobrien { 68077311Sobrien char buf1[40], buf2[40]; 68177311Sobrien 68277311Sobrien sprint_value (buf1, val); 68377311Sobrien sprint_value (buf2, val & mask); 68477311Sobrien as_warn (_("%s shortened to %s"), buf1, buf2); 68577311Sobrien } 68677311Sobrien return val & mask; 68777311Sobrien} 68877311Sobrien 68960519Sobrien/* Returns 0 if attempting to add a prefix where one from the same 69060519Sobrien class already exists, 1 if non rep/repne added, 2 if rep/repne 69160519Sobrien added. */ 69260519Sobrienstatic int 69360519Sobrienadd_prefix (prefix) 69460519Sobrien unsigned int prefix; 69560519Sobrien{ 69660519Sobrien int ret = 1; 69760519Sobrien int q; 69860519Sobrien 69994546Sobrien if (prefix >= REX_OPCODE && prefix < REX_OPCODE + 16 70094546Sobrien && flag_code == CODE_64BIT) 70177311Sobrien q = REX_PREFIX; 70277311Sobrien else 70377311Sobrien switch (prefix) 70477311Sobrien { 70577311Sobrien default: 70677311Sobrien abort (); 70760519Sobrien 70877311Sobrien case CS_PREFIX_OPCODE: 70977311Sobrien case DS_PREFIX_OPCODE: 71077311Sobrien case ES_PREFIX_OPCODE: 71177311Sobrien case FS_PREFIX_OPCODE: 71277311Sobrien case GS_PREFIX_OPCODE: 71377311Sobrien case SS_PREFIX_OPCODE: 71477311Sobrien q = SEG_PREFIX; 71577311Sobrien break; 71660519Sobrien 71777311Sobrien case REPNE_PREFIX_OPCODE: 71877311Sobrien case REPE_PREFIX_OPCODE: 71977311Sobrien ret = 2; 72077311Sobrien /* fall thru */ 72177311Sobrien case LOCK_PREFIX_OPCODE: 72277311Sobrien q = LOCKREP_PREFIX; 72377311Sobrien break; 72460519Sobrien 72577311Sobrien case FWAIT_OPCODE: 72677311Sobrien q = WAIT_PREFIX; 72777311Sobrien break; 72860519Sobrien 72977311Sobrien case ADDR_PREFIX_OPCODE: 73077311Sobrien q = ADDR_PREFIX; 73177311Sobrien break; 73260519Sobrien 73377311Sobrien case DATA_PREFIX_OPCODE: 73477311Sobrien q = DATA_PREFIX; 73577311Sobrien break; 73677311Sobrien } 73760519Sobrien 73894546Sobrien if (i.prefix[q] != 0) 73960519Sobrien { 74060519Sobrien as_bad (_("same type of prefix used twice")); 74160519Sobrien return 0; 74260519Sobrien } 74360519Sobrien 74460519Sobrien i.prefixes += 1; 74560519Sobrien i.prefix[q] = prefix; 74660519Sobrien return ret; 74760519Sobrien} 74860519Sobrien 74933965Sjdpstatic void 75077311Sobrienset_code_flag (value) 75177311Sobrien int value; 75233965Sjdp{ 75377311Sobrien flag_code = value; 75477311Sobrien cpu_arch_flags &= ~(Cpu64 | CpuNo64); 75577311Sobrien cpu_arch_flags |= (flag_code == CODE_64BIT ? Cpu64 : CpuNo64); 75677311Sobrien if (value == CODE_64BIT && !(cpu_arch_flags & CpuSledgehammer)) 75777311Sobrien { 75877311Sobrien as_bad (_("64bit mode not supported on this CPU.")); 75977311Sobrien } 76077311Sobrien if (value == CODE_32BIT && !(cpu_arch_flags & Cpu386)) 76177311Sobrien { 76277311Sobrien as_bad (_("32bit mode not supported on this CPU.")); 76377311Sobrien } 76460519Sobrien stackop_size = '\0'; 76533965Sjdp} 76633965Sjdp 76760519Sobrienstatic void 76877311Sobrienset_16bit_gcc_code_flag (new_code_flag) 76977311Sobrien int new_code_flag; 77060519Sobrien{ 77177311Sobrien flag_code = new_code_flag; 77277311Sobrien cpu_arch_flags &= ~(Cpu64 | CpuNo64); 77377311Sobrien cpu_arch_flags |= (flag_code == CODE_64BIT ? Cpu64 : CpuNo64); 77477311Sobrien stackop_size = 'l'; 77560519Sobrien} 77660519Sobrien 77760519Sobrienstatic void 77860519Sobrienset_intel_syntax (syntax_flag) 77960519Sobrien int syntax_flag; 78060519Sobrien{ 78160519Sobrien /* Find out if register prefixing is specified. */ 78260519Sobrien int ask_naked_reg = 0; 78360519Sobrien 78460519Sobrien SKIP_WHITESPACE (); 78594546Sobrien if (!is_end_of_line[(unsigned char) *input_line_pointer]) 78660519Sobrien { 78760519Sobrien char *string = input_line_pointer; 78860519Sobrien int e = get_symbol_end (); 78960519Sobrien 79077311Sobrien if (strcmp (string, "prefix") == 0) 79160519Sobrien ask_naked_reg = 1; 79277311Sobrien else if (strcmp (string, "noprefix") == 0) 79360519Sobrien ask_naked_reg = -1; 79460519Sobrien else 79560519Sobrien as_bad (_("bad argument to syntax directive.")); 79660519Sobrien *input_line_pointer = e; 79760519Sobrien } 79860519Sobrien demand_empty_rest_of_line (); 79960519Sobrien 80060519Sobrien intel_syntax = syntax_flag; 80160519Sobrien 80260519Sobrien if (ask_naked_reg == 0) 803130570Sobrien allow_naked_reg = (intel_syntax 804130570Sobrien && (bfd_get_symbol_leading_char (stdoutput) != '\0')); 80560519Sobrien else 80660519Sobrien allow_naked_reg = (ask_naked_reg < 0); 80760519Sobrien} 80860519Sobrien 80977311Sobrienstatic void 81077311Sobrienset_cpu_arch (dummy) 81177311Sobrien int dummy ATTRIBUTE_UNUSED; 81277311Sobrien{ 81377311Sobrien SKIP_WHITESPACE (); 81477311Sobrien 81594546Sobrien if (!is_end_of_line[(unsigned char) *input_line_pointer]) 81677311Sobrien { 81777311Sobrien char *string = input_line_pointer; 81877311Sobrien int e = get_symbol_end (); 81977311Sobrien int i; 82077311Sobrien 82177311Sobrien for (i = 0; cpu_arch[i].name; i++) 82277311Sobrien { 82377311Sobrien if (strcmp (string, cpu_arch[i].name) == 0) 82477311Sobrien { 82577311Sobrien cpu_arch_name = cpu_arch[i].name; 82678840Sobrien cpu_arch_flags = (cpu_arch[i].flags 82778840Sobrien | (flag_code == CODE_64BIT ? Cpu64 : CpuNo64)); 82877311Sobrien break; 82977311Sobrien } 83077311Sobrien } 83177311Sobrien if (!cpu_arch[i].name) 83277311Sobrien as_bad (_("no such architecture: `%s'"), string); 83377311Sobrien 83477311Sobrien *input_line_pointer = e; 83577311Sobrien } 83677311Sobrien else 83777311Sobrien as_bad (_("missing cpu architecture")); 83877311Sobrien 83978840Sobrien no_cond_jump_promotion = 0; 84078840Sobrien if (*input_line_pointer == ',' 84194546Sobrien && !is_end_of_line[(unsigned char) input_line_pointer[1]]) 84278840Sobrien { 84378840Sobrien char *string = ++input_line_pointer; 84478840Sobrien int e = get_symbol_end (); 84578840Sobrien 84678840Sobrien if (strcmp (string, "nojumps") == 0) 84778840Sobrien no_cond_jump_promotion = 1; 84878840Sobrien else if (strcmp (string, "jumps") == 0) 84978840Sobrien ; 85078840Sobrien else 85178840Sobrien as_bad (_("no such architecture modifier: `%s'"), string); 85278840Sobrien 85378840Sobrien *input_line_pointer = e; 85478840Sobrien } 85578840Sobrien 85677311Sobrien demand_empty_rest_of_line (); 85777311Sobrien} 85877311Sobrien 85977311Sobrienunsigned long 86077311Sobrieni386_mach () 86177311Sobrien{ 86277311Sobrien if (!strcmp (default_arch, "x86_64")) 86377311Sobrien return bfd_mach_x86_64; 86477311Sobrien else if (!strcmp (default_arch, "i386")) 86577311Sobrien return bfd_mach_i386_i386; 86677311Sobrien else 86777311Sobrien as_fatal (_("Unknown architecture")); 86877311Sobrien} 86977311Sobrien 87033965Sjdpvoid 87133965Sjdpmd_begin () 87233965Sjdp{ 87333965Sjdp const char *hash_err; 87433965Sjdp 87577311Sobrien /* Initialize op_hash hash table. */ 87633965Sjdp op_hash = hash_new (); 87733965Sjdp 87833965Sjdp { 87994546Sobrien const template *optab; 88094546Sobrien templates *core_optab; 88133965Sjdp 88277311Sobrien /* Setup for loop. */ 88377311Sobrien optab = i386_optab; 88433965Sjdp core_optab = (templates *) xmalloc (sizeof (templates)); 88560519Sobrien core_optab->start = optab; 88633965Sjdp 88760519Sobrien while (1) 88833965Sjdp { 88960519Sobrien ++optab; 89060519Sobrien if (optab->name == NULL 89160519Sobrien || strcmp (optab->name, (optab - 1)->name) != 0) 89233965Sjdp { 89333965Sjdp /* different name --> ship out current template list; 89477311Sobrien add to hash table; & begin anew. */ 89560519Sobrien core_optab->end = optab; 89660519Sobrien hash_err = hash_insert (op_hash, 89760519Sobrien (optab - 1)->name, 89860519Sobrien (PTR) core_optab); 89933965Sjdp if (hash_err) 90033965Sjdp { 90160519Sobrien as_fatal (_("Internal Error: Can't hash %s: %s"), 90260519Sobrien (optab - 1)->name, 90333965Sjdp hash_err); 90433965Sjdp } 90560519Sobrien if (optab->name == NULL) 90660519Sobrien break; 90733965Sjdp core_optab = (templates *) xmalloc (sizeof (templates)); 90860519Sobrien core_optab->start = optab; 90933965Sjdp } 91033965Sjdp } 91133965Sjdp } 91233965Sjdp 91377311Sobrien /* Initialize reg_hash hash table. */ 91433965Sjdp reg_hash = hash_new (); 91533965Sjdp { 91694546Sobrien const reg_entry *regtab; 91733965Sjdp 91860519Sobrien for (regtab = i386_regtab; 91960519Sobrien regtab < i386_regtab + sizeof (i386_regtab) / sizeof (i386_regtab[0]); 92060519Sobrien regtab++) 92133965Sjdp { 92233965Sjdp hash_err = hash_insert (reg_hash, regtab->reg_name, (PTR) regtab); 92333965Sjdp if (hash_err) 92477311Sobrien as_fatal (_("Internal Error: Can't hash %s: %s"), 92577311Sobrien regtab->reg_name, 92677311Sobrien hash_err); 92733965Sjdp } 92833965Sjdp } 92933965Sjdp 93077311Sobrien /* Fill in lexical tables: mnemonic_chars, operand_chars. */ 93133965Sjdp { 93294546Sobrien int c; 93394546Sobrien char *p; 93433965Sjdp 93533965Sjdp for (c = 0; c < 256; c++) 93633965Sjdp { 93789867Sobrien if (ISDIGIT (c)) 93833965Sjdp { 93960519Sobrien digit_chars[c] = c; 94060519Sobrien mnemonic_chars[c] = c; 94133965Sjdp register_chars[c] = c; 94260519Sobrien operand_chars[c] = c; 94333965Sjdp } 94489867Sobrien else if (ISLOWER (c)) 94533965Sjdp { 94660519Sobrien mnemonic_chars[c] = c; 94760519Sobrien register_chars[c] = c; 94860519Sobrien operand_chars[c] = c; 94933965Sjdp } 95089867Sobrien else if (ISUPPER (c)) 95133965Sjdp { 95289867Sobrien mnemonic_chars[c] = TOLOWER (c); 95360519Sobrien register_chars[c] = mnemonic_chars[c]; 95460519Sobrien operand_chars[c] = c; 95533965Sjdp } 95660519Sobrien 95789867Sobrien if (ISALPHA (c) || ISDIGIT (c)) 95860519Sobrien identifier_chars[c] = c; 95960519Sobrien else if (c >= 128) 96033965Sjdp { 96160519Sobrien identifier_chars[c] = c; 96260519Sobrien operand_chars[c] = c; 96333965Sjdp } 96460519Sobrien } 96533965Sjdp 96633965Sjdp#ifdef LEX_AT 96760519Sobrien identifier_chars['@'] = '@'; 96833965Sjdp#endif 96960519Sobrien digit_chars['-'] = '-'; 97060519Sobrien identifier_chars['_'] = '_'; 97160519Sobrien identifier_chars['.'] = '.'; 97233965Sjdp 97333965Sjdp for (p = operand_special_chars; *p != '\0'; p++) 97433965Sjdp operand_chars[(unsigned char) *p] = *p; 97533965Sjdp } 97633965Sjdp 97733965Sjdp#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 97833965Sjdp if (OUTPUT_FLAVOR == bfd_target_elf_flavour) 97933965Sjdp { 98033965Sjdp record_alignment (text_section, 2); 98133965Sjdp record_alignment (data_section, 2); 98233965Sjdp record_alignment (bss_section, 2); 98333965Sjdp } 98433965Sjdp#endif 985130570Sobrien 986130570Sobrien if (flag_code == CODE_64BIT) 987130570Sobrien { 988130570Sobrien x86_dwarf2_return_column = 16; 989130570Sobrien x86_cie_data_alignment = -8; 990130570Sobrien } 991130570Sobrien else 992130570Sobrien { 993130570Sobrien x86_dwarf2_return_column = 8; 994130570Sobrien x86_cie_data_alignment = -4; 995130570Sobrien } 99633965Sjdp} 99733965Sjdp 99833965Sjdpvoid 99933965Sjdpi386_print_statistics (file) 100033965Sjdp FILE *file; 100133965Sjdp{ 100233965Sjdp hash_print_statistics (file, "i386 opcode", op_hash); 100333965Sjdp hash_print_statistics (file, "i386 register", reg_hash); 100433965Sjdp} 100533965Sjdp 100633965Sjdp#ifdef DEBUG386 100733965Sjdp 100877311Sobrien/* Debugging routines for md_assemble. */ 100933965Sjdpstatic void pi PARAMS ((char *, i386_insn *)); 101033965Sjdpstatic void pte PARAMS ((template *)); 101133965Sjdpstatic void pt PARAMS ((unsigned int)); 101233965Sjdpstatic void pe PARAMS ((expressionS *)); 101333965Sjdpstatic void ps PARAMS ((symbolS *)); 101433965Sjdp 101533965Sjdpstatic void 101633965Sjdppi (line, x) 101733965Sjdp char *line; 101833965Sjdp i386_insn *x; 101933965Sjdp{ 102077311Sobrien unsigned int i; 102133965Sjdp 102233965Sjdp fprintf (stdout, "%s: template ", line); 102333965Sjdp pte (&x->tm); 102477311Sobrien fprintf (stdout, " address: base %s index %s scale %x\n", 102577311Sobrien x->base_reg ? x->base_reg->reg_name : "none", 102677311Sobrien x->index_reg ? x->index_reg->reg_name : "none", 102777311Sobrien x->log2_scale_factor); 102877311Sobrien fprintf (stdout, " modrm: mode %x reg %x reg/mem %x\n", 102933965Sjdp x->rm.mode, x->rm.reg, x->rm.regmem); 103077311Sobrien fprintf (stdout, " sib: base %x index %x scale %x\n", 103177311Sobrien x->sib.base, x->sib.index, x->sib.scale); 103277311Sobrien fprintf (stdout, " rex: 64bit %x extX %x extY %x extZ %x\n", 103394546Sobrien (x->rex & REX_MODE64) != 0, 103494546Sobrien (x->rex & REX_EXTX) != 0, 103594546Sobrien (x->rex & REX_EXTY) != 0, 103694546Sobrien (x->rex & REX_EXTZ) != 0); 103733965Sjdp for (i = 0; i < x->operands; i++) 103833965Sjdp { 103933965Sjdp fprintf (stdout, " #%d: ", i + 1); 104033965Sjdp pt (x->types[i]); 104133965Sjdp fprintf (stdout, "\n"); 104233965Sjdp if (x->types[i] 104360519Sobrien & (Reg | SReg2 | SReg3 | Control | Debug | Test | RegMMX | RegXMM)) 104460519Sobrien fprintf (stdout, "%s\n", x->op[i].regs->reg_name); 104533965Sjdp if (x->types[i] & Imm) 104660519Sobrien pe (x->op[i].imms); 104760519Sobrien if (x->types[i] & Disp) 104860519Sobrien pe (x->op[i].disps); 104933965Sjdp } 105033965Sjdp} 105133965Sjdp 105233965Sjdpstatic void 105333965Sjdppte (t) 105433965Sjdp template *t; 105533965Sjdp{ 105677311Sobrien unsigned int i; 105733965Sjdp fprintf (stdout, " %d operands ", t->operands); 105877311Sobrien fprintf (stdout, "opcode %x ", t->base_opcode); 105933965Sjdp if (t->extension_opcode != None) 106033965Sjdp fprintf (stdout, "ext %x ", t->extension_opcode); 106133965Sjdp if (t->opcode_modifier & D) 106233965Sjdp fprintf (stdout, "D"); 106333965Sjdp if (t->opcode_modifier & W) 106433965Sjdp fprintf (stdout, "W"); 106533965Sjdp fprintf (stdout, "\n"); 106633965Sjdp for (i = 0; i < t->operands; i++) 106733965Sjdp { 106833965Sjdp fprintf (stdout, " #%d type ", i + 1); 106933965Sjdp pt (t->operand_types[i]); 107033965Sjdp fprintf (stdout, "\n"); 107133965Sjdp } 107233965Sjdp} 107333965Sjdp 107433965Sjdpstatic void 107533965Sjdppe (e) 107633965Sjdp expressionS *e; 107733965Sjdp{ 107860519Sobrien fprintf (stdout, " operation %d\n", e->X_op); 107960519Sobrien fprintf (stdout, " add_number %ld (%lx)\n", 108060519Sobrien (long) e->X_add_number, (long) e->X_add_number); 108133965Sjdp if (e->X_add_symbol) 108233965Sjdp { 108333965Sjdp fprintf (stdout, " add_symbol "); 108433965Sjdp ps (e->X_add_symbol); 108533965Sjdp fprintf (stdout, "\n"); 108633965Sjdp } 108733965Sjdp if (e->X_op_symbol) 108833965Sjdp { 108933965Sjdp fprintf (stdout, " op_symbol "); 109033965Sjdp ps (e->X_op_symbol); 109133965Sjdp fprintf (stdout, "\n"); 109233965Sjdp } 109333965Sjdp} 109433965Sjdp 109533965Sjdpstatic void 109633965Sjdpps (s) 109733965Sjdp symbolS *s; 109833965Sjdp{ 109933965Sjdp fprintf (stdout, "%s type %s%s", 110033965Sjdp S_GET_NAME (s), 110133965Sjdp S_IS_EXTERNAL (s) ? "EXTERNAL " : "", 110233965Sjdp segment_name (S_GET_SEGMENT (s))); 110333965Sjdp} 110433965Sjdp 110533965Sjdpstruct type_name 110633965Sjdp { 110733965Sjdp unsigned int mask; 110833965Sjdp char *tname; 110933965Sjdp } 111033965Sjdp 111194546Sobrienstatic const type_names[] = 111233965Sjdp{ 111333965Sjdp { Reg8, "r8" }, 111433965Sjdp { Reg16, "r16" }, 111533965Sjdp { Reg32, "r32" }, 111677311Sobrien { Reg64, "r64" }, 111733965Sjdp { Imm8, "i8" }, 111833965Sjdp { Imm8S, "i8s" }, 111933965Sjdp { Imm16, "i16" }, 112033965Sjdp { Imm32, "i32" }, 112177311Sobrien { Imm32S, "i32s" }, 112277311Sobrien { Imm64, "i64" }, 112360519Sobrien { Imm1, "i1" }, 112433965Sjdp { BaseIndex, "BaseIndex" }, 112533965Sjdp { Disp8, "d8" }, 112633965Sjdp { Disp16, "d16" }, 112733965Sjdp { Disp32, "d32" }, 112877311Sobrien { Disp32S, "d32s" }, 112977311Sobrien { Disp64, "d64" }, 113033965Sjdp { InOutPortReg, "InOutPortReg" }, 113133965Sjdp { ShiftCount, "ShiftCount" }, 113233965Sjdp { Control, "control reg" }, 113333965Sjdp { Test, "test reg" }, 113460519Sobrien { Debug, "debug reg" }, 113533965Sjdp { FloatReg, "FReg" }, 113633965Sjdp { FloatAcc, "FAcc" }, 113760519Sobrien { SReg2, "SReg2" }, 113860519Sobrien { SReg3, "SReg3" }, 113960519Sobrien { Acc, "Acc" }, 114033965Sjdp { JumpAbsolute, "Jump Absolute" }, 114133965Sjdp { RegMMX, "rMMX" }, 114260519Sobrien { RegXMM, "rXMM" }, 114360519Sobrien { EsSeg, "es" }, 114433965Sjdp { 0, "" } 114533965Sjdp}; 114633965Sjdp 114733965Sjdpstatic void 114833965Sjdppt (t) 114933965Sjdp unsigned int t; 115033965Sjdp{ 115194546Sobrien const struct type_name *ty; 115233965Sjdp 115377311Sobrien for (ty = type_names; ty->mask; ty++) 115477311Sobrien if (t & ty->mask) 115577311Sobrien fprintf (stdout, "%s, ", ty->tname); 115633965Sjdp fflush (stdout); 115733965Sjdp} 115833965Sjdp 115933965Sjdp#endif /* DEBUG386 */ 116033965Sjdp 116194546Sobrienstatic bfd_reloc_code_real_type reloc 116294546Sobrien PARAMS ((int, int, int, bfd_reloc_code_real_type)); 116360519Sobrien 116433965Sjdpstatic bfd_reloc_code_real_type 116577311Sobrienreloc (size, pcrel, sign, other) 116633965Sjdp int size; 116733965Sjdp int pcrel; 116877311Sobrien int sign; 116933965Sjdp bfd_reloc_code_real_type other; 117033965Sjdp{ 117177311Sobrien if (other != NO_RELOC) 117277311Sobrien return other; 117333965Sjdp 117433965Sjdp if (pcrel) 117560519Sobrien { 117677311Sobrien if (!sign) 117777311Sobrien as_bad (_("There are no unsigned pc-relative relocations")); 117860519Sobrien switch (size) 117960519Sobrien { 118060519Sobrien case 1: return BFD_RELOC_8_PCREL; 118160519Sobrien case 2: return BFD_RELOC_16_PCREL; 118260519Sobrien case 4: return BFD_RELOC_32_PCREL; 118360519Sobrien } 118460519Sobrien as_bad (_("can not do %d byte pc-relative relocation"), size); 118560519Sobrien } 118633965Sjdp else 118760519Sobrien { 118877311Sobrien if (sign) 118977311Sobrien switch (size) 119077311Sobrien { 119177311Sobrien case 4: return BFD_RELOC_X86_64_32S; 119277311Sobrien } 119377311Sobrien else 119477311Sobrien switch (size) 119577311Sobrien { 119677311Sobrien case 1: return BFD_RELOC_8; 119777311Sobrien case 2: return BFD_RELOC_16; 119877311Sobrien case 4: return BFD_RELOC_32; 119977311Sobrien case 8: return BFD_RELOC_64; 120077311Sobrien } 120177311Sobrien as_bad (_("can not do %s %d byte relocation"), 120277311Sobrien sign ? "signed" : "unsigned", size); 120360519Sobrien } 120433965Sjdp 120577311Sobrien abort (); 120633965Sjdp return BFD_RELOC_NONE; 120733965Sjdp} 120833965Sjdp 120977311Sobrien/* Here we decide which fixups can be adjusted to make them relative to 121077311Sobrien the beginning of the section instead of the symbol. Basically we need 121177311Sobrien to make sure that the dynamic relocations are done correctly, so in 121277311Sobrien some cases we force the original symbol to be used. */ 121377311Sobrien 121433965Sjdpint 121560519Sobrientc_i386_fix_adjustable (fixP) 1216104848Sobrien fixS *fixP ATTRIBUTE_UNUSED; 121733965Sjdp{ 121877311Sobrien#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 1219104848Sobrien if (OUTPUT_FLAVOR != bfd_target_elf_flavour) 1220104848Sobrien return 1; 1221104848Sobrien 1222130570Sobrien /* Don't adjust pc-relative references to merge sections in 64-bit 1223130570Sobrien mode. */ 1224130570Sobrien if (use_rela_relocations 1225130570Sobrien && (S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0 1226130570Sobrien && fixP->fx_pcrel) 122733965Sjdp return 0; 1228104848Sobrien 1229130570Sobrien /* The x86_64 GOTPCREL are represented as 32bit PCrel relocations 1230130570Sobrien and changed later by validate_fix. */ 1231130570Sobrien if (GOT_symbol && fixP->fx_subsy == GOT_symbol 1232130570Sobrien && fixP->fx_r_type == BFD_RELOC_32_PCREL) 1233130570Sobrien return 0; 1234130570Sobrien 123577311Sobrien /* adjust_reloc_syms doesn't know about the GOT. */ 123633965Sjdp if (fixP->fx_r_type == BFD_RELOC_386_GOTOFF 123733965Sjdp || fixP->fx_r_type == BFD_RELOC_386_PLT32 123860519Sobrien || fixP->fx_r_type == BFD_RELOC_386_GOT32 1239104848Sobrien || fixP->fx_r_type == BFD_RELOC_386_TLS_GD 1240104848Sobrien || fixP->fx_r_type == BFD_RELOC_386_TLS_LDM 1241104848Sobrien || fixP->fx_r_type == BFD_RELOC_386_TLS_LDO_32 1242104848Sobrien || fixP->fx_r_type == BFD_RELOC_386_TLS_IE_32 1243104848Sobrien || fixP->fx_r_type == BFD_RELOC_386_TLS_IE 1244104848Sobrien || fixP->fx_r_type == BFD_RELOC_386_TLS_GOTIE 1245104848Sobrien || fixP->fx_r_type == BFD_RELOC_386_TLS_LE_32 1246104848Sobrien || fixP->fx_r_type == BFD_RELOC_386_TLS_LE 124777311Sobrien || fixP->fx_r_type == BFD_RELOC_X86_64_PLT32 124877311Sobrien || fixP->fx_r_type == BFD_RELOC_X86_64_GOT32 124977311Sobrien || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL 1250130570Sobrien || fixP->fx_r_type == BFD_RELOC_X86_64_TLSGD 1251130570Sobrien || fixP->fx_r_type == BFD_RELOC_X86_64_TLSLD 1252130570Sobrien || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF32 1253130570Sobrien || fixP->fx_r_type == BFD_RELOC_X86_64_GOTTPOFF 1254130570Sobrien || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF32 125560519Sobrien || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT 125660519Sobrien || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) 125733965Sjdp return 0; 1258104848Sobrien#endif 125933965Sjdp return 1; 126033965Sjdp} 126133965Sjdp 126294546Sobrienstatic int intel_float_operand PARAMS ((const char *mnemonic)); 126360519Sobrien 126460519Sobrienstatic int 126560519Sobrienintel_float_operand (mnemonic) 126694546Sobrien const char *mnemonic; 126760519Sobrien{ 126877311Sobrien if (mnemonic[0] == 'f' && mnemonic[1] == 'i') 126960519Sobrien return 2; 127060519Sobrien 127160519Sobrien if (mnemonic[0] == 'f') 127260519Sobrien return 1; 127360519Sobrien 127460519Sobrien return 0; 127560519Sobrien} 127660519Sobrien 127733965Sjdp/* This is the guts of the machine-dependent assembler. LINE points to a 127833965Sjdp machine dependent instruction. This function is supposed to emit 127933965Sjdp the frags/bytes it assembles to. */ 128033965Sjdp 128133965Sjdpvoid 128233965Sjdpmd_assemble (line) 128333965Sjdp char *line; 128433965Sjdp{ 128533965Sjdp int j; 128660519Sobrien char mnemonic[MAX_MNEM_SIZE]; 128738891Sjdp 128877311Sobrien /* Initialize globals. */ 128933965Sjdp memset (&i, '\0', sizeof (i)); 129033965Sjdp for (j = 0; j < MAX_OPERANDS; j++) 129178840Sobrien i.reloc[j] = NO_RELOC; 129233965Sjdp memset (disp_expressions, '\0', sizeof (disp_expressions)); 129333965Sjdp memset (im_expressions, '\0', sizeof (im_expressions)); 129477311Sobrien save_stack_p = save_stack; 129533965Sjdp 129660519Sobrien /* First parse an instruction mnemonic & call i386_operand for the operands. 129733965Sjdp We assume that the scrubber has arranged it so that line[0] is the valid 129877311Sobrien start of a (possibly prefixed) mnemonic. */ 129933965Sjdp 130094546Sobrien line = parse_insn (line, mnemonic); 130194546Sobrien if (line == NULL) 130294546Sobrien return; 130360519Sobrien 130494546Sobrien line = parse_operands (line, mnemonic); 130594546Sobrien if (line == NULL) 130694546Sobrien return; 130760519Sobrien 130894546Sobrien /* Now we've parsed the mnemonic into a set of templates, and have the 130994546Sobrien operands at hand. */ 131060519Sobrien 131194546Sobrien /* All intel opcodes have reversed operands except for "bound" and 131294546Sobrien "enter". We also don't reverse intersegment "jmp" and "call" 131394546Sobrien instructions with 2 immediate operands so that the immediate segment 131494546Sobrien precedes the offset, as it does when in AT&T mode. "enter" and the 131594546Sobrien intersegment "jmp" and "call" instructions are the only ones that 131694546Sobrien have two immediate operands. */ 131794546Sobrien if (intel_syntax && i.operands > 1 131894546Sobrien && (strcmp (mnemonic, "bound") != 0) 131994546Sobrien && !((i.types[0] & Imm) && (i.types[1] & Imm))) 132094546Sobrien swap_operands (); 132133965Sjdp 132294546Sobrien if (i.imm_operands) 132394546Sobrien optimize_imm (); 132460519Sobrien 132594546Sobrien if (i.disp_operands) 132694546Sobrien optimize_disp (); 132733965Sjdp 132894546Sobrien /* Next, we find a template that matches the given insn, 132994546Sobrien making sure the overlap of the given operands types is consistent 133094546Sobrien with the template operand types. */ 133177311Sobrien 133294546Sobrien if (!match_template ()) 133394546Sobrien return; 133489867Sobrien 1335104848Sobrien if (intel_syntax) 1336104848Sobrien { 1337104848Sobrien /* Undo SYSV386_COMPAT brokenness when in Intel mode. See i386.h */ 1338104848Sobrien if (SYSV386_COMPAT 1339104848Sobrien && (i.tm.base_opcode & 0xfffffde0) == 0xdce0) 1340104848Sobrien i.tm.base_opcode ^= FloatR; 134194546Sobrien 1342104848Sobrien /* Zap movzx and movsx suffix. The suffix may have been set from 1343104848Sobrien "word ptr" or "byte ptr" on the source operand, but we'll use 1344104848Sobrien the suffix later to choose the destination register. */ 1345104848Sobrien if ((i.tm.base_opcode & ~9) == 0x0fb6) 1346104848Sobrien i.suffix = 0; 1347104848Sobrien } 1348104848Sobrien 134994546Sobrien if (i.tm.opcode_modifier & FWait) 135094546Sobrien if (!add_prefix (FWAIT_OPCODE)) 135194546Sobrien return; 135294546Sobrien 135394546Sobrien /* Check string instruction segment overrides. */ 135494546Sobrien if ((i.tm.opcode_modifier & IsString) != 0 && i.mem_operands != 0) 135594546Sobrien { 135694546Sobrien if (!check_string ()) 135733965Sjdp return; 135894546Sobrien } 135933965Sjdp 136094546Sobrien if (!process_suffix ()) 136194546Sobrien return; 136260519Sobrien 136394546Sobrien /* Make still unresolved immediate matches conform to size of immediate 136494546Sobrien given in i.suffix. */ 136594546Sobrien if (!finalize_imm ()) 136694546Sobrien return; 136760519Sobrien 136894546Sobrien if (i.types[0] & Imm1) 136994546Sobrien i.imm_operands = 0; /* kludge for shift insns. */ 137094546Sobrien if (i.types[0] & ImplicitRegister) 137194546Sobrien i.reg_operands--; 137294546Sobrien if (i.types[1] & ImplicitRegister) 137394546Sobrien i.reg_operands--; 137494546Sobrien if (i.types[2] & ImplicitRegister) 137594546Sobrien i.reg_operands--; 137660519Sobrien 137794546Sobrien if (i.tm.opcode_modifier & ImmExt) 137894546Sobrien { 1379130570Sobrien expressionS *exp; 1380130570Sobrien 1381130570Sobrien if ((i.tm.cpu_flags & CpuPNI) && i.operands > 0) 1382130570Sobrien { 1383130570Sobrien /* These Intel Prescott New Instructions have the fixed 1384130570Sobrien operands with an opcode suffix which is coded in the same 1385130570Sobrien place as an 8-bit immediate field would be. Here we check 1386130570Sobrien those operands and remove them afterwards. */ 1387130570Sobrien unsigned int x; 1388130570Sobrien 1389130570Sobrien for (x = 0; x < i.operands; x++) 1390130570Sobrien if (i.op[x].regs->reg_num != x) 1391130570Sobrien as_bad (_("can't use register '%%%s' as operand %d in '%s'."), 1392130570Sobrien i.op[x].regs->reg_name, x + 1, i.tm.name); 1393130570Sobrien i.operands = 0; 1394130570Sobrien } 1395130570Sobrien 139694546Sobrien /* These AMD 3DNow! and Intel Katmai New Instructions have an 139794546Sobrien opcode suffix which is coded in the same place as an 8-bit 139894546Sobrien immediate field would be. Here we fake an 8-bit immediate 139994546Sobrien operand from the opcode suffix stored in tm.extension_opcode. */ 140060519Sobrien 140194546Sobrien assert (i.imm_operands == 0 && i.operands <= 2 && 2 < MAX_OPERANDS); 140233965Sjdp 140394546Sobrien exp = &im_expressions[i.imm_operands++]; 140494546Sobrien i.op[i.operands].imms = exp; 140594546Sobrien i.types[i.operands++] = Imm8; 140694546Sobrien exp->X_op = O_constant; 140794546Sobrien exp->X_add_number = i.tm.extension_opcode; 140894546Sobrien i.tm.extension_opcode = None; 140994546Sobrien } 141033965Sjdp 141194546Sobrien /* For insns with operands there are more diddles to do to the opcode. */ 141294546Sobrien if (i.operands) 141394546Sobrien { 141494546Sobrien if (!process_operands ()) 141594546Sobrien return; 141694546Sobrien } 141794546Sobrien else if (!quiet_warnings && (i.tm.opcode_modifier & Ugh) != 0) 141894546Sobrien { 141994546Sobrien /* UnixWare fsub no args is alias for fsubp, fadd -> faddp, etc. */ 142094546Sobrien as_warn (_("translating to `%sp'"), i.tm.name); 142194546Sobrien } 142233965Sjdp 142394546Sobrien /* Handle conversion of 'int $3' --> special int3 insn. */ 142494546Sobrien if (i.tm.base_opcode == INT_OPCODE && i.op[0].imms->X_add_number == 3) 142594546Sobrien { 142694546Sobrien i.tm.base_opcode = INT3_OPCODE; 142794546Sobrien i.imm_operands = 0; 142894546Sobrien } 142933965Sjdp 143094546Sobrien if ((i.tm.opcode_modifier & (Jump | JumpByte | JumpDword)) 143194546Sobrien && i.op[0].disps->X_op == O_constant) 143294546Sobrien { 143394546Sobrien /* Convert "jmp constant" (and "call constant") to a jump (call) to 143494546Sobrien the absolute address given by the constant. Since ix86 jumps and 143594546Sobrien calls are pc relative, we need to generate a reloc. */ 143694546Sobrien i.op[0].disps->X_add_symbol = &abs_symbol; 143794546Sobrien i.op[0].disps->X_op = O_symbol; 143894546Sobrien } 143933965Sjdp 144094546Sobrien if ((i.tm.opcode_modifier & Rex64) != 0) 144194546Sobrien i.rex |= REX_MODE64; 144233965Sjdp 144394546Sobrien /* For 8 bit registers we need an empty rex prefix. Also if the 144494546Sobrien instruction already has a prefix, we need to convert old 144594546Sobrien registers to new ones. */ 144660519Sobrien 144794546Sobrien if (((i.types[0] & Reg8) != 0 144894546Sobrien && (i.op[0].regs->reg_flags & RegRex64) != 0) 144994546Sobrien || ((i.types[1] & Reg8) != 0 145094546Sobrien && (i.op[1].regs->reg_flags & RegRex64) != 0) 145194546Sobrien || (((i.types[0] & Reg8) != 0 || (i.types[1] & Reg8) != 0) 145294546Sobrien && i.rex != 0)) 145394546Sobrien { 145494546Sobrien int x; 145560519Sobrien 145694546Sobrien i.rex |= REX_OPCODE; 145794546Sobrien for (x = 0; x < 2; x++) 145894546Sobrien { 145994546Sobrien /* Look for 8 bit operand that uses old registers. */ 146094546Sobrien if ((i.types[x] & Reg8) != 0 146194546Sobrien && (i.op[x].regs->reg_flags & RegRex64) == 0) 146294546Sobrien { 146394546Sobrien /* In case it is "hi" register, give up. */ 146494546Sobrien if (i.op[x].regs->reg_num > 3) 146594546Sobrien as_bad (_("can't encode register '%%%s' in an instruction requiring REX prefix.\n"), 146694546Sobrien i.op[x].regs->reg_name); 146760519Sobrien 146894546Sobrien /* Otherwise it is equivalent to the extended register. 146994546Sobrien Since the encoding doesn't change this is merely 147094546Sobrien cosmetic cleanup for debug output. */ 147160519Sobrien 147294546Sobrien i.op[x].regs = i.op[x].regs + 8; 147394546Sobrien } 147494546Sobrien } 147594546Sobrien } 147660519Sobrien 147794546Sobrien if (i.rex != 0) 147894546Sobrien add_prefix (REX_OPCODE | i.rex); 147994546Sobrien 148094546Sobrien /* We are ready to output the insn. */ 148194546Sobrien output_insn (); 148294546Sobrien} 148394546Sobrien 148494546Sobrienstatic char * 148594546Sobrienparse_insn (line, mnemonic) 148694546Sobrien char *line; 148794546Sobrien char *mnemonic; 148894546Sobrien{ 148994546Sobrien char *l = line; 149094546Sobrien char *token_start = l; 149194546Sobrien char *mnem_p; 149294546Sobrien 149394546Sobrien /* Non-zero if we found a prefix only acceptable with string insns. */ 149494546Sobrien const char *expecting_string_instruction = NULL; 149594546Sobrien 149694546Sobrien while (1) 149794546Sobrien { 149894546Sobrien mnem_p = mnemonic; 149994546Sobrien while ((*mnem_p = mnemonic_chars[(unsigned char) *l]) != 0) 150094546Sobrien { 150194546Sobrien mnem_p++; 150294546Sobrien if (mnem_p >= mnemonic + MAX_MNEM_SIZE) 150360519Sobrien { 150494546Sobrien as_bad (_("no such instruction: `%s'"), token_start); 150594546Sobrien return NULL; 150694546Sobrien } 150794546Sobrien l++; 150894546Sobrien } 150994546Sobrien if (!is_space_char (*l) 151094546Sobrien && *l != END_OF_INSN 151194546Sobrien && *l != PREFIX_SEPARATOR 151294546Sobrien && *l != ',') 151394546Sobrien { 151494546Sobrien as_bad (_("invalid character %s in mnemonic"), 151594546Sobrien output_invalid (*l)); 151694546Sobrien return NULL; 151794546Sobrien } 151894546Sobrien if (token_start == l) 151994546Sobrien { 152094546Sobrien if (*l == PREFIX_SEPARATOR) 152194546Sobrien as_bad (_("expecting prefix; got nothing")); 152294546Sobrien else 152394546Sobrien as_bad (_("expecting mnemonic; got nothing")); 152494546Sobrien return NULL; 152594546Sobrien } 152677311Sobrien 152794546Sobrien /* Look up instruction (or prefix) via hash table. */ 152894546Sobrien current_templates = hash_find (op_hash, mnemonic); 152994546Sobrien 153094546Sobrien if (*l != END_OF_INSN 153194546Sobrien && (!is_space_char (*l) || l[1] != END_OF_INSN) 153294546Sobrien && current_templates 153394546Sobrien && (current_templates->start->opcode_modifier & IsPrefix)) 153494546Sobrien { 153594546Sobrien /* If we are in 16-bit mode, do not allow addr16 or data16. 153694546Sobrien Similarly, in 32-bit mode, do not allow addr32 or data32. */ 153794546Sobrien if ((current_templates->start->opcode_modifier & (Size16 | Size32)) 153894546Sobrien && flag_code != CODE_64BIT 153994546Sobrien && (((current_templates->start->opcode_modifier & Size32) != 0) 154094546Sobrien ^ (flag_code == CODE_16BIT))) 154194546Sobrien { 154294546Sobrien as_bad (_("redundant %s prefix"), 154394546Sobrien current_templates->start->name); 154494546Sobrien return NULL; 154577311Sobrien } 154694546Sobrien /* Add prefix, checking for repeated prefixes. */ 154794546Sobrien switch (add_prefix (current_templates->start->base_opcode)) 154894546Sobrien { 154994546Sobrien case 0: 155094546Sobrien return NULL; 155194546Sobrien case 2: 155294546Sobrien expecting_string_instruction = current_templates->start->name; 155394546Sobrien break; 155494546Sobrien } 155594546Sobrien /* Skip past PREFIX_SEPARATOR and reset token_start. */ 155694546Sobrien token_start = ++l; 155794546Sobrien } 155894546Sobrien else 155994546Sobrien break; 156094546Sobrien } 156160519Sobrien 156294546Sobrien if (!current_templates) 156394546Sobrien { 156494546Sobrien /* See if we can get a match by trimming off a suffix. */ 156594546Sobrien switch (mnem_p[-1]) 156694546Sobrien { 156794546Sobrien case WORD_MNEM_SUFFIX: 156894546Sobrien case BYTE_MNEM_SUFFIX: 156994546Sobrien case QWORD_MNEM_SUFFIX: 157094546Sobrien i.suffix = mnem_p[-1]; 157194546Sobrien mnem_p[-1] = '\0'; 157294546Sobrien current_templates = hash_find (op_hash, mnemonic); 157394546Sobrien break; 157494546Sobrien case SHORT_MNEM_SUFFIX: 157594546Sobrien case LONG_MNEM_SUFFIX: 157694546Sobrien if (!intel_syntax) 157794546Sobrien { 157894546Sobrien i.suffix = mnem_p[-1]; 157994546Sobrien mnem_p[-1] = '\0'; 158094546Sobrien current_templates = hash_find (op_hash, mnemonic); 158194546Sobrien } 158294546Sobrien break; 158377311Sobrien 158494546Sobrien /* Intel Syntax. */ 158594546Sobrien case 'd': 158694546Sobrien if (intel_syntax) 158777311Sobrien { 158894546Sobrien if (intel_float_operand (mnemonic)) 158994546Sobrien i.suffix = SHORT_MNEM_SUFFIX; 159094546Sobrien else 159194546Sobrien i.suffix = LONG_MNEM_SUFFIX; 159294546Sobrien mnem_p[-1] = '\0'; 159394546Sobrien current_templates = hash_find (op_hash, mnemonic); 159494546Sobrien } 159594546Sobrien break; 159694546Sobrien } 159794546Sobrien if (!current_templates) 159894546Sobrien { 159994546Sobrien as_bad (_("no such instruction: `%s'"), token_start); 160094546Sobrien return NULL; 160194546Sobrien } 160294546Sobrien } 160377311Sobrien 160494546Sobrien if (current_templates->start->opcode_modifier & (Jump | JumpByte)) 160594546Sobrien { 160694546Sobrien /* Check for a branch hint. We allow ",pt" and ",pn" for 160794546Sobrien predict taken and predict not taken respectively. 160894546Sobrien I'm not sure that branch hints actually do anything on loop 160994546Sobrien and jcxz insns (JumpByte) for current Pentium4 chips. They 161094546Sobrien may work in the future and it doesn't hurt to accept them 161194546Sobrien now. */ 161294546Sobrien if (l[0] == ',' && l[1] == 'p') 161394546Sobrien { 161494546Sobrien if (l[2] == 't') 161594546Sobrien { 161694546Sobrien if (!add_prefix (DS_PREFIX_OPCODE)) 161794546Sobrien return NULL; 161894546Sobrien l += 3; 161994546Sobrien } 162094546Sobrien else if (l[2] == 'n') 162194546Sobrien { 162294546Sobrien if (!add_prefix (CS_PREFIX_OPCODE)) 162394546Sobrien return NULL; 162494546Sobrien l += 3; 162594546Sobrien } 162694546Sobrien } 162794546Sobrien } 162894546Sobrien /* Any other comma loses. */ 162994546Sobrien if (*l == ',') 163094546Sobrien { 163194546Sobrien as_bad (_("invalid character %s in mnemonic"), 163294546Sobrien output_invalid (*l)); 163394546Sobrien return NULL; 163494546Sobrien } 163577311Sobrien 163694546Sobrien /* Check if instruction is supported on specified architecture. */ 163794546Sobrien if ((current_templates->start->cpu_flags & ~(Cpu64 | CpuNo64)) 163894546Sobrien & ~(cpu_arch_flags & ~(Cpu64 | CpuNo64))) 163994546Sobrien { 164094546Sobrien as_warn (_("`%s' is not supported on `%s'"), 164194546Sobrien current_templates->start->name, cpu_arch_name); 164294546Sobrien } 164394546Sobrien else if ((Cpu386 & ~cpu_arch_flags) && (flag_code != CODE_16BIT)) 164494546Sobrien { 164594546Sobrien as_warn (_("use .code16 to ensure correct addressing mode")); 164694546Sobrien } 164794546Sobrien 164894546Sobrien /* Check for rep/repne without a string instruction. */ 164994546Sobrien if (expecting_string_instruction 165094546Sobrien && !(current_templates->start->opcode_modifier & IsString)) 165194546Sobrien { 165294546Sobrien as_bad (_("expecting string instruction after `%s'"), 165394546Sobrien expecting_string_instruction); 165494546Sobrien return NULL; 165594546Sobrien } 165694546Sobrien 165794546Sobrien return l; 165894546Sobrien} 165994546Sobrien 166094546Sobrienstatic char * 166194546Sobrienparse_operands (l, mnemonic) 166294546Sobrien char *l; 166394546Sobrien const char *mnemonic; 166494546Sobrien{ 166594546Sobrien char *token_start; 166694546Sobrien 166794546Sobrien /* 1 if operand is pending after ','. */ 166894546Sobrien unsigned int expecting_operand = 0; 166994546Sobrien 167094546Sobrien /* Non-zero if operand parens not balanced. */ 167194546Sobrien unsigned int paren_not_balanced; 167294546Sobrien 167394546Sobrien while (*l != END_OF_INSN) 167494546Sobrien { 167594546Sobrien /* Skip optional white space before operand. */ 167694546Sobrien if (is_space_char (*l)) 167794546Sobrien ++l; 167894546Sobrien if (!is_operand_char (*l) && *l != END_OF_INSN) 167994546Sobrien { 168094546Sobrien as_bad (_("invalid character %s before operand %d"), 168194546Sobrien output_invalid (*l), 168294546Sobrien i.operands + 1); 168394546Sobrien return NULL; 168494546Sobrien } 168594546Sobrien token_start = l; /* after white space */ 168694546Sobrien paren_not_balanced = 0; 168794546Sobrien while (paren_not_balanced || *l != ',') 168894546Sobrien { 168994546Sobrien if (*l == END_OF_INSN) 169094546Sobrien { 169194546Sobrien if (paren_not_balanced) 169277311Sobrien { 169394546Sobrien if (!intel_syntax) 169494546Sobrien as_bad (_("unbalanced parenthesis in operand %d."), 169594546Sobrien i.operands + 1); 169694546Sobrien else 169794546Sobrien as_bad (_("unbalanced brackets in operand %d."), 169894546Sobrien i.operands + 1); 169994546Sobrien return NULL; 170077311Sobrien } 170194546Sobrien else 170294546Sobrien break; /* we are done */ 170360519Sobrien } 170494546Sobrien else if (!is_operand_char (*l) && !is_space_char (*l)) 170594546Sobrien { 170694546Sobrien as_bad (_("invalid character %s in operand %d"), 170794546Sobrien output_invalid (*l), 170894546Sobrien i.operands + 1); 170994546Sobrien return NULL; 171094546Sobrien } 171194546Sobrien if (!intel_syntax) 171294546Sobrien { 171394546Sobrien if (*l == '(') 171494546Sobrien ++paren_not_balanced; 171594546Sobrien if (*l == ')') 171694546Sobrien --paren_not_balanced; 171794546Sobrien } 171894546Sobrien else 171994546Sobrien { 172094546Sobrien if (*l == '[') 172194546Sobrien ++paren_not_balanced; 172294546Sobrien if (*l == ']') 172394546Sobrien --paren_not_balanced; 172494546Sobrien } 172594546Sobrien l++; 172694546Sobrien } 172794546Sobrien if (l != token_start) 172894546Sobrien { /* Yes, we've read in another operand. */ 172994546Sobrien unsigned int operand_ok; 173094546Sobrien this_operand = i.operands++; 173194546Sobrien if (i.operands > MAX_OPERANDS) 173294546Sobrien { 173394546Sobrien as_bad (_("spurious operands; (%d operands/instruction max)"), 173494546Sobrien MAX_OPERANDS); 173594546Sobrien return NULL; 173694546Sobrien } 173794546Sobrien /* Now parse operand adding info to 'i' as we go along. */ 173894546Sobrien END_STRING_AND_SAVE (l); 173960519Sobrien 174094546Sobrien if (intel_syntax) 174194546Sobrien operand_ok = 174294546Sobrien i386_intel_operand (token_start, 174394546Sobrien intel_float_operand (mnemonic)); 174494546Sobrien else 174594546Sobrien operand_ok = i386_operand (token_start); 174660519Sobrien 174794546Sobrien RESTORE_END_STRING (l); 174894546Sobrien if (!operand_ok) 174994546Sobrien return NULL; 175094546Sobrien } 175194546Sobrien else 175294546Sobrien { 175394546Sobrien if (expecting_operand) 175494546Sobrien { 175594546Sobrien expecting_operand_after_comma: 175694546Sobrien as_bad (_("expecting operand after ','; got nothing")); 175794546Sobrien return NULL; 175894546Sobrien } 175994546Sobrien if (*l == ',') 176094546Sobrien { 176194546Sobrien as_bad (_("expecting operand before ','; got nothing")); 176294546Sobrien return NULL; 176394546Sobrien } 176494546Sobrien } 176560519Sobrien 176694546Sobrien /* Now *l must be either ',' or END_OF_INSN. */ 176794546Sobrien if (*l == ',') 176894546Sobrien { 176994546Sobrien if (*++l == END_OF_INSN) 177094546Sobrien { 177194546Sobrien /* Just skip it, if it's \n complain. */ 177294546Sobrien goto expecting_operand_after_comma; 177394546Sobrien } 177494546Sobrien expecting_operand = 1; 177594546Sobrien } 177694546Sobrien } 177794546Sobrien return l; 177894546Sobrien} 177960519Sobrien 178094546Sobrienstatic void 178194546Sobrienswap_operands () 178294546Sobrien{ 178394546Sobrien union i386_op temp_op; 178494546Sobrien unsigned int temp_type; 1785130570Sobrien enum bfd_reloc_code_real temp_reloc; 178694546Sobrien int xchg1 = 0; 178794546Sobrien int xchg2 = 0; 178894546Sobrien 178994546Sobrien if (i.operands == 2) 179094546Sobrien { 179194546Sobrien xchg1 = 0; 179294546Sobrien xchg2 = 1; 179394546Sobrien } 179494546Sobrien else if (i.operands == 3) 179594546Sobrien { 179694546Sobrien xchg1 = 0; 179794546Sobrien xchg2 = 2; 179894546Sobrien } 179994546Sobrien temp_type = i.types[xchg2]; 180094546Sobrien i.types[xchg2] = i.types[xchg1]; 180194546Sobrien i.types[xchg1] = temp_type; 180294546Sobrien temp_op = i.op[xchg2]; 180394546Sobrien i.op[xchg2] = i.op[xchg1]; 180494546Sobrien i.op[xchg1] = temp_op; 180594546Sobrien temp_reloc = i.reloc[xchg2]; 180694546Sobrien i.reloc[xchg2] = i.reloc[xchg1]; 180794546Sobrien i.reloc[xchg1] = temp_reloc; 180894546Sobrien 180994546Sobrien if (i.mem_operands == 2) 181094546Sobrien { 181194546Sobrien const seg_entry *temp_seg; 181294546Sobrien temp_seg = i.seg[0]; 181394546Sobrien i.seg[0] = i.seg[1]; 181494546Sobrien i.seg[1] = temp_seg; 181594546Sobrien } 181694546Sobrien} 181794546Sobrien 181894546Sobrien/* Try to ensure constant immediates are represented in the smallest 181994546Sobrien opcode possible. */ 182094546Sobrienstatic void 182194546Sobrienoptimize_imm () 182294546Sobrien{ 182394546Sobrien char guess_suffix = 0; 182494546Sobrien int op; 182594546Sobrien 182694546Sobrien if (i.suffix) 182794546Sobrien guess_suffix = i.suffix; 182894546Sobrien else if (i.reg_operands) 182994546Sobrien { 183094546Sobrien /* Figure out a suffix from the last register operand specified. 183194546Sobrien We can't do this properly yet, ie. excluding InOutPortReg, 183294546Sobrien but the following works for instructions with immediates. 183394546Sobrien In any case, we can't set i.suffix yet. */ 183494546Sobrien for (op = i.operands; --op >= 0;) 183594546Sobrien if (i.types[op] & Reg) 183677311Sobrien { 183794546Sobrien if (i.types[op] & Reg8) 183894546Sobrien guess_suffix = BYTE_MNEM_SUFFIX; 183994546Sobrien else if (i.types[op] & Reg16) 184094546Sobrien guess_suffix = WORD_MNEM_SUFFIX; 184194546Sobrien else if (i.types[op] & Reg32) 184294546Sobrien guess_suffix = LONG_MNEM_SUFFIX; 184394546Sobrien else if (i.types[op] & Reg64) 184494546Sobrien guess_suffix = QWORD_MNEM_SUFFIX; 184577311Sobrien break; 184677311Sobrien } 184794546Sobrien } 184894546Sobrien else if ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0)) 184994546Sobrien guess_suffix = WORD_MNEM_SUFFIX; 185033965Sjdp 185194546Sobrien for (op = i.operands; --op >= 0;) 185294546Sobrien if (i.types[op] & Imm) 185394546Sobrien { 185494546Sobrien switch (i.op[op].imms->X_op) 185533965Sjdp { 185694546Sobrien case O_constant: 185794546Sobrien /* If a suffix is given, this operand may be shortened. */ 185894546Sobrien switch (guess_suffix) 185933965Sjdp { 186094546Sobrien case LONG_MNEM_SUFFIX: 186194546Sobrien i.types[op] |= Imm32 | Imm64; 186294546Sobrien break; 186394546Sobrien case WORD_MNEM_SUFFIX: 186494546Sobrien i.types[op] |= Imm16 | Imm32S | Imm32 | Imm64; 186594546Sobrien break; 186694546Sobrien case BYTE_MNEM_SUFFIX: 186794546Sobrien i.types[op] |= Imm16 | Imm8 | Imm8S | Imm32S | Imm32 | Imm64; 186894546Sobrien break; 186994546Sobrien } 187033965Sjdp 187194546Sobrien /* If this operand is at most 16 bits, convert it 187294546Sobrien to a signed 16 bit number before trying to see 187394546Sobrien whether it will fit in an even smaller size. 187494546Sobrien This allows a 16-bit operand such as $0xffe0 to 187594546Sobrien be recognised as within Imm8S range. */ 187694546Sobrien if ((i.types[op] & Imm16) 187794546Sobrien && (i.op[op].imms->X_add_number & ~(offsetT) 0xffff) == 0) 187894546Sobrien { 187994546Sobrien i.op[op].imms->X_add_number = 188094546Sobrien (((i.op[op].imms->X_add_number & 0xffff) ^ 0x8000) - 0x8000); 188160519Sobrien } 188294546Sobrien if ((i.types[op] & Imm32) 188394546Sobrien && ((i.op[op].imms->X_add_number & ~(((offsetT) 2 << 31) - 1)) 188494546Sobrien == 0)) 188533965Sjdp { 188694546Sobrien i.op[op].imms->X_add_number = ((i.op[op].imms->X_add_number 188794546Sobrien ^ ((offsetT) 1 << 31)) 188894546Sobrien - ((offsetT) 1 << 31)); 188994546Sobrien } 189094546Sobrien i.types[op] |= smallest_imm_type (i.op[op].imms->X_add_number); 189160519Sobrien 189294546Sobrien /* We must avoid matching of Imm32 templates when 64bit 189394546Sobrien only immediate is available. */ 189494546Sobrien if (guess_suffix == QWORD_MNEM_SUFFIX) 189594546Sobrien i.types[op] &= ~Imm32; 189694546Sobrien break; 189794546Sobrien 189894546Sobrien case O_absent: 189994546Sobrien case O_register: 190094546Sobrien abort (); 190194546Sobrien 190294546Sobrien /* Symbols and expressions. */ 190394546Sobrien default: 190494546Sobrien /* Convert symbolic operand to proper sizes for matching. */ 190594546Sobrien switch (guess_suffix) 190694546Sobrien { 190794546Sobrien case QWORD_MNEM_SUFFIX: 190894546Sobrien i.types[op] = Imm64 | Imm32S; 190994546Sobrien break; 191094546Sobrien case LONG_MNEM_SUFFIX: 191194546Sobrien i.types[op] = Imm32 | Imm64; 191294546Sobrien break; 191394546Sobrien case WORD_MNEM_SUFFIX: 191494546Sobrien i.types[op] = Imm16 | Imm32 | Imm64; 191594546Sobrien break; 191694546Sobrien break; 191794546Sobrien case BYTE_MNEM_SUFFIX: 191894546Sobrien i.types[op] = Imm8 | Imm8S | Imm16 | Imm32S | Imm32; 191994546Sobrien break; 192094546Sobrien break; 192133965Sjdp } 192294546Sobrien break; 192333965Sjdp } 192477311Sobrien } 192594546Sobrien} 192694546Sobrien 192794546Sobrien/* Try to use the smallest displacement type too. */ 192894546Sobrienstatic void 192994546Sobrienoptimize_disp () 193094546Sobrien{ 193194546Sobrien int op; 193294546Sobrien 193394546Sobrien for (op = i.operands; --op >= 0;) 193494546Sobrien if ((i.types[op] & Disp) && i.op[op].disps->X_op == O_constant) 193577311Sobrien { 193694546Sobrien offsetT disp = i.op[op].disps->X_add_number; 193733965Sjdp 193894546Sobrien if (i.types[op] & Disp16) 193977311Sobrien { 194094546Sobrien /* We know this operand is at most 16 bits, so 194194546Sobrien convert to a signed 16 bit number before trying 194294546Sobrien to see whether it will fit in an even smaller 194394546Sobrien size. */ 194494546Sobrien 194594546Sobrien disp = (((disp & 0xffff) ^ 0x8000) - 0x8000); 194677311Sobrien } 194794546Sobrien else if (i.types[op] & Disp32) 194877311Sobrien { 194994546Sobrien /* We know this operand is at most 32 bits, so convert to a 195094546Sobrien signed 32 bit number before trying to see whether it will 195194546Sobrien fit in an even smaller size. */ 195294546Sobrien disp &= (((offsetT) 2 << 31) - 1); 195394546Sobrien disp = (disp ^ ((offsetT) 1 << 31)) - ((addressT) 1 << 31); 195477311Sobrien } 195594546Sobrien if (flag_code == CODE_64BIT) 195694546Sobrien { 195794546Sobrien if (fits_in_signed_long (disp)) 195894546Sobrien i.types[op] |= Disp32S; 195994546Sobrien if (fits_in_unsigned_long (disp)) 196094546Sobrien i.types[op] |= Disp32; 196194546Sobrien } 196294546Sobrien if ((i.types[op] & (Disp32 | Disp32S | Disp16)) 196394546Sobrien && fits_in_signed_byte (disp)) 196494546Sobrien i.types[op] |= Disp8; 196560519Sobrien } 196694546Sobrien} 196760519Sobrien 196894546Sobrienstatic int 196994546Sobrienmatch_template () 197094546Sobrien{ 197194546Sobrien /* Points to template once we've found it. */ 197294546Sobrien const template *t; 197394546Sobrien unsigned int overlap0, overlap1, overlap2; 197494546Sobrien unsigned int found_reverse_match; 197594546Sobrien int suffix_check; 197660519Sobrien 197794546Sobrien#define MATCH(overlap, given, template) \ 197894546Sobrien ((overlap & ~JumpAbsolute) \ 197994546Sobrien && (((given) & (BaseIndex | JumpAbsolute)) \ 198094546Sobrien == ((overlap) & (BaseIndex | JumpAbsolute)))) 198160519Sobrien 198294546Sobrien /* If given types r0 and r1 are registers they must be of the same type 198394546Sobrien unless the expected operand type register overlap is null. 198494546Sobrien Note that Acc in a template matches every size of reg. */ 198594546Sobrien#define CONSISTENT_REGISTER_MATCH(m0, g0, t0, m1, g1, t1) \ 198694546Sobrien (((g0) & Reg) == 0 || ((g1) & Reg) == 0 \ 198794546Sobrien || ((g0) & Reg) == ((g1) & Reg) \ 198894546Sobrien || ((((m0) & Acc) ? Reg : (t0)) & (((m1) & Acc) ? Reg : (t1)) & Reg) == 0 ) 198938891Sjdp 199094546Sobrien overlap0 = 0; 199194546Sobrien overlap1 = 0; 199294546Sobrien overlap2 = 0; 199394546Sobrien found_reverse_match = 0; 199494546Sobrien suffix_check = (i.suffix == BYTE_MNEM_SUFFIX 199594546Sobrien ? No_bSuf 199694546Sobrien : (i.suffix == WORD_MNEM_SUFFIX 199794546Sobrien ? No_wSuf 199894546Sobrien : (i.suffix == SHORT_MNEM_SUFFIX 199994546Sobrien ? No_sSuf 200094546Sobrien : (i.suffix == LONG_MNEM_SUFFIX 200194546Sobrien ? No_lSuf 200294546Sobrien : (i.suffix == QWORD_MNEM_SUFFIX 200394546Sobrien ? No_qSuf 200494546Sobrien : (i.suffix == LONG_DOUBLE_MNEM_SUFFIX 200594546Sobrien ? No_xSuf : 0)))))); 200660519Sobrien 200794546Sobrien for (t = current_templates->start; 200894546Sobrien t < current_templates->end; 200994546Sobrien t++) 201094546Sobrien { 201194546Sobrien /* Must have right number of operands. */ 201294546Sobrien if (i.operands != t->operands) 201394546Sobrien continue; 201460519Sobrien 201594546Sobrien /* Check the suffix, except for some instructions in intel mode. */ 201694546Sobrien if ((t->opcode_modifier & suffix_check) 201794546Sobrien && !(intel_syntax 201894546Sobrien && (t->opcode_modifier & IgnoreSize)) 201994546Sobrien && !(intel_syntax 202094546Sobrien && t->base_opcode == 0xd9 202194546Sobrien && (t->extension_opcode == 5 /* 0xd9,5 "fldcw" */ 202294546Sobrien || t->extension_opcode == 7))) /* 0xd9,7 "f{n}stcw" */ 202394546Sobrien continue; 202494546Sobrien 202594546Sobrien /* Do not verify operands when there are none. */ 202694546Sobrien else if (!t->operands) 202794546Sobrien { 202894546Sobrien if (t->cpu_flags & ~cpu_arch_flags) 202994546Sobrien continue; 203094546Sobrien /* We've found a match; break out of loop. */ 203194546Sobrien break; 203294546Sobrien } 203394546Sobrien 203494546Sobrien overlap0 = i.types[0] & t->operand_types[0]; 203594546Sobrien switch (t->operands) 203694546Sobrien { 203794546Sobrien case 1: 203894546Sobrien if (!MATCH (overlap0, i.types[0], t->operand_types[0])) 203994546Sobrien continue; 204094546Sobrien break; 204194546Sobrien case 2: 204294546Sobrien case 3: 204394546Sobrien overlap1 = i.types[1] & t->operand_types[1]; 204494546Sobrien if (!MATCH (overlap0, i.types[0], t->operand_types[0]) 204594546Sobrien || !MATCH (overlap1, i.types[1], t->operand_types[1]) 204694546Sobrien || !CONSISTENT_REGISTER_MATCH (overlap0, i.types[0], 204794546Sobrien t->operand_types[0], 204894546Sobrien overlap1, i.types[1], 204994546Sobrien t->operand_types[1])) 205094546Sobrien { 205194546Sobrien /* Check if other direction is valid ... */ 205294546Sobrien if ((t->opcode_modifier & (D | FloatD)) == 0) 205394546Sobrien continue; 205494546Sobrien 205594546Sobrien /* Try reversing direction of operands. */ 205694546Sobrien overlap0 = i.types[0] & t->operand_types[1]; 205794546Sobrien overlap1 = i.types[1] & t->operand_types[0]; 205894546Sobrien if (!MATCH (overlap0, i.types[0], t->operand_types[1]) 205994546Sobrien || !MATCH (overlap1, i.types[1], t->operand_types[0]) 206094546Sobrien || !CONSISTENT_REGISTER_MATCH (overlap0, i.types[0], 206194546Sobrien t->operand_types[1], 206294546Sobrien overlap1, i.types[1], 206394546Sobrien t->operand_types[0])) 206494546Sobrien { 206594546Sobrien /* Does not match either direction. */ 206694546Sobrien continue; 206794546Sobrien } 206894546Sobrien /* found_reverse_match holds which of D or FloatDR 206994546Sobrien we've found. */ 207094546Sobrien found_reverse_match = t->opcode_modifier & (D | FloatDR); 207194546Sobrien } 207294546Sobrien /* Found a forward 2 operand match here. */ 207394546Sobrien else if (t->operands == 3) 207494546Sobrien { 207594546Sobrien /* Here we make use of the fact that there are no 207694546Sobrien reverse match 3 operand instructions, and all 3 207794546Sobrien operand instructions only need to be checked for 207894546Sobrien register consistency between operands 2 and 3. */ 207994546Sobrien overlap2 = i.types[2] & t->operand_types[2]; 208094546Sobrien if (!MATCH (overlap2, i.types[2], t->operand_types[2]) 208194546Sobrien || !CONSISTENT_REGISTER_MATCH (overlap1, i.types[1], 208294546Sobrien t->operand_types[1], 208394546Sobrien overlap2, i.types[2], 208494546Sobrien t->operand_types[2])) 208594546Sobrien 208694546Sobrien continue; 208794546Sobrien } 208894546Sobrien /* Found either forward/reverse 2 or 3 operand match here: 208994546Sobrien slip through to break. */ 209094546Sobrien } 209194546Sobrien if (t->cpu_flags & ~cpu_arch_flags) 209294546Sobrien { 209394546Sobrien found_reverse_match = 0; 209494546Sobrien continue; 209594546Sobrien } 209694546Sobrien /* We've found a match; break out of loop. */ 209794546Sobrien break; 209894546Sobrien } 209994546Sobrien 210094546Sobrien if (t == current_templates->end) 210194546Sobrien { 210294546Sobrien /* We found no match. */ 210394546Sobrien as_bad (_("suffix or operands invalid for `%s'"), 210494546Sobrien current_templates->start->name); 210594546Sobrien return 0; 210694546Sobrien } 210794546Sobrien 210894546Sobrien if (!quiet_warnings) 210994546Sobrien { 211094546Sobrien if (!intel_syntax 211194546Sobrien && ((i.types[0] & JumpAbsolute) 211294546Sobrien != (t->operand_types[0] & JumpAbsolute))) 211394546Sobrien { 211494546Sobrien as_warn (_("indirect %s without `*'"), t->name); 211594546Sobrien } 211694546Sobrien 211794546Sobrien if ((t->opcode_modifier & (IsPrefix | IgnoreSize)) 211894546Sobrien == (IsPrefix | IgnoreSize)) 211994546Sobrien { 212094546Sobrien /* Warn them that a data or address size prefix doesn't 212194546Sobrien affect assembly of the next line of code. */ 212294546Sobrien as_warn (_("stand-alone `%s' prefix"), t->name); 212394546Sobrien } 212494546Sobrien } 212594546Sobrien 212694546Sobrien /* Copy the template we found. */ 212794546Sobrien i.tm = *t; 212894546Sobrien if (found_reverse_match) 212994546Sobrien { 213094546Sobrien /* If we found a reverse match we must alter the opcode 213194546Sobrien direction bit. found_reverse_match holds bits to change 213294546Sobrien (different for int & float insns). */ 213394546Sobrien 213494546Sobrien i.tm.base_opcode ^= found_reverse_match; 213594546Sobrien 213694546Sobrien i.tm.operand_types[0] = t->operand_types[1]; 213794546Sobrien i.tm.operand_types[1] = t->operand_types[0]; 213894546Sobrien } 213994546Sobrien 214094546Sobrien return 1; 214194546Sobrien} 214294546Sobrien 214394546Sobrienstatic int 214494546Sobriencheck_string () 214594546Sobrien{ 214694546Sobrien int mem_op = (i.types[0] & AnyMem) ? 0 : 1; 214794546Sobrien if ((i.tm.operand_types[mem_op] & EsSeg) != 0) 214894546Sobrien { 214994546Sobrien if (i.seg[0] != NULL && i.seg[0] != &es) 215094546Sobrien { 215194546Sobrien as_bad (_("`%s' operand %d must use `%%es' segment"), 215294546Sobrien i.tm.name, 215394546Sobrien mem_op + 1); 215494546Sobrien return 0; 215594546Sobrien } 215694546Sobrien /* There's only ever one segment override allowed per instruction. 215794546Sobrien This instruction possibly has a legal segment override on the 215894546Sobrien second operand, so copy the segment to where non-string 215994546Sobrien instructions store it, allowing common code. */ 216094546Sobrien i.seg[0] = i.seg[1]; 216194546Sobrien } 216294546Sobrien else if ((i.tm.operand_types[mem_op + 1] & EsSeg) != 0) 216394546Sobrien { 216494546Sobrien if (i.seg[1] != NULL && i.seg[1] != &es) 216594546Sobrien { 216694546Sobrien as_bad (_("`%s' operand %d must use `%%es' segment"), 216794546Sobrien i.tm.name, 216894546Sobrien mem_op + 2); 216994546Sobrien return 0; 217094546Sobrien } 217194546Sobrien } 217294546Sobrien return 1; 217394546Sobrien} 217494546Sobrien 217594546Sobrienstatic int 217694546Sobrienprocess_suffix () 217794546Sobrien{ 217894546Sobrien /* If matched instruction specifies an explicit instruction mnemonic 217994546Sobrien suffix, use it. */ 218094546Sobrien if (i.tm.opcode_modifier & (Size16 | Size32 | Size64)) 218194546Sobrien { 218294546Sobrien if (i.tm.opcode_modifier & Size16) 218394546Sobrien i.suffix = WORD_MNEM_SUFFIX; 218494546Sobrien else if (i.tm.opcode_modifier & Size64) 218594546Sobrien i.suffix = QWORD_MNEM_SUFFIX; 218694546Sobrien else 218794546Sobrien i.suffix = LONG_MNEM_SUFFIX; 218894546Sobrien } 218994546Sobrien else if (i.reg_operands) 219094546Sobrien { 219194546Sobrien /* If there's no instruction mnemonic suffix we try to invent one 219294546Sobrien based on register operands. */ 219394546Sobrien if (!i.suffix) 219494546Sobrien { 219594546Sobrien /* We take i.suffix from the last register operand specified, 219694546Sobrien Destination register type is more significant than source 219794546Sobrien register type. */ 219894546Sobrien int op; 219994546Sobrien for (op = i.operands; --op >= 0;) 220094546Sobrien if ((i.types[op] & Reg) 220194546Sobrien && !(i.tm.operand_types[op] & InOutPortReg)) 220260519Sobrien { 220394546Sobrien i.suffix = ((i.types[op] & Reg8) ? BYTE_MNEM_SUFFIX : 220494546Sobrien (i.types[op] & Reg16) ? WORD_MNEM_SUFFIX : 220594546Sobrien (i.types[op] & Reg64) ? QWORD_MNEM_SUFFIX : 220694546Sobrien LONG_MNEM_SUFFIX); 220794546Sobrien break; 220860519Sobrien } 220994546Sobrien } 221094546Sobrien else if (i.suffix == BYTE_MNEM_SUFFIX) 221194546Sobrien { 221294546Sobrien if (!check_byte_reg ()) 221394546Sobrien return 0; 221494546Sobrien } 221594546Sobrien else if (i.suffix == LONG_MNEM_SUFFIX) 221694546Sobrien { 221794546Sobrien if (!check_long_reg ()) 221894546Sobrien return 0; 221994546Sobrien } 222094546Sobrien else if (i.suffix == QWORD_MNEM_SUFFIX) 222194546Sobrien { 222294546Sobrien if (!check_qword_reg ()) 222394546Sobrien return 0; 222494546Sobrien } 222594546Sobrien else if (i.suffix == WORD_MNEM_SUFFIX) 222694546Sobrien { 222794546Sobrien if (!check_word_reg ()) 222894546Sobrien return 0; 222994546Sobrien } 223094546Sobrien else if (intel_syntax && (i.tm.opcode_modifier & IgnoreSize)) 223194546Sobrien /* Do nothing if the instruction is going to ignore the prefix. */ 223294546Sobrien ; 223394546Sobrien else 223494546Sobrien abort (); 223594546Sobrien } 223694546Sobrien else if ((i.tm.opcode_modifier & DefaultSize) && !i.suffix) 223794546Sobrien { 223894546Sobrien i.suffix = stackop_size; 223994546Sobrien } 224033965Sjdp 224194546Sobrien /* Change the opcode based on the operand size given by i.suffix; 224294546Sobrien We need not change things for byte insns. */ 224394546Sobrien 224494546Sobrien if (!i.suffix && (i.tm.opcode_modifier & W)) 224594546Sobrien { 224694546Sobrien as_bad (_("no instruction mnemonic suffix given and no register operands; can't size instruction")); 224794546Sobrien return 0; 224894546Sobrien } 224994546Sobrien 225094546Sobrien if (i.suffix && i.suffix != BYTE_MNEM_SUFFIX) 225194546Sobrien { 225294546Sobrien /* It's not a byte, select word/dword operation. */ 225394546Sobrien if (i.tm.opcode_modifier & W) 225494546Sobrien { 225594546Sobrien if (i.tm.opcode_modifier & ShortForm) 225694546Sobrien i.tm.base_opcode |= 8; 225794546Sobrien else 225894546Sobrien i.tm.base_opcode |= 1; 225994546Sobrien } 226099468Sobrien 226194546Sobrien /* Now select between word & dword operations via the operand 226294546Sobrien size prefix, except for instructions that will ignore this 226394546Sobrien prefix anyway. */ 226494546Sobrien if (i.suffix != QWORD_MNEM_SUFFIX 2265104848Sobrien && !(i.tm.opcode_modifier & IgnoreSize) 2266104848Sobrien && ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT) 2267104848Sobrien || (flag_code == CODE_64BIT 2268104848Sobrien && (i.tm.opcode_modifier & JumpByte)))) 226994546Sobrien { 227094546Sobrien unsigned int prefix = DATA_PREFIX_OPCODE; 227194546Sobrien if (i.tm.opcode_modifier & JumpByte) /* jcxz, loop */ 227294546Sobrien prefix = ADDR_PREFIX_OPCODE; 227333965Sjdp 227494546Sobrien if (!add_prefix (prefix)) 227594546Sobrien return 0; 227694546Sobrien } 227794546Sobrien 227894546Sobrien /* Set mode64 for an operand. */ 227994546Sobrien if (i.suffix == QWORD_MNEM_SUFFIX 2280104848Sobrien && flag_code == CODE_64BIT 228194546Sobrien && (i.tm.opcode_modifier & NoRex64) == 0) 2282104848Sobrien i.rex |= REX_MODE64; 228394546Sobrien 228494546Sobrien /* Size floating point instruction. */ 228594546Sobrien if (i.suffix == LONG_MNEM_SUFFIX) 228694546Sobrien { 228794546Sobrien if (i.tm.opcode_modifier & FloatMF) 228894546Sobrien i.tm.base_opcode ^= 4; 228994546Sobrien } 229094546Sobrien } 229194546Sobrien 229294546Sobrien return 1; 229394546Sobrien} 229494546Sobrien 229594546Sobrienstatic int 229694546Sobriencheck_byte_reg () 229794546Sobrien{ 229894546Sobrien int op; 229994546Sobrien for (op = i.operands; --op >= 0;) 230094546Sobrien { 230194546Sobrien /* If this is an eight bit register, it's OK. If it's the 16 or 230294546Sobrien 32 bit version of an eight bit register, we will just use the 230394546Sobrien low portion, and that's OK too. */ 230494546Sobrien if (i.types[op] & Reg8) 230594546Sobrien continue; 230694546Sobrien 230794546Sobrien /* movzx and movsx should not generate this warning. */ 230894546Sobrien if (intel_syntax 230994546Sobrien && (i.tm.base_opcode == 0xfb7 231094546Sobrien || i.tm.base_opcode == 0xfb6 231194546Sobrien || i.tm.base_opcode == 0x63 231294546Sobrien || i.tm.base_opcode == 0xfbe 231394546Sobrien || i.tm.base_opcode == 0xfbf)) 231494546Sobrien continue; 231594546Sobrien 231694546Sobrien if ((i.types[op] & WordReg) && i.op[op].regs->reg_num < 4 231760519Sobrien#if 0 231894546Sobrien /* Check that the template allows eight bit regs. This 231994546Sobrien kills insns such as `orb $1,%edx', which maybe should be 232094546Sobrien allowed. */ 232194546Sobrien && (i.tm.operand_types[op] & (Reg8 | InOutPortReg)) 232260519Sobrien#endif 232394546Sobrien ) 232494546Sobrien { 232594546Sobrien /* Prohibit these changes in the 64bit mode, since the 232694546Sobrien lowering is more complicated. */ 232794546Sobrien if (flag_code == CODE_64BIT 232894546Sobrien && (i.tm.operand_types[op] & InOutPortReg) == 0) 232994546Sobrien { 233099468Sobrien as_bad (_("Incorrect register `%%%s' used with `%c' suffix"), 233194546Sobrien i.op[op].regs->reg_name, 233294546Sobrien i.suffix); 233394546Sobrien return 0; 233494546Sobrien } 233560519Sobrien#if REGISTER_WARNINGS 233694546Sobrien if (!quiet_warnings 233794546Sobrien && (i.tm.operand_types[op] & InOutPortReg) == 0) 233894546Sobrien as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"), 233994546Sobrien (i.op[op].regs + (i.types[op] & Reg16 234094546Sobrien ? REGNAM_AL - REGNAM_AX 234194546Sobrien : REGNAM_AL - REGNAM_EAX))->reg_name, 234294546Sobrien i.op[op].regs->reg_name, 234394546Sobrien i.suffix); 234460519Sobrien#endif 234594546Sobrien continue; 234694546Sobrien } 234794546Sobrien /* Any other register is bad. */ 234894546Sobrien if (i.types[op] & (Reg | RegMMX | RegXMM 234994546Sobrien | SReg2 | SReg3 235094546Sobrien | Control | Debug | Test 235194546Sobrien | FloatReg | FloatAcc)) 235294546Sobrien { 235394546Sobrien as_bad (_("`%%%s' not allowed with `%s%c'"), 235494546Sobrien i.op[op].regs->reg_name, 235594546Sobrien i.tm.name, 235694546Sobrien i.suffix); 235794546Sobrien return 0; 235894546Sobrien } 235994546Sobrien } 236094546Sobrien return 1; 236194546Sobrien} 236277311Sobrien 236394546Sobrienstatic int 236494546Sobriencheck_long_reg () 236594546Sobrien{ 236694546Sobrien int op; 236777311Sobrien 236894546Sobrien for (op = i.operands; --op >= 0;) 236994546Sobrien /* Reject eight bit registers, except where the template requires 237094546Sobrien them. (eg. movzb) */ 237194546Sobrien if ((i.types[op] & Reg8) != 0 237294546Sobrien && (i.tm.operand_types[op] & (Reg16 | Reg32 | Acc)) != 0) 237360519Sobrien { 237494546Sobrien as_bad (_("`%%%s' not allowed with `%s%c'"), 237594546Sobrien i.op[op].regs->reg_name, 237694546Sobrien i.tm.name, 237794546Sobrien i.suffix); 237894546Sobrien return 0; 237960519Sobrien } 238094546Sobrien /* Warn if the e prefix on a general reg is missing. */ 238194546Sobrien else if ((!quiet_warnings || flag_code == CODE_64BIT) 238294546Sobrien && (i.types[op] & Reg16) != 0 238394546Sobrien && (i.tm.operand_types[op] & (Reg32 | Acc)) != 0) 238433965Sjdp { 238594546Sobrien /* Prohibit these changes in the 64bit mode, since the 238694546Sobrien lowering is more complicated. */ 238794546Sobrien if (flag_code == CODE_64BIT) 238833965Sjdp { 238999468Sobrien as_bad (_("Incorrect register `%%%s' used with `%c' suffix"), 239094546Sobrien i.op[op].regs->reg_name, 239194546Sobrien i.suffix); 239294546Sobrien return 0; 239360519Sobrien } 239494546Sobrien#if REGISTER_WARNINGS 239594546Sobrien else 239694546Sobrien as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"), 239794546Sobrien (i.op[op].regs + REGNAM_EAX - REGNAM_AX)->reg_name, 239894546Sobrien i.op[op].regs->reg_name, 239994546Sobrien i.suffix); 240094546Sobrien#endif 240133965Sjdp } 240294546Sobrien /* Warn if the r prefix on a general reg is missing. */ 240394546Sobrien else if ((i.types[op] & Reg64) != 0 240494546Sobrien && (i.tm.operand_types[op] & (Reg32 | Acc)) != 0) 240533965Sjdp { 240699468Sobrien as_bad (_("Incorrect register `%%%s' used with `%c' suffix"), 240794546Sobrien i.op[op].regs->reg_name, 240894546Sobrien i.suffix); 240994546Sobrien return 0; 241033965Sjdp } 241194546Sobrien return 1; 241294546Sobrien} 241333965Sjdp 241494546Sobrienstatic int 241594546Sobriencheck_qword_reg () 241694546Sobrien{ 241794546Sobrien int op; 241860519Sobrien 241994546Sobrien for (op = i.operands; --op >= 0; ) 242094546Sobrien /* Reject eight bit registers, except where the template requires 242194546Sobrien them. (eg. movzb) */ 242294546Sobrien if ((i.types[op] & Reg8) != 0 242394546Sobrien && (i.tm.operand_types[op] & (Reg16 | Reg32 | Acc)) != 0) 242433965Sjdp { 242594546Sobrien as_bad (_("`%%%s' not allowed with `%s%c'"), 242694546Sobrien i.op[op].regs->reg_name, 242794546Sobrien i.tm.name, 242894546Sobrien i.suffix); 242994546Sobrien return 0; 243033965Sjdp } 243194546Sobrien /* Warn if the e prefix on a general reg is missing. */ 243294546Sobrien else if (((i.types[op] & Reg16) != 0 243394546Sobrien || (i.types[op] & Reg32) != 0) 243494546Sobrien && (i.tm.operand_types[op] & (Reg32 | Acc)) != 0) 243594546Sobrien { 243694546Sobrien /* Prohibit these changes in the 64bit mode, since the 243794546Sobrien lowering is more complicated. */ 243899468Sobrien as_bad (_("Incorrect register `%%%s' used with `%c' suffix"), 243994546Sobrien i.op[op].regs->reg_name, 244094546Sobrien i.suffix); 244194546Sobrien return 0; 244294546Sobrien } 244394546Sobrien return 1; 244494546Sobrien} 244533965Sjdp 244694546Sobrienstatic int 244794546Sobriencheck_word_reg () 244894546Sobrien{ 244994546Sobrien int op; 245094546Sobrien for (op = i.operands; --op >= 0;) 245194546Sobrien /* Reject eight bit registers, except where the template requires 245294546Sobrien them. (eg. movzb) */ 245394546Sobrien if ((i.types[op] & Reg8) != 0 245494546Sobrien && (i.tm.operand_types[op] & (Reg16 | Reg32 | Acc)) != 0) 245533965Sjdp { 245694546Sobrien as_bad (_("`%%%s' not allowed with `%s%c'"), 245794546Sobrien i.op[op].regs->reg_name, 245894546Sobrien i.tm.name, 245994546Sobrien i.suffix); 246094546Sobrien return 0; 246194546Sobrien } 246294546Sobrien /* Warn if the e prefix on a general reg is present. */ 246394546Sobrien else if ((!quiet_warnings || flag_code == CODE_64BIT) 246494546Sobrien && (i.types[op] & Reg32) != 0 246594546Sobrien && (i.tm.operand_types[op] & (Reg16 | Acc)) != 0) 246694546Sobrien { 246794546Sobrien /* Prohibit these changes in the 64bit mode, since the 246894546Sobrien lowering is more complicated. */ 246994546Sobrien if (flag_code == CODE_64BIT) 247033965Sjdp { 247199468Sobrien as_bad (_("Incorrect register `%%%s' used with `%c' suffix"), 247294546Sobrien i.op[op].regs->reg_name, 247394546Sobrien i.suffix); 247494546Sobrien return 0; 247533965Sjdp } 247694546Sobrien else 247794546Sobrien#if REGISTER_WARNINGS 247894546Sobrien as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"), 247994546Sobrien (i.op[op].regs + REGNAM_AX - REGNAM_EAX)->reg_name, 248094546Sobrien i.op[op].regs->reg_name, 248194546Sobrien i.suffix); 248294546Sobrien#endif 248394546Sobrien } 248494546Sobrien return 1; 248594546Sobrien} 248660519Sobrien 248794546Sobrienstatic int 248894546Sobrienfinalize_imm () 248994546Sobrien{ 249094546Sobrien unsigned int overlap0, overlap1, overlap2; 249177311Sobrien 249294546Sobrien overlap0 = i.types[0] & i.tm.operand_types[0]; 249394546Sobrien if ((overlap0 & (Imm8 | Imm8S | Imm16 | Imm32 | Imm32S)) 249494546Sobrien && overlap0 != Imm8 && overlap0 != Imm8S 249594546Sobrien && overlap0 != Imm16 && overlap0 != Imm32S 249694546Sobrien && overlap0 != Imm32 && overlap0 != Imm64) 249794546Sobrien { 249894546Sobrien if (i.suffix) 249994546Sobrien { 250094546Sobrien overlap0 &= (i.suffix == BYTE_MNEM_SUFFIX 250194546Sobrien ? Imm8 | Imm8S 250294546Sobrien : (i.suffix == WORD_MNEM_SUFFIX 250394546Sobrien ? Imm16 250494546Sobrien : (i.suffix == QWORD_MNEM_SUFFIX 250594546Sobrien ? Imm64 | Imm32S 250694546Sobrien : Imm32))); 250794546Sobrien } 250894546Sobrien else if (overlap0 == (Imm16 | Imm32S | Imm32) 250994546Sobrien || overlap0 == (Imm16 | Imm32) 251094546Sobrien || overlap0 == (Imm16 | Imm32S)) 251194546Sobrien { 251294546Sobrien overlap0 = ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0) 251394546Sobrien ? Imm16 : Imm32S); 251494546Sobrien } 251594546Sobrien if (overlap0 != Imm8 && overlap0 != Imm8S 251694546Sobrien && overlap0 != Imm16 && overlap0 != Imm32S 251794546Sobrien && overlap0 != Imm32 && overlap0 != Imm64) 251894546Sobrien { 251994546Sobrien as_bad (_("no instruction mnemonic suffix given; can't determine immediate size")); 252094546Sobrien return 0; 252194546Sobrien } 252294546Sobrien } 252394546Sobrien i.types[0] = overlap0; 252491054Sobrien 252594546Sobrien overlap1 = i.types[1] & i.tm.operand_types[1]; 252694546Sobrien if ((overlap1 & (Imm8 | Imm8S | Imm16 | Imm32S | Imm32)) 252794546Sobrien && overlap1 != Imm8 && overlap1 != Imm8S 252894546Sobrien && overlap1 != Imm16 && overlap1 != Imm32S 252994546Sobrien && overlap1 != Imm32 && overlap1 != Imm64) 253094546Sobrien { 253194546Sobrien if (i.suffix) 253294546Sobrien { 253394546Sobrien overlap1 &= (i.suffix == BYTE_MNEM_SUFFIX 253494546Sobrien ? Imm8 | Imm8S 253594546Sobrien : (i.suffix == WORD_MNEM_SUFFIX 253694546Sobrien ? Imm16 253794546Sobrien : (i.suffix == QWORD_MNEM_SUFFIX 253894546Sobrien ? Imm64 | Imm32S 253994546Sobrien : Imm32))); 254094546Sobrien } 254194546Sobrien else if (overlap1 == (Imm16 | Imm32 | Imm32S) 254294546Sobrien || overlap1 == (Imm16 | Imm32) 254394546Sobrien || overlap1 == (Imm16 | Imm32S)) 254494546Sobrien { 254594546Sobrien overlap1 = ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0) 254694546Sobrien ? Imm16 : Imm32S); 254794546Sobrien } 254894546Sobrien if (overlap1 != Imm8 && overlap1 != Imm8S 254994546Sobrien && overlap1 != Imm16 && overlap1 != Imm32S 255094546Sobrien && overlap1 != Imm32 && overlap1 != Imm64) 255194546Sobrien { 255294546Sobrien as_bad (_("no instruction mnemonic suffix given; can't determine immediate size %x %c"),overlap1, i.suffix); 255394546Sobrien return 0; 255494546Sobrien } 255594546Sobrien } 255694546Sobrien i.types[1] = overlap1; 255777311Sobrien 255894546Sobrien overlap2 = i.types[2] & i.tm.operand_types[2]; 255994546Sobrien assert ((overlap2 & Imm) == 0); 256094546Sobrien i.types[2] = overlap2; 256133965Sjdp 256294546Sobrien return 1; 256394546Sobrien} 256460519Sobrien 256594546Sobrienstatic int 256694546Sobrienprocess_operands () 256794546Sobrien{ 256894546Sobrien /* Default segment register this instruction will use for memory 256994546Sobrien accesses. 0 means unknown. This is only for optimizing out 257094546Sobrien unnecessary segment overrides. */ 257194546Sobrien const seg_entry *default_seg = 0; 257260519Sobrien 257394546Sobrien /* The imul $imm, %reg instruction is converted into 257494546Sobrien imul $imm, %reg, %reg, and the clr %reg instruction 257594546Sobrien is converted into xor %reg, %reg. */ 257694546Sobrien if (i.tm.opcode_modifier & regKludge) 257794546Sobrien { 257894546Sobrien unsigned int first_reg_op = (i.types[0] & Reg) ? 0 : 1; 257994546Sobrien /* Pretend we saw the extra register operand. */ 258094546Sobrien assert (i.op[first_reg_op + 1].regs == 0); 258194546Sobrien i.op[first_reg_op + 1].regs = i.op[first_reg_op].regs; 258294546Sobrien i.types[first_reg_op + 1] = i.types[first_reg_op]; 258394546Sobrien i.reg_operands = 2; 258494546Sobrien } 258560519Sobrien 258694546Sobrien if (i.tm.opcode_modifier & ShortForm) 258794546Sobrien { 258894546Sobrien /* The register or float register operand is in operand 0 or 1. */ 258994546Sobrien unsigned int op = (i.types[0] & (Reg | FloatReg)) ? 0 : 1; 259094546Sobrien /* Register goes in low 3 bits of opcode. */ 259194546Sobrien i.tm.base_opcode |= i.op[op].regs->reg_num; 259294546Sobrien if ((i.op[op].regs->reg_flags & RegRex) != 0) 259394546Sobrien i.rex |= REX_EXTZ; 259494546Sobrien if (!quiet_warnings && (i.tm.opcode_modifier & Ugh) != 0) 259594546Sobrien { 259694546Sobrien /* Warn about some common errors, but press on regardless. 259794546Sobrien The first case can be generated by gcc (<= 2.8.1). */ 259894546Sobrien if (i.operands == 2) 259994546Sobrien { 260094546Sobrien /* Reversed arguments on faddp, fsubp, etc. */ 260194546Sobrien as_warn (_("translating to `%s %%%s,%%%s'"), i.tm.name, 260294546Sobrien i.op[1].regs->reg_name, 260394546Sobrien i.op[0].regs->reg_name); 260494546Sobrien } 260594546Sobrien else 260694546Sobrien { 260794546Sobrien /* Extraneous `l' suffix on fp insn. */ 260894546Sobrien as_warn (_("translating to `%s %%%s'"), i.tm.name, 260994546Sobrien i.op[0].regs->reg_name); 261094546Sobrien } 261194546Sobrien } 261294546Sobrien } 261394546Sobrien else if (i.tm.opcode_modifier & Modrm) 261494546Sobrien { 261594546Sobrien /* The opcode is completed (modulo i.tm.extension_opcode which 2616104848Sobrien must be put into the modrm byte). Now, we make the modrm and 2617104848Sobrien index base bytes based on all the info we've collected. */ 261860519Sobrien 261994546Sobrien default_seg = build_modrm_byte (); 262094546Sobrien } 262194546Sobrien else if (i.tm.opcode_modifier & (Seg2ShortForm | Seg3ShortForm)) 262294546Sobrien { 262394546Sobrien if (i.tm.base_opcode == POP_SEG_SHORT 262494546Sobrien && i.op[0].regs->reg_num == 1) 262594546Sobrien { 262694546Sobrien as_bad (_("you can't `pop %%cs'")); 262794546Sobrien return 0; 262894546Sobrien } 262994546Sobrien i.tm.base_opcode |= (i.op[0].regs->reg_num << 3); 263094546Sobrien if ((i.op[0].regs->reg_flags & RegRex) != 0) 263194546Sobrien i.rex |= REX_EXTZ; 263294546Sobrien } 263394546Sobrien else if ((i.tm.base_opcode & ~(D | W)) == MOV_AX_DISP32) 263494546Sobrien { 263594546Sobrien default_seg = &ds; 263694546Sobrien } 263794546Sobrien else if ((i.tm.opcode_modifier & IsString) != 0) 263894546Sobrien { 263994546Sobrien /* For the string instructions that allow a segment override 264094546Sobrien on one of their operands, the default segment is ds. */ 264194546Sobrien default_seg = &ds; 264294546Sobrien } 264333965Sjdp 2644104848Sobrien if (i.tm.base_opcode == 0x8d /* lea */ && i.seg[0] && !quiet_warnings) 2645104848Sobrien as_warn (_("segment override on `lea' is ineffectual")); 2646104848Sobrien 2647104848Sobrien /* If a segment was explicitly specified, and the specified segment 2648104848Sobrien is not the default, use an opcode prefix to select it. If we 2649104848Sobrien never figured out what the default segment is, then default_seg 2650104848Sobrien will be zero at this point, and the specified segment prefix will 2651104848Sobrien always be used. */ 265294546Sobrien if ((i.seg[0]) && (i.seg[0] != default_seg)) 265394546Sobrien { 265494546Sobrien if (!add_prefix (i.seg[0]->seg_prefix)) 265594546Sobrien return 0; 265694546Sobrien } 265794546Sobrien return 1; 265894546Sobrien} 265933965Sjdp 266094546Sobrienstatic const seg_entry * 266194546Sobrienbuild_modrm_byte () 266294546Sobrien{ 266394546Sobrien const seg_entry *default_seg = 0; 266433965Sjdp 266594546Sobrien /* i.reg_operands MUST be the number of real register operands; 266694546Sobrien implicit registers do not count. */ 266794546Sobrien if (i.reg_operands == 2) 266894546Sobrien { 266994546Sobrien unsigned int source, dest; 267094546Sobrien source = ((i.types[0] 267194546Sobrien & (Reg | RegMMX | RegXMM 267294546Sobrien | SReg2 | SReg3 267394546Sobrien | Control | Debug | Test)) 267494546Sobrien ? 0 : 1); 267594546Sobrien dest = source + 1; 267660519Sobrien 267794546Sobrien i.rm.mode = 3; 267894546Sobrien /* One of the register operands will be encoded in the i.tm.reg 267994546Sobrien field, the other in the combined i.tm.mode and i.tm.regmem 268094546Sobrien fields. If no form of this instruction supports a memory 268194546Sobrien destination operand, then we assume the source operand may 268294546Sobrien sometimes be a memory operand and so we need to store the 268394546Sobrien destination in the i.rm.reg field. */ 268494546Sobrien if ((i.tm.operand_types[dest] & AnyMem) == 0) 268594546Sobrien { 268694546Sobrien i.rm.reg = i.op[dest].regs->reg_num; 268794546Sobrien i.rm.regmem = i.op[source].regs->reg_num; 268894546Sobrien if ((i.op[dest].regs->reg_flags & RegRex) != 0) 268994546Sobrien i.rex |= REX_EXTX; 269094546Sobrien if ((i.op[source].regs->reg_flags & RegRex) != 0) 269194546Sobrien i.rex |= REX_EXTZ; 269294546Sobrien } 269394546Sobrien else 269494546Sobrien { 269594546Sobrien i.rm.reg = i.op[source].regs->reg_num; 269694546Sobrien i.rm.regmem = i.op[dest].regs->reg_num; 269794546Sobrien if ((i.op[dest].regs->reg_flags & RegRex) != 0) 269894546Sobrien i.rex |= REX_EXTZ; 269994546Sobrien if ((i.op[source].regs->reg_flags & RegRex) != 0) 270094546Sobrien i.rex |= REX_EXTX; 270194546Sobrien } 270294546Sobrien } 270394546Sobrien else 270494546Sobrien { /* If it's not 2 reg operands... */ 270594546Sobrien if (i.mem_operands) 270694546Sobrien { 270794546Sobrien unsigned int fake_zero_displacement = 0; 270894546Sobrien unsigned int op = ((i.types[0] & AnyMem) 270994546Sobrien ? 0 271094546Sobrien : (i.types[1] & AnyMem) ? 1 : 2); 271133965Sjdp 271294546Sobrien default_seg = &ds; 271333965Sjdp 271494546Sobrien if (i.base_reg == 0) 271594546Sobrien { 271694546Sobrien i.rm.mode = 0; 271794546Sobrien if (!i.disp_operands) 271894546Sobrien fake_zero_displacement = 1; 271994546Sobrien if (i.index_reg == 0) 272094546Sobrien { 272194546Sobrien /* Operand is just <disp> */ 272294546Sobrien if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0) 272394546Sobrien && (flag_code != CODE_64BIT)) 272494546Sobrien { 272594546Sobrien i.rm.regmem = NO_BASE_REGISTER_16; 272694546Sobrien i.types[op] &= ~Disp; 272794546Sobrien i.types[op] |= Disp16; 272894546Sobrien } 272994546Sobrien else if (flag_code != CODE_64BIT 273094546Sobrien || (i.prefix[ADDR_PREFIX] != 0)) 273194546Sobrien { 273294546Sobrien i.rm.regmem = NO_BASE_REGISTER; 273394546Sobrien i.types[op] &= ~Disp; 273494546Sobrien i.types[op] |= Disp32; 273594546Sobrien } 273694546Sobrien else 273794546Sobrien { 273894546Sobrien /* 64bit mode overwrites the 32bit absolute 273994546Sobrien addressing by RIP relative addressing and 274094546Sobrien absolute addressing is encoded by one of the 274194546Sobrien redundant SIB forms. */ 274294546Sobrien i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; 274394546Sobrien i.sib.base = NO_BASE_REGISTER; 274494546Sobrien i.sib.index = NO_INDEX_REGISTER; 274594546Sobrien i.types[op] &= ~Disp; 274694546Sobrien i.types[op] |= Disp32S; 274794546Sobrien } 274894546Sobrien } 274994546Sobrien else /* !i.base_reg && i.index_reg */ 275094546Sobrien { 275194546Sobrien i.sib.index = i.index_reg->reg_num; 275294546Sobrien i.sib.base = NO_BASE_REGISTER; 275394546Sobrien i.sib.scale = i.log2_scale_factor; 275494546Sobrien i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; 275594546Sobrien i.types[op] &= ~Disp; 275694546Sobrien if (flag_code != CODE_64BIT) 275794546Sobrien i.types[op] |= Disp32; /* Must be 32 bit */ 275894546Sobrien else 275994546Sobrien i.types[op] |= Disp32S; 276094546Sobrien if ((i.index_reg->reg_flags & RegRex) != 0) 276194546Sobrien i.rex |= REX_EXTY; 276294546Sobrien } 276394546Sobrien } 276494546Sobrien /* RIP addressing for 64bit mode. */ 276594546Sobrien else if (i.base_reg->reg_type == BaseIndex) 276694546Sobrien { 276794546Sobrien i.rm.regmem = NO_BASE_REGISTER; 276894546Sobrien i.types[op] &= ~Disp; 276994546Sobrien i.types[op] |= Disp32S; 277094546Sobrien i.flags[op] = Operand_PCrel; 277194546Sobrien } 277294546Sobrien else if (i.base_reg->reg_type & Reg16) 277394546Sobrien { 277494546Sobrien switch (i.base_reg->reg_num) 277594546Sobrien { 277694546Sobrien case 3: /* (%bx) */ 277794546Sobrien if (i.index_reg == 0) 277894546Sobrien i.rm.regmem = 7; 277994546Sobrien else /* (%bx,%si) -> 0, or (%bx,%di) -> 1 */ 278094546Sobrien i.rm.regmem = i.index_reg->reg_num - 6; 278194546Sobrien break; 278294546Sobrien case 5: /* (%bp) */ 278394546Sobrien default_seg = &ss; 278494546Sobrien if (i.index_reg == 0) 278594546Sobrien { 278694546Sobrien i.rm.regmem = 6; 278794546Sobrien if ((i.types[op] & Disp) == 0) 278894546Sobrien { 278994546Sobrien /* fake (%bp) into 0(%bp) */ 279094546Sobrien i.types[op] |= Disp8; 279160519Sobrien fake_zero_displacement = 1; 279294546Sobrien } 279394546Sobrien } 279494546Sobrien else /* (%bp,%si) -> 2, or (%bp,%di) -> 3 */ 279594546Sobrien i.rm.regmem = i.index_reg->reg_num - 6 + 2; 279694546Sobrien break; 279794546Sobrien default: /* (%si) -> 4 or (%di) -> 5 */ 279894546Sobrien i.rm.regmem = i.base_reg->reg_num - 6 + 4; 279994546Sobrien } 280094546Sobrien i.rm.mode = mode_from_disp_size (i.types[op]); 280194546Sobrien } 280294546Sobrien else /* i.base_reg and 32/64 bit mode */ 280394546Sobrien { 280494546Sobrien if (flag_code == CODE_64BIT 280594546Sobrien && (i.types[op] & Disp)) 280694546Sobrien { 280794546Sobrien if (i.types[op] & Disp8) 280894546Sobrien i.types[op] = Disp8 | Disp32S; 280994546Sobrien else 281094546Sobrien i.types[op] = Disp32S; 281194546Sobrien } 281294546Sobrien i.rm.regmem = i.base_reg->reg_num; 281394546Sobrien if ((i.base_reg->reg_flags & RegRex) != 0) 281494546Sobrien i.rex |= REX_EXTZ; 281594546Sobrien i.sib.base = i.base_reg->reg_num; 281694546Sobrien /* x86-64 ignores REX prefix bit here to avoid decoder 281794546Sobrien complications. */ 281894546Sobrien if ((i.base_reg->reg_num & 7) == EBP_REG_NUM) 281994546Sobrien { 282094546Sobrien default_seg = &ss; 282194546Sobrien if (i.disp_operands == 0) 282294546Sobrien { 282394546Sobrien fake_zero_displacement = 1; 282494546Sobrien i.types[op] |= Disp8; 282594546Sobrien } 282694546Sobrien } 282794546Sobrien else if (i.base_reg->reg_num == ESP_REG_NUM) 282894546Sobrien { 282994546Sobrien default_seg = &ss; 283094546Sobrien } 283194546Sobrien i.sib.scale = i.log2_scale_factor; 283294546Sobrien if (i.index_reg == 0) 283394546Sobrien { 283494546Sobrien /* <disp>(%esp) becomes two byte modrm with no index 283594546Sobrien register. We've already stored the code for esp 283694546Sobrien in i.rm.regmem ie. ESCAPE_TO_TWO_BYTE_ADDRESSING. 283794546Sobrien Any base register besides %esp will not use the 283894546Sobrien extra modrm byte. */ 283994546Sobrien i.sib.index = NO_INDEX_REGISTER; 284094546Sobrien#if !SCALE1_WHEN_NO_INDEX 284194546Sobrien /* Another case where we force the second modrm byte. */ 284294546Sobrien if (i.log2_scale_factor) 284394546Sobrien i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; 284460519Sobrien#endif 284594546Sobrien } 284694546Sobrien else 284794546Sobrien { 284894546Sobrien i.sib.index = i.index_reg->reg_num; 284994546Sobrien i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; 285094546Sobrien if ((i.index_reg->reg_flags & RegRex) != 0) 285194546Sobrien i.rex |= REX_EXTY; 285294546Sobrien } 285394546Sobrien i.rm.mode = mode_from_disp_size (i.types[op]); 285494546Sobrien } 285560519Sobrien 285694546Sobrien if (fake_zero_displacement) 285794546Sobrien { 285894546Sobrien /* Fakes a zero displacement assuming that i.types[op] 285994546Sobrien holds the correct displacement size. */ 286094546Sobrien expressionS *exp; 286160519Sobrien 286294546Sobrien assert (i.op[op].disps == 0); 286394546Sobrien exp = &disp_expressions[i.disp_operands++]; 286494546Sobrien i.op[op].disps = exp; 286594546Sobrien exp->X_op = O_constant; 286694546Sobrien exp->X_add_number = 0; 286794546Sobrien exp->X_add_symbol = (symbolS *) 0; 286894546Sobrien exp->X_op_symbol = (symbolS *) 0; 286994546Sobrien } 287094546Sobrien } 287133965Sjdp 287294546Sobrien /* Fill in i.rm.reg or i.rm.regmem field with register operand 287394546Sobrien (if any) based on i.tm.extension_opcode. Again, we must be 287494546Sobrien careful to make sure that segment/control/debug/test/MMX 287594546Sobrien registers are coded into the i.rm.reg field. */ 287694546Sobrien if (i.reg_operands) 287794546Sobrien { 287894546Sobrien unsigned int op = 287994546Sobrien ((i.types[0] 288094546Sobrien & (Reg | RegMMX | RegXMM 288194546Sobrien | SReg2 | SReg3 288294546Sobrien | Control | Debug | Test)) 288394546Sobrien ? 0 288494546Sobrien : ((i.types[1] 288594546Sobrien & (Reg | RegMMX | RegXMM 288694546Sobrien | SReg2 | SReg3 288794546Sobrien | Control | Debug | Test)) 288894546Sobrien ? 1 288994546Sobrien : 2)); 289094546Sobrien /* If there is an extension opcode to put here, the register 289194546Sobrien number must be put into the regmem field. */ 289294546Sobrien if (i.tm.extension_opcode != None) 289394546Sobrien { 289494546Sobrien i.rm.regmem = i.op[op].regs->reg_num; 289594546Sobrien if ((i.op[op].regs->reg_flags & RegRex) != 0) 289694546Sobrien i.rex |= REX_EXTZ; 289794546Sobrien } 289894546Sobrien else 289994546Sobrien { 290094546Sobrien i.rm.reg = i.op[op].regs->reg_num; 290194546Sobrien if ((i.op[op].regs->reg_flags & RegRex) != 0) 290294546Sobrien i.rex |= REX_EXTX; 290394546Sobrien } 290433965Sjdp 290594546Sobrien /* Now, if no memory operand has set i.rm.mode = 0, 1, 2 we 290694546Sobrien must set it to 3 to indicate this is a register operand 290794546Sobrien in the regmem field. */ 290894546Sobrien if (!i.mem_operands) 290994546Sobrien i.rm.mode = 3; 291094546Sobrien } 291133965Sjdp 291294546Sobrien /* Fill in i.rm.reg field with extension opcode (if any). */ 291394546Sobrien if (i.tm.extension_opcode != None) 291494546Sobrien i.rm.reg = i.tm.extension_opcode; 291594546Sobrien } 291694546Sobrien return default_seg; 291794546Sobrien} 291833965Sjdp 291994546Sobrienstatic void 292094546Sobrienoutput_branch () 292194546Sobrien{ 292294546Sobrien char *p; 292394546Sobrien int code16; 292494546Sobrien int prefix; 292594546Sobrien relax_substateT subtype; 292694546Sobrien symbolS *sym; 292794546Sobrien offsetT off; 292833965Sjdp 292994546Sobrien code16 = 0; 293094546Sobrien if (flag_code == CODE_16BIT) 293194546Sobrien code16 = CODE16; 293294546Sobrien 293394546Sobrien prefix = 0; 293494546Sobrien if (i.prefix[DATA_PREFIX] != 0) 293533965Sjdp { 293694546Sobrien prefix = 1; 293794546Sobrien i.prefixes -= 1; 293894546Sobrien code16 ^= CODE16; 293933965Sjdp } 294094546Sobrien /* Pentium4 branch hints. */ 294194546Sobrien if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */ 294294546Sobrien || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE /* taken */) 294360519Sobrien { 294494546Sobrien prefix++; 294594546Sobrien i.prefixes--; 294660519Sobrien } 294794546Sobrien if (i.prefix[REX_PREFIX] != 0) 294894546Sobrien { 294994546Sobrien prefix++; 295094546Sobrien i.prefixes--; 295194546Sobrien } 295260519Sobrien 295394546Sobrien if (i.prefixes != 0 && !intel_syntax) 295494546Sobrien as_warn (_("skipping prefixes on this instruction")); 295577311Sobrien 295694546Sobrien /* It's always a symbol; End frag & setup for relax. 295794546Sobrien Make sure there is enough room in this frag for the largest 295894546Sobrien instruction we may generate in md_convert_frag. This is 2 295994546Sobrien bytes for the opcode and room for the prefix and largest 296094546Sobrien displacement. */ 296194546Sobrien frag_grow (prefix + 2 + 4); 296294546Sobrien /* Prefix and 1 opcode byte go in fr_fix. */ 296394546Sobrien p = frag_more (prefix + 1); 296494546Sobrien if (i.prefix[DATA_PREFIX] != 0) 296594546Sobrien *p++ = DATA_PREFIX_OPCODE; 296694546Sobrien if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE 296794546Sobrien || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE) 296894546Sobrien *p++ = i.prefix[SEG_PREFIX]; 296994546Sobrien if (i.prefix[REX_PREFIX] != 0) 297094546Sobrien *p++ = i.prefix[REX_PREFIX]; 297194546Sobrien *p = i.tm.base_opcode; 297277311Sobrien 297394546Sobrien if ((unsigned char) *p == JUMP_PC_RELATIVE) 297494546Sobrien subtype = ENCODE_RELAX_STATE (UNCOND_JUMP, SMALL); 297594546Sobrien else if ((cpu_arch_flags & Cpu386) != 0) 297694546Sobrien subtype = ENCODE_RELAX_STATE (COND_JUMP, SMALL); 297794546Sobrien else 297894546Sobrien subtype = ENCODE_RELAX_STATE (COND_JUMP86, SMALL); 297994546Sobrien subtype |= code16; 298077311Sobrien 298194546Sobrien sym = i.op[0].disps->X_add_symbol; 298294546Sobrien off = i.op[0].disps->X_add_number; 298377311Sobrien 298494546Sobrien if (i.op[0].disps->X_op != O_constant 298594546Sobrien && i.op[0].disps->X_op != O_symbol) 298694546Sobrien { 298794546Sobrien /* Handle complex expressions. */ 298894546Sobrien sym = make_expr_symbol (i.op[0].disps); 298994546Sobrien off = 0; 299077311Sobrien } 299177311Sobrien 299294546Sobrien /* 1 possible extra opcode + 4 byte displacement go in var part. 299394546Sobrien Pass reloc in fr_var. */ 299494546Sobrien frag_var (rs_machine_dependent, 5, i.reloc[0], subtype, sym, off, p); 299594546Sobrien} 299677311Sobrien 299794546Sobrienstatic void 299894546Sobrienoutput_jump () 299994546Sobrien{ 300094546Sobrien char *p; 300194546Sobrien int size; 3002104848Sobrien fixS *fixP; 300333965Sjdp 300494546Sobrien if (i.tm.opcode_modifier & JumpByte) 300594546Sobrien { 300694546Sobrien /* This is a loop or jecxz type instruction. */ 300794546Sobrien size = 1; 300894546Sobrien if (i.prefix[ADDR_PREFIX] != 0) 300994546Sobrien { 301094546Sobrien FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE); 301194546Sobrien i.prefixes -= 1; 301294546Sobrien } 301394546Sobrien /* Pentium4 branch hints. */ 301494546Sobrien if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */ 301594546Sobrien || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE /* taken */) 301694546Sobrien { 301794546Sobrien FRAG_APPEND_1_CHAR (i.prefix[SEG_PREFIX]); 301894546Sobrien i.prefixes--; 301994546Sobrien } 302094546Sobrien } 302194546Sobrien else 302294546Sobrien { 302394546Sobrien int code16; 302478840Sobrien 302594546Sobrien code16 = 0; 302694546Sobrien if (flag_code == CODE_16BIT) 302794546Sobrien code16 = CODE16; 302833965Sjdp 302994546Sobrien if (i.prefix[DATA_PREFIX] != 0) 303094546Sobrien { 303194546Sobrien FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE); 303294546Sobrien i.prefixes -= 1; 303394546Sobrien code16 ^= CODE16; 303494546Sobrien } 303560519Sobrien 303694546Sobrien size = 4; 303794546Sobrien if (code16) 303894546Sobrien size = 2; 303994546Sobrien } 304033965Sjdp 304194546Sobrien if (i.prefix[REX_PREFIX] != 0) 304294546Sobrien { 304394546Sobrien FRAG_APPEND_1_CHAR (i.prefix[REX_PREFIX]); 304494546Sobrien i.prefixes -= 1; 304594546Sobrien } 304633965Sjdp 304794546Sobrien if (i.prefixes != 0 && !intel_syntax) 304894546Sobrien as_warn (_("skipping prefixes on this instruction")); 304989867Sobrien 305094546Sobrien p = frag_more (1 + size); 305194546Sobrien *p++ = i.tm.base_opcode; 305289867Sobrien 3053104848Sobrien fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size, 3054104848Sobrien i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0])); 3055104848Sobrien 3056104848Sobrien /* All jumps handled here are signed, but don't use a signed limit 3057104848Sobrien check for 32 and 16 bit jumps as we want to allow wrap around at 3058104848Sobrien 4G and 64k respectively. */ 3059104848Sobrien if (size == 1) 3060104848Sobrien fixP->fx_signed = 1; 306194546Sobrien} 306289867Sobrien 306394546Sobrienstatic void 306494546Sobrienoutput_interseg_jump () 306594546Sobrien{ 306694546Sobrien char *p; 306794546Sobrien int size; 306894546Sobrien int prefix; 306994546Sobrien int code16; 307089867Sobrien 307194546Sobrien code16 = 0; 307294546Sobrien if (flag_code == CODE_16BIT) 307394546Sobrien code16 = CODE16; 307433965Sjdp 307594546Sobrien prefix = 0; 307694546Sobrien if (i.prefix[DATA_PREFIX] != 0) 307794546Sobrien { 307894546Sobrien prefix = 1; 307994546Sobrien i.prefixes -= 1; 308094546Sobrien code16 ^= CODE16; 308194546Sobrien } 308294546Sobrien if (i.prefix[REX_PREFIX] != 0) 308394546Sobrien { 308494546Sobrien prefix++; 308594546Sobrien i.prefixes -= 1; 308694546Sobrien } 308738891Sjdp 308894546Sobrien size = 4; 308994546Sobrien if (code16) 309094546Sobrien size = 2; 309138891Sjdp 309294546Sobrien if (i.prefixes != 0 && !intel_syntax) 309394546Sobrien as_warn (_("skipping prefixes on this instruction")); 309433965Sjdp 309594546Sobrien /* 1 opcode; 2 segment; offset */ 309694546Sobrien p = frag_more (prefix + 1 + 2 + size); 309733965Sjdp 309894546Sobrien if (i.prefix[DATA_PREFIX] != 0) 309994546Sobrien *p++ = DATA_PREFIX_OPCODE; 310077311Sobrien 310194546Sobrien if (i.prefix[REX_PREFIX] != 0) 310294546Sobrien *p++ = i.prefix[REX_PREFIX]; 310360519Sobrien 310494546Sobrien *p++ = i.tm.base_opcode; 310594546Sobrien if (i.op[1].imms->X_op == O_constant) 310694546Sobrien { 310794546Sobrien offsetT n = i.op[1].imms->X_add_number; 310833965Sjdp 310994546Sobrien if (size == 2 311094546Sobrien && !fits_in_unsigned_word (n) 311194546Sobrien && !fits_in_signed_word (n)) 311294546Sobrien { 311394546Sobrien as_bad (_("16-bit jump out of range")); 311494546Sobrien return; 311594546Sobrien } 311694546Sobrien md_number_to_chars (p, n, size); 311794546Sobrien } 311894546Sobrien else 311994546Sobrien fix_new_exp (frag_now, p - frag_now->fr_literal, size, 312094546Sobrien i.op[1].imms, 0, reloc (size, 0, 0, i.reloc[1])); 312194546Sobrien if (i.op[0].imms->X_op != O_constant) 312294546Sobrien as_bad (_("can't handle non absolute segment in `%s'"), 312394546Sobrien i.tm.name); 312494546Sobrien md_number_to_chars (p + size, (valueT) i.op[0].imms->X_add_number, 2); 312594546Sobrien} 312660519Sobrien 312794546Sobrienstatic void 312894546Sobrienoutput_insn () 312994546Sobrien{ 3130104848Sobrien fragS *insn_start_frag; 3131104848Sobrien offsetT insn_start_off; 3132104848Sobrien 313394546Sobrien /* Tie dwarf2 debug info to the address at the start of the insn. 313494546Sobrien We can't do this after the insn has been output as the current 313594546Sobrien frag may have been closed off. eg. by frag_var. */ 313694546Sobrien dwarf2_emit_insn (0); 313760519Sobrien 3138104848Sobrien insn_start_frag = frag_now; 3139104848Sobrien insn_start_off = frag_now_fix (); 3140104848Sobrien 314194546Sobrien /* Output jumps. */ 314294546Sobrien if (i.tm.opcode_modifier & Jump) 314394546Sobrien output_branch (); 314494546Sobrien else if (i.tm.opcode_modifier & (JumpByte | JumpDword)) 314594546Sobrien output_jump (); 314694546Sobrien else if (i.tm.opcode_modifier & JumpInterSegment) 314794546Sobrien output_interseg_jump (); 314894546Sobrien else 314994546Sobrien { 315094546Sobrien /* Output normal instructions here. */ 315194546Sobrien char *p; 315294546Sobrien unsigned char *q; 315333965Sjdp 3154130570Sobrien /* All opcodes on i386 have either 1 or 2 bytes, PadLock instructions 3155130570Sobrien have 3 bytes. We may use one more higher byte to specify a prefix 3156130570Sobrien the instruction requires. */ 3157130570Sobrien if ((i.tm.cpu_flags & CpuPadLock) != 0 3158130570Sobrien && (i.tm.base_opcode & 0xff000000) != 0) 3159130570Sobrien { 3160130570Sobrien unsigned int prefix; 3161130570Sobrien prefix = (i.tm.base_opcode >> 24) & 0xff; 316260519Sobrien 3163130570Sobrien if (prefix != REPE_PREFIX_OPCODE 3164130570Sobrien || i.prefix[LOCKREP_PREFIX] != REPE_PREFIX_OPCODE) 3165130570Sobrien add_prefix (prefix); 3166130570Sobrien } 3167130570Sobrien else 3168130570Sobrien if ((i.tm.cpu_flags & CpuPadLock) == 0 3169130570Sobrien && (i.tm.base_opcode & 0xff0000) != 0) 3170130570Sobrien add_prefix ((i.tm.base_opcode >> 16) & 0xff); 3171130570Sobrien 317294546Sobrien /* The prefix bytes. */ 317394546Sobrien for (q = i.prefix; 317494546Sobrien q < i.prefix + sizeof (i.prefix) / sizeof (i.prefix[0]); 317594546Sobrien q++) 317694546Sobrien { 317794546Sobrien if (*q) 317894546Sobrien { 317994546Sobrien p = frag_more (1); 318094546Sobrien md_number_to_chars (p, (valueT) *q, 1); 318194546Sobrien } 318294546Sobrien } 318360519Sobrien 318494546Sobrien /* Now the opcode; be careful about word order here! */ 318594546Sobrien if (fits_in_unsigned_byte (i.tm.base_opcode)) 318694546Sobrien { 318794546Sobrien FRAG_APPEND_1_CHAR (i.tm.base_opcode); 318894546Sobrien } 318994546Sobrien else 319094546Sobrien { 3191130570Sobrien if ((i.tm.cpu_flags & CpuPadLock) != 0) 3192130570Sobrien { 3193130570Sobrien p = frag_more (3); 3194130570Sobrien *p++ = (i.tm.base_opcode >> 16) & 0xff; 3195130570Sobrien } 3196130570Sobrien else 3197130570Sobrien p = frag_more (2); 3198130570Sobrien 319994546Sobrien /* Put out high byte first: can't use md_number_to_chars! */ 320094546Sobrien *p++ = (i.tm.base_opcode >> 8) & 0xff; 320194546Sobrien *p = i.tm.base_opcode & 0xff; 320294546Sobrien } 320377311Sobrien 320494546Sobrien /* Now the modrm byte and sib byte (if present). */ 320594546Sobrien if (i.tm.opcode_modifier & Modrm) 320694546Sobrien { 320794546Sobrien p = frag_more (1); 320894546Sobrien md_number_to_chars (p, 320994546Sobrien (valueT) (i.rm.regmem << 0 321094546Sobrien | i.rm.reg << 3 321194546Sobrien | i.rm.mode << 6), 321294546Sobrien 1); 321394546Sobrien /* If i.rm.regmem == ESP (4) 321494546Sobrien && i.rm.mode != (Register mode) 321594546Sobrien && not 16 bit 321694546Sobrien ==> need second modrm byte. */ 321794546Sobrien if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING 321894546Sobrien && i.rm.mode != 3 321994546Sobrien && !(i.base_reg && (i.base_reg->reg_type & Reg16) != 0)) 322094546Sobrien { 322194546Sobrien p = frag_more (1); 322294546Sobrien md_number_to_chars (p, 322394546Sobrien (valueT) (i.sib.base << 0 322494546Sobrien | i.sib.index << 3 322594546Sobrien | i.sib.scale << 6), 322694546Sobrien 1); 322794546Sobrien } 322894546Sobrien } 322977311Sobrien 323094546Sobrien if (i.disp_operands) 3231104848Sobrien output_disp (insn_start_frag, insn_start_off); 323277311Sobrien 323394546Sobrien if (i.imm_operands) 3234104848Sobrien output_imm (insn_start_frag, insn_start_off); 323594546Sobrien } 323660519Sobrien 323794546Sobrien#ifdef DEBUG386 323894546Sobrien if (flag_debug) 323994546Sobrien { 324094546Sobrien pi (line, &i); 324194546Sobrien } 324294546Sobrien#endif /* DEBUG386 */ 324394546Sobrien} 324433965Sjdp 324594546Sobrienstatic void 3246104848Sobrienoutput_disp (insn_start_frag, insn_start_off) 3247104848Sobrien fragS *insn_start_frag; 3248104848Sobrien offsetT insn_start_off; 324994546Sobrien{ 325094546Sobrien char *p; 325194546Sobrien unsigned int n; 325277311Sobrien 325394546Sobrien for (n = 0; n < i.operands; n++) 325494546Sobrien { 325594546Sobrien if (i.types[n] & Disp) 325694546Sobrien { 325794546Sobrien if (i.op[n].disps->X_op == O_constant) 325894546Sobrien { 325994546Sobrien int size; 326094546Sobrien offsetT val; 326133965Sjdp 326294546Sobrien size = 4; 326394546Sobrien if (i.types[n] & (Disp8 | Disp16 | Disp64)) 326494546Sobrien { 326594546Sobrien size = 2; 326694546Sobrien if (i.types[n] & Disp8) 326794546Sobrien size = 1; 326894546Sobrien if (i.types[n] & Disp64) 326994546Sobrien size = 8; 327094546Sobrien } 327194546Sobrien val = offset_in_range (i.op[n].disps->X_add_number, 327294546Sobrien size); 327394546Sobrien p = frag_more (size); 327494546Sobrien md_number_to_chars (p, val, size); 327594546Sobrien } 327694546Sobrien else 327794546Sobrien { 3278130570Sobrien enum bfd_reloc_code_real reloc_type; 327994546Sobrien int size = 4; 328094546Sobrien int sign = 0; 328194546Sobrien int pcrel = (i.flags[n] & Operand_PCrel) != 0; 328233965Sjdp 328394546Sobrien /* The PC relative address is computed relative 328494546Sobrien to the instruction boundary, so in case immediate 328594546Sobrien fields follows, we need to adjust the value. */ 328694546Sobrien if (pcrel && i.imm_operands) 328794546Sobrien { 328894546Sobrien int imm_size = 4; 328994546Sobrien unsigned int n1; 329033965Sjdp 329194546Sobrien for (n1 = 0; n1 < i.operands; n1++) 329294546Sobrien if (i.types[n1] & Imm) 329333965Sjdp { 329494546Sobrien if (i.types[n1] & (Imm8 | Imm8S | Imm16 | Imm64)) 329533965Sjdp { 329694546Sobrien imm_size = 2; 329794546Sobrien if (i.types[n1] & (Imm8 | Imm8S)) 329894546Sobrien imm_size = 1; 329994546Sobrien if (i.types[n1] & Imm64) 330094546Sobrien imm_size = 8; 330133965Sjdp } 330294546Sobrien break; 330333965Sjdp } 330494546Sobrien /* We should find the immediate. */ 330594546Sobrien if (n1 == i.operands) 330694546Sobrien abort (); 330794546Sobrien i.op[n].disps->X_add_number -= imm_size; 330894546Sobrien } 330960519Sobrien 331094546Sobrien if (i.types[n] & Disp32S) 331194546Sobrien sign = 1; 331260519Sobrien 331394546Sobrien if (i.types[n] & (Disp16 | Disp64)) 331494546Sobrien { 331594546Sobrien size = 2; 331694546Sobrien if (i.types[n] & Disp64) 331794546Sobrien size = 8; 331894546Sobrien } 331977311Sobrien 332094546Sobrien p = frag_more (size); 3321104848Sobrien reloc_type = reloc (size, pcrel, sign, i.reloc[n]); 3322104848Sobrien if (reloc_type == BFD_RELOC_32 3323104848Sobrien && GOT_symbol 3324104848Sobrien && GOT_symbol == i.op[n].disps->X_add_symbol 3325104848Sobrien && (i.op[n].disps->X_op == O_symbol 3326104848Sobrien || (i.op[n].disps->X_op == O_add 3327104848Sobrien && ((symbol_get_value_expression 3328104848Sobrien (i.op[n].disps->X_op_symbol)->X_op) 3329104848Sobrien == O_subtract)))) 3330104848Sobrien { 3331104848Sobrien offsetT add; 3332104848Sobrien 3333104848Sobrien if (insn_start_frag == frag_now) 3334104848Sobrien add = (p - frag_now->fr_literal) - insn_start_off; 3335104848Sobrien else 3336104848Sobrien { 3337104848Sobrien fragS *fr; 3338104848Sobrien 3339104848Sobrien add = insn_start_frag->fr_fix - insn_start_off; 3340104848Sobrien for (fr = insn_start_frag->fr_next; 3341104848Sobrien fr && fr != frag_now; fr = fr->fr_next) 3342104848Sobrien add += fr->fr_fix; 3343104848Sobrien add += p - frag_now->fr_literal; 3344104848Sobrien } 3345104848Sobrien 3346104848Sobrien /* We don't support dynamic linking on x86-64 yet. */ 3347104848Sobrien if (flag_code == CODE_64BIT) 3348104848Sobrien abort (); 3349104848Sobrien reloc_type = BFD_RELOC_386_GOTPC; 3350104848Sobrien i.op[n].disps->X_add_number += add; 3351104848Sobrien } 335299468Sobrien fix_new_exp (frag_now, p - frag_now->fr_literal, size, 3353104848Sobrien i.op[n].disps, pcrel, reloc_type); 335494546Sobrien } 335594546Sobrien } 335694546Sobrien } 335794546Sobrien} 335877311Sobrien 335994546Sobrienstatic void 3360104848Sobrienoutput_imm (insn_start_frag, insn_start_off) 3361104848Sobrien fragS *insn_start_frag; 3362104848Sobrien offsetT insn_start_off; 336394546Sobrien{ 336494546Sobrien char *p; 336594546Sobrien unsigned int n; 336677311Sobrien 336794546Sobrien for (n = 0; n < i.operands; n++) 336894546Sobrien { 336994546Sobrien if (i.types[n] & Imm) 337094546Sobrien { 337194546Sobrien if (i.op[n].imms->X_op == O_constant) 337294546Sobrien { 337394546Sobrien int size; 337494546Sobrien offsetT val; 337533965Sjdp 337694546Sobrien size = 4; 337794546Sobrien if (i.types[n] & (Imm8 | Imm8S | Imm16 | Imm64)) 337894546Sobrien { 337994546Sobrien size = 2; 338094546Sobrien if (i.types[n] & (Imm8 | Imm8S)) 338194546Sobrien size = 1; 338294546Sobrien else if (i.types[n] & Imm64) 338394546Sobrien size = 8; 338494546Sobrien } 338594546Sobrien val = offset_in_range (i.op[n].imms->X_add_number, 338694546Sobrien size); 338794546Sobrien p = frag_more (size); 338894546Sobrien md_number_to_chars (p, val, size); 338994546Sobrien } 339094546Sobrien else 339194546Sobrien { 339294546Sobrien /* Not absolute_section. 339394546Sobrien Need a 32-bit fixup (don't support 8bit 339494546Sobrien non-absolute imms). Try to support other 339594546Sobrien sizes ... */ 3396130570Sobrien enum bfd_reloc_code_real reloc_type; 339794546Sobrien int size = 4; 339894546Sobrien int sign = 0; 339933965Sjdp 340094546Sobrien if ((i.types[n] & (Imm32S)) 340194546Sobrien && i.suffix == QWORD_MNEM_SUFFIX) 340294546Sobrien sign = 1; 340394546Sobrien if (i.types[n] & (Imm8 | Imm8S | Imm16 | Imm64)) 340494546Sobrien { 340594546Sobrien size = 2; 340694546Sobrien if (i.types[n] & (Imm8 | Imm8S)) 340794546Sobrien size = 1; 340894546Sobrien if (i.types[n] & Imm64) 340994546Sobrien size = 8; 341094546Sobrien } 341160519Sobrien 341294546Sobrien p = frag_more (size); 341394546Sobrien reloc_type = reloc (size, 0, sign, i.reloc[n]); 3414130570Sobrien 3415104848Sobrien /* This is tough to explain. We end up with this one if we 3416104848Sobrien * have operands that look like 3417104848Sobrien * "_GLOBAL_OFFSET_TABLE_+[.-.L284]". The goal here is to 3418104848Sobrien * obtain the absolute address of the GOT, and it is strongly 3419104848Sobrien * preferable from a performance point of view to avoid using 3420104848Sobrien * a runtime relocation for this. The actual sequence of 3421104848Sobrien * instructions often look something like: 3422104848Sobrien * 3423104848Sobrien * call .L66 3424104848Sobrien * .L66: 3425104848Sobrien * popl %ebx 3426104848Sobrien * addl $_GLOBAL_OFFSET_TABLE_+[.-.L66],%ebx 3427104848Sobrien * 3428104848Sobrien * The call and pop essentially return the absolute address 3429104848Sobrien * of the label .L66 and store it in %ebx. The linker itself 3430104848Sobrien * will ultimately change the first operand of the addl so 3431104848Sobrien * that %ebx points to the GOT, but to keep things simple, the 3432104848Sobrien * .o file must have this operand set so that it generates not 3433104848Sobrien * the absolute address of .L66, but the absolute address of 3434104848Sobrien * itself. This allows the linker itself simply treat a GOTPC 3435104848Sobrien * relocation as asking for a pcrel offset to the GOT to be 3436104848Sobrien * added in, and the addend of the relocation is stored in the 3437104848Sobrien * operand field for the instruction itself. 3438104848Sobrien * 3439104848Sobrien * Our job here is to fix the operand so that it would add 3440104848Sobrien * the correct offset so that %ebx would point to itself. The 3441104848Sobrien * thing that is tricky is that .-.L66 will point to the 3442104848Sobrien * beginning of the instruction, so we need to further modify 3443104848Sobrien * the operand so that it will point to itself. There are 3444104848Sobrien * other cases where you have something like: 3445104848Sobrien * 3446104848Sobrien * .long $_GLOBAL_OFFSET_TABLE_+[.-.L66] 3447104848Sobrien * 3448104848Sobrien * and here no correction would be required. Internally in 3449104848Sobrien * the assembler we treat operands of this form as not being 3450104848Sobrien * pcrel since the '.' is explicitly mentioned, and I wonder 3451104848Sobrien * whether it would simplify matters to do it this way. Who 3452104848Sobrien * knows. In earlier versions of the PIC patches, the 3453104848Sobrien * pcrel_adjust field was used to store the correction, but 3454104848Sobrien * since the expression is not pcrel, I felt it would be 3455104848Sobrien * confusing to do it this way. */ 3456104848Sobrien 345794546Sobrien if (reloc_type == BFD_RELOC_32 345894546Sobrien && GOT_symbol 345994546Sobrien && GOT_symbol == i.op[n].imms->X_add_symbol 346094546Sobrien && (i.op[n].imms->X_op == O_symbol 346194546Sobrien || (i.op[n].imms->X_op == O_add 346294546Sobrien && ((symbol_get_value_expression 346394546Sobrien (i.op[n].imms->X_op_symbol)->X_op) 346494546Sobrien == O_subtract)))) 346594546Sobrien { 3466104848Sobrien offsetT add; 3467104848Sobrien 3468104848Sobrien if (insn_start_frag == frag_now) 3469104848Sobrien add = (p - frag_now->fr_literal) - insn_start_off; 3470104848Sobrien else 3471104848Sobrien { 3472104848Sobrien fragS *fr; 3473104848Sobrien 3474104848Sobrien add = insn_start_frag->fr_fix - insn_start_off; 3475104848Sobrien for (fr = insn_start_frag->fr_next; 3476104848Sobrien fr && fr != frag_now; fr = fr->fr_next) 3477104848Sobrien add += fr->fr_fix; 3478104848Sobrien add += p - frag_now->fr_literal; 3479104848Sobrien } 3480104848Sobrien 348194546Sobrien /* We don't support dynamic linking on x86-64 yet. */ 348294546Sobrien if (flag_code == CODE_64BIT) 348394546Sobrien abort (); 348494546Sobrien reloc_type = BFD_RELOC_386_GOTPC; 3485104848Sobrien i.op[n].imms->X_add_number += add; 348694546Sobrien } 348794546Sobrien fix_new_exp (frag_now, p - frag_now->fr_literal, size, 348894546Sobrien i.op[n].imms, 0, reloc_type); 348994546Sobrien } 349094546Sobrien } 349194546Sobrien } 349233965Sjdp} 349333965Sjdp 349478840Sobrien#ifndef LEX_AT 3495130570Sobrienstatic char *lex_got PARAMS ((enum bfd_reloc_code_real *, int *)); 349678840Sobrien 349778840Sobrien/* Parse operands of the form 349878840Sobrien <symbol>@GOTOFF+<nnn> 349978840Sobrien and similar .plt or .got references. 350078840Sobrien 350178840Sobrien If we find one, set up the correct relocation in RELOC and copy the 350278840Sobrien input string, minus the `@GOTOFF' into a malloc'd buffer for 350378840Sobrien parsing by the calling routine. Return this buffer, and if ADJUST 350478840Sobrien is non-null set it to the length of the string we removed from the 350578840Sobrien input line. Otherwise return NULL. */ 350678840Sobrienstatic char * 350778840Sobrienlex_got (reloc, adjust) 3508130570Sobrien enum bfd_reloc_code_real *reloc; 350978840Sobrien int *adjust; 351078840Sobrien{ 351178840Sobrien static const char * const mode_name[NUM_FLAG_CODE] = { "32", "16", "64" }; 351278840Sobrien static const struct { 351378840Sobrien const char *str; 3514130570Sobrien const enum bfd_reloc_code_real rel[NUM_FLAG_CODE]; 351578840Sobrien } gotrel[] = { 3516104848Sobrien { "PLT", { BFD_RELOC_386_PLT32, 0, BFD_RELOC_X86_64_PLT32 } }, 3517104848Sobrien { "GOTOFF", { BFD_RELOC_386_GOTOFF, 0, 0 } }, 3518104848Sobrien { "GOTPCREL", { 0, 0, BFD_RELOC_X86_64_GOTPCREL } }, 3519130570Sobrien { "TLSGD", { BFD_RELOC_386_TLS_GD, 0, BFD_RELOC_X86_64_TLSGD } }, 3520104848Sobrien { "TLSLDM", { BFD_RELOC_386_TLS_LDM, 0, 0 } }, 3521130570Sobrien { "TLSLD", { 0, 0, BFD_RELOC_X86_64_TLSLD } }, 3522130570Sobrien { "GOTTPOFF", { BFD_RELOC_386_TLS_IE_32, 0, BFD_RELOC_X86_64_GOTTPOFF } }, 3523130570Sobrien { "TPOFF", { BFD_RELOC_386_TLS_LE_32, 0, BFD_RELOC_X86_64_TPOFF32 } }, 3524104848Sobrien { "NTPOFF", { BFD_RELOC_386_TLS_LE, 0, 0 } }, 3525130570Sobrien { "DTPOFF", { BFD_RELOC_386_TLS_LDO_32, 0, BFD_RELOC_X86_64_DTPOFF32 } }, 3526104848Sobrien { "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE, 0, 0 } }, 3527104848Sobrien { "INDNTPOFF",{ BFD_RELOC_386_TLS_IE, 0, 0 } }, 3528104848Sobrien { "GOT", { BFD_RELOC_386_GOT32, 0, BFD_RELOC_X86_64_GOT32 } } 352978840Sobrien }; 353078840Sobrien char *cp; 353178840Sobrien unsigned int j; 353278840Sobrien 353378840Sobrien for (cp = input_line_pointer; *cp != '@'; cp++) 353478840Sobrien if (is_end_of_line[(unsigned char) *cp]) 353578840Sobrien return NULL; 353678840Sobrien 353778840Sobrien for (j = 0; j < sizeof (gotrel) / sizeof (gotrel[0]); j++) 353878840Sobrien { 353978840Sobrien int len; 354078840Sobrien 354178840Sobrien len = strlen (gotrel[j].str); 354289867Sobrien if (strncasecmp (cp + 1, gotrel[j].str, len) == 0) 354378840Sobrien { 354478840Sobrien if (gotrel[j].rel[(unsigned int) flag_code] != 0) 354578840Sobrien { 354689867Sobrien int first, second; 354789867Sobrien char *tmpbuf, *past_reloc; 354878840Sobrien 354978840Sobrien *reloc = gotrel[j].rel[(unsigned int) flag_code]; 355089867Sobrien if (adjust) 355189867Sobrien *adjust = len; 355278840Sobrien 355378840Sobrien if (GOT_symbol == NULL) 355478840Sobrien GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME); 355578840Sobrien 355678840Sobrien /* Replace the relocation token with ' ', so that 355778840Sobrien errors like foo@GOTOFF1 will be detected. */ 355889867Sobrien 355989867Sobrien /* The length of the first part of our input line. */ 356078840Sobrien first = cp - input_line_pointer; 356189867Sobrien 356289867Sobrien /* The second part goes from after the reloc token until 356389867Sobrien (and including) an end_of_line char. Don't use strlen 356489867Sobrien here as the end_of_line char may not be a NUL. */ 356589867Sobrien past_reloc = cp + 1 + len; 356689867Sobrien for (cp = past_reloc; !is_end_of_line[(unsigned char) *cp++]; ) 356789867Sobrien ; 356889867Sobrien second = cp - past_reloc; 356989867Sobrien 357089867Sobrien /* Allocate and copy string. The trailing NUL shouldn't 357189867Sobrien be necessary, but be safe. */ 357289867Sobrien tmpbuf = xmalloc (first + second + 2); 357378840Sobrien memcpy (tmpbuf, input_line_pointer, first); 357478840Sobrien tmpbuf[first] = ' '; 357589867Sobrien memcpy (tmpbuf + first + 1, past_reloc, second); 357689867Sobrien tmpbuf[first + second + 1] = '\0'; 357778840Sobrien return tmpbuf; 357878840Sobrien } 357978840Sobrien 358078840Sobrien as_bad (_("@%s reloc is not supported in %s bit mode"), 358178840Sobrien gotrel[j].str, mode_name[(unsigned int) flag_code]); 358278840Sobrien return NULL; 358378840Sobrien } 358478840Sobrien } 358578840Sobrien 358678840Sobrien /* Might be a symbol version string. Don't as_bad here. */ 358778840Sobrien return NULL; 358878840Sobrien} 358978840Sobrien 359078840Sobrien/* x86_cons_fix_new is called via the expression parsing code when a 359178840Sobrien reloc is needed. We use this hook to get the correct .got reloc. */ 3592130570Sobrienstatic enum bfd_reloc_code_real got_reloc = NO_RELOC; 359378840Sobrien 359478840Sobrienvoid 359578840Sobrienx86_cons_fix_new (frag, off, len, exp) 359678840Sobrien fragS *frag; 359778840Sobrien unsigned int off; 359878840Sobrien unsigned int len; 359978840Sobrien expressionS *exp; 360078840Sobrien{ 3601130570Sobrien enum bfd_reloc_code_real r = reloc (len, 0, 0, got_reloc); 360278840Sobrien got_reloc = NO_RELOC; 360378840Sobrien fix_new_exp (frag, off, len, exp, 0, r); 360478840Sobrien} 360578840Sobrien 360678840Sobrienvoid 360778840Sobrienx86_cons (exp, size) 360878840Sobrien expressionS *exp; 360978840Sobrien int size; 361078840Sobrien{ 361178840Sobrien if (size == 4) 361278840Sobrien { 361378840Sobrien /* Handle @GOTOFF and the like in an expression. */ 361478840Sobrien char *save; 361578840Sobrien char *gotfree_input_line; 361678840Sobrien int adjust; 361778840Sobrien 361878840Sobrien save = input_line_pointer; 361978840Sobrien gotfree_input_line = lex_got (&got_reloc, &adjust); 362078840Sobrien if (gotfree_input_line) 362178840Sobrien input_line_pointer = gotfree_input_line; 362278840Sobrien 362378840Sobrien expression (exp); 362478840Sobrien 362578840Sobrien if (gotfree_input_line) 362678840Sobrien { 362778840Sobrien /* expression () has merrily parsed up to the end of line, 362878840Sobrien or a comma - in the wrong buffer. Transfer how far 362978840Sobrien input_line_pointer has moved to the right buffer. */ 363078840Sobrien input_line_pointer = (save 363178840Sobrien + (input_line_pointer - gotfree_input_line) 363278840Sobrien + adjust); 363378840Sobrien free (gotfree_input_line); 363478840Sobrien } 363578840Sobrien } 363678840Sobrien else 363778840Sobrien expression (exp); 363878840Sobrien} 363978840Sobrien#endif 364078840Sobrien 364160519Sobrienstatic int i386_immediate PARAMS ((char *)); 364260519Sobrien 364360519Sobrienstatic int 364460519Sobrieni386_immediate (imm_start) 364560519Sobrien char *imm_start; 364660519Sobrien{ 364760519Sobrien char *save_input_line_pointer; 364878840Sobrien#ifndef LEX_AT 364978840Sobrien char *gotfree_input_line; 365078840Sobrien#endif 365160519Sobrien segT exp_seg = 0; 365277311Sobrien expressionS *exp; 365360519Sobrien 365460519Sobrien if (i.imm_operands == MAX_IMMEDIATE_OPERANDS) 365560519Sobrien { 365660519Sobrien as_bad (_("only 1 or 2 immediate operands are allowed")); 365760519Sobrien return 0; 365860519Sobrien } 365960519Sobrien 366060519Sobrien exp = &im_expressions[i.imm_operands++]; 366160519Sobrien i.op[this_operand].imms = exp; 366260519Sobrien 366360519Sobrien if (is_space_char (*imm_start)) 366460519Sobrien ++imm_start; 366560519Sobrien 366660519Sobrien save_input_line_pointer = input_line_pointer; 366760519Sobrien input_line_pointer = imm_start; 366860519Sobrien 366960519Sobrien#ifndef LEX_AT 367078840Sobrien gotfree_input_line = lex_got (&i.reloc[this_operand], NULL); 367178840Sobrien if (gotfree_input_line) 367278840Sobrien input_line_pointer = gotfree_input_line; 367360519Sobrien#endif 367460519Sobrien 367560519Sobrien exp_seg = expression (exp); 367660519Sobrien 367760519Sobrien SKIP_WHITESPACE (); 367860519Sobrien if (*input_line_pointer) 367978840Sobrien as_bad (_("junk `%s' after expression"), input_line_pointer); 368060519Sobrien 368160519Sobrien input_line_pointer = save_input_line_pointer; 368278840Sobrien#ifndef LEX_AT 368378840Sobrien if (gotfree_input_line) 368478840Sobrien free (gotfree_input_line); 368578840Sobrien#endif 368660519Sobrien 368760519Sobrien if (exp->X_op == O_absent || exp->X_op == O_big) 368860519Sobrien { 368977311Sobrien /* Missing or bad expr becomes absolute 0. */ 369060519Sobrien as_bad (_("missing or invalid immediate expression `%s' taken as 0"), 369160519Sobrien imm_start); 369260519Sobrien exp->X_op = O_constant; 369360519Sobrien exp->X_add_number = 0; 369460519Sobrien exp->X_add_symbol = (symbolS *) 0; 369560519Sobrien exp->X_op_symbol = (symbolS *) 0; 369660519Sobrien } 369777311Sobrien else if (exp->X_op == O_constant) 369860519Sobrien { 369977311Sobrien /* Size it properly later. */ 370077311Sobrien i.types[this_operand] |= Imm64; 370177311Sobrien /* If BFD64, sign extend val. */ 370277311Sobrien if (!use_rela_relocations) 370377311Sobrien if ((exp->X_add_number & ~(((addressT) 2 << 31) - 1)) == 0) 370477311Sobrien exp->X_add_number = (exp->X_add_number ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31); 370560519Sobrien } 370660519Sobrien#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT)) 3707130570Sobrien else if (OUTPUT_FLAVOR == bfd_target_aout_flavour 3708104848Sobrien && exp_seg != absolute_section 370977311Sobrien && exp_seg != text_section 371060519Sobrien && exp_seg != data_section 371160519Sobrien && exp_seg != bss_section 371260519Sobrien && exp_seg != undefined_section 3713130570Sobrien && !bfd_is_com_section (exp_seg)) 371460519Sobrien { 371560519Sobrien as_bad (_("unimplemented segment %s in operand"), exp_seg->name); 371660519Sobrien return 0; 371760519Sobrien } 371860519Sobrien#endif 371960519Sobrien else 372060519Sobrien { 372160519Sobrien /* This is an address. The size of the address will be 372260519Sobrien determined later, depending on destination register, 372377311Sobrien suffix, or the default for the section. */ 372477311Sobrien i.types[this_operand] |= Imm8 | Imm16 | Imm32 | Imm32S | Imm64; 372560519Sobrien } 372660519Sobrien 372760519Sobrien return 1; 372860519Sobrien} 372960519Sobrien 373078840Sobrienstatic char *i386_scale PARAMS ((char *)); 373160519Sobrien 373278840Sobrienstatic char * 373360519Sobrieni386_scale (scale) 373460519Sobrien char *scale; 373560519Sobrien{ 373678840Sobrien offsetT val; 373778840Sobrien char *save = input_line_pointer; 373860519Sobrien 373978840Sobrien input_line_pointer = scale; 374078840Sobrien val = get_absolute_expression (); 374178840Sobrien 374278840Sobrien switch (val) 374360519Sobrien { 374478840Sobrien case 0: 374578840Sobrien case 1: 374660519Sobrien i.log2_scale_factor = 0; 374760519Sobrien break; 374878840Sobrien case 2: 374960519Sobrien i.log2_scale_factor = 1; 375060519Sobrien break; 375178840Sobrien case 4: 375260519Sobrien i.log2_scale_factor = 2; 375360519Sobrien break; 375478840Sobrien case 8: 375560519Sobrien i.log2_scale_factor = 3; 375660519Sobrien break; 375760519Sobrien default: 375860519Sobrien as_bad (_("expecting scale factor of 1, 2, 4, or 8: got `%s'"), 375960519Sobrien scale); 376078840Sobrien input_line_pointer = save; 376178840Sobrien return NULL; 376260519Sobrien } 376394546Sobrien if (i.log2_scale_factor != 0 && i.index_reg == 0) 376460519Sobrien { 376560519Sobrien as_warn (_("scale factor of %d without an index register"), 376660519Sobrien 1 << i.log2_scale_factor); 376760519Sobrien#if SCALE1_WHEN_NO_INDEX 376860519Sobrien i.log2_scale_factor = 0; 376960519Sobrien#endif 377060519Sobrien } 377178840Sobrien scale = input_line_pointer; 377278840Sobrien input_line_pointer = save; 377378840Sobrien return scale; 377460519Sobrien} 377560519Sobrien 377660519Sobrienstatic int i386_displacement PARAMS ((char *, char *)); 377760519Sobrien 377860519Sobrienstatic int 377960519Sobrieni386_displacement (disp_start, disp_end) 378060519Sobrien char *disp_start; 378160519Sobrien char *disp_end; 378260519Sobrien{ 378394546Sobrien expressionS *exp; 378460519Sobrien segT exp_seg = 0; 378560519Sobrien char *save_input_line_pointer; 378678840Sobrien#ifndef LEX_AT 378778840Sobrien char *gotfree_input_line; 378878840Sobrien#endif 378960519Sobrien int bigdisp = Disp32; 379060519Sobrien 379191054Sobrien if (flag_code == CODE_64BIT) 379291054Sobrien { 379394546Sobrien if (i.prefix[ADDR_PREFIX] == 0) 379494546Sobrien bigdisp = Disp64; 379591054Sobrien } 379691054Sobrien else if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0)) 379760519Sobrien bigdisp = Disp16; 379860519Sobrien i.types[this_operand] |= bigdisp; 379960519Sobrien 380060519Sobrien exp = &disp_expressions[i.disp_operands]; 380160519Sobrien i.op[this_operand].disps = exp; 380260519Sobrien i.disp_operands++; 380360519Sobrien save_input_line_pointer = input_line_pointer; 380460519Sobrien input_line_pointer = disp_start; 380560519Sobrien END_STRING_AND_SAVE (disp_end); 380660519Sobrien 380760519Sobrien#ifndef GCC_ASM_O_HACK 380860519Sobrien#define GCC_ASM_O_HACK 0 380960519Sobrien#endif 381060519Sobrien#if GCC_ASM_O_HACK 381160519Sobrien END_STRING_AND_SAVE (disp_end + 1); 381260519Sobrien if ((i.types[this_operand] & BaseIndex) != 0 381360519Sobrien && displacement_string_end[-1] == '+') 381460519Sobrien { 381560519Sobrien /* This hack is to avoid a warning when using the "o" 381660519Sobrien constraint within gcc asm statements. 381760519Sobrien For instance: 381860519Sobrien 381960519Sobrien #define _set_tssldt_desc(n,addr,limit,type) \ 382060519Sobrien __asm__ __volatile__ ( \ 382160519Sobrien "movw %w2,%0\n\t" \ 382260519Sobrien "movw %w1,2+%0\n\t" \ 382360519Sobrien "rorl $16,%1\n\t" \ 382460519Sobrien "movb %b1,4+%0\n\t" \ 382560519Sobrien "movb %4,5+%0\n\t" \ 382660519Sobrien "movb $0,6+%0\n\t" \ 382760519Sobrien "movb %h1,7+%0\n\t" \ 382860519Sobrien "rorl $16,%1" \ 382960519Sobrien : "=o"(*(n)) : "q" (addr), "ri"(limit), "i"(type)) 383060519Sobrien 383160519Sobrien This works great except that the output assembler ends 383260519Sobrien up looking a bit weird if it turns out that there is 383360519Sobrien no offset. You end up producing code that looks like: 383460519Sobrien 383560519Sobrien #APP 383660519Sobrien movw $235,(%eax) 383760519Sobrien movw %dx,2+(%eax) 383860519Sobrien rorl $16,%edx 383960519Sobrien movb %dl,4+(%eax) 384060519Sobrien movb $137,5+(%eax) 384160519Sobrien movb $0,6+(%eax) 384260519Sobrien movb %dh,7+(%eax) 384360519Sobrien rorl $16,%edx 384460519Sobrien #NO_APP 384560519Sobrien 384677311Sobrien So here we provide the missing zero. */ 384760519Sobrien 384860519Sobrien *displacement_string_end = '0'; 384960519Sobrien } 385060519Sobrien#endif 385160519Sobrien#ifndef LEX_AT 385278840Sobrien gotfree_input_line = lex_got (&i.reloc[this_operand], NULL); 385378840Sobrien if (gotfree_input_line) 385478840Sobrien input_line_pointer = gotfree_input_line; 385578840Sobrien#endif 385660519Sobrien 385778840Sobrien exp_seg = expression (exp); 385860519Sobrien 385978840Sobrien SKIP_WHITESPACE (); 386078840Sobrien if (*input_line_pointer) 386178840Sobrien as_bad (_("junk `%s' after expression"), input_line_pointer); 386278840Sobrien#if GCC_ASM_O_HACK 386378840Sobrien RESTORE_END_STRING (disp_end + 1); 386460519Sobrien#endif 386578840Sobrien RESTORE_END_STRING (disp_end); 386678840Sobrien input_line_pointer = save_input_line_pointer; 386778840Sobrien#ifndef LEX_AT 386878840Sobrien if (gotfree_input_line) 386978840Sobrien free (gotfree_input_line); 387078840Sobrien#endif 387160519Sobrien 387260519Sobrien /* We do this to make sure that the section symbol is in 387360519Sobrien the symbol table. We will ultimately change the relocation 387477311Sobrien to be relative to the beginning of the section. */ 387578840Sobrien if (i.reloc[this_operand] == BFD_RELOC_386_GOTOFF 387678840Sobrien || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL) 387760519Sobrien { 387878840Sobrien if (exp->X_op != O_symbol) 387978840Sobrien { 388078840Sobrien as_bad (_("bad expression used with @%s"), 388178840Sobrien (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL 388278840Sobrien ? "GOTPCREL" 388378840Sobrien : "GOTOFF")); 388478840Sobrien return 0; 388578840Sobrien } 388678840Sobrien 388777311Sobrien if (S_IS_LOCAL (exp->X_add_symbol) 388860519Sobrien && S_GET_SEGMENT (exp->X_add_symbol) != undefined_section) 388960519Sobrien section_symbol (S_GET_SEGMENT (exp->X_add_symbol)); 389060519Sobrien exp->X_op = O_subtract; 389160519Sobrien exp->X_op_symbol = GOT_symbol; 389278840Sobrien if (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL) 389394546Sobrien i.reloc[this_operand] = BFD_RELOC_32_PCREL; 389477311Sobrien else 389594546Sobrien i.reloc[this_operand] = BFD_RELOC_32; 389660519Sobrien } 389760519Sobrien 389860519Sobrien if (exp->X_op == O_absent || exp->X_op == O_big) 389960519Sobrien { 390077311Sobrien /* Missing or bad expr becomes absolute 0. */ 390160519Sobrien as_bad (_("missing or invalid displacement expression `%s' taken as 0"), 390260519Sobrien disp_start); 390360519Sobrien exp->X_op = O_constant; 390460519Sobrien exp->X_add_number = 0; 390560519Sobrien exp->X_add_symbol = (symbolS *) 0; 390660519Sobrien exp->X_op_symbol = (symbolS *) 0; 390760519Sobrien } 390860519Sobrien 390960519Sobrien#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT)) 391077311Sobrien if (exp->X_op != O_constant 391177311Sobrien && OUTPUT_FLAVOR == bfd_target_aout_flavour 3912104848Sobrien && exp_seg != absolute_section 391377311Sobrien && exp_seg != text_section 391477311Sobrien && exp_seg != data_section 391577311Sobrien && exp_seg != bss_section 3916104848Sobrien && exp_seg != undefined_section 3917130570Sobrien && !bfd_is_com_section (exp_seg)) 391860519Sobrien { 391960519Sobrien as_bad (_("unimplemented segment %s in operand"), exp_seg->name); 392060519Sobrien return 0; 392160519Sobrien } 392260519Sobrien#endif 392377311Sobrien else if (flag_code == CODE_64BIT) 392477311Sobrien i.types[this_operand] |= Disp32S | Disp32; 392560519Sobrien return 1; 392660519Sobrien} 392760519Sobrien 392877311Sobrienstatic int i386_index_check PARAMS ((const char *)); 392960519Sobrien 393077311Sobrien/* Make sure the memory operand we've been dealt is valid. 393177311Sobrien Return 1 on success, 0 on a failure. */ 393277311Sobrien 393360519Sobrienstatic int 393477311Sobrieni386_index_check (operand_string) 393577311Sobrien const char *operand_string; 393660519Sobrien{ 393777311Sobrien int ok; 393877311Sobrien#if INFER_ADDR_PREFIX 393977311Sobrien int fudged = 0; 394060519Sobrien 394177311Sobrien tryprefix: 394277311Sobrien#endif 394377311Sobrien ok = 1; 394477311Sobrien if (flag_code == CODE_64BIT) 394560519Sobrien { 394691054Sobrien if (i.prefix[ADDR_PREFIX] == 0) 394791054Sobrien { 394891054Sobrien /* 64bit checks. */ 394991054Sobrien if ((i.base_reg 395091054Sobrien && ((i.base_reg->reg_type & Reg64) == 0) 395191054Sobrien && (i.base_reg->reg_type != BaseIndex 395291054Sobrien || i.index_reg)) 395391054Sobrien || (i.index_reg 395494546Sobrien && ((i.index_reg->reg_type & (Reg64 | BaseIndex)) 395594546Sobrien != (Reg64 | BaseIndex)))) 395691054Sobrien ok = 0; 395791054Sobrien } 395891054Sobrien else 395991054Sobrien { 396091054Sobrien /* 32bit checks. */ 396191054Sobrien if ((i.base_reg 396291054Sobrien && (i.base_reg->reg_type & (Reg32 | RegRex)) != Reg32) 396391054Sobrien || (i.index_reg 396494546Sobrien && ((i.index_reg->reg_type & (Reg32 | BaseIndex | RegRex)) 396594546Sobrien != (Reg32 | BaseIndex)))) 396691054Sobrien ok = 0; 396791054Sobrien } 396860519Sobrien } 396960519Sobrien else 397060519Sobrien { 397177311Sobrien if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0)) 397260519Sobrien { 397377311Sobrien /* 16bit checks. */ 397477311Sobrien if ((i.base_reg 397594546Sobrien && ((i.base_reg->reg_type & (Reg16 | BaseIndex | RegRex)) 397694546Sobrien != (Reg16 | BaseIndex))) 397777311Sobrien || (i.index_reg 397894546Sobrien && (((i.index_reg->reg_type & (Reg16 | BaseIndex)) 397994546Sobrien != (Reg16 | BaseIndex)) 398094546Sobrien || !(i.base_reg 398194546Sobrien && i.base_reg->reg_num < 6 398294546Sobrien && i.index_reg->reg_num >= 6 398394546Sobrien && i.log2_scale_factor == 0)))) 398477311Sobrien ok = 0; 398560519Sobrien } 398677311Sobrien else 398777311Sobrien { 398877311Sobrien /* 32bit checks. */ 398977311Sobrien if ((i.base_reg 399077311Sobrien && (i.base_reg->reg_type & (Reg32 | RegRex)) != Reg32) 399177311Sobrien || (i.index_reg 399294546Sobrien && ((i.index_reg->reg_type & (Reg32 | BaseIndex | RegRex)) 399394546Sobrien != (Reg32 | BaseIndex)))) 399477311Sobrien ok = 0; 399577311Sobrien } 399660519Sobrien } 399777311Sobrien if (!ok) 399860519Sobrien { 399960519Sobrien#if INFER_ADDR_PREFIX 400077311Sobrien if (flag_code != CODE_64BIT 400177311Sobrien && i.prefix[ADDR_PREFIX] == 0 && stackop_size != '\0') 400260519Sobrien { 400360519Sobrien i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE; 400460519Sobrien i.prefixes += 1; 400560519Sobrien /* Change the size of any displacement too. At most one of 400660519Sobrien Disp16 or Disp32 is set. 400760519Sobrien FIXME. There doesn't seem to be any real need for separate 400860519Sobrien Disp16 and Disp32 flags. The same goes for Imm16 and Imm32. 400977311Sobrien Removing them would probably clean up the code quite a lot. */ 401094546Sobrien if (i.types[this_operand] & (Disp16 | Disp32)) 401194546Sobrien i.types[this_operand] ^= (Disp16 | Disp32); 401260519Sobrien fudged = 1; 401360519Sobrien goto tryprefix; 401460519Sobrien } 401560519Sobrien if (fudged) 401660519Sobrien as_bad (_("`%s' is not a valid base/index expression"), 401760519Sobrien operand_string); 401860519Sobrien else 401960519Sobrien#endif 402060519Sobrien as_bad (_("`%s' is not a valid %s bit base/index expression"), 402160519Sobrien operand_string, 402277311Sobrien flag_code_names[flag_code]); 402360519Sobrien return 0; 402460519Sobrien } 402560519Sobrien return 1; 402660519Sobrien} 402760519Sobrien 402833965Sjdp/* Parse OPERAND_STRING into the i386_insn structure I. Returns non-zero 402977311Sobrien on error. */ 403033965Sjdp 403133965Sjdpstatic int 403233965Sjdpi386_operand (operand_string) 403333965Sjdp char *operand_string; 403433965Sjdp{ 403560519Sobrien const reg_entry *r; 403660519Sobrien char *end_op; 403760519Sobrien char *op_string = operand_string; 403833965Sjdp 403960519Sobrien if (is_space_char (*op_string)) 404060519Sobrien ++op_string; 404133965Sjdp 404233965Sjdp /* We check for an absolute prefix (differentiating, 404377311Sobrien for example, 'jmp pc_relative_label' from 'jmp *absolute_label'. */ 404433965Sjdp if (*op_string == ABSOLUTE_PREFIX) 404533965Sjdp { 404660519Sobrien ++op_string; 404760519Sobrien if (is_space_char (*op_string)) 404860519Sobrien ++op_string; 404933965Sjdp i.types[this_operand] |= JumpAbsolute; 405033965Sjdp } 405133965Sjdp 405277311Sobrien /* Check if operand is a register. */ 405360519Sobrien if ((*op_string == REGISTER_PREFIX || allow_naked_reg) 405460519Sobrien && (r = parse_register (op_string, &end_op)) != NULL) 405533965Sjdp { 405660519Sobrien /* Check for a segment override by searching for ':' after a 405760519Sobrien segment register. */ 405860519Sobrien op_string = end_op; 405960519Sobrien if (is_space_char (*op_string)) 406060519Sobrien ++op_string; 406160519Sobrien if (*op_string == ':' && (r->reg_type & (SReg2 | SReg3))) 406233965Sjdp { 406333965Sjdp switch (r->reg_num) 406433965Sjdp { 406533965Sjdp case 0: 406660519Sobrien i.seg[i.mem_operands] = &es; 406733965Sjdp break; 406833965Sjdp case 1: 406960519Sobrien i.seg[i.mem_operands] = &cs; 407033965Sjdp break; 407133965Sjdp case 2: 407260519Sobrien i.seg[i.mem_operands] = &ss; 407333965Sjdp break; 407433965Sjdp case 3: 407560519Sobrien i.seg[i.mem_operands] = &ds; 407633965Sjdp break; 407733965Sjdp case 4: 407860519Sobrien i.seg[i.mem_operands] = &fs; 407933965Sjdp break; 408033965Sjdp case 5: 408160519Sobrien i.seg[i.mem_operands] = &gs; 408233965Sjdp break; 408333965Sjdp } 408460519Sobrien 408560519Sobrien /* Skip the ':' and whitespace. */ 408660519Sobrien ++op_string; 408760519Sobrien if (is_space_char (*op_string)) 408860519Sobrien ++op_string; 408960519Sobrien 409060519Sobrien if (!is_digit_char (*op_string) 409160519Sobrien && !is_identifier_char (*op_string) 409260519Sobrien && *op_string != '(' 409360519Sobrien && *op_string != ABSOLUTE_PREFIX) 409433965Sjdp { 409560519Sobrien as_bad (_("bad memory operand `%s'"), op_string); 409633965Sjdp return 0; 409733965Sjdp } 409877311Sobrien /* Handle case of %es:*foo. */ 409933965Sjdp if (*op_string == ABSOLUTE_PREFIX) 410033965Sjdp { 410160519Sobrien ++op_string; 410260519Sobrien if (is_space_char (*op_string)) 410360519Sobrien ++op_string; 410433965Sjdp i.types[this_operand] |= JumpAbsolute; 410533965Sjdp } 410633965Sjdp goto do_memory_reference; 410733965Sjdp } 410860519Sobrien if (*op_string) 410960519Sobrien { 411060519Sobrien as_bad (_("junk `%s' after register"), op_string); 411160519Sobrien return 0; 411260519Sobrien } 411360519Sobrien i.types[this_operand] |= r->reg_type & ~BaseIndex; 411460519Sobrien i.op[this_operand].regs = r; 411533965Sjdp i.reg_operands++; 411633965Sjdp } 411760519Sobrien else if (*op_string == REGISTER_PREFIX) 411860519Sobrien { 411960519Sobrien as_bad (_("bad register name `%s'"), op_string); 412060519Sobrien return 0; 412160519Sobrien } 412233965Sjdp else if (*op_string == IMMEDIATE_PREFIX) 412377311Sobrien { 412460519Sobrien ++op_string; 412560519Sobrien if (i.types[this_operand] & JumpAbsolute) 412633965Sjdp { 412760519Sobrien as_bad (_("immediate operand illegal with absolute jump")); 412833965Sjdp return 0; 412933965Sjdp } 413060519Sobrien if (!i386_immediate (op_string)) 413160519Sobrien return 0; 413233965Sjdp } 413360519Sobrien else if (is_digit_char (*op_string) 413460519Sobrien || is_identifier_char (*op_string) 413577311Sobrien || *op_string == '(') 413633965Sjdp { 413777311Sobrien /* This is a memory reference of some sort. */ 413860519Sobrien char *base_string; 413933965Sjdp 414077311Sobrien /* Start and end of displacement string expression (if found). */ 414160519Sobrien char *displacement_string_start; 414260519Sobrien char *displacement_string_end; 414360519Sobrien 414433965Sjdp do_memory_reference: 414560519Sobrien if ((i.mem_operands == 1 414660519Sobrien && (current_templates->start->opcode_modifier & IsString) == 0) 414760519Sobrien || i.mem_operands == 2) 414833965Sjdp { 414960519Sobrien as_bad (_("too many memory references for `%s'"), 415060519Sobrien current_templates->start->name); 415133965Sjdp return 0; 415233965Sjdp } 415333965Sjdp 415433965Sjdp /* Check for base index form. We detect the base index form by 415533965Sjdp looking for an ')' at the end of the operand, searching 415633965Sjdp for the '(' matching it, and finding a REGISTER_PREFIX or ',' 415760519Sobrien after the '('. */ 415860519Sobrien base_string = op_string + strlen (op_string); 415960519Sobrien 416060519Sobrien --base_string; 416160519Sobrien if (is_space_char (*base_string)) 416260519Sobrien --base_string; 416360519Sobrien 416477311Sobrien /* If we only have a displacement, set-up for it to be parsed later. */ 416560519Sobrien displacement_string_start = op_string; 416660519Sobrien displacement_string_end = base_string + 1; 416760519Sobrien 416833965Sjdp if (*base_string == ')') 416933965Sjdp { 417060519Sobrien char *temp_string; 417133965Sjdp unsigned int parens_balanced = 1; 417233965Sjdp /* We've already checked that the number of left & right ()'s are 417377311Sobrien equal, so this loop will not be infinite. */ 417433965Sjdp do 417533965Sjdp { 417633965Sjdp base_string--; 417733965Sjdp if (*base_string == ')') 417833965Sjdp parens_balanced++; 417933965Sjdp if (*base_string == '(') 418033965Sjdp parens_balanced--; 418133965Sjdp } 418233965Sjdp while (parens_balanced); 418333965Sjdp 418460519Sobrien temp_string = base_string; 418533965Sjdp 418660519Sobrien /* Skip past '(' and whitespace. */ 418760519Sobrien ++base_string; 418860519Sobrien if (is_space_char (*base_string)) 418960519Sobrien ++base_string; 419033965Sjdp 419160519Sobrien if (*base_string == ',' 419260519Sobrien || ((*base_string == REGISTER_PREFIX || allow_naked_reg) 419360519Sobrien && (i.base_reg = parse_register (base_string, &end_op)) != NULL)) 419433965Sjdp { 419560519Sobrien displacement_string_end = temp_string; 419633965Sjdp 419760519Sobrien i.types[this_operand] |= BaseIndex; 419860519Sobrien 419960519Sobrien if (i.base_reg) 420033965Sjdp { 420160519Sobrien base_string = end_op; 420260519Sobrien if (is_space_char (*base_string)) 420360519Sobrien ++base_string; 420433965Sjdp } 420560519Sobrien 420660519Sobrien /* There may be an index reg or scale factor here. */ 420760519Sobrien if (*base_string == ',') 420833965Sjdp { 420960519Sobrien ++base_string; 421060519Sobrien if (is_space_char (*base_string)) 421160519Sobrien ++base_string; 421233965Sjdp 421360519Sobrien if ((*base_string == REGISTER_PREFIX || allow_naked_reg) 421460519Sobrien && (i.index_reg = parse_register (base_string, &end_op)) != NULL) 421560519Sobrien { 421660519Sobrien base_string = end_op; 421760519Sobrien if (is_space_char (*base_string)) 421860519Sobrien ++base_string; 421960519Sobrien if (*base_string == ',') 422060519Sobrien { 422160519Sobrien ++base_string; 422260519Sobrien if (is_space_char (*base_string)) 422360519Sobrien ++base_string; 422460519Sobrien } 422577311Sobrien else if (*base_string != ')') 422660519Sobrien { 422760519Sobrien as_bad (_("expecting `,' or `)' after index register in `%s'"), 422860519Sobrien operand_string); 422960519Sobrien return 0; 423060519Sobrien } 423160519Sobrien } 423260519Sobrien else if (*base_string == REGISTER_PREFIX) 423360519Sobrien { 423460519Sobrien as_bad (_("bad register name `%s'"), base_string); 423560519Sobrien return 0; 423660519Sobrien } 423733965Sjdp 423877311Sobrien /* Check for scale factor. */ 423978840Sobrien if (*base_string != ')') 424060519Sobrien { 424178840Sobrien char *end_scale = i386_scale (base_string); 424278840Sobrien 424378840Sobrien if (!end_scale) 424460519Sobrien return 0; 424533965Sjdp 424678840Sobrien base_string = end_scale; 424760519Sobrien if (is_space_char (*base_string)) 424860519Sobrien ++base_string; 424960519Sobrien if (*base_string != ')') 425060519Sobrien { 425160519Sobrien as_bad (_("expecting `)' after scale factor in `%s'"), 425260519Sobrien operand_string); 425360519Sobrien return 0; 425460519Sobrien } 425560519Sobrien } 425660519Sobrien else if (!i.index_reg) 425760519Sobrien { 425860519Sobrien as_bad (_("expecting index register or scale factor after `,'; got '%c'"), 425960519Sobrien *base_string); 426060519Sobrien return 0; 426160519Sobrien } 426233965Sjdp } 426360519Sobrien else if (*base_string != ')') 426433965Sjdp { 426560519Sobrien as_bad (_("expecting `,' or `)' after base register in `%s'"), 426660519Sobrien operand_string); 426733965Sjdp return 0; 426833965Sjdp } 426933965Sjdp } 427060519Sobrien else if (*base_string == REGISTER_PREFIX) 427133965Sjdp { 427260519Sobrien as_bad (_("bad register name `%s'"), base_string); 427360519Sobrien return 0; 427433965Sjdp } 427533965Sjdp } 427633965Sjdp 427760519Sobrien /* If there's an expression beginning the operand, parse it, 427860519Sobrien assuming displacement_string_start and 427960519Sobrien displacement_string_end are meaningful. */ 428060519Sobrien if (displacement_string_start != displacement_string_end) 428133965Sjdp { 428260519Sobrien if (!i386_displacement (displacement_string_start, 428360519Sobrien displacement_string_end)) 428460519Sobrien return 0; 428533965Sjdp } 428633965Sjdp 428760519Sobrien /* Special case for (%dx) while doing input/output op. */ 428860519Sobrien if (i.base_reg 428960519Sobrien && i.base_reg->reg_type == (Reg16 | InOutPortReg) 429060519Sobrien && i.index_reg == 0 429160519Sobrien && i.log2_scale_factor == 0 429260519Sobrien && i.seg[i.mem_operands] == 0 429360519Sobrien && (i.types[this_operand] & Disp) == 0) 429433965Sjdp { 429560519Sobrien i.types[this_operand] = InOutPortReg; 429633965Sjdp return 1; 429733965Sjdp } 429860519Sobrien 429960519Sobrien if (i386_index_check (operand_string) == 0) 430060519Sobrien return 0; 430160519Sobrien i.mem_operands++; 430233965Sjdp } 430333965Sjdp else 430477311Sobrien { 430577311Sobrien /* It's not a memory operand; argh! */ 430660519Sobrien as_bad (_("invalid char %s beginning operand %d `%s'"), 430760519Sobrien output_invalid (*op_string), 430860519Sobrien this_operand + 1, 430933965Sjdp op_string); 431033965Sjdp return 0; 431133965Sjdp } 431277311Sobrien return 1; /* Normal return. */ 431333965Sjdp} 431433965Sjdp 431561847Sobrien/* md_estimate_size_before_relax() 431661847Sobrien 431761847Sobrien Called just before relax() for rs_machine_dependent frags. The x86 431861847Sobrien assembler uses these frags to handle variable size jump 431961847Sobrien instructions. 432061847Sobrien 432161847Sobrien Any symbol that is now undefined will not become defined. 432261847Sobrien Return the correct fr_subtype in the frag. 432361847Sobrien Return the initial "guess for variable size of frag" to caller. 432461847Sobrien The guess is actually the growth beyond the fixed part. Whatever 432561847Sobrien we do to grow the fixed or variable part contributes to our 432661847Sobrien returned value. */ 432761847Sobrien 432833965Sjdpint 432933965Sjdpmd_estimate_size_before_relax (fragP, segment) 433094546Sobrien fragS *fragP; 433194546Sobrien segT segment; 433233965Sjdp{ 433360519Sobrien /* We've already got fragP->fr_subtype right; all we have to do is 433461847Sobrien check for un-relaxable symbols. On an ELF system, we can't relax 433561847Sobrien an externally visible symbol, because it may be overridden by a 433661847Sobrien shared library. */ 433761847Sobrien if (S_GET_SEGMENT (fragP->fr_symbol) != segment 433877311Sobrien#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 4339104848Sobrien || (OUTPUT_FLAVOR == bfd_target_elf_flavour 4340104848Sobrien && (S_IS_EXTERNAL (fragP->fr_symbol) 4341104848Sobrien || S_IS_WEAK (fragP->fr_symbol))) 434261847Sobrien#endif 434361847Sobrien ) 434433965Sjdp { 434561847Sobrien /* Symbol is undefined in this segment, or we need to keep a 434661847Sobrien reloc so that weak symbols can be overridden. */ 434761847Sobrien int size = (fragP->fr_subtype & CODE16) ? 2 : 4; 4348130570Sobrien enum bfd_reloc_code_real reloc_type; 434961847Sobrien unsigned char *opcode; 435061847Sobrien int old_fr_fix; 435160519Sobrien 435261847Sobrien if (fragP->fr_var != NO_RELOC) 435361847Sobrien reloc_type = fragP->fr_var; 435461847Sobrien else if (size == 2) 435560519Sobrien reloc_type = BFD_RELOC_16_PCREL; 435660519Sobrien else 435760519Sobrien reloc_type = BFD_RELOC_32_PCREL; 435860519Sobrien 435961847Sobrien old_fr_fix = fragP->fr_fix; 436061847Sobrien opcode = (unsigned char *) fragP->fr_opcode; 436161847Sobrien 436278840Sobrien switch (TYPE_FROM_RELAX_STATE (fragP->fr_subtype)) 436333965Sjdp { 436478840Sobrien case UNCOND_JUMP: 436578840Sobrien /* Make jmp (0xeb) a (d)word displacement jump. */ 436677311Sobrien opcode[0] = 0xe9; 436760519Sobrien fragP->fr_fix += size; 436899468Sobrien fix_new (fragP, old_fr_fix, size, 436999468Sobrien fragP->fr_symbol, 437099468Sobrien fragP->fr_offset, 1, 437199468Sobrien reloc_type); 437233965Sjdp break; 437333965Sjdp 437478840Sobrien case COND_JUMP86: 437599468Sobrien if (size == 2 437699468Sobrien && (!no_cond_jump_promotion || fragP->fr_var != NO_RELOC)) 437778840Sobrien { 437878840Sobrien /* Negate the condition, and branch past an 437978840Sobrien unconditional jump. */ 438078840Sobrien opcode[0] ^= 1; 438178840Sobrien opcode[1] = 3; 438278840Sobrien /* Insert an unconditional jump. */ 438378840Sobrien opcode[2] = 0xe9; 438478840Sobrien /* We added two extra opcode bytes, and have a two byte 438578840Sobrien offset. */ 438678840Sobrien fragP->fr_fix += 2 + 2; 438799468Sobrien fix_new (fragP, old_fr_fix + 2, 2, 438899468Sobrien fragP->fr_symbol, 438999468Sobrien fragP->fr_offset, 1, 439099468Sobrien reloc_type); 439178840Sobrien break; 439278840Sobrien } 439378840Sobrien /* Fall through. */ 439478840Sobrien 439578840Sobrien case COND_JUMP: 439699468Sobrien if (no_cond_jump_promotion && fragP->fr_var == NO_RELOC) 439799468Sobrien { 4398104848Sobrien fixS *fixP; 4399104848Sobrien 440099468Sobrien fragP->fr_fix += 1; 4401104848Sobrien fixP = fix_new (fragP, old_fr_fix, 1, 4402104848Sobrien fragP->fr_symbol, 4403104848Sobrien fragP->fr_offset, 1, 4404104848Sobrien BFD_RELOC_8_PCREL); 4405104848Sobrien fixP->fx_signed = 1; 440699468Sobrien break; 440799468Sobrien } 440878840Sobrien 440960519Sobrien /* This changes the byte-displacement jump 0x7N 441078840Sobrien to the (d)word-displacement jump 0x0f,0x8N. */ 441133965Sjdp opcode[1] = opcode[0] + 0x10; 441260519Sobrien opcode[0] = TWO_BYTE_OPCODE_ESCAPE; 441377311Sobrien /* We've added an opcode byte. */ 441477311Sobrien fragP->fr_fix += 1 + size; 441599468Sobrien fix_new (fragP, old_fr_fix + 1, size, 441699468Sobrien fragP->fr_symbol, 441799468Sobrien fragP->fr_offset, 1, 441899468Sobrien reloc_type); 441933965Sjdp break; 442078840Sobrien 442178840Sobrien default: 442278840Sobrien BAD_CASE (fragP->fr_subtype); 442378840Sobrien break; 442433965Sjdp } 442533965Sjdp frag_wane (fragP); 442661847Sobrien return fragP->fr_fix - old_fr_fix; 442733965Sjdp } 442878840Sobrien 442978840Sobrien /* Guess size depending on current relax state. Initially the relax 443078840Sobrien state will correspond to a short jump and we return 1, because 443178840Sobrien the variable part of the frag (the branch offset) is one byte 443278840Sobrien long. However, we can relax a section more than once and in that 443378840Sobrien case we must either set fr_subtype back to the unrelaxed state, 443478840Sobrien or return the value for the appropriate branch. */ 443578840Sobrien return md_relax_table[fragP->fr_subtype].rlx_length; 443661847Sobrien} 443761847Sobrien 443877311Sobrien/* Called after relax() is finished. 443977311Sobrien 444077311Sobrien In: Address of frag. 444177311Sobrien fr_type == rs_machine_dependent. 444277311Sobrien fr_subtype is what the address relaxed to. 444377311Sobrien 444477311Sobrien Out: Any fixSs and constants are set up. 444577311Sobrien Caller will turn frag into a ".space 0". */ 444677311Sobrien 444733965Sjdpvoid 444833965Sjdpmd_convert_frag (abfd, sec, fragP) 444960519Sobrien bfd *abfd ATTRIBUTE_UNUSED; 445060519Sobrien segT sec ATTRIBUTE_UNUSED; 445194546Sobrien fragS *fragP; 445233965Sjdp{ 445394546Sobrien unsigned char *opcode; 445433965Sjdp unsigned char *where_to_put_displacement = NULL; 445577311Sobrien offsetT target_address; 445677311Sobrien offsetT opcode_address; 445733965Sjdp unsigned int extension = 0; 445877311Sobrien offsetT displacement_from_opcode_start; 445933965Sjdp 446033965Sjdp opcode = (unsigned char *) fragP->fr_opcode; 446133965Sjdp 446277311Sobrien /* Address we want to reach in file space. */ 446333965Sjdp target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset; 446433965Sjdp 446577311Sobrien /* Address opcode resides at in file space. */ 446633965Sjdp opcode_address = fragP->fr_address + fragP->fr_fix; 446733965Sjdp 446877311Sobrien /* Displacement from opcode start to fill into instruction. */ 446933965Sjdp displacement_from_opcode_start = target_address - opcode_address; 447033965Sjdp 447178840Sobrien if ((fragP->fr_subtype & BIG) == 0) 447233965Sjdp { 447377311Sobrien /* Don't have to change opcode. */ 447477311Sobrien extension = 1; /* 1 opcode + 1 displacement */ 447533965Sjdp where_to_put_displacement = &opcode[1]; 447678840Sobrien } 447778840Sobrien else 447878840Sobrien { 447978840Sobrien if (no_cond_jump_promotion 448078840Sobrien && TYPE_FROM_RELAX_STATE (fragP->fr_subtype) != UNCOND_JUMP) 448178840Sobrien as_warn_where (fragP->fr_file, fragP->fr_line, _("long jump required")); 448233965Sjdp 448378840Sobrien switch (fragP->fr_subtype) 448478840Sobrien { 448578840Sobrien case ENCODE_RELAX_STATE (UNCOND_JUMP, BIG): 448678840Sobrien extension = 4; /* 1 opcode + 4 displacement */ 448778840Sobrien opcode[0] = 0xe9; 448878840Sobrien where_to_put_displacement = &opcode[1]; 448978840Sobrien break; 449033965Sjdp 449178840Sobrien case ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16): 449278840Sobrien extension = 2; /* 1 opcode + 2 displacement */ 449378840Sobrien opcode[0] = 0xe9; 449478840Sobrien where_to_put_displacement = &opcode[1]; 449578840Sobrien break; 449633965Sjdp 449778840Sobrien case ENCODE_RELAX_STATE (COND_JUMP, BIG): 449878840Sobrien case ENCODE_RELAX_STATE (COND_JUMP86, BIG): 449978840Sobrien extension = 5; /* 2 opcode + 4 displacement */ 450078840Sobrien opcode[1] = opcode[0] + 0x10; 450178840Sobrien opcode[0] = TWO_BYTE_OPCODE_ESCAPE; 450278840Sobrien where_to_put_displacement = &opcode[2]; 450378840Sobrien break; 450433965Sjdp 450578840Sobrien case ENCODE_RELAX_STATE (COND_JUMP, BIG16): 450678840Sobrien extension = 3; /* 2 opcode + 2 displacement */ 450778840Sobrien opcode[1] = opcode[0] + 0x10; 450878840Sobrien opcode[0] = TWO_BYTE_OPCODE_ESCAPE; 450978840Sobrien where_to_put_displacement = &opcode[2]; 451078840Sobrien break; 451133965Sjdp 451278840Sobrien case ENCODE_RELAX_STATE (COND_JUMP86, BIG16): 451378840Sobrien extension = 4; 451478840Sobrien opcode[0] ^= 1; 451578840Sobrien opcode[1] = 3; 451678840Sobrien opcode[2] = 0xe9; 451778840Sobrien where_to_put_displacement = &opcode[3]; 451878840Sobrien break; 451978840Sobrien 452078840Sobrien default: 452178840Sobrien BAD_CASE (fragP->fr_subtype); 452278840Sobrien break; 452378840Sobrien } 452433965Sjdp } 452578840Sobrien 452677311Sobrien /* Now put displacement after opcode. */ 452733965Sjdp md_number_to_chars ((char *) where_to_put_displacement, 452833965Sjdp (valueT) (displacement_from_opcode_start - extension), 452978840Sobrien DISP_SIZE_FROM_RELAX_STATE (fragP->fr_subtype)); 453033965Sjdp fragP->fr_fix += extension; 453133965Sjdp} 453233965Sjdp 453377311Sobrien/* Size of byte displacement jmp. */ 453477311Sobrienint md_short_jump_size = 2; 453533965Sjdp 453677311Sobrien/* Size of dword displacement jmp. */ 453777311Sobrienint md_long_jump_size = 5; 453833965Sjdp 453977311Sobrien/* Size of relocation record. */ 454077311Sobrienconst int md_reloc_size = 8; 454177311Sobrien 454233965Sjdpvoid 454333965Sjdpmd_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) 454433965Sjdp char *ptr; 454533965Sjdp addressT from_addr, to_addr; 454660519Sobrien fragS *frag ATTRIBUTE_UNUSED; 454760519Sobrien symbolS *to_symbol ATTRIBUTE_UNUSED; 454833965Sjdp{ 454977311Sobrien offsetT offset; 455033965Sjdp 455133965Sjdp offset = to_addr - (from_addr + 2); 455277311Sobrien /* Opcode for byte-disp jump. */ 455377311Sobrien md_number_to_chars (ptr, (valueT) 0xeb, 1); 455433965Sjdp md_number_to_chars (ptr + 1, (valueT) offset, 1); 455533965Sjdp} 455633965Sjdp 455733965Sjdpvoid 455833965Sjdpmd_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) 455933965Sjdp char *ptr; 456033965Sjdp addressT from_addr, to_addr; 456177311Sobrien fragS *frag ATTRIBUTE_UNUSED; 456277311Sobrien symbolS *to_symbol ATTRIBUTE_UNUSED; 456333965Sjdp{ 456477311Sobrien offsetT offset; 456533965Sjdp 456677311Sobrien offset = to_addr - (from_addr + 5); 456777311Sobrien md_number_to_chars (ptr, (valueT) 0xe9, 1); 456877311Sobrien md_number_to_chars (ptr + 1, (valueT) offset, 4); 456933965Sjdp} 457033965Sjdp 457133965Sjdp/* Apply a fixup (fixS) to segment data, once it has been determined 457233965Sjdp by our caller that we have all the info we need to fix it up. 457333965Sjdp 457433965Sjdp On the 386, immediates, displacements, and data pointers are all in 457533965Sjdp the same (little-endian) format, so we don't need to care about which 457633965Sjdp we are handling. */ 457733965Sjdp 457889867Sobrienvoid 457989867Sobrienmd_apply_fix3 (fixP, valP, seg) 458077311Sobrien /* The fix we're to put in. */ 458177311Sobrien fixS *fixP; 458277311Sobrien /* Pointer to the value of the bits. */ 4583104848Sobrien valueT *valP; 458477311Sobrien /* Segment fix is from. */ 458577311Sobrien segT seg ATTRIBUTE_UNUSED; 458633965Sjdp{ 458789867Sobrien char *p = fixP->fx_where + fixP->fx_frag->fr_literal; 4588104848Sobrien valueT value = *valP; 458933965Sjdp 4590130570Sobrien#if !defined (TE_Mach) 459160519Sobrien if (fixP->fx_pcrel) 459233965Sjdp { 459360519Sobrien switch (fixP->fx_r_type) 459460519Sobrien { 459560519Sobrien default: 459660519Sobrien break; 459760519Sobrien 459860519Sobrien case BFD_RELOC_32: 459960519Sobrien fixP->fx_r_type = BFD_RELOC_32_PCREL; 460060519Sobrien break; 460160519Sobrien case BFD_RELOC_16: 460260519Sobrien fixP->fx_r_type = BFD_RELOC_16_PCREL; 460360519Sobrien break; 460460519Sobrien case BFD_RELOC_8: 460560519Sobrien fixP->fx_r_type = BFD_RELOC_8_PCREL; 460660519Sobrien break; 460760519Sobrien } 460860519Sobrien } 460960519Sobrien 4610130570Sobrien if (fixP->fx_addsy != NULL 4611104848Sobrien && (fixP->fx_r_type == BFD_RELOC_32_PCREL 4612104848Sobrien || fixP->fx_r_type == BFD_RELOC_16_PCREL 4613104848Sobrien || fixP->fx_r_type == BFD_RELOC_8_PCREL) 4614104848Sobrien && !use_rela_relocations) 461560519Sobrien { 4616104848Sobrien /* This is a hack. There should be a better way to handle this. 4617104848Sobrien This covers for the fact that bfd_install_relocation will 4618104848Sobrien subtract the current location (for partial_inplace, PC relative 4619104848Sobrien relocations); see more below. */ 462033965Sjdp#ifndef OBJ_AOUT 462138891Sjdp if (OUTPUT_FLAVOR == bfd_target_elf_flavour 462260519Sobrien#ifdef TE_PE 462360519Sobrien || OUTPUT_FLAVOR == bfd_target_coff_flavour 462460519Sobrien#endif 462560519Sobrien ) 462633965Sjdp value += fixP->fx_where + fixP->fx_frag->fr_address; 462733965Sjdp#endif 462833965Sjdp#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 462960519Sobrien if (OUTPUT_FLAVOR == bfd_target_elf_flavour) 463033965Sjdp { 4631130570Sobrien segT sym_seg = S_GET_SEGMENT (fixP->fx_addsy); 463260519Sobrien 4633130570Sobrien if ((sym_seg == seg 463460519Sobrien || (symbol_section_p (fixP->fx_addsy) 4635130570Sobrien && sym_seg != absolute_section)) 4636130570Sobrien && !generic_force_reloc (fixP)) 463760519Sobrien { 463860519Sobrien /* Yes, we add the values in twice. This is because 4639130570Sobrien bfd_install_relocation subtracts them out again. I think 4640130570Sobrien bfd_install_relocation is broken, but I don't dare change 464160519Sobrien it. FIXME. */ 464260519Sobrien value += fixP->fx_where + fixP->fx_frag->fr_address; 464360519Sobrien } 464433965Sjdp } 464533965Sjdp#endif 464638891Sjdp#if defined (OBJ_COFF) && defined (TE_PE) 464738891Sjdp /* For some reason, the PE format does not store a section 464860519Sobrien address offset for a PC relative symbol. */ 464938891Sjdp if (S_GET_SEGMENT (fixP->fx_addsy) != seg) 465038891Sjdp value += md_pcrel_from (fixP); 465138891Sjdp#endif 465233965Sjdp } 465333965Sjdp 465433965Sjdp /* Fix a few things - the dynamic linker expects certain values here, 4655130570Sobrien and we must not disappoint it. */ 465633965Sjdp#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 465733965Sjdp if (OUTPUT_FLAVOR == bfd_target_elf_flavour 465833965Sjdp && fixP->fx_addsy) 465977311Sobrien switch (fixP->fx_r_type) 466077311Sobrien { 466177311Sobrien case BFD_RELOC_386_PLT32: 466277311Sobrien case BFD_RELOC_X86_64_PLT32: 466377311Sobrien /* Make the jump instruction point to the address of the operand. At 466477311Sobrien runtime we merely add the offset to the actual PLT entry. */ 466577311Sobrien value = -4; 466677311Sobrien break; 466777311Sobrien 4668104848Sobrien case BFD_RELOC_386_TLS_GD: 4669104848Sobrien case BFD_RELOC_386_TLS_LDM: 4670104848Sobrien case BFD_RELOC_386_TLS_IE_32: 4671104848Sobrien case BFD_RELOC_386_TLS_IE: 4672104848Sobrien case BFD_RELOC_386_TLS_GOTIE: 4673130570Sobrien case BFD_RELOC_X86_64_TLSGD: 4674130570Sobrien case BFD_RELOC_X86_64_TLSLD: 4675130570Sobrien case BFD_RELOC_X86_64_GOTTPOFF: 4676130570Sobrien value = 0; /* Fully resolved at runtime. No addend. */ 4677130570Sobrien /* Fallthrough */ 4678130570Sobrien case BFD_RELOC_386_TLS_LE: 4679130570Sobrien case BFD_RELOC_386_TLS_LDO_32: 4680130570Sobrien case BFD_RELOC_386_TLS_LE_32: 4681130570Sobrien case BFD_RELOC_X86_64_DTPOFF32: 4682130570Sobrien case BFD_RELOC_X86_64_TPOFF32: 4683130570Sobrien S_SET_THREAD_LOCAL (fixP->fx_addsy); 4684130570Sobrien break; 4685130570Sobrien 4686130570Sobrien case BFD_RELOC_386_GOT32: 468777311Sobrien case BFD_RELOC_X86_64_GOT32: 468877311Sobrien value = 0; /* Fully resolved at runtime. No addend. */ 468977311Sobrien break; 469060519Sobrien 469177311Sobrien case BFD_RELOC_VTABLE_INHERIT: 469277311Sobrien case BFD_RELOC_VTABLE_ENTRY: 469377311Sobrien fixP->fx_done = 0; 469489867Sobrien return; 469577311Sobrien 469677311Sobrien default: 469777311Sobrien break; 469877311Sobrien } 469977311Sobrien#endif /* defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) */ 4700104848Sobrien *valP = value; 4701130570Sobrien#endif /* !defined (TE_Mach) */ 470277311Sobrien 470377311Sobrien /* Are we finished with this relocation now? */ 4704104848Sobrien if (fixP->fx_addsy == NULL) 470577311Sobrien fixP->fx_done = 1; 470677311Sobrien else if (use_rela_relocations) 470777311Sobrien { 470877311Sobrien fixP->fx_no_overflow = 1; 470999468Sobrien /* Remember value for tc_gen_reloc. */ 471099468Sobrien fixP->fx_addnumber = value; 471177311Sobrien value = 0; 471277311Sobrien } 4713130570Sobrien 471477311Sobrien md_number_to_chars (p, value, fixP->fx_size); 471533965Sjdp} 471633965Sjdp 471733965Sjdp#define MAX_LITTLENUMS 6 471833965Sjdp 471977311Sobrien/* Turn the string pointed to by litP into a floating point constant 472077311Sobrien of type TYPE, and emit the appropriate bytes. The number of 472177311Sobrien LITTLENUMS emitted is stored in *SIZEP. An error message is 472277311Sobrien returned, or NULL on OK. */ 472377311Sobrien 472433965Sjdpchar * 472533965Sjdpmd_atof (type, litP, sizeP) 472660519Sobrien int type; 472733965Sjdp char *litP; 472833965Sjdp int *sizeP; 472933965Sjdp{ 473033965Sjdp int prec; 473133965Sjdp LITTLENUM_TYPE words[MAX_LITTLENUMS]; 473233965Sjdp LITTLENUM_TYPE *wordP; 473333965Sjdp char *t; 473433965Sjdp 473533965Sjdp switch (type) 473633965Sjdp { 473733965Sjdp case 'f': 473833965Sjdp case 'F': 473933965Sjdp prec = 2; 474033965Sjdp break; 474133965Sjdp 474233965Sjdp case 'd': 474333965Sjdp case 'D': 474433965Sjdp prec = 4; 474533965Sjdp break; 474633965Sjdp 474733965Sjdp case 'x': 474833965Sjdp case 'X': 474933965Sjdp prec = 5; 475033965Sjdp break; 475133965Sjdp 475233965Sjdp default: 475333965Sjdp *sizeP = 0; 475460519Sobrien return _("Bad call to md_atof ()"); 475533965Sjdp } 475633965Sjdp t = atof_ieee (input_line_pointer, type, words); 475733965Sjdp if (t) 475833965Sjdp input_line_pointer = t; 475933965Sjdp 476033965Sjdp *sizeP = prec * sizeof (LITTLENUM_TYPE); 476133965Sjdp /* This loops outputs the LITTLENUMs in REVERSE order; in accord with 476233965Sjdp the bigendian 386. */ 476333965Sjdp for (wordP = words + prec - 1; prec--;) 476433965Sjdp { 476533965Sjdp md_number_to_chars (litP, (valueT) (*wordP--), sizeof (LITTLENUM_TYPE)); 476633965Sjdp litP += sizeof (LITTLENUM_TYPE); 476733965Sjdp } 476833965Sjdp return 0; 476933965Sjdp} 477033965Sjdp 477133965Sjdpchar output_invalid_buf[8]; 477233965Sjdp 477333965Sjdpstatic char * 477433965Sjdpoutput_invalid (c) 477560519Sobrien int c; 477633965Sjdp{ 477789867Sobrien if (ISPRINT (c)) 477833965Sjdp sprintf (output_invalid_buf, "'%c'", c); 477933965Sjdp else 478033965Sjdp sprintf (output_invalid_buf, "(0x%x)", (unsigned) c); 478133965Sjdp return output_invalid_buf; 478233965Sjdp} 478333965Sjdp 478460519Sobrien/* REG_STRING starts *before* REGISTER_PREFIX. */ 478560519Sobrien 478660519Sobrienstatic const reg_entry * 478760519Sobrienparse_register (reg_string, end_op) 478833965Sjdp char *reg_string; 478960519Sobrien char **end_op; 479033965Sjdp{ 479160519Sobrien char *s = reg_string; 479260519Sobrien char *p; 479360519Sobrien char reg_name_given[MAX_REG_NAME_SIZE + 1]; 479460519Sobrien const reg_entry *r; 479533965Sjdp 479660519Sobrien /* Skip possible REGISTER_PREFIX and possible whitespace. */ 479760519Sobrien if (*s == REGISTER_PREFIX) 479860519Sobrien ++s; 479960519Sobrien 480060519Sobrien if (is_space_char (*s)) 480160519Sobrien ++s; 480260519Sobrien 480360519Sobrien p = reg_name_given; 480460519Sobrien while ((*p++ = register_chars[(unsigned char) *s]) != '\0') 480533965Sjdp { 480633965Sjdp if (p >= reg_name_given + MAX_REG_NAME_SIZE) 480760519Sobrien return (const reg_entry *) NULL; 480860519Sobrien s++; 480933965Sjdp } 481060519Sobrien 481177311Sobrien /* For naked regs, make sure that we are not dealing with an identifier. 481277311Sobrien This prevents confusing an identifier like `eax_var' with register 481377311Sobrien `eax'. */ 481477311Sobrien if (allow_naked_reg && identifier_chars[(unsigned char) *s]) 481577311Sobrien return (const reg_entry *) NULL; 481677311Sobrien 481760519Sobrien *end_op = s; 481860519Sobrien 481960519Sobrien r = (const reg_entry *) hash_find (reg_hash, reg_name_given); 482060519Sobrien 482160519Sobrien /* Handle floating point regs, allowing spaces in the (i) part. */ 482277311Sobrien if (r == i386_regtab /* %st is first entry of table */) 482360519Sobrien { 482460519Sobrien if (is_space_char (*s)) 482560519Sobrien ++s; 482660519Sobrien if (*s == '(') 482760519Sobrien { 482860519Sobrien ++s; 482960519Sobrien if (is_space_char (*s)) 483060519Sobrien ++s; 483160519Sobrien if (*s >= '0' && *s <= '7') 483260519Sobrien { 483360519Sobrien r = &i386_float_regtab[*s - '0']; 483460519Sobrien ++s; 483560519Sobrien if (is_space_char (*s)) 483660519Sobrien ++s; 483760519Sobrien if (*s == ')') 483860519Sobrien { 483960519Sobrien *end_op = s + 1; 484060519Sobrien return r; 484160519Sobrien } 484260519Sobrien } 484377311Sobrien /* We have "%st(" then garbage. */ 484460519Sobrien return (const reg_entry *) NULL; 484560519Sobrien } 484660519Sobrien } 484760519Sobrien 484885824Sobrien if (r != NULL 484994546Sobrien && (r->reg_flags & (RegRex64 | RegRex)) != 0 485085824Sobrien && flag_code != CODE_64BIT) 485185824Sobrien { 485285824Sobrien return (const reg_entry *) NULL; 485385824Sobrien } 485485824Sobrien 485560519Sobrien return r; 485633965Sjdp} 485733965Sjdp 485860519Sobrien#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 4859130570Sobrienconst char *md_shortopts = "kVQ:sqn"; 486033965Sjdp#else 4861130570Sobrienconst char *md_shortopts = "qn"; 486233965Sjdp#endif 486377311Sobrien 486433965Sjdpstruct option md_longopts[] = { 486577311Sobrien#define OPTION_32 (OPTION_MD_BASE + 0) 486677311Sobrien {"32", no_argument, NULL, OPTION_32}, 486777311Sobrien#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 486877311Sobrien#define OPTION_64 (OPTION_MD_BASE + 1) 486977311Sobrien {"64", no_argument, NULL, OPTION_64}, 487077311Sobrien#endif 487133965Sjdp {NULL, no_argument, NULL, 0} 487233965Sjdp}; 487360519Sobriensize_t md_longopts_size = sizeof (md_longopts); 487433965Sjdp 487533965Sjdpint 487633965Sjdpmd_parse_option (c, arg) 487733965Sjdp int c; 487860519Sobrien char *arg ATTRIBUTE_UNUSED; 487933965Sjdp{ 488033965Sjdp switch (c) 488133965Sjdp { 4882130570Sobrien case 'n': 4883130570Sobrien optimize_align_code = 0; 4884130570Sobrien break; 4885130570Sobrien 488677311Sobrien case 'q': 488777311Sobrien quiet_warnings = 1; 488833965Sjdp break; 488933965Sjdp 489033965Sjdp#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 489177311Sobrien /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section 489277311Sobrien should be emitted or not. FIXME: Not implemented. */ 489377311Sobrien case 'Q': 489433965Sjdp break; 489533965Sjdp 489633965Sjdp /* -V: SVR4 argument to print version ID. */ 489733965Sjdp case 'V': 489833965Sjdp print_version_id (); 489933965Sjdp break; 490033965Sjdp 490177311Sobrien /* -k: Ignore for FreeBSD compatibility. */ 490277311Sobrien case 'k': 490333965Sjdp break; 490460519Sobrien 490560519Sobrien case 's': 490660519Sobrien /* -s: On i386 Solaris, this tells the native assembler to use 490794546Sobrien .stab instead of .stab.excl. We always use .stab anyhow. */ 490860519Sobrien break; 490960519Sobrien 491077311Sobrien case OPTION_64: 491177311Sobrien { 491277311Sobrien const char **list, **l; 491377311Sobrien 491477311Sobrien list = bfd_target_list (); 491577311Sobrien for (l = list; *l != NULL; l++) 491677311Sobrien if (strcmp (*l, "elf64-x86-64") == 0) 491777311Sobrien { 491877311Sobrien default_arch = "x86_64"; 491977311Sobrien break; 492077311Sobrien } 492177311Sobrien if (*l == NULL) 492277311Sobrien as_fatal (_("No compiled in support for x86_64")); 492377311Sobrien free (list); 492477311Sobrien } 492560519Sobrien break; 492633965Sjdp#endif 492733965Sjdp 492877311Sobrien case OPTION_32: 492977311Sobrien default_arch = "i386"; 493077311Sobrien break; 493177311Sobrien 493233965Sjdp default: 493333965Sjdp return 0; 493433965Sjdp } 493533965Sjdp return 1; 493633965Sjdp} 493733965Sjdp 493833965Sjdpvoid 493933965Sjdpmd_show_usage (stream) 494033965Sjdp FILE *stream; 494133965Sjdp{ 494260519Sobrien#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 494360519Sobrien fprintf (stream, _("\ 494477311Sobrien -Q ignored\n\ 494577311Sobrien -V print assembler version number\n\ 494677311Sobrien -k ignored\n\ 4947130570Sobrien -n Do not optimize code alignment\n\ 494877311Sobrien -q quieten some warnings\n\ 494977311Sobrien -s ignored\n")); 495077311Sobrien#else 495177311Sobrien fprintf (stream, _("\ 4952130570Sobrien -n Do not optimize code alignment\n\ 495377311Sobrien -q quieten some warnings\n")); 495460519Sobrien#endif 495533965Sjdp} 495633965Sjdp 495777311Sobrien#if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \ 495877311Sobrien || defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) 495933965Sjdp 496033965Sjdp/* Pick the target format to use. */ 496133965Sjdp 496277311Sobrienconst char * 496333965Sjdpi386_target_format () 496433965Sjdp{ 496577311Sobrien if (!strcmp (default_arch, "x86_64")) 496677311Sobrien set_code_flag (CODE_64BIT); 496777311Sobrien else if (!strcmp (default_arch, "i386")) 496877311Sobrien set_code_flag (CODE_32BIT); 496977311Sobrien else 497077311Sobrien as_fatal (_("Unknown architecture")); 497133965Sjdp switch (OUTPUT_FLAVOR) 497233965Sjdp { 497360519Sobrien#ifdef OBJ_MAYBE_AOUT 497460519Sobrien case bfd_target_aout_flavour: 497577311Sobrien return AOUT_TARGET_FORMAT; 497660519Sobrien#endif 497760519Sobrien#ifdef OBJ_MAYBE_COFF 497833965Sjdp case bfd_target_coff_flavour: 497933965Sjdp return "coff-i386"; 498060519Sobrien#endif 498177311Sobrien#if defined (OBJ_MAYBE_ELF) || defined (OBJ_ELF) 498233965Sjdp case bfd_target_elf_flavour: 498377311Sobrien { 498477311Sobrien if (flag_code == CODE_64BIT) 498577311Sobrien use_rela_relocations = 1; 4986104848Sobrien return flag_code == CODE_64BIT ? "elf64-x86-64" : ELF_TARGET_FORMAT; 498777311Sobrien } 498860519Sobrien#endif 498933965Sjdp default: 499033965Sjdp abort (); 499133965Sjdp return NULL; 499233965Sjdp } 499333965Sjdp} 499433965Sjdp 499577311Sobrien#endif /* OBJ_MAYBE_ more than one */ 499689867Sobrien 499789867Sobrien#if (defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) 499889867Sobrienvoid i386_elf_emit_arch_note () 499989867Sobrien{ 500089867Sobrien if (OUTPUT_FLAVOR == bfd_target_elf_flavour 500189867Sobrien && cpu_arch_name != NULL) 500289867Sobrien { 500389867Sobrien char *p; 500489867Sobrien asection *seg = now_seg; 500589867Sobrien subsegT subseg = now_subseg; 500689867Sobrien Elf_Internal_Note i_note; 500789867Sobrien Elf_External_Note e_note; 500889867Sobrien asection *note_secp; 500989867Sobrien int len; 501089867Sobrien 501189867Sobrien /* Create the .note section. */ 501289867Sobrien note_secp = subseg_new (".note", 0); 501389867Sobrien bfd_set_section_flags (stdoutput, 501489867Sobrien note_secp, 501589867Sobrien SEC_HAS_CONTENTS | SEC_READONLY); 501689867Sobrien 501789867Sobrien /* Process the arch string. */ 501889867Sobrien len = strlen (cpu_arch_name); 501989867Sobrien 502089867Sobrien i_note.namesz = len + 1; 502189867Sobrien i_note.descsz = 0; 502289867Sobrien i_note.type = NT_ARCH; 502389867Sobrien p = frag_more (sizeof (e_note.namesz)); 502489867Sobrien md_number_to_chars (p, (valueT) i_note.namesz, sizeof (e_note.namesz)); 502589867Sobrien p = frag_more (sizeof (e_note.descsz)); 502689867Sobrien md_number_to_chars (p, (valueT) i_note.descsz, sizeof (e_note.descsz)); 502789867Sobrien p = frag_more (sizeof (e_note.type)); 502889867Sobrien md_number_to_chars (p, (valueT) i_note.type, sizeof (e_note.type)); 502989867Sobrien p = frag_more (len + 1); 503089867Sobrien strcpy (p, cpu_arch_name); 503189867Sobrien 503289867Sobrien frag_align (2, 0, 0); 503389867Sobrien 503489867Sobrien subseg_set (seg, subseg); 503589867Sobrien } 503689867Sobrien} 503789867Sobrien#endif 503833965Sjdp 503933965SjdpsymbolS * 504033965Sjdpmd_undefined_symbol (name) 504133965Sjdp char *name; 504233965Sjdp{ 504360519Sobrien if (name[0] == GLOBAL_OFFSET_TABLE_NAME[0] 504460519Sobrien && name[1] == GLOBAL_OFFSET_TABLE_NAME[1] 504560519Sobrien && name[2] == GLOBAL_OFFSET_TABLE_NAME[2] 504660519Sobrien && strcmp (name, GLOBAL_OFFSET_TABLE_NAME) == 0) 504760519Sobrien { 504860519Sobrien if (!GOT_symbol) 504960519Sobrien { 505060519Sobrien if (symbol_find (name)) 505160519Sobrien as_bad (_("GOT already in symbol table")); 505260519Sobrien GOT_symbol = symbol_new (name, undefined_section, 505360519Sobrien (valueT) 0, &zero_address_frag); 505460519Sobrien }; 505560519Sobrien return GOT_symbol; 505660519Sobrien } 505733965Sjdp return 0; 505833965Sjdp} 505933965Sjdp 506033965Sjdp/* Round up a section size to the appropriate boundary. */ 506177311Sobrien 506233965SjdpvalueT 506333965Sjdpmd_section_align (segment, size) 506460519Sobrien segT segment ATTRIBUTE_UNUSED; 506533965Sjdp valueT size; 506633965Sjdp{ 506760519Sobrien#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT)) 506860519Sobrien if (OUTPUT_FLAVOR == bfd_target_aout_flavour) 506960519Sobrien { 507060519Sobrien /* For a.out, force the section size to be aligned. If we don't do 507160519Sobrien this, BFD will align it for us, but it will not write out the 507260519Sobrien final bytes of the section. This may be a bug in BFD, but it is 507360519Sobrien easier to fix it here since that is how the other a.out targets 507460519Sobrien work. */ 507560519Sobrien int align; 507633965Sjdp 507760519Sobrien align = bfd_get_section_alignment (stdoutput, segment); 507860519Sobrien size = ((size + (1 << align) - 1) & ((valueT) -1 << align)); 507960519Sobrien } 508033965Sjdp#endif 508133965Sjdp 508233965Sjdp return size; 508333965Sjdp} 508433965Sjdp 508560519Sobrien/* On the i386, PC-relative offsets are relative to the start of the 508660519Sobrien next instruction. That is, the address of the offset, plus its 508760519Sobrien size, since the offset is always the last part of the insn. */ 508860519Sobrien 508933965Sjdplong 509033965Sjdpmd_pcrel_from (fixP) 509133965Sjdp fixS *fixP; 509233965Sjdp{ 509333965Sjdp return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address; 509433965Sjdp} 509533965Sjdp 509633965Sjdp#ifndef I386COFF 509733965Sjdp 509833965Sjdpstatic void 509933965Sjdps_bss (ignore) 510060519Sobrien int ignore ATTRIBUTE_UNUSED; 510133965Sjdp{ 510294546Sobrien int temp; 510333965Sjdp 510433965Sjdp temp = get_absolute_expression (); 510533965Sjdp subseg_set (bss_section, (subsegT) temp); 510633965Sjdp demand_empty_rest_of_line (); 510733965Sjdp} 510833965Sjdp 510933965Sjdp#endif 511033965Sjdp 511133965Sjdpvoid 511233965Sjdpi386_validate_fix (fixp) 511333965Sjdp fixS *fixp; 511433965Sjdp{ 511533965Sjdp if (fixp->fx_subsy && fixp->fx_subsy == GOT_symbol) 511633965Sjdp { 511777311Sobrien /* GOTOFF relocation are nonsense in 64bit mode. */ 511877311Sobrien if (fixp->fx_r_type == BFD_RELOC_32_PCREL) 511977311Sobrien { 512077311Sobrien if (flag_code != CODE_64BIT) 512177311Sobrien abort (); 512277311Sobrien fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL; 512377311Sobrien } 512477311Sobrien else 512577311Sobrien { 512677311Sobrien if (flag_code == CODE_64BIT) 512777311Sobrien abort (); 512877311Sobrien fixp->fx_r_type = BFD_RELOC_386_GOTOFF; 512977311Sobrien } 513033965Sjdp fixp->fx_subsy = 0; 513133965Sjdp } 513233965Sjdp} 513333965Sjdp 513433965Sjdparelent * 513533965Sjdptc_gen_reloc (section, fixp) 513660519Sobrien asection *section ATTRIBUTE_UNUSED; 513733965Sjdp fixS *fixp; 513833965Sjdp{ 513933965Sjdp arelent *rel; 514033965Sjdp bfd_reloc_code_real_type code; 514133965Sjdp 514260519Sobrien switch (fixp->fx_r_type) 514333965Sjdp { 514477311Sobrien case BFD_RELOC_X86_64_PLT32: 514577311Sobrien case BFD_RELOC_X86_64_GOT32: 514677311Sobrien case BFD_RELOC_X86_64_GOTPCREL: 514733965Sjdp case BFD_RELOC_386_PLT32: 514833965Sjdp case BFD_RELOC_386_GOT32: 514933965Sjdp case BFD_RELOC_386_GOTOFF: 515033965Sjdp case BFD_RELOC_386_GOTPC: 5151104848Sobrien case BFD_RELOC_386_TLS_GD: 5152104848Sobrien case BFD_RELOC_386_TLS_LDM: 5153104848Sobrien case BFD_RELOC_386_TLS_LDO_32: 5154104848Sobrien case BFD_RELOC_386_TLS_IE_32: 5155104848Sobrien case BFD_RELOC_386_TLS_IE: 5156104848Sobrien case BFD_RELOC_386_TLS_GOTIE: 5157104848Sobrien case BFD_RELOC_386_TLS_LE_32: 5158104848Sobrien case BFD_RELOC_386_TLS_LE: 515977311Sobrien case BFD_RELOC_X86_64_32S: 5160130570Sobrien case BFD_RELOC_X86_64_TLSGD: 5161130570Sobrien case BFD_RELOC_X86_64_TLSLD: 5162130570Sobrien case BFD_RELOC_X86_64_DTPOFF32: 5163130570Sobrien case BFD_RELOC_X86_64_GOTTPOFF: 5164130570Sobrien case BFD_RELOC_X86_64_TPOFF32: 516538891Sjdp case BFD_RELOC_RVA: 516660519Sobrien case BFD_RELOC_VTABLE_ENTRY: 516760519Sobrien case BFD_RELOC_VTABLE_INHERIT: 516833965Sjdp code = fixp->fx_r_type; 516933965Sjdp break; 517033965Sjdp default: 517160519Sobrien if (fixp->fx_pcrel) 517233965Sjdp { 517360519Sobrien switch (fixp->fx_size) 517460519Sobrien { 517560519Sobrien default: 517689867Sobrien as_bad_where (fixp->fx_file, fixp->fx_line, 517789867Sobrien _("can not do %d byte pc-relative relocation"), 517889867Sobrien fixp->fx_size); 517960519Sobrien code = BFD_RELOC_32_PCREL; 518060519Sobrien break; 518160519Sobrien case 1: code = BFD_RELOC_8_PCREL; break; 518260519Sobrien case 2: code = BFD_RELOC_16_PCREL; break; 518360519Sobrien case 4: code = BFD_RELOC_32_PCREL; break; 518460519Sobrien } 518533965Sjdp } 518660519Sobrien else 518760519Sobrien { 518860519Sobrien switch (fixp->fx_size) 518960519Sobrien { 519060519Sobrien default: 519189867Sobrien as_bad_where (fixp->fx_file, fixp->fx_line, 519289867Sobrien _("can not do %d byte relocation"), 519389867Sobrien fixp->fx_size); 519460519Sobrien code = BFD_RELOC_32; 519560519Sobrien break; 519660519Sobrien case 1: code = BFD_RELOC_8; break; 519760519Sobrien case 2: code = BFD_RELOC_16; break; 519860519Sobrien case 4: code = BFD_RELOC_32; break; 519994546Sobrien#ifdef BFD64 520077311Sobrien case 8: code = BFD_RELOC_64; break; 520194546Sobrien#endif 520260519Sobrien } 520360519Sobrien } 520460519Sobrien break; 520533965Sjdp } 520633965Sjdp 520733965Sjdp if (code == BFD_RELOC_32 520833965Sjdp && GOT_symbol 520933965Sjdp && fixp->fx_addsy == GOT_symbol) 521077311Sobrien { 521177311Sobrien /* We don't support GOTPC on 64bit targets. */ 521277311Sobrien if (flag_code == CODE_64BIT) 521377311Sobrien abort (); 521477311Sobrien code = BFD_RELOC_386_GOTPC; 521577311Sobrien } 521633965Sjdp 521733965Sjdp rel = (arelent *) xmalloc (sizeof (arelent)); 521860519Sobrien rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); 521960519Sobrien *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 522060519Sobrien 522133965Sjdp rel->address = fixp->fx_frag->fr_address + fixp->fx_where; 522277311Sobrien if (!use_rela_relocations) 522377311Sobrien { 522477311Sobrien /* HACK: Since i386 ELF uses Rel instead of Rela, encode the 522577311Sobrien vtable entry to be used in the relocation's section offset. */ 522677311Sobrien if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) 522777311Sobrien rel->address = fixp->fx_offset; 522860519Sobrien 5229104848Sobrien rel->addend = 0; 523077311Sobrien } 523177311Sobrien /* Use the rela in 64bit mode. */ 523233965Sjdp else 523377311Sobrien { 523499468Sobrien if (!fixp->fx_pcrel) 523599468Sobrien rel->addend = fixp->fx_offset; 523699468Sobrien else 523799468Sobrien switch (code) 523899468Sobrien { 523999468Sobrien case BFD_RELOC_X86_64_PLT32: 524099468Sobrien case BFD_RELOC_X86_64_GOT32: 524199468Sobrien case BFD_RELOC_X86_64_GOTPCREL: 5242130570Sobrien case BFD_RELOC_X86_64_TLSGD: 5243130570Sobrien case BFD_RELOC_X86_64_TLSLD: 5244130570Sobrien case BFD_RELOC_X86_64_GOTTPOFF: 524599468Sobrien rel->addend = fixp->fx_offset - fixp->fx_size; 524699468Sobrien break; 524799468Sobrien default: 524899468Sobrien rel->addend = (section->vma 524999468Sobrien - fixp->fx_size 525099468Sobrien + fixp->fx_addnumber 525199468Sobrien + md_pcrel_from (fixp)); 525299468Sobrien break; 525399468Sobrien } 525477311Sobrien } 525533965Sjdp 525633965Sjdp rel->howto = bfd_reloc_type_lookup (stdoutput, code); 525733965Sjdp if (rel->howto == NULL) 525833965Sjdp { 525933965Sjdp as_bad_where (fixp->fx_file, fixp->fx_line, 526060519Sobrien _("cannot represent relocation type %s"), 526133965Sjdp bfd_get_reloc_code_name (code)); 526233965Sjdp /* Set howto to a garbage value so that we can keep going. */ 526333965Sjdp rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32); 526433965Sjdp assert (rel->howto != NULL); 526533965Sjdp } 526633965Sjdp 526733965Sjdp return rel; 526833965Sjdp} 526933965Sjdp 527033965Sjdp 527177311Sobrien/* Parse operands using Intel syntax. This implements a recursive descent 527277311Sobrien parser based on the BNF grammar published in Appendix B of the MASM 6.1 527377311Sobrien Programmer's Guide. 527477311Sobrien 527577311Sobrien FIXME: We do not recognize the full operand grammar defined in the MASM 527677311Sobrien documentation. In particular, all the structure/union and 527777311Sobrien high-level macro operands are missing. 527877311Sobrien 527977311Sobrien Uppercase words are terminals, lower case words are non-terminals. 528077311Sobrien Objects surrounded by double brackets '[[' ']]' are optional. Vertical 528177311Sobrien bars '|' denote choices. Most grammar productions are implemented in 528277311Sobrien functions called 'intel_<production>'. 528377311Sobrien 528477311Sobrien Initial production is 'expr'. 528577311Sobrien 528677311Sobrien addOp + | - 528777311Sobrien 528877311Sobrien alpha [a-zA-Z] 528977311Sobrien 529077311Sobrien byteRegister AL | AH | BL | BH | CL | CH | DL | DH 529177311Sobrien 529277311Sobrien constant digits [[ radixOverride ]] 529377311Sobrien 529477311Sobrien dataType BYTE | WORD | DWORD | QWORD | XWORD 529577311Sobrien 529677311Sobrien digits decdigit 529777311Sobrien | digits decdigit 529877311Sobrien | digits hexdigit 529977311Sobrien 530077311Sobrien decdigit [0-9] 530177311Sobrien 530277311Sobrien e05 e05 addOp e06 530377311Sobrien | e06 530477311Sobrien 530577311Sobrien e06 e06 mulOp e09 530677311Sobrien | e09 530777311Sobrien 530877311Sobrien e09 OFFSET e10 530977311Sobrien | e09 PTR e10 531077311Sobrien | e09 : e10 531177311Sobrien | e10 531277311Sobrien 531377311Sobrien e10 e10 [ expr ] 531477311Sobrien | e11 531577311Sobrien 531677311Sobrien e11 ( expr ) 531777311Sobrien | [ expr ] 531877311Sobrien | constant 531977311Sobrien | dataType 532077311Sobrien | id 532177311Sobrien | $ 532277311Sobrien | register 532377311Sobrien 532477311Sobrien => expr SHORT e05 532577311Sobrien | e05 532677311Sobrien 532777311Sobrien gpRegister AX | EAX | BX | EBX | CX | ECX | DX | EDX 532877311Sobrien | BP | EBP | SP | ESP | DI | EDI | SI | ESI 532977311Sobrien 533077311Sobrien hexdigit a | b | c | d | e | f 533177311Sobrien | A | B | C | D | E | F 533277311Sobrien 533377311Sobrien id alpha 533477311Sobrien | id alpha 533577311Sobrien | id decdigit 533677311Sobrien 533777311Sobrien mulOp * | / | MOD 533877311Sobrien 533977311Sobrien quote " | ' 534077311Sobrien 534177311Sobrien register specialRegister 534277311Sobrien | gpRegister 534377311Sobrien | byteRegister 534477311Sobrien 534577311Sobrien segmentRegister CS | DS | ES | FS | GS | SS 534677311Sobrien 534777311Sobrien specialRegister CR0 | CR2 | CR3 534877311Sobrien | DR0 | DR1 | DR2 | DR3 | DR6 | DR7 534977311Sobrien | TR3 | TR4 | TR5 | TR6 | TR7 535077311Sobrien 535177311Sobrien We simplify the grammar in obvious places (e.g., register parsing is 535277311Sobrien done by calling parse_register) and eliminate immediate left recursion 535377311Sobrien to implement a recursive-descent parser. 535477311Sobrien 535577311Sobrien expr SHORT e05 535677311Sobrien | e05 535777311Sobrien 535877311Sobrien e05 e06 e05' 535977311Sobrien 536077311Sobrien e05' addOp e06 e05' 536177311Sobrien | Empty 536277311Sobrien 536377311Sobrien e06 e09 e06' 536477311Sobrien 536577311Sobrien e06' mulOp e09 e06' 536677311Sobrien | Empty 536777311Sobrien 536877311Sobrien e09 OFFSET e10 e09' 536977311Sobrien | e10 e09' 537077311Sobrien 537177311Sobrien e09' PTR e10 e09' 537277311Sobrien | : e10 e09' 537377311Sobrien | Empty 537477311Sobrien 537577311Sobrien e10 e11 e10' 537677311Sobrien 537777311Sobrien e10' [ expr ] e10' 537877311Sobrien | Empty 537977311Sobrien 538077311Sobrien e11 ( expr ) 538177311Sobrien | [ expr ] 538277311Sobrien | BYTE 538377311Sobrien | WORD 538477311Sobrien | DWORD 538577311Sobrien | QWORD 538677311Sobrien | XWORD 538777311Sobrien | . 538877311Sobrien | $ 538977311Sobrien | register 539077311Sobrien | id 539177311Sobrien | constant */ 539277311Sobrien 539377311Sobrien/* Parsing structure for the intel syntax parser. Used to implement the 539477311Sobrien semantic actions for the operand grammar. */ 539577311Sobrienstruct intel_parser_s 539677311Sobrien { 539777311Sobrien char *op_string; /* The string being parsed. */ 539877311Sobrien int got_a_float; /* Whether the operand is a float. */ 539977311Sobrien int op_modifier; /* Operand modifier. */ 540077311Sobrien int is_mem; /* 1 if operand is memory reference. */ 540177311Sobrien const reg_entry *reg; /* Last register reference found. */ 540277311Sobrien char *disp; /* Displacement string being built. */ 540377311Sobrien }; 540477311Sobrien 540577311Sobrienstatic struct intel_parser_s intel_parser; 540677311Sobrien 540777311Sobrien/* Token structure for parsing intel syntax. */ 540877311Sobrienstruct intel_token 540977311Sobrien { 541077311Sobrien int code; /* Token code. */ 541177311Sobrien const reg_entry *reg; /* Register entry for register tokens. */ 541277311Sobrien char *str; /* String representation. */ 541377311Sobrien }; 541477311Sobrien 541577311Sobrienstatic struct intel_token cur_token, prev_token; 541677311Sobrien 541777311Sobrien/* Token codes for the intel parser. Since T_SHORT is already used 541877311Sobrien by COFF, undefine it first to prevent a warning. */ 541977311Sobrien#define T_NIL -1 542077311Sobrien#define T_CONST 1 542177311Sobrien#define T_REG 2 542277311Sobrien#define T_BYTE 3 542377311Sobrien#define T_WORD 4 542477311Sobrien#define T_DWORD 5 542577311Sobrien#define T_QWORD 6 542677311Sobrien#define T_XWORD 7 542777311Sobrien#undef T_SHORT 542877311Sobrien#define T_SHORT 8 542977311Sobrien#define T_OFFSET 9 543077311Sobrien#define T_PTR 10 543177311Sobrien#define T_ID 11 543277311Sobrien 543377311Sobrien/* Prototypes for intel parser functions. */ 543477311Sobrienstatic int intel_match_token PARAMS ((int code)); 543577311Sobrienstatic void intel_get_token PARAMS ((void)); 543677311Sobrienstatic void intel_putback_token PARAMS ((void)); 543777311Sobrienstatic int intel_expr PARAMS ((void)); 543877311Sobrienstatic int intel_e05 PARAMS ((void)); 543977311Sobrienstatic int intel_e05_1 PARAMS ((void)); 544077311Sobrienstatic int intel_e06 PARAMS ((void)); 544177311Sobrienstatic int intel_e06_1 PARAMS ((void)); 544277311Sobrienstatic int intel_e09 PARAMS ((void)); 544377311Sobrienstatic int intel_e09_1 PARAMS ((void)); 544477311Sobrienstatic int intel_e10 PARAMS ((void)); 544577311Sobrienstatic int intel_e10_1 PARAMS ((void)); 544677311Sobrienstatic int intel_e11 PARAMS ((void)); 544777311Sobrien 544877311Sobrienstatic int 544977311Sobrieni386_intel_operand (operand_string, got_a_float) 545077311Sobrien char *operand_string; 545177311Sobrien int got_a_float; 545277311Sobrien{ 545377311Sobrien int ret; 545477311Sobrien char *p; 545577311Sobrien 545677311Sobrien /* Initialize token holders. */ 545777311Sobrien cur_token.code = prev_token.code = T_NIL; 545877311Sobrien cur_token.reg = prev_token.reg = NULL; 545977311Sobrien cur_token.str = prev_token.str = NULL; 546077311Sobrien 546177311Sobrien /* Initialize parser structure. */ 546277311Sobrien p = intel_parser.op_string = (char *) malloc (strlen (operand_string) + 1); 546377311Sobrien if (p == NULL) 546477311Sobrien abort (); 546577311Sobrien strcpy (intel_parser.op_string, operand_string); 546677311Sobrien intel_parser.got_a_float = got_a_float; 546777311Sobrien intel_parser.op_modifier = -1; 546877311Sobrien intel_parser.is_mem = 0; 546977311Sobrien intel_parser.reg = NULL; 547077311Sobrien intel_parser.disp = (char *) malloc (strlen (operand_string) + 1); 547177311Sobrien if (intel_parser.disp == NULL) 547277311Sobrien abort (); 547377311Sobrien intel_parser.disp[0] = '\0'; 547477311Sobrien 547577311Sobrien /* Read the first token and start the parser. */ 547677311Sobrien intel_get_token (); 547777311Sobrien ret = intel_expr (); 547877311Sobrien 547977311Sobrien if (ret) 548077311Sobrien { 548177311Sobrien /* If we found a memory reference, hand it over to i386_displacement 548277311Sobrien to fill in the rest of the operand fields. */ 548377311Sobrien if (intel_parser.is_mem) 548477311Sobrien { 548577311Sobrien if ((i.mem_operands == 1 548677311Sobrien && (current_templates->start->opcode_modifier & IsString) == 0) 548777311Sobrien || i.mem_operands == 2) 548877311Sobrien { 548977311Sobrien as_bad (_("too many memory references for '%s'"), 549077311Sobrien current_templates->start->name); 549177311Sobrien ret = 0; 549277311Sobrien } 549377311Sobrien else 549477311Sobrien { 549577311Sobrien char *s = intel_parser.disp; 549677311Sobrien i.mem_operands++; 549777311Sobrien 549877311Sobrien /* Add the displacement expression. */ 549977311Sobrien if (*s != '\0') 5500130570Sobrien ret = i386_displacement (s, s + strlen (s)); 5501130570Sobrien if (ret) 5502130570Sobrien ret = i386_index_check (operand_string); 550377311Sobrien } 550477311Sobrien } 550577311Sobrien 550677311Sobrien /* Constant and OFFSET expressions are handled by i386_immediate. */ 550777311Sobrien else if (intel_parser.op_modifier == OFFSET_FLAT 550877311Sobrien || intel_parser.reg == NULL) 550977311Sobrien ret = i386_immediate (intel_parser.disp); 551077311Sobrien } 551177311Sobrien 551277311Sobrien free (p); 551377311Sobrien free (intel_parser.disp); 551477311Sobrien 551577311Sobrien return ret; 551677311Sobrien} 551777311Sobrien 551877311Sobrien/* expr SHORT e05 551977311Sobrien | e05 */ 552077311Sobrienstatic int 552177311Sobrienintel_expr () 552277311Sobrien{ 552377311Sobrien /* expr SHORT e05 */ 552477311Sobrien if (cur_token.code == T_SHORT) 552577311Sobrien { 552677311Sobrien intel_parser.op_modifier = SHORT; 552777311Sobrien intel_match_token (T_SHORT); 552877311Sobrien 552977311Sobrien return (intel_e05 ()); 553077311Sobrien } 553177311Sobrien 553277311Sobrien /* expr e05 */ 553377311Sobrien else 553477311Sobrien return intel_e05 (); 553577311Sobrien} 553677311Sobrien 553777311Sobrien/* e05 e06 e05' 553877311Sobrien 553977311Sobrien e05' addOp e06 e05' 554077311Sobrien | Empty */ 554177311Sobrienstatic int 554277311Sobrienintel_e05 () 554377311Sobrien{ 554477311Sobrien return (intel_e06 () && intel_e05_1 ()); 554577311Sobrien} 554677311Sobrien 554777311Sobrienstatic int 554877311Sobrienintel_e05_1 () 554977311Sobrien{ 555077311Sobrien /* e05' addOp e06 e05' */ 555177311Sobrien if (cur_token.code == '+' || cur_token.code == '-') 555277311Sobrien { 555377311Sobrien strcat (intel_parser.disp, cur_token.str); 555477311Sobrien intel_match_token (cur_token.code); 555577311Sobrien 555677311Sobrien return (intel_e06 () && intel_e05_1 ()); 555777311Sobrien } 555877311Sobrien 555977311Sobrien /* e05' Empty */ 556077311Sobrien else 556177311Sobrien return 1; 556277311Sobrien} 556377311Sobrien 556477311Sobrien/* e06 e09 e06' 556577311Sobrien 556677311Sobrien e06' mulOp e09 e06' 556777311Sobrien | Empty */ 556877311Sobrienstatic int 556977311Sobrienintel_e06 () 557077311Sobrien{ 557177311Sobrien return (intel_e09 () && intel_e06_1 ()); 557277311Sobrien} 557377311Sobrien 557477311Sobrienstatic int 557577311Sobrienintel_e06_1 () 557677311Sobrien{ 557777311Sobrien /* e06' mulOp e09 e06' */ 557877311Sobrien if (cur_token.code == '*' || cur_token.code == '/') 557977311Sobrien { 558077311Sobrien strcat (intel_parser.disp, cur_token.str); 558177311Sobrien intel_match_token (cur_token.code); 558277311Sobrien 558377311Sobrien return (intel_e09 () && intel_e06_1 ()); 558477311Sobrien } 558577311Sobrien 558677311Sobrien /* e06' Empty */ 558777311Sobrien else 558877311Sobrien return 1; 558977311Sobrien} 559077311Sobrien 559177311Sobrien/* e09 OFFSET e10 e09' 559277311Sobrien | e10 e09' 559377311Sobrien 559477311Sobrien e09' PTR e10 e09' 559577311Sobrien | : e10 e09' 559677311Sobrien | Empty */ 559777311Sobrienstatic int 559877311Sobrienintel_e09 () 559977311Sobrien{ 560077311Sobrien /* e09 OFFSET e10 e09' */ 560177311Sobrien if (cur_token.code == T_OFFSET) 560277311Sobrien { 560377311Sobrien intel_parser.is_mem = 0; 560477311Sobrien intel_parser.op_modifier = OFFSET_FLAT; 560577311Sobrien intel_match_token (T_OFFSET); 560677311Sobrien 560777311Sobrien return (intel_e10 () && intel_e09_1 ()); 560877311Sobrien } 560977311Sobrien 561077311Sobrien /* e09 e10 e09' */ 561177311Sobrien else 561277311Sobrien return (intel_e10 () && intel_e09_1 ()); 561377311Sobrien} 561477311Sobrien 561577311Sobrienstatic int 561677311Sobrienintel_e09_1 () 561777311Sobrien{ 561877311Sobrien /* e09' PTR e10 e09' */ 561977311Sobrien if (cur_token.code == T_PTR) 562077311Sobrien { 562177311Sobrien if (prev_token.code == T_BYTE) 562277311Sobrien i.suffix = BYTE_MNEM_SUFFIX; 562377311Sobrien 562477311Sobrien else if (prev_token.code == T_WORD) 562577311Sobrien { 562677311Sobrien if (intel_parser.got_a_float == 2) /* "fi..." */ 562777311Sobrien i.suffix = SHORT_MNEM_SUFFIX; 562877311Sobrien else 562977311Sobrien i.suffix = WORD_MNEM_SUFFIX; 563077311Sobrien } 563177311Sobrien 563277311Sobrien else if (prev_token.code == T_DWORD) 563377311Sobrien { 563477311Sobrien if (intel_parser.got_a_float == 1) /* "f..." */ 563577311Sobrien i.suffix = SHORT_MNEM_SUFFIX; 563677311Sobrien else 563777311Sobrien i.suffix = LONG_MNEM_SUFFIX; 563877311Sobrien } 563977311Sobrien 564077311Sobrien else if (prev_token.code == T_QWORD) 564177311Sobrien { 564277311Sobrien if (intel_parser.got_a_float == 1) /* "f..." */ 564377311Sobrien i.suffix = LONG_MNEM_SUFFIX; 564477311Sobrien else 564577311Sobrien i.suffix = QWORD_MNEM_SUFFIX; 564677311Sobrien } 564777311Sobrien 564877311Sobrien else if (prev_token.code == T_XWORD) 564977311Sobrien i.suffix = LONG_DOUBLE_MNEM_SUFFIX; 565077311Sobrien 565177311Sobrien else 565277311Sobrien { 565377311Sobrien as_bad (_("Unknown operand modifier `%s'\n"), prev_token.str); 565477311Sobrien return 0; 565577311Sobrien } 565677311Sobrien 565777311Sobrien intel_match_token (T_PTR); 565877311Sobrien 565977311Sobrien return (intel_e10 () && intel_e09_1 ()); 566077311Sobrien } 566177311Sobrien 566277311Sobrien /* e09 : e10 e09' */ 566377311Sobrien else if (cur_token.code == ':') 566477311Sobrien { 566577311Sobrien /* Mark as a memory operand only if it's not already known to be an 566677311Sobrien offset expression. */ 566777311Sobrien if (intel_parser.op_modifier != OFFSET_FLAT) 566877311Sobrien intel_parser.is_mem = 1; 566977311Sobrien 567077311Sobrien return (intel_match_token (':') && intel_e10 () && intel_e09_1 ()); 567177311Sobrien } 567277311Sobrien 567377311Sobrien /* e09' Empty */ 567477311Sobrien else 567577311Sobrien return 1; 567677311Sobrien} 567777311Sobrien 567877311Sobrien/* e10 e11 e10' 567977311Sobrien 568077311Sobrien e10' [ expr ] e10' 568177311Sobrien | Empty */ 568277311Sobrienstatic int 568377311Sobrienintel_e10 () 568477311Sobrien{ 568577311Sobrien return (intel_e11 () && intel_e10_1 ()); 568677311Sobrien} 568777311Sobrien 568877311Sobrienstatic int 568977311Sobrienintel_e10_1 () 569077311Sobrien{ 569177311Sobrien /* e10' [ expr ] e10' */ 569277311Sobrien if (cur_token.code == '[') 569377311Sobrien { 569477311Sobrien intel_match_token ('['); 569577311Sobrien 569677311Sobrien /* Mark as a memory operand only if it's not already known to be an 569777311Sobrien offset expression. If it's an offset expression, we need to keep 569877311Sobrien the brace in. */ 569977311Sobrien if (intel_parser.op_modifier != OFFSET_FLAT) 570077311Sobrien intel_parser.is_mem = 1; 570177311Sobrien else 570277311Sobrien strcat (intel_parser.disp, "["); 570377311Sobrien 570477311Sobrien /* Add a '+' to the displacement string if necessary. */ 570577311Sobrien if (*intel_parser.disp != '\0' 570677311Sobrien && *(intel_parser.disp + strlen (intel_parser.disp) - 1) != '+') 570777311Sobrien strcat (intel_parser.disp, "+"); 570877311Sobrien 570977311Sobrien if (intel_expr () && intel_match_token (']')) 571077311Sobrien { 571177311Sobrien /* Preserve brackets when the operand is an offset expression. */ 571277311Sobrien if (intel_parser.op_modifier == OFFSET_FLAT) 571377311Sobrien strcat (intel_parser.disp, "]"); 571477311Sobrien 571577311Sobrien return intel_e10_1 (); 571677311Sobrien } 571777311Sobrien else 571877311Sobrien return 0; 571977311Sobrien } 572077311Sobrien 572177311Sobrien /* e10' Empty */ 572277311Sobrien else 572377311Sobrien return 1; 572477311Sobrien} 572577311Sobrien 572677311Sobrien/* e11 ( expr ) 572777311Sobrien | [ expr ] 572877311Sobrien | BYTE 572977311Sobrien | WORD 573077311Sobrien | DWORD 573177311Sobrien | QWORD 573277311Sobrien | XWORD 573377311Sobrien | $ 573477311Sobrien | . 573577311Sobrien | register 573677311Sobrien | id 573777311Sobrien | constant */ 573877311Sobrienstatic int 573977311Sobrienintel_e11 () 574077311Sobrien{ 574177311Sobrien /* e11 ( expr ) */ 574277311Sobrien if (cur_token.code == '(') 574377311Sobrien { 574477311Sobrien intel_match_token ('('); 574577311Sobrien strcat (intel_parser.disp, "("); 574677311Sobrien 574777311Sobrien if (intel_expr () && intel_match_token (')')) 574877311Sobrien { 574977311Sobrien strcat (intel_parser.disp, ")"); 575077311Sobrien return 1; 575177311Sobrien } 575277311Sobrien else 575377311Sobrien return 0; 575477311Sobrien } 575577311Sobrien 575677311Sobrien /* e11 [ expr ] */ 575777311Sobrien else if (cur_token.code == '[') 575877311Sobrien { 575977311Sobrien intel_match_token ('['); 576077311Sobrien 576177311Sobrien /* Mark as a memory operand only if it's not already known to be an 576277311Sobrien offset expression. If it's an offset expression, we need to keep 576377311Sobrien the brace in. */ 576477311Sobrien if (intel_parser.op_modifier != OFFSET_FLAT) 576577311Sobrien intel_parser.is_mem = 1; 576677311Sobrien else 576777311Sobrien strcat (intel_parser.disp, "["); 576877311Sobrien 576977311Sobrien /* Operands for jump/call inside brackets denote absolute addresses. */ 577077311Sobrien if (current_templates->start->opcode_modifier & Jump 577177311Sobrien || current_templates->start->opcode_modifier & JumpDword 577277311Sobrien || current_templates->start->opcode_modifier & JumpByte 577377311Sobrien || current_templates->start->opcode_modifier & JumpInterSegment) 577477311Sobrien i.types[this_operand] |= JumpAbsolute; 577577311Sobrien 577677311Sobrien /* Add a '+' to the displacement string if necessary. */ 577777311Sobrien if (*intel_parser.disp != '\0' 577877311Sobrien && *(intel_parser.disp + strlen (intel_parser.disp) - 1) != '+') 577977311Sobrien strcat (intel_parser.disp, "+"); 578077311Sobrien 578177311Sobrien if (intel_expr () && intel_match_token (']')) 578277311Sobrien { 578377311Sobrien /* Preserve brackets when the operand is an offset expression. */ 578477311Sobrien if (intel_parser.op_modifier == OFFSET_FLAT) 578577311Sobrien strcat (intel_parser.disp, "]"); 578677311Sobrien 578777311Sobrien return 1; 578877311Sobrien } 578977311Sobrien else 579077311Sobrien return 0; 579177311Sobrien } 579277311Sobrien 579377311Sobrien /* e11 BYTE 579477311Sobrien | WORD 579577311Sobrien | DWORD 579677311Sobrien | QWORD 579777311Sobrien | XWORD */ 579877311Sobrien else if (cur_token.code == T_BYTE 579977311Sobrien || cur_token.code == T_WORD 580077311Sobrien || cur_token.code == T_DWORD 580177311Sobrien || cur_token.code == T_QWORD 580277311Sobrien || cur_token.code == T_XWORD) 580377311Sobrien { 580477311Sobrien intel_match_token (cur_token.code); 580577311Sobrien 580677311Sobrien return 1; 580777311Sobrien } 580877311Sobrien 580977311Sobrien /* e11 $ 581077311Sobrien | . */ 581177311Sobrien else if (cur_token.code == '$' || cur_token.code == '.') 581277311Sobrien { 581377311Sobrien strcat (intel_parser.disp, cur_token.str); 581477311Sobrien intel_match_token (cur_token.code); 581577311Sobrien 581677311Sobrien /* Mark as a memory operand only if it's not already known to be an 581777311Sobrien offset expression. */ 581877311Sobrien if (intel_parser.op_modifier != OFFSET_FLAT) 581977311Sobrien intel_parser.is_mem = 1; 582077311Sobrien 582177311Sobrien return 1; 582277311Sobrien } 582377311Sobrien 582477311Sobrien /* e11 register */ 582577311Sobrien else if (cur_token.code == T_REG) 582677311Sobrien { 582777311Sobrien const reg_entry *reg = intel_parser.reg = cur_token.reg; 582877311Sobrien 582977311Sobrien intel_match_token (T_REG); 583077311Sobrien 583177311Sobrien /* Check for segment change. */ 583277311Sobrien if (cur_token.code == ':') 583377311Sobrien { 583477311Sobrien if (reg->reg_type & (SReg2 | SReg3)) 583577311Sobrien { 583677311Sobrien switch (reg->reg_num) 583777311Sobrien { 583877311Sobrien case 0: 583977311Sobrien i.seg[i.mem_operands] = &es; 584077311Sobrien break; 584177311Sobrien case 1: 584277311Sobrien i.seg[i.mem_operands] = &cs; 584377311Sobrien break; 584477311Sobrien case 2: 584577311Sobrien i.seg[i.mem_operands] = &ss; 584677311Sobrien break; 584777311Sobrien case 3: 584877311Sobrien i.seg[i.mem_operands] = &ds; 584977311Sobrien break; 585077311Sobrien case 4: 585177311Sobrien i.seg[i.mem_operands] = &fs; 585277311Sobrien break; 585377311Sobrien case 5: 585477311Sobrien i.seg[i.mem_operands] = &gs; 585577311Sobrien break; 585677311Sobrien } 585777311Sobrien } 585877311Sobrien else 585977311Sobrien { 586077311Sobrien as_bad (_("`%s' is not a valid segment register"), reg->reg_name); 586177311Sobrien return 0; 586277311Sobrien } 586377311Sobrien } 586477311Sobrien 586577311Sobrien /* Not a segment register. Check for register scaling. */ 586677311Sobrien else if (cur_token.code == '*') 586777311Sobrien { 586877311Sobrien if (!intel_parser.is_mem) 586977311Sobrien { 587077311Sobrien as_bad (_("Register scaling only allowed in memory operands.")); 587177311Sobrien return 0; 587277311Sobrien } 587377311Sobrien 587477311Sobrien /* What follows must be a valid scale. */ 587577311Sobrien if (intel_match_token ('*') 587677311Sobrien && strchr ("01248", *cur_token.str)) 587777311Sobrien { 587877311Sobrien i.index_reg = reg; 587977311Sobrien i.types[this_operand] |= BaseIndex; 588077311Sobrien 588177311Sobrien /* Set the scale after setting the register (otherwise, 588277311Sobrien i386_scale will complain) */ 588377311Sobrien i386_scale (cur_token.str); 588477311Sobrien intel_match_token (T_CONST); 588577311Sobrien } 588677311Sobrien else 588777311Sobrien { 588877311Sobrien as_bad (_("expecting scale factor of 1, 2, 4, or 8: got `%s'"), 588977311Sobrien cur_token.str); 589077311Sobrien return 0; 589177311Sobrien } 589277311Sobrien } 589377311Sobrien 589477311Sobrien /* No scaling. If this is a memory operand, the register is either a 589577311Sobrien base register (first occurrence) or an index register (second 589677311Sobrien occurrence). */ 589777311Sobrien else if (intel_parser.is_mem && !(reg->reg_type & (SReg2 | SReg3))) 589877311Sobrien { 589977311Sobrien if (i.base_reg && i.index_reg) 590077311Sobrien { 590177311Sobrien as_bad (_("Too many register references in memory operand.\n")); 590277311Sobrien return 0; 590377311Sobrien } 590477311Sobrien 590577311Sobrien if (i.base_reg == NULL) 590677311Sobrien i.base_reg = reg; 590777311Sobrien else 590877311Sobrien i.index_reg = reg; 590977311Sobrien 591077311Sobrien i.types[this_operand] |= BaseIndex; 591177311Sobrien } 591277311Sobrien 591377311Sobrien /* Offset modifier. Add the register to the displacement string to be 591477311Sobrien parsed as an immediate expression after we're done. */ 591577311Sobrien else if (intel_parser.op_modifier == OFFSET_FLAT) 591677311Sobrien strcat (intel_parser.disp, reg->reg_name); 591777311Sobrien 591877311Sobrien /* It's neither base nor index nor offset. */ 591977311Sobrien else 592077311Sobrien { 592177311Sobrien i.types[this_operand] |= reg->reg_type & ~BaseIndex; 592277311Sobrien i.op[this_operand].regs = reg; 592377311Sobrien i.reg_operands++; 592477311Sobrien } 592577311Sobrien 592677311Sobrien /* Since registers are not part of the displacement string (except 592777311Sobrien when we're parsing offset operands), we may need to remove any 592877311Sobrien preceding '+' from the displacement string. */ 592977311Sobrien if (*intel_parser.disp != '\0' 593077311Sobrien && intel_parser.op_modifier != OFFSET_FLAT) 593177311Sobrien { 593277311Sobrien char *s = intel_parser.disp; 593377311Sobrien s += strlen (s) - 1; 593477311Sobrien if (*s == '+') 593577311Sobrien *s = '\0'; 593677311Sobrien } 593777311Sobrien 593877311Sobrien return 1; 593977311Sobrien } 594077311Sobrien 594177311Sobrien /* e11 id */ 594277311Sobrien else if (cur_token.code == T_ID) 594377311Sobrien { 594477311Sobrien /* Add the identifier to the displacement string. */ 594577311Sobrien strcat (intel_parser.disp, cur_token.str); 594677311Sobrien intel_match_token (T_ID); 594777311Sobrien 594877311Sobrien /* The identifier represents a memory reference only if it's not 594977311Sobrien preceded by an offset modifier. */ 595077311Sobrien if (intel_parser.op_modifier != OFFSET_FLAT) 595177311Sobrien intel_parser.is_mem = 1; 595277311Sobrien 595377311Sobrien return 1; 595477311Sobrien } 595577311Sobrien 595677311Sobrien /* e11 constant */ 595777311Sobrien else if (cur_token.code == T_CONST 595877311Sobrien || cur_token.code == '-' 595977311Sobrien || cur_token.code == '+') 596077311Sobrien { 596177311Sobrien char *save_str; 596277311Sobrien 596377311Sobrien /* Allow constants that start with `+' or `-'. */ 596477311Sobrien if (cur_token.code == '-' || cur_token.code == '+') 596577311Sobrien { 596677311Sobrien strcat (intel_parser.disp, cur_token.str); 596777311Sobrien intel_match_token (cur_token.code); 596877311Sobrien if (cur_token.code != T_CONST) 596977311Sobrien { 597077311Sobrien as_bad (_("Syntax error. Expecting a constant. Got `%s'.\n"), 597177311Sobrien cur_token.str); 597277311Sobrien return 0; 597377311Sobrien } 597477311Sobrien } 597577311Sobrien 597677311Sobrien save_str = (char *) malloc (strlen (cur_token.str) + 1); 597777311Sobrien if (save_str == NULL) 597877311Sobrien abort (); 597977311Sobrien strcpy (save_str, cur_token.str); 598077311Sobrien 598177311Sobrien /* Get the next token to check for register scaling. */ 598277311Sobrien intel_match_token (cur_token.code); 598377311Sobrien 598477311Sobrien /* Check if this constant is a scaling factor for an index register. */ 598577311Sobrien if (cur_token.code == '*') 598677311Sobrien { 598777311Sobrien if (intel_match_token ('*') && cur_token.code == T_REG) 598877311Sobrien { 598977311Sobrien if (!intel_parser.is_mem) 599077311Sobrien { 599177311Sobrien as_bad (_("Register scaling only allowed in memory operands.")); 599277311Sobrien return 0; 599377311Sobrien } 599477311Sobrien 599577311Sobrien /* The constant is followed by `* reg', so it must be 599677311Sobrien a valid scale. */ 599777311Sobrien if (strchr ("01248", *save_str)) 599877311Sobrien { 599977311Sobrien i.index_reg = cur_token.reg; 600077311Sobrien i.types[this_operand] |= BaseIndex; 600177311Sobrien 600277311Sobrien /* Set the scale after setting the register (otherwise, 600377311Sobrien i386_scale will complain) */ 600477311Sobrien i386_scale (save_str); 600577311Sobrien intel_match_token (T_REG); 600677311Sobrien 600777311Sobrien /* Since registers are not part of the displacement 600877311Sobrien string, we may need to remove any preceding '+' from 600977311Sobrien the displacement string. */ 601077311Sobrien if (*intel_parser.disp != '\0') 601177311Sobrien { 601277311Sobrien char *s = intel_parser.disp; 601377311Sobrien s += strlen (s) - 1; 601477311Sobrien if (*s == '+') 601577311Sobrien *s = '\0'; 601677311Sobrien } 601777311Sobrien 601877311Sobrien free (save_str); 601977311Sobrien 602077311Sobrien return 1; 602177311Sobrien } 602277311Sobrien else 602377311Sobrien return 0; 602477311Sobrien } 602577311Sobrien 602677311Sobrien /* The constant was not used for register scaling. Since we have 602777311Sobrien already consumed the token following `*' we now need to put it 602877311Sobrien back in the stream. */ 602977311Sobrien else 603077311Sobrien intel_putback_token (); 603177311Sobrien } 603277311Sobrien 603377311Sobrien /* Add the constant to the displacement string. */ 603477311Sobrien strcat (intel_parser.disp, save_str); 603577311Sobrien free (save_str); 603677311Sobrien 603777311Sobrien return 1; 603877311Sobrien } 603977311Sobrien 604077311Sobrien as_bad (_("Unrecognized token '%s'"), cur_token.str); 604177311Sobrien return 0; 604277311Sobrien} 604377311Sobrien 604477311Sobrien/* Match the given token against cur_token. If they match, read the next 604577311Sobrien token from the operand string. */ 604677311Sobrienstatic int 604777311Sobrienintel_match_token (code) 604877311Sobrien int code; 604977311Sobrien{ 605077311Sobrien if (cur_token.code == code) 605177311Sobrien { 605277311Sobrien intel_get_token (); 605377311Sobrien return 1; 605477311Sobrien } 605577311Sobrien else 605677311Sobrien { 605777311Sobrien as_bad (_("Unexpected token `%s'\n"), cur_token.str); 605877311Sobrien return 0; 605977311Sobrien } 606077311Sobrien} 606177311Sobrien 606277311Sobrien/* Read a new token from intel_parser.op_string and store it in cur_token. */ 606377311Sobrienstatic void 606477311Sobrienintel_get_token () 606577311Sobrien{ 606677311Sobrien char *end_op; 606777311Sobrien const reg_entry *reg; 606877311Sobrien struct intel_token new_token; 606977311Sobrien 607077311Sobrien new_token.code = T_NIL; 607177311Sobrien new_token.reg = NULL; 607277311Sobrien new_token.str = NULL; 607377311Sobrien 607477311Sobrien /* Free the memory allocated to the previous token and move 607577311Sobrien cur_token to prev_token. */ 607677311Sobrien if (prev_token.str) 607777311Sobrien free (prev_token.str); 607877311Sobrien 607977311Sobrien prev_token = cur_token; 608077311Sobrien 608177311Sobrien /* Skip whitespace. */ 608277311Sobrien while (is_space_char (*intel_parser.op_string)) 608377311Sobrien intel_parser.op_string++; 608477311Sobrien 608577311Sobrien /* Return an empty token if we find nothing else on the line. */ 608677311Sobrien if (*intel_parser.op_string == '\0') 608777311Sobrien { 608877311Sobrien cur_token = new_token; 608977311Sobrien return; 609077311Sobrien } 609177311Sobrien 609277311Sobrien /* The new token cannot be larger than the remainder of the operand 609377311Sobrien string. */ 609477311Sobrien new_token.str = (char *) malloc (strlen (intel_parser.op_string) + 1); 609577311Sobrien if (new_token.str == NULL) 609677311Sobrien abort (); 609777311Sobrien new_token.str[0] = '\0'; 609877311Sobrien 609977311Sobrien if (strchr ("0123456789", *intel_parser.op_string)) 610077311Sobrien { 610177311Sobrien char *p = new_token.str; 610277311Sobrien char *q = intel_parser.op_string; 610377311Sobrien new_token.code = T_CONST; 610477311Sobrien 610577311Sobrien /* Allow any kind of identifier char to encompass floating point and 610677311Sobrien hexadecimal numbers. */ 610777311Sobrien while (is_identifier_char (*q)) 610877311Sobrien *p++ = *q++; 610977311Sobrien *p = '\0'; 611077311Sobrien 611177311Sobrien /* Recognize special symbol names [0-9][bf]. */ 611277311Sobrien if (strlen (intel_parser.op_string) == 2 611377311Sobrien && (intel_parser.op_string[1] == 'b' 611477311Sobrien || intel_parser.op_string[1] == 'f')) 611577311Sobrien new_token.code = T_ID; 611677311Sobrien } 611777311Sobrien 611877311Sobrien else if (strchr ("+-/*:[]()", *intel_parser.op_string)) 611977311Sobrien { 612077311Sobrien new_token.code = *intel_parser.op_string; 612177311Sobrien new_token.str[0] = *intel_parser.op_string; 612277311Sobrien new_token.str[1] = '\0'; 612377311Sobrien } 612477311Sobrien 612577311Sobrien else if ((*intel_parser.op_string == REGISTER_PREFIX || allow_naked_reg) 612677311Sobrien && ((reg = parse_register (intel_parser.op_string, &end_op)) != NULL)) 612777311Sobrien { 612877311Sobrien new_token.code = T_REG; 612977311Sobrien new_token.reg = reg; 613077311Sobrien 613177311Sobrien if (*intel_parser.op_string == REGISTER_PREFIX) 613277311Sobrien { 613377311Sobrien new_token.str[0] = REGISTER_PREFIX; 613477311Sobrien new_token.str[1] = '\0'; 613577311Sobrien } 613677311Sobrien 613777311Sobrien strcat (new_token.str, reg->reg_name); 613877311Sobrien } 613977311Sobrien 614077311Sobrien else if (is_identifier_char (*intel_parser.op_string)) 614177311Sobrien { 614277311Sobrien char *p = new_token.str; 614377311Sobrien char *q = intel_parser.op_string; 614477311Sobrien 614577311Sobrien /* A '.' or '$' followed by an identifier char is an identifier. 614677311Sobrien Otherwise, it's operator '.' followed by an expression. */ 614777311Sobrien if ((*q == '.' || *q == '$') && !is_identifier_char (*(q + 1))) 614877311Sobrien { 614977311Sobrien new_token.code = *q; 615077311Sobrien new_token.str[0] = *q; 615177311Sobrien new_token.str[1] = '\0'; 615277311Sobrien } 615377311Sobrien else 615477311Sobrien { 615577311Sobrien while (is_identifier_char (*q) || *q == '@') 615677311Sobrien *p++ = *q++; 615777311Sobrien *p = '\0'; 615877311Sobrien 615977311Sobrien if (strcasecmp (new_token.str, "BYTE") == 0) 616077311Sobrien new_token.code = T_BYTE; 616177311Sobrien 616277311Sobrien else if (strcasecmp (new_token.str, "WORD") == 0) 616377311Sobrien new_token.code = T_WORD; 616477311Sobrien 616577311Sobrien else if (strcasecmp (new_token.str, "DWORD") == 0) 616677311Sobrien new_token.code = T_DWORD; 616777311Sobrien 616877311Sobrien else if (strcasecmp (new_token.str, "QWORD") == 0) 616977311Sobrien new_token.code = T_QWORD; 617077311Sobrien 617177311Sobrien else if (strcasecmp (new_token.str, "XWORD") == 0) 617277311Sobrien new_token.code = T_XWORD; 617377311Sobrien 617477311Sobrien else if (strcasecmp (new_token.str, "PTR") == 0) 617577311Sobrien new_token.code = T_PTR; 617677311Sobrien 617777311Sobrien else if (strcasecmp (new_token.str, "SHORT") == 0) 617877311Sobrien new_token.code = T_SHORT; 617977311Sobrien 618077311Sobrien else if (strcasecmp (new_token.str, "OFFSET") == 0) 618177311Sobrien { 618277311Sobrien new_token.code = T_OFFSET; 618377311Sobrien 618477311Sobrien /* ??? This is not mentioned in the MASM grammar but gcc 618577311Sobrien makes use of it with -mintel-syntax. OFFSET may be 618677311Sobrien followed by FLAT: */ 618777311Sobrien if (strncasecmp (q, " FLAT:", 6) == 0) 618877311Sobrien strcat (new_token.str, " FLAT:"); 618977311Sobrien } 619077311Sobrien 619177311Sobrien /* ??? This is not mentioned in the MASM grammar. */ 619277311Sobrien else if (strcasecmp (new_token.str, "FLAT") == 0) 619377311Sobrien new_token.code = T_OFFSET; 619477311Sobrien 619577311Sobrien else 619677311Sobrien new_token.code = T_ID; 619777311Sobrien } 619877311Sobrien } 619977311Sobrien 620077311Sobrien else 620177311Sobrien as_bad (_("Unrecognized token `%s'\n"), intel_parser.op_string); 620277311Sobrien 620377311Sobrien intel_parser.op_string += strlen (new_token.str); 620477311Sobrien cur_token = new_token; 620577311Sobrien} 620677311Sobrien 620777311Sobrien/* Put cur_token back into the token stream and make cur_token point to 620877311Sobrien prev_token. */ 620977311Sobrienstatic void 621077311Sobrienintel_putback_token () 621177311Sobrien{ 621277311Sobrien intel_parser.op_string -= strlen (cur_token.str); 621377311Sobrien free (cur_token.str); 621477311Sobrien cur_token = prev_token; 621577311Sobrien 621677311Sobrien /* Forget prev_token. */ 621777311Sobrien prev_token.code = T_NIL; 621877311Sobrien prev_token.reg = NULL; 621977311Sobrien prev_token.str = NULL; 622077311Sobrien} 6221130570Sobrien 6222130570Sobrienint 6223130570Sobrientc_x86_regname_to_dw2regnum (const char *regname) 6224130570Sobrien{ 6225130570Sobrien unsigned int regnum; 6226130570Sobrien unsigned int regnames_count; 6227130570Sobrien char *regnames_32[] = 6228130570Sobrien { 6229130570Sobrien "eax", "ecx", "edx", "ebx", 6230130570Sobrien "esp", "ebp", "esi", "edi", 6231130570Sobrien "eip" 6232130570Sobrien }; 6233130570Sobrien char *regnames_64[] = 6234130570Sobrien { 6235130570Sobrien "rax", "rbx", "rcx", "rdx", 6236130570Sobrien "rdi", "rsi", "rbp", "rsp", 6237130570Sobrien "r8", "r9", "r10", "r11", 6238130570Sobrien "r12", "r13", "r14", "r15", 6239130570Sobrien "rip" 6240130570Sobrien }; 6241130570Sobrien char **regnames; 6242130570Sobrien 6243130570Sobrien if (flag_code == CODE_64BIT) 6244130570Sobrien { 6245130570Sobrien regnames = regnames_64; 6246130570Sobrien regnames_count = ARRAY_SIZE (regnames_64); 6247130570Sobrien } 6248130570Sobrien else 6249130570Sobrien { 6250130570Sobrien regnames = regnames_32; 6251130570Sobrien regnames_count = ARRAY_SIZE (regnames_32); 6252130570Sobrien } 6253130570Sobrien 6254130570Sobrien for (regnum = 0; regnum < regnames_count; regnum++) 6255130570Sobrien if (strcmp (regname, regnames[regnum]) == 0) 6256130570Sobrien return regnum; 6257130570Sobrien 6258130570Sobrien return -1; 6259130570Sobrien} 6260130570Sobrien 6261130570Sobrienvoid 6262130570Sobrientc_x86_frame_initial_instructions (void) 6263130570Sobrien{ 6264130570Sobrien static unsigned int sp_regno; 6265130570Sobrien 6266130570Sobrien if (!sp_regno) 6267130570Sobrien sp_regno = tc_x86_regname_to_dw2regnum (flag_code == CODE_64BIT 6268130570Sobrien ? "rsp" : "esp"); 6269130570Sobrien 6270130570Sobrien cfi_add_CFA_def_cfa (sp_regno, -x86_cie_data_alignment); 6271130570Sobrien cfi_add_CFA_offset (x86_dwarf2_return_column, x86_cie_data_alignment); 6272130570Sobrien} 6273