tc-i386.c revision 91054
133965Sjdp/* i386.c -- Assemble code for the Intel 80386 278840Sobrien Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 391054Sobrien 2000, 2001, 2002 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 2457823Scracauer/* $FreeBSD: head/contrib/binutils/gas/config/tc-i386.c 91054 2002-02-22 04:51:15Z obrien $ */ 2557823Scracauer 2633965Sjdp 2777311Sobrien/* Intel 80386 machine specific gas. 2877311Sobrien Written by Eliot Dresselhaus (eliot@mgm.mit.edu). 2977311Sobrien x86_64 support by Jan Hubicka (jh@suse.cz) 3077311Sobrien Bugs & suggestions are completely welcome. This is free software. 3177311Sobrien Please help us make it better. */ 3277311Sobrien 3333965Sjdp#include "as.h" 3489867Sobrien#include "safe-ctype.h" 3533965Sjdp#include "subsegs.h" 3677311Sobrien#include "dwarf2dbg.h" 3733965Sjdp#include "opcode/i386.h" 3833965Sjdp 3960519Sobrien#ifndef REGISTER_WARNINGS 4060519Sobrien#define REGISTER_WARNINGS 1 4133965Sjdp#endif 4233965Sjdp 4360519Sobrien#ifndef INFER_ADDR_PREFIX 4460519Sobrien#define INFER_ADDR_PREFIX 1 4560519Sobrien#endif 4660519Sobrien 4760519Sobrien#ifndef SCALE1_WHEN_NO_INDEX 4860519Sobrien/* Specifying a scale factor besides 1 when there is no index is 4960519Sobrien futile. eg. `mov (%ebx,2),%al' does exactly the same as 5060519Sobrien `mov (%ebx),%al'. To slavishly follow what the programmer 5160519Sobrien specified, set SCALE1_WHEN_NO_INDEX to 0. */ 5260519Sobrien#define SCALE1_WHEN_NO_INDEX 1 5360519Sobrien#endif 5460519Sobrien 5591054Sobrien#ifndef true 5660519Sobrien#define true 1 5791054Sobrien#endif 5891054Sobrien#ifndef false 5960519Sobrien#define false 0 6091054Sobrien#endif 6160519Sobrien 6260519Sobrienstatic unsigned int mode_from_disp_size PARAMS ((unsigned int)); 6377311Sobrienstatic int fits_in_signed_byte PARAMS ((offsetT)); 6477311Sobrienstatic int fits_in_unsigned_byte PARAMS ((offsetT)); 6577311Sobrienstatic int fits_in_unsigned_word PARAMS ((offsetT)); 6677311Sobrienstatic int fits_in_signed_word PARAMS ((offsetT)); 6777311Sobrienstatic int fits_in_unsigned_long PARAMS ((offsetT)); 6877311Sobrienstatic int fits_in_signed_long PARAMS ((offsetT)); 6977311Sobrienstatic int smallest_imm_type PARAMS ((offsetT)); 7077311Sobrienstatic offsetT offset_in_range PARAMS ((offsetT, int)); 7160519Sobrienstatic int add_prefix PARAMS ((unsigned int)); 7277311Sobrienstatic void set_code_flag PARAMS ((int)); 7377311Sobrienstatic void set_16bit_gcc_code_flag PARAMS ((int)); 7460519Sobrienstatic void set_intel_syntax PARAMS ((int)); 7577311Sobrienstatic void set_cpu_arch PARAMS ((int)); 7660519Sobrien 7733965Sjdp#ifdef BFD_ASSEMBLER 7833965Sjdpstatic bfd_reloc_code_real_type reloc 7977311Sobrien PARAMS ((int, int, int, bfd_reloc_code_real_type)); 8078840Sobrien#define RELOC_ENUM enum bfd_reloc_code_real 8178840Sobrien#else 8278840Sobrien#define RELOC_ENUM int 8333965Sjdp#endif 8433965Sjdp 8577311Sobrien#ifndef DEFAULT_ARCH 8677311Sobrien#define DEFAULT_ARCH "i386" 8777311Sobrien#endif 8889867Sobrienstatic const char *default_arch = DEFAULT_ARCH; 8977311Sobrien 9033965Sjdp/* 'md_assemble ()' gathers together information and puts it into a 9177311Sobrien i386_insn. */ 9233965Sjdp 9360519Sobrienunion i386_op 9460519Sobrien { 9560519Sobrien expressionS *disps; 9660519Sobrien expressionS *imms; 9760519Sobrien const reg_entry *regs; 9860519Sobrien }; 9960519Sobrien 10033965Sjdpstruct _i386_insn 10133965Sjdp { 10277311Sobrien /* TM holds the template for the insn were currently assembling. */ 10333965Sjdp template tm; 10460519Sobrien 10560519Sobrien /* SUFFIX holds the instruction mnemonic suffix if given. 10660519Sobrien (e.g. 'l' for 'movl') */ 10733965Sjdp char suffix; 10833965Sjdp 10977311Sobrien /* OPERANDS gives the number of given operands. */ 11033965Sjdp unsigned int operands; 11133965Sjdp 11233965Sjdp /* REG_OPERANDS, DISP_OPERANDS, MEM_OPERANDS, IMM_OPERANDS give the number 11333965Sjdp of given register, displacement, memory operands and immediate 11477311Sobrien operands. */ 11533965Sjdp unsigned int reg_operands, disp_operands, mem_operands, imm_operands; 11633965Sjdp 11733965Sjdp /* TYPES [i] is the type (see above #defines) which tells us how to 11860519Sobrien use OP[i] for the corresponding operand. */ 11933965Sjdp unsigned int types[MAX_OPERANDS]; 12033965Sjdp 12160519Sobrien /* Displacement expression, immediate expression, or register for each 12260519Sobrien operand. */ 12360519Sobrien union i386_op op[MAX_OPERANDS]; 12433965Sjdp 12577311Sobrien /* Flags for operands. */ 12677311Sobrien unsigned int flags[MAX_OPERANDS]; 12777311Sobrien#define Operand_PCrel 1 12877311Sobrien 12933965Sjdp /* Relocation type for operand */ 13078840Sobrien RELOC_ENUM reloc[MAX_OPERANDS]; 13133965Sjdp 13233965Sjdp /* BASE_REG, INDEX_REG, and LOG2_SCALE_FACTOR are used to encode 13333965Sjdp the base index byte below. */ 13460519Sobrien const reg_entry *base_reg; 13560519Sobrien const reg_entry *index_reg; 13633965Sjdp unsigned int log2_scale_factor; 13733965Sjdp 13860519Sobrien /* SEG gives the seg_entries of this insn. They are zero unless 13977311Sobrien explicit segment overrides are given. */ 14077311Sobrien const seg_entry *seg[2]; 14133965Sjdp 14233965Sjdp /* PREFIX holds all the given prefix opcodes (usually null). 14360519Sobrien PREFIXES is the number of prefix opcodes. */ 14460519Sobrien unsigned int prefixes; 14533965Sjdp unsigned char prefix[MAX_PREFIXES]; 14633965Sjdp 14760519Sobrien /* RM and SIB are the modrm byte and the sib byte where the 14860519Sobrien addressing modes of this insn are encoded. */ 14933965Sjdp 15033965Sjdp modrm_byte rm; 15177311Sobrien rex_byte rex; 15260519Sobrien sib_byte sib; 15333965Sjdp }; 15433965Sjdp 15533965Sjdptypedef struct _i386_insn i386_insn; 15633965Sjdp 15760519Sobrien/* List of chars besides those in app.c:symbol_chars that can start an 15860519Sobrien operand. Used to prevent the scrubber eating vital white-space. */ 15960519Sobrien#ifdef LEX_AT 16060519Sobrienconst char extra_symbol_chars[] = "*%-(@"; 16160519Sobrien#else 16260519Sobrienconst char extra_symbol_chars[] = "*%-("; 16360519Sobrien#endif 16460519Sobrien 16533965Sjdp/* This array holds the chars that always start a comment. If the 16677311Sobrien pre-processor is disabled, these aren't very useful. */ 16789867Sobrien#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && ! defined (TE_LINUX) && !defined(TE_FreeBSD) && !defined(TE_NetBSD)) 16860519Sobrien/* Putting '/' here makes it impossible to use the divide operator. 16960519Sobrien However, we need it for compatibility with SVR4 systems. */ 17033965Sjdpconst char comment_chars[] = "#/"; 17160519Sobrien#define PREFIX_SEPARATOR '\\' 17233965Sjdp#else 17333965Sjdpconst char comment_chars[] = "#"; 17460519Sobrien#define PREFIX_SEPARATOR '/' 17533965Sjdp#endif 17633965Sjdp 17733965Sjdp/* This array holds the chars that only start a comment at the beginning of 17833965Sjdp a line. If the line seems to have the form '# 123 filename' 17977311Sobrien .line and .file directives will appear in the pre-processed output. 18077311Sobrien Note that input_file.c hand checks for '#' at the beginning of the 18133965Sjdp first line of the input file. This is because the compiler outputs 18277311Sobrien #NO_APP at the beginning of its output. 18377311Sobrien Also note that comments started like this one will always work if 18433965Sjdp '/' isn't otherwise defined. */ 18589867Sobrien#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && ! defined (TE_LINUX) && !defined(TE_FreeBSD) && !defined(TE_NetBSD)) 18633965Sjdpconst char line_comment_chars[] = ""; 18733965Sjdp#else 18833965Sjdpconst char line_comment_chars[] = "/"; 18933965Sjdp#endif 19060519Sobrien 19177311Sobrienconst char line_separator_chars[] = ";"; 19233965Sjdp 19377311Sobrien/* Chars that can be used to separate mant from exp in floating point 19477311Sobrien nums. */ 19533965Sjdpconst char EXP_CHARS[] = "eE"; 19633965Sjdp 19777311Sobrien/* Chars that mean this number is a floating point constant 19877311Sobrien As in 0f12.456 19977311Sobrien or 0d1.2345e12. */ 20033965Sjdpconst char FLT_CHARS[] = "fFdDxX"; 20133965Sjdp 20277311Sobrien/* Tables for lexical analysis. */ 20360519Sobrienstatic char mnemonic_chars[256]; 20433965Sjdpstatic char register_chars[256]; 20533965Sjdpstatic char operand_chars[256]; 20633965Sjdpstatic char identifier_chars[256]; 20733965Sjdpstatic char digit_chars[256]; 20833965Sjdp 20977311Sobrien/* Lexical macros. */ 21060519Sobrien#define is_mnemonic_char(x) (mnemonic_chars[(unsigned char) x]) 21133965Sjdp#define is_operand_char(x) (operand_chars[(unsigned char) x]) 21233965Sjdp#define is_register_char(x) (register_chars[(unsigned char) x]) 21360519Sobrien#define is_space_char(x) ((x) == ' ') 21433965Sjdp#define is_identifier_char(x) (identifier_chars[(unsigned char) x]) 21533965Sjdp#define is_digit_char(x) (digit_chars[(unsigned char) x]) 21633965Sjdp 21777311Sobrien/* All non-digit non-letter charcters that may occur in an operand. */ 21833965Sjdpstatic char operand_special_chars[] = "%$-+(,)*._~/<>|&^!:[@]"; 21933965Sjdp 22033965Sjdp/* md_assemble() always leaves the strings it's passed unaltered. To 22133965Sjdp effect this we maintain a stack of saved characters that we've smashed 22233965Sjdp with '\0's (indicating end of strings for various sub-fields of the 22377311Sobrien assembler instruction). */ 22433965Sjdpstatic char save_stack[32]; 22577311Sobrienstatic char *save_stack_p; 22660519Sobrien#define END_STRING_AND_SAVE(s) \ 22760519Sobrien do { *save_stack_p++ = *(s); *(s) = '\0'; } while (0) 22860519Sobrien#define RESTORE_END_STRING(s) \ 22960519Sobrien do { *(s) = *--save_stack_p; } while (0) 23033965Sjdp 23177311Sobrien/* The instruction we're assembling. */ 23233965Sjdpstatic i386_insn i; 23333965Sjdp 23460519Sobrien/* Possible templates for current insn. */ 23560519Sobrienstatic const templates *current_templates; 23660519Sobrien 23777311Sobrien/* Per instruction expressionS buffers: 2 displacements & 2 immediate max. */ 23833965Sjdpstatic expressionS disp_expressions[2], im_expressions[2]; 23933965Sjdp 24077311Sobrien/* Current operand we are working on. */ 24177311Sobrienstatic int this_operand; 24233965Sjdp 24377311Sobrien/* We support four different modes. FLAG_CODE variable is used to distinguish 24477311Sobrien these. */ 24533965Sjdp 24677311Sobrienenum flag_code { 24777311Sobrien CODE_32BIT, 24877311Sobrien CODE_16BIT, 24977311Sobrien CODE_64BIT }; 25078840Sobrien#define NUM_FLAG_CODE ((int) CODE_64BIT + 1) 25133965Sjdp 25277311Sobrienstatic enum flag_code flag_code; 25377311Sobrienstatic int use_rela_relocations = 0; 25460519Sobrien 25577311Sobrien/* The names used to print error messages. */ 25677311Sobrienstatic const char *flag_code_names[] = 25777311Sobrien { 25877311Sobrien "32", 25977311Sobrien "16", 26077311Sobrien "64" 26177311Sobrien }; 26260519Sobrien 26377311Sobrien/* 1 for intel syntax, 26477311Sobrien 0 if att syntax. */ 26577311Sobrienstatic int intel_syntax = 0; 26660519Sobrien 26777311Sobrien/* 1 if register prefix % not required. */ 26877311Sobrienstatic int allow_naked_reg = 0; 26977311Sobrien 27077311Sobrien/* Used in 16 bit gcc mode to add an l suffix to call, ret, enter, 27177311Sobrien leave, push, and pop instructions so that gcc has the same stack 27277311Sobrien frame as in 32 bit mode. */ 27377311Sobrienstatic char stackop_size = '\0'; 27477311Sobrien 27577311Sobrien/* Non-zero to quieten some warnings. */ 27677311Sobrienstatic int quiet_warnings = 0; 27777311Sobrien 27877311Sobrien/* CPU name. */ 27977311Sobrienstatic const char *cpu_arch_name = NULL; 28077311Sobrien 28177311Sobrien/* CPU feature flags. */ 28277311Sobrienstatic unsigned int cpu_arch_flags = CpuUnknownFlags|CpuNo64; 28377311Sobrien 28478840Sobrien/* If set, conditional jumps are not automatically promoted to handle 28578840Sobrien larger than a byte offset. */ 28678840Sobrienstatic unsigned int no_cond_jump_promotion = 0; 28778840Sobrien 28833965Sjdp/* Interface to relax_segment. 28978840Sobrien There are 3 major relax states for 386 jump insns because the 29078840Sobrien different types of jumps add different sizes to frags when we're 29178840Sobrien figuring out what sort of jump to choose to reach a given label. */ 29233965Sjdp 29377311Sobrien/* Types. */ 29478840Sobrien#define UNCOND_JUMP 0 29577311Sobrien#define COND_JUMP 1 29678840Sobrien#define COND_JUMP86 2 29778840Sobrien 29877311Sobrien/* Sizes. */ 29960519Sobrien#define CODE16 1 30060519Sobrien#define SMALL 0 30160519Sobrien#define SMALL16 (SMALL|CODE16) 30260519Sobrien#define BIG 2 30360519Sobrien#define BIG16 (BIG|CODE16) 30433965Sjdp 30533965Sjdp#ifndef INLINE 30633965Sjdp#ifdef __GNUC__ 30733965Sjdp#define INLINE __inline__ 30833965Sjdp#else 30933965Sjdp#define INLINE 31033965Sjdp#endif 31133965Sjdp#endif 31233965Sjdp 31378840Sobrien#define ENCODE_RELAX_STATE(type, size) \ 31478840Sobrien ((relax_substateT) (((type) << 2) | (size))) 31578840Sobrien#define TYPE_FROM_RELAX_STATE(s) \ 31678840Sobrien ((s) >> 2) 31778840Sobrien#define DISP_SIZE_FROM_RELAX_STATE(s) \ 31878840Sobrien ((((s) & 3) == BIG ? 4 : (((s) & 3) == BIG16 ? 2 : 1))) 31933965Sjdp 32060519Sobrien/* This table is used by relax_frag to promote short jumps to long 32160519Sobrien ones where necessary. SMALL (short) jumps may be promoted to BIG 32260519Sobrien (32 bit long) ones, and SMALL16 jumps to BIG16 (16 bit long). We 32360519Sobrien don't allow a short jump in a 32 bit code segment to be promoted to 32460519Sobrien a 16 bit offset jump because it's slower (requires data size 32560519Sobrien prefix), and doesn't work, unless the destination is in the bottom 32660519Sobrien 64k of the code segment (The top 16 bits of eip are zeroed). */ 32760519Sobrien 32833965Sjdpconst relax_typeS md_relax_table[] = 32933965Sjdp{ 33060519Sobrien /* The fields are: 33160519Sobrien 1) most positive reach of this state, 33260519Sobrien 2) most negative reach of this state, 33378840Sobrien 3) how many bytes this mode will have in the variable part of the frag 33477311Sobrien 4) which index into the table to try if we can't fit into this one. */ 33533965Sjdp 33678840Sobrien /* UNCOND_JUMP states. */ 33778840Sobrien {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG)}, 33878840Sobrien {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16)}, 33978840Sobrien /* dword jmp adds 4 bytes to frag: 34078840Sobrien 0 extra opcode bytes, 4 displacement bytes. */ 34133965Sjdp {0, 0, 4, 0}, 34278840Sobrien /* word jmp adds 2 byte2 to frag: 34378840Sobrien 0 extra opcode bytes, 2 displacement bytes. */ 34460519Sobrien {0, 0, 2, 0}, 34533965Sjdp 34678840Sobrien /* COND_JUMP states. */ 34778840Sobrien {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP, BIG)}, 34878840Sobrien {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP, BIG16)}, 34978840Sobrien /* dword conditionals adds 5 bytes to frag: 35078840Sobrien 1 extra opcode byte, 4 displacement bytes. */ 35178840Sobrien {0, 0, 5, 0}, 35278840Sobrien /* word conditionals add 3 bytes to frag: 35378840Sobrien 1 extra opcode byte, 2 displacement bytes. */ 35433965Sjdp {0, 0, 3, 0}, 35533965Sjdp 35678840Sobrien /* COND_JUMP86 states. */ 35778840Sobrien {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP86, BIG)}, 35878840Sobrien {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP86, BIG16)}, 35978840Sobrien /* dword conditionals adds 5 bytes to frag: 36078840Sobrien 1 extra opcode byte, 4 displacement bytes. */ 36178840Sobrien {0, 0, 5, 0}, 36278840Sobrien /* word conditionals add 4 bytes to frag: 36378840Sobrien 1 displacement byte and a 3 byte long branch insn. */ 36478840Sobrien {0, 0, 4, 0} 36533965Sjdp}; 36633965Sjdp 36777311Sobrienstatic const arch_entry cpu_arch[] = { 36877311Sobrien {"i8086", Cpu086 }, 36977311Sobrien {"i186", Cpu086|Cpu186 }, 37077311Sobrien {"i286", Cpu086|Cpu186|Cpu286 }, 37177311Sobrien {"i386", Cpu086|Cpu186|Cpu286|Cpu386 }, 37277311Sobrien {"i486", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486 }, 37377311Sobrien {"i586", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuMMX }, 37477311Sobrien {"i686", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX|CpuSSE }, 37577311Sobrien {"pentium", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuMMX }, 37677311Sobrien {"pentiumpro",Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX|CpuSSE }, 37777311Sobrien {"pentium4", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuSSE|CpuSSE2 }, 37877311Sobrien {"k6", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuK6|CpuMMX|Cpu3dnow }, 37977311Sobrien {"athlon", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuAthlon|CpuMMX|Cpu3dnow }, 38077311Sobrien {"sledgehammer",Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuAthlon|CpuSledgehammer|CpuMMX|Cpu3dnow|CpuSSE|CpuSSE2 }, 38177311Sobrien {NULL, 0 } 38277311Sobrien}; 38333965Sjdp 38433965Sjdpvoid 38533965Sjdpi386_align_code (fragP, count) 38633965Sjdp fragS *fragP; 38733965Sjdp int count; 38833965Sjdp{ 38977311Sobrien /* Various efficient no-op patterns for aligning code labels. 39077311Sobrien Note: Don't try to assemble the instructions in the comments. 39177311Sobrien 0L and 0w are not legal. */ 39233965Sjdp static const char f32_1[] = 39333965Sjdp {0x90}; /* nop */ 39433965Sjdp static const char f32_2[] = 39533965Sjdp {0x89,0xf6}; /* movl %esi,%esi */ 39633965Sjdp static const char f32_3[] = 39733965Sjdp {0x8d,0x76,0x00}; /* leal 0(%esi),%esi */ 39833965Sjdp static const char f32_4[] = 39933965Sjdp {0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ 40033965Sjdp static const char f32_5[] = 40133965Sjdp {0x90, /* nop */ 40233965Sjdp 0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ 40333965Sjdp static const char f32_6[] = 40433965Sjdp {0x8d,0xb6,0x00,0x00,0x00,0x00}; /* leal 0L(%esi),%esi */ 40533965Sjdp static const char f32_7[] = 40633965Sjdp {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ 40733965Sjdp static const char f32_8[] = 40833965Sjdp {0x90, /* nop */ 40933965Sjdp 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ 41033965Sjdp static const char f32_9[] = 41133965Sjdp {0x89,0xf6, /* movl %esi,%esi */ 41233965Sjdp 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ 41333965Sjdp static const char f32_10[] = 41433965Sjdp {0x8d,0x76,0x00, /* leal 0(%esi),%esi */ 41533965Sjdp 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ 41633965Sjdp static const char f32_11[] = 41733965Sjdp {0x8d,0x74,0x26,0x00, /* leal 0(%esi,1),%esi */ 41833965Sjdp 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ 41933965Sjdp static const char f32_12[] = 42033965Sjdp {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ 42133965Sjdp 0x8d,0xbf,0x00,0x00,0x00,0x00}; /* leal 0L(%edi),%edi */ 42233965Sjdp static const char f32_13[] = 42333965Sjdp {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ 42433965Sjdp 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ 42533965Sjdp static const char f32_14[] = 42633965Sjdp {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00, /* leal 0L(%esi,1),%esi */ 42733965Sjdp 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ 42833965Sjdp static const char f32_15[] = 42933965Sjdp {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */ 43033965Sjdp 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90}; 43160519Sobrien static const char f16_3[] = 43260519Sobrien {0x8d,0x74,0x00}; /* lea 0(%esi),%esi */ 43333965Sjdp static const char f16_4[] = 43438891Sjdp {0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */ 43533965Sjdp static const char f16_5[] = 43633965Sjdp {0x90, /* nop */ 43738891Sjdp 0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */ 43833965Sjdp static const char f16_6[] = 43933965Sjdp {0x89,0xf6, /* mov %si,%si */ 44033965Sjdp 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ 44133965Sjdp static const char f16_7[] = 44238891Sjdp {0x8d,0x74,0x00, /* lea 0(%si),%si */ 44333965Sjdp 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ 44433965Sjdp static const char f16_8[] = 44538891Sjdp {0x8d,0xb4,0x00,0x00, /* lea 0w(%si),%si */ 44633965Sjdp 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ 44733965Sjdp static const char *const f32_patt[] = { 44833965Sjdp f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8, 44933965Sjdp f32_9, f32_10, f32_11, f32_12, f32_13, f32_14, f32_15 45033965Sjdp }; 45133965Sjdp static const char *const f16_patt[] = { 45260519Sobrien f32_1, f32_2, f16_3, f16_4, f16_5, f16_6, f16_7, f16_8, 45333965Sjdp f32_15, f32_15, f32_15, f32_15, f32_15, f32_15, f32_15 45433965Sjdp }; 45533965Sjdp 45677311Sobrien /* ??? We can't use these fillers for x86_64, since they often kills the 45777311Sobrien upper halves. Solve later. */ 45877311Sobrien if (flag_code == CODE_64BIT) 45977311Sobrien count = 1; 46077311Sobrien 46133965Sjdp if (count > 0 && count <= 15) 46233965Sjdp { 46377311Sobrien if (flag_code == CODE_16BIT) 46433965Sjdp { 46577311Sobrien memcpy (fragP->fr_literal + fragP->fr_fix, 46677311Sobrien f16_patt[count - 1], count); 46777311Sobrien if (count > 8) 46877311Sobrien /* Adjust jump offset. */ 46933965Sjdp fragP->fr_literal[fragP->fr_fix + 1] = count - 2; 47033965Sjdp } 47133965Sjdp else 47277311Sobrien memcpy (fragP->fr_literal + fragP->fr_fix, 47377311Sobrien f32_patt[count - 1], count); 47433965Sjdp fragP->fr_var = count; 47533965Sjdp } 47633965Sjdp} 47733965Sjdp 47833965Sjdpstatic char *output_invalid PARAMS ((int c)); 47933965Sjdpstatic int i386_operand PARAMS ((char *operand_string)); 48060519Sobrienstatic int i386_intel_operand PARAMS ((char *operand_string, int got_a_float)); 48160519Sobrienstatic const reg_entry *parse_register PARAMS ((char *reg_string, 48260519Sobrien char **end_op)); 48360519Sobrien 48433965Sjdp#ifndef I386COFF 48533965Sjdpstatic void s_bss PARAMS ((int)); 48633965Sjdp#endif 48733965Sjdp 48877311SobriensymbolS *GOT_symbol; /* Pre-defined "_GLOBAL_OFFSET_TABLE_". */ 48933965Sjdp 49060519Sobrienstatic INLINE unsigned int 49133965Sjdpmode_from_disp_size (t) 49260519Sobrien unsigned int t; 49333965Sjdp{ 49477311Sobrien return (t & Disp8) ? 1 : (t & (Disp16 | Disp32 | Disp32S)) ? 2 : 0; 49533965Sjdp} 49633965Sjdp 49733965Sjdpstatic INLINE int 49833965Sjdpfits_in_signed_byte (num) 49977311Sobrien offsetT num; 50033965Sjdp{ 50133965Sjdp return (num >= -128) && (num <= 127); 50277311Sobrien} 50333965Sjdp 50433965Sjdpstatic INLINE int 50533965Sjdpfits_in_unsigned_byte (num) 50677311Sobrien offsetT num; 50733965Sjdp{ 50833965Sjdp return (num & 0xff) == num; 50977311Sobrien} 51033965Sjdp 51133965Sjdpstatic INLINE int 51233965Sjdpfits_in_unsigned_word (num) 51377311Sobrien offsetT num; 51433965Sjdp{ 51533965Sjdp return (num & 0xffff) == num; 51677311Sobrien} 51733965Sjdp 51833965Sjdpstatic INLINE int 51933965Sjdpfits_in_signed_word (num) 52077311Sobrien offsetT num; 52133965Sjdp{ 52233965Sjdp return (-32768 <= num) && (num <= 32767); 52377311Sobrien} 52477311Sobrienstatic INLINE int 52577311Sobrienfits_in_signed_long (num) 52677311Sobrien offsetT num ATTRIBUTE_UNUSED; 52777311Sobrien{ 52877311Sobrien#ifndef BFD64 52977311Sobrien return 1; 53077311Sobrien#else 53177311Sobrien return (!(((offsetT) -1 << 31) & num) 53277311Sobrien || (((offsetT) -1 << 31) & num) == ((offsetT) -1 << 31)); 53377311Sobrien#endif 53477311Sobrien} /* fits_in_signed_long() */ 53577311Sobrienstatic INLINE int 53677311Sobrienfits_in_unsigned_long (num) 53777311Sobrien offsetT num ATTRIBUTE_UNUSED; 53877311Sobrien{ 53977311Sobrien#ifndef BFD64 54077311Sobrien return 1; 54177311Sobrien#else 54277311Sobrien return (num & (((offsetT) 2 << 31) - 1)) == num; 54377311Sobrien#endif 54477311Sobrien} /* fits_in_unsigned_long() */ 54533965Sjdp 54633965Sjdpstatic int 54733965Sjdpsmallest_imm_type (num) 54877311Sobrien offsetT num; 54933965Sjdp{ 55089867Sobrien if (cpu_arch_flags != (Cpu086 | Cpu186 | Cpu286 | Cpu386 | Cpu486 | CpuNo64)) 55177311Sobrien { 55277311Sobrien /* This code is disabled on the 486 because all the Imm1 forms 55377311Sobrien in the opcode table are slower on the i486. They're the 55477311Sobrien versions with the implicitly specified single-position 55577311Sobrien displacement, which has another syntax if you really want to 55677311Sobrien use that form. */ 55777311Sobrien if (num == 1) 55877311Sobrien return Imm1 | Imm8 | Imm8S | Imm16 | Imm32 | Imm32S | Imm64; 55977311Sobrien } 56033965Sjdp return (fits_in_signed_byte (num) 56177311Sobrien ? (Imm8S | Imm8 | Imm16 | Imm32 | Imm32S | Imm64) 56233965Sjdp : fits_in_unsigned_byte (num) 56377311Sobrien ? (Imm8 | Imm16 | Imm32 | Imm32S | Imm64) 56433965Sjdp : (fits_in_signed_word (num) || fits_in_unsigned_word (num)) 56577311Sobrien ? (Imm16 | Imm32 | Imm32S | Imm64) 56677311Sobrien : fits_in_signed_long (num) 56777311Sobrien ? (Imm32 | Imm32S | Imm64) 56877311Sobrien : fits_in_unsigned_long (num) 56977311Sobrien ? (Imm32 | Imm64) 57077311Sobrien : Imm64); 57177311Sobrien} 57233965Sjdp 57377311Sobrienstatic offsetT 57477311Sobrienoffset_in_range (val, size) 57577311Sobrien offsetT val; 57677311Sobrien int size; 57777311Sobrien{ 57877311Sobrien addressT mask; 57977311Sobrien 58077311Sobrien switch (size) 58177311Sobrien { 58277311Sobrien case 1: mask = ((addressT) 1 << 8) - 1; break; 58377311Sobrien case 2: mask = ((addressT) 1 << 16) - 1; break; 58477311Sobrien case 4: mask = ((addressT) 2 << 31) - 1; break; 58577311Sobrien#ifdef BFD64 58677311Sobrien case 8: mask = ((addressT) 2 << 63) - 1; break; 58777311Sobrien#endif 58877311Sobrien default: abort (); 58977311Sobrien } 59077311Sobrien 59177311Sobrien /* If BFD64, sign extend val. */ 59277311Sobrien if (!use_rela_relocations) 59377311Sobrien if ((val & ~(((addressT) 2 << 31) - 1)) == 0) 59477311Sobrien val = (val ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31); 59577311Sobrien 59677311Sobrien if ((val & ~mask) != 0 && (val & ~mask) != ~mask) 59777311Sobrien { 59877311Sobrien char buf1[40], buf2[40]; 59977311Sobrien 60077311Sobrien sprint_value (buf1, val); 60177311Sobrien sprint_value (buf2, val & mask); 60277311Sobrien as_warn (_("%s shortened to %s"), buf1, buf2); 60377311Sobrien } 60477311Sobrien return val & mask; 60577311Sobrien} 60677311Sobrien 60760519Sobrien/* Returns 0 if attempting to add a prefix where one from the same 60860519Sobrien class already exists, 1 if non rep/repne added, 2 if rep/repne 60960519Sobrien added. */ 61060519Sobrienstatic int 61160519Sobrienadd_prefix (prefix) 61260519Sobrien unsigned int prefix; 61360519Sobrien{ 61460519Sobrien int ret = 1; 61560519Sobrien int q; 61660519Sobrien 61777311Sobrien if (prefix >= 0x40 && prefix < 0x50 && flag_code == CODE_64BIT) 61877311Sobrien q = REX_PREFIX; 61977311Sobrien else 62077311Sobrien switch (prefix) 62177311Sobrien { 62277311Sobrien default: 62377311Sobrien abort (); 62460519Sobrien 62577311Sobrien case CS_PREFIX_OPCODE: 62677311Sobrien case DS_PREFIX_OPCODE: 62777311Sobrien case ES_PREFIX_OPCODE: 62877311Sobrien case FS_PREFIX_OPCODE: 62977311Sobrien case GS_PREFIX_OPCODE: 63077311Sobrien case SS_PREFIX_OPCODE: 63177311Sobrien q = SEG_PREFIX; 63277311Sobrien break; 63360519Sobrien 63477311Sobrien case REPNE_PREFIX_OPCODE: 63577311Sobrien case REPE_PREFIX_OPCODE: 63677311Sobrien ret = 2; 63777311Sobrien /* fall thru */ 63877311Sobrien case LOCK_PREFIX_OPCODE: 63977311Sobrien q = LOCKREP_PREFIX; 64077311Sobrien break; 64160519Sobrien 64277311Sobrien case FWAIT_OPCODE: 64377311Sobrien q = WAIT_PREFIX; 64477311Sobrien break; 64560519Sobrien 64677311Sobrien case ADDR_PREFIX_OPCODE: 64777311Sobrien q = ADDR_PREFIX; 64877311Sobrien break; 64960519Sobrien 65077311Sobrien case DATA_PREFIX_OPCODE: 65177311Sobrien q = DATA_PREFIX; 65277311Sobrien break; 65377311Sobrien } 65460519Sobrien 65560519Sobrien if (i.prefix[q]) 65660519Sobrien { 65760519Sobrien as_bad (_("same type of prefix used twice")); 65860519Sobrien return 0; 65960519Sobrien } 66060519Sobrien 66160519Sobrien i.prefixes += 1; 66260519Sobrien i.prefix[q] = prefix; 66360519Sobrien return ret; 66460519Sobrien} 66560519Sobrien 66633965Sjdpstatic void 66777311Sobrienset_code_flag (value) 66877311Sobrien int value; 66933965Sjdp{ 67077311Sobrien flag_code = value; 67177311Sobrien cpu_arch_flags &= ~(Cpu64 | CpuNo64); 67277311Sobrien cpu_arch_flags |= (flag_code == CODE_64BIT ? Cpu64 : CpuNo64); 67377311Sobrien if (value == CODE_64BIT && !(cpu_arch_flags & CpuSledgehammer)) 67477311Sobrien { 67577311Sobrien as_bad (_("64bit mode not supported on this CPU.")); 67677311Sobrien } 67777311Sobrien if (value == CODE_32BIT && !(cpu_arch_flags & Cpu386)) 67877311Sobrien { 67977311Sobrien as_bad (_("32bit mode not supported on this CPU.")); 68077311Sobrien } 68160519Sobrien stackop_size = '\0'; 68233965Sjdp} 68333965Sjdp 68460519Sobrienstatic void 68577311Sobrienset_16bit_gcc_code_flag (new_code_flag) 68677311Sobrien int new_code_flag; 68760519Sobrien{ 68877311Sobrien flag_code = new_code_flag; 68977311Sobrien cpu_arch_flags &= ~(Cpu64 | CpuNo64); 69077311Sobrien cpu_arch_flags |= (flag_code == CODE_64BIT ? Cpu64 : CpuNo64); 69177311Sobrien stackop_size = 'l'; 69260519Sobrien} 69360519Sobrien 69460519Sobrienstatic void 69560519Sobrienset_intel_syntax (syntax_flag) 69660519Sobrien int syntax_flag; 69760519Sobrien{ 69860519Sobrien /* Find out if register prefixing is specified. */ 69960519Sobrien int ask_naked_reg = 0; 70060519Sobrien 70160519Sobrien SKIP_WHITESPACE (); 70260519Sobrien if (! is_end_of_line[(unsigned char) *input_line_pointer]) 70360519Sobrien { 70460519Sobrien char *string = input_line_pointer; 70560519Sobrien int e = get_symbol_end (); 70660519Sobrien 70777311Sobrien if (strcmp (string, "prefix") == 0) 70860519Sobrien ask_naked_reg = 1; 70977311Sobrien else if (strcmp (string, "noprefix") == 0) 71060519Sobrien ask_naked_reg = -1; 71160519Sobrien else 71260519Sobrien as_bad (_("bad argument to syntax directive.")); 71360519Sobrien *input_line_pointer = e; 71460519Sobrien } 71560519Sobrien demand_empty_rest_of_line (); 71660519Sobrien 71760519Sobrien intel_syntax = syntax_flag; 71860519Sobrien 71960519Sobrien if (ask_naked_reg == 0) 72060519Sobrien { 72160519Sobrien#ifdef BFD_ASSEMBLER 72260519Sobrien allow_naked_reg = (intel_syntax 72360519Sobrien && (bfd_get_symbol_leading_char (stdoutput) != '\0')); 72460519Sobrien#else 72577311Sobrien /* Conservative default. */ 72677311Sobrien allow_naked_reg = 0; 72760519Sobrien#endif 72860519Sobrien } 72960519Sobrien else 73060519Sobrien allow_naked_reg = (ask_naked_reg < 0); 73160519Sobrien} 73260519Sobrien 73377311Sobrienstatic void 73477311Sobrienset_cpu_arch (dummy) 73577311Sobrien int dummy ATTRIBUTE_UNUSED; 73677311Sobrien{ 73777311Sobrien SKIP_WHITESPACE (); 73877311Sobrien 73977311Sobrien if (! is_end_of_line[(unsigned char) *input_line_pointer]) 74077311Sobrien { 74177311Sobrien char *string = input_line_pointer; 74277311Sobrien int e = get_symbol_end (); 74377311Sobrien int i; 74477311Sobrien 74577311Sobrien for (i = 0; cpu_arch[i].name; i++) 74677311Sobrien { 74777311Sobrien if (strcmp (string, cpu_arch[i].name) == 0) 74877311Sobrien { 74977311Sobrien cpu_arch_name = cpu_arch[i].name; 75078840Sobrien cpu_arch_flags = (cpu_arch[i].flags 75178840Sobrien | (flag_code == CODE_64BIT ? Cpu64 : CpuNo64)); 75277311Sobrien break; 75377311Sobrien } 75477311Sobrien } 75577311Sobrien if (!cpu_arch[i].name) 75677311Sobrien as_bad (_("no such architecture: `%s'"), string); 75777311Sobrien 75877311Sobrien *input_line_pointer = e; 75977311Sobrien } 76077311Sobrien else 76177311Sobrien as_bad (_("missing cpu architecture")); 76277311Sobrien 76378840Sobrien no_cond_jump_promotion = 0; 76478840Sobrien if (*input_line_pointer == ',' 76578840Sobrien && ! is_end_of_line[(unsigned char) input_line_pointer[1]]) 76678840Sobrien { 76778840Sobrien char *string = ++input_line_pointer; 76878840Sobrien int e = get_symbol_end (); 76978840Sobrien 77078840Sobrien if (strcmp (string, "nojumps") == 0) 77178840Sobrien no_cond_jump_promotion = 1; 77278840Sobrien else if (strcmp (string, "jumps") == 0) 77378840Sobrien ; 77478840Sobrien else 77578840Sobrien as_bad (_("no such architecture modifier: `%s'"), string); 77678840Sobrien 77778840Sobrien *input_line_pointer = e; 77878840Sobrien } 77978840Sobrien 78077311Sobrien demand_empty_rest_of_line (); 78177311Sobrien} 78277311Sobrien 78333965Sjdpconst pseudo_typeS md_pseudo_table[] = 78433965Sjdp{ 78538891Sjdp#if !defined(OBJ_AOUT) && !defined(USE_ALIGN_PTWO) 78633965Sjdp {"align", s_align_bytes, 0}, 78733965Sjdp#else 78833965Sjdp {"align", s_align_ptwo, 0}, 78933965Sjdp#endif 79077311Sobrien {"arch", set_cpu_arch, 0}, 79177311Sobrien#ifndef I386COFF 79277311Sobrien {"bss", s_bss, 0}, 79377311Sobrien#endif 79433965Sjdp {"ffloat", float_cons, 'f'}, 79533965Sjdp {"dfloat", float_cons, 'd'}, 79633965Sjdp {"tfloat", float_cons, 'x'}, 79733965Sjdp {"value", cons, 2}, 79833965Sjdp {"noopt", s_ignore, 0}, 79933965Sjdp {"optim", s_ignore, 0}, 80077311Sobrien {"code16gcc", set_16bit_gcc_code_flag, CODE_16BIT}, 80177311Sobrien {"code16", set_code_flag, CODE_16BIT}, 80277311Sobrien {"code32", set_code_flag, CODE_32BIT}, 80377311Sobrien {"code64", set_code_flag, CODE_64BIT}, 80460519Sobrien {"intel_syntax", set_intel_syntax, 1}, 80560519Sobrien {"att_syntax", set_intel_syntax, 0}, 80677311Sobrien {"file", dwarf2_directive_file, 0}, 80777311Sobrien {"loc", dwarf2_directive_loc, 0}, 80833965Sjdp {0, 0, 0} 80933965Sjdp}; 81033965Sjdp 81177311Sobrien/* For interface with expression (). */ 81233965Sjdpextern char *input_line_pointer; 81333965Sjdp 81477311Sobrien/* Hash table for instruction mnemonic lookup. */ 81533965Sjdpstatic struct hash_control *op_hash; 81677311Sobrien 81777311Sobrien/* Hash table for register lookup. */ 81833965Sjdpstatic struct hash_control *reg_hash; 81933965Sjdp 82077311Sobrien#ifdef BFD_ASSEMBLER 82177311Sobrienunsigned long 82277311Sobrieni386_mach () 82377311Sobrien{ 82477311Sobrien if (!strcmp (default_arch, "x86_64")) 82577311Sobrien return bfd_mach_x86_64; 82677311Sobrien else if (!strcmp (default_arch, "i386")) 82777311Sobrien return bfd_mach_i386_i386; 82877311Sobrien else 82977311Sobrien as_fatal (_("Unknown architecture")); 83077311Sobrien} 83177311Sobrien#endif 83277311Sobrien 83333965Sjdpvoid 83433965Sjdpmd_begin () 83533965Sjdp{ 83633965Sjdp const char *hash_err; 83733965Sjdp 83877311Sobrien /* Initialize op_hash hash table. */ 83933965Sjdp op_hash = hash_new (); 84033965Sjdp 84133965Sjdp { 84233965Sjdp register const template *optab; 84333965Sjdp register templates *core_optab; 84433965Sjdp 84577311Sobrien /* Setup for loop. */ 84677311Sobrien optab = i386_optab; 84733965Sjdp core_optab = (templates *) xmalloc (sizeof (templates)); 84860519Sobrien core_optab->start = optab; 84933965Sjdp 85060519Sobrien while (1) 85133965Sjdp { 85260519Sobrien ++optab; 85360519Sobrien if (optab->name == NULL 85460519Sobrien || strcmp (optab->name, (optab - 1)->name) != 0) 85533965Sjdp { 85633965Sjdp /* different name --> ship out current template list; 85777311Sobrien add to hash table; & begin anew. */ 85860519Sobrien core_optab->end = optab; 85960519Sobrien hash_err = hash_insert (op_hash, 86060519Sobrien (optab - 1)->name, 86160519Sobrien (PTR) core_optab); 86233965Sjdp if (hash_err) 86333965Sjdp { 86460519Sobrien as_fatal (_("Internal Error: Can't hash %s: %s"), 86560519Sobrien (optab - 1)->name, 86633965Sjdp hash_err); 86733965Sjdp } 86860519Sobrien if (optab->name == NULL) 86960519Sobrien break; 87033965Sjdp core_optab = (templates *) xmalloc (sizeof (templates)); 87160519Sobrien core_optab->start = optab; 87233965Sjdp } 87333965Sjdp } 87433965Sjdp } 87533965Sjdp 87677311Sobrien /* Initialize reg_hash hash table. */ 87733965Sjdp reg_hash = hash_new (); 87833965Sjdp { 87933965Sjdp register const reg_entry *regtab; 88033965Sjdp 88160519Sobrien for (regtab = i386_regtab; 88260519Sobrien regtab < i386_regtab + sizeof (i386_regtab) / sizeof (i386_regtab[0]); 88360519Sobrien regtab++) 88433965Sjdp { 88533965Sjdp hash_err = hash_insert (reg_hash, regtab->reg_name, (PTR) regtab); 88633965Sjdp if (hash_err) 88777311Sobrien as_fatal (_("Internal Error: Can't hash %s: %s"), 88877311Sobrien regtab->reg_name, 88977311Sobrien hash_err); 89033965Sjdp } 89133965Sjdp } 89233965Sjdp 89377311Sobrien /* Fill in lexical tables: mnemonic_chars, operand_chars. */ 89433965Sjdp { 89533965Sjdp register int c; 89633965Sjdp register char *p; 89733965Sjdp 89833965Sjdp for (c = 0; c < 256; c++) 89933965Sjdp { 90089867Sobrien if (ISDIGIT (c)) 90133965Sjdp { 90260519Sobrien digit_chars[c] = c; 90360519Sobrien mnemonic_chars[c] = c; 90433965Sjdp register_chars[c] = c; 90560519Sobrien operand_chars[c] = c; 90633965Sjdp } 90789867Sobrien else if (ISLOWER (c)) 90833965Sjdp { 90960519Sobrien mnemonic_chars[c] = c; 91060519Sobrien register_chars[c] = c; 91160519Sobrien operand_chars[c] = c; 91233965Sjdp } 91389867Sobrien else if (ISUPPER (c)) 91433965Sjdp { 91589867Sobrien mnemonic_chars[c] = TOLOWER (c); 91660519Sobrien register_chars[c] = mnemonic_chars[c]; 91760519Sobrien operand_chars[c] = c; 91833965Sjdp } 91960519Sobrien 92089867Sobrien if (ISALPHA (c) || ISDIGIT (c)) 92160519Sobrien identifier_chars[c] = c; 92260519Sobrien else if (c >= 128) 92333965Sjdp { 92460519Sobrien identifier_chars[c] = c; 92560519Sobrien operand_chars[c] = c; 92633965Sjdp } 92760519Sobrien } 92833965Sjdp 92933965Sjdp#ifdef LEX_AT 93060519Sobrien identifier_chars['@'] = '@'; 93133965Sjdp#endif 93260519Sobrien digit_chars['-'] = '-'; 93360519Sobrien identifier_chars['_'] = '_'; 93460519Sobrien identifier_chars['.'] = '.'; 93533965Sjdp 93633965Sjdp for (p = operand_special_chars; *p != '\0'; p++) 93733965Sjdp operand_chars[(unsigned char) *p] = *p; 93833965Sjdp } 93933965Sjdp 94033965Sjdp#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 94133965Sjdp if (OUTPUT_FLAVOR == bfd_target_elf_flavour) 94233965Sjdp { 94333965Sjdp record_alignment (text_section, 2); 94433965Sjdp record_alignment (data_section, 2); 94533965Sjdp record_alignment (bss_section, 2); 94633965Sjdp } 94733965Sjdp#endif 94833965Sjdp} 94933965Sjdp 95033965Sjdpvoid 95133965Sjdpi386_print_statistics (file) 95233965Sjdp FILE *file; 95333965Sjdp{ 95433965Sjdp hash_print_statistics (file, "i386 opcode", op_hash); 95533965Sjdp hash_print_statistics (file, "i386 register", reg_hash); 95633965Sjdp} 95733965Sjdp 95833965Sjdp#ifdef DEBUG386 95933965Sjdp 96077311Sobrien/* Debugging routines for md_assemble. */ 96133965Sjdpstatic void pi PARAMS ((char *, i386_insn *)); 96233965Sjdpstatic void pte PARAMS ((template *)); 96333965Sjdpstatic void pt PARAMS ((unsigned int)); 96433965Sjdpstatic void pe PARAMS ((expressionS *)); 96533965Sjdpstatic void ps PARAMS ((symbolS *)); 96633965Sjdp 96733965Sjdpstatic void 96833965Sjdppi (line, x) 96933965Sjdp char *line; 97033965Sjdp i386_insn *x; 97133965Sjdp{ 97277311Sobrien unsigned int i; 97333965Sjdp 97433965Sjdp fprintf (stdout, "%s: template ", line); 97533965Sjdp pte (&x->tm); 97677311Sobrien fprintf (stdout, " address: base %s index %s scale %x\n", 97777311Sobrien x->base_reg ? x->base_reg->reg_name : "none", 97877311Sobrien x->index_reg ? x->index_reg->reg_name : "none", 97977311Sobrien x->log2_scale_factor); 98077311Sobrien fprintf (stdout, " modrm: mode %x reg %x reg/mem %x\n", 98133965Sjdp x->rm.mode, x->rm.reg, x->rm.regmem); 98277311Sobrien fprintf (stdout, " sib: base %x index %x scale %x\n", 98377311Sobrien x->sib.base, x->sib.index, x->sib.scale); 98477311Sobrien fprintf (stdout, " rex: 64bit %x extX %x extY %x extZ %x\n", 98577311Sobrien x->rex.mode64, x->rex.extX, x->rex.extY, x->rex.extZ); 98633965Sjdp for (i = 0; i < x->operands; i++) 98733965Sjdp { 98833965Sjdp fprintf (stdout, " #%d: ", i + 1); 98933965Sjdp pt (x->types[i]); 99033965Sjdp fprintf (stdout, "\n"); 99133965Sjdp if (x->types[i] 99260519Sobrien & (Reg | SReg2 | SReg3 | Control | Debug | Test | RegMMX | RegXMM)) 99360519Sobrien fprintf (stdout, "%s\n", x->op[i].regs->reg_name); 99433965Sjdp if (x->types[i] & Imm) 99560519Sobrien pe (x->op[i].imms); 99660519Sobrien if (x->types[i] & Disp) 99760519Sobrien pe (x->op[i].disps); 99833965Sjdp } 99933965Sjdp} 100033965Sjdp 100133965Sjdpstatic void 100233965Sjdppte (t) 100333965Sjdp template *t; 100433965Sjdp{ 100577311Sobrien unsigned int i; 100633965Sjdp fprintf (stdout, " %d operands ", t->operands); 100777311Sobrien fprintf (stdout, "opcode %x ", t->base_opcode); 100833965Sjdp if (t->extension_opcode != None) 100933965Sjdp fprintf (stdout, "ext %x ", t->extension_opcode); 101033965Sjdp if (t->opcode_modifier & D) 101133965Sjdp fprintf (stdout, "D"); 101233965Sjdp if (t->opcode_modifier & W) 101333965Sjdp fprintf (stdout, "W"); 101433965Sjdp fprintf (stdout, "\n"); 101533965Sjdp for (i = 0; i < t->operands; i++) 101633965Sjdp { 101733965Sjdp fprintf (stdout, " #%d type ", i + 1); 101833965Sjdp pt (t->operand_types[i]); 101933965Sjdp fprintf (stdout, "\n"); 102033965Sjdp } 102133965Sjdp} 102233965Sjdp 102333965Sjdpstatic void 102433965Sjdppe (e) 102533965Sjdp expressionS *e; 102633965Sjdp{ 102760519Sobrien fprintf (stdout, " operation %d\n", e->X_op); 102860519Sobrien fprintf (stdout, " add_number %ld (%lx)\n", 102960519Sobrien (long) e->X_add_number, (long) e->X_add_number); 103033965Sjdp if (e->X_add_symbol) 103133965Sjdp { 103233965Sjdp fprintf (stdout, " add_symbol "); 103333965Sjdp ps (e->X_add_symbol); 103433965Sjdp fprintf (stdout, "\n"); 103533965Sjdp } 103633965Sjdp if (e->X_op_symbol) 103733965Sjdp { 103833965Sjdp fprintf (stdout, " op_symbol "); 103933965Sjdp ps (e->X_op_symbol); 104033965Sjdp fprintf (stdout, "\n"); 104133965Sjdp } 104233965Sjdp} 104333965Sjdp 104433965Sjdpstatic void 104533965Sjdpps (s) 104633965Sjdp symbolS *s; 104733965Sjdp{ 104833965Sjdp fprintf (stdout, "%s type %s%s", 104933965Sjdp S_GET_NAME (s), 105033965Sjdp S_IS_EXTERNAL (s) ? "EXTERNAL " : "", 105133965Sjdp segment_name (S_GET_SEGMENT (s))); 105233965Sjdp} 105333965Sjdp 105433965Sjdpstruct type_name 105533965Sjdp { 105633965Sjdp unsigned int mask; 105733965Sjdp char *tname; 105833965Sjdp } 105933965Sjdp 106033965Sjdptype_names[] = 106133965Sjdp{ 106233965Sjdp { Reg8, "r8" }, 106333965Sjdp { Reg16, "r16" }, 106433965Sjdp { Reg32, "r32" }, 106577311Sobrien { Reg64, "r64" }, 106633965Sjdp { Imm8, "i8" }, 106733965Sjdp { Imm8S, "i8s" }, 106833965Sjdp { Imm16, "i16" }, 106933965Sjdp { Imm32, "i32" }, 107077311Sobrien { Imm32S, "i32s" }, 107177311Sobrien { Imm64, "i64" }, 107260519Sobrien { Imm1, "i1" }, 107333965Sjdp { BaseIndex, "BaseIndex" }, 107433965Sjdp { Disp8, "d8" }, 107533965Sjdp { Disp16, "d16" }, 107633965Sjdp { Disp32, "d32" }, 107777311Sobrien { Disp32S, "d32s" }, 107877311Sobrien { Disp64, "d64" }, 107933965Sjdp { InOutPortReg, "InOutPortReg" }, 108033965Sjdp { ShiftCount, "ShiftCount" }, 108133965Sjdp { Control, "control reg" }, 108233965Sjdp { Test, "test reg" }, 108360519Sobrien { Debug, "debug reg" }, 108433965Sjdp { FloatReg, "FReg" }, 108533965Sjdp { FloatAcc, "FAcc" }, 108660519Sobrien { SReg2, "SReg2" }, 108760519Sobrien { SReg3, "SReg3" }, 108860519Sobrien { Acc, "Acc" }, 108933965Sjdp { JumpAbsolute, "Jump Absolute" }, 109033965Sjdp { RegMMX, "rMMX" }, 109160519Sobrien { RegXMM, "rXMM" }, 109260519Sobrien { EsSeg, "es" }, 109333965Sjdp { 0, "" } 109433965Sjdp}; 109533965Sjdp 109633965Sjdpstatic void 109733965Sjdppt (t) 109833965Sjdp unsigned int t; 109933965Sjdp{ 110033965Sjdp register struct type_name *ty; 110133965Sjdp 110277311Sobrien for (ty = type_names; ty->mask; ty++) 110377311Sobrien if (t & ty->mask) 110477311Sobrien fprintf (stdout, "%s, ", ty->tname); 110533965Sjdp fflush (stdout); 110633965Sjdp} 110733965Sjdp 110833965Sjdp#endif /* DEBUG386 */ 110933965Sjdp 111060519Sobrienint 111160519Sobrientc_i386_force_relocation (fixp) 111260519Sobrien struct fix *fixp; 111360519Sobrien{ 111433965Sjdp#ifdef BFD_ASSEMBLER 111560519Sobrien if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT 111660519Sobrien || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) 111760519Sobrien return 1; 111860519Sobrien return 0; 111960519Sobrien#else 112077311Sobrien /* For COFF. */ 112160519Sobrien return fixp->fx_r_type == 7; 112260519Sobrien#endif 112360519Sobrien} 112460519Sobrien 112560519Sobrien#ifdef BFD_ASSEMBLER 112660519Sobrien 112733965Sjdpstatic bfd_reloc_code_real_type 112877311Sobrienreloc (size, pcrel, sign, other) 112933965Sjdp int size; 113033965Sjdp int pcrel; 113177311Sobrien int sign; 113233965Sjdp bfd_reloc_code_real_type other; 113333965Sjdp{ 113477311Sobrien if (other != NO_RELOC) 113577311Sobrien return other; 113633965Sjdp 113733965Sjdp if (pcrel) 113860519Sobrien { 113977311Sobrien if (!sign) 114077311Sobrien as_bad (_("There are no unsigned pc-relative relocations")); 114160519Sobrien switch (size) 114260519Sobrien { 114360519Sobrien case 1: return BFD_RELOC_8_PCREL; 114460519Sobrien case 2: return BFD_RELOC_16_PCREL; 114560519Sobrien case 4: return BFD_RELOC_32_PCREL; 114660519Sobrien } 114760519Sobrien as_bad (_("can not do %d byte pc-relative relocation"), size); 114860519Sobrien } 114933965Sjdp else 115060519Sobrien { 115177311Sobrien if (sign) 115277311Sobrien switch (size) 115377311Sobrien { 115477311Sobrien case 4: return BFD_RELOC_X86_64_32S; 115577311Sobrien } 115677311Sobrien else 115777311Sobrien switch (size) 115877311Sobrien { 115977311Sobrien case 1: return BFD_RELOC_8; 116077311Sobrien case 2: return BFD_RELOC_16; 116177311Sobrien case 4: return BFD_RELOC_32; 116277311Sobrien case 8: return BFD_RELOC_64; 116377311Sobrien } 116477311Sobrien as_bad (_("can not do %s %d byte relocation"), 116577311Sobrien sign ? "signed" : "unsigned", size); 116660519Sobrien } 116733965Sjdp 116877311Sobrien abort (); 116933965Sjdp return BFD_RELOC_NONE; 117033965Sjdp} 117133965Sjdp 117277311Sobrien/* Here we decide which fixups can be adjusted to make them relative to 117377311Sobrien the beginning of the section instead of the symbol. Basically we need 117477311Sobrien to make sure that the dynamic relocations are done correctly, so in 117577311Sobrien some cases we force the original symbol to be used. */ 117677311Sobrien 117733965Sjdpint 117860519Sobrientc_i386_fix_adjustable (fixP) 117960519Sobrien fixS *fixP; 118033965Sjdp{ 118177311Sobrien#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 118260519Sobrien /* Prevent all adjustments to global symbols, or else dynamic 118360519Sobrien linking will not work correctly. */ 118461847Sobrien if (S_IS_EXTERNAL (fixP->fx_addsy) 118591054Sobrien || S_IS_WEAK (fixP->fx_addsy) 118691054Sobrien /* Don't adjust pc-relative references to merge sections in 64-bit 118791054Sobrien mode. */ 118891054Sobrien || (use_rela_relocations 118991054Sobrien && (S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0 119091054Sobrien && fixP->fx_pcrel)) 119133965Sjdp return 0; 119260519Sobrien#endif 119377311Sobrien /* adjust_reloc_syms doesn't know about the GOT. */ 119433965Sjdp if (fixP->fx_r_type == BFD_RELOC_386_GOTOFF 119533965Sjdp || fixP->fx_r_type == BFD_RELOC_386_PLT32 119660519Sobrien || fixP->fx_r_type == BFD_RELOC_386_GOT32 119777311Sobrien || fixP->fx_r_type == BFD_RELOC_X86_64_PLT32 119877311Sobrien || fixP->fx_r_type == BFD_RELOC_X86_64_GOT32 119977311Sobrien || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL 120060519Sobrien || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT 120160519Sobrien || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) 120233965Sjdp return 0; 120333965Sjdp return 1; 120433965Sjdp} 120533965Sjdp#else 120677311Sobrien#define reloc(SIZE,PCREL,SIGN,OTHER) 0 120777311Sobrien#define BFD_RELOC_16 0 120877311Sobrien#define BFD_RELOC_32 0 120977311Sobrien#define BFD_RELOC_16_PCREL 0 121077311Sobrien#define BFD_RELOC_32_PCREL 0 121177311Sobrien#define BFD_RELOC_386_PLT32 0 121277311Sobrien#define BFD_RELOC_386_GOT32 0 121377311Sobrien#define BFD_RELOC_386_GOTOFF 0 121477311Sobrien#define BFD_RELOC_X86_64_PLT32 0 121577311Sobrien#define BFD_RELOC_X86_64_GOT32 0 121677311Sobrien#define BFD_RELOC_X86_64_GOTPCREL 0 121733965Sjdp#endif 121833965Sjdp 121977311Sobrienstatic int intel_float_operand PARAMS ((char *mnemonic)); 122060519Sobrien 122160519Sobrienstatic int 122260519Sobrienintel_float_operand (mnemonic) 122360519Sobrien char *mnemonic; 122460519Sobrien{ 122577311Sobrien if (mnemonic[0] == 'f' && mnemonic[1] == 'i') 122660519Sobrien return 2; 122760519Sobrien 122860519Sobrien if (mnemonic[0] == 'f') 122960519Sobrien return 1; 123060519Sobrien 123160519Sobrien return 0; 123260519Sobrien} 123360519Sobrien 123433965Sjdp/* This is the guts of the machine-dependent assembler. LINE points to a 123533965Sjdp machine dependent instruction. This function is supposed to emit 123633965Sjdp the frags/bytes it assembles to. */ 123733965Sjdp 123833965Sjdpvoid 123933965Sjdpmd_assemble (line) 124033965Sjdp char *line; 124133965Sjdp{ 124277311Sobrien /* Points to template once we've found it. */ 124338891Sjdp const template *t; 124433965Sjdp 124533965Sjdp int j; 124633965Sjdp 124760519Sobrien char mnemonic[MAX_MNEM_SIZE]; 124838891Sjdp 124977311Sobrien /* Initialize globals. */ 125033965Sjdp memset (&i, '\0', sizeof (i)); 125133965Sjdp for (j = 0; j < MAX_OPERANDS; j++) 125278840Sobrien i.reloc[j] = NO_RELOC; 125333965Sjdp memset (disp_expressions, '\0', sizeof (disp_expressions)); 125433965Sjdp memset (im_expressions, '\0', sizeof (im_expressions)); 125577311Sobrien save_stack_p = save_stack; 125633965Sjdp 125760519Sobrien /* First parse an instruction mnemonic & call i386_operand for the operands. 125833965Sjdp We assume that the scrubber has arranged it so that line[0] is the valid 125977311Sobrien start of a (possibly prefixed) mnemonic. */ 126033965Sjdp { 126133965Sjdp char *l = line; 126233965Sjdp char *token_start = l; 126360519Sobrien char *mnem_p; 126433965Sjdp 126577311Sobrien /* Non-zero if we found a prefix only acceptable with string insns. */ 126660519Sobrien const char *expecting_string_instruction = NULL; 126760519Sobrien 126860519Sobrien while (1) 126933965Sjdp { 127060519Sobrien mnem_p = mnemonic; 127160519Sobrien while ((*mnem_p = mnemonic_chars[(unsigned char) *l]) != 0) 127233965Sjdp { 127360519Sobrien mnem_p++; 127460519Sobrien if (mnem_p >= mnemonic + sizeof (mnemonic)) 127560519Sobrien { 127677311Sobrien as_bad (_("no such instruction: `%s'"), token_start); 127760519Sobrien return; 127860519Sobrien } 127960519Sobrien l++; 128060519Sobrien } 128160519Sobrien if (!is_space_char (*l) 128260519Sobrien && *l != END_OF_INSN 128389867Sobrien && *l != PREFIX_SEPARATOR 128489867Sobrien && *l != ',') 128560519Sobrien { 128660519Sobrien as_bad (_("invalid character %s in mnemonic"), 128760519Sobrien output_invalid (*l)); 128833965Sjdp return; 128933965Sjdp } 129060519Sobrien if (token_start == l) 129133965Sjdp { 129260519Sobrien if (*l == PREFIX_SEPARATOR) 129360519Sobrien as_bad (_("expecting prefix; got nothing")); 129460519Sobrien else 129560519Sobrien as_bad (_("expecting mnemonic; got nothing")); 129660519Sobrien return; 129733965Sjdp } 129860519Sobrien 129960519Sobrien /* Look up instruction (or prefix) via hash table. */ 130060519Sobrien current_templates = hash_find (op_hash, mnemonic); 130160519Sobrien 130260519Sobrien if (*l != END_OF_INSN 130360519Sobrien && (! is_space_char (*l) || l[1] != END_OF_INSN) 130460519Sobrien && current_templates 130560519Sobrien && (current_templates->start->opcode_modifier & IsPrefix)) 130633965Sjdp { 130760519Sobrien /* If we are in 16-bit mode, do not allow addr16 or data16. 130860519Sobrien Similarly, in 32-bit mode, do not allow addr32 or data32. */ 130960519Sobrien if ((current_templates->start->opcode_modifier & (Size16 | Size32)) 131091054Sobrien && flag_code != CODE_64BIT 131160519Sobrien && (((current_templates->start->opcode_modifier & Size32) != 0) 131277311Sobrien ^ (flag_code == CODE_16BIT))) 131333965Sjdp { 131460519Sobrien as_bad (_("redundant %s prefix"), 131560519Sobrien current_templates->start->name); 131633965Sjdp return; 131733965Sjdp } 131860519Sobrien /* Add prefix, checking for repeated prefixes. */ 131960519Sobrien switch (add_prefix (current_templates->start->base_opcode)) 132033965Sjdp { 132160519Sobrien case 0: 132233965Sjdp return; 132360519Sobrien case 2: 132477311Sobrien expecting_string_instruction = current_templates->start->name; 132560519Sobrien break; 132633965Sjdp } 132760519Sobrien /* Skip past PREFIX_SEPARATOR and reset token_start. */ 132833965Sjdp token_start = ++l; 132933965Sjdp } 133060519Sobrien else 133160519Sobrien break; 133233965Sjdp } 133333965Sjdp 133433965Sjdp if (!current_templates) 133533965Sjdp { 133660519Sobrien /* See if we can get a match by trimming off a suffix. */ 133760519Sobrien switch (mnem_p[-1]) 133833965Sjdp { 133960519Sobrien case WORD_MNEM_SUFFIX: 134060519Sobrien case BYTE_MNEM_SUFFIX: 134177311Sobrien case QWORD_MNEM_SUFFIX: 134260519Sobrien i.suffix = mnem_p[-1]; 134360519Sobrien mnem_p[-1] = '\0'; 134460519Sobrien current_templates = hash_find (op_hash, mnemonic); 134560519Sobrien break; 134677311Sobrien case SHORT_MNEM_SUFFIX: 134777311Sobrien case LONG_MNEM_SUFFIX: 134877311Sobrien if (!intel_syntax) 134977311Sobrien { 135077311Sobrien i.suffix = mnem_p[-1]; 135177311Sobrien mnem_p[-1] = '\0'; 135277311Sobrien current_templates = hash_find (op_hash, mnemonic); 135377311Sobrien } 135477311Sobrien break; 135560519Sobrien 135677311Sobrien /* Intel Syntax. */ 135777311Sobrien case 'd': 135860519Sobrien if (intel_syntax) 135960519Sobrien { 136077311Sobrien if (intel_float_operand (mnemonic)) 136177311Sobrien i.suffix = SHORT_MNEM_SUFFIX; 136277311Sobrien else 136377311Sobrien i.suffix = LONG_MNEM_SUFFIX; 136460519Sobrien mnem_p[-1] = '\0'; 136560519Sobrien current_templates = hash_find (op_hash, mnemonic); 136660519Sobrien } 136777311Sobrien break; 136833965Sjdp } 136933965Sjdp if (!current_templates) 137033965Sjdp { 137177311Sobrien as_bad (_("no such instruction: `%s'"), token_start); 137233965Sjdp return; 137333965Sjdp } 137433965Sjdp } 137533965Sjdp 137689867Sobrien if (current_templates->start->opcode_modifier & (Jump | JumpByte)) 137777311Sobrien { 137889867Sobrien /* Check for a branch hint. We allow ",pt" and ",pn" for 137989867Sobrien predict taken and predict not taken respectively. 138089867Sobrien I'm not sure that branch hints actually do anything on loop 138189867Sobrien and jcxz insns (JumpByte) for current Pentium4 chips. They 138289867Sobrien may work in the future and it doesn't hurt to accept them 138389867Sobrien now. */ 138489867Sobrien if (l[0] == ',' && l[1] == 'p') 138577311Sobrien { 138689867Sobrien if (l[2] == 't') 138789867Sobrien { 138889867Sobrien if (! add_prefix (DS_PREFIX_OPCODE)) 138989867Sobrien return; 139089867Sobrien l += 3; 139189867Sobrien } 139289867Sobrien else if (l[2] == 'n') 139389867Sobrien { 139489867Sobrien if (! add_prefix (CS_PREFIX_OPCODE)) 139589867Sobrien return; 139689867Sobrien l += 3; 139789867Sobrien } 139877311Sobrien } 139977311Sobrien } 140089867Sobrien /* Any other comma loses. */ 140189867Sobrien if (*l == ',') 140289867Sobrien { 140389867Sobrien as_bad (_("invalid character %s in mnemonic"), 140489867Sobrien output_invalid (*l)); 140589867Sobrien return; 140689867Sobrien } 140777311Sobrien 140889867Sobrien /* Check if instruction is supported on specified architecture. */ 140989867Sobrien if ((current_templates->start->cpu_flags & ~(Cpu64 | CpuNo64)) 141089867Sobrien & ~(cpu_arch_flags & ~(Cpu64 | CpuNo64))) 141189867Sobrien { 141289867Sobrien as_warn (_("`%s' is not supported on `%s'"), 141389867Sobrien current_templates->start->name, cpu_arch_name); 141489867Sobrien } 141589867Sobrien else if ((Cpu386 & ~cpu_arch_flags) && (flag_code != CODE_16BIT)) 141689867Sobrien { 141789867Sobrien as_warn (_("use .code16 to ensure correct addressing mode")); 141889867Sobrien } 141989867Sobrien 142077311Sobrien /* Check for rep/repne without a string instruction. */ 142160519Sobrien if (expecting_string_instruction 142260519Sobrien && !(current_templates->start->opcode_modifier & IsString)) 142333965Sjdp { 142460519Sobrien as_bad (_("expecting string instruction after `%s'"), 142560519Sobrien expecting_string_instruction); 142633965Sjdp return; 142733965Sjdp } 142833965Sjdp 142977311Sobrien /* There may be operands to parse. */ 143060519Sobrien if (*l != END_OF_INSN) 143133965Sjdp { 143277311Sobrien /* 1 if operand is pending after ','. */ 143360519Sobrien unsigned int expecting_operand = 0; 143460519Sobrien 143577311Sobrien /* Non-zero if operand parens not balanced. */ 143660519Sobrien unsigned int paren_not_balanced; 143760519Sobrien 143833965Sjdp do 143933965Sjdp { 144077311Sobrien /* Skip optional white space before operand. */ 144160519Sobrien if (is_space_char (*l)) 144260519Sobrien ++l; 144360519Sobrien if (!is_operand_char (*l) && *l != END_OF_INSN) 144433965Sjdp { 144560519Sobrien as_bad (_("invalid character %s before operand %d"), 144660519Sobrien output_invalid (*l), 144760519Sobrien i.operands + 1); 144860519Sobrien return; 144933965Sjdp } 145033965Sjdp token_start = l; /* after white space */ 145133965Sjdp paren_not_balanced = 0; 145233965Sjdp while (paren_not_balanced || *l != ',') 145333965Sjdp { 145433965Sjdp if (*l == END_OF_INSN) 145533965Sjdp { 145633965Sjdp if (paren_not_balanced) 145733965Sjdp { 145860519Sobrien if (!intel_syntax) 145960519Sobrien as_bad (_("unbalanced parenthesis in operand %d."), 146060519Sobrien i.operands + 1); 146160519Sobrien else 146260519Sobrien as_bad (_("unbalanced brackets in operand %d."), 146360519Sobrien i.operands + 1); 146433965Sjdp return; 146533965Sjdp } 146633965Sjdp else 146733965Sjdp break; /* we are done */ 146833965Sjdp } 146933965Sjdp else if (!is_operand_char (*l) && !is_space_char (*l)) 147033965Sjdp { 147160519Sobrien as_bad (_("invalid character %s in operand %d"), 147233965Sjdp output_invalid (*l), 147360519Sobrien i.operands + 1); 147433965Sjdp return; 147533965Sjdp } 147660519Sobrien if (!intel_syntax) 147760519Sobrien { 147860519Sobrien if (*l == '(') 147960519Sobrien ++paren_not_balanced; 148060519Sobrien if (*l == ')') 148160519Sobrien --paren_not_balanced; 148260519Sobrien } 148360519Sobrien else 148460519Sobrien { 148560519Sobrien if (*l == '[') 148660519Sobrien ++paren_not_balanced; 148760519Sobrien if (*l == ']') 148860519Sobrien --paren_not_balanced; 148960519Sobrien } 149033965Sjdp l++; 149133965Sjdp } 149233965Sjdp if (l != token_start) 149377311Sobrien { /* Yes, we've read in another operand. */ 149433965Sjdp unsigned int operand_ok; 149533965Sjdp this_operand = i.operands++; 149633965Sjdp if (i.operands > MAX_OPERANDS) 149733965Sjdp { 149860519Sobrien as_bad (_("spurious operands; (%d operands/instruction max)"), 149933965Sjdp MAX_OPERANDS); 150033965Sjdp return; 150133965Sjdp } 150277311Sobrien /* Now parse operand adding info to 'i' as we go along. */ 150333965Sjdp END_STRING_AND_SAVE (l); 150460519Sobrien 150560519Sobrien if (intel_syntax) 150677311Sobrien operand_ok = 150777311Sobrien i386_intel_operand (token_start, 150877311Sobrien intel_float_operand (mnemonic)); 150960519Sobrien else 151060519Sobrien operand_ok = i386_operand (token_start); 151160519Sobrien 151277311Sobrien RESTORE_END_STRING (l); 151333965Sjdp if (!operand_ok) 151433965Sjdp return; 151533965Sjdp } 151633965Sjdp else 151733965Sjdp { 151833965Sjdp if (expecting_operand) 151933965Sjdp { 152033965Sjdp expecting_operand_after_comma: 152160519Sobrien as_bad (_("expecting operand after ','; got nothing")); 152233965Sjdp return; 152333965Sjdp } 152433965Sjdp if (*l == ',') 152533965Sjdp { 152660519Sobrien as_bad (_("expecting operand before ','; got nothing")); 152733965Sjdp return; 152833965Sjdp } 152933965Sjdp } 153033965Sjdp 153177311Sobrien /* Now *l must be either ',' or END_OF_INSN. */ 153233965Sjdp if (*l == ',') 153333965Sjdp { 153433965Sjdp if (*++l == END_OF_INSN) 153577311Sobrien { 153677311Sobrien /* Just skip it, if it's \n complain. */ 153733965Sjdp goto expecting_operand_after_comma; 153833965Sjdp } 153933965Sjdp expecting_operand = 1; 154033965Sjdp } 154133965Sjdp } 154277311Sobrien while (*l != END_OF_INSN); 154333965Sjdp } 154433965Sjdp } 154533965Sjdp 154660519Sobrien /* Now we've parsed the mnemonic into a set of templates, and have the 154733965Sjdp operands at hand. 154833965Sjdp 154933965Sjdp Next, we find a template that matches the given insn, 155033965Sjdp making sure the overlap of the given operands types is consistent 155177311Sobrien with the template operand types. */ 155233965Sjdp 155360519Sobrien#define MATCH(overlap, given, template) \ 155460519Sobrien ((overlap & ~JumpAbsolute) \ 155560519Sobrien && ((given) & (BaseIndex|JumpAbsolute)) == ((overlap) & (BaseIndex|JumpAbsolute))) 155633965Sjdp 155760519Sobrien /* If given types r0 and r1 are registers they must be of the same type 155860519Sobrien unless the expected operand type register overlap is null. 155960519Sobrien Note that Acc in a template matches every size of reg. */ 156060519Sobrien#define CONSISTENT_REGISTER_MATCH(m0, g0, t0, m1, g1, t1) \ 156160519Sobrien ( ((g0) & Reg) == 0 || ((g1) & Reg) == 0 || \ 156260519Sobrien ((g0) & Reg) == ((g1) & Reg) || \ 156360519Sobrien ((((m0) & Acc) ? Reg : (t0)) & (((m1) & Acc) ? Reg : (t1)) & Reg) == 0 ) 156433965Sjdp 156533965Sjdp { 156633965Sjdp register unsigned int overlap0, overlap1; 156733965Sjdp unsigned int overlap2; 156833965Sjdp unsigned int found_reverse_match; 156960519Sobrien int suffix_check; 157033965Sjdp 157160519Sobrien /* All intel opcodes have reversed operands except for "bound" and 157260519Sobrien "enter". We also don't reverse intersegment "jmp" and "call" 157360519Sobrien instructions with 2 immediate operands so that the immediate segment 157460519Sobrien precedes the offset, as it does when in AT&T mode. "enter" and the 157560519Sobrien intersegment "jmp" and "call" instructions are the only ones that 157660519Sobrien have two immediate operands. */ 157760519Sobrien if (intel_syntax && i.operands > 1 157860519Sobrien && (strcmp (mnemonic, "bound") != 0) 157960519Sobrien && !((i.types[0] & Imm) && (i.types[1] & Imm))) 158060519Sobrien { 158160519Sobrien union i386_op temp_op; 158260519Sobrien unsigned int temp_type; 158378840Sobrien RELOC_ENUM temp_reloc; 158460519Sobrien int xchg1 = 0; 158560519Sobrien int xchg2 = 0; 158660519Sobrien 158760519Sobrien if (i.operands == 2) 158860519Sobrien { 158960519Sobrien xchg1 = 0; 159060519Sobrien xchg2 = 1; 159160519Sobrien } 159260519Sobrien else if (i.operands == 3) 159360519Sobrien { 159460519Sobrien xchg1 = 0; 159560519Sobrien xchg2 = 2; 159660519Sobrien } 159760519Sobrien temp_type = i.types[xchg2]; 159860519Sobrien i.types[xchg2] = i.types[xchg1]; 159960519Sobrien i.types[xchg1] = temp_type; 160060519Sobrien temp_op = i.op[xchg2]; 160160519Sobrien i.op[xchg2] = i.op[xchg1]; 160260519Sobrien i.op[xchg1] = temp_op; 160378840Sobrien temp_reloc = i.reloc[xchg2]; 160478840Sobrien i.reloc[xchg2] = i.reloc[xchg1]; 160578840Sobrien i.reloc[xchg1] = temp_reloc; 160660519Sobrien 160760519Sobrien if (i.mem_operands == 2) 160860519Sobrien { 160960519Sobrien const seg_entry *temp_seg; 161060519Sobrien temp_seg = i.seg[0]; 161160519Sobrien i.seg[0] = i.seg[1]; 161260519Sobrien i.seg[1] = temp_seg; 161360519Sobrien } 161460519Sobrien } 161560519Sobrien 161660519Sobrien if (i.imm_operands) 161760519Sobrien { 161860519Sobrien /* Try to ensure constant immediates are represented in the smallest 161960519Sobrien opcode possible. */ 162060519Sobrien char guess_suffix = 0; 162160519Sobrien int op; 162260519Sobrien 162360519Sobrien if (i.suffix) 162460519Sobrien guess_suffix = i.suffix; 162560519Sobrien else if (i.reg_operands) 162660519Sobrien { 162760519Sobrien /* Figure out a suffix from the last register operand specified. 162860519Sobrien We can't do this properly yet, ie. excluding InOutPortReg, 162960519Sobrien but the following works for instructions with immediates. 163060519Sobrien In any case, we can't set i.suffix yet. */ 163177311Sobrien for (op = i.operands; --op >= 0;) 163260519Sobrien if (i.types[op] & Reg) 163360519Sobrien { 163460519Sobrien if (i.types[op] & Reg8) 163560519Sobrien guess_suffix = BYTE_MNEM_SUFFIX; 163660519Sobrien else if (i.types[op] & Reg16) 163760519Sobrien guess_suffix = WORD_MNEM_SUFFIX; 163877311Sobrien else if (i.types[op] & Reg32) 163977311Sobrien guess_suffix = LONG_MNEM_SUFFIX; 164077311Sobrien else if (i.types[op] & Reg64) 164177311Sobrien guess_suffix = QWORD_MNEM_SUFFIX; 164260519Sobrien break; 164360519Sobrien } 164460519Sobrien } 164577311Sobrien else if ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0)) 164660519Sobrien guess_suffix = WORD_MNEM_SUFFIX; 164760519Sobrien 164877311Sobrien for (op = i.operands; --op >= 0;) 164977311Sobrien if (i.types[op] & Imm) 165060519Sobrien { 165177311Sobrien switch (i.op[op].imms->X_op) 165260519Sobrien { 165377311Sobrien case O_constant: 165477311Sobrien /* If a suffix is given, this operand may be shortened. */ 165577311Sobrien switch (guess_suffix) 165677311Sobrien { 165777311Sobrien case LONG_MNEM_SUFFIX: 165877311Sobrien i.types[op] |= Imm32 | Imm64; 165977311Sobrien break; 166077311Sobrien case WORD_MNEM_SUFFIX: 166177311Sobrien i.types[op] |= Imm16 | Imm32S | Imm32 | Imm64; 166277311Sobrien break; 166377311Sobrien case BYTE_MNEM_SUFFIX: 166477311Sobrien i.types[op] |= Imm16 | Imm8 | Imm8S | Imm32S | Imm32 | Imm64; 166577311Sobrien break; 166677311Sobrien } 166777311Sobrien 166877311Sobrien /* If this operand is at most 16 bits, convert it 166977311Sobrien to a signed 16 bit number before trying to see 167077311Sobrien whether it will fit in an even smaller size. 167177311Sobrien This allows a 16-bit operand such as $0xffe0 to 167277311Sobrien be recognised as within Imm8S range. */ 167377311Sobrien if ((i.types[op] & Imm16) 167477311Sobrien && (i.op[op].imms->X_add_number & ~(offsetT) 0xffff) == 0) 167577311Sobrien { 167677311Sobrien i.op[op].imms->X_add_number = 167777311Sobrien (((i.op[op].imms->X_add_number & 0xffff) ^ 0x8000) - 0x8000); 167877311Sobrien } 167977311Sobrien if ((i.types[op] & Imm32) 168077311Sobrien && (i.op[op].imms->X_add_number & ~(((offsetT) 2 << 31) - 1)) == 0) 168177311Sobrien { 168277311Sobrien i.op[op].imms->X_add_number = 168377311Sobrien (i.op[op].imms->X_add_number ^ ((offsetT) 1 << 31)) - ((addressT) 1 << 31); 168477311Sobrien } 168577311Sobrien i.types[op] |= smallest_imm_type (i.op[op].imms->X_add_number); 168677311Sobrien /* We must avoid matching of Imm32 templates when 64bit only immediate is available. */ 168777311Sobrien if (guess_suffix == QWORD_MNEM_SUFFIX) 168877311Sobrien i.types[op] &= ~Imm32; 168977311Sobrien break; 169077311Sobrien case O_absent: 169177311Sobrien case O_register: 169277311Sobrien abort (); 169377311Sobrien /* Symbols and expressions. */ 169477311Sobrien default: 169577311Sobrien /* Convert symbolic operand to proper sizes for matching. */ 169677311Sobrien switch (guess_suffix) 169777311Sobrien { 169877311Sobrien case QWORD_MNEM_SUFFIX: 169977311Sobrien i.types[op] = Imm64 | Imm32S; 170077311Sobrien break; 170177311Sobrien case LONG_MNEM_SUFFIX: 170277311Sobrien i.types[op] = Imm32 | Imm64; 170377311Sobrien break; 170477311Sobrien case WORD_MNEM_SUFFIX: 170577311Sobrien i.types[op] = Imm16 | Imm32 | Imm64; 170677311Sobrien break; 170777311Sobrien break; 170877311Sobrien case BYTE_MNEM_SUFFIX: 170977311Sobrien i.types[op] = Imm8 | Imm8S | Imm16 | Imm32S | Imm32; 171077311Sobrien break; 171177311Sobrien break; 171277311Sobrien } 171377311Sobrien break; 171460519Sobrien } 171577311Sobrien } 171677311Sobrien } 171760519Sobrien 171877311Sobrien if (i.disp_operands) 171977311Sobrien { 172077311Sobrien /* Try to use the smallest displacement type too. */ 172177311Sobrien int op; 172277311Sobrien 172377311Sobrien for (op = i.operands; --op >= 0;) 172477311Sobrien if ((i.types[op] & Disp) 172578840Sobrien && i.op[op].disps->X_op == O_constant) 172677311Sobrien { 172777311Sobrien offsetT disp = i.op[op].disps->X_add_number; 172877311Sobrien 172977311Sobrien if (i.types[op] & Disp16) 173060519Sobrien { 173177311Sobrien /* We know this operand is at most 16 bits, so 173277311Sobrien convert to a signed 16 bit number before trying 173377311Sobrien to see whether it will fit in an even smaller 173477311Sobrien size. */ 173577311Sobrien 173677311Sobrien disp = (((disp & 0xffff) ^ 0x8000) - 0x8000); 173760519Sobrien } 173877311Sobrien else if (i.types[op] & Disp32) 173977311Sobrien { 174077311Sobrien /* We know this operand is at most 32 bits, so convert to a 174177311Sobrien signed 32 bit number before trying to see whether it will 174277311Sobrien fit in an even smaller size. */ 174377311Sobrien disp &= (((offsetT) 2 << 31) - 1); 174477311Sobrien disp = (disp ^ ((offsetT) 1 << 31)) - ((addressT) 1 << 31); 174577311Sobrien } 174677311Sobrien if (flag_code == CODE_64BIT) 174777311Sobrien { 174877311Sobrien if (fits_in_signed_long (disp)) 174977311Sobrien i.types[op] |= Disp32S; 175077311Sobrien if (fits_in_unsigned_long (disp)) 175177311Sobrien i.types[op] |= Disp32; 175277311Sobrien } 175377311Sobrien if ((i.types[op] & (Disp32 | Disp32S | Disp16)) 175477311Sobrien && fits_in_signed_byte (disp)) 175577311Sobrien i.types[op] |= Disp8; 175660519Sobrien } 175760519Sobrien } 175860519Sobrien 175960519Sobrien overlap0 = 0; 176060519Sobrien overlap1 = 0; 176160519Sobrien overlap2 = 0; 176260519Sobrien found_reverse_match = 0; 176360519Sobrien suffix_check = (i.suffix == BYTE_MNEM_SUFFIX 176460519Sobrien ? No_bSuf 176560519Sobrien : (i.suffix == WORD_MNEM_SUFFIX 176660519Sobrien ? No_wSuf 176760519Sobrien : (i.suffix == SHORT_MNEM_SUFFIX 176860519Sobrien ? No_sSuf 176960519Sobrien : (i.suffix == LONG_MNEM_SUFFIX 177060519Sobrien ? No_lSuf 177177311Sobrien : (i.suffix == QWORD_MNEM_SUFFIX 177277311Sobrien ? No_qSuf 177360519Sobrien : (i.suffix == LONG_DOUBLE_MNEM_SUFFIX ? No_xSuf : 0)))))); 177460519Sobrien 177533965Sjdp for (t = current_templates->start; 177633965Sjdp t < current_templates->end; 177733965Sjdp t++) 177833965Sjdp { 177977311Sobrien /* Must have right number of operands. */ 178033965Sjdp if (i.operands != t->operands) 178133965Sjdp continue; 178260519Sobrien 178360519Sobrien /* Check the suffix, except for some instructions in intel mode. */ 178460519Sobrien if ((t->opcode_modifier & suffix_check) 178560519Sobrien && !(intel_syntax 178677311Sobrien && (t->opcode_modifier & IgnoreSize)) 178777311Sobrien && !(intel_syntax 178860519Sobrien && t->base_opcode == 0xd9 178977311Sobrien && (t->extension_opcode == 5 /* 0xd9,5 "fldcw" */ 179077311Sobrien || t->extension_opcode == 7))) /* 0xd9,7 "f{n}stcw" */ 179160519Sobrien continue; 179260519Sobrien 179377311Sobrien /* Do not verify operands when there are none. */ 179433965Sjdp else if (!t->operands) 179577311Sobrien { 179677311Sobrien if (t->cpu_flags & ~cpu_arch_flags) 179777311Sobrien continue; 179877311Sobrien /* We've found a match; break out of loop. */ 179977311Sobrien break; 180077311Sobrien } 180133965Sjdp 180233965Sjdp overlap0 = i.types[0] & t->operand_types[0]; 180333965Sjdp switch (t->operands) 180433965Sjdp { 180533965Sjdp case 1: 180660519Sobrien if (!MATCH (overlap0, i.types[0], t->operand_types[0])) 180733965Sjdp continue; 180833965Sjdp break; 180933965Sjdp case 2: 181033965Sjdp case 3: 181133965Sjdp overlap1 = i.types[1] & t->operand_types[1]; 181260519Sobrien if (!MATCH (overlap0, i.types[0], t->operand_types[0]) 181360519Sobrien || !MATCH (overlap1, i.types[1], t->operand_types[1]) 181460519Sobrien || !CONSISTENT_REGISTER_MATCH (overlap0, i.types[0], 181560519Sobrien t->operand_types[0], 181660519Sobrien overlap1, i.types[1], 181760519Sobrien t->operand_types[1])) 181833965Sjdp { 181977311Sobrien /* Check if other direction is valid ... */ 182060519Sobrien if ((t->opcode_modifier & (D|FloatD)) == 0) 182133965Sjdp continue; 182233965Sjdp 182377311Sobrien /* Try reversing direction of operands. */ 182433965Sjdp overlap0 = i.types[0] & t->operand_types[1]; 182533965Sjdp overlap1 = i.types[1] & t->operand_types[0]; 182660519Sobrien if (!MATCH (overlap0, i.types[0], t->operand_types[1]) 182760519Sobrien || !MATCH (overlap1, i.types[1], t->operand_types[0]) 182860519Sobrien || !CONSISTENT_REGISTER_MATCH (overlap0, i.types[0], 182960519Sobrien t->operand_types[1], 183060519Sobrien overlap1, i.types[1], 183160519Sobrien t->operand_types[0])) 183233965Sjdp { 183377311Sobrien /* Does not match either direction. */ 183433965Sjdp continue; 183533965Sjdp } 183660519Sobrien /* found_reverse_match holds which of D or FloatDR 183760519Sobrien we've found. */ 183860519Sobrien found_reverse_match = t->opcode_modifier & (D|FloatDR); 183960519Sobrien } 184077311Sobrien /* Found a forward 2 operand match here. */ 184177311Sobrien else if (t->operands == 3) 184233965Sjdp { 184360519Sobrien /* Here we make use of the fact that there are no 184460519Sobrien reverse match 3 operand instructions, and all 3 184560519Sobrien operand instructions only need to be checked for 184660519Sobrien register consistency between operands 2 and 3. */ 184733965Sjdp overlap2 = i.types[2] & t->operand_types[2]; 184860519Sobrien if (!MATCH (overlap2, i.types[2], t->operand_types[2]) 184960519Sobrien || !CONSISTENT_REGISTER_MATCH (overlap1, i.types[1], 185060519Sobrien t->operand_types[1], 185160519Sobrien overlap2, i.types[2], 185260519Sobrien t->operand_types[2])) 185360519Sobrien 185433965Sjdp continue; 185533965Sjdp } 185677311Sobrien /* Found either forward/reverse 2 or 3 operand match here: 185777311Sobrien slip through to break. */ 185833965Sjdp } 185977311Sobrien if (t->cpu_flags & ~cpu_arch_flags) 186077311Sobrien { 186177311Sobrien found_reverse_match = 0; 186277311Sobrien continue; 186377311Sobrien } 186477311Sobrien /* We've found a match; break out of loop. */ 186577311Sobrien break; 186677311Sobrien } 186733965Sjdp if (t == current_templates->end) 186877311Sobrien { 186977311Sobrien /* We found no match. */ 187060519Sobrien as_bad (_("suffix or operands invalid for `%s'"), 187160519Sobrien current_templates->start->name); 187233965Sjdp return; 187333965Sjdp } 187433965Sjdp 187577311Sobrien if (!quiet_warnings) 187660519Sobrien { 187777311Sobrien if (!intel_syntax 187877311Sobrien && ((i.types[0] & JumpAbsolute) 187977311Sobrien != (t->operand_types[0] & JumpAbsolute))) 188077311Sobrien { 188177311Sobrien as_warn (_("indirect %s without `*'"), t->name); 188277311Sobrien } 188360519Sobrien 188477311Sobrien if ((t->opcode_modifier & (IsPrefix|IgnoreSize)) 188577311Sobrien == (IsPrefix|IgnoreSize)) 188677311Sobrien { 188777311Sobrien /* Warn them that a data or address size prefix doesn't 188877311Sobrien affect assembly of the next line of code. */ 188977311Sobrien as_warn (_("stand-alone `%s' prefix"), t->name); 189077311Sobrien } 189160519Sobrien } 189260519Sobrien 189338891Sjdp /* Copy the template we found. */ 189433965Sjdp i.tm = *t; 189538891Sjdp if (found_reverse_match) 189638891Sjdp { 189760519Sobrien /* If we found a reverse match we must alter the opcode 189860519Sobrien direction bit. found_reverse_match holds bits to change 189960519Sobrien (different for int & float insns). */ 190060519Sobrien 190160519Sobrien i.tm.base_opcode ^= found_reverse_match; 190260519Sobrien 190338891Sjdp i.tm.operand_types[0] = t->operand_types[1]; 190438891Sjdp i.tm.operand_types[1] = t->operand_types[0]; 190538891Sjdp } 190638891Sjdp 190760519Sobrien /* Undo SYSV386_COMPAT brokenness when in Intel mode. See i386.h */ 190877311Sobrien if (SYSV386_COMPAT 190977311Sobrien && intel_syntax 191077311Sobrien && (i.tm.base_opcode & 0xfffffde0) == 0xdce0) 191177311Sobrien i.tm.base_opcode ^= FloatR; 191260519Sobrien 191360519Sobrien if (i.tm.opcode_modifier & FWait) 191460519Sobrien if (! add_prefix (FWAIT_OPCODE)) 191560519Sobrien return; 191660519Sobrien 191777311Sobrien /* Check string instruction segment overrides. */ 191860519Sobrien if ((i.tm.opcode_modifier & IsString) != 0 && i.mem_operands != 0) 191933965Sjdp { 192060519Sobrien int mem_op = (i.types[0] & AnyMem) ? 0 : 1; 192160519Sobrien if ((i.tm.operand_types[mem_op] & EsSeg) != 0) 192233965Sjdp { 192360519Sobrien if (i.seg[0] != NULL && i.seg[0] != &es) 192460519Sobrien { 192560519Sobrien as_bad (_("`%s' operand %d must use `%%es' segment"), 192660519Sobrien i.tm.name, 192760519Sobrien mem_op + 1); 192860519Sobrien return; 192960519Sobrien } 193060519Sobrien /* There's only ever one segment override allowed per instruction. 193160519Sobrien This instruction possibly has a legal segment override on the 193260519Sobrien second operand, so copy the segment to where non-string 193360519Sobrien instructions store it, allowing common code. */ 193460519Sobrien i.seg[0] = i.seg[1]; 193533965Sjdp } 193660519Sobrien else if ((i.tm.operand_types[mem_op + 1] & EsSeg) != 0) 193760519Sobrien { 193860519Sobrien if (i.seg[1] != NULL && i.seg[1] != &es) 193960519Sobrien { 194060519Sobrien as_bad (_("`%s' operand %d must use `%%es' segment"), 194160519Sobrien i.tm.name, 194260519Sobrien mem_op + 2); 194360519Sobrien return; 194460519Sobrien } 194560519Sobrien } 194633965Sjdp } 194733965Sjdp 194860519Sobrien /* If matched instruction specifies an explicit instruction mnemonic 194960519Sobrien suffix, use it. */ 195077311Sobrien if (i.tm.opcode_modifier & (Size16 | Size32 | Size64)) 195133965Sjdp { 195260519Sobrien if (i.tm.opcode_modifier & Size16) 195360519Sobrien i.suffix = WORD_MNEM_SUFFIX; 195477311Sobrien else if (i.tm.opcode_modifier & Size64) 195577311Sobrien i.suffix = QWORD_MNEM_SUFFIX; 195660519Sobrien else 195760519Sobrien i.suffix = LONG_MNEM_SUFFIX; 195833965Sjdp } 195960519Sobrien else if (i.reg_operands) 196033965Sjdp { 196160519Sobrien /* If there's no instruction mnemonic suffix we try to invent one 196277311Sobrien based on register operands. */ 196360519Sobrien if (!i.suffix) 196460519Sobrien { 196560519Sobrien /* We take i.suffix from the last register operand specified, 196660519Sobrien Destination register type is more significant than source 196760519Sobrien register type. */ 196860519Sobrien int op; 196977311Sobrien for (op = i.operands; --op >= 0;) 197060519Sobrien if ((i.types[op] & Reg) 197160519Sobrien && !(i.tm.operand_types[op] & InOutPortReg)) 197260519Sobrien { 197360519Sobrien i.suffix = ((i.types[op] & Reg8) ? BYTE_MNEM_SUFFIX : 197460519Sobrien (i.types[op] & Reg16) ? WORD_MNEM_SUFFIX : 197577311Sobrien (i.types[op] & Reg64) ? QWORD_MNEM_SUFFIX : 197660519Sobrien LONG_MNEM_SUFFIX); 197760519Sobrien break; 197860519Sobrien } 197960519Sobrien } 198060519Sobrien else if (i.suffix == BYTE_MNEM_SUFFIX) 198160519Sobrien { 198260519Sobrien int op; 198377311Sobrien for (op = i.operands; --op >= 0;) 198460519Sobrien { 198560519Sobrien /* If this is an eight bit register, it's OK. If it's 198660519Sobrien the 16 or 32 bit version of an eight bit register, 198777311Sobrien we will just use the low portion, and that's OK too. */ 198860519Sobrien if (i.types[op] & Reg8) 198960519Sobrien continue; 199033965Sjdp 199177311Sobrien /* movzx and movsx should not generate this warning. */ 199260519Sobrien if (intel_syntax 199360519Sobrien && (i.tm.base_opcode == 0xfb7 199460519Sobrien || i.tm.base_opcode == 0xfb6 199577311Sobrien || i.tm.base_opcode == 0x63 199660519Sobrien || i.tm.base_opcode == 0xfbe 199760519Sobrien || i.tm.base_opcode == 0xfbf)) 199860519Sobrien continue; 199933965Sjdp 200060519Sobrien if ((i.types[op] & WordReg) && i.op[op].regs->reg_num < 4 200160519Sobrien#if 0 200260519Sobrien /* Check that the template allows eight bit regs 200360519Sobrien This kills insns such as `orb $1,%edx', which 200460519Sobrien maybe should be allowed. */ 200560519Sobrien && (i.tm.operand_types[op] & (Reg8|InOutPortReg)) 200660519Sobrien#endif 200760519Sobrien ) 200860519Sobrien { 200977311Sobrien /* Prohibit these changes in the 64bit mode, since 201077311Sobrien the lowering is more complicated. */ 201177311Sobrien if (flag_code == CODE_64BIT 201277311Sobrien && (i.tm.operand_types[op] & InOutPortReg) == 0) 201377311Sobrien as_bad (_("Incorrect register `%%%s' used with`%c' suffix"), 201477311Sobrien i.op[op].regs->reg_name, 201577311Sobrien i.suffix); 201660519Sobrien#if REGISTER_WARNINGS 201777311Sobrien if (!quiet_warnings 201877311Sobrien && (i.tm.operand_types[op] & InOutPortReg) == 0) 201960519Sobrien as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"), 202077311Sobrien (i.op[op].regs 202177311Sobrien + (i.types[op] & Reg16 202277311Sobrien ? REGNAM_AL - REGNAM_AX 202377311Sobrien : REGNAM_AL - REGNAM_EAX))->reg_name, 202460519Sobrien i.op[op].regs->reg_name, 202560519Sobrien i.suffix); 202660519Sobrien#endif 202760519Sobrien continue; 202860519Sobrien } 202977311Sobrien /* Any other register is bad. */ 203060519Sobrien if (i.types[op] & (Reg | RegMMX | RegXMM 203160519Sobrien | SReg2 | SReg3 203260519Sobrien | Control | Debug | Test 203360519Sobrien | FloatReg | FloatAcc)) 203460519Sobrien { 203560519Sobrien as_bad (_("`%%%s' not allowed with `%s%c'"), 203660519Sobrien i.op[op].regs->reg_name, 203760519Sobrien i.tm.name, 203860519Sobrien i.suffix); 203960519Sobrien return; 204060519Sobrien } 204160519Sobrien } 204260519Sobrien } 204360519Sobrien else if (i.suffix == LONG_MNEM_SUFFIX) 204433965Sjdp { 204560519Sobrien int op; 204677311Sobrien 204777311Sobrien for (op = i.operands; --op >= 0;) 204877311Sobrien /* Reject eight bit registers, except where the template 204977311Sobrien requires them. (eg. movzb) */ 205077311Sobrien if ((i.types[op] & Reg8) != 0 205177311Sobrien && (i.tm.operand_types[op] & (Reg16 | Reg32 | Acc)) != 0) 205277311Sobrien { 205377311Sobrien as_bad (_("`%%%s' not allowed with `%s%c'"), 205477311Sobrien i.op[op].regs->reg_name, 205577311Sobrien i.tm.name, 205677311Sobrien i.suffix); 205777311Sobrien return; 205877311Sobrien } 205977311Sobrien /* Warn if the e prefix on a general reg is missing. */ 206077311Sobrien else if ((!quiet_warnings || flag_code == CODE_64BIT) 206177311Sobrien && (i.types[op] & Reg16) != 0 206277311Sobrien && (i.tm.operand_types[op] & (Reg32|Acc)) != 0) 206377311Sobrien { 206477311Sobrien /* Prohibit these changes in the 64bit mode, since 206577311Sobrien the lowering is more complicated. */ 206677311Sobrien if (flag_code == CODE_64BIT) 206777311Sobrien as_bad (_("Incorrect register `%%%s' used with`%c' suffix"), 206877311Sobrien i.op[op].regs->reg_name, 206977311Sobrien i.suffix); 207077311Sobrien#if REGISTER_WARNINGS 207177311Sobrien else 207277311Sobrien as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"), 207377311Sobrien (i.op[op].regs + REGNAM_EAX - REGNAM_AX)->reg_name, 207477311Sobrien i.op[op].regs->reg_name, 207577311Sobrien i.suffix); 207677311Sobrien#endif 207777311Sobrien } 207877311Sobrien /* Warn if the r prefix on a general reg is missing. */ 207977311Sobrien else if ((i.types[op] & Reg64) != 0 208077311Sobrien && (i.tm.operand_types[op] & (Reg32|Acc)) != 0) 208177311Sobrien { 208277311Sobrien as_bad (_("Incorrect register `%%%s' used with`%c' suffix"), 208377311Sobrien i.op[op].regs->reg_name, 208477311Sobrien i.suffix); 208577311Sobrien } 208677311Sobrien } 208777311Sobrien else if (i.suffix == QWORD_MNEM_SUFFIX) 208877311Sobrien { 208977311Sobrien int op; 209077311Sobrien 209160519Sobrien for (op = i.operands; --op >= 0; ) 209260519Sobrien /* Reject eight bit registers, except where the template 209360519Sobrien requires them. (eg. movzb) */ 209460519Sobrien if ((i.types[op] & Reg8) != 0 209560519Sobrien && (i.tm.operand_types[op] & (Reg16|Reg32|Acc)) != 0) 209660519Sobrien { 209760519Sobrien as_bad (_("`%%%s' not allowed with `%s%c'"), 209860519Sobrien i.op[op].regs->reg_name, 209960519Sobrien i.tm.name, 210060519Sobrien i.suffix); 210160519Sobrien return; 210260519Sobrien } 210360519Sobrien /* Warn if the e prefix on a general reg is missing. */ 210477311Sobrien else if (((i.types[op] & Reg16) != 0 210577311Sobrien || (i.types[op] & Reg32) != 0) 210660519Sobrien && (i.tm.operand_types[op] & (Reg32|Acc)) != 0) 210760519Sobrien { 210877311Sobrien /* Prohibit these changes in the 64bit mode, since 210977311Sobrien the lowering is more complicated. */ 211077311Sobrien as_bad (_("Incorrect register `%%%s' used with`%c' suffix"), 211177311Sobrien i.op[op].regs->reg_name, 211277311Sobrien i.suffix); 211360519Sobrien } 211433965Sjdp } 211560519Sobrien else if (i.suffix == WORD_MNEM_SUFFIX) 211660519Sobrien { 211760519Sobrien int op; 211877311Sobrien for (op = i.operands; --op >= 0;) 211960519Sobrien /* Reject eight bit registers, except where the template 212060519Sobrien requires them. (eg. movzb) */ 212160519Sobrien if ((i.types[op] & Reg8) != 0 212260519Sobrien && (i.tm.operand_types[op] & (Reg16|Reg32|Acc)) != 0) 212360519Sobrien { 212460519Sobrien as_bad (_("`%%%s' not allowed with `%s%c'"), 212560519Sobrien i.op[op].regs->reg_name, 212660519Sobrien i.tm.name, 212760519Sobrien i.suffix); 212860519Sobrien return; 212960519Sobrien } 213060519Sobrien /* Warn if the e prefix on a general reg is present. */ 213177311Sobrien else if ((!quiet_warnings || flag_code == CODE_64BIT) 213277311Sobrien && (i.types[op] & Reg32) != 0 213360519Sobrien && (i.tm.operand_types[op] & (Reg16|Acc)) != 0) 213460519Sobrien { 213577311Sobrien /* Prohibit these changes in the 64bit mode, since 213677311Sobrien the lowering is more complicated. */ 213777311Sobrien if (flag_code == CODE_64BIT) 213877311Sobrien as_bad (_("Incorrect register `%%%s' used with`%c' suffix"), 213977311Sobrien i.op[op].regs->reg_name, 214077311Sobrien i.suffix); 214177311Sobrien else 214277311Sobrien#if REGISTER_WARNINGS 214377311Sobrien as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"), 214477311Sobrien (i.op[op].regs + REGNAM_AX - REGNAM_EAX)->reg_name, 214577311Sobrien i.op[op].regs->reg_name, 214677311Sobrien i.suffix); 214777311Sobrien#endif 214860519Sobrien } 214960519Sobrien } 215077311Sobrien else if (intel_syntax && (i.tm.opcode_modifier & IgnoreSize)) 215177311Sobrien /* Do nothing if the instruction is going to ignore the prefix. */ 215277311Sobrien ; 215360519Sobrien else 215477311Sobrien abort (); 215533965Sjdp } 215660519Sobrien else if ((i.tm.opcode_modifier & DefaultSize) && !i.suffix) 215760519Sobrien { 215860519Sobrien i.suffix = stackop_size; 215960519Sobrien } 216033965Sjdp /* Make still unresolved immediate matches conform to size of immediate 216160519Sobrien given in i.suffix. Note: overlap2 cannot be an immediate! */ 216277311Sobrien if ((overlap0 & (Imm8 | Imm8S | Imm16 | Imm32 | Imm32S)) 216333965Sjdp && overlap0 != Imm8 && overlap0 != Imm8S 216477311Sobrien && overlap0 != Imm16 && overlap0 != Imm32S 216577311Sobrien && overlap0 != Imm32 && overlap0 != Imm64) 216633965Sjdp { 216760519Sobrien if (i.suffix) 216833965Sjdp { 216960519Sobrien overlap0 &= (i.suffix == BYTE_MNEM_SUFFIX ? (Imm8 | Imm8S) : 217077311Sobrien (i.suffix == WORD_MNEM_SUFFIX ? Imm16 : 217177311Sobrien (i.suffix == QWORD_MNEM_SUFFIX ? Imm64 | Imm32S : Imm32))); 217260519Sobrien } 217377311Sobrien else if (overlap0 == (Imm16 | Imm32S | Imm32) 217477311Sobrien || overlap0 == (Imm16 | Imm32) 217577311Sobrien || overlap0 == (Imm16 | Imm32S)) 217660519Sobrien { 217760519Sobrien overlap0 = 217877311Sobrien ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0)) ? Imm16 : Imm32S; 217960519Sobrien } 218077311Sobrien if (overlap0 != Imm8 && overlap0 != Imm8S 218177311Sobrien && overlap0 != Imm16 && overlap0 != Imm32S 218277311Sobrien && overlap0 != Imm32 && overlap0 != Imm64) 218360519Sobrien { 218460519Sobrien as_bad (_("no instruction mnemonic suffix given; can't determine immediate size")); 218533965Sjdp return; 218633965Sjdp } 218733965Sjdp } 218877311Sobrien if ((overlap1 & (Imm8 | Imm8S | Imm16 | Imm32S | Imm32)) 218933965Sjdp && overlap1 != Imm8 && overlap1 != Imm8S 219077311Sobrien && overlap1 != Imm16 && overlap1 != Imm32S 219177311Sobrien && overlap1 != Imm32 && overlap1 != Imm64) 219233965Sjdp { 219360519Sobrien if (i.suffix) 219433965Sjdp { 219560519Sobrien overlap1 &= (i.suffix == BYTE_MNEM_SUFFIX ? (Imm8 | Imm8S) : 219677311Sobrien (i.suffix == WORD_MNEM_SUFFIX ? Imm16 : 219777311Sobrien (i.suffix == QWORD_MNEM_SUFFIX ? Imm64 | Imm32S : Imm32))); 219860519Sobrien } 219977311Sobrien else if (overlap1 == (Imm16 | Imm32 | Imm32S) 220077311Sobrien || overlap1 == (Imm16 | Imm32) 220177311Sobrien || overlap1 == (Imm16 | Imm32S)) 220260519Sobrien { 220360519Sobrien overlap1 = 220477311Sobrien ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0)) ? Imm16 : Imm32S; 220560519Sobrien } 220677311Sobrien if (overlap1 != Imm8 && overlap1 != Imm8S 220777311Sobrien && overlap1 != Imm16 && overlap1 != Imm32S 220877311Sobrien && overlap1 != Imm32 && overlap1 != Imm64) 220960519Sobrien { 221077311Sobrien as_bad (_("no instruction mnemonic suffix given; can't determine immediate size %x %c"),overlap1, i.suffix); 221133965Sjdp return; 221233965Sjdp } 221333965Sjdp } 221460519Sobrien assert ((overlap2 & Imm) == 0); 221533965Sjdp 221633965Sjdp i.types[0] = overlap0; 221733965Sjdp if (overlap0 & ImplicitRegister) 221833965Sjdp i.reg_operands--; 221960519Sobrien if (overlap0 & Imm1) 222077311Sobrien i.imm_operands = 0; /* kludge for shift insns. */ 222160519Sobrien 222260519Sobrien i.types[1] = overlap1; 222333965Sjdp if (overlap1 & ImplicitRegister) 222433965Sjdp i.reg_operands--; 222560519Sobrien 222660519Sobrien i.types[2] = overlap2; 222733965Sjdp if (overlap2 & ImplicitRegister) 222833965Sjdp i.reg_operands--; 222933965Sjdp 223033965Sjdp /* Finalize opcode. First, we change the opcode based on the operand 223160519Sobrien size given by i.suffix: We need not change things for byte insns. */ 223233965Sjdp 223338891Sjdp if (!i.suffix && (i.tm.opcode_modifier & W)) 223433965Sjdp { 223560519Sobrien as_bad (_("no instruction mnemonic suffix given and no register operands; can't size instruction")); 223633965Sjdp return; 223733965Sjdp } 223833965Sjdp 223977311Sobrien /* For movzx and movsx, need to check the register type. */ 224060519Sobrien if (intel_syntax 224160519Sobrien && (i.tm.base_opcode == 0xfb6 || i.tm.base_opcode == 0xfbe)) 224260519Sobrien if (i.suffix && i.suffix == BYTE_MNEM_SUFFIX) 224360519Sobrien { 224460519Sobrien unsigned int prefix = DATA_PREFIX_OPCODE; 224560519Sobrien 224660519Sobrien if ((i.op[1].regs->reg_type & Reg16) != 0) 224760519Sobrien if (!add_prefix (prefix)) 224860519Sobrien return; 224960519Sobrien } 225060519Sobrien 225160519Sobrien if (i.suffix && i.suffix != BYTE_MNEM_SUFFIX) 225233965Sjdp { 225360519Sobrien /* It's not a byte, select word/dword operation. */ 225438891Sjdp if (i.tm.opcode_modifier & W) 225533965Sjdp { 225660519Sobrien if (i.tm.opcode_modifier & ShortForm) 225760519Sobrien i.tm.base_opcode |= 8; 225860519Sobrien else 225960519Sobrien i.tm.base_opcode |= 1; 226033965Sjdp } 226160519Sobrien /* Now select between word & dword operations via the operand 226260519Sobrien size prefix, except for instructions that will ignore this 226360519Sobrien prefix anyway. */ 226477311Sobrien if (i.suffix != QWORD_MNEM_SUFFIX 226577311Sobrien && (i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT) 226660519Sobrien && !(i.tm.opcode_modifier & IgnoreSize)) 226760519Sobrien { 226860519Sobrien unsigned int prefix = DATA_PREFIX_OPCODE; 226960519Sobrien if (i.tm.opcode_modifier & JumpByte) /* jcxz, loop */ 227060519Sobrien prefix = ADDR_PREFIX_OPCODE; 227160519Sobrien 227260519Sobrien if (! add_prefix (prefix)) 227360519Sobrien return; 227460519Sobrien } 227577311Sobrien 227691054Sobrien if (i.suffix != QWORD_MNEM_SUFFIX && (flag_code == CODE_64BIT) 227791054Sobrien && !(i.tm.opcode_modifier & IgnoreSize) 227891054Sobrien && (i.tm.opcode_modifier & JumpByte)) 227991054Sobrien { 228091054Sobrien if (! add_prefix (ADDR_PREFIX_OPCODE)) 228191054Sobrien return; 228291054Sobrien } 228391054Sobrien 228477311Sobrien /* Set mode64 for an operand. */ 228577311Sobrien if (i.suffix == QWORD_MNEM_SUFFIX 228677311Sobrien && !(i.tm.opcode_modifier & NoRex64)) 228777311Sobrien { 228877311Sobrien i.rex.mode64 = 1; 228977311Sobrien if (flag_code < CODE_64BIT) 229077311Sobrien { 229177311Sobrien as_bad (_("64bit operations available only in 64bit modes.")); 229277311Sobrien return; 229377311Sobrien } 229477311Sobrien } 229577311Sobrien 229660519Sobrien /* Size floating point instruction. */ 229777311Sobrien if (i.suffix == LONG_MNEM_SUFFIX) 229860519Sobrien { 229960519Sobrien if (i.tm.opcode_modifier & FloatMF) 230060519Sobrien i.tm.base_opcode ^= 4; 230160519Sobrien } 230233965Sjdp } 230333965Sjdp 230460519Sobrien if (i.tm.opcode_modifier & ImmExt) 230560519Sobrien { 230660519Sobrien /* These AMD 3DNow! and Intel Katmai New Instructions have an 230760519Sobrien opcode suffix which is coded in the same place as an 8-bit 230860519Sobrien immediate field would be. Here we fake an 8-bit immediate 230960519Sobrien operand from the opcode suffix stored in tm.extension_opcode. */ 231060519Sobrien 231160519Sobrien expressionS *exp; 231260519Sobrien 231377311Sobrien assert (i.imm_operands == 0 && i.operands <= 2 && 2 < MAX_OPERANDS); 231460519Sobrien 231560519Sobrien exp = &im_expressions[i.imm_operands++]; 231660519Sobrien i.op[i.operands].imms = exp; 231760519Sobrien i.types[i.operands++] = Imm8; 231860519Sobrien exp->X_op = O_constant; 231960519Sobrien exp->X_add_number = i.tm.extension_opcode; 232060519Sobrien i.tm.extension_opcode = None; 232160519Sobrien } 232260519Sobrien 232377311Sobrien /* For insns with operands there are more diddles to do to the opcode. */ 232433965Sjdp if (i.operands) 232533965Sjdp { 232660519Sobrien /* Default segment register this instruction will use 232733965Sjdp for memory accesses. 0 means unknown. 232833965Sjdp This is only for optimizing out unnecessary segment overrides. */ 232933965Sjdp const seg_entry *default_seg = 0; 233033965Sjdp 233133965Sjdp /* The imul $imm, %reg instruction is converted into 233260519Sobrien imul $imm, %reg, %reg, and the clr %reg instruction 233360519Sobrien is converted into xor %reg, %reg. */ 233460519Sobrien if (i.tm.opcode_modifier & regKludge) 233533965Sjdp { 233660519Sobrien unsigned int first_reg_op = (i.types[0] & Reg) ? 0 : 1; 233777311Sobrien /* Pretend we saw the extra register operand. */ 233877311Sobrien assert (i.op[first_reg_op + 1].regs == 0); 233977311Sobrien i.op[first_reg_op + 1].regs = i.op[first_reg_op].regs; 234077311Sobrien i.types[first_reg_op + 1] = i.types[first_reg_op]; 234133965Sjdp i.reg_operands = 2; 234233965Sjdp } 234333965Sjdp 234438891Sjdp if (i.tm.opcode_modifier & ShortForm) 234533965Sjdp { 234677311Sobrien /* The register or float register operand is in operand 0 or 1. */ 234733965Sjdp unsigned int op = (i.types[0] & (Reg | FloatReg)) ? 0 : 1; 234877311Sobrien /* Register goes in low 3 bits of opcode. */ 234960519Sobrien i.tm.base_opcode |= i.op[op].regs->reg_num; 235077311Sobrien if (i.op[op].regs->reg_flags & RegRex) 235177311Sobrien i.rex.extZ = 1; 235277311Sobrien if (!quiet_warnings && (i.tm.opcode_modifier & Ugh) != 0) 235333965Sjdp { 235460519Sobrien /* Warn about some common errors, but press on regardless. 235560519Sobrien The first case can be generated by gcc (<= 2.8.1). */ 235660519Sobrien if (i.operands == 2) 235760519Sobrien { 235877311Sobrien /* Reversed arguments on faddp, fsubp, etc. */ 235960519Sobrien as_warn (_("translating to `%s %%%s,%%%s'"), i.tm.name, 236060519Sobrien i.op[1].regs->reg_name, 236160519Sobrien i.op[0].regs->reg_name); 236260519Sobrien } 236360519Sobrien else 236460519Sobrien { 236577311Sobrien /* Extraneous `l' suffix on fp insn. */ 236660519Sobrien as_warn (_("translating to `%s %%%s'"), i.tm.name, 236760519Sobrien i.op[0].regs->reg_name); 236860519Sobrien } 236933965Sjdp } 237033965Sjdp } 237138891Sjdp else if (i.tm.opcode_modifier & Modrm) 237233965Sjdp { 237338891Sjdp /* The opcode is completed (modulo i.tm.extension_opcode which 237438891Sjdp must be put into the modrm byte). 237538891Sjdp Now, we make the modrm & index base bytes based on all the 237677311Sobrien info we've collected. */ 237733965Sjdp 237833965Sjdp /* i.reg_operands MUST be the number of real register operands; 237977311Sobrien implicit registers do not count. */ 238033965Sjdp if (i.reg_operands == 2) 238133965Sjdp { 238233965Sjdp unsigned int source, dest; 238333965Sjdp source = ((i.types[0] 238460519Sobrien & (Reg | RegMMX | RegXMM 238560519Sobrien | SReg2 | SReg3 238660519Sobrien | Control | Debug | Test)) 238733965Sjdp ? 0 : 1); 238833965Sjdp dest = source + 1; 238960519Sobrien 239033965Sjdp i.rm.mode = 3; 239160519Sobrien /* One of the register operands will be encoded in the 239260519Sobrien i.tm.reg field, the other in the combined i.tm.mode 239360519Sobrien and i.tm.regmem fields. If no form of this 239460519Sobrien instruction supports a memory destination operand, 239560519Sobrien then we assume the source operand may sometimes be 239660519Sobrien a memory operand and so we need to store the 239760519Sobrien destination in the i.rm.reg field. */ 239860519Sobrien if ((i.tm.operand_types[dest] & AnyMem) == 0) 239933965Sjdp { 240060519Sobrien i.rm.reg = i.op[dest].regs->reg_num; 240160519Sobrien i.rm.regmem = i.op[source].regs->reg_num; 240277311Sobrien if (i.op[dest].regs->reg_flags & RegRex) 240377311Sobrien i.rex.extX = 1; 240477311Sobrien if (i.op[source].regs->reg_flags & RegRex) 240577311Sobrien i.rex.extZ = 1; 240633965Sjdp } 240733965Sjdp else 240833965Sjdp { 240960519Sobrien i.rm.reg = i.op[source].regs->reg_num; 241060519Sobrien i.rm.regmem = i.op[dest].regs->reg_num; 241177311Sobrien if (i.op[dest].regs->reg_flags & RegRex) 241277311Sobrien i.rex.extZ = 1; 241377311Sobrien if (i.op[source].regs->reg_flags & RegRex) 241477311Sobrien i.rex.extX = 1; 241533965Sjdp } 241633965Sjdp } 241733965Sjdp else 241877311Sobrien { /* If it's not 2 reg operands... */ 241933965Sjdp if (i.mem_operands) 242033965Sjdp { 242133965Sjdp unsigned int fake_zero_displacement = 0; 242260519Sobrien unsigned int op = ((i.types[0] & AnyMem) 242360519Sobrien ? 0 242460519Sobrien : (i.types[1] & AnyMem) ? 1 : 2); 242533965Sjdp 242660519Sobrien default_seg = &ds; 242733965Sjdp 242860519Sobrien if (! i.base_reg) 242933965Sjdp { 243060519Sobrien i.rm.mode = 0; 243160519Sobrien if (! i.disp_operands) 243260519Sobrien fake_zero_displacement = 1; 243360519Sobrien if (! i.index_reg) 243433965Sjdp { 243577311Sobrien /* Operand is just <disp> */ 243691054Sobrien if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0) 243791054Sobrien && (flag_code != CODE_64BIT)) 243860519Sobrien { 243960519Sobrien i.rm.regmem = NO_BASE_REGISTER_16; 244060519Sobrien i.types[op] &= ~Disp; 244160519Sobrien i.types[op] |= Disp16; 244260519Sobrien } 244391054Sobrien else if (flag_code != CODE_64BIT 244491054Sobrien || (i.prefix[ADDR_PREFIX] != 0)) 244560519Sobrien { 244660519Sobrien i.rm.regmem = NO_BASE_REGISTER; 244760519Sobrien i.types[op] &= ~Disp; 244860519Sobrien i.types[op] |= Disp32; 244960519Sobrien } 245077311Sobrien else 245177311Sobrien { 245277311Sobrien /* 64bit mode overwrites the 32bit 245377311Sobrien absolute addressing by RIP relative 245477311Sobrien addressing and absolute addressing 245577311Sobrien is encoded by one of the redundant 245677311Sobrien SIB forms. */ 245777311Sobrien 245877311Sobrien i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; 245977311Sobrien i.sib.base = NO_BASE_REGISTER; 246077311Sobrien i.sib.index = NO_INDEX_REGISTER; 246177311Sobrien i.types[op] &= ~Disp; 246277311Sobrien i.types[op] |= Disp32S; 246377311Sobrien } 246433965Sjdp } 246577311Sobrien else /* ! i.base_reg && i.index_reg */ 246660519Sobrien { 246760519Sobrien i.sib.index = i.index_reg->reg_num; 246860519Sobrien i.sib.base = NO_BASE_REGISTER; 246960519Sobrien i.sib.scale = i.log2_scale_factor; 247060519Sobrien i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; 247160519Sobrien i.types[op] &= ~Disp; 247277311Sobrien if (flag_code != CODE_64BIT) 247377311Sobrien i.types[op] |= Disp32; /* Must be 32 bit */ 247477311Sobrien else 247577311Sobrien i.types[op] |= Disp32S; 247677311Sobrien if (i.index_reg->reg_flags & RegRex) 247777311Sobrien i.rex.extY = 1; 247860519Sobrien } 247933965Sjdp } 248077311Sobrien /* RIP addressing for 64bit mode. */ 248177311Sobrien else if (i.base_reg->reg_type == BaseIndex) 248277311Sobrien { 248377311Sobrien i.rm.regmem = NO_BASE_REGISTER; 248477311Sobrien i.types[op] &= ~Disp; 248577311Sobrien i.types[op] |= Disp32S; 248677311Sobrien i.flags[op] = Operand_PCrel; 248777311Sobrien } 248860519Sobrien else if (i.base_reg->reg_type & Reg16) 248933965Sjdp { 249060519Sobrien switch (i.base_reg->reg_num) 249133965Sjdp { 249277311Sobrien case 3: /* (%bx) */ 249360519Sobrien if (! i.index_reg) 249460519Sobrien i.rm.regmem = 7; 249577311Sobrien else /* (%bx,%si) -> 0, or (%bx,%di) -> 1 */ 249660519Sobrien i.rm.regmem = i.index_reg->reg_num - 6; 249760519Sobrien break; 249877311Sobrien case 5: /* (%bp) */ 249960519Sobrien default_seg = &ss; 250060519Sobrien if (! i.index_reg) 250160519Sobrien { 250260519Sobrien i.rm.regmem = 6; 250360519Sobrien if ((i.types[op] & Disp) == 0) 250460519Sobrien { 250577311Sobrien /* fake (%bp) into 0(%bp) */ 250660519Sobrien i.types[op] |= Disp8; 250760519Sobrien fake_zero_displacement = 1; 250860519Sobrien } 250960519Sobrien } 251077311Sobrien else /* (%bp,%si) -> 2, or (%bp,%di) -> 3 */ 251160519Sobrien i.rm.regmem = i.index_reg->reg_num - 6 + 2; 251260519Sobrien break; 251377311Sobrien default: /* (%si) -> 4 or (%di) -> 5 */ 251460519Sobrien i.rm.regmem = i.base_reg->reg_num - 6 + 4; 251533965Sjdp } 251660519Sobrien i.rm.mode = mode_from_disp_size (i.types[op]); 251733965Sjdp } 251877311Sobrien else /* i.base_reg and 32/64 bit mode */ 251933965Sjdp { 252077311Sobrien if (flag_code == CODE_64BIT 252177311Sobrien && (i.types[op] & Disp)) 252277311Sobrien { 252377311Sobrien if (i.types[op] & Disp8) 252477311Sobrien i.types[op] = Disp8 | Disp32S; 252577311Sobrien else 252677311Sobrien i.types[op] = Disp32S; 252777311Sobrien } 252833965Sjdp i.rm.regmem = i.base_reg->reg_num; 252977311Sobrien if (i.base_reg->reg_flags & RegRex) 253077311Sobrien i.rex.extZ = 1; 253160519Sobrien i.sib.base = i.base_reg->reg_num; 253277311Sobrien /* x86-64 ignores REX prefix bit here to avoid 253377311Sobrien decoder complications. */ 253477311Sobrien if ((i.base_reg->reg_num & 7) == EBP_REG_NUM) 253533965Sjdp { 253660519Sobrien default_seg = &ss; 253760519Sobrien if (i.disp_operands == 0) 253860519Sobrien { 253933965Sjdp fake_zero_displacement = 1; 254033965Sjdp i.types[op] |= Disp8; 254133965Sjdp } 254233965Sjdp } 254360519Sobrien else if (i.base_reg->reg_num == ESP_REG_NUM) 254460519Sobrien { 254560519Sobrien default_seg = &ss; 254660519Sobrien } 254760519Sobrien i.sib.scale = i.log2_scale_factor; 254860519Sobrien if (! i.index_reg) 254960519Sobrien { 255060519Sobrien /* <disp>(%esp) becomes two byte modrm 255160519Sobrien with no index register. We've already 255260519Sobrien stored the code for esp in i.rm.regmem 255360519Sobrien ie. ESCAPE_TO_TWO_BYTE_ADDRESSING. Any 255460519Sobrien base register besides %esp will not use 255560519Sobrien the extra modrm byte. */ 255660519Sobrien i.sib.index = NO_INDEX_REGISTER; 255760519Sobrien#if ! SCALE1_WHEN_NO_INDEX 255860519Sobrien /* Another case where we force the second 255960519Sobrien modrm byte. */ 256060519Sobrien if (i.log2_scale_factor) 256160519Sobrien i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; 256260519Sobrien#endif 256360519Sobrien } 256460519Sobrien else 256560519Sobrien { 256660519Sobrien i.sib.index = i.index_reg->reg_num; 256760519Sobrien i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; 256877311Sobrien if (i.index_reg->reg_flags & RegRex) 256977311Sobrien i.rex.extY = 1; 257060519Sobrien } 257160519Sobrien i.rm.mode = mode_from_disp_size (i.types[op]); 257233965Sjdp } 257360519Sobrien 257433965Sjdp if (fake_zero_displacement) 257533965Sjdp { 257633965Sjdp /* Fakes a zero displacement assuming that i.types[op] 257777311Sobrien holds the correct displacement size. */ 257860519Sobrien expressionS *exp; 257960519Sobrien 258060519Sobrien assert (i.op[op].disps == 0); 258133965Sjdp exp = &disp_expressions[i.disp_operands++]; 258260519Sobrien i.op[op].disps = exp; 258333965Sjdp exp->X_op = O_constant; 258433965Sjdp exp->X_add_number = 0; 258533965Sjdp exp->X_add_symbol = (symbolS *) 0; 258633965Sjdp exp->X_op_symbol = (symbolS *) 0; 258733965Sjdp } 258833965Sjdp } 258933965Sjdp 259033965Sjdp /* Fill in i.rm.reg or i.rm.regmem field with register 259138891Sjdp operand (if any) based on i.tm.extension_opcode. 259238891Sjdp Again, we must be careful to make sure that 259338891Sjdp segment/control/debug/test/MMX registers are coded 259477311Sobrien into the i.rm.reg field. */ 259533965Sjdp if (i.reg_operands) 259633965Sjdp { 259733965Sjdp unsigned int op = 259833965Sjdp ((i.types[0] 259960519Sobrien & (Reg | RegMMX | RegXMM 260060519Sobrien | SReg2 | SReg3 260160519Sobrien | Control | Debug | Test)) 260233965Sjdp ? 0 260333965Sjdp : ((i.types[1] 260460519Sobrien & (Reg | RegMMX | RegXMM 260560519Sobrien | SReg2 | SReg3 260660519Sobrien | Control | Debug | Test)) 260733965Sjdp ? 1 260833965Sjdp : 2)); 260933965Sjdp /* If there is an extension opcode to put here, the 261077311Sobrien register number must be put into the regmem field. */ 261138891Sjdp if (i.tm.extension_opcode != None) 261277311Sobrien { 261377311Sobrien i.rm.regmem = i.op[op].regs->reg_num; 261477311Sobrien if (i.op[op].regs->reg_flags & RegRex) 261577311Sobrien i.rex.extZ = 1; 261677311Sobrien } 261733965Sjdp else 261877311Sobrien { 261977311Sobrien i.rm.reg = i.op[op].regs->reg_num; 262077311Sobrien if (i.op[op].regs->reg_flags & RegRex) 262177311Sobrien i.rex.extX = 1; 262277311Sobrien } 262333965Sjdp 262433965Sjdp /* Now, if no memory operand has set i.rm.mode = 0, 1, 2 262533965Sjdp we must set it to 3 to indicate this is a register 262660519Sobrien operand in the regmem field. */ 262733965Sjdp if (!i.mem_operands) 262833965Sjdp i.rm.mode = 3; 262933965Sjdp } 263033965Sjdp 263177311Sobrien /* Fill in i.rm.reg field with extension opcode (if any). */ 263238891Sjdp if (i.tm.extension_opcode != None) 263338891Sjdp i.rm.reg = i.tm.extension_opcode; 263433965Sjdp } 263533965Sjdp } 263660519Sobrien else if (i.tm.opcode_modifier & (Seg2ShortForm | Seg3ShortForm)) 263733965Sjdp { 263877311Sobrien if (i.tm.base_opcode == POP_SEG_SHORT 263977311Sobrien && i.op[0].regs->reg_num == 1) 264033965Sjdp { 264160519Sobrien as_bad (_("you can't `pop %%cs'")); 264260519Sobrien return; 264333965Sjdp } 264460519Sobrien i.tm.base_opcode |= (i.op[0].regs->reg_num << 3); 264577311Sobrien if (i.op[0].regs->reg_flags & RegRex) 264677311Sobrien i.rex.extZ = 1; 264733965Sjdp } 264860519Sobrien else if ((i.tm.base_opcode & ~(D|W)) == MOV_AX_DISP32) 264960519Sobrien { 265060519Sobrien default_seg = &ds; 265160519Sobrien } 265260519Sobrien else if ((i.tm.opcode_modifier & IsString) != 0) 265360519Sobrien { 265460519Sobrien /* For the string instructions that allow a segment override 265560519Sobrien on one of their operands, the default segment is ds. */ 265660519Sobrien default_seg = &ds; 265760519Sobrien } 265833965Sjdp 265933965Sjdp /* If a segment was explicitly specified, 266033965Sjdp and the specified segment is not the default, 266133965Sjdp use an opcode prefix to select it. 266233965Sjdp If we never figured out what the default segment is, 266333965Sjdp then default_seg will be zero at this point, 266433965Sjdp and the specified segment prefix will always be used. */ 266560519Sobrien if ((i.seg[0]) && (i.seg[0] != default_seg)) 266633965Sjdp { 266760519Sobrien if (! add_prefix (i.seg[0]->seg_prefix)) 266860519Sobrien return; 266933965Sjdp } 267033965Sjdp } 267177311Sobrien else if (!quiet_warnings && (i.tm.opcode_modifier & Ugh) != 0) 267260519Sobrien { 267360519Sobrien /* UnixWare fsub no args is alias for fsubp, fadd -> faddp, etc. */ 267460519Sobrien as_warn (_("translating to `%sp'"), i.tm.name); 267560519Sobrien } 267633965Sjdp } 267733965Sjdp 267877311Sobrien /* Handle conversion of 'int $3' --> special int3 insn. */ 267960519Sobrien if (i.tm.base_opcode == INT_OPCODE && i.op[0].imms->X_add_number == 3) 268033965Sjdp { 268138891Sjdp i.tm.base_opcode = INT3_OPCODE; 268233965Sjdp i.imm_operands = 0; 268333965Sjdp } 268433965Sjdp 268560519Sobrien if ((i.tm.opcode_modifier & (Jump | JumpByte | JumpDword)) 268660519Sobrien && i.op[0].disps->X_op == O_constant) 268760519Sobrien { 268860519Sobrien /* Convert "jmp constant" (and "call constant") to a jump (call) to 268960519Sobrien the absolute address given by the constant. Since ix86 jumps and 269060519Sobrien calls are pc relative, we need to generate a reloc. */ 269160519Sobrien i.op[0].disps->X_add_symbol = &abs_symbol; 269260519Sobrien i.op[0].disps->X_op = O_symbol; 269360519Sobrien } 269460519Sobrien 269577311Sobrien if (i.tm.opcode_modifier & Rex64) 269677311Sobrien i.rex.mode64 = 1; 269777311Sobrien 269877311Sobrien /* For 8bit registers we would need an empty rex prefix. 269977311Sobrien Also in the case instruction is already having prefix, 270077311Sobrien we need to convert old registers to new ones. */ 270177311Sobrien 270277311Sobrien if (((i.types[0] & Reg8) && (i.op[0].regs->reg_flags & RegRex64)) 270377311Sobrien || ((i.types[1] & Reg8) && (i.op[1].regs->reg_flags & RegRex64)) 270477311Sobrien || ((i.rex.mode64 || i.rex.extX || i.rex.extY || i.rex.extZ || i.rex.empty) 270577311Sobrien && ((i.types[0] & Reg8) || (i.types[1] & Reg8)))) 270677311Sobrien { 270777311Sobrien int x; 270877311Sobrien i.rex.empty = 1; 270977311Sobrien for (x = 0; x < 2; x++) 271077311Sobrien { 271177311Sobrien /* Look for 8bit operand that does use old registers. */ 271277311Sobrien if (i.types[x] & Reg8 271377311Sobrien && !(i.op[x].regs->reg_flags & RegRex64)) 271477311Sobrien { 271577311Sobrien /* In case it is "hi" register, give up. */ 271677311Sobrien if (i.op[x].regs->reg_num > 3) 271777311Sobrien as_bad (_("Can't encode registers '%%%s' in the instruction requiring REX prefix.\n"), 271877311Sobrien i.op[x].regs->reg_name); 271977311Sobrien 272077311Sobrien /* Otherwise it is equivalent to the extended register. 272177311Sobrien Since the encoding don't change this is merely cosmetical 272277311Sobrien cleanup for debug output. */ 272377311Sobrien 272477311Sobrien i.op[x].regs = i.op[x].regs + 8; 272577311Sobrien } 272677311Sobrien } 272777311Sobrien } 272877311Sobrien 272977311Sobrien if (i.rex.mode64 || i.rex.extX || i.rex.extY || i.rex.extZ || i.rex.empty) 273077311Sobrien add_prefix (0x40 273177311Sobrien | (i.rex.mode64 ? 8 : 0) 273277311Sobrien | (i.rex.extX ? 4 : 0) 273377311Sobrien | (i.rex.extY ? 2 : 0) 273477311Sobrien | (i.rex.extZ ? 1 : 0)); 273577311Sobrien 273677311Sobrien /* We are ready to output the insn. */ 273733965Sjdp { 273833965Sjdp register char *p; 273933965Sjdp 274078840Sobrien /* Tie dwarf2 debug info to the address at the start of the insn. 274178840Sobrien We can't do this after the insn has been output as the current 274278840Sobrien frag may have been closed off. eg. by frag_var. */ 274378840Sobrien dwarf2_emit_insn (0); 274478840Sobrien 274577311Sobrien /* Output jumps. */ 274638891Sjdp if (i.tm.opcode_modifier & Jump) 274733965Sjdp { 274860519Sobrien int code16; 274960519Sobrien int prefix; 275089867Sobrien relax_substateT subtype; 275189867Sobrien symbolS *sym; 275289867Sobrien offsetT off; 275333965Sjdp 275460519Sobrien code16 = 0; 275577311Sobrien if (flag_code == CODE_16BIT) 275660519Sobrien code16 = CODE16; 275760519Sobrien 275860519Sobrien prefix = 0; 275960519Sobrien if (i.prefix[DATA_PREFIX]) 276033965Sjdp { 276160519Sobrien prefix = 1; 276260519Sobrien i.prefixes -= 1; 276360519Sobrien code16 ^= CODE16; 276460519Sobrien } 276578840Sobrien /* Pentium4 branch hints. */ 276678840Sobrien if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */ 276778840Sobrien || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE /* taken */) 276878840Sobrien { 276978840Sobrien prefix++; 277078840Sobrien i.prefixes--; 277178840Sobrien } 277277311Sobrien if (i.prefix[REX_PREFIX]) 277377311Sobrien { 277477311Sobrien prefix++; 277577311Sobrien i.prefixes--; 277677311Sobrien } 277733965Sjdp 277860519Sobrien if (i.prefixes != 0 && !intel_syntax) 277960519Sobrien as_warn (_("skipping prefixes on this instruction")); 278033965Sjdp 278160519Sobrien /* It's always a symbol; End frag & setup for relax. 278260519Sobrien Make sure there is enough room in this frag for the largest 278360519Sobrien instruction we may generate in md_convert_frag. This is 2 278460519Sobrien bytes for the opcode and room for the prefix and largest 278560519Sobrien displacement. */ 278678840Sobrien frag_grow (prefix + 2 + 4); 278760519Sobrien /* Prefix and 1 opcode byte go in fr_fix. */ 278860519Sobrien p = frag_more (prefix + 1); 278977311Sobrien if (i.prefix[DATA_PREFIX]) 279060519Sobrien *p++ = DATA_PREFIX_OPCODE; 279178840Sobrien if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE 279278840Sobrien || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE) 279378840Sobrien *p++ = i.prefix[SEG_PREFIX]; 279477311Sobrien if (i.prefix[REX_PREFIX]) 279577311Sobrien *p++ = i.prefix[REX_PREFIX]; 279660519Sobrien *p = i.tm.base_opcode; 279789867Sobrien 279889867Sobrien if ((unsigned char) *p == JUMP_PC_RELATIVE) 279989867Sobrien subtype = ENCODE_RELAX_STATE (UNCOND_JUMP, SMALL); 280089867Sobrien else if ((cpu_arch_flags & Cpu386) != 0) 280189867Sobrien subtype = ENCODE_RELAX_STATE (COND_JUMP, SMALL); 280289867Sobrien else 280389867Sobrien subtype = ENCODE_RELAX_STATE (COND_JUMP86, SMALL); 280489867Sobrien subtype |= code16; 280589867Sobrien 280689867Sobrien sym = i.op[0].disps->X_add_symbol; 280789867Sobrien off = i.op[0].disps->X_add_number; 280889867Sobrien 280989867Sobrien if (i.op[0].disps->X_op != O_constant 281089867Sobrien && i.op[0].disps->X_op != O_symbol) 281189867Sobrien { 281289867Sobrien /* Handle complex expressions. */ 281389867Sobrien sym = make_expr_symbol (i.op[0].disps); 281489867Sobrien off = 0; 281589867Sobrien } 281689867Sobrien 281789867Sobrien /* 1 possible extra opcode + 4 byte displacement go in var part. 281861847Sobrien Pass reloc in fr_var. */ 281989867Sobrien frag_var (rs_machine_dependent, 5, i.reloc[0], subtype, sym, off, p); 282033965Sjdp } 282138891Sjdp else if (i.tm.opcode_modifier & (JumpByte | JumpDword)) 282233965Sjdp { 282360519Sobrien int size; 282433965Sjdp 282560519Sobrien if (i.tm.opcode_modifier & JumpByte) 282633965Sjdp { 282760519Sobrien /* This is a loop or jecxz type instruction. */ 282860519Sobrien size = 1; 282960519Sobrien if (i.prefix[ADDR_PREFIX]) 283033965Sjdp { 283160519Sobrien FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE); 283260519Sobrien i.prefixes -= 1; 283360519Sobrien } 283478840Sobrien /* Pentium4 branch hints. */ 283578840Sobrien if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */ 283678840Sobrien || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE /* taken */) 283778840Sobrien { 283878840Sobrien FRAG_APPEND_1_CHAR (i.prefix[SEG_PREFIX]); 283978840Sobrien i.prefixes--; 284078840Sobrien } 284160519Sobrien } 284260519Sobrien else 284360519Sobrien { 284460519Sobrien int code16; 284538891Sjdp 284660519Sobrien code16 = 0; 284777311Sobrien if (flag_code == CODE_16BIT) 284860519Sobrien code16 = CODE16; 284938891Sjdp 285060519Sobrien if (i.prefix[DATA_PREFIX]) 285160519Sobrien { 285260519Sobrien FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE); 285360519Sobrien i.prefixes -= 1; 285460519Sobrien code16 ^= CODE16; 285533965Sjdp } 285633965Sjdp 285760519Sobrien size = 4; 285860519Sobrien if (code16) 285960519Sobrien size = 2; 286033965Sjdp } 286133965Sjdp 286277311Sobrien if (i.prefix[REX_PREFIX]) 286377311Sobrien { 286477311Sobrien FRAG_APPEND_1_CHAR (i.prefix[REX_PREFIX]); 286577311Sobrien i.prefixes -= 1; 286677311Sobrien } 286777311Sobrien 286860519Sobrien if (i.prefixes != 0 && !intel_syntax) 286960519Sobrien as_warn (_("skipping prefixes on this instruction")); 287060519Sobrien 287178840Sobrien p = frag_more (1 + size); 287278840Sobrien *p++ = i.tm.base_opcode; 287333965Sjdp 287460519Sobrien fix_new_exp (frag_now, p - frag_now->fr_literal, size, 287578840Sobrien i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0])); 287633965Sjdp } 287738891Sjdp else if (i.tm.opcode_modifier & JumpInterSegment) 287833965Sjdp { 287960519Sobrien int size; 288060519Sobrien int prefix; 288160519Sobrien int code16; 288260519Sobrien 288360519Sobrien code16 = 0; 288477311Sobrien if (flag_code == CODE_16BIT) 288560519Sobrien code16 = CODE16; 288660519Sobrien 288760519Sobrien prefix = 0; 288860519Sobrien if (i.prefix[DATA_PREFIX]) 288933965Sjdp { 289060519Sobrien prefix = 1; 289160519Sobrien i.prefixes -= 1; 289260519Sobrien code16 ^= CODE16; 289333965Sjdp } 289477311Sobrien if (i.prefix[REX_PREFIX]) 289577311Sobrien { 289677311Sobrien prefix++; 289777311Sobrien i.prefixes -= 1; 289877311Sobrien } 289933965Sjdp 290060519Sobrien size = 4; 290160519Sobrien if (code16) 290260519Sobrien size = 2; 290360519Sobrien 290460519Sobrien if (i.prefixes != 0 && !intel_syntax) 290560519Sobrien as_warn (_("skipping prefixes on this instruction")); 290660519Sobrien 290777311Sobrien /* 1 opcode; 2 segment; offset */ 290860519Sobrien p = frag_more (prefix + 1 + 2 + size); 290977311Sobrien 291077311Sobrien if (i.prefix[DATA_PREFIX]) 291160519Sobrien *p++ = DATA_PREFIX_OPCODE; 291277311Sobrien 291377311Sobrien if (i.prefix[REX_PREFIX]) 291477311Sobrien *p++ = i.prefix[REX_PREFIX]; 291577311Sobrien 291660519Sobrien *p++ = i.tm.base_opcode; 291760519Sobrien if (i.op[1].imms->X_op == O_constant) 291860519Sobrien { 291977311Sobrien offsetT n = i.op[1].imms->X_add_number; 292060519Sobrien 292160519Sobrien if (size == 2 292260519Sobrien && !fits_in_unsigned_word (n) 292360519Sobrien && !fits_in_signed_word (n)) 292460519Sobrien { 292560519Sobrien as_bad (_("16-bit jump out of range")); 292660519Sobrien return; 292760519Sobrien } 292877311Sobrien md_number_to_chars (p, n, size); 292960519Sobrien } 293033965Sjdp else 293160519Sobrien fix_new_exp (frag_now, p - frag_now->fr_literal, size, 293278840Sobrien i.op[1].imms, 0, reloc (size, 0, 0, i.reloc[1])); 293360519Sobrien if (i.op[0].imms->X_op != O_constant) 293460519Sobrien as_bad (_("can't handle non absolute segment in `%s'"), 293560519Sobrien i.tm.name); 293660519Sobrien md_number_to_chars (p + size, (valueT) i.op[0].imms->X_add_number, 2); 293733965Sjdp } 293833965Sjdp else 293933965Sjdp { 294077311Sobrien /* Output normal instructions here. */ 294133965Sjdp unsigned char *q; 294233965Sjdp 294377311Sobrien /* All opcodes on i386 have eighter 1 or 2 bytes. We may use third 294477311Sobrien byte for the SSE instructions to specify prefix they require. */ 294577311Sobrien if (i.tm.base_opcode & 0xff0000) 294677311Sobrien add_prefix ((i.tm.base_opcode >> 16) & 0xff); 294777311Sobrien 294877311Sobrien /* The prefix bytes. */ 294960519Sobrien for (q = i.prefix; 295060519Sobrien q < i.prefix + sizeof (i.prefix) / sizeof (i.prefix[0]); 295160519Sobrien q++) 295233965Sjdp { 295360519Sobrien if (*q) 295460519Sobrien { 295560519Sobrien p = frag_more (1); 295660519Sobrien md_number_to_chars (p, (valueT) *q, 1); 295760519Sobrien } 295833965Sjdp } 295933965Sjdp 296077311Sobrien /* Now the opcode; be careful about word order here! */ 296138891Sjdp if (fits_in_unsigned_byte (i.tm.base_opcode)) 296233965Sjdp { 296338891Sjdp FRAG_APPEND_1_CHAR (i.tm.base_opcode); 296433965Sjdp } 296577311Sobrien else 296633965Sjdp { 296733965Sjdp p = frag_more (2); 296877311Sobrien /* Put out high byte first: can't use md_number_to_chars! */ 296938891Sjdp *p++ = (i.tm.base_opcode >> 8) & 0xff; 297038891Sjdp *p = i.tm.base_opcode & 0xff; 297133965Sjdp } 297233965Sjdp 297360519Sobrien /* Now the modrm byte and sib byte (if present). */ 297438891Sjdp if (i.tm.opcode_modifier & Modrm) 297533965Sjdp { 297633965Sjdp p = frag_more (1); 297733965Sjdp md_number_to_chars (p, 297833965Sjdp (valueT) (i.rm.regmem << 0 297933965Sjdp | i.rm.reg << 3 298033965Sjdp | i.rm.mode << 6), 298133965Sjdp 1); 298260519Sobrien /* If i.rm.regmem == ESP (4) 298360519Sobrien && i.rm.mode != (Register mode) 298460519Sobrien && not 16 bit 298560519Sobrien ==> need second modrm byte. */ 298660519Sobrien if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING 298760519Sobrien && i.rm.mode != 3 298860519Sobrien && !(i.base_reg && (i.base_reg->reg_type & Reg16) != 0)) 298933965Sjdp { 299033965Sjdp p = frag_more (1); 299160519Sobrien md_number_to_chars (p, 299260519Sobrien (valueT) (i.sib.base << 0 299360519Sobrien | i.sib.index << 3 299460519Sobrien | i.sib.scale << 6), 299533965Sjdp 1); 299633965Sjdp } 299733965Sjdp } 299833965Sjdp 299933965Sjdp if (i.disp_operands) 300033965Sjdp { 300133965Sjdp register unsigned int n; 300233965Sjdp 300333965Sjdp for (n = 0; n < i.operands; n++) 300433965Sjdp { 300560519Sobrien if (i.types[n] & Disp) 300633965Sjdp { 300760519Sobrien if (i.op[n].disps->X_op == O_constant) 300833965Sjdp { 300977311Sobrien int size; 301077311Sobrien offsetT val; 301160519Sobrien 301277311Sobrien size = 4; 301377311Sobrien if (i.types[n] & (Disp8 | Disp16 | Disp64)) 301433965Sjdp { 301560519Sobrien size = 2; 301660519Sobrien if (i.types[n] & Disp8) 301777311Sobrien size = 1; 301877311Sobrien if (i.types[n] & Disp64) 301977311Sobrien size = 8; 302033965Sjdp } 302177311Sobrien val = offset_in_range (i.op[n].disps->X_add_number, 302277311Sobrien size); 302360519Sobrien p = frag_more (size); 302477311Sobrien md_number_to_chars (p, val, size); 302533965Sjdp } 302633965Sjdp else 302760519Sobrien { 302860519Sobrien int size = 4; 302977311Sobrien int sign = 0; 303077311Sobrien int pcrel = (i.flags[n] & Operand_PCrel) != 0; 303160519Sobrien 303277311Sobrien /* The PC relative address is computed relative 303377311Sobrien to the instruction boundary, so in case immediate 303477311Sobrien fields follows, we need to adjust the value. */ 303577311Sobrien if (pcrel && i.imm_operands) 303677311Sobrien { 303777311Sobrien int imm_size = 4; 303877311Sobrien register unsigned int n1; 303960519Sobrien 304077311Sobrien for (n1 = 0; n1 < i.operands; n1++) 304177311Sobrien if (i.types[n1] & Imm) 304277311Sobrien { 304377311Sobrien if (i.types[n1] & (Imm8 | Imm8S | Imm16 | Imm64)) 304477311Sobrien { 304577311Sobrien imm_size = 2; 304677311Sobrien if (i.types[n1] & (Imm8 | Imm8S)) 304777311Sobrien imm_size = 1; 304877311Sobrien if (i.types[n1] & Imm64) 304977311Sobrien imm_size = 8; 305077311Sobrien } 305177311Sobrien break; 305277311Sobrien } 305377311Sobrien /* We should find the immediate. */ 305477311Sobrien if (n1 == i.operands) 305577311Sobrien abort (); 305677311Sobrien i.op[n].disps->X_add_number -= imm_size; 305777311Sobrien } 305877311Sobrien 305977311Sobrien if (i.types[n] & Disp32S) 306077311Sobrien sign = 1; 306177311Sobrien 306277311Sobrien if (i.types[n] & (Disp16 | Disp64)) 306377311Sobrien { 306477311Sobrien size = 2; 306577311Sobrien if (i.types[n] & Disp64) 306677311Sobrien size = 8; 306777311Sobrien } 306877311Sobrien 306960519Sobrien p = frag_more (size); 307060519Sobrien fix_new_exp (frag_now, p - frag_now->fr_literal, size, 307177311Sobrien i.op[n].disps, pcrel, 307278840Sobrien reloc (size, pcrel, sign, i.reloc[n])); 307333965Sjdp } 307433965Sjdp } 307533965Sjdp } 307677311Sobrien } 307733965Sjdp 307877311Sobrien /* Output immediate. */ 307933965Sjdp if (i.imm_operands) 308033965Sjdp { 308133965Sjdp register unsigned int n; 308233965Sjdp 308333965Sjdp for (n = 0; n < i.operands; n++) 308433965Sjdp { 308560519Sobrien if (i.types[n] & Imm) 308633965Sjdp { 308760519Sobrien if (i.op[n].imms->X_op == O_constant) 308833965Sjdp { 308977311Sobrien int size; 309077311Sobrien offsetT val; 309160519Sobrien 309277311Sobrien size = 4; 309377311Sobrien if (i.types[n] & (Imm8 | Imm8S | Imm16 | Imm64)) 309433965Sjdp { 309560519Sobrien size = 2; 309660519Sobrien if (i.types[n] & (Imm8 | Imm8S)) 309777311Sobrien size = 1; 309877311Sobrien else if (i.types[n] & Imm64) 309977311Sobrien size = 8; 310033965Sjdp } 310177311Sobrien val = offset_in_range (i.op[n].imms->X_add_number, 310277311Sobrien size); 310360519Sobrien p = frag_more (size); 310477311Sobrien md_number_to_chars (p, val, size); 310533965Sjdp } 310633965Sjdp else 310777311Sobrien { 310877311Sobrien /* Not absolute_section. 310977311Sobrien Need a 32-bit fixup (don't support 8bit 311060519Sobrien non-absolute imms). Try to support other 311177311Sobrien sizes ... */ 311278840Sobrien RELOC_ENUM reloc_type; 311360519Sobrien int size = 4; 311477311Sobrien int sign = 0; 311533965Sjdp 311677311Sobrien if ((i.types[n] & (Imm32S)) 311777311Sobrien && i.suffix == QWORD_MNEM_SUFFIX) 311877311Sobrien sign = 1; 311977311Sobrien if (i.types[n] & (Imm8 | Imm8S | Imm16 | Imm64)) 312077311Sobrien { 312177311Sobrien size = 2; 312277311Sobrien if (i.types[n] & (Imm8 | Imm8S)) 312377311Sobrien size = 1; 312477311Sobrien if (i.types[n] & Imm64) 312577311Sobrien size = 8; 312677311Sobrien } 312760519Sobrien 312833965Sjdp p = frag_more (size); 312978840Sobrien reloc_type = reloc (size, 0, sign, i.reloc[n]); 313033965Sjdp#ifdef BFD_ASSEMBLER 313160519Sobrien if (reloc_type == BFD_RELOC_32 313233965Sjdp && GOT_symbol 313360519Sobrien && GOT_symbol == i.op[n].imms->X_add_symbol 313460519Sobrien && (i.op[n].imms->X_op == O_symbol 313560519Sobrien || (i.op[n].imms->X_op == O_add 313660519Sobrien && ((symbol_get_value_expression 313760519Sobrien (i.op[n].imms->X_op_symbol)->X_op) 313833965Sjdp == O_subtract)))) 313933965Sjdp { 314077311Sobrien /* We don't support dynamic linking on x86-64 yet. */ 314177311Sobrien if (flag_code == CODE_64BIT) 314277311Sobrien abort (); 314360519Sobrien reloc_type = BFD_RELOC_386_GOTPC; 314460519Sobrien i.op[n].imms->X_add_number += 3; 314533965Sjdp } 314633965Sjdp#endif 314733965Sjdp fix_new_exp (frag_now, p - frag_now->fr_literal, size, 314860519Sobrien i.op[n].imms, 0, reloc_type); 314933965Sjdp } 315033965Sjdp } 315133965Sjdp } 315277311Sobrien } 315333965Sjdp } 315433965Sjdp 315533965Sjdp#ifdef DEBUG386 315633965Sjdp if (flag_debug) 315733965Sjdp { 315833965Sjdp pi (line, &i); 315933965Sjdp } 316077311Sobrien#endif /* DEBUG386 */ 316133965Sjdp } 316233965Sjdp} 316333965Sjdp 316478840Sobrien#ifndef LEX_AT 316578840Sobrienstatic char *lex_got PARAMS ((RELOC_ENUM *, int *)); 316678840Sobrien 316778840Sobrien/* Parse operands of the form 316878840Sobrien <symbol>@GOTOFF+<nnn> 316978840Sobrien and similar .plt or .got references. 317078840Sobrien 317178840Sobrien If we find one, set up the correct relocation in RELOC and copy the 317278840Sobrien input string, minus the `@GOTOFF' into a malloc'd buffer for 317378840Sobrien parsing by the calling routine. Return this buffer, and if ADJUST 317478840Sobrien is non-null set it to the length of the string we removed from the 317578840Sobrien input line. Otherwise return NULL. */ 317678840Sobrienstatic char * 317778840Sobrienlex_got (reloc, adjust) 317878840Sobrien RELOC_ENUM *reloc; 317978840Sobrien int *adjust; 318078840Sobrien{ 318178840Sobrien static const char * const mode_name[NUM_FLAG_CODE] = { "32", "16", "64" }; 318278840Sobrien static const struct { 318378840Sobrien const char *str; 318478840Sobrien const RELOC_ENUM rel[NUM_FLAG_CODE]; 318578840Sobrien } gotrel[] = { 318678840Sobrien { "PLT", { BFD_RELOC_386_PLT32, 0, BFD_RELOC_X86_64_PLT32 } }, 318778840Sobrien { "GOTOFF", { BFD_RELOC_386_GOTOFF, 0, 0 } }, 318878840Sobrien { "GOTPCREL", { 0, 0, BFD_RELOC_X86_64_GOTPCREL } }, 318978840Sobrien { "GOT", { BFD_RELOC_386_GOT32, 0, BFD_RELOC_X86_64_GOT32 } } 319078840Sobrien }; 319178840Sobrien char *cp; 319278840Sobrien unsigned int j; 319378840Sobrien 319478840Sobrien for (cp = input_line_pointer; *cp != '@'; cp++) 319578840Sobrien if (is_end_of_line[(unsigned char) *cp]) 319678840Sobrien return NULL; 319778840Sobrien 319878840Sobrien for (j = 0; j < sizeof (gotrel) / sizeof (gotrel[0]); j++) 319978840Sobrien { 320078840Sobrien int len; 320178840Sobrien 320278840Sobrien len = strlen (gotrel[j].str); 320389867Sobrien if (strncasecmp (cp + 1, gotrel[j].str, len) == 0) 320478840Sobrien { 320578840Sobrien if (gotrel[j].rel[(unsigned int) flag_code] != 0) 320678840Sobrien { 320789867Sobrien int first, second; 320889867Sobrien char *tmpbuf, *past_reloc; 320978840Sobrien 321078840Sobrien *reloc = gotrel[j].rel[(unsigned int) flag_code]; 321189867Sobrien if (adjust) 321289867Sobrien *adjust = len; 321378840Sobrien 321478840Sobrien if (GOT_symbol == NULL) 321578840Sobrien GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME); 321678840Sobrien 321778840Sobrien /* Replace the relocation token with ' ', so that 321878840Sobrien errors like foo@GOTOFF1 will be detected. */ 321989867Sobrien 322089867Sobrien /* The length of the first part of our input line. */ 322178840Sobrien first = cp - input_line_pointer; 322289867Sobrien 322389867Sobrien /* The second part goes from after the reloc token until 322489867Sobrien (and including) an end_of_line char. Don't use strlen 322589867Sobrien here as the end_of_line char may not be a NUL. */ 322689867Sobrien past_reloc = cp + 1 + len; 322789867Sobrien for (cp = past_reloc; !is_end_of_line[(unsigned char) *cp++]; ) 322889867Sobrien ; 322989867Sobrien second = cp - past_reloc; 323089867Sobrien 323189867Sobrien /* Allocate and copy string. The trailing NUL shouldn't 323289867Sobrien be necessary, but be safe. */ 323389867Sobrien tmpbuf = xmalloc (first + second + 2); 323478840Sobrien memcpy (tmpbuf, input_line_pointer, first); 323578840Sobrien tmpbuf[first] = ' '; 323689867Sobrien memcpy (tmpbuf + first + 1, past_reloc, second); 323789867Sobrien tmpbuf[first + second + 1] = '\0'; 323878840Sobrien return tmpbuf; 323978840Sobrien } 324078840Sobrien 324178840Sobrien as_bad (_("@%s reloc is not supported in %s bit mode"), 324278840Sobrien gotrel[j].str, mode_name[(unsigned int) flag_code]); 324378840Sobrien return NULL; 324478840Sobrien } 324578840Sobrien } 324678840Sobrien 324778840Sobrien /* Might be a symbol version string. Don't as_bad here. */ 324878840Sobrien return NULL; 324978840Sobrien} 325078840Sobrien 325178840Sobrien/* x86_cons_fix_new is called via the expression parsing code when a 325278840Sobrien reloc is needed. We use this hook to get the correct .got reloc. */ 325378840Sobrienstatic RELOC_ENUM got_reloc = NO_RELOC; 325478840Sobrien 325578840Sobrienvoid 325678840Sobrienx86_cons_fix_new (frag, off, len, exp) 325778840Sobrien fragS *frag; 325878840Sobrien unsigned int off; 325978840Sobrien unsigned int len; 326078840Sobrien expressionS *exp; 326178840Sobrien{ 326278840Sobrien RELOC_ENUM r = reloc (len, 0, 0, got_reloc); 326378840Sobrien got_reloc = NO_RELOC; 326478840Sobrien fix_new_exp (frag, off, len, exp, 0, r); 326578840Sobrien} 326678840Sobrien 326778840Sobrienvoid 326878840Sobrienx86_cons (exp, size) 326978840Sobrien expressionS *exp; 327078840Sobrien int size; 327178840Sobrien{ 327278840Sobrien if (size == 4) 327378840Sobrien { 327478840Sobrien /* Handle @GOTOFF and the like in an expression. */ 327578840Sobrien char *save; 327678840Sobrien char *gotfree_input_line; 327778840Sobrien int adjust; 327878840Sobrien 327978840Sobrien save = input_line_pointer; 328078840Sobrien gotfree_input_line = lex_got (&got_reloc, &adjust); 328178840Sobrien if (gotfree_input_line) 328278840Sobrien input_line_pointer = gotfree_input_line; 328378840Sobrien 328478840Sobrien expression (exp); 328578840Sobrien 328678840Sobrien if (gotfree_input_line) 328778840Sobrien { 328878840Sobrien /* expression () has merrily parsed up to the end of line, 328978840Sobrien or a comma - in the wrong buffer. Transfer how far 329078840Sobrien input_line_pointer has moved to the right buffer. */ 329178840Sobrien input_line_pointer = (save 329278840Sobrien + (input_line_pointer - gotfree_input_line) 329378840Sobrien + adjust); 329478840Sobrien free (gotfree_input_line); 329578840Sobrien } 329678840Sobrien } 329778840Sobrien else 329878840Sobrien expression (exp); 329978840Sobrien} 330078840Sobrien#endif 330178840Sobrien 330260519Sobrienstatic int i386_immediate PARAMS ((char *)); 330360519Sobrien 330460519Sobrienstatic int 330560519Sobrieni386_immediate (imm_start) 330660519Sobrien char *imm_start; 330760519Sobrien{ 330860519Sobrien char *save_input_line_pointer; 330978840Sobrien#ifndef LEX_AT 331078840Sobrien char *gotfree_input_line; 331178840Sobrien#endif 331260519Sobrien segT exp_seg = 0; 331377311Sobrien expressionS *exp; 331460519Sobrien 331560519Sobrien if (i.imm_operands == MAX_IMMEDIATE_OPERANDS) 331660519Sobrien { 331760519Sobrien as_bad (_("only 1 or 2 immediate operands are allowed")); 331860519Sobrien return 0; 331960519Sobrien } 332060519Sobrien 332160519Sobrien exp = &im_expressions[i.imm_operands++]; 332260519Sobrien i.op[this_operand].imms = exp; 332360519Sobrien 332460519Sobrien if (is_space_char (*imm_start)) 332560519Sobrien ++imm_start; 332660519Sobrien 332760519Sobrien save_input_line_pointer = input_line_pointer; 332860519Sobrien input_line_pointer = imm_start; 332960519Sobrien 333060519Sobrien#ifndef LEX_AT 333178840Sobrien gotfree_input_line = lex_got (&i.reloc[this_operand], NULL); 333278840Sobrien if (gotfree_input_line) 333378840Sobrien input_line_pointer = gotfree_input_line; 333460519Sobrien#endif 333560519Sobrien 333660519Sobrien exp_seg = expression (exp); 333760519Sobrien 333860519Sobrien SKIP_WHITESPACE (); 333960519Sobrien if (*input_line_pointer) 334078840Sobrien as_bad (_("junk `%s' after expression"), input_line_pointer); 334160519Sobrien 334260519Sobrien input_line_pointer = save_input_line_pointer; 334378840Sobrien#ifndef LEX_AT 334478840Sobrien if (gotfree_input_line) 334578840Sobrien free (gotfree_input_line); 334678840Sobrien#endif 334760519Sobrien 334860519Sobrien if (exp->X_op == O_absent || exp->X_op == O_big) 334960519Sobrien { 335077311Sobrien /* Missing or bad expr becomes absolute 0. */ 335160519Sobrien as_bad (_("missing or invalid immediate expression `%s' taken as 0"), 335260519Sobrien imm_start); 335360519Sobrien exp->X_op = O_constant; 335460519Sobrien exp->X_add_number = 0; 335560519Sobrien exp->X_add_symbol = (symbolS *) 0; 335660519Sobrien exp->X_op_symbol = (symbolS *) 0; 335760519Sobrien } 335877311Sobrien else if (exp->X_op == O_constant) 335960519Sobrien { 336077311Sobrien /* Size it properly later. */ 336177311Sobrien i.types[this_operand] |= Imm64; 336277311Sobrien /* If BFD64, sign extend val. */ 336377311Sobrien if (!use_rela_relocations) 336477311Sobrien if ((exp->X_add_number & ~(((addressT) 2 << 31) - 1)) == 0) 336577311Sobrien exp->X_add_number = (exp->X_add_number ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31); 336660519Sobrien } 336760519Sobrien#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT)) 336877311Sobrien else if (1 336960519Sobrien#ifdef BFD_ASSEMBLER 337077311Sobrien && OUTPUT_FLAVOR == bfd_target_aout_flavour 337160519Sobrien#endif 337277311Sobrien && exp_seg != text_section 337360519Sobrien && exp_seg != data_section 337460519Sobrien && exp_seg != bss_section 337560519Sobrien && exp_seg != undefined_section 337660519Sobrien#ifdef BFD_ASSEMBLER 337760519Sobrien && !bfd_is_com_section (exp_seg) 337860519Sobrien#endif 337960519Sobrien ) 338060519Sobrien { 338160519Sobrien#ifdef BFD_ASSEMBLER 338260519Sobrien as_bad (_("unimplemented segment %s in operand"), exp_seg->name); 338360519Sobrien#else 338460519Sobrien as_bad (_("unimplemented segment type %d in operand"), exp_seg); 338560519Sobrien#endif 338660519Sobrien return 0; 338760519Sobrien } 338860519Sobrien#endif 338960519Sobrien else 339060519Sobrien { 339160519Sobrien /* This is an address. The size of the address will be 339260519Sobrien determined later, depending on destination register, 339377311Sobrien suffix, or the default for the section. */ 339477311Sobrien i.types[this_operand] |= Imm8 | Imm16 | Imm32 | Imm32S | Imm64; 339560519Sobrien } 339660519Sobrien 339760519Sobrien return 1; 339860519Sobrien} 339960519Sobrien 340078840Sobrienstatic char *i386_scale PARAMS ((char *)); 340160519Sobrien 340278840Sobrienstatic char * 340360519Sobrieni386_scale (scale) 340460519Sobrien char *scale; 340560519Sobrien{ 340678840Sobrien offsetT val; 340778840Sobrien char *save = input_line_pointer; 340860519Sobrien 340978840Sobrien input_line_pointer = scale; 341078840Sobrien val = get_absolute_expression (); 341178840Sobrien 341278840Sobrien switch (val) 341360519Sobrien { 341478840Sobrien case 0: 341578840Sobrien case 1: 341660519Sobrien i.log2_scale_factor = 0; 341760519Sobrien break; 341878840Sobrien case 2: 341960519Sobrien i.log2_scale_factor = 1; 342060519Sobrien break; 342178840Sobrien case 4: 342260519Sobrien i.log2_scale_factor = 2; 342360519Sobrien break; 342478840Sobrien case 8: 342560519Sobrien i.log2_scale_factor = 3; 342660519Sobrien break; 342760519Sobrien default: 342860519Sobrien as_bad (_("expecting scale factor of 1, 2, 4, or 8: got `%s'"), 342960519Sobrien scale); 343078840Sobrien input_line_pointer = save; 343178840Sobrien return NULL; 343260519Sobrien } 343360519Sobrien if (i.log2_scale_factor != 0 && ! i.index_reg) 343460519Sobrien { 343560519Sobrien as_warn (_("scale factor of %d without an index register"), 343660519Sobrien 1 << i.log2_scale_factor); 343760519Sobrien#if SCALE1_WHEN_NO_INDEX 343860519Sobrien i.log2_scale_factor = 0; 343960519Sobrien#endif 344060519Sobrien } 344178840Sobrien scale = input_line_pointer; 344278840Sobrien input_line_pointer = save; 344378840Sobrien return scale; 344460519Sobrien} 344560519Sobrien 344660519Sobrienstatic int i386_displacement PARAMS ((char *, char *)); 344760519Sobrien 344860519Sobrienstatic int 344960519Sobrieni386_displacement (disp_start, disp_end) 345060519Sobrien char *disp_start; 345160519Sobrien char *disp_end; 345260519Sobrien{ 345360519Sobrien register expressionS *exp; 345460519Sobrien segT exp_seg = 0; 345560519Sobrien char *save_input_line_pointer; 345678840Sobrien#ifndef LEX_AT 345778840Sobrien char *gotfree_input_line; 345878840Sobrien#endif 345960519Sobrien int bigdisp = Disp32; 346060519Sobrien 346191054Sobrien if (flag_code == CODE_64BIT) 346291054Sobrien { 346391054Sobrien if (!i.prefix[ADDR_PREFIX]) 346491054Sobrien bigdisp = Disp64; 346591054Sobrien } 346691054Sobrien else if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0)) 346760519Sobrien bigdisp = Disp16; 346860519Sobrien i.types[this_operand] |= bigdisp; 346960519Sobrien 347060519Sobrien exp = &disp_expressions[i.disp_operands]; 347160519Sobrien i.op[this_operand].disps = exp; 347260519Sobrien i.disp_operands++; 347360519Sobrien save_input_line_pointer = input_line_pointer; 347460519Sobrien input_line_pointer = disp_start; 347560519Sobrien END_STRING_AND_SAVE (disp_end); 347660519Sobrien 347760519Sobrien#ifndef GCC_ASM_O_HACK 347860519Sobrien#define GCC_ASM_O_HACK 0 347960519Sobrien#endif 348060519Sobrien#if GCC_ASM_O_HACK 348160519Sobrien END_STRING_AND_SAVE (disp_end + 1); 348260519Sobrien if ((i.types[this_operand] & BaseIndex) != 0 348360519Sobrien && displacement_string_end[-1] == '+') 348460519Sobrien { 348560519Sobrien /* This hack is to avoid a warning when using the "o" 348660519Sobrien constraint within gcc asm statements. 348760519Sobrien For instance: 348860519Sobrien 348960519Sobrien #define _set_tssldt_desc(n,addr,limit,type) \ 349060519Sobrien __asm__ __volatile__ ( \ 349160519Sobrien "movw %w2,%0\n\t" \ 349260519Sobrien "movw %w1,2+%0\n\t" \ 349360519Sobrien "rorl $16,%1\n\t" \ 349460519Sobrien "movb %b1,4+%0\n\t" \ 349560519Sobrien "movb %4,5+%0\n\t" \ 349660519Sobrien "movb $0,6+%0\n\t" \ 349760519Sobrien "movb %h1,7+%0\n\t" \ 349860519Sobrien "rorl $16,%1" \ 349960519Sobrien : "=o"(*(n)) : "q" (addr), "ri"(limit), "i"(type)) 350060519Sobrien 350160519Sobrien This works great except that the output assembler ends 350260519Sobrien up looking a bit weird if it turns out that there is 350360519Sobrien no offset. You end up producing code that looks like: 350460519Sobrien 350560519Sobrien #APP 350660519Sobrien movw $235,(%eax) 350760519Sobrien movw %dx,2+(%eax) 350860519Sobrien rorl $16,%edx 350960519Sobrien movb %dl,4+(%eax) 351060519Sobrien movb $137,5+(%eax) 351160519Sobrien movb $0,6+(%eax) 351260519Sobrien movb %dh,7+(%eax) 351360519Sobrien rorl $16,%edx 351460519Sobrien #NO_APP 351560519Sobrien 351677311Sobrien So here we provide the missing zero. */ 351760519Sobrien 351860519Sobrien *displacement_string_end = '0'; 351960519Sobrien } 352060519Sobrien#endif 352160519Sobrien#ifndef LEX_AT 352278840Sobrien gotfree_input_line = lex_got (&i.reloc[this_operand], NULL); 352378840Sobrien if (gotfree_input_line) 352478840Sobrien input_line_pointer = gotfree_input_line; 352578840Sobrien#endif 352660519Sobrien 352778840Sobrien exp_seg = expression (exp); 352860519Sobrien 352978840Sobrien SKIP_WHITESPACE (); 353078840Sobrien if (*input_line_pointer) 353178840Sobrien as_bad (_("junk `%s' after expression"), input_line_pointer); 353278840Sobrien#if GCC_ASM_O_HACK 353378840Sobrien RESTORE_END_STRING (disp_end + 1); 353460519Sobrien#endif 353578840Sobrien RESTORE_END_STRING (disp_end); 353678840Sobrien input_line_pointer = save_input_line_pointer; 353778840Sobrien#ifndef LEX_AT 353878840Sobrien if (gotfree_input_line) 353978840Sobrien free (gotfree_input_line); 354078840Sobrien#endif 354160519Sobrien 354260519Sobrien#ifdef BFD_ASSEMBLER 354360519Sobrien /* We do this to make sure that the section symbol is in 354460519Sobrien the symbol table. We will ultimately change the relocation 354577311Sobrien to be relative to the beginning of the section. */ 354678840Sobrien if (i.reloc[this_operand] == BFD_RELOC_386_GOTOFF 354778840Sobrien || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL) 354860519Sobrien { 354978840Sobrien if (exp->X_op != O_symbol) 355078840Sobrien { 355178840Sobrien as_bad (_("bad expression used with @%s"), 355278840Sobrien (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL 355378840Sobrien ? "GOTPCREL" 355478840Sobrien : "GOTOFF")); 355578840Sobrien return 0; 355678840Sobrien } 355778840Sobrien 355877311Sobrien if (S_IS_LOCAL (exp->X_add_symbol) 355960519Sobrien && S_GET_SEGMENT (exp->X_add_symbol) != undefined_section) 356060519Sobrien section_symbol (S_GET_SEGMENT (exp->X_add_symbol)); 356160519Sobrien exp->X_op = O_subtract; 356260519Sobrien exp->X_op_symbol = GOT_symbol; 356378840Sobrien if (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL) 356478840Sobrien i.reloc[this_operand] = BFD_RELOC_32_PCREL; 356577311Sobrien else 356678840Sobrien i.reloc[this_operand] = BFD_RELOC_32; 356760519Sobrien } 356860519Sobrien#endif 356960519Sobrien 357060519Sobrien if (exp->X_op == O_absent || exp->X_op == O_big) 357160519Sobrien { 357277311Sobrien /* Missing or bad expr becomes absolute 0. */ 357360519Sobrien as_bad (_("missing or invalid displacement expression `%s' taken as 0"), 357460519Sobrien disp_start); 357560519Sobrien exp->X_op = O_constant; 357660519Sobrien exp->X_add_number = 0; 357760519Sobrien exp->X_add_symbol = (symbolS *) 0; 357860519Sobrien exp->X_op_symbol = (symbolS *) 0; 357960519Sobrien } 358060519Sobrien 358160519Sobrien#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT)) 358277311Sobrien if (exp->X_op != O_constant 358360519Sobrien#ifdef BFD_ASSEMBLER 358477311Sobrien && OUTPUT_FLAVOR == bfd_target_aout_flavour 358560519Sobrien#endif 358677311Sobrien && exp_seg != text_section 358777311Sobrien && exp_seg != data_section 358877311Sobrien && exp_seg != bss_section 358977311Sobrien && exp_seg != undefined_section) 359060519Sobrien { 359160519Sobrien#ifdef BFD_ASSEMBLER 359260519Sobrien as_bad (_("unimplemented segment %s in operand"), exp_seg->name); 359360519Sobrien#else 359460519Sobrien as_bad (_("unimplemented segment type %d in operand"), exp_seg); 359560519Sobrien#endif 359660519Sobrien return 0; 359760519Sobrien } 359860519Sobrien#endif 359977311Sobrien else if (flag_code == CODE_64BIT) 360077311Sobrien i.types[this_operand] |= Disp32S | Disp32; 360160519Sobrien return 1; 360260519Sobrien} 360360519Sobrien 360477311Sobrienstatic int i386_index_check PARAMS ((const char *)); 360560519Sobrien 360677311Sobrien/* Make sure the memory operand we've been dealt is valid. 360777311Sobrien Return 1 on success, 0 on a failure. */ 360877311Sobrien 360960519Sobrienstatic int 361077311Sobrieni386_index_check (operand_string) 361177311Sobrien const char *operand_string; 361260519Sobrien{ 361377311Sobrien int ok; 361477311Sobrien#if INFER_ADDR_PREFIX 361577311Sobrien int fudged = 0; 361660519Sobrien 361777311Sobrien tryprefix: 361877311Sobrien#endif 361977311Sobrien ok = 1; 362077311Sobrien if (flag_code == CODE_64BIT) 362160519Sobrien { 362291054Sobrien if (i.prefix[ADDR_PREFIX] == 0) 362391054Sobrien { 362491054Sobrien /* 64bit checks. */ 362591054Sobrien if ((i.base_reg 362691054Sobrien && ((i.base_reg->reg_type & Reg64) == 0) 362791054Sobrien && (i.base_reg->reg_type != BaseIndex 362891054Sobrien || i.index_reg)) 362991054Sobrien || (i.index_reg 363091054Sobrien && ((i.index_reg->reg_type & (Reg64|BaseIndex)) 363191054Sobrien != (Reg64|BaseIndex)))) 363291054Sobrien ok = 0; 363391054Sobrien } 363491054Sobrien else 363591054Sobrien { 363691054Sobrien /* 32bit checks. */ 363791054Sobrien if ((i.base_reg 363891054Sobrien && (i.base_reg->reg_type & (Reg32 | RegRex)) != Reg32) 363991054Sobrien || (i.index_reg 364091054Sobrien && ((i.index_reg->reg_type & (Reg32|BaseIndex|RegRex)) 364191054Sobrien != (Reg32|BaseIndex)))) 364291054Sobrien ok = 0; 364391054Sobrien } 364460519Sobrien } 364560519Sobrien else 364660519Sobrien { 364777311Sobrien if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0)) 364860519Sobrien { 364977311Sobrien /* 16bit checks. */ 365077311Sobrien if ((i.base_reg 365177311Sobrien && ((i.base_reg->reg_type & (Reg16|BaseIndex|RegRex)) 365277311Sobrien != (Reg16|BaseIndex))) 365377311Sobrien || (i.index_reg 365477311Sobrien && (((i.index_reg->reg_type & (Reg16|BaseIndex)) 365577311Sobrien != (Reg16|BaseIndex)) 365677311Sobrien || ! (i.base_reg 365777311Sobrien && i.base_reg->reg_num < 6 365877311Sobrien && i.index_reg->reg_num >= 6 365977311Sobrien && i.log2_scale_factor == 0)))) 366077311Sobrien ok = 0; 366160519Sobrien } 366277311Sobrien else 366377311Sobrien { 366477311Sobrien /* 32bit checks. */ 366577311Sobrien if ((i.base_reg 366677311Sobrien && (i.base_reg->reg_type & (Reg32 | RegRex)) != Reg32) 366777311Sobrien || (i.index_reg 366877311Sobrien && ((i.index_reg->reg_type & (Reg32|BaseIndex|RegRex)) 366977311Sobrien != (Reg32|BaseIndex)))) 367077311Sobrien ok = 0; 367177311Sobrien } 367260519Sobrien } 367377311Sobrien if (!ok) 367460519Sobrien { 367560519Sobrien#if INFER_ADDR_PREFIX 367677311Sobrien if (flag_code != CODE_64BIT 367777311Sobrien && i.prefix[ADDR_PREFIX] == 0 && stackop_size != '\0') 367860519Sobrien { 367960519Sobrien i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE; 368060519Sobrien i.prefixes += 1; 368160519Sobrien /* Change the size of any displacement too. At most one of 368260519Sobrien Disp16 or Disp32 is set. 368360519Sobrien FIXME. There doesn't seem to be any real need for separate 368460519Sobrien Disp16 and Disp32 flags. The same goes for Imm16 and Imm32. 368577311Sobrien Removing them would probably clean up the code quite a lot. */ 368660519Sobrien if (i.types[this_operand] & (Disp16|Disp32)) 368760519Sobrien i.types[this_operand] ^= (Disp16|Disp32); 368860519Sobrien fudged = 1; 368960519Sobrien goto tryprefix; 369060519Sobrien } 369160519Sobrien if (fudged) 369260519Sobrien as_bad (_("`%s' is not a valid base/index expression"), 369360519Sobrien operand_string); 369460519Sobrien else 369560519Sobrien#endif 369660519Sobrien as_bad (_("`%s' is not a valid %s bit base/index expression"), 369760519Sobrien operand_string, 369877311Sobrien flag_code_names[flag_code]); 369960519Sobrien return 0; 370060519Sobrien } 370160519Sobrien return 1; 370260519Sobrien} 370360519Sobrien 370433965Sjdp/* Parse OPERAND_STRING into the i386_insn structure I. Returns non-zero 370577311Sobrien on error. */ 370633965Sjdp 370733965Sjdpstatic int 370833965Sjdpi386_operand (operand_string) 370933965Sjdp char *operand_string; 371033965Sjdp{ 371160519Sobrien const reg_entry *r; 371260519Sobrien char *end_op; 371360519Sobrien char *op_string = operand_string; 371433965Sjdp 371560519Sobrien if (is_space_char (*op_string)) 371660519Sobrien ++op_string; 371733965Sjdp 371833965Sjdp /* We check for an absolute prefix (differentiating, 371977311Sobrien for example, 'jmp pc_relative_label' from 'jmp *absolute_label'. */ 372033965Sjdp if (*op_string == ABSOLUTE_PREFIX) 372133965Sjdp { 372260519Sobrien ++op_string; 372360519Sobrien if (is_space_char (*op_string)) 372460519Sobrien ++op_string; 372533965Sjdp i.types[this_operand] |= JumpAbsolute; 372633965Sjdp } 372733965Sjdp 372877311Sobrien /* Check if operand is a register. */ 372960519Sobrien if ((*op_string == REGISTER_PREFIX || allow_naked_reg) 373060519Sobrien && (r = parse_register (op_string, &end_op)) != NULL) 373133965Sjdp { 373260519Sobrien /* Check for a segment override by searching for ':' after a 373360519Sobrien segment register. */ 373460519Sobrien op_string = end_op; 373560519Sobrien if (is_space_char (*op_string)) 373660519Sobrien ++op_string; 373760519Sobrien if (*op_string == ':' && (r->reg_type & (SReg2 | SReg3))) 373833965Sjdp { 373933965Sjdp switch (r->reg_num) 374033965Sjdp { 374133965Sjdp case 0: 374260519Sobrien i.seg[i.mem_operands] = &es; 374333965Sjdp break; 374433965Sjdp case 1: 374560519Sobrien i.seg[i.mem_operands] = &cs; 374633965Sjdp break; 374733965Sjdp case 2: 374860519Sobrien i.seg[i.mem_operands] = &ss; 374933965Sjdp break; 375033965Sjdp case 3: 375160519Sobrien i.seg[i.mem_operands] = &ds; 375233965Sjdp break; 375333965Sjdp case 4: 375460519Sobrien i.seg[i.mem_operands] = &fs; 375533965Sjdp break; 375633965Sjdp case 5: 375760519Sobrien i.seg[i.mem_operands] = &gs; 375833965Sjdp break; 375933965Sjdp } 376060519Sobrien 376160519Sobrien /* Skip the ':' and whitespace. */ 376260519Sobrien ++op_string; 376360519Sobrien if (is_space_char (*op_string)) 376460519Sobrien ++op_string; 376560519Sobrien 376660519Sobrien if (!is_digit_char (*op_string) 376760519Sobrien && !is_identifier_char (*op_string) 376860519Sobrien && *op_string != '(' 376960519Sobrien && *op_string != ABSOLUTE_PREFIX) 377033965Sjdp { 377160519Sobrien as_bad (_("bad memory operand `%s'"), op_string); 377233965Sjdp return 0; 377333965Sjdp } 377477311Sobrien /* Handle case of %es:*foo. */ 377533965Sjdp if (*op_string == ABSOLUTE_PREFIX) 377633965Sjdp { 377760519Sobrien ++op_string; 377860519Sobrien if (is_space_char (*op_string)) 377960519Sobrien ++op_string; 378033965Sjdp i.types[this_operand] |= JumpAbsolute; 378133965Sjdp } 378233965Sjdp goto do_memory_reference; 378333965Sjdp } 378460519Sobrien if (*op_string) 378560519Sobrien { 378660519Sobrien as_bad (_("junk `%s' after register"), op_string); 378760519Sobrien return 0; 378860519Sobrien } 378960519Sobrien i.types[this_operand] |= r->reg_type & ~BaseIndex; 379060519Sobrien i.op[this_operand].regs = r; 379133965Sjdp i.reg_operands++; 379233965Sjdp } 379360519Sobrien else if (*op_string == REGISTER_PREFIX) 379460519Sobrien { 379560519Sobrien as_bad (_("bad register name `%s'"), op_string); 379660519Sobrien return 0; 379760519Sobrien } 379833965Sjdp else if (*op_string == IMMEDIATE_PREFIX) 379977311Sobrien { 380060519Sobrien ++op_string; 380160519Sobrien if (i.types[this_operand] & JumpAbsolute) 380233965Sjdp { 380360519Sobrien as_bad (_("immediate operand illegal with absolute jump")); 380433965Sjdp return 0; 380533965Sjdp } 380660519Sobrien if (!i386_immediate (op_string)) 380760519Sobrien return 0; 380833965Sjdp } 380960519Sobrien else if (is_digit_char (*op_string) 381060519Sobrien || is_identifier_char (*op_string) 381177311Sobrien || *op_string == '(') 381233965Sjdp { 381377311Sobrien /* This is a memory reference of some sort. */ 381460519Sobrien char *base_string; 381533965Sjdp 381677311Sobrien /* Start and end of displacement string expression (if found). */ 381760519Sobrien char *displacement_string_start; 381860519Sobrien char *displacement_string_end; 381960519Sobrien 382033965Sjdp do_memory_reference: 382160519Sobrien if ((i.mem_operands == 1 382260519Sobrien && (current_templates->start->opcode_modifier & IsString) == 0) 382360519Sobrien || i.mem_operands == 2) 382433965Sjdp { 382560519Sobrien as_bad (_("too many memory references for `%s'"), 382660519Sobrien current_templates->start->name); 382733965Sjdp return 0; 382833965Sjdp } 382933965Sjdp 383033965Sjdp /* Check for base index form. We detect the base index form by 383133965Sjdp looking for an ')' at the end of the operand, searching 383233965Sjdp for the '(' matching it, and finding a REGISTER_PREFIX or ',' 383360519Sobrien after the '('. */ 383460519Sobrien base_string = op_string + strlen (op_string); 383560519Sobrien 383660519Sobrien --base_string; 383760519Sobrien if (is_space_char (*base_string)) 383860519Sobrien --base_string; 383960519Sobrien 384077311Sobrien /* If we only have a displacement, set-up for it to be parsed later. */ 384160519Sobrien displacement_string_start = op_string; 384260519Sobrien displacement_string_end = base_string + 1; 384360519Sobrien 384433965Sjdp if (*base_string == ')') 384533965Sjdp { 384660519Sobrien char *temp_string; 384733965Sjdp unsigned int parens_balanced = 1; 384833965Sjdp /* We've already checked that the number of left & right ()'s are 384977311Sobrien equal, so this loop will not be infinite. */ 385033965Sjdp do 385133965Sjdp { 385233965Sjdp base_string--; 385333965Sjdp if (*base_string == ')') 385433965Sjdp parens_balanced++; 385533965Sjdp if (*base_string == '(') 385633965Sjdp parens_balanced--; 385733965Sjdp } 385833965Sjdp while (parens_balanced); 385933965Sjdp 386060519Sobrien temp_string = base_string; 386133965Sjdp 386260519Sobrien /* Skip past '(' and whitespace. */ 386360519Sobrien ++base_string; 386460519Sobrien if (is_space_char (*base_string)) 386560519Sobrien ++base_string; 386633965Sjdp 386760519Sobrien if (*base_string == ',' 386860519Sobrien || ((*base_string == REGISTER_PREFIX || allow_naked_reg) 386960519Sobrien && (i.base_reg = parse_register (base_string, &end_op)) != NULL)) 387033965Sjdp { 387160519Sobrien displacement_string_end = temp_string; 387233965Sjdp 387360519Sobrien i.types[this_operand] |= BaseIndex; 387460519Sobrien 387560519Sobrien if (i.base_reg) 387633965Sjdp { 387760519Sobrien base_string = end_op; 387860519Sobrien if (is_space_char (*base_string)) 387960519Sobrien ++base_string; 388033965Sjdp } 388160519Sobrien 388260519Sobrien /* There may be an index reg or scale factor here. */ 388360519Sobrien if (*base_string == ',') 388433965Sjdp { 388560519Sobrien ++base_string; 388660519Sobrien if (is_space_char (*base_string)) 388760519Sobrien ++base_string; 388833965Sjdp 388960519Sobrien if ((*base_string == REGISTER_PREFIX || allow_naked_reg) 389060519Sobrien && (i.index_reg = parse_register (base_string, &end_op)) != NULL) 389160519Sobrien { 389260519Sobrien base_string = end_op; 389360519Sobrien if (is_space_char (*base_string)) 389460519Sobrien ++base_string; 389560519Sobrien if (*base_string == ',') 389660519Sobrien { 389760519Sobrien ++base_string; 389860519Sobrien if (is_space_char (*base_string)) 389960519Sobrien ++base_string; 390060519Sobrien } 390177311Sobrien else if (*base_string != ')') 390260519Sobrien { 390360519Sobrien as_bad (_("expecting `,' or `)' after index register in `%s'"), 390460519Sobrien operand_string); 390560519Sobrien return 0; 390660519Sobrien } 390760519Sobrien } 390860519Sobrien else if (*base_string == REGISTER_PREFIX) 390960519Sobrien { 391060519Sobrien as_bad (_("bad register name `%s'"), base_string); 391160519Sobrien return 0; 391260519Sobrien } 391333965Sjdp 391477311Sobrien /* Check for scale factor. */ 391578840Sobrien if (*base_string != ')') 391660519Sobrien { 391778840Sobrien char *end_scale = i386_scale (base_string); 391878840Sobrien 391978840Sobrien if (!end_scale) 392060519Sobrien return 0; 392133965Sjdp 392278840Sobrien base_string = end_scale; 392360519Sobrien if (is_space_char (*base_string)) 392460519Sobrien ++base_string; 392560519Sobrien if (*base_string != ')') 392660519Sobrien { 392760519Sobrien as_bad (_("expecting `)' after scale factor in `%s'"), 392860519Sobrien operand_string); 392960519Sobrien return 0; 393060519Sobrien } 393160519Sobrien } 393260519Sobrien else if (!i.index_reg) 393360519Sobrien { 393460519Sobrien as_bad (_("expecting index register or scale factor after `,'; got '%c'"), 393560519Sobrien *base_string); 393660519Sobrien return 0; 393760519Sobrien } 393833965Sjdp } 393960519Sobrien else if (*base_string != ')') 394033965Sjdp { 394160519Sobrien as_bad (_("expecting `,' or `)' after base register in `%s'"), 394260519Sobrien operand_string); 394333965Sjdp return 0; 394433965Sjdp } 394533965Sjdp } 394660519Sobrien else if (*base_string == REGISTER_PREFIX) 394733965Sjdp { 394860519Sobrien as_bad (_("bad register name `%s'"), base_string); 394960519Sobrien return 0; 395033965Sjdp } 395133965Sjdp } 395233965Sjdp 395360519Sobrien /* If there's an expression beginning the operand, parse it, 395460519Sobrien assuming displacement_string_start and 395560519Sobrien displacement_string_end are meaningful. */ 395660519Sobrien if (displacement_string_start != displacement_string_end) 395733965Sjdp { 395860519Sobrien if (!i386_displacement (displacement_string_start, 395960519Sobrien displacement_string_end)) 396060519Sobrien return 0; 396133965Sjdp } 396233965Sjdp 396360519Sobrien /* Special case for (%dx) while doing input/output op. */ 396460519Sobrien if (i.base_reg 396560519Sobrien && i.base_reg->reg_type == (Reg16 | InOutPortReg) 396660519Sobrien && i.index_reg == 0 396760519Sobrien && i.log2_scale_factor == 0 396860519Sobrien && i.seg[i.mem_operands] == 0 396960519Sobrien && (i.types[this_operand] & Disp) == 0) 397033965Sjdp { 397160519Sobrien i.types[this_operand] = InOutPortReg; 397233965Sjdp return 1; 397333965Sjdp } 397460519Sobrien 397560519Sobrien if (i386_index_check (operand_string) == 0) 397660519Sobrien return 0; 397760519Sobrien i.mem_operands++; 397833965Sjdp } 397933965Sjdp else 398077311Sobrien { 398177311Sobrien /* It's not a memory operand; argh! */ 398260519Sobrien as_bad (_("invalid char %s beginning operand %d `%s'"), 398360519Sobrien output_invalid (*op_string), 398460519Sobrien this_operand + 1, 398533965Sjdp op_string); 398633965Sjdp return 0; 398733965Sjdp } 398877311Sobrien return 1; /* Normal return. */ 398933965Sjdp} 399033965Sjdp 399161847Sobrien/* md_estimate_size_before_relax() 399261847Sobrien 399361847Sobrien Called just before relax() for rs_machine_dependent frags. The x86 399461847Sobrien assembler uses these frags to handle variable size jump 399561847Sobrien instructions. 399661847Sobrien 399761847Sobrien Any symbol that is now undefined will not become defined. 399861847Sobrien Return the correct fr_subtype in the frag. 399961847Sobrien Return the initial "guess for variable size of frag" to caller. 400061847Sobrien The guess is actually the growth beyond the fixed part. Whatever 400161847Sobrien we do to grow the fixed or variable part contributes to our 400261847Sobrien returned value. */ 400361847Sobrien 400433965Sjdpint 400533965Sjdpmd_estimate_size_before_relax (fragP, segment) 400633965Sjdp register fragS *fragP; 400733965Sjdp register segT segment; 400833965Sjdp{ 400960519Sobrien /* We've already got fragP->fr_subtype right; all we have to do is 401061847Sobrien check for un-relaxable symbols. On an ELF system, we can't relax 401161847Sobrien an externally visible symbol, because it may be overridden by a 401261847Sobrien shared library. */ 401361847Sobrien if (S_GET_SEGMENT (fragP->fr_symbol) != segment 401477311Sobrien#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 401561847Sobrien || S_IS_EXTERNAL (fragP->fr_symbol) 401661847Sobrien || S_IS_WEAK (fragP->fr_symbol) 401761847Sobrien#endif 401861847Sobrien ) 401933965Sjdp { 402061847Sobrien /* Symbol is undefined in this segment, or we need to keep a 402161847Sobrien reloc so that weak symbols can be overridden. */ 402261847Sobrien int size = (fragP->fr_subtype & CODE16) ? 2 : 4; 402378840Sobrien RELOC_ENUM reloc_type; 402461847Sobrien unsigned char *opcode; 402561847Sobrien int old_fr_fix; 402660519Sobrien 402761847Sobrien if (fragP->fr_var != NO_RELOC) 402861847Sobrien reloc_type = fragP->fr_var; 402961847Sobrien else if (size == 2) 403060519Sobrien reloc_type = BFD_RELOC_16_PCREL; 403160519Sobrien else 403260519Sobrien reloc_type = BFD_RELOC_32_PCREL; 403360519Sobrien 403461847Sobrien old_fr_fix = fragP->fr_fix; 403561847Sobrien opcode = (unsigned char *) fragP->fr_opcode; 403661847Sobrien 403778840Sobrien switch (TYPE_FROM_RELAX_STATE (fragP->fr_subtype)) 403833965Sjdp { 403978840Sobrien case UNCOND_JUMP: 404078840Sobrien /* Make jmp (0xeb) a (d)word displacement jump. */ 404177311Sobrien opcode[0] = 0xe9; 404260519Sobrien fragP->fr_fix += size; 404360519Sobrien fix_new (fragP, old_fr_fix, size, 404460519Sobrien fragP->fr_symbol, 404533965Sjdp fragP->fr_offset, 1, 404660519Sobrien reloc_type); 404733965Sjdp break; 404833965Sjdp 404978840Sobrien case COND_JUMP86: 405078840Sobrien if (no_cond_jump_promotion) 405178840Sobrien goto relax_guess; 405278840Sobrien 405378840Sobrien if (size == 2) 405478840Sobrien { 405578840Sobrien /* Negate the condition, and branch past an 405678840Sobrien unconditional jump. */ 405778840Sobrien opcode[0] ^= 1; 405878840Sobrien opcode[1] = 3; 405978840Sobrien /* Insert an unconditional jump. */ 406078840Sobrien opcode[2] = 0xe9; 406178840Sobrien /* We added two extra opcode bytes, and have a two byte 406278840Sobrien offset. */ 406378840Sobrien fragP->fr_fix += 2 + 2; 406478840Sobrien fix_new (fragP, old_fr_fix + 2, 2, 406578840Sobrien fragP->fr_symbol, 406678840Sobrien fragP->fr_offset, 1, 406778840Sobrien reloc_type); 406878840Sobrien break; 406978840Sobrien } 407078840Sobrien /* Fall through. */ 407178840Sobrien 407278840Sobrien case COND_JUMP: 407378840Sobrien if (no_cond_jump_promotion) 407478840Sobrien goto relax_guess; 407578840Sobrien 407660519Sobrien /* This changes the byte-displacement jump 0x7N 407778840Sobrien to the (d)word-displacement jump 0x0f,0x8N. */ 407833965Sjdp opcode[1] = opcode[0] + 0x10; 407960519Sobrien opcode[0] = TWO_BYTE_OPCODE_ESCAPE; 408077311Sobrien /* We've added an opcode byte. */ 408177311Sobrien fragP->fr_fix += 1 + size; 408260519Sobrien fix_new (fragP, old_fr_fix + 1, size, 408333965Sjdp fragP->fr_symbol, 408460519Sobrien fragP->fr_offset, 1, 408560519Sobrien reloc_type); 408633965Sjdp break; 408778840Sobrien 408878840Sobrien default: 408978840Sobrien BAD_CASE (fragP->fr_subtype); 409078840Sobrien break; 409133965Sjdp } 409233965Sjdp frag_wane (fragP); 409361847Sobrien return fragP->fr_fix - old_fr_fix; 409433965Sjdp } 409578840Sobrien 409678840Sobrien relax_guess: 409778840Sobrien /* Guess size depending on current relax state. Initially the relax 409878840Sobrien state will correspond to a short jump and we return 1, because 409978840Sobrien the variable part of the frag (the branch offset) is one byte 410078840Sobrien long. However, we can relax a section more than once and in that 410178840Sobrien case we must either set fr_subtype back to the unrelaxed state, 410278840Sobrien or return the value for the appropriate branch. */ 410378840Sobrien return md_relax_table[fragP->fr_subtype].rlx_length; 410461847Sobrien} 410561847Sobrien 410677311Sobrien/* Called after relax() is finished. 410777311Sobrien 410877311Sobrien In: Address of frag. 410977311Sobrien fr_type == rs_machine_dependent. 411077311Sobrien fr_subtype is what the address relaxed to. 411177311Sobrien 411277311Sobrien Out: Any fixSs and constants are set up. 411377311Sobrien Caller will turn frag into a ".space 0". */ 411477311Sobrien 411533965Sjdp#ifndef BFD_ASSEMBLER 411633965Sjdpvoid 411733965Sjdpmd_convert_frag (headers, sec, fragP) 411860519Sobrien object_headers *headers ATTRIBUTE_UNUSED; 411960519Sobrien segT sec ATTRIBUTE_UNUSED; 412033965Sjdp register fragS *fragP; 412133965Sjdp#else 412233965Sjdpvoid 412333965Sjdpmd_convert_frag (abfd, sec, fragP) 412460519Sobrien bfd *abfd ATTRIBUTE_UNUSED; 412560519Sobrien segT sec ATTRIBUTE_UNUSED; 412633965Sjdp register fragS *fragP; 412733965Sjdp#endif 412833965Sjdp{ 412933965Sjdp register unsigned char *opcode; 413033965Sjdp unsigned char *where_to_put_displacement = NULL; 413177311Sobrien offsetT target_address; 413277311Sobrien offsetT opcode_address; 413333965Sjdp unsigned int extension = 0; 413477311Sobrien offsetT displacement_from_opcode_start; 413533965Sjdp 413633965Sjdp opcode = (unsigned char *) fragP->fr_opcode; 413733965Sjdp 413877311Sobrien /* Address we want to reach in file space. */ 413933965Sjdp target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset; 414033965Sjdp 414177311Sobrien /* Address opcode resides at in file space. */ 414233965Sjdp opcode_address = fragP->fr_address + fragP->fr_fix; 414333965Sjdp 414477311Sobrien /* Displacement from opcode start to fill into instruction. */ 414533965Sjdp displacement_from_opcode_start = target_address - opcode_address; 414633965Sjdp 414778840Sobrien if ((fragP->fr_subtype & BIG) == 0) 414833965Sjdp { 414977311Sobrien /* Don't have to change opcode. */ 415077311Sobrien extension = 1; /* 1 opcode + 1 displacement */ 415133965Sjdp where_to_put_displacement = &opcode[1]; 415278840Sobrien } 415378840Sobrien else 415478840Sobrien { 415578840Sobrien if (no_cond_jump_promotion 415678840Sobrien && TYPE_FROM_RELAX_STATE (fragP->fr_subtype) != UNCOND_JUMP) 415778840Sobrien as_warn_where (fragP->fr_file, fragP->fr_line, _("long jump required")); 415833965Sjdp 415978840Sobrien switch (fragP->fr_subtype) 416078840Sobrien { 416178840Sobrien case ENCODE_RELAX_STATE (UNCOND_JUMP, BIG): 416278840Sobrien extension = 4; /* 1 opcode + 4 displacement */ 416378840Sobrien opcode[0] = 0xe9; 416478840Sobrien where_to_put_displacement = &opcode[1]; 416578840Sobrien break; 416633965Sjdp 416778840Sobrien case ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16): 416878840Sobrien extension = 2; /* 1 opcode + 2 displacement */ 416978840Sobrien opcode[0] = 0xe9; 417078840Sobrien where_to_put_displacement = &opcode[1]; 417178840Sobrien break; 417233965Sjdp 417378840Sobrien case ENCODE_RELAX_STATE (COND_JUMP, BIG): 417478840Sobrien case ENCODE_RELAX_STATE (COND_JUMP86, BIG): 417578840Sobrien extension = 5; /* 2 opcode + 4 displacement */ 417678840Sobrien opcode[1] = opcode[0] + 0x10; 417778840Sobrien opcode[0] = TWO_BYTE_OPCODE_ESCAPE; 417878840Sobrien where_to_put_displacement = &opcode[2]; 417978840Sobrien break; 418033965Sjdp 418178840Sobrien case ENCODE_RELAX_STATE (COND_JUMP, BIG16): 418278840Sobrien extension = 3; /* 2 opcode + 2 displacement */ 418378840Sobrien opcode[1] = opcode[0] + 0x10; 418478840Sobrien opcode[0] = TWO_BYTE_OPCODE_ESCAPE; 418578840Sobrien where_to_put_displacement = &opcode[2]; 418678840Sobrien break; 418733965Sjdp 418878840Sobrien case ENCODE_RELAX_STATE (COND_JUMP86, BIG16): 418978840Sobrien extension = 4; 419078840Sobrien opcode[0] ^= 1; 419178840Sobrien opcode[1] = 3; 419278840Sobrien opcode[2] = 0xe9; 419378840Sobrien where_to_put_displacement = &opcode[3]; 419478840Sobrien break; 419578840Sobrien 419678840Sobrien default: 419778840Sobrien BAD_CASE (fragP->fr_subtype); 419878840Sobrien break; 419978840Sobrien } 420033965Sjdp } 420178840Sobrien 420277311Sobrien /* Now put displacement after opcode. */ 420333965Sjdp md_number_to_chars ((char *) where_to_put_displacement, 420433965Sjdp (valueT) (displacement_from_opcode_start - extension), 420578840Sobrien DISP_SIZE_FROM_RELAX_STATE (fragP->fr_subtype)); 420633965Sjdp fragP->fr_fix += extension; 420733965Sjdp} 420833965Sjdp 420977311Sobrien/* Size of byte displacement jmp. */ 421077311Sobrienint md_short_jump_size = 2; 421133965Sjdp 421277311Sobrien/* Size of dword displacement jmp. */ 421377311Sobrienint md_long_jump_size = 5; 421433965Sjdp 421577311Sobrien/* Size of relocation record. */ 421677311Sobrienconst int md_reloc_size = 8; 421777311Sobrien 421833965Sjdpvoid 421933965Sjdpmd_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) 422033965Sjdp char *ptr; 422133965Sjdp addressT from_addr, to_addr; 422260519Sobrien fragS *frag ATTRIBUTE_UNUSED; 422360519Sobrien symbolS *to_symbol ATTRIBUTE_UNUSED; 422433965Sjdp{ 422577311Sobrien offsetT offset; 422633965Sjdp 422733965Sjdp offset = to_addr - (from_addr + 2); 422877311Sobrien /* Opcode for byte-disp jump. */ 422977311Sobrien md_number_to_chars (ptr, (valueT) 0xeb, 1); 423033965Sjdp md_number_to_chars (ptr + 1, (valueT) offset, 1); 423133965Sjdp} 423233965Sjdp 423333965Sjdpvoid 423433965Sjdpmd_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) 423533965Sjdp char *ptr; 423633965Sjdp addressT from_addr, to_addr; 423777311Sobrien fragS *frag ATTRIBUTE_UNUSED; 423877311Sobrien symbolS *to_symbol ATTRIBUTE_UNUSED; 423933965Sjdp{ 424077311Sobrien offsetT offset; 424133965Sjdp 424277311Sobrien offset = to_addr - (from_addr + 5); 424377311Sobrien md_number_to_chars (ptr, (valueT) 0xe9, 1); 424477311Sobrien md_number_to_chars (ptr + 1, (valueT) offset, 4); 424533965Sjdp} 424633965Sjdp 424733965Sjdp/* Apply a fixup (fixS) to segment data, once it has been determined 424833965Sjdp by our caller that we have all the info we need to fix it up. 424933965Sjdp 425033965Sjdp On the 386, immediates, displacements, and data pointers are all in 425133965Sjdp the same (little-endian) format, so we don't need to care about which 425233965Sjdp we are handling. */ 425333965Sjdp 425489867Sobrienvoid 425589867Sobrienmd_apply_fix3 (fixP, valP, seg) 425677311Sobrien /* The fix we're to put in. */ 425777311Sobrien fixS *fixP; 425877311Sobrien /* Pointer to the value of the bits. */ 425989867Sobrien valueT * valP; 426077311Sobrien /* Segment fix is from. */ 426177311Sobrien segT seg ATTRIBUTE_UNUSED; 426233965Sjdp{ 426389867Sobrien char *p = fixP->fx_where + fixP->fx_frag->fr_literal; 426489867Sobrien valueT value = * valP; 426533965Sjdp 426633965Sjdp#if defined (BFD_ASSEMBLER) && !defined (TE_Mach) 426760519Sobrien if (fixP->fx_pcrel) 426833965Sjdp { 426960519Sobrien switch (fixP->fx_r_type) 427060519Sobrien { 427160519Sobrien default: 427260519Sobrien break; 427360519Sobrien 427460519Sobrien case BFD_RELOC_32: 427560519Sobrien fixP->fx_r_type = BFD_RELOC_32_PCREL; 427660519Sobrien break; 427760519Sobrien case BFD_RELOC_16: 427860519Sobrien fixP->fx_r_type = BFD_RELOC_16_PCREL; 427960519Sobrien break; 428060519Sobrien case BFD_RELOC_8: 428160519Sobrien fixP->fx_r_type = BFD_RELOC_8_PCREL; 428260519Sobrien break; 428360519Sobrien } 428460519Sobrien } 428560519Sobrien 428660519Sobrien /* This is a hack. There should be a better way to handle this. 428760519Sobrien This covers for the fact that bfd_install_relocation will 428860519Sobrien subtract the current location (for partial_inplace, PC relative 428960519Sobrien relocations); see more below. */ 429060519Sobrien if ((fixP->fx_r_type == BFD_RELOC_32_PCREL 429160519Sobrien || fixP->fx_r_type == BFD_RELOC_16_PCREL 429260519Sobrien || fixP->fx_r_type == BFD_RELOC_8_PCREL) 429377311Sobrien && fixP->fx_addsy && !use_rela_relocations) 429460519Sobrien { 429533965Sjdp#ifndef OBJ_AOUT 429638891Sjdp if (OUTPUT_FLAVOR == bfd_target_elf_flavour 429760519Sobrien#ifdef TE_PE 429860519Sobrien || OUTPUT_FLAVOR == bfd_target_coff_flavour 429960519Sobrien#endif 430060519Sobrien ) 430133965Sjdp value += fixP->fx_where + fixP->fx_frag->fr_address; 430233965Sjdp#endif 430333965Sjdp#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 430460519Sobrien if (OUTPUT_FLAVOR == bfd_target_elf_flavour) 430533965Sjdp { 430660519Sobrien segT fseg = S_GET_SEGMENT (fixP->fx_addsy); 430760519Sobrien 430860519Sobrien if ((fseg == seg 430960519Sobrien || (symbol_section_p (fixP->fx_addsy) 431060519Sobrien && fseg != absolute_section)) 431160519Sobrien && ! S_IS_EXTERNAL (fixP->fx_addsy) 431260519Sobrien && ! S_IS_WEAK (fixP->fx_addsy) 431360519Sobrien && S_IS_DEFINED (fixP->fx_addsy) 431460519Sobrien && ! S_IS_COMMON (fixP->fx_addsy)) 431560519Sobrien { 431660519Sobrien /* Yes, we add the values in twice. This is because 431760519Sobrien bfd_perform_relocation subtracts them out again. I think 431860519Sobrien bfd_perform_relocation is broken, but I don't dare change 431960519Sobrien it. FIXME. */ 432060519Sobrien value += fixP->fx_where + fixP->fx_frag->fr_address; 432160519Sobrien } 432233965Sjdp } 432333965Sjdp#endif 432438891Sjdp#if defined (OBJ_COFF) && defined (TE_PE) 432538891Sjdp /* For some reason, the PE format does not store a section 432660519Sobrien address offset for a PC relative symbol. */ 432738891Sjdp if (S_GET_SEGMENT (fixP->fx_addsy) != seg) 432838891Sjdp value += md_pcrel_from (fixP); 432938891Sjdp#endif 433033965Sjdp } 433133965Sjdp 433233965Sjdp /* Fix a few things - the dynamic linker expects certain values here, 433377311Sobrien and we must not dissappoint it. */ 433433965Sjdp#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 433533965Sjdp if (OUTPUT_FLAVOR == bfd_target_elf_flavour 433633965Sjdp && fixP->fx_addsy) 433777311Sobrien switch (fixP->fx_r_type) 433877311Sobrien { 433977311Sobrien case BFD_RELOC_386_PLT32: 434077311Sobrien case BFD_RELOC_X86_64_PLT32: 434177311Sobrien /* Make the jump instruction point to the address of the operand. At 434277311Sobrien runtime we merely add the offset to the actual PLT entry. */ 434377311Sobrien value = -4; 434477311Sobrien break; 434577311Sobrien case BFD_RELOC_386_GOTPC: 434677311Sobrien 434777311Sobrien/* This is tough to explain. We end up with this one if we have 434833965Sjdp * operands that look like "_GLOBAL_OFFSET_TABLE_+[.-.L284]". The goal 434933965Sjdp * here is to obtain the absolute address of the GOT, and it is strongly 435033965Sjdp * preferable from a performance point of view to avoid using a runtime 435160519Sobrien * relocation for this. The actual sequence of instructions often look 435233965Sjdp * something like: 435360519Sobrien * 435460519Sobrien * call .L66 435533965Sjdp * .L66: 435660519Sobrien * popl %ebx 435760519Sobrien * addl $_GLOBAL_OFFSET_TABLE_+[.-.L66],%ebx 435860519Sobrien * 435960519Sobrien * The call and pop essentially return the absolute address of 436033965Sjdp * the label .L66 and store it in %ebx. The linker itself will 436133965Sjdp * ultimately change the first operand of the addl so that %ebx points to 436233965Sjdp * the GOT, but to keep things simple, the .o file must have this operand 436333965Sjdp * set so that it generates not the absolute address of .L66, but the 436433965Sjdp * absolute address of itself. This allows the linker itself simply 436533965Sjdp * treat a GOTPC relocation as asking for a pcrel offset to the GOT to be 436633965Sjdp * added in, and the addend of the relocation is stored in the operand 436733965Sjdp * field for the instruction itself. 436860519Sobrien * 436960519Sobrien * Our job here is to fix the operand so that it would add the correct 437033965Sjdp * offset so that %ebx would point to itself. The thing that is tricky is 437133965Sjdp * that .-.L66 will point to the beginning of the instruction, so we need 437233965Sjdp * to further modify the operand so that it will point to itself. 437333965Sjdp * There are other cases where you have something like: 437460519Sobrien * 437560519Sobrien * .long $_GLOBAL_OFFSET_TABLE_+[.-.L66] 437660519Sobrien * 437733965Sjdp * and here no correction would be required. Internally in the assembler 437860519Sobrien * we treat operands of this form as not being pcrel since the '.' is 437933965Sjdp * explicitly mentioned, and I wonder whether it would simplify matters 438033965Sjdp * to do it this way. Who knows. In earlier versions of the PIC patches, 438133965Sjdp * the pcrel_adjust field was used to store the correction, but since the 438277311Sobrien * expression is not pcrel, I felt it would be confusing to do it this 438377311Sobrien * way. */ 438433965Sjdp 438577311Sobrien value -= 1; 438677311Sobrien break; 438777311Sobrien case BFD_RELOC_386_GOT32: 438877311Sobrien case BFD_RELOC_X86_64_GOT32: 438977311Sobrien value = 0; /* Fully resolved at runtime. No addend. */ 439077311Sobrien break; 439177311Sobrien case BFD_RELOC_386_GOTOFF: 439277311Sobrien case BFD_RELOC_X86_64_GOTPCREL: 439377311Sobrien break; 439460519Sobrien 439577311Sobrien case BFD_RELOC_VTABLE_INHERIT: 439677311Sobrien case BFD_RELOC_VTABLE_ENTRY: 439777311Sobrien fixP->fx_done = 0; 439889867Sobrien return; 439977311Sobrien 440077311Sobrien default: 440177311Sobrien break; 440277311Sobrien } 440377311Sobrien#endif /* defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) */ 440489867Sobrien * valP = value; 440577311Sobrien#endif /* defined (BFD_ASSEMBLER) && !defined (TE_Mach) */ 440677311Sobrien 440777311Sobrien /* Are we finished with this relocation now? */ 440889867Sobrien if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) 440977311Sobrien fixP->fx_done = 1; 441089867Sobrien#ifdef BFD_ASSEMBLER 441177311Sobrien else if (use_rela_relocations) 441277311Sobrien { 441377311Sobrien fixP->fx_no_overflow = 1; 441477311Sobrien value = 0; 441577311Sobrien } 441689867Sobrien#endif 441777311Sobrien md_number_to_chars (p, value, fixP->fx_size); 441833965Sjdp} 441933965Sjdp 442033965Sjdp#define MAX_LITTLENUMS 6 442133965Sjdp 442277311Sobrien/* Turn the string pointed to by litP into a floating point constant 442377311Sobrien of type TYPE, and emit the appropriate bytes. The number of 442477311Sobrien LITTLENUMS emitted is stored in *SIZEP. An error message is 442577311Sobrien returned, or NULL on OK. */ 442677311Sobrien 442733965Sjdpchar * 442833965Sjdpmd_atof (type, litP, sizeP) 442960519Sobrien int type; 443033965Sjdp char *litP; 443133965Sjdp int *sizeP; 443233965Sjdp{ 443333965Sjdp int prec; 443433965Sjdp LITTLENUM_TYPE words[MAX_LITTLENUMS]; 443533965Sjdp LITTLENUM_TYPE *wordP; 443633965Sjdp char *t; 443733965Sjdp 443833965Sjdp switch (type) 443933965Sjdp { 444033965Sjdp case 'f': 444133965Sjdp case 'F': 444233965Sjdp prec = 2; 444333965Sjdp break; 444433965Sjdp 444533965Sjdp case 'd': 444633965Sjdp case 'D': 444733965Sjdp prec = 4; 444833965Sjdp break; 444933965Sjdp 445033965Sjdp case 'x': 445133965Sjdp case 'X': 445233965Sjdp prec = 5; 445333965Sjdp break; 445433965Sjdp 445533965Sjdp default: 445633965Sjdp *sizeP = 0; 445760519Sobrien return _("Bad call to md_atof ()"); 445833965Sjdp } 445933965Sjdp t = atof_ieee (input_line_pointer, type, words); 446033965Sjdp if (t) 446133965Sjdp input_line_pointer = t; 446233965Sjdp 446333965Sjdp *sizeP = prec * sizeof (LITTLENUM_TYPE); 446433965Sjdp /* This loops outputs the LITTLENUMs in REVERSE order; in accord with 446533965Sjdp the bigendian 386. */ 446633965Sjdp for (wordP = words + prec - 1; prec--;) 446733965Sjdp { 446833965Sjdp md_number_to_chars (litP, (valueT) (*wordP--), sizeof (LITTLENUM_TYPE)); 446933965Sjdp litP += sizeof (LITTLENUM_TYPE); 447033965Sjdp } 447133965Sjdp return 0; 447233965Sjdp} 447333965Sjdp 447433965Sjdpchar output_invalid_buf[8]; 447533965Sjdp 447633965Sjdpstatic char * 447733965Sjdpoutput_invalid (c) 447860519Sobrien int c; 447933965Sjdp{ 448089867Sobrien if (ISPRINT (c)) 448133965Sjdp sprintf (output_invalid_buf, "'%c'", c); 448233965Sjdp else 448333965Sjdp sprintf (output_invalid_buf, "(0x%x)", (unsigned) c); 448433965Sjdp return output_invalid_buf; 448533965Sjdp} 448633965Sjdp 448760519Sobrien/* REG_STRING starts *before* REGISTER_PREFIX. */ 448860519Sobrien 448960519Sobrienstatic const reg_entry * 449060519Sobrienparse_register (reg_string, end_op) 449133965Sjdp char *reg_string; 449260519Sobrien char **end_op; 449333965Sjdp{ 449460519Sobrien char *s = reg_string; 449560519Sobrien char *p; 449660519Sobrien char reg_name_given[MAX_REG_NAME_SIZE + 1]; 449760519Sobrien const reg_entry *r; 449833965Sjdp 449960519Sobrien /* Skip possible REGISTER_PREFIX and possible whitespace. */ 450060519Sobrien if (*s == REGISTER_PREFIX) 450160519Sobrien ++s; 450260519Sobrien 450360519Sobrien if (is_space_char (*s)) 450460519Sobrien ++s; 450560519Sobrien 450660519Sobrien p = reg_name_given; 450760519Sobrien while ((*p++ = register_chars[(unsigned char) *s]) != '\0') 450833965Sjdp { 450933965Sjdp if (p >= reg_name_given + MAX_REG_NAME_SIZE) 451060519Sobrien return (const reg_entry *) NULL; 451160519Sobrien s++; 451233965Sjdp } 451360519Sobrien 451477311Sobrien /* For naked regs, make sure that we are not dealing with an identifier. 451577311Sobrien This prevents confusing an identifier like `eax_var' with register 451677311Sobrien `eax'. */ 451777311Sobrien if (allow_naked_reg && identifier_chars[(unsigned char) *s]) 451877311Sobrien return (const reg_entry *) NULL; 451977311Sobrien 452060519Sobrien *end_op = s; 452160519Sobrien 452260519Sobrien r = (const reg_entry *) hash_find (reg_hash, reg_name_given); 452360519Sobrien 452460519Sobrien /* Handle floating point regs, allowing spaces in the (i) part. */ 452577311Sobrien if (r == i386_regtab /* %st is first entry of table */) 452660519Sobrien { 452760519Sobrien if (is_space_char (*s)) 452860519Sobrien ++s; 452960519Sobrien if (*s == '(') 453060519Sobrien { 453160519Sobrien ++s; 453260519Sobrien if (is_space_char (*s)) 453360519Sobrien ++s; 453460519Sobrien if (*s >= '0' && *s <= '7') 453560519Sobrien { 453660519Sobrien r = &i386_float_regtab[*s - '0']; 453760519Sobrien ++s; 453860519Sobrien if (is_space_char (*s)) 453960519Sobrien ++s; 454060519Sobrien if (*s == ')') 454160519Sobrien { 454260519Sobrien *end_op = s + 1; 454360519Sobrien return r; 454460519Sobrien } 454560519Sobrien } 454677311Sobrien /* We have "%st(" then garbage. */ 454760519Sobrien return (const reg_entry *) NULL; 454860519Sobrien } 454960519Sobrien } 455060519Sobrien 455185824Sobrien if (r != NULL 455285824Sobrien && r->reg_flags & (RegRex64|RegRex) 455385824Sobrien && flag_code != CODE_64BIT) 455485824Sobrien { 455585824Sobrien return (const reg_entry *) NULL; 455685824Sobrien } 455785824Sobrien 455860519Sobrien return r; 455933965Sjdp} 456033965Sjdp 456160519Sobrien#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 456277311Sobrienconst char *md_shortopts = "kVQ:sq"; 456333965Sjdp#else 456477311Sobrienconst char *md_shortopts = "q"; 456533965Sjdp#endif 456677311Sobrien 456733965Sjdpstruct option md_longopts[] = { 456877311Sobrien#define OPTION_32 (OPTION_MD_BASE + 0) 456977311Sobrien {"32", no_argument, NULL, OPTION_32}, 457077311Sobrien#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 457177311Sobrien#define OPTION_64 (OPTION_MD_BASE + 1) 457277311Sobrien {"64", no_argument, NULL, OPTION_64}, 457377311Sobrien#endif 457433965Sjdp {NULL, no_argument, NULL, 0} 457533965Sjdp}; 457660519Sobriensize_t md_longopts_size = sizeof (md_longopts); 457733965Sjdp 457833965Sjdpint 457933965Sjdpmd_parse_option (c, arg) 458033965Sjdp int c; 458160519Sobrien char *arg ATTRIBUTE_UNUSED; 458233965Sjdp{ 458333965Sjdp switch (c) 458433965Sjdp { 458577311Sobrien case 'q': 458677311Sobrien quiet_warnings = 1; 458733965Sjdp break; 458833965Sjdp 458933965Sjdp#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 459077311Sobrien /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section 459177311Sobrien should be emitted or not. FIXME: Not implemented. */ 459277311Sobrien case 'Q': 459333965Sjdp break; 459433965Sjdp 459533965Sjdp /* -V: SVR4 argument to print version ID. */ 459633965Sjdp case 'V': 459733965Sjdp print_version_id (); 459833965Sjdp break; 459933965Sjdp 460077311Sobrien /* -k: Ignore for FreeBSD compatibility. */ 460177311Sobrien case 'k': 460233965Sjdp break; 460360519Sobrien 460460519Sobrien case 's': 460560519Sobrien /* -s: On i386 Solaris, this tells the native assembler to use 460660519Sobrien .stab instead of .stab.excl. We always use .stab anyhow. */ 460760519Sobrien break; 460860519Sobrien 460977311Sobrien case OPTION_64: 461077311Sobrien { 461177311Sobrien const char **list, **l; 461277311Sobrien 461377311Sobrien list = bfd_target_list (); 461477311Sobrien for (l = list; *l != NULL; l++) 461577311Sobrien if (strcmp (*l, "elf64-x86-64") == 0) 461677311Sobrien { 461777311Sobrien default_arch = "x86_64"; 461877311Sobrien break; 461977311Sobrien } 462077311Sobrien if (*l == NULL) 462177311Sobrien as_fatal (_("No compiled in support for x86_64")); 462277311Sobrien free (list); 462377311Sobrien } 462460519Sobrien break; 462533965Sjdp#endif 462633965Sjdp 462777311Sobrien case OPTION_32: 462877311Sobrien default_arch = "i386"; 462977311Sobrien break; 463077311Sobrien 463133965Sjdp default: 463233965Sjdp return 0; 463333965Sjdp } 463433965Sjdp return 1; 463533965Sjdp} 463633965Sjdp 463733965Sjdpvoid 463833965Sjdpmd_show_usage (stream) 463933965Sjdp FILE *stream; 464033965Sjdp{ 464160519Sobrien#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) 464260519Sobrien fprintf (stream, _("\ 464377311Sobrien -Q ignored\n\ 464477311Sobrien -V print assembler version number\n\ 464577311Sobrien -k ignored\n\ 464677311Sobrien -q quieten some warnings\n\ 464777311Sobrien -s ignored\n")); 464877311Sobrien#else 464977311Sobrien fprintf (stream, _("\ 465077311Sobrien -q quieten some warnings\n")); 465160519Sobrien#endif 465233965Sjdp} 465333965Sjdp 465433965Sjdp#ifdef BFD_ASSEMBLER 465577311Sobrien#if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \ 465677311Sobrien || defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) 465733965Sjdp 465833965Sjdp/* Pick the target format to use. */ 465933965Sjdp 466077311Sobrienconst char * 466133965Sjdpi386_target_format () 466233965Sjdp{ 466377311Sobrien if (!strcmp (default_arch, "x86_64")) 466477311Sobrien set_code_flag (CODE_64BIT); 466577311Sobrien else if (!strcmp (default_arch, "i386")) 466677311Sobrien set_code_flag (CODE_32BIT); 466777311Sobrien else 466877311Sobrien as_fatal (_("Unknown architecture")); 466933965Sjdp switch (OUTPUT_FLAVOR) 467033965Sjdp { 467160519Sobrien#ifdef OBJ_MAYBE_AOUT 467260519Sobrien case bfd_target_aout_flavour: 467377311Sobrien return AOUT_TARGET_FORMAT; 467460519Sobrien#endif 467560519Sobrien#ifdef OBJ_MAYBE_COFF 467633965Sjdp case bfd_target_coff_flavour: 467733965Sjdp return "coff-i386"; 467860519Sobrien#endif 467977311Sobrien#if defined (OBJ_MAYBE_ELF) || defined (OBJ_ELF) 468033965Sjdp case bfd_target_elf_flavour: 468177311Sobrien { 468277311Sobrien if (flag_code == CODE_64BIT) 468377311Sobrien use_rela_relocations = 1; 468477311Sobrien return flag_code == CODE_64BIT ? "elf64-x86-64" : "elf32-i386"; 468577311Sobrien } 468660519Sobrien#endif 468733965Sjdp default: 468833965Sjdp abort (); 468933965Sjdp return NULL; 469033965Sjdp } 469133965Sjdp} 469233965Sjdp 469377311Sobrien#endif /* OBJ_MAYBE_ more than one */ 469489867Sobrien 469589867Sobrien#if (defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) 469689867Sobrienvoid i386_elf_emit_arch_note () 469789867Sobrien{ 469889867Sobrien if (OUTPUT_FLAVOR == bfd_target_elf_flavour 469989867Sobrien && cpu_arch_name != NULL) 470089867Sobrien { 470189867Sobrien char *p; 470289867Sobrien asection *seg = now_seg; 470389867Sobrien subsegT subseg = now_subseg; 470489867Sobrien Elf_Internal_Note i_note; 470589867Sobrien Elf_External_Note e_note; 470689867Sobrien asection *note_secp; 470789867Sobrien int len; 470889867Sobrien 470989867Sobrien /* Create the .note section. */ 471089867Sobrien note_secp = subseg_new (".note", 0); 471189867Sobrien bfd_set_section_flags (stdoutput, 471289867Sobrien note_secp, 471389867Sobrien SEC_HAS_CONTENTS | SEC_READONLY); 471489867Sobrien 471589867Sobrien /* Process the arch string. */ 471689867Sobrien len = strlen (cpu_arch_name); 471789867Sobrien 471889867Sobrien i_note.namesz = len + 1; 471989867Sobrien i_note.descsz = 0; 472089867Sobrien i_note.type = NT_ARCH; 472189867Sobrien p = frag_more (sizeof (e_note.namesz)); 472289867Sobrien md_number_to_chars (p, (valueT) i_note.namesz, sizeof (e_note.namesz)); 472389867Sobrien p = frag_more (sizeof (e_note.descsz)); 472489867Sobrien md_number_to_chars (p, (valueT) i_note.descsz, sizeof (e_note.descsz)); 472589867Sobrien p = frag_more (sizeof (e_note.type)); 472689867Sobrien md_number_to_chars (p, (valueT) i_note.type, sizeof (e_note.type)); 472789867Sobrien p = frag_more (len + 1); 472889867Sobrien strcpy (p, cpu_arch_name); 472989867Sobrien 473089867Sobrien frag_align (2, 0, 0); 473189867Sobrien 473289867Sobrien subseg_set (seg, subseg); 473389867Sobrien } 473489867Sobrien} 473589867Sobrien#endif 473677311Sobrien#endif /* BFD_ASSEMBLER */ 473733965Sjdp 473833965SjdpsymbolS * 473933965Sjdpmd_undefined_symbol (name) 474033965Sjdp char *name; 474133965Sjdp{ 474260519Sobrien if (name[0] == GLOBAL_OFFSET_TABLE_NAME[0] 474360519Sobrien && name[1] == GLOBAL_OFFSET_TABLE_NAME[1] 474460519Sobrien && name[2] == GLOBAL_OFFSET_TABLE_NAME[2] 474560519Sobrien && strcmp (name, GLOBAL_OFFSET_TABLE_NAME) == 0) 474660519Sobrien { 474760519Sobrien if (!GOT_symbol) 474860519Sobrien { 474960519Sobrien if (symbol_find (name)) 475060519Sobrien as_bad (_("GOT already in symbol table")); 475160519Sobrien GOT_symbol = symbol_new (name, undefined_section, 475260519Sobrien (valueT) 0, &zero_address_frag); 475360519Sobrien }; 475460519Sobrien return GOT_symbol; 475560519Sobrien } 475633965Sjdp return 0; 475733965Sjdp} 475833965Sjdp 475933965Sjdp/* Round up a section size to the appropriate boundary. */ 476077311Sobrien 476133965SjdpvalueT 476233965Sjdpmd_section_align (segment, size) 476360519Sobrien segT segment ATTRIBUTE_UNUSED; 476433965Sjdp valueT size; 476533965Sjdp{ 476633965Sjdp#ifdef BFD_ASSEMBLER 476760519Sobrien#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT)) 476860519Sobrien if (OUTPUT_FLAVOR == bfd_target_aout_flavour) 476960519Sobrien { 477060519Sobrien /* For a.out, force the section size to be aligned. If we don't do 477160519Sobrien this, BFD will align it for us, but it will not write out the 477260519Sobrien final bytes of the section. This may be a bug in BFD, but it is 477360519Sobrien easier to fix it here since that is how the other a.out targets 477460519Sobrien work. */ 477560519Sobrien int align; 477633965Sjdp 477760519Sobrien align = bfd_get_section_alignment (stdoutput, segment); 477860519Sobrien size = ((size + (1 << align) - 1) & ((valueT) -1 << align)); 477960519Sobrien } 478033965Sjdp#endif 478133965Sjdp#endif 478233965Sjdp 478333965Sjdp return size; 478433965Sjdp} 478533965Sjdp 478660519Sobrien/* On the i386, PC-relative offsets are relative to the start of the 478760519Sobrien next instruction. That is, the address of the offset, plus its 478860519Sobrien size, since the offset is always the last part of the insn. */ 478960519Sobrien 479033965Sjdplong 479133965Sjdpmd_pcrel_from (fixP) 479233965Sjdp fixS *fixP; 479333965Sjdp{ 479433965Sjdp return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address; 479533965Sjdp} 479633965Sjdp 479733965Sjdp#ifndef I386COFF 479833965Sjdp 479933965Sjdpstatic void 480033965Sjdps_bss (ignore) 480160519Sobrien int ignore ATTRIBUTE_UNUSED; 480233965Sjdp{ 480333965Sjdp register int temp; 480433965Sjdp 480533965Sjdp temp = get_absolute_expression (); 480633965Sjdp subseg_set (bss_section, (subsegT) temp); 480733965Sjdp demand_empty_rest_of_line (); 480833965Sjdp} 480933965Sjdp 481033965Sjdp#endif 481133965Sjdp 481233965Sjdp#ifdef BFD_ASSEMBLER 481333965Sjdp 481433965Sjdpvoid 481533965Sjdpi386_validate_fix (fixp) 481633965Sjdp fixS *fixp; 481733965Sjdp{ 481833965Sjdp if (fixp->fx_subsy && fixp->fx_subsy == GOT_symbol) 481933965Sjdp { 482077311Sobrien /* GOTOFF relocation are nonsense in 64bit mode. */ 482177311Sobrien if (fixp->fx_r_type == BFD_RELOC_32_PCREL) 482277311Sobrien { 482377311Sobrien if (flag_code != CODE_64BIT) 482477311Sobrien abort (); 482577311Sobrien fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL; 482677311Sobrien } 482777311Sobrien else 482877311Sobrien { 482977311Sobrien if (flag_code == CODE_64BIT) 483077311Sobrien abort (); 483177311Sobrien fixp->fx_r_type = BFD_RELOC_386_GOTOFF; 483277311Sobrien } 483333965Sjdp fixp->fx_subsy = 0; 483433965Sjdp } 483533965Sjdp} 483633965Sjdp 483733965Sjdparelent * 483833965Sjdptc_gen_reloc (section, fixp) 483960519Sobrien asection *section ATTRIBUTE_UNUSED; 484033965Sjdp fixS *fixp; 484133965Sjdp{ 484233965Sjdp arelent *rel; 484333965Sjdp bfd_reloc_code_real_type code; 484433965Sjdp 484560519Sobrien switch (fixp->fx_r_type) 484633965Sjdp { 484777311Sobrien case BFD_RELOC_X86_64_PLT32: 484877311Sobrien case BFD_RELOC_X86_64_GOT32: 484977311Sobrien case BFD_RELOC_X86_64_GOTPCREL: 485033965Sjdp case BFD_RELOC_386_PLT32: 485133965Sjdp case BFD_RELOC_386_GOT32: 485233965Sjdp case BFD_RELOC_386_GOTOFF: 485333965Sjdp case BFD_RELOC_386_GOTPC: 485477311Sobrien case BFD_RELOC_X86_64_32S: 485538891Sjdp case BFD_RELOC_RVA: 485660519Sobrien case BFD_RELOC_VTABLE_ENTRY: 485760519Sobrien case BFD_RELOC_VTABLE_INHERIT: 485833965Sjdp code = fixp->fx_r_type; 485933965Sjdp break; 486033965Sjdp default: 486160519Sobrien if (fixp->fx_pcrel) 486233965Sjdp { 486360519Sobrien switch (fixp->fx_size) 486460519Sobrien { 486560519Sobrien default: 486689867Sobrien as_bad_where (fixp->fx_file, fixp->fx_line, 486789867Sobrien _("can not do %d byte pc-relative relocation"), 486889867Sobrien fixp->fx_size); 486960519Sobrien code = BFD_RELOC_32_PCREL; 487060519Sobrien break; 487160519Sobrien case 1: code = BFD_RELOC_8_PCREL; break; 487260519Sobrien case 2: code = BFD_RELOC_16_PCREL; break; 487360519Sobrien case 4: code = BFD_RELOC_32_PCREL; break; 487460519Sobrien } 487533965Sjdp } 487660519Sobrien else 487760519Sobrien { 487860519Sobrien switch (fixp->fx_size) 487960519Sobrien { 488060519Sobrien default: 488189867Sobrien as_bad_where (fixp->fx_file, fixp->fx_line, 488289867Sobrien _("can not do %d byte relocation"), 488389867Sobrien fixp->fx_size); 488460519Sobrien code = BFD_RELOC_32; 488560519Sobrien break; 488660519Sobrien case 1: code = BFD_RELOC_8; break; 488760519Sobrien case 2: code = BFD_RELOC_16; break; 488860519Sobrien case 4: code = BFD_RELOC_32; break; 488977311Sobrien case 8: code = BFD_RELOC_64; break; 489060519Sobrien } 489160519Sobrien } 489260519Sobrien break; 489333965Sjdp } 489433965Sjdp 489533965Sjdp if (code == BFD_RELOC_32 489633965Sjdp && GOT_symbol 489733965Sjdp && fixp->fx_addsy == GOT_symbol) 489877311Sobrien { 489977311Sobrien /* We don't support GOTPC on 64bit targets. */ 490077311Sobrien if (flag_code == CODE_64BIT) 490177311Sobrien abort (); 490277311Sobrien code = BFD_RELOC_386_GOTPC; 490377311Sobrien } 490433965Sjdp 490533965Sjdp rel = (arelent *) xmalloc (sizeof (arelent)); 490660519Sobrien rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); 490760519Sobrien *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 490860519Sobrien 490933965Sjdp rel->address = fixp->fx_frag->fr_address + fixp->fx_where; 491077311Sobrien if (!use_rela_relocations) 491177311Sobrien { 491277311Sobrien /* HACK: Since i386 ELF uses Rel instead of Rela, encode the 491377311Sobrien vtable entry to be used in the relocation's section offset. */ 491477311Sobrien if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) 491577311Sobrien rel->address = fixp->fx_offset; 491660519Sobrien 491777311Sobrien if (fixp->fx_pcrel) 491877311Sobrien rel->addend = fixp->fx_addnumber; 491977311Sobrien else 492077311Sobrien rel->addend = 0; 492177311Sobrien } 492277311Sobrien /* Use the rela in 64bit mode. */ 492333965Sjdp else 492477311Sobrien { 492577311Sobrien rel->addend = fixp->fx_offset; 492677311Sobrien if (fixp->fx_pcrel) 492777311Sobrien rel->addend -= fixp->fx_size; 492877311Sobrien } 492933965Sjdp 493033965Sjdp rel->howto = bfd_reloc_type_lookup (stdoutput, code); 493133965Sjdp if (rel->howto == NULL) 493233965Sjdp { 493333965Sjdp as_bad_where (fixp->fx_file, fixp->fx_line, 493460519Sobrien _("cannot represent relocation type %s"), 493533965Sjdp bfd_get_reloc_code_name (code)); 493633965Sjdp /* Set howto to a garbage value so that we can keep going. */ 493733965Sjdp rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32); 493833965Sjdp assert (rel->howto != NULL); 493933965Sjdp } 494033965Sjdp 494133965Sjdp return rel; 494233965Sjdp} 494333965Sjdp 494477311Sobrien#else /* ! BFD_ASSEMBLER */ 494533965Sjdp 494633965Sjdp#if (defined(OBJ_AOUT) | defined(OBJ_BOUT)) 494733965Sjdpvoid 494833965Sjdptc_aout_fix_to_chars (where, fixP, segment_address_in_file) 494933965Sjdp char *where; 495033965Sjdp fixS *fixP; 495133965Sjdp relax_addressT segment_address_in_file; 495233965Sjdp{ 495377311Sobrien /* In: length of relocation (or of address) in chars: 1, 2 or 4. 495477311Sobrien Out: GNU LD relocation length code: 0, 1, or 2. */ 495533965Sjdp 495677311Sobrien static const unsigned char nbytes_r_length[] = { 42, 0, 1, 42, 2 }; 495733965Sjdp long r_symbolnum; 495833965Sjdp 495933965Sjdp know (fixP->fx_addsy != NULL); 496033965Sjdp 496133965Sjdp md_number_to_chars (where, 496233965Sjdp (valueT) (fixP->fx_frag->fr_address 496333965Sjdp + fixP->fx_where - segment_address_in_file), 496433965Sjdp 4); 496533965Sjdp 496633965Sjdp r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy) 496733965Sjdp ? S_GET_TYPE (fixP->fx_addsy) 496833965Sjdp : fixP->fx_addsy->sy_number); 496933965Sjdp 497033965Sjdp where[6] = (r_symbolnum >> 16) & 0x0ff; 497133965Sjdp where[5] = (r_symbolnum >> 8) & 0x0ff; 497233965Sjdp where[4] = r_symbolnum & 0x0ff; 497333965Sjdp where[7] = ((((!S_IS_DEFINED (fixP->fx_addsy)) << 3) & 0x08) 497433965Sjdp | ((nbytes_r_length[fixP->fx_size] << 1) & 0x06) 497533965Sjdp | (((fixP->fx_pcrel << 0) & 0x01) & 0x0f)); 497633965Sjdp} 497733965Sjdp 497877311Sobrien#endif /* OBJ_AOUT or OBJ_BOUT. */ 497933965Sjdp 498033965Sjdp#if defined (I386COFF) 498133965Sjdp 498233965Sjdpshort 498333965Sjdptc_coff_fix2rtype (fixP) 498433965Sjdp fixS *fixP; 498533965Sjdp{ 498633965Sjdp if (fixP->fx_r_type == R_IMAGEBASE) 498733965Sjdp return R_IMAGEBASE; 498833965Sjdp 498933965Sjdp return (fixP->fx_pcrel ? 499033965Sjdp (fixP->fx_size == 1 ? R_PCRBYTE : 499133965Sjdp fixP->fx_size == 2 ? R_PCRWORD : 499233965Sjdp R_PCRLONG) : 499333965Sjdp (fixP->fx_size == 1 ? R_RELBYTE : 499433965Sjdp fixP->fx_size == 2 ? R_RELWORD : 499533965Sjdp R_DIR32)); 499633965Sjdp} 499733965Sjdp 499833965Sjdpint 499933965Sjdptc_coff_sizemachdep (frag) 500033965Sjdp fragS *frag; 500133965Sjdp{ 500233965Sjdp if (frag->fr_next) 500333965Sjdp return (frag->fr_next->fr_address - frag->fr_address); 500433965Sjdp else 500533965Sjdp return 0; 500633965Sjdp} 500733965Sjdp 500877311Sobrien#endif /* I386COFF */ 500933965Sjdp 501077311Sobrien#endif /* ! BFD_ASSEMBLER */ 501133965Sjdp 501277311Sobrien/* Parse operands using Intel syntax. This implements a recursive descent 501377311Sobrien parser based on the BNF grammar published in Appendix B of the MASM 6.1 501477311Sobrien Programmer's Guide. 501577311Sobrien 501677311Sobrien FIXME: We do not recognize the full operand grammar defined in the MASM 501777311Sobrien documentation. In particular, all the structure/union and 501877311Sobrien high-level macro operands are missing. 501977311Sobrien 502077311Sobrien Uppercase words are terminals, lower case words are non-terminals. 502177311Sobrien Objects surrounded by double brackets '[[' ']]' are optional. Vertical 502277311Sobrien bars '|' denote choices. Most grammar productions are implemented in 502377311Sobrien functions called 'intel_<production>'. 502477311Sobrien 502577311Sobrien Initial production is 'expr'. 502677311Sobrien 502777311Sobrien addOp + | - 502877311Sobrien 502977311Sobrien alpha [a-zA-Z] 503077311Sobrien 503177311Sobrien byteRegister AL | AH | BL | BH | CL | CH | DL | DH 503277311Sobrien 503377311Sobrien constant digits [[ radixOverride ]] 503477311Sobrien 503577311Sobrien dataType BYTE | WORD | DWORD | QWORD | XWORD 503677311Sobrien 503777311Sobrien digits decdigit 503877311Sobrien | digits decdigit 503977311Sobrien | digits hexdigit 504077311Sobrien 504177311Sobrien decdigit [0-9] 504277311Sobrien 504377311Sobrien e05 e05 addOp e06 504477311Sobrien | e06 504577311Sobrien 504677311Sobrien e06 e06 mulOp e09 504777311Sobrien | e09 504877311Sobrien 504977311Sobrien e09 OFFSET e10 505077311Sobrien | e09 PTR e10 505177311Sobrien | e09 : e10 505277311Sobrien | e10 505377311Sobrien 505477311Sobrien e10 e10 [ expr ] 505577311Sobrien | e11 505677311Sobrien 505777311Sobrien e11 ( expr ) 505877311Sobrien | [ expr ] 505977311Sobrien | constant 506077311Sobrien | dataType 506177311Sobrien | id 506277311Sobrien | $ 506377311Sobrien | register 506477311Sobrien 506577311Sobrien => expr SHORT e05 506677311Sobrien | e05 506777311Sobrien 506877311Sobrien gpRegister AX | EAX | BX | EBX | CX | ECX | DX | EDX 506977311Sobrien | BP | EBP | SP | ESP | DI | EDI | SI | ESI 507077311Sobrien 507177311Sobrien hexdigit a | b | c | d | e | f 507277311Sobrien | A | B | C | D | E | F 507377311Sobrien 507477311Sobrien id alpha 507577311Sobrien | id alpha 507677311Sobrien | id decdigit 507777311Sobrien 507877311Sobrien mulOp * | / | MOD 507977311Sobrien 508077311Sobrien quote " | ' 508177311Sobrien 508277311Sobrien register specialRegister 508377311Sobrien | gpRegister 508477311Sobrien | byteRegister 508577311Sobrien 508677311Sobrien segmentRegister CS | DS | ES | FS | GS | SS 508777311Sobrien 508877311Sobrien specialRegister CR0 | CR2 | CR3 508977311Sobrien | DR0 | DR1 | DR2 | DR3 | DR6 | DR7 509077311Sobrien | TR3 | TR4 | TR5 | TR6 | TR7 509177311Sobrien 509277311Sobrien We simplify the grammar in obvious places (e.g., register parsing is 509377311Sobrien done by calling parse_register) and eliminate immediate left recursion 509477311Sobrien to implement a recursive-descent parser. 509577311Sobrien 509677311Sobrien expr SHORT e05 509777311Sobrien | e05 509877311Sobrien 509977311Sobrien e05 e06 e05' 510077311Sobrien 510177311Sobrien e05' addOp e06 e05' 510277311Sobrien | Empty 510377311Sobrien 510477311Sobrien e06 e09 e06' 510577311Sobrien 510677311Sobrien e06' mulOp e09 e06' 510777311Sobrien | Empty 510877311Sobrien 510977311Sobrien e09 OFFSET e10 e09' 511077311Sobrien | e10 e09' 511177311Sobrien 511277311Sobrien e09' PTR e10 e09' 511377311Sobrien | : e10 e09' 511477311Sobrien | Empty 511577311Sobrien 511677311Sobrien e10 e11 e10' 511777311Sobrien 511877311Sobrien e10' [ expr ] e10' 511977311Sobrien | Empty 512077311Sobrien 512177311Sobrien e11 ( expr ) 512277311Sobrien | [ expr ] 512377311Sobrien | BYTE 512477311Sobrien | WORD 512577311Sobrien | DWORD 512677311Sobrien | QWORD 512777311Sobrien | XWORD 512877311Sobrien | . 512977311Sobrien | $ 513077311Sobrien | register 513177311Sobrien | id 513277311Sobrien | constant */ 513377311Sobrien 513477311Sobrien/* Parsing structure for the intel syntax parser. Used to implement the 513577311Sobrien semantic actions for the operand grammar. */ 513677311Sobrienstruct intel_parser_s 513777311Sobrien { 513877311Sobrien char *op_string; /* The string being parsed. */ 513977311Sobrien int got_a_float; /* Whether the operand is a float. */ 514077311Sobrien int op_modifier; /* Operand modifier. */ 514177311Sobrien int is_mem; /* 1 if operand is memory reference. */ 514277311Sobrien const reg_entry *reg; /* Last register reference found. */ 514377311Sobrien char *disp; /* Displacement string being built. */ 514477311Sobrien }; 514577311Sobrien 514677311Sobrienstatic struct intel_parser_s intel_parser; 514777311Sobrien 514877311Sobrien/* Token structure for parsing intel syntax. */ 514977311Sobrienstruct intel_token 515077311Sobrien { 515177311Sobrien int code; /* Token code. */ 515277311Sobrien const reg_entry *reg; /* Register entry for register tokens. */ 515377311Sobrien char *str; /* String representation. */ 515477311Sobrien }; 515577311Sobrien 515677311Sobrienstatic struct intel_token cur_token, prev_token; 515777311Sobrien 515877311Sobrien/* Token codes for the intel parser. Since T_SHORT is already used 515977311Sobrien by COFF, undefine it first to prevent a warning. */ 516077311Sobrien#define T_NIL -1 516177311Sobrien#define T_CONST 1 516277311Sobrien#define T_REG 2 516377311Sobrien#define T_BYTE 3 516477311Sobrien#define T_WORD 4 516577311Sobrien#define T_DWORD 5 516677311Sobrien#define T_QWORD 6 516777311Sobrien#define T_XWORD 7 516877311Sobrien#undef T_SHORT 516977311Sobrien#define T_SHORT 8 517077311Sobrien#define T_OFFSET 9 517177311Sobrien#define T_PTR 10 517277311Sobrien#define T_ID 11 517377311Sobrien 517477311Sobrien/* Prototypes for intel parser functions. */ 517577311Sobrienstatic int intel_match_token PARAMS ((int code)); 517677311Sobrienstatic void intel_get_token PARAMS ((void)); 517777311Sobrienstatic void intel_putback_token PARAMS ((void)); 517877311Sobrienstatic int intel_expr PARAMS ((void)); 517977311Sobrienstatic int intel_e05 PARAMS ((void)); 518077311Sobrienstatic int intel_e05_1 PARAMS ((void)); 518177311Sobrienstatic int intel_e06 PARAMS ((void)); 518277311Sobrienstatic int intel_e06_1 PARAMS ((void)); 518377311Sobrienstatic int intel_e09 PARAMS ((void)); 518477311Sobrienstatic int intel_e09_1 PARAMS ((void)); 518577311Sobrienstatic int intel_e10 PARAMS ((void)); 518677311Sobrienstatic int intel_e10_1 PARAMS ((void)); 518777311Sobrienstatic int intel_e11 PARAMS ((void)); 518877311Sobrien 518977311Sobrienstatic int 519077311Sobrieni386_intel_operand (operand_string, got_a_float) 519177311Sobrien char *operand_string; 519277311Sobrien int got_a_float; 519377311Sobrien{ 519477311Sobrien int ret; 519577311Sobrien char *p; 519677311Sobrien 519777311Sobrien /* Initialize token holders. */ 519877311Sobrien cur_token.code = prev_token.code = T_NIL; 519977311Sobrien cur_token.reg = prev_token.reg = NULL; 520077311Sobrien cur_token.str = prev_token.str = NULL; 520177311Sobrien 520277311Sobrien /* Initialize parser structure. */ 520377311Sobrien p = intel_parser.op_string = (char *) malloc (strlen (operand_string) + 1); 520477311Sobrien if (p == NULL) 520577311Sobrien abort (); 520677311Sobrien strcpy (intel_parser.op_string, operand_string); 520777311Sobrien intel_parser.got_a_float = got_a_float; 520877311Sobrien intel_parser.op_modifier = -1; 520977311Sobrien intel_parser.is_mem = 0; 521077311Sobrien intel_parser.reg = NULL; 521177311Sobrien intel_parser.disp = (char *) malloc (strlen (operand_string) + 1); 521277311Sobrien if (intel_parser.disp == NULL) 521377311Sobrien abort (); 521477311Sobrien intel_parser.disp[0] = '\0'; 521577311Sobrien 521677311Sobrien /* Read the first token and start the parser. */ 521777311Sobrien intel_get_token (); 521877311Sobrien ret = intel_expr (); 521977311Sobrien 522077311Sobrien if (ret) 522177311Sobrien { 522277311Sobrien /* If we found a memory reference, hand it over to i386_displacement 522377311Sobrien to fill in the rest of the operand fields. */ 522477311Sobrien if (intel_parser.is_mem) 522577311Sobrien { 522677311Sobrien if ((i.mem_operands == 1 522777311Sobrien && (current_templates->start->opcode_modifier & IsString) == 0) 522877311Sobrien || i.mem_operands == 2) 522977311Sobrien { 523077311Sobrien as_bad (_("too many memory references for '%s'"), 523177311Sobrien current_templates->start->name); 523277311Sobrien ret = 0; 523377311Sobrien } 523477311Sobrien else 523577311Sobrien { 523677311Sobrien char *s = intel_parser.disp; 523777311Sobrien i.mem_operands++; 523877311Sobrien 523977311Sobrien /* Add the displacement expression. */ 524077311Sobrien if (*s != '\0') 524177311Sobrien ret = i386_displacement (s, s + strlen (s)) 524277311Sobrien && i386_index_check (s); 524377311Sobrien } 524477311Sobrien } 524577311Sobrien 524677311Sobrien /* Constant and OFFSET expressions are handled by i386_immediate. */ 524777311Sobrien else if (intel_parser.op_modifier == OFFSET_FLAT 524877311Sobrien || intel_parser.reg == NULL) 524977311Sobrien ret = i386_immediate (intel_parser.disp); 525077311Sobrien } 525177311Sobrien 525277311Sobrien free (p); 525377311Sobrien free (intel_parser.disp); 525477311Sobrien 525577311Sobrien return ret; 525677311Sobrien} 525777311Sobrien 525877311Sobrien/* expr SHORT e05 525977311Sobrien | e05 */ 526077311Sobrienstatic int 526177311Sobrienintel_expr () 526277311Sobrien{ 526377311Sobrien /* expr SHORT e05 */ 526477311Sobrien if (cur_token.code == T_SHORT) 526577311Sobrien { 526677311Sobrien intel_parser.op_modifier = SHORT; 526777311Sobrien intel_match_token (T_SHORT); 526877311Sobrien 526977311Sobrien return (intel_e05 ()); 527077311Sobrien } 527177311Sobrien 527277311Sobrien /* expr e05 */ 527377311Sobrien else 527477311Sobrien return intel_e05 (); 527577311Sobrien} 527677311Sobrien 527777311Sobrien/* e05 e06 e05' 527877311Sobrien 527977311Sobrien e05' addOp e06 e05' 528077311Sobrien | Empty */ 528177311Sobrienstatic int 528277311Sobrienintel_e05 () 528377311Sobrien{ 528477311Sobrien return (intel_e06 () && intel_e05_1 ()); 528577311Sobrien} 528677311Sobrien 528777311Sobrienstatic int 528877311Sobrienintel_e05_1 () 528977311Sobrien{ 529077311Sobrien /* e05' addOp e06 e05' */ 529177311Sobrien if (cur_token.code == '+' || cur_token.code == '-') 529277311Sobrien { 529377311Sobrien strcat (intel_parser.disp, cur_token.str); 529477311Sobrien intel_match_token (cur_token.code); 529577311Sobrien 529677311Sobrien return (intel_e06 () && intel_e05_1 ()); 529777311Sobrien } 529877311Sobrien 529977311Sobrien /* e05' Empty */ 530077311Sobrien else 530177311Sobrien return 1; 530277311Sobrien} 530377311Sobrien 530477311Sobrien/* e06 e09 e06' 530577311Sobrien 530677311Sobrien e06' mulOp e09 e06' 530777311Sobrien | Empty */ 530877311Sobrienstatic int 530977311Sobrienintel_e06 () 531077311Sobrien{ 531177311Sobrien return (intel_e09 () && intel_e06_1 ()); 531277311Sobrien} 531377311Sobrien 531477311Sobrienstatic int 531577311Sobrienintel_e06_1 () 531677311Sobrien{ 531777311Sobrien /* e06' mulOp e09 e06' */ 531877311Sobrien if (cur_token.code == '*' || cur_token.code == '/') 531977311Sobrien { 532077311Sobrien strcat (intel_parser.disp, cur_token.str); 532177311Sobrien intel_match_token (cur_token.code); 532277311Sobrien 532377311Sobrien return (intel_e09 () && intel_e06_1 ()); 532477311Sobrien } 532577311Sobrien 532677311Sobrien /* e06' Empty */ 532777311Sobrien else 532877311Sobrien return 1; 532977311Sobrien} 533077311Sobrien 533177311Sobrien/* e09 OFFSET e10 e09' 533277311Sobrien | e10 e09' 533377311Sobrien 533477311Sobrien e09' PTR e10 e09' 533577311Sobrien | : e10 e09' 533677311Sobrien | Empty */ 533777311Sobrienstatic int 533877311Sobrienintel_e09 () 533977311Sobrien{ 534077311Sobrien /* e09 OFFSET e10 e09' */ 534177311Sobrien if (cur_token.code == T_OFFSET) 534277311Sobrien { 534377311Sobrien intel_parser.is_mem = 0; 534477311Sobrien intel_parser.op_modifier = OFFSET_FLAT; 534577311Sobrien intel_match_token (T_OFFSET); 534677311Sobrien 534777311Sobrien return (intel_e10 () && intel_e09_1 ()); 534877311Sobrien } 534977311Sobrien 535077311Sobrien /* e09 e10 e09' */ 535177311Sobrien else 535277311Sobrien return (intel_e10 () && intel_e09_1 ()); 535377311Sobrien} 535477311Sobrien 535577311Sobrienstatic int 535677311Sobrienintel_e09_1 () 535777311Sobrien{ 535877311Sobrien /* e09' PTR e10 e09' */ 535977311Sobrien if (cur_token.code == T_PTR) 536077311Sobrien { 536177311Sobrien if (prev_token.code == T_BYTE) 536277311Sobrien i.suffix = BYTE_MNEM_SUFFIX; 536377311Sobrien 536477311Sobrien else if (prev_token.code == T_WORD) 536577311Sobrien { 536677311Sobrien if (intel_parser.got_a_float == 2) /* "fi..." */ 536777311Sobrien i.suffix = SHORT_MNEM_SUFFIX; 536877311Sobrien else 536977311Sobrien i.suffix = WORD_MNEM_SUFFIX; 537077311Sobrien } 537177311Sobrien 537277311Sobrien else if (prev_token.code == T_DWORD) 537377311Sobrien { 537477311Sobrien if (intel_parser.got_a_float == 1) /* "f..." */ 537577311Sobrien i.suffix = SHORT_MNEM_SUFFIX; 537677311Sobrien else 537777311Sobrien i.suffix = LONG_MNEM_SUFFIX; 537877311Sobrien } 537977311Sobrien 538077311Sobrien else if (prev_token.code == T_QWORD) 538177311Sobrien { 538277311Sobrien if (intel_parser.got_a_float == 1) /* "f..." */ 538377311Sobrien i.suffix = LONG_MNEM_SUFFIX; 538477311Sobrien else 538577311Sobrien i.suffix = QWORD_MNEM_SUFFIX; 538677311Sobrien } 538777311Sobrien 538877311Sobrien else if (prev_token.code == T_XWORD) 538977311Sobrien i.suffix = LONG_DOUBLE_MNEM_SUFFIX; 539077311Sobrien 539177311Sobrien else 539277311Sobrien { 539377311Sobrien as_bad (_("Unknown operand modifier `%s'\n"), prev_token.str); 539477311Sobrien return 0; 539577311Sobrien } 539677311Sobrien 539777311Sobrien intel_match_token (T_PTR); 539877311Sobrien 539977311Sobrien return (intel_e10 () && intel_e09_1 ()); 540077311Sobrien } 540177311Sobrien 540277311Sobrien /* e09 : e10 e09' */ 540377311Sobrien else if (cur_token.code == ':') 540477311Sobrien { 540577311Sobrien /* Mark as a memory operand only if it's not already known to be an 540677311Sobrien offset expression. */ 540777311Sobrien if (intel_parser.op_modifier != OFFSET_FLAT) 540877311Sobrien intel_parser.is_mem = 1; 540977311Sobrien 541077311Sobrien return (intel_match_token (':') && intel_e10 () && intel_e09_1 ()); 541177311Sobrien } 541277311Sobrien 541377311Sobrien /* e09' Empty */ 541477311Sobrien else 541577311Sobrien return 1; 541677311Sobrien} 541777311Sobrien 541877311Sobrien/* e10 e11 e10' 541977311Sobrien 542077311Sobrien e10' [ expr ] e10' 542177311Sobrien | Empty */ 542277311Sobrienstatic int 542377311Sobrienintel_e10 () 542477311Sobrien{ 542577311Sobrien return (intel_e11 () && intel_e10_1 ()); 542677311Sobrien} 542777311Sobrien 542877311Sobrienstatic int 542977311Sobrienintel_e10_1 () 543077311Sobrien{ 543177311Sobrien /* e10' [ expr ] e10' */ 543277311Sobrien if (cur_token.code == '[') 543377311Sobrien { 543477311Sobrien intel_match_token ('['); 543577311Sobrien 543677311Sobrien /* Mark as a memory operand only if it's not already known to be an 543777311Sobrien offset expression. If it's an offset expression, we need to keep 543877311Sobrien the brace in. */ 543977311Sobrien if (intel_parser.op_modifier != OFFSET_FLAT) 544077311Sobrien intel_parser.is_mem = 1; 544177311Sobrien else 544277311Sobrien strcat (intel_parser.disp, "["); 544377311Sobrien 544477311Sobrien /* Add a '+' to the displacement string if necessary. */ 544577311Sobrien if (*intel_parser.disp != '\0' 544677311Sobrien && *(intel_parser.disp + strlen (intel_parser.disp) - 1) != '+') 544777311Sobrien strcat (intel_parser.disp, "+"); 544877311Sobrien 544977311Sobrien if (intel_expr () && intel_match_token (']')) 545077311Sobrien { 545177311Sobrien /* Preserve brackets when the operand is an offset expression. */ 545277311Sobrien if (intel_parser.op_modifier == OFFSET_FLAT) 545377311Sobrien strcat (intel_parser.disp, "]"); 545477311Sobrien 545577311Sobrien return intel_e10_1 (); 545677311Sobrien } 545777311Sobrien else 545877311Sobrien return 0; 545977311Sobrien } 546077311Sobrien 546177311Sobrien /* e10' Empty */ 546277311Sobrien else 546377311Sobrien return 1; 546477311Sobrien} 546577311Sobrien 546677311Sobrien/* e11 ( expr ) 546777311Sobrien | [ expr ] 546877311Sobrien | BYTE 546977311Sobrien | WORD 547077311Sobrien | DWORD 547177311Sobrien | QWORD 547277311Sobrien | XWORD 547377311Sobrien | $ 547477311Sobrien | . 547577311Sobrien | register 547677311Sobrien | id 547777311Sobrien | constant */ 547877311Sobrienstatic int 547977311Sobrienintel_e11 () 548077311Sobrien{ 548177311Sobrien /* e11 ( expr ) */ 548277311Sobrien if (cur_token.code == '(') 548377311Sobrien { 548477311Sobrien intel_match_token ('('); 548577311Sobrien strcat (intel_parser.disp, "("); 548677311Sobrien 548777311Sobrien if (intel_expr () && intel_match_token (')')) 548877311Sobrien { 548977311Sobrien strcat (intel_parser.disp, ")"); 549077311Sobrien return 1; 549177311Sobrien } 549277311Sobrien else 549377311Sobrien return 0; 549477311Sobrien } 549577311Sobrien 549677311Sobrien /* e11 [ expr ] */ 549777311Sobrien else if (cur_token.code == '[') 549877311Sobrien { 549977311Sobrien intel_match_token ('['); 550077311Sobrien 550177311Sobrien /* Mark as a memory operand only if it's not already known to be an 550277311Sobrien offset expression. If it's an offset expression, we need to keep 550377311Sobrien the brace in. */ 550477311Sobrien if (intel_parser.op_modifier != OFFSET_FLAT) 550577311Sobrien intel_parser.is_mem = 1; 550677311Sobrien else 550777311Sobrien strcat (intel_parser.disp, "["); 550877311Sobrien 550977311Sobrien /* Operands for jump/call inside brackets denote absolute addresses. */ 551077311Sobrien if (current_templates->start->opcode_modifier & Jump 551177311Sobrien || current_templates->start->opcode_modifier & JumpDword 551277311Sobrien || current_templates->start->opcode_modifier & JumpByte 551377311Sobrien || current_templates->start->opcode_modifier & JumpInterSegment) 551477311Sobrien i.types[this_operand] |= JumpAbsolute; 551577311Sobrien 551677311Sobrien /* Add a '+' to the displacement string if necessary. */ 551777311Sobrien if (*intel_parser.disp != '\0' 551877311Sobrien && *(intel_parser.disp + strlen (intel_parser.disp) - 1) != '+') 551977311Sobrien strcat (intel_parser.disp, "+"); 552077311Sobrien 552177311Sobrien if (intel_expr () && intel_match_token (']')) 552277311Sobrien { 552377311Sobrien /* Preserve brackets when the operand is an offset expression. */ 552477311Sobrien if (intel_parser.op_modifier == OFFSET_FLAT) 552577311Sobrien strcat (intel_parser.disp, "]"); 552677311Sobrien 552777311Sobrien return 1; 552877311Sobrien } 552977311Sobrien else 553077311Sobrien return 0; 553177311Sobrien } 553277311Sobrien 553377311Sobrien /* e11 BYTE 553477311Sobrien | WORD 553577311Sobrien | DWORD 553677311Sobrien | QWORD 553777311Sobrien | XWORD */ 553877311Sobrien else if (cur_token.code == T_BYTE 553977311Sobrien || cur_token.code == T_WORD 554077311Sobrien || cur_token.code == T_DWORD 554177311Sobrien || cur_token.code == T_QWORD 554277311Sobrien || cur_token.code == T_XWORD) 554377311Sobrien { 554477311Sobrien intel_match_token (cur_token.code); 554577311Sobrien 554677311Sobrien return 1; 554777311Sobrien } 554877311Sobrien 554977311Sobrien /* e11 $ 555077311Sobrien | . */ 555177311Sobrien else 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 /* Mark as a memory operand only if it's not already known to be an 555777311Sobrien offset expression. */ 555877311Sobrien if (intel_parser.op_modifier != OFFSET_FLAT) 555977311Sobrien intel_parser.is_mem = 1; 556077311Sobrien 556177311Sobrien return 1; 556277311Sobrien } 556377311Sobrien 556477311Sobrien /* e11 register */ 556577311Sobrien else if (cur_token.code == T_REG) 556677311Sobrien { 556777311Sobrien const reg_entry *reg = intel_parser.reg = cur_token.reg; 556877311Sobrien 556977311Sobrien intel_match_token (T_REG); 557077311Sobrien 557177311Sobrien /* Check for segment change. */ 557277311Sobrien if (cur_token.code == ':') 557377311Sobrien { 557477311Sobrien if (reg->reg_type & (SReg2 | SReg3)) 557577311Sobrien { 557677311Sobrien switch (reg->reg_num) 557777311Sobrien { 557877311Sobrien case 0: 557977311Sobrien i.seg[i.mem_operands] = &es; 558077311Sobrien break; 558177311Sobrien case 1: 558277311Sobrien i.seg[i.mem_operands] = &cs; 558377311Sobrien break; 558477311Sobrien case 2: 558577311Sobrien i.seg[i.mem_operands] = &ss; 558677311Sobrien break; 558777311Sobrien case 3: 558877311Sobrien i.seg[i.mem_operands] = &ds; 558977311Sobrien break; 559077311Sobrien case 4: 559177311Sobrien i.seg[i.mem_operands] = &fs; 559277311Sobrien break; 559377311Sobrien case 5: 559477311Sobrien i.seg[i.mem_operands] = &gs; 559577311Sobrien break; 559677311Sobrien } 559777311Sobrien } 559877311Sobrien else 559977311Sobrien { 560077311Sobrien as_bad (_("`%s' is not a valid segment register"), reg->reg_name); 560177311Sobrien return 0; 560277311Sobrien } 560377311Sobrien } 560477311Sobrien 560577311Sobrien /* Not a segment register. Check for register scaling. */ 560677311Sobrien else if (cur_token.code == '*') 560777311Sobrien { 560877311Sobrien if (!intel_parser.is_mem) 560977311Sobrien { 561077311Sobrien as_bad (_("Register scaling only allowed in memory operands.")); 561177311Sobrien return 0; 561277311Sobrien } 561377311Sobrien 561477311Sobrien /* What follows must be a valid scale. */ 561577311Sobrien if (intel_match_token ('*') 561677311Sobrien && strchr ("01248", *cur_token.str)) 561777311Sobrien { 561877311Sobrien i.index_reg = reg; 561977311Sobrien i.types[this_operand] |= BaseIndex; 562077311Sobrien 562177311Sobrien /* Set the scale after setting the register (otherwise, 562277311Sobrien i386_scale will complain) */ 562377311Sobrien i386_scale (cur_token.str); 562477311Sobrien intel_match_token (T_CONST); 562577311Sobrien } 562677311Sobrien else 562777311Sobrien { 562877311Sobrien as_bad (_("expecting scale factor of 1, 2, 4, or 8: got `%s'"), 562977311Sobrien cur_token.str); 563077311Sobrien return 0; 563177311Sobrien } 563277311Sobrien } 563377311Sobrien 563477311Sobrien /* No scaling. If this is a memory operand, the register is either a 563577311Sobrien base register (first occurrence) or an index register (second 563677311Sobrien occurrence). */ 563777311Sobrien else if (intel_parser.is_mem && !(reg->reg_type & (SReg2 | SReg3))) 563877311Sobrien { 563977311Sobrien if (i.base_reg && i.index_reg) 564077311Sobrien { 564177311Sobrien as_bad (_("Too many register references in memory operand.\n")); 564277311Sobrien return 0; 564377311Sobrien } 564477311Sobrien 564577311Sobrien if (i.base_reg == NULL) 564677311Sobrien i.base_reg = reg; 564777311Sobrien else 564877311Sobrien i.index_reg = reg; 564977311Sobrien 565077311Sobrien i.types[this_operand] |= BaseIndex; 565177311Sobrien } 565277311Sobrien 565377311Sobrien /* Offset modifier. Add the register to the displacement string to be 565477311Sobrien parsed as an immediate expression after we're done. */ 565577311Sobrien else if (intel_parser.op_modifier == OFFSET_FLAT) 565677311Sobrien strcat (intel_parser.disp, reg->reg_name); 565777311Sobrien 565877311Sobrien /* It's neither base nor index nor offset. */ 565977311Sobrien else 566077311Sobrien { 566177311Sobrien i.types[this_operand] |= reg->reg_type & ~BaseIndex; 566277311Sobrien i.op[this_operand].regs = reg; 566377311Sobrien i.reg_operands++; 566477311Sobrien } 566577311Sobrien 566677311Sobrien /* Since registers are not part of the displacement string (except 566777311Sobrien when we're parsing offset operands), we may need to remove any 566877311Sobrien preceding '+' from the displacement string. */ 566977311Sobrien if (*intel_parser.disp != '\0' 567077311Sobrien && intel_parser.op_modifier != OFFSET_FLAT) 567177311Sobrien { 567277311Sobrien char *s = intel_parser.disp; 567377311Sobrien s += strlen (s) - 1; 567477311Sobrien if (*s == '+') 567577311Sobrien *s = '\0'; 567677311Sobrien } 567777311Sobrien 567877311Sobrien return 1; 567977311Sobrien } 568077311Sobrien 568177311Sobrien /* e11 id */ 568277311Sobrien else if (cur_token.code == T_ID) 568377311Sobrien { 568477311Sobrien /* Add the identifier to the displacement string. */ 568577311Sobrien strcat (intel_parser.disp, cur_token.str); 568677311Sobrien intel_match_token (T_ID); 568777311Sobrien 568877311Sobrien /* The identifier represents a memory reference only if it's not 568977311Sobrien preceded by an offset modifier. */ 569077311Sobrien if (intel_parser.op_modifier != OFFSET_FLAT) 569177311Sobrien intel_parser.is_mem = 1; 569277311Sobrien 569377311Sobrien return 1; 569477311Sobrien } 569577311Sobrien 569677311Sobrien /* e11 constant */ 569777311Sobrien else if (cur_token.code == T_CONST 569877311Sobrien || cur_token.code == '-' 569977311Sobrien || cur_token.code == '+') 570077311Sobrien { 570177311Sobrien char *save_str; 570277311Sobrien 570377311Sobrien /* Allow constants that start with `+' or `-'. */ 570477311Sobrien if (cur_token.code == '-' || cur_token.code == '+') 570577311Sobrien { 570677311Sobrien strcat (intel_parser.disp, cur_token.str); 570777311Sobrien intel_match_token (cur_token.code); 570877311Sobrien if (cur_token.code != T_CONST) 570977311Sobrien { 571077311Sobrien as_bad (_("Syntax error. Expecting a constant. Got `%s'.\n"), 571177311Sobrien cur_token.str); 571277311Sobrien return 0; 571377311Sobrien } 571477311Sobrien } 571577311Sobrien 571677311Sobrien save_str = (char *) malloc (strlen (cur_token.str) + 1); 571777311Sobrien if (save_str == NULL) 571877311Sobrien abort (); 571977311Sobrien strcpy (save_str, cur_token.str); 572077311Sobrien 572177311Sobrien /* Get the next token to check for register scaling. */ 572277311Sobrien intel_match_token (cur_token.code); 572377311Sobrien 572477311Sobrien /* Check if this constant is a scaling factor for an index register. */ 572577311Sobrien if (cur_token.code == '*') 572677311Sobrien { 572777311Sobrien if (intel_match_token ('*') && cur_token.code == T_REG) 572877311Sobrien { 572977311Sobrien if (!intel_parser.is_mem) 573077311Sobrien { 573177311Sobrien as_bad (_("Register scaling only allowed in memory operands.")); 573277311Sobrien return 0; 573377311Sobrien } 573477311Sobrien 573577311Sobrien /* The constant is followed by `* reg', so it must be 573677311Sobrien a valid scale. */ 573777311Sobrien if (strchr ("01248", *save_str)) 573877311Sobrien { 573977311Sobrien i.index_reg = cur_token.reg; 574077311Sobrien i.types[this_operand] |= BaseIndex; 574177311Sobrien 574277311Sobrien /* Set the scale after setting the register (otherwise, 574377311Sobrien i386_scale will complain) */ 574477311Sobrien i386_scale (save_str); 574577311Sobrien intel_match_token (T_REG); 574677311Sobrien 574777311Sobrien /* Since registers are not part of the displacement 574877311Sobrien string, we may need to remove any preceding '+' from 574977311Sobrien the displacement string. */ 575077311Sobrien if (*intel_parser.disp != '\0') 575177311Sobrien { 575277311Sobrien char *s = intel_parser.disp; 575377311Sobrien s += strlen (s) - 1; 575477311Sobrien if (*s == '+') 575577311Sobrien *s = '\0'; 575677311Sobrien } 575777311Sobrien 575877311Sobrien free (save_str); 575977311Sobrien 576077311Sobrien return 1; 576177311Sobrien } 576277311Sobrien else 576377311Sobrien return 0; 576477311Sobrien } 576577311Sobrien 576677311Sobrien /* The constant was not used for register scaling. Since we have 576777311Sobrien already consumed the token following `*' we now need to put it 576877311Sobrien back in the stream. */ 576977311Sobrien else 577077311Sobrien intel_putback_token (); 577177311Sobrien } 577277311Sobrien 577377311Sobrien /* Add the constant to the displacement string. */ 577477311Sobrien strcat (intel_parser.disp, save_str); 577577311Sobrien free (save_str); 577677311Sobrien 577777311Sobrien return 1; 577877311Sobrien } 577977311Sobrien 578077311Sobrien as_bad (_("Unrecognized token '%s'"), cur_token.str); 578177311Sobrien return 0; 578277311Sobrien} 578377311Sobrien 578477311Sobrien/* Match the given token against cur_token. If they match, read the next 578577311Sobrien token from the operand string. */ 578677311Sobrienstatic int 578777311Sobrienintel_match_token (code) 578877311Sobrien int code; 578977311Sobrien{ 579077311Sobrien if (cur_token.code == code) 579177311Sobrien { 579277311Sobrien intel_get_token (); 579377311Sobrien return 1; 579477311Sobrien } 579577311Sobrien else 579677311Sobrien { 579777311Sobrien as_bad (_("Unexpected token `%s'\n"), cur_token.str); 579877311Sobrien return 0; 579977311Sobrien } 580077311Sobrien} 580177311Sobrien 580277311Sobrien/* Read a new token from intel_parser.op_string and store it in cur_token. */ 580377311Sobrienstatic void 580477311Sobrienintel_get_token () 580577311Sobrien{ 580677311Sobrien char *end_op; 580777311Sobrien const reg_entry *reg; 580877311Sobrien struct intel_token new_token; 580977311Sobrien 581077311Sobrien new_token.code = T_NIL; 581177311Sobrien new_token.reg = NULL; 581277311Sobrien new_token.str = NULL; 581377311Sobrien 581477311Sobrien /* Free the memory allocated to the previous token and move 581577311Sobrien cur_token to prev_token. */ 581677311Sobrien if (prev_token.str) 581777311Sobrien free (prev_token.str); 581877311Sobrien 581977311Sobrien prev_token = cur_token; 582077311Sobrien 582177311Sobrien /* Skip whitespace. */ 582277311Sobrien while (is_space_char (*intel_parser.op_string)) 582377311Sobrien intel_parser.op_string++; 582477311Sobrien 582577311Sobrien /* Return an empty token if we find nothing else on the line. */ 582677311Sobrien if (*intel_parser.op_string == '\0') 582777311Sobrien { 582877311Sobrien cur_token = new_token; 582977311Sobrien return; 583077311Sobrien } 583177311Sobrien 583277311Sobrien /* The new token cannot be larger than the remainder of the operand 583377311Sobrien string. */ 583477311Sobrien new_token.str = (char *) malloc (strlen (intel_parser.op_string) + 1); 583577311Sobrien if (new_token.str == NULL) 583677311Sobrien abort (); 583777311Sobrien new_token.str[0] = '\0'; 583877311Sobrien 583977311Sobrien if (strchr ("0123456789", *intel_parser.op_string)) 584077311Sobrien { 584177311Sobrien char *p = new_token.str; 584277311Sobrien char *q = intel_parser.op_string; 584377311Sobrien new_token.code = T_CONST; 584477311Sobrien 584577311Sobrien /* Allow any kind of identifier char to encompass floating point and 584677311Sobrien hexadecimal numbers. */ 584777311Sobrien while (is_identifier_char (*q)) 584877311Sobrien *p++ = *q++; 584977311Sobrien *p = '\0'; 585077311Sobrien 585177311Sobrien /* Recognize special symbol names [0-9][bf]. */ 585277311Sobrien if (strlen (intel_parser.op_string) == 2 585377311Sobrien && (intel_parser.op_string[1] == 'b' 585477311Sobrien || intel_parser.op_string[1] == 'f')) 585577311Sobrien new_token.code = T_ID; 585677311Sobrien } 585777311Sobrien 585877311Sobrien else if (strchr ("+-/*:[]()", *intel_parser.op_string)) 585977311Sobrien { 586077311Sobrien new_token.code = *intel_parser.op_string; 586177311Sobrien new_token.str[0] = *intel_parser.op_string; 586277311Sobrien new_token.str[1] = '\0'; 586377311Sobrien } 586477311Sobrien 586577311Sobrien else if ((*intel_parser.op_string == REGISTER_PREFIX || allow_naked_reg) 586677311Sobrien && ((reg = parse_register (intel_parser.op_string, &end_op)) != NULL)) 586777311Sobrien { 586877311Sobrien new_token.code = T_REG; 586977311Sobrien new_token.reg = reg; 587077311Sobrien 587177311Sobrien if (*intel_parser.op_string == REGISTER_PREFIX) 587277311Sobrien { 587377311Sobrien new_token.str[0] = REGISTER_PREFIX; 587477311Sobrien new_token.str[1] = '\0'; 587577311Sobrien } 587677311Sobrien 587777311Sobrien strcat (new_token.str, reg->reg_name); 587877311Sobrien } 587977311Sobrien 588077311Sobrien else if (is_identifier_char (*intel_parser.op_string)) 588177311Sobrien { 588277311Sobrien char *p = new_token.str; 588377311Sobrien char *q = intel_parser.op_string; 588477311Sobrien 588577311Sobrien /* A '.' or '$' followed by an identifier char is an identifier. 588677311Sobrien Otherwise, it's operator '.' followed by an expression. */ 588777311Sobrien if ((*q == '.' || *q == '$') && !is_identifier_char (*(q + 1))) 588877311Sobrien { 588977311Sobrien new_token.code = *q; 589077311Sobrien new_token.str[0] = *q; 589177311Sobrien new_token.str[1] = '\0'; 589277311Sobrien } 589377311Sobrien else 589477311Sobrien { 589577311Sobrien while (is_identifier_char (*q) || *q == '@') 589677311Sobrien *p++ = *q++; 589777311Sobrien *p = '\0'; 589877311Sobrien 589977311Sobrien if (strcasecmp (new_token.str, "BYTE") == 0) 590077311Sobrien new_token.code = T_BYTE; 590177311Sobrien 590277311Sobrien else if (strcasecmp (new_token.str, "WORD") == 0) 590377311Sobrien new_token.code = T_WORD; 590477311Sobrien 590577311Sobrien else if (strcasecmp (new_token.str, "DWORD") == 0) 590677311Sobrien new_token.code = T_DWORD; 590777311Sobrien 590877311Sobrien else if (strcasecmp (new_token.str, "QWORD") == 0) 590977311Sobrien new_token.code = T_QWORD; 591077311Sobrien 591177311Sobrien else if (strcasecmp (new_token.str, "XWORD") == 0) 591277311Sobrien new_token.code = T_XWORD; 591377311Sobrien 591477311Sobrien else if (strcasecmp (new_token.str, "PTR") == 0) 591577311Sobrien new_token.code = T_PTR; 591677311Sobrien 591777311Sobrien else if (strcasecmp (new_token.str, "SHORT") == 0) 591877311Sobrien new_token.code = T_SHORT; 591977311Sobrien 592077311Sobrien else if (strcasecmp (new_token.str, "OFFSET") == 0) 592177311Sobrien { 592277311Sobrien new_token.code = T_OFFSET; 592377311Sobrien 592477311Sobrien /* ??? This is not mentioned in the MASM grammar but gcc 592577311Sobrien makes use of it with -mintel-syntax. OFFSET may be 592677311Sobrien followed by FLAT: */ 592777311Sobrien if (strncasecmp (q, " FLAT:", 6) == 0) 592877311Sobrien strcat (new_token.str, " FLAT:"); 592977311Sobrien } 593077311Sobrien 593177311Sobrien /* ??? This is not mentioned in the MASM grammar. */ 593277311Sobrien else if (strcasecmp (new_token.str, "FLAT") == 0) 593377311Sobrien new_token.code = T_OFFSET; 593477311Sobrien 593577311Sobrien else 593677311Sobrien new_token.code = T_ID; 593777311Sobrien } 593877311Sobrien } 593977311Sobrien 594077311Sobrien else 594177311Sobrien as_bad (_("Unrecognized token `%s'\n"), intel_parser.op_string); 594277311Sobrien 594377311Sobrien intel_parser.op_string += strlen (new_token.str); 594477311Sobrien cur_token = new_token; 594577311Sobrien} 594677311Sobrien 594777311Sobrien/* Put cur_token back into the token stream and make cur_token point to 594877311Sobrien prev_token. */ 594977311Sobrienstatic void 595077311Sobrienintel_putback_token () 595177311Sobrien{ 595277311Sobrien intel_parser.op_string -= strlen (cur_token.str); 595377311Sobrien free (cur_token.str); 595477311Sobrien cur_token = prev_token; 595577311Sobrien 595677311Sobrien /* Forget prev_token. */ 595777311Sobrien prev_token.code = T_NIL; 595877311Sobrien prev_token.reg = NULL; 595977311Sobrien prev_token.str = NULL; 596077311Sobrien} 5961