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