1218822Sdim/* tc-i386.c -- Assemble code for the Intel 80386
278840Sobrien   Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3218822Sdim   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
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
20218822Sdim   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
21218822Sdim   02110-1301, USA.  */
2233965Sjdp
2377311Sobrien/* Intel 80386 machine specific gas.
2477311Sobrien   Written by Eliot Dresselhaus (eliot@mgm.mit.edu).
2577311Sobrien   x86_64 support by Jan Hubicka (jh@suse.cz)
26130570Sobrien   VIA PadLock support by Michal Ludvig (mludvig@suse.cz)
2777311Sobrien   Bugs & suggestions are completely welcome.  This is free software.
2877311Sobrien   Please help us make it better.  */
2977311Sobrien
3033965Sjdp#include "as.h"
3189867Sobrien#include "safe-ctype.h"
3233965Sjdp#include "subsegs.h"
3377311Sobrien#include "dwarf2dbg.h"
34130570Sobrien#include "dw2gencfi.h"
35218822Sdim#include "elf/x86-64.h"
3633965Sjdp
3760519Sobrien#ifndef REGISTER_WARNINGS
3860519Sobrien#define REGISTER_WARNINGS 1
3933965Sjdp#endif
4033965Sjdp
4160519Sobrien#ifndef INFER_ADDR_PREFIX
4260519Sobrien#define INFER_ADDR_PREFIX 1
4360519Sobrien#endif
4460519Sobrien
4560519Sobrien#ifndef SCALE1_WHEN_NO_INDEX
4660519Sobrien/* Specifying a scale factor besides 1 when there is no index is
4760519Sobrien   futile.  eg. `mov (%ebx,2),%al' does exactly the same as
4860519Sobrien   `mov (%ebx),%al'.  To slavishly follow what the programmer
4960519Sobrien   specified, set SCALE1_WHEN_NO_INDEX to 0.  */
5060519Sobrien#define SCALE1_WHEN_NO_INDEX 1
5160519Sobrien#endif
5260519Sobrien
5394546Sobrien#ifndef DEFAULT_ARCH
5494546Sobrien#define DEFAULT_ARCH "i386"
5591054Sobrien#endif
5660519Sobrien
5794546Sobrien#ifndef INLINE
5894546Sobrien#if __GNUC__ >= 2
5994546Sobrien#define INLINE __inline__
6094546Sobrien#else
6194546Sobrien#define INLINE
6294546Sobrien#endif
6394546Sobrien#endif
6494546Sobrien
65218822Sdimstatic void set_code_flag (int);
66218822Sdimstatic void set_16bit_gcc_code_flag (int);
67218822Sdimstatic void set_intel_syntax (int);
68218822Sdimstatic void set_cpu_arch (int);
69218822Sdim#ifdef TE_PE
70218822Sdimstatic void pe_directive_secrel (int);
71218822Sdim#endif
72218822Sdimstatic void signed_cons (int);
73218822Sdimstatic char *output_invalid (int c);
74218822Sdimstatic int i386_operand (char *);
75218822Sdimstatic int i386_intel_operand (char *, int);
76218822Sdimstatic const reg_entry *parse_register (char *, char **);
77218822Sdimstatic char *parse_insn (char *, char *);
78218822Sdimstatic char *parse_operands (char *, const char *);
79218822Sdimstatic void swap_operands (void);
80218822Sdimstatic void swap_2_operands (int, int);
81218822Sdimstatic void optimize_imm (void);
82218822Sdimstatic void optimize_disp (void);
83218822Sdimstatic int match_template (void);
84218822Sdimstatic int check_string (void);
85218822Sdimstatic int process_suffix (void);
86218822Sdimstatic int check_byte_reg (void);
87218822Sdimstatic int check_long_reg (void);
88218822Sdimstatic int check_qword_reg (void);
89218822Sdimstatic int check_word_reg (void);
90218822Sdimstatic int finalize_imm (void);
91218822Sdimstatic int process_operands (void);
92218822Sdimstatic const seg_entry *build_modrm_byte (void);
93218822Sdimstatic void output_insn (void);
94218822Sdimstatic void output_imm (fragS *, offsetT);
95218822Sdimstatic void output_disp (fragS *, offsetT);
9694546Sobrien#ifndef I386COFF
97218822Sdimstatic void s_bss (int);
9833965Sjdp#endif
99218822Sdim#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
100218822Sdimstatic void handle_large_common (int small ATTRIBUTE_UNUSED);
101218822Sdim#endif
10233965Sjdp
10389867Sobrienstatic const char *default_arch = DEFAULT_ARCH;
10477311Sobrien
10533965Sjdp/* 'md_assemble ()' gathers together information and puts it into a
10677311Sobrien   i386_insn.  */
10733965Sjdp
10860519Sobrienunion i386_op
10960519Sobrien  {
11060519Sobrien    expressionS *disps;
11160519Sobrien    expressionS *imms;
11260519Sobrien    const reg_entry *regs;
11360519Sobrien  };
11460519Sobrien
11533965Sjdpstruct _i386_insn
11633965Sjdp  {
11777311Sobrien    /* TM holds the template for the insn were currently assembling.  */
11833965Sjdp    template tm;
11960519Sobrien
12060519Sobrien    /* SUFFIX holds the instruction mnemonic suffix if given.
12160519Sobrien       (e.g. 'l' for 'movl')  */
12233965Sjdp    char suffix;
12333965Sjdp
12477311Sobrien    /* OPERANDS gives the number of given operands.  */
12533965Sjdp    unsigned int operands;
12633965Sjdp
12733965Sjdp    /* REG_OPERANDS, DISP_OPERANDS, MEM_OPERANDS, IMM_OPERANDS give the number
12833965Sjdp       of given register, displacement, memory operands and immediate
12977311Sobrien       operands.  */
13033965Sjdp    unsigned int reg_operands, disp_operands, mem_operands, imm_operands;
13133965Sjdp
13233965Sjdp    /* TYPES [i] is the type (see above #defines) which tells us how to
13360519Sobrien       use OP[i] for the corresponding operand.  */
13433965Sjdp    unsigned int types[MAX_OPERANDS];
13533965Sjdp
13660519Sobrien    /* Displacement expression, immediate expression, or register for each
13760519Sobrien       operand.  */
13860519Sobrien    union i386_op op[MAX_OPERANDS];
13933965Sjdp
14077311Sobrien    /* Flags for operands.  */
14177311Sobrien    unsigned int flags[MAX_OPERANDS];
14277311Sobrien#define Operand_PCrel 1
14377311Sobrien
14433965Sjdp    /* Relocation type for operand */
145130570Sobrien    enum bfd_reloc_code_real reloc[MAX_OPERANDS];
14633965Sjdp
14733965Sjdp    /* BASE_REG, INDEX_REG, and LOG2_SCALE_FACTOR are used to encode
14833965Sjdp       the base index byte below.  */
14960519Sobrien    const reg_entry *base_reg;
15060519Sobrien    const reg_entry *index_reg;
15133965Sjdp    unsigned int log2_scale_factor;
15233965Sjdp
15360519Sobrien    /* SEG gives the seg_entries of this insn.  They are zero unless
15477311Sobrien       explicit segment overrides are given.  */
15577311Sobrien    const seg_entry *seg[2];
15633965Sjdp
15733965Sjdp    /* PREFIX holds all the given prefix opcodes (usually null).
15860519Sobrien       PREFIXES is the number of prefix opcodes.  */
15960519Sobrien    unsigned int prefixes;
16033965Sjdp    unsigned char prefix[MAX_PREFIXES];
16133965Sjdp
16260519Sobrien    /* RM and SIB are the modrm byte and the sib byte where the
16360519Sobrien       addressing modes of this insn are encoded.  */
16433965Sjdp
16533965Sjdp    modrm_byte rm;
16677311Sobrien    rex_byte rex;
16760519Sobrien    sib_byte sib;
16833965Sjdp  };
16933965Sjdp
17033965Sjdptypedef struct _i386_insn i386_insn;
17133965Sjdp
17260519Sobrien/* List of chars besides those in app.c:symbol_chars that can start an
17360519Sobrien   operand.  Used to prevent the scrubber eating vital white-space.  */
174218822Sdimconst char extra_symbol_chars[] = "*%-(["
17560519Sobrien#ifdef LEX_AT
176218822Sdim	"@"
17760519Sobrien#endif
178218822Sdim#ifdef LEX_QM
179218822Sdim	"?"
180218822Sdim#endif
181218822Sdim	;
18260519Sobrien
18394546Sobrien#if (defined (TE_I386AIX)				\
18494546Sobrien     || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF))	\
185218822Sdim	 && !defined (TE_GNU)				\
18694546Sobrien	 && !defined (TE_LINUX)				\
187218822Sdim 	 && !defined (TE_NETWARE)			\
18894546Sobrien	 && !defined (TE_FreeBSD)			\
18994546Sobrien	 && !defined (TE_NetBSD)))
19033965Sjdp/* This array holds the chars that always start a comment.  If the
191218822Sdim   pre-processor is disabled, these aren't very useful.  The option
192218822Sdim   --divide will remove '/' from this list.  */
193218822Sdimconst char *i386_comment_chars = "#/";
194218822Sdim#define SVR4_COMMENT_CHARS 1
19560519Sobrien#define PREFIX_SEPARATOR '\\'
19633965Sjdp
197218822Sdim#else
198218822Sdimconst char *i386_comment_chars = "#";
199218822Sdim#define PREFIX_SEPARATOR '/'
200218822Sdim#endif
201218822Sdim
20233965Sjdp/* This array holds the chars that only start a comment at the beginning of
20333965Sjdp   a line.  If the line seems to have the form '# 123 filename'
20477311Sobrien   .line and .file directives will appear in the pre-processed output.
20577311Sobrien   Note that input_file.c hand checks for '#' at the beginning of the
20633965Sjdp   first line of the input file.  This is because the compiler outputs
20777311Sobrien   #NO_APP at the beginning of its output.
20877311Sobrien   Also note that comments started like this one will always work if
20933965Sjdp   '/' isn't otherwise defined.  */
210218822Sdimconst char line_comment_chars[] = "#/";
21194546Sobrien
21277311Sobrienconst char line_separator_chars[] = ";";
21333965Sjdp
21477311Sobrien/* Chars that can be used to separate mant from exp in floating point
21577311Sobrien   nums.  */
21633965Sjdpconst char EXP_CHARS[] = "eE";
21733965Sjdp
21877311Sobrien/* Chars that mean this number is a floating point constant
21977311Sobrien   As in 0f12.456
22077311Sobrien   or    0d1.2345e12.  */
22133965Sjdpconst char FLT_CHARS[] = "fFdDxX";
22233965Sjdp
22377311Sobrien/* Tables for lexical analysis.  */
22460519Sobrienstatic char mnemonic_chars[256];
22533965Sjdpstatic char register_chars[256];
22633965Sjdpstatic char operand_chars[256];
22733965Sjdpstatic char identifier_chars[256];
22833965Sjdpstatic char digit_chars[256];
22933965Sjdp
23077311Sobrien/* Lexical macros.  */
23160519Sobrien#define is_mnemonic_char(x) (mnemonic_chars[(unsigned char) x])
23233965Sjdp#define is_operand_char(x) (operand_chars[(unsigned char) x])
23333965Sjdp#define is_register_char(x) (register_chars[(unsigned char) x])
23460519Sobrien#define is_space_char(x) ((x) == ' ')
23533965Sjdp#define is_identifier_char(x) (identifier_chars[(unsigned char) x])
23633965Sjdp#define is_digit_char(x) (digit_chars[(unsigned char) x])
23733965Sjdp
238130570Sobrien/* All non-digit non-letter characters that may occur in an operand.  */
23933965Sjdpstatic char operand_special_chars[] = "%$-+(,)*._~/<>|&^!:[@]";
24033965Sjdp
24133965Sjdp/* md_assemble() always leaves the strings it's passed unaltered.  To
24233965Sjdp   effect this we maintain a stack of saved characters that we've smashed
24333965Sjdp   with '\0's (indicating end of strings for various sub-fields of the
24477311Sobrien   assembler instruction).  */
24533965Sjdpstatic char save_stack[32];
24677311Sobrienstatic char *save_stack_p;
24760519Sobrien#define END_STRING_AND_SAVE(s) \
24860519Sobrien	do { *save_stack_p++ = *(s); *(s) = '\0'; } while (0)
24960519Sobrien#define RESTORE_END_STRING(s) \
25060519Sobrien	do { *(s) = *--save_stack_p; } while (0)
25133965Sjdp
25277311Sobrien/* The instruction we're assembling.  */
25333965Sjdpstatic i386_insn i;
25433965Sjdp
25560519Sobrien/* Possible templates for current insn.  */
25660519Sobrienstatic const templates *current_templates;
25760519Sobrien
258218822Sdim/* Per instruction expressionS buffers: max displacements & immediates.  */
259218822Sdimstatic expressionS disp_expressions[MAX_MEMORY_OPERANDS];
260218822Sdimstatic expressionS im_expressions[MAX_IMMEDIATE_OPERANDS];
26133965Sjdp
26277311Sobrien/* Current operand we are working on.  */
26377311Sobrienstatic int this_operand;
26433965Sjdp
26577311Sobrien/* We support four different modes.  FLAG_CODE variable is used to distinguish
26677311Sobrien   these.  */
26733965Sjdp
26877311Sobrienenum flag_code {
26977311Sobrien	CODE_32BIT,
27077311Sobrien	CODE_16BIT,
27177311Sobrien	CODE_64BIT };
27278840Sobrien#define NUM_FLAG_CODE ((int) CODE_64BIT + 1)
27333965Sjdp
27477311Sobrienstatic enum flag_code flag_code;
275218822Sdimstatic unsigned int object_64bit;
27677311Sobrienstatic int use_rela_relocations = 0;
27760519Sobrien
27877311Sobrien/* The names used to print error messages.  */
27977311Sobrienstatic const char *flag_code_names[] =
28077311Sobrien  {
28177311Sobrien    "32",
28277311Sobrien    "16",
28377311Sobrien    "64"
28477311Sobrien  };
28560519Sobrien
28677311Sobrien/* 1 for intel syntax,
28777311Sobrien   0 if att syntax.  */
28877311Sobrienstatic int intel_syntax = 0;
28960519Sobrien
29077311Sobrien/* 1 if register prefix % not required.  */
29177311Sobrienstatic int allow_naked_reg = 0;
29277311Sobrien
293218822Sdim/* Register prefix used for error message.  */
294218822Sdimstatic const char *register_prefix = "%";
295218822Sdim
29677311Sobrien/* Used in 16 bit gcc mode to add an l suffix to call, ret, enter,
29777311Sobrien   leave, push, and pop instructions so that gcc has the same stack
29877311Sobrien   frame as in 32 bit mode.  */
29977311Sobrienstatic char stackop_size = '\0';
30077311Sobrien
301130570Sobrien/* Non-zero to optimize code alignment.  */
302130570Sobrienint optimize_align_code = 1;
303130570Sobrien
30477311Sobrien/* Non-zero to quieten some warnings.  */
30577311Sobrienstatic int quiet_warnings = 0;
30677311Sobrien
30777311Sobrien/* CPU name.  */
30877311Sobrienstatic const char *cpu_arch_name = NULL;
309218822Sdimstatic const char *cpu_sub_arch_name = NULL;
31077311Sobrien
31177311Sobrien/* CPU feature flags.  */
31294546Sobrienstatic unsigned int cpu_arch_flags = CpuUnknownFlags | CpuNo64;
31377311Sobrien
314218822Sdim/* If we have selected a cpu we are generating instructions for.  */
315218822Sdimstatic int cpu_arch_tune_set = 0;
316218822Sdim
317218822Sdim/* Cpu we are generating instructions for.  */
318218822Sdimstatic enum processor_type cpu_arch_tune = PROCESSOR_UNKNOWN;
319218822Sdim
320218822Sdim/* CPU feature flags of cpu we are generating instructions for.  */
321218822Sdimstatic unsigned int cpu_arch_tune_flags = 0;
322218822Sdim
323218822Sdim/* CPU instruction set architecture used.  */
324218822Sdimstatic enum processor_type cpu_arch_isa = PROCESSOR_UNKNOWN;
325218822Sdim
326218822Sdim/* CPU feature flags of instruction set architecture used.  */
327218822Sdimstatic unsigned int cpu_arch_isa_flags = 0;
328218822Sdim
32978840Sobrien/* If set, conditional jumps are not automatically promoted to handle
33078840Sobrien   larger than a byte offset.  */
33178840Sobrienstatic unsigned int no_cond_jump_promotion = 0;
33278840Sobrien
33394546Sobrien/* Pre-defined "_GLOBAL_OFFSET_TABLE_".  */
334218822Sdimstatic symbolS *GOT_symbol;
33594546Sobrien
336130570Sobrien/* The dwarf2 return column, adjusted for 32 or 64 bit.  */
337130570Sobrienunsigned int x86_dwarf2_return_column;
338130570Sobrien
339130570Sobrien/* The dwarf2 data alignment, adjusted for 32 or 64 bit.  */
340130570Sobrienint x86_cie_data_alignment;
341130570Sobrien
34233965Sjdp/* Interface to relax_segment.
34378840Sobrien   There are 3 major relax states for 386 jump insns because the
34478840Sobrien   different types of jumps add different sizes to frags when we're
34578840Sobrien   figuring out what sort of jump to choose to reach a given label.  */
34633965Sjdp
34777311Sobrien/* Types.  */
34878840Sobrien#define UNCOND_JUMP 0
34977311Sobrien#define COND_JUMP 1
35078840Sobrien#define COND_JUMP86 2
35178840Sobrien
35277311Sobrien/* Sizes.  */
35360519Sobrien#define CODE16	1
35460519Sobrien#define SMALL	0
35594546Sobrien#define SMALL16 (SMALL | CODE16)
35660519Sobrien#define BIG	2
35794546Sobrien#define BIG16	(BIG | CODE16)
35833965Sjdp
35933965Sjdp#ifndef INLINE
36033965Sjdp#ifdef __GNUC__
36133965Sjdp#define INLINE __inline__
36233965Sjdp#else
36333965Sjdp#define INLINE
36433965Sjdp#endif
36533965Sjdp#endif
36633965Sjdp
36778840Sobrien#define ENCODE_RELAX_STATE(type, size) \
36878840Sobrien  ((relax_substateT) (((type) << 2) | (size)))
36978840Sobrien#define TYPE_FROM_RELAX_STATE(s) \
37078840Sobrien  ((s) >> 2)
37178840Sobrien#define DISP_SIZE_FROM_RELAX_STATE(s) \
37278840Sobrien    ((((s) & 3) == BIG ? 4 : (((s) & 3) == BIG16 ? 2 : 1)))
37333965Sjdp
37460519Sobrien/* This table is used by relax_frag to promote short jumps to long
37560519Sobrien   ones where necessary.  SMALL (short) jumps may be promoted to BIG
37660519Sobrien   (32 bit long) ones, and SMALL16 jumps to BIG16 (16 bit long).  We
37760519Sobrien   don't allow a short jump in a 32 bit code segment to be promoted to
37860519Sobrien   a 16 bit offset jump because it's slower (requires data size
37960519Sobrien   prefix), and doesn't work, unless the destination is in the bottom
38060519Sobrien   64k of the code segment (The top 16 bits of eip are zeroed).  */
38160519Sobrien
38233965Sjdpconst relax_typeS md_relax_table[] =
38333965Sjdp{
38460519Sobrien  /* The fields are:
38560519Sobrien     1) most positive reach of this state,
38660519Sobrien     2) most negative reach of this state,
38778840Sobrien     3) how many bytes this mode will have in the variable part of the frag
38877311Sobrien     4) which index into the table to try if we can't fit into this one.  */
38933965Sjdp
39078840Sobrien  /* UNCOND_JUMP states.  */
39178840Sobrien  {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG)},
39278840Sobrien  {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16)},
39378840Sobrien  /* dword jmp adds 4 bytes to frag:
39478840Sobrien     0 extra opcode bytes, 4 displacement bytes.  */
39533965Sjdp  {0, 0, 4, 0},
39678840Sobrien  /* word jmp adds 2 byte2 to frag:
39778840Sobrien     0 extra opcode bytes, 2 displacement bytes.  */
39860519Sobrien  {0, 0, 2, 0},
39933965Sjdp
40078840Sobrien  /* COND_JUMP states.  */
40178840Sobrien  {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP, BIG)},
40278840Sobrien  {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP, BIG16)},
40378840Sobrien  /* dword conditionals adds 5 bytes to frag:
40478840Sobrien     1 extra opcode byte, 4 displacement bytes.  */
40578840Sobrien  {0, 0, 5, 0},
40678840Sobrien  /* word conditionals add 3 bytes to frag:
40778840Sobrien     1 extra opcode byte, 2 displacement bytes.  */
40833965Sjdp  {0, 0, 3, 0},
40933965Sjdp
41078840Sobrien  /* COND_JUMP86 states.  */
41178840Sobrien  {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP86, BIG)},
41278840Sobrien  {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP86, BIG16)},
41378840Sobrien  /* dword conditionals adds 5 bytes to frag:
41478840Sobrien     1 extra opcode byte, 4 displacement bytes.  */
41578840Sobrien  {0, 0, 5, 0},
41678840Sobrien  /* word conditionals add 4 bytes to frag:
41778840Sobrien     1 displacement byte and a 3 byte long branch insn.  */
41878840Sobrien  {0, 0, 4, 0}
41933965Sjdp};
42033965Sjdp
421218822Sdimstatic const arch_entry cpu_arch[] =
422218822Sdim{
423218822Sdim  {"generic32", PROCESSOR_GENERIC32,
424218822Sdim   Cpu186|Cpu286|Cpu386},
425218822Sdim  {"generic64", PROCESSOR_GENERIC64,
426218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX
427218822Sdim   |CpuMMX2|CpuSSE|CpuSSE2},
428218822Sdim  {"i8086", PROCESSOR_UNKNOWN,
429218822Sdim   0},
430218822Sdim  {"i186", PROCESSOR_UNKNOWN,
431218822Sdim   Cpu186},
432218822Sdim  {"i286", PROCESSOR_UNKNOWN,
433218822Sdim   Cpu186|Cpu286},
434218822Sdim  {"i386", PROCESSOR_GENERIC32,
435218822Sdim   Cpu186|Cpu286|Cpu386},
436218822Sdim  {"i486", PROCESSOR_I486,
437218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486},
438218822Sdim  {"i586", PROCESSOR_PENTIUM,
439218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586},
440218822Sdim  {"i686", PROCESSOR_PENTIUMPRO,
441218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686},
442218822Sdim  {"pentium", PROCESSOR_PENTIUM,
443218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586},
444218822Sdim  {"pentiumpro",PROCESSOR_PENTIUMPRO,
445218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686},
446218822Sdim  {"pentiumii",	PROCESSOR_PENTIUMPRO,
447218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX},
448218822Sdim  {"pentiumiii",PROCESSOR_PENTIUMPRO,
449218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX|CpuMMX2|CpuSSE},
450218822Sdim  {"pentium4", PROCESSOR_PENTIUM4,
451218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX
452218822Sdim   |CpuMMX2|CpuSSE|CpuSSE2},
453218822Sdim  {"prescott", PROCESSOR_NOCONA,
454218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX
455218822Sdim   |CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3},
456218822Sdim  {"nocona", PROCESSOR_NOCONA,
457218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX
458218822Sdim   |CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3},
459218822Sdim  {"yonah", PROCESSOR_CORE,
460218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX
461218822Sdim   |CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3},
462218822Sdim  {"core", PROCESSOR_CORE,
463218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX
464218822Sdim   |CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3},
465218822Sdim  {"merom", PROCESSOR_CORE2,
466218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX
467218822Sdim   |CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3},
468218822Sdim  {"core2", PROCESSOR_CORE2,
469218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX
470218822Sdim   |CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3},
471218822Sdim  {"k6", PROCESSOR_K6,
472218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuK6|CpuMMX},
473218822Sdim  {"k6_2", PROCESSOR_K6,
474218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuK6|CpuMMX|Cpu3dnow},
475218822Sdim  {"athlon", PROCESSOR_ATHLON,
476218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6
477218822Sdim   |CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA},
478218822Sdim  {"sledgehammer", PROCESSOR_K8,
479218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6
480218822Sdim   |CpuSledgehammer|CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2},
481218822Sdim  {"opteron", PROCESSOR_K8,
482218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6
483218822Sdim   |CpuSledgehammer|CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2},
484218822Sdim  {"k8", PROCESSOR_K8,
485218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6
486218822Sdim   |CpuSledgehammer|CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2},
487218822Sdim  {"amdfam10", PROCESSOR_AMDFAM10,
488218822Sdim   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuSledgehammer
489218822Sdim   |CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a
490218822Sdim   |CpuABM},
491218822Sdim  {".mmx", PROCESSOR_UNKNOWN,
492218822Sdim   CpuMMX},
493218822Sdim  {".sse", PROCESSOR_UNKNOWN,
494218822Sdim   CpuMMX|CpuMMX2|CpuSSE},
495218822Sdim  {".sse2", PROCESSOR_UNKNOWN,
496218822Sdim   CpuMMX|CpuMMX2|CpuSSE|CpuSSE2},
497218822Sdim  {".sse3", PROCESSOR_UNKNOWN,
498218822Sdim   CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3},
499218822Sdim  {".ssse3", PROCESSOR_UNKNOWN,
500218822Sdim   CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3},
501218822Sdim  {".sse4.1", PROCESSOR_UNKNOWN,
502218822Sdim   CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1},
503218822Sdim  {".sse4.2", PROCESSOR_UNKNOWN,
504218822Sdim   CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4},
505218822Sdim  {".sse4", PROCESSOR_UNKNOWN,
506218822Sdim   CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4},
507218822Sdim  {".3dnow", PROCESSOR_UNKNOWN,
508218822Sdim   CpuMMX|Cpu3dnow},
509218822Sdim  {".3dnowa", PROCESSOR_UNKNOWN,
510218822Sdim   CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA},
511218822Sdim  {".padlock", PROCESSOR_UNKNOWN,
512218822Sdim   CpuPadLock},
513218822Sdim  {".pacifica", PROCESSOR_UNKNOWN,
514218822Sdim   CpuSVME},
515218822Sdim  {".svme", PROCESSOR_UNKNOWN,
516218822Sdim   CpuSVME},
517218822Sdim  {".sse4a", PROCESSOR_UNKNOWN,
518218822Sdim   CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a},
519218822Sdim  {".abm", PROCESSOR_UNKNOWN,
520238123Sjhb   CpuABM},
521238123Sjhb  {".xsave", PROCESSOR_UNKNOWN,
522238123Sjhb   CpuXSAVE}
52377311Sobrien};
52433965Sjdp
52594546Sobrienconst pseudo_typeS md_pseudo_table[] =
52694546Sobrien{
52794546Sobrien#if !defined(OBJ_AOUT) && !defined(USE_ALIGN_PTWO)
52894546Sobrien  {"align", s_align_bytes, 0},
52994546Sobrien#else
53094546Sobrien  {"align", s_align_ptwo, 0},
53194546Sobrien#endif
53294546Sobrien  {"arch", set_cpu_arch, 0},
53394546Sobrien#ifndef I386COFF
53494546Sobrien  {"bss", s_bss, 0},
53594546Sobrien#endif
53694546Sobrien  {"ffloat", float_cons, 'f'},
53794546Sobrien  {"dfloat", float_cons, 'd'},
53894546Sobrien  {"tfloat", float_cons, 'x'},
53994546Sobrien  {"value", cons, 2},
540218822Sdim  {"slong", signed_cons, 4},
54194546Sobrien  {"noopt", s_ignore, 0},
54294546Sobrien  {"optim", s_ignore, 0},
54394546Sobrien  {"code16gcc", set_16bit_gcc_code_flag, CODE_16BIT},
54494546Sobrien  {"code16", set_code_flag, CODE_16BIT},
54594546Sobrien  {"code32", set_code_flag, CODE_32BIT},
54694546Sobrien  {"code64", set_code_flag, CODE_64BIT},
54794546Sobrien  {"intel_syntax", set_intel_syntax, 1},
54894546Sobrien  {"att_syntax", set_intel_syntax, 0},
549218822Sdim#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
550218822Sdim  {"largecomm", handle_large_common, 0},
551218822Sdim#else
552218822Sdim  {"file", (void (*) (int)) dwarf2_directive_file, 0},
55394546Sobrien  {"loc", dwarf2_directive_loc, 0},
554218822Sdim  {"loc_mark_labels", dwarf2_directive_loc_mark_labels, 0},
555218822Sdim#endif
556218822Sdim#ifdef TE_PE
557218822Sdim  {"secrel32", pe_directive_secrel, 0},
558218822Sdim#endif
55994546Sobrien  {0, 0, 0}
56094546Sobrien};
56194546Sobrien
56294546Sobrien/* For interface with expression ().  */
56394546Sobrienextern char *input_line_pointer;
56494546Sobrien
56594546Sobrien/* Hash table for instruction mnemonic lookup.  */
56694546Sobrienstatic struct hash_control *op_hash;
56794546Sobrien
56894546Sobrien/* Hash table for register lookup.  */
56994546Sobrienstatic struct hash_control *reg_hash;
57094546Sobrien
57133965Sjdpvoid
572218822Sdimi386_align_code (fragS *fragP, int count)
57333965Sjdp{
57477311Sobrien  /* Various efficient no-op patterns for aligning code labels.
57577311Sobrien     Note: Don't try to assemble the instructions in the comments.
57677311Sobrien     0L and 0w are not legal.  */
57733965Sjdp  static const char f32_1[] =
57833965Sjdp    {0x90};					/* nop			*/
57933965Sjdp  static const char f32_2[] =
580218822Sdim    {0x66,0x90};				/* xchg %ax,%ax */
58133965Sjdp  static const char f32_3[] =
58233965Sjdp    {0x8d,0x76,0x00};				/* leal 0(%esi),%esi	*/
58333965Sjdp  static const char f32_4[] =
58433965Sjdp    {0x8d,0x74,0x26,0x00};			/* leal 0(%esi,1),%esi	*/
58533965Sjdp  static const char f32_5[] =
58633965Sjdp    {0x90,					/* nop			*/
58733965Sjdp     0x8d,0x74,0x26,0x00};			/* leal 0(%esi,1),%esi	*/
58833965Sjdp  static const char f32_6[] =
58933965Sjdp    {0x8d,0xb6,0x00,0x00,0x00,0x00};		/* leal 0L(%esi),%esi	*/
59033965Sjdp  static const char f32_7[] =
59133965Sjdp    {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00};	/* leal 0L(%esi,1),%esi */
59233965Sjdp  static const char f32_8[] =
59333965Sjdp    {0x90,					/* nop			*/
59433965Sjdp     0x8d,0xb4,0x26,0x00,0x00,0x00,0x00};	/* leal 0L(%esi,1),%esi */
59533965Sjdp  static const char f32_9[] =
59633965Sjdp    {0x89,0xf6,					/* movl %esi,%esi	*/
59733965Sjdp     0x8d,0xbc,0x27,0x00,0x00,0x00,0x00};	/* leal 0L(%edi,1),%edi */
59833965Sjdp  static const char f32_10[] =
59933965Sjdp    {0x8d,0x76,0x00,				/* leal 0(%esi),%esi	*/
60033965Sjdp     0x8d,0xbc,0x27,0x00,0x00,0x00,0x00};	/* leal 0L(%edi,1),%edi */
60133965Sjdp  static const char f32_11[] =
60233965Sjdp    {0x8d,0x74,0x26,0x00,			/* leal 0(%esi,1),%esi	*/
60333965Sjdp     0x8d,0xbc,0x27,0x00,0x00,0x00,0x00};	/* leal 0L(%edi,1),%edi */
60433965Sjdp  static const char f32_12[] =
60533965Sjdp    {0x8d,0xb6,0x00,0x00,0x00,0x00,		/* leal 0L(%esi),%esi	*/
60633965Sjdp     0x8d,0xbf,0x00,0x00,0x00,0x00};		/* leal 0L(%edi),%edi	*/
60733965Sjdp  static const char f32_13[] =
60833965Sjdp    {0x8d,0xb6,0x00,0x00,0x00,0x00,		/* leal 0L(%esi),%esi	*/
60933965Sjdp     0x8d,0xbc,0x27,0x00,0x00,0x00,0x00};	/* leal 0L(%edi,1),%edi */
61033965Sjdp  static const char f32_14[] =
61133965Sjdp    {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00,	/* leal 0L(%esi,1),%esi */
61233965Sjdp     0x8d,0xbc,0x27,0x00,0x00,0x00,0x00};	/* leal 0L(%edi,1),%edi */
61333965Sjdp  static const char f32_15[] =
61433965Sjdp    {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90,	/* jmp .+15; lotsa nops	*/
61533965Sjdp     0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90};
61660519Sobrien  static const char f16_3[] =
61760519Sobrien    {0x8d,0x74,0x00};				/* lea 0(%esi),%esi	*/
61833965Sjdp  static const char f16_4[] =
61938891Sjdp    {0x8d,0xb4,0x00,0x00};			/* lea 0w(%si),%si	*/
62033965Sjdp  static const char f16_5[] =
62133965Sjdp    {0x90,					/* nop			*/
62238891Sjdp     0x8d,0xb4,0x00,0x00};			/* lea 0w(%si),%si	*/
62333965Sjdp  static const char f16_6[] =
62433965Sjdp    {0x89,0xf6,					/* mov %si,%si		*/
62533965Sjdp     0x8d,0xbd,0x00,0x00};			/* lea 0w(%di),%di	*/
62633965Sjdp  static const char f16_7[] =
62738891Sjdp    {0x8d,0x74,0x00,				/* lea 0(%si),%si	*/
62833965Sjdp     0x8d,0xbd,0x00,0x00};			/* lea 0w(%di),%di	*/
62933965Sjdp  static const char f16_8[] =
63038891Sjdp    {0x8d,0xb4,0x00,0x00,			/* lea 0w(%si),%si	*/
63133965Sjdp     0x8d,0xbd,0x00,0x00};			/* lea 0w(%di),%di	*/
63233965Sjdp  static const char *const f32_patt[] = {
63333965Sjdp    f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8,
63433965Sjdp    f32_9, f32_10, f32_11, f32_12, f32_13, f32_14, f32_15
63533965Sjdp  };
63633965Sjdp  static const char *const f16_patt[] = {
63760519Sobrien    f32_1, f32_2, f16_3, f16_4, f16_5, f16_6, f16_7, f16_8,
63833965Sjdp    f32_15, f32_15, f32_15, f32_15, f32_15, f32_15, f32_15
63933965Sjdp  };
640218822Sdim  /* nopl (%[re]ax) */
641218822Sdim  static const char alt_3[] =
642218822Sdim    {0x0f,0x1f,0x00};
643218822Sdim  /* nopl 0(%[re]ax) */
644218822Sdim  static const char alt_4[] =
645218822Sdim    {0x0f,0x1f,0x40,0x00};
646218822Sdim  /* nopl 0(%[re]ax,%[re]ax,1) */
647218822Sdim  static const char alt_5[] =
648218822Sdim    {0x0f,0x1f,0x44,0x00,0x00};
649218822Sdim  /* nopw 0(%[re]ax,%[re]ax,1) */
650218822Sdim  static const char alt_6[] =
651218822Sdim    {0x66,0x0f,0x1f,0x44,0x00,0x00};
652218822Sdim  /* nopl 0L(%[re]ax) */
653218822Sdim  static const char alt_7[] =
654218822Sdim    {0x0f,0x1f,0x80,0x00,0x00,0x00,0x00};
655218822Sdim  /* nopl 0L(%[re]ax,%[re]ax,1) */
656218822Sdim  static const char alt_8[] =
657218822Sdim    {0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
658218822Sdim  /* nopw 0L(%[re]ax,%[re]ax,1) */
659218822Sdim  static const char alt_9[] =
660218822Sdim    {0x66,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
661218822Sdim  /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
662218822Sdim  static const char alt_10[] =
663218822Sdim    {0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
664218822Sdim  /* data16
665218822Sdim     nopw %cs:0L(%[re]ax,%[re]ax,1) */
666218822Sdim  static const char alt_long_11[] =
667218822Sdim    {0x66,
668218822Sdim     0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
669218822Sdim  /* data16
670218822Sdim     data16
671218822Sdim     nopw %cs:0L(%[re]ax,%[re]ax,1) */
672218822Sdim  static const char alt_long_12[] =
673218822Sdim    {0x66,
674218822Sdim     0x66,
675218822Sdim     0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
676218822Sdim  /* data16
677218822Sdim     data16
678218822Sdim     data16
679218822Sdim     nopw %cs:0L(%[re]ax,%[re]ax,1) */
680218822Sdim  static const char alt_long_13[] =
681218822Sdim    {0x66,
682218822Sdim     0x66,
683218822Sdim     0x66,
684218822Sdim     0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
685218822Sdim  /* data16
686218822Sdim     data16
687218822Sdim     data16
688218822Sdim     data16
689218822Sdim     nopw %cs:0L(%[re]ax,%[re]ax,1) */
690218822Sdim  static const char alt_long_14[] =
691218822Sdim    {0x66,
692218822Sdim     0x66,
693218822Sdim     0x66,
694218822Sdim     0x66,
695218822Sdim     0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
696218822Sdim  /* data16
697218822Sdim     data16
698218822Sdim     data16
699218822Sdim     data16
700218822Sdim     data16
701218822Sdim     nopw %cs:0L(%[re]ax,%[re]ax,1) */
702218822Sdim  static const char alt_long_15[] =
703218822Sdim    {0x66,
704218822Sdim     0x66,
705218822Sdim     0x66,
706218822Sdim     0x66,
707218822Sdim     0x66,
708218822Sdim     0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
709218822Sdim  /* nopl 0(%[re]ax,%[re]ax,1)
710218822Sdim     nopw 0(%[re]ax,%[re]ax,1) */
711218822Sdim  static const char alt_short_11[] =
712218822Sdim    {0x0f,0x1f,0x44,0x00,0x00,
713218822Sdim     0x66,0x0f,0x1f,0x44,0x00,0x00};
714218822Sdim  /* nopw 0(%[re]ax,%[re]ax,1)
715218822Sdim     nopw 0(%[re]ax,%[re]ax,1) */
716218822Sdim  static const char alt_short_12[] =
717218822Sdim    {0x66,0x0f,0x1f,0x44,0x00,0x00,
718218822Sdim     0x66,0x0f,0x1f,0x44,0x00,0x00};
719218822Sdim  /* nopw 0(%[re]ax,%[re]ax,1)
720218822Sdim     nopl 0L(%[re]ax) */
721218822Sdim  static const char alt_short_13[] =
722218822Sdim    {0x66,0x0f,0x1f,0x44,0x00,0x00,
723218822Sdim     0x0f,0x1f,0x80,0x00,0x00,0x00,0x00};
724218822Sdim  /* nopl 0L(%[re]ax)
725218822Sdim     nopl 0L(%[re]ax) */
726218822Sdim  static const char alt_short_14[] =
727218822Sdim    {0x0f,0x1f,0x80,0x00,0x00,0x00,0x00,
728218822Sdim     0x0f,0x1f,0x80,0x00,0x00,0x00,0x00};
729218822Sdim  /* nopl 0L(%[re]ax)
730218822Sdim     nopl 0L(%[re]ax,%[re]ax,1) */
731218822Sdim  static const char alt_short_15[] =
732218822Sdim    {0x0f,0x1f,0x80,0x00,0x00,0x00,0x00,
733218822Sdim     0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
734218822Sdim  static const char *const alt_short_patt[] = {
735218822Sdim    f32_1, f32_2, alt_3, alt_4, alt_5, alt_6, alt_7, alt_8,
736218822Sdim    alt_9, alt_10, alt_short_11, alt_short_12, alt_short_13,
737218822Sdim    alt_short_14, alt_short_15
738218822Sdim  };
739218822Sdim  static const char *const alt_long_patt[] = {
740218822Sdim    f32_1, f32_2, alt_3, alt_4, alt_5, alt_6, alt_7, alt_8,
741218822Sdim    alt_9, alt_10, alt_long_11, alt_long_12, alt_long_13,
742218822Sdim    alt_long_14, alt_long_15
743218822Sdim  };
74433965Sjdp
745130570Sobrien  if (count <= 0 || count > 15)
746130570Sobrien    return;
747130570Sobrien
748218822Sdim  /* We need to decide which NOP sequence to use for 32bit and
749218822Sdim     64bit. When -mtune= is used:
750218822Sdim
751218822Sdim     1. For PROCESSOR_I486, PROCESSOR_PENTIUM and PROCESSOR_GENERIC32,
752218822Sdim     f32_patt will be used.
753218822Sdim     2. For PROCESSOR_K8 and PROCESSOR_AMDFAM10 in 64bit, NOPs with
754218822Sdim     0x66 prefix will be used.
755218822Sdim     3. For PROCESSOR_CORE2, alt_long_patt will be used.
756218822Sdim     4. For PROCESSOR_PENTIUMPRO, PROCESSOR_PENTIUM4, PROCESSOR_NOCONA,
757218822Sdim     PROCESSOR_CORE, PROCESSOR_CORE2, PROCESSOR_K6, PROCESSOR_ATHLON
758218822Sdim     and PROCESSOR_GENERIC64, alt_short_patt will be used.
759218822Sdim
760218822Sdim     When -mtune= isn't used, alt_short_patt will be used if
761218822Sdim     cpu_arch_isa_flags has Cpu686. Otherwise, f32_patt will be used.
762218822Sdim
763218822Sdim     When -march= or .arch is used, we can't use anything beyond
764218822Sdim     cpu_arch_isa_flags.   */
765218822Sdim
766218822Sdim  if (flag_code == CODE_16BIT)
767130570Sobrien    {
768218822Sdim      memcpy (fragP->fr_literal + fragP->fr_fix,
769218822Sdim	      f16_patt[count - 1], count);
770218822Sdim      if (count > 8)
771218822Sdim	/* Adjust jump offset.  */
772218822Sdim	fragP->fr_literal[fragP->fr_fix + 1] = count - 2;
773218822Sdim    }
774218822Sdim  else if (flag_code == CODE_64BIT && cpu_arch_tune == PROCESSOR_K8)
775218822Sdim    {
776130570Sobrien      int i;
777130570Sobrien      int nnops = (count + 3) / 4;
778130570Sobrien      int len = count / nnops;
779130570Sobrien      int remains = count - nnops * len;
780130570Sobrien      int pos = 0;
78177311Sobrien
782218822Sdim      /* The recommended way to pad 64bit code is to use NOPs preceded
783218822Sdim	 by maximally four 0x66 prefixes.  Balance the size of nops.  */
784130570Sobrien      for (i = 0; i < remains; i++)
78533965Sjdp	{
786130570Sobrien	  memset (fragP->fr_literal + fragP->fr_fix + pos, 0x66, len);
787130570Sobrien	  fragP->fr_literal[fragP->fr_fix + pos + len] = 0x90;
788130570Sobrien	  pos += len + 1;
78933965Sjdp	}
790130570Sobrien      for (; i < nnops; i++)
791130570Sobrien	{
792130570Sobrien	  memset (fragP->fr_literal + fragP->fr_fix + pos, 0x66, len - 1);
793130570Sobrien	  fragP->fr_literal[fragP->fr_fix + pos + len - 1] = 0x90;
794130570Sobrien	  pos += len;
795130570Sobrien	}
796130570Sobrien    }
797130570Sobrien  else
798218822Sdim    {
799218822Sdim      const char *const *patt = NULL;
800218822Sdim
801218822Sdim      if (cpu_arch_isa == PROCESSOR_UNKNOWN)
802218822Sdim	{
803218822Sdim	  /* PROCESSOR_UNKNOWN means that all ISAs may be used.  */
804218822Sdim	  switch (cpu_arch_tune)
805218822Sdim	    {
806218822Sdim	    case PROCESSOR_UNKNOWN:
807218822Sdim	      /* We use cpu_arch_isa_flags to check if we SHOULD
808218822Sdim		 optimize for Cpu686.  */
809218822Sdim	      if ((cpu_arch_isa_flags & Cpu686) != 0)
810218822Sdim		patt = alt_short_patt;
811218822Sdim	      else
812218822Sdim		patt = f32_patt;
813218822Sdim	      break;
814218822Sdim	    case PROCESSOR_CORE2:
815218822Sdim	      patt = alt_long_patt;
816218822Sdim	      break;
817218822Sdim	    case PROCESSOR_PENTIUMPRO:
818218822Sdim	    case PROCESSOR_PENTIUM4:
819218822Sdim	    case PROCESSOR_NOCONA:
820218822Sdim	    case PROCESSOR_CORE:
821218822Sdim	    case PROCESSOR_K6:
822218822Sdim	    case PROCESSOR_ATHLON:
823218822Sdim	    case PROCESSOR_K8:
824218822Sdim	    case PROCESSOR_GENERIC64:
825218822Sdim	    case PROCESSOR_AMDFAM10:
826218822Sdim	      patt = alt_short_patt;
827218822Sdim	      break;
828218822Sdim	    case PROCESSOR_I486:
829218822Sdim	    case PROCESSOR_PENTIUM:
830218822Sdim	    case PROCESSOR_GENERIC32:
831218822Sdim	      patt = f32_patt;
832218822Sdim	      break;
833218822Sdim	    }
834218822Sdim	}
835218822Sdim      else
836218822Sdim	{
837218822Sdim	  switch (cpu_arch_tune)
838218822Sdim	    {
839218822Sdim	    case PROCESSOR_UNKNOWN:
840218822Sdim	      /* When cpu_arch_isa is net, cpu_arch_tune shouldn't be
841218822Sdim		 PROCESSOR_UNKNOWN.  */
842218822Sdim	      abort ();
843218822Sdim	      break;
844218822Sdim
845218822Sdim	    case PROCESSOR_I486:
846218822Sdim	    case PROCESSOR_PENTIUM:
847218822Sdim	    case PROCESSOR_PENTIUMPRO:
848218822Sdim	    case PROCESSOR_PENTIUM4:
849218822Sdim	    case PROCESSOR_NOCONA:
850218822Sdim	    case PROCESSOR_CORE:
851218822Sdim	    case PROCESSOR_K6:
852218822Sdim	    case PROCESSOR_ATHLON:
853218822Sdim	    case PROCESSOR_K8:
854218822Sdim	    case PROCESSOR_AMDFAM10:
855218822Sdim	    case PROCESSOR_GENERIC32:
856218822Sdim	      /* We use cpu_arch_isa_flags to check if we CAN optimize
857218822Sdim		 for Cpu686.  */
858218822Sdim	      if ((cpu_arch_isa_flags & Cpu686) != 0)
859218822Sdim		patt = alt_short_patt;
860218822Sdim	      else
861218822Sdim		patt = f32_patt;
862218822Sdim	      break;
863218822Sdim	    case PROCESSOR_CORE2:
864218822Sdim	      if ((cpu_arch_isa_flags & Cpu686) != 0)
865218822Sdim		patt = alt_long_patt;
866218822Sdim	      else
867218822Sdim		patt = f32_patt;
868218822Sdim	      break;
869218822Sdim	    case PROCESSOR_GENERIC64:
870218822Sdim	      patt = alt_short_patt;
871218822Sdim	      break;
872218822Sdim	    }
873218822Sdim	}
874218822Sdim
875130570Sobrien      memcpy (fragP->fr_literal + fragP->fr_fix,
876218822Sdim	      patt[count - 1], count);
877218822Sdim    }
878130570Sobrien  fragP->fr_var = count;
87933965Sjdp}
88033965Sjdp
88160519Sobrienstatic INLINE unsigned int
882218822Sdimmode_from_disp_size (unsigned int t)
88333965Sjdp{
88477311Sobrien  return (t & Disp8) ? 1 : (t & (Disp16 | Disp32 | Disp32S)) ? 2 : 0;
88533965Sjdp}
88633965Sjdp
88733965Sjdpstatic INLINE int
888218822Sdimfits_in_signed_byte (offsetT num)
88933965Sjdp{
89033965Sjdp  return (num >= -128) && (num <= 127);
89177311Sobrien}
89233965Sjdp
89333965Sjdpstatic INLINE int
894218822Sdimfits_in_unsigned_byte (offsetT num)
89533965Sjdp{
89633965Sjdp  return (num & 0xff) == num;
89777311Sobrien}
89833965Sjdp
89933965Sjdpstatic INLINE int
900218822Sdimfits_in_unsigned_word (offsetT num)
90133965Sjdp{
90233965Sjdp  return (num & 0xffff) == num;
90377311Sobrien}
90433965Sjdp
90533965Sjdpstatic INLINE int
906218822Sdimfits_in_signed_word (offsetT num)
90733965Sjdp{
90833965Sjdp  return (-32768 <= num) && (num <= 32767);
90977311Sobrien}
910218822Sdim
91177311Sobrienstatic INLINE int
912218822Sdimfits_in_signed_long (offsetT num ATTRIBUTE_UNUSED)
91377311Sobrien{
91477311Sobrien#ifndef BFD64
91577311Sobrien  return 1;
91677311Sobrien#else
917286519Sdim  return (!(-((offsetT) 1 << 31) & num)
918286519Sdim	  || (-((offsetT) 1 << 31) & num) == -((offsetT) 1 << 31));
91977311Sobrien#endif
92077311Sobrien}				/* fits_in_signed_long() */
921218822Sdim
92277311Sobrienstatic INLINE int
923218822Sdimfits_in_unsigned_long (offsetT num ATTRIBUTE_UNUSED)
92477311Sobrien{
92577311Sobrien#ifndef BFD64
92677311Sobrien  return 1;
92777311Sobrien#else
92877311Sobrien  return (num & (((offsetT) 2 << 31) - 1)) == num;
92977311Sobrien#endif
93077311Sobrien}				/* fits_in_unsigned_long() */
93133965Sjdp
932218822Sdimstatic unsigned int
933218822Sdimsmallest_imm_type (offsetT num)
93433965Sjdp{
935218822Sdim  if (cpu_arch_flags != (Cpu186 | Cpu286 | Cpu386 | Cpu486 | CpuNo64))
93677311Sobrien    {
93777311Sobrien      /* This code is disabled on the 486 because all the Imm1 forms
93877311Sobrien	 in the opcode table are slower on the i486.  They're the
93977311Sobrien	 versions with the implicitly specified single-position
94077311Sobrien	 displacement, which has another syntax if you really want to
94177311Sobrien	 use that form.  */
94277311Sobrien      if (num == 1)
94377311Sobrien	return Imm1 | Imm8 | Imm8S | Imm16 | Imm32 | Imm32S | Imm64;
94477311Sobrien    }
94533965Sjdp  return (fits_in_signed_byte (num)
94677311Sobrien	  ? (Imm8S | Imm8 | Imm16 | Imm32 | Imm32S | Imm64)
94733965Sjdp	  : fits_in_unsigned_byte (num)
94877311Sobrien	  ? (Imm8 | Imm16 | Imm32 | Imm32S | Imm64)
94933965Sjdp	  : (fits_in_signed_word (num) || fits_in_unsigned_word (num))
95077311Sobrien	  ? (Imm16 | Imm32 | Imm32S | Imm64)
95177311Sobrien	  : fits_in_signed_long (num)
95277311Sobrien	  ? (Imm32 | Imm32S | Imm64)
95377311Sobrien	  : fits_in_unsigned_long (num)
95477311Sobrien	  ? (Imm32 | Imm64)
95577311Sobrien	  : Imm64);
95677311Sobrien}
95733965Sjdp
95877311Sobrienstatic offsetT
959218822Sdimoffset_in_range (offsetT val, int size)
96077311Sobrien{
96177311Sobrien  addressT mask;
96277311Sobrien
96377311Sobrien  switch (size)
96477311Sobrien    {
96577311Sobrien    case 1: mask = ((addressT) 1 <<  8) - 1; break;
96677311Sobrien    case 2: mask = ((addressT) 1 << 16) - 1; break;
96777311Sobrien    case 4: mask = ((addressT) 2 << 31) - 1; break;
96877311Sobrien#ifdef BFD64
96977311Sobrien    case 8: mask = ((addressT) 2 << 63) - 1; break;
97077311Sobrien#endif
97177311Sobrien    default: abort ();
97277311Sobrien    }
97377311Sobrien
97477311Sobrien  /* If BFD64, sign extend val.  */
97577311Sobrien  if (!use_rela_relocations)
97677311Sobrien    if ((val & ~(((addressT) 2 << 31) - 1)) == 0)
97777311Sobrien      val = (val ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31);
97877311Sobrien
97977311Sobrien  if ((val & ~mask) != 0 && (val & ~mask) != ~mask)
98077311Sobrien    {
98177311Sobrien      char buf1[40], buf2[40];
98277311Sobrien
98377311Sobrien      sprint_value (buf1, val);
98477311Sobrien      sprint_value (buf2, val & mask);
98577311Sobrien      as_warn (_("%s shortened to %s"), buf1, buf2);
98677311Sobrien    }
98777311Sobrien  return val & mask;
98877311Sobrien}
98977311Sobrien
99060519Sobrien/* Returns 0 if attempting to add a prefix where one from the same
99160519Sobrien   class already exists, 1 if non rep/repne added, 2 if rep/repne
99260519Sobrien   added.  */
99360519Sobrienstatic int
994218822Sdimadd_prefix (unsigned int prefix)
99560519Sobrien{
99660519Sobrien  int ret = 1;
997218822Sdim  unsigned int q;
99860519Sobrien
99994546Sobrien  if (prefix >= REX_OPCODE && prefix < REX_OPCODE + 16
100094546Sobrien      && flag_code == CODE_64BIT)
1001218822Sdim    {
1002218822Sdim      if ((i.prefix[REX_PREFIX] & prefix & REX_W)
1003218822Sdim	  || ((i.prefix[REX_PREFIX] & (REX_R | REX_X | REX_B))
1004218822Sdim	      && (prefix & (REX_R | REX_X | REX_B))))
1005218822Sdim	ret = 0;
1006218822Sdim      q = REX_PREFIX;
1007218822Sdim    }
100877311Sobrien  else
1009218822Sdim    {
1010218822Sdim      switch (prefix)
1011218822Sdim	{
1012218822Sdim	default:
1013218822Sdim	  abort ();
101460519Sobrien
1015218822Sdim	case CS_PREFIX_OPCODE:
1016218822Sdim	case DS_PREFIX_OPCODE:
1017218822Sdim	case ES_PREFIX_OPCODE:
1018218822Sdim	case FS_PREFIX_OPCODE:
1019218822Sdim	case GS_PREFIX_OPCODE:
1020218822Sdim	case SS_PREFIX_OPCODE:
1021218822Sdim	  q = SEG_PREFIX;
1022218822Sdim	  break;
102360519Sobrien
1024218822Sdim	case REPNE_PREFIX_OPCODE:
1025218822Sdim	case REPE_PREFIX_OPCODE:
1026218822Sdim	  ret = 2;
1027218822Sdim	  /* fall thru */
1028218822Sdim	case LOCK_PREFIX_OPCODE:
1029218822Sdim	  q = LOCKREP_PREFIX;
1030218822Sdim	  break;
103160519Sobrien
1032218822Sdim	case FWAIT_OPCODE:
1033218822Sdim	  q = WAIT_PREFIX;
1034218822Sdim	  break;
103560519Sobrien
1036218822Sdim	case ADDR_PREFIX_OPCODE:
1037218822Sdim	  q = ADDR_PREFIX;
1038218822Sdim	  break;
103960519Sobrien
1040218822Sdim	case DATA_PREFIX_OPCODE:
1041218822Sdim	  q = DATA_PREFIX;
1042218822Sdim	  break;
1043218822Sdim	}
1044218822Sdim      if (i.prefix[q] != 0)
1045218822Sdim	ret = 0;
1046218822Sdim    }
104760519Sobrien
1048218822Sdim  if (ret)
104960519Sobrien    {
1050218822Sdim      if (!i.prefix[q])
1051218822Sdim	++i.prefixes;
1052218822Sdim      i.prefix[q] |= prefix;
105360519Sobrien    }
1054218822Sdim  else
1055218822Sdim    as_bad (_("same type of prefix used twice"));
105660519Sobrien
105760519Sobrien  return ret;
105860519Sobrien}
105960519Sobrien
106033965Sjdpstatic void
1061218822Sdimset_code_flag (int value)
106233965Sjdp{
106377311Sobrien  flag_code = value;
106477311Sobrien  cpu_arch_flags &= ~(Cpu64 | CpuNo64);
106577311Sobrien  cpu_arch_flags |= (flag_code == CODE_64BIT ? Cpu64 : CpuNo64);
106677311Sobrien  if (value == CODE_64BIT && !(cpu_arch_flags & CpuSledgehammer))
106777311Sobrien    {
106877311Sobrien      as_bad (_("64bit mode not supported on this CPU."));
106977311Sobrien    }
107077311Sobrien  if (value == CODE_32BIT && !(cpu_arch_flags & Cpu386))
107177311Sobrien    {
107277311Sobrien      as_bad (_("32bit mode not supported on this CPU."));
107377311Sobrien    }
107460519Sobrien  stackop_size = '\0';
107533965Sjdp}
107633965Sjdp
107760519Sobrienstatic void
1078218822Sdimset_16bit_gcc_code_flag (int new_code_flag)
107960519Sobrien{
108077311Sobrien  flag_code = new_code_flag;
108177311Sobrien  cpu_arch_flags &= ~(Cpu64 | CpuNo64);
108277311Sobrien  cpu_arch_flags |= (flag_code == CODE_64BIT ? Cpu64 : CpuNo64);
1083218822Sdim  stackop_size = LONG_MNEM_SUFFIX;
108460519Sobrien}
108560519Sobrien
108660519Sobrienstatic void
1087218822Sdimset_intel_syntax (int syntax_flag)
108860519Sobrien{
108960519Sobrien  /* Find out if register prefixing is specified.  */
109060519Sobrien  int ask_naked_reg = 0;
109160519Sobrien
109260519Sobrien  SKIP_WHITESPACE ();
109394546Sobrien  if (!is_end_of_line[(unsigned char) *input_line_pointer])
109460519Sobrien    {
109560519Sobrien      char *string = input_line_pointer;
109660519Sobrien      int e = get_symbol_end ();
109760519Sobrien
109877311Sobrien      if (strcmp (string, "prefix") == 0)
109960519Sobrien	ask_naked_reg = 1;
110077311Sobrien      else if (strcmp (string, "noprefix") == 0)
110160519Sobrien	ask_naked_reg = -1;
110260519Sobrien      else
110360519Sobrien	as_bad (_("bad argument to syntax directive."));
110460519Sobrien      *input_line_pointer = e;
110560519Sobrien    }
110660519Sobrien  demand_empty_rest_of_line ();
110760519Sobrien
110860519Sobrien  intel_syntax = syntax_flag;
110960519Sobrien
111060519Sobrien  if (ask_naked_reg == 0)
1111130570Sobrien    allow_naked_reg = (intel_syntax
1112130570Sobrien		       && (bfd_get_symbol_leading_char (stdoutput) != '\0'));
111360519Sobrien  else
111460519Sobrien    allow_naked_reg = (ask_naked_reg < 0);
1115218822Sdim
1116218822Sdim  identifier_chars['%'] = intel_syntax && allow_naked_reg ? '%' : 0;
1117218822Sdim  identifier_chars['$'] = intel_syntax ? '$' : 0;
1118218822Sdim  register_prefix = allow_naked_reg ? "" : "%";
111960519Sobrien}
112060519Sobrien
112177311Sobrienstatic void
1122218822Sdimset_cpu_arch (int dummy ATTRIBUTE_UNUSED)
112377311Sobrien{
112477311Sobrien  SKIP_WHITESPACE ();
112577311Sobrien
112694546Sobrien  if (!is_end_of_line[(unsigned char) *input_line_pointer])
112777311Sobrien    {
112877311Sobrien      char *string = input_line_pointer;
112977311Sobrien      int e = get_symbol_end ();
1130218822Sdim      unsigned int i;
113177311Sobrien
1132218822Sdim      for (i = 0; i < ARRAY_SIZE (cpu_arch); i++)
113377311Sobrien	{
113477311Sobrien	  if (strcmp (string, cpu_arch[i].name) == 0)
113577311Sobrien	    {
1136218822Sdim	      if (*string != '.')
1137218822Sdim		{
1138218822Sdim		  cpu_arch_name = cpu_arch[i].name;
1139218822Sdim		  cpu_sub_arch_name = NULL;
1140218822Sdim		  cpu_arch_flags = (cpu_arch[i].flags
1141218822Sdim				    | (flag_code == CODE_64BIT
1142218822Sdim				       ? Cpu64 : CpuNo64));
1143218822Sdim		  cpu_arch_isa = cpu_arch[i].type;
1144218822Sdim		  cpu_arch_isa_flags = cpu_arch[i].flags;
1145218822Sdim		  if (!cpu_arch_tune_set)
1146218822Sdim		    {
1147218822Sdim		      cpu_arch_tune = cpu_arch_isa;
1148218822Sdim		      cpu_arch_tune_flags = cpu_arch_isa_flags;
1149218822Sdim		    }
1150218822Sdim		  break;
1151218822Sdim		}
1152218822Sdim	      if ((cpu_arch_flags | cpu_arch[i].flags) != cpu_arch_flags)
1153218822Sdim		{
1154218822Sdim		  cpu_sub_arch_name = cpu_arch[i].name;
1155218822Sdim		  cpu_arch_flags |= cpu_arch[i].flags;
1156218822Sdim		}
1157218822Sdim	      *input_line_pointer = e;
1158218822Sdim	      demand_empty_rest_of_line ();
1159218822Sdim	      return;
116077311Sobrien	    }
116177311Sobrien	}
1162218822Sdim      if (i >= ARRAY_SIZE (cpu_arch))
116377311Sobrien	as_bad (_("no such architecture: `%s'"), string);
116477311Sobrien
116577311Sobrien      *input_line_pointer = e;
116677311Sobrien    }
116777311Sobrien  else
116877311Sobrien    as_bad (_("missing cpu architecture"));
116977311Sobrien
117078840Sobrien  no_cond_jump_promotion = 0;
117178840Sobrien  if (*input_line_pointer == ','
117294546Sobrien      && !is_end_of_line[(unsigned char) input_line_pointer[1]])
117378840Sobrien    {
117478840Sobrien      char *string = ++input_line_pointer;
117578840Sobrien      int e = get_symbol_end ();
117678840Sobrien
117778840Sobrien      if (strcmp (string, "nojumps") == 0)
117878840Sobrien	no_cond_jump_promotion = 1;
117978840Sobrien      else if (strcmp (string, "jumps") == 0)
118078840Sobrien	;
118178840Sobrien      else
118278840Sobrien	as_bad (_("no such architecture modifier: `%s'"), string);
118378840Sobrien
118478840Sobrien      *input_line_pointer = e;
118578840Sobrien    }
118678840Sobrien
118777311Sobrien  demand_empty_rest_of_line ();
118877311Sobrien}
118977311Sobrien
119077311Sobrienunsigned long
119177311Sobrieni386_mach ()
119277311Sobrien{
119377311Sobrien  if (!strcmp (default_arch, "x86_64"))
119477311Sobrien    return bfd_mach_x86_64;
119577311Sobrien  else if (!strcmp (default_arch, "i386"))
119677311Sobrien    return bfd_mach_i386_i386;
119777311Sobrien  else
119877311Sobrien    as_fatal (_("Unknown architecture"));
119977311Sobrien}
120077311Sobrien
120133965Sjdpvoid
120233965Sjdpmd_begin ()
120333965Sjdp{
120433965Sjdp  const char *hash_err;
120533965Sjdp
120677311Sobrien  /* Initialize op_hash hash table.  */
120733965Sjdp  op_hash = hash_new ();
120833965Sjdp
120933965Sjdp  {
121094546Sobrien    const template *optab;
121194546Sobrien    templates *core_optab;
121233965Sjdp
121377311Sobrien    /* Setup for loop.  */
121477311Sobrien    optab = i386_optab;
121533965Sjdp    core_optab = (templates *) xmalloc (sizeof (templates));
121660519Sobrien    core_optab->start = optab;
121733965Sjdp
121860519Sobrien    while (1)
121933965Sjdp      {
122060519Sobrien	++optab;
122160519Sobrien	if (optab->name == NULL
122260519Sobrien	    || strcmp (optab->name, (optab - 1)->name) != 0)
122333965Sjdp	  {
122433965Sjdp	    /* different name --> ship out current template list;
122577311Sobrien	       add to hash table; & begin anew.  */
122660519Sobrien	    core_optab->end = optab;
122760519Sobrien	    hash_err = hash_insert (op_hash,
122860519Sobrien				    (optab - 1)->name,
122960519Sobrien				    (PTR) core_optab);
123033965Sjdp	    if (hash_err)
123133965Sjdp	      {
123260519Sobrien		as_fatal (_("Internal Error:  Can't hash %s: %s"),
123360519Sobrien			  (optab - 1)->name,
123433965Sjdp			  hash_err);
123533965Sjdp	      }
123660519Sobrien	    if (optab->name == NULL)
123760519Sobrien	      break;
123833965Sjdp	    core_optab = (templates *) xmalloc (sizeof (templates));
123960519Sobrien	    core_optab->start = optab;
124033965Sjdp	  }
124133965Sjdp      }
124233965Sjdp  }
124333965Sjdp
124477311Sobrien  /* Initialize reg_hash hash table.  */
124533965Sjdp  reg_hash = hash_new ();
124633965Sjdp  {
124794546Sobrien    const reg_entry *regtab;
1248218822Sdim    unsigned int regtab_size = i386_regtab_size;
124933965Sjdp
1250218822Sdim    for (regtab = i386_regtab; regtab_size--; regtab++)
125133965Sjdp      {
125233965Sjdp	hash_err = hash_insert (reg_hash, regtab->reg_name, (PTR) regtab);
125333965Sjdp	if (hash_err)
125477311Sobrien	  as_fatal (_("Internal Error:  Can't hash %s: %s"),
125577311Sobrien		    regtab->reg_name,
125677311Sobrien		    hash_err);
125733965Sjdp      }
125833965Sjdp  }
125933965Sjdp
126077311Sobrien  /* Fill in lexical tables:  mnemonic_chars, operand_chars.  */
126133965Sjdp  {
126294546Sobrien    int c;
126394546Sobrien    char *p;
126433965Sjdp
126533965Sjdp    for (c = 0; c < 256; c++)
126633965Sjdp      {
126789867Sobrien	if (ISDIGIT (c))
126833965Sjdp	  {
126960519Sobrien	    digit_chars[c] = c;
127060519Sobrien	    mnemonic_chars[c] = c;
127133965Sjdp	    register_chars[c] = c;
127260519Sobrien	    operand_chars[c] = c;
127333965Sjdp	  }
127489867Sobrien	else if (ISLOWER (c))
127533965Sjdp	  {
127660519Sobrien	    mnemonic_chars[c] = c;
127760519Sobrien	    register_chars[c] = c;
127860519Sobrien	    operand_chars[c] = c;
127933965Sjdp	  }
128089867Sobrien	else if (ISUPPER (c))
128133965Sjdp	  {
128289867Sobrien	    mnemonic_chars[c] = TOLOWER (c);
128360519Sobrien	    register_chars[c] = mnemonic_chars[c];
128460519Sobrien	    operand_chars[c] = c;
128533965Sjdp	  }
128660519Sobrien
128789867Sobrien	if (ISALPHA (c) || ISDIGIT (c))
128860519Sobrien	  identifier_chars[c] = c;
128960519Sobrien	else if (c >= 128)
129033965Sjdp	  {
129160519Sobrien	    identifier_chars[c] = c;
129260519Sobrien	    operand_chars[c] = c;
129333965Sjdp	  }
129460519Sobrien      }
129533965Sjdp
129633965Sjdp#ifdef LEX_AT
129760519Sobrien    identifier_chars['@'] = '@';
129833965Sjdp#endif
1299218822Sdim#ifdef LEX_QM
1300218822Sdim    identifier_chars['?'] = '?';
1301218822Sdim    operand_chars['?'] = '?';
1302218822Sdim#endif
130360519Sobrien    digit_chars['-'] = '-';
1304218822Sdim    mnemonic_chars['-'] = '-';
1305218822Sdim    mnemonic_chars['.'] = '.';
130660519Sobrien    identifier_chars['_'] = '_';
130760519Sobrien    identifier_chars['.'] = '.';
130833965Sjdp
130933965Sjdp    for (p = operand_special_chars; *p != '\0'; p++)
131033965Sjdp      operand_chars[(unsigned char) *p] = *p;
131133965Sjdp  }
131233965Sjdp
131333965Sjdp#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
1314218822Sdim  if (IS_ELF)
131533965Sjdp    {
131633965Sjdp      record_alignment (text_section, 2);
131733965Sjdp      record_alignment (data_section, 2);
131833965Sjdp      record_alignment (bss_section, 2);
131933965Sjdp    }
132033965Sjdp#endif
1321130570Sobrien
1322130570Sobrien  if (flag_code == CODE_64BIT)
1323130570Sobrien    {
1324130570Sobrien      x86_dwarf2_return_column = 16;
1325130570Sobrien      x86_cie_data_alignment = -8;
1326130570Sobrien    }
1327130570Sobrien  else
1328130570Sobrien    {
1329130570Sobrien      x86_dwarf2_return_column = 8;
1330130570Sobrien      x86_cie_data_alignment = -4;
1331130570Sobrien    }
133233965Sjdp}
133333965Sjdp
133433965Sjdpvoid
1335218822Sdimi386_print_statistics (FILE *file)
133633965Sjdp{
133733965Sjdp  hash_print_statistics (file, "i386 opcode", op_hash);
133833965Sjdp  hash_print_statistics (file, "i386 register", reg_hash);
133933965Sjdp}
134033965Sjdp
134133965Sjdp#ifdef DEBUG386
134233965Sjdp
134377311Sobrien/* Debugging routines for md_assemble.  */
1344218822Sdimstatic void pte (template *);
1345218822Sdimstatic void pt (unsigned int);
1346218822Sdimstatic void pe (expressionS *);
1347218822Sdimstatic void ps (symbolS *);
134833965Sjdp
134933965Sjdpstatic void
1350218822Sdimpi (char *line, i386_insn *x)
135133965Sjdp{
135277311Sobrien  unsigned int i;
135333965Sjdp
135433965Sjdp  fprintf (stdout, "%s: template ", line);
135533965Sjdp  pte (&x->tm);
135677311Sobrien  fprintf (stdout, "  address: base %s  index %s  scale %x\n",
135777311Sobrien	   x->base_reg ? x->base_reg->reg_name : "none",
135877311Sobrien	   x->index_reg ? x->index_reg->reg_name : "none",
135977311Sobrien	   x->log2_scale_factor);
136077311Sobrien  fprintf (stdout, "  modrm:  mode %x  reg %x  reg/mem %x\n",
136133965Sjdp	   x->rm.mode, x->rm.reg, x->rm.regmem);
136277311Sobrien  fprintf (stdout, "  sib:  base %x  index %x  scale %x\n",
136377311Sobrien	   x->sib.base, x->sib.index, x->sib.scale);
136477311Sobrien  fprintf (stdout, "  rex: 64bit %x  extX %x  extY %x  extZ %x\n",
1365218822Sdim	   (x->rex & REX_W) != 0,
1366218822Sdim	   (x->rex & REX_R) != 0,
1367218822Sdim	   (x->rex & REX_X) != 0,
1368218822Sdim	   (x->rex & REX_B) != 0);
136933965Sjdp  for (i = 0; i < x->operands; i++)
137033965Sjdp    {
137133965Sjdp      fprintf (stdout, "    #%d:  ", i + 1);
137233965Sjdp      pt (x->types[i]);
137333965Sjdp      fprintf (stdout, "\n");
137433965Sjdp      if (x->types[i]
137560519Sobrien	  & (Reg | SReg2 | SReg3 | Control | Debug | Test | RegMMX | RegXMM))
137660519Sobrien	fprintf (stdout, "%s\n", x->op[i].regs->reg_name);
137733965Sjdp      if (x->types[i] & Imm)
137860519Sobrien	pe (x->op[i].imms);
137960519Sobrien      if (x->types[i] & Disp)
138060519Sobrien	pe (x->op[i].disps);
138133965Sjdp    }
138233965Sjdp}
138333965Sjdp
138433965Sjdpstatic void
1385218822Sdimpte (template *t)
138633965Sjdp{
138777311Sobrien  unsigned int i;
138833965Sjdp  fprintf (stdout, " %d operands ", t->operands);
138977311Sobrien  fprintf (stdout, "opcode %x ", t->base_opcode);
139033965Sjdp  if (t->extension_opcode != None)
139133965Sjdp    fprintf (stdout, "ext %x ", t->extension_opcode);
139233965Sjdp  if (t->opcode_modifier & D)
139333965Sjdp    fprintf (stdout, "D");
139433965Sjdp  if (t->opcode_modifier & W)
139533965Sjdp    fprintf (stdout, "W");
139633965Sjdp  fprintf (stdout, "\n");
139733965Sjdp  for (i = 0; i < t->operands; i++)
139833965Sjdp    {
139933965Sjdp      fprintf (stdout, "    #%d type ", i + 1);
140033965Sjdp      pt (t->operand_types[i]);
140133965Sjdp      fprintf (stdout, "\n");
140233965Sjdp    }
140333965Sjdp}
140433965Sjdp
140533965Sjdpstatic void
1406218822Sdimpe (expressionS *e)
140733965Sjdp{
140860519Sobrien  fprintf (stdout, "    operation     %d\n", e->X_op);
140960519Sobrien  fprintf (stdout, "    add_number    %ld (%lx)\n",
141060519Sobrien	   (long) e->X_add_number, (long) e->X_add_number);
141133965Sjdp  if (e->X_add_symbol)
141233965Sjdp    {
141333965Sjdp      fprintf (stdout, "    add_symbol    ");
141433965Sjdp      ps (e->X_add_symbol);
141533965Sjdp      fprintf (stdout, "\n");
141633965Sjdp    }
141733965Sjdp  if (e->X_op_symbol)
141833965Sjdp    {
141933965Sjdp      fprintf (stdout, "    op_symbol    ");
142033965Sjdp      ps (e->X_op_symbol);
142133965Sjdp      fprintf (stdout, "\n");
142233965Sjdp    }
142333965Sjdp}
142433965Sjdp
142533965Sjdpstatic void
1426218822Sdimps (symbolS *s)
142733965Sjdp{
142833965Sjdp  fprintf (stdout, "%s type %s%s",
142933965Sjdp	   S_GET_NAME (s),
143033965Sjdp	   S_IS_EXTERNAL (s) ? "EXTERNAL " : "",
143133965Sjdp	   segment_name (S_GET_SEGMENT (s)));
143233965Sjdp}
143333965Sjdp
1434218822Sdimstatic struct type_name
143533965Sjdp  {
143633965Sjdp    unsigned int mask;
143733965Sjdp    char *tname;
143833965Sjdp  }
1439218822Sdimconst type_names[] =
144033965Sjdp{
144133965Sjdp  { Reg8, "r8" },
144233965Sjdp  { Reg16, "r16" },
144333965Sjdp  { Reg32, "r32" },
144477311Sobrien  { Reg64, "r64" },
144533965Sjdp  { Imm8, "i8" },
144633965Sjdp  { Imm8S, "i8s" },
144733965Sjdp  { Imm16, "i16" },
144833965Sjdp  { Imm32, "i32" },
144977311Sobrien  { Imm32S, "i32s" },
145077311Sobrien  { Imm64, "i64" },
145160519Sobrien  { Imm1, "i1" },
145233965Sjdp  { BaseIndex, "BaseIndex" },
145333965Sjdp  { Disp8, "d8" },
145433965Sjdp  { Disp16, "d16" },
145533965Sjdp  { Disp32, "d32" },
145677311Sobrien  { Disp32S, "d32s" },
145777311Sobrien  { Disp64, "d64" },
145833965Sjdp  { InOutPortReg, "InOutPortReg" },
145933965Sjdp  { ShiftCount, "ShiftCount" },
146033965Sjdp  { Control, "control reg" },
146133965Sjdp  { Test, "test reg" },
146260519Sobrien  { Debug, "debug reg" },
146333965Sjdp  { FloatReg, "FReg" },
146433965Sjdp  { FloatAcc, "FAcc" },
146560519Sobrien  { SReg2, "SReg2" },
146660519Sobrien  { SReg3, "SReg3" },
146760519Sobrien  { Acc, "Acc" },
146833965Sjdp  { JumpAbsolute, "Jump Absolute" },
146933965Sjdp  { RegMMX, "rMMX" },
147060519Sobrien  { RegXMM, "rXMM" },
147160519Sobrien  { EsSeg, "es" },
147233965Sjdp  { 0, "" }
147333965Sjdp};
147433965Sjdp
147533965Sjdpstatic void
147633965Sjdppt (t)
147733965Sjdp     unsigned int t;
147833965Sjdp{
147994546Sobrien  const struct type_name *ty;
148033965Sjdp
148177311Sobrien  for (ty = type_names; ty->mask; ty++)
148277311Sobrien    if (t & ty->mask)
148377311Sobrien      fprintf (stdout, "%s, ", ty->tname);
148433965Sjdp  fflush (stdout);
148533965Sjdp}
148633965Sjdp
148733965Sjdp#endif /* DEBUG386 */
148833965Sjdp
148933965Sjdpstatic bfd_reloc_code_real_type
1490218822Sdimreloc (unsigned int size,
1491218822Sdim       int pcrel,
1492218822Sdim       int sign,
1493218822Sdim       bfd_reloc_code_real_type other)
149433965Sjdp{
149577311Sobrien  if (other != NO_RELOC)
1496218822Sdim    {
1497218822Sdim      reloc_howto_type *reloc;
149833965Sjdp
1499218822Sdim      if (size == 8)
1500218822Sdim	switch (other)
1501218822Sdim	  {
1502218822Sdim	  case BFD_RELOC_X86_64_GOT32:
1503218822Sdim	    return BFD_RELOC_X86_64_GOT64;
1504218822Sdim	    break;
1505218822Sdim	  case BFD_RELOC_X86_64_PLTOFF64:
1506218822Sdim	    return BFD_RELOC_X86_64_PLTOFF64;
1507218822Sdim	    break;
1508218822Sdim	  case BFD_RELOC_X86_64_GOTPC32:
1509218822Sdim	    other = BFD_RELOC_X86_64_GOTPC64;
1510218822Sdim	    break;
1511218822Sdim	  case BFD_RELOC_X86_64_GOTPCREL:
1512218822Sdim	    other = BFD_RELOC_X86_64_GOTPCREL64;
1513218822Sdim	    break;
1514218822Sdim	  case BFD_RELOC_X86_64_TPOFF32:
1515218822Sdim	    other = BFD_RELOC_X86_64_TPOFF64;
1516218822Sdim	    break;
1517218822Sdim	  case BFD_RELOC_X86_64_DTPOFF32:
1518218822Sdim	    other = BFD_RELOC_X86_64_DTPOFF64;
1519218822Sdim	    break;
1520218822Sdim	  default:
1521218822Sdim	    break;
1522218822Sdim	  }
1523218822Sdim
1524218822Sdim      /* Sign-checking 4-byte relocations in 16-/32-bit code is pointless.  */
1525218822Sdim      if (size == 4 && flag_code != CODE_64BIT)
1526218822Sdim	sign = -1;
1527218822Sdim
1528218822Sdim      reloc = bfd_reloc_type_lookup (stdoutput, other);
1529218822Sdim      if (!reloc)
1530218822Sdim	as_bad (_("unknown relocation (%u)"), other);
1531218822Sdim      else if (size != bfd_get_reloc_size (reloc))
1532218822Sdim	as_bad (_("%u-byte relocation cannot be applied to %u-byte field"),
1533218822Sdim		bfd_get_reloc_size (reloc),
1534218822Sdim		size);
1535218822Sdim      else if (pcrel && !reloc->pc_relative)
1536218822Sdim	as_bad (_("non-pc-relative relocation for pc-relative field"));
1537218822Sdim      else if ((reloc->complain_on_overflow == complain_overflow_signed
1538218822Sdim		&& !sign)
1539218822Sdim	       || (reloc->complain_on_overflow == complain_overflow_unsigned
1540218822Sdim		   && sign > 0))
1541218822Sdim	as_bad (_("relocated field and relocation type differ in signedness"));
1542218822Sdim      else
1543218822Sdim	return other;
1544218822Sdim      return NO_RELOC;
1545218822Sdim    }
1546218822Sdim
154733965Sjdp  if (pcrel)
154860519Sobrien    {
154977311Sobrien      if (!sign)
1550218822Sdim	as_bad (_("there are no unsigned pc-relative relocations"));
155160519Sobrien      switch (size)
155260519Sobrien	{
155360519Sobrien	case 1: return BFD_RELOC_8_PCREL;
155460519Sobrien	case 2: return BFD_RELOC_16_PCREL;
155560519Sobrien	case 4: return BFD_RELOC_32_PCREL;
1556218822Sdim	case 8: return BFD_RELOC_64_PCREL;
155760519Sobrien	}
1558218822Sdim      as_bad (_("cannot do %u byte pc-relative relocation"), size);
155960519Sobrien    }
156033965Sjdp  else
156160519Sobrien    {
1562218822Sdim      if (sign > 0)
156377311Sobrien	switch (size)
156477311Sobrien	  {
156577311Sobrien	  case 4: return BFD_RELOC_X86_64_32S;
156677311Sobrien	  }
156777311Sobrien      else
156877311Sobrien	switch (size)
156977311Sobrien	  {
157077311Sobrien	  case 1: return BFD_RELOC_8;
157177311Sobrien	  case 2: return BFD_RELOC_16;
157277311Sobrien	  case 4: return BFD_RELOC_32;
157377311Sobrien	  case 8: return BFD_RELOC_64;
157477311Sobrien	  }
1575218822Sdim      as_bad (_("cannot do %s %u byte relocation"),
1576218822Sdim	      sign > 0 ? "signed" : "unsigned", size);
157760519Sobrien    }
157833965Sjdp
157977311Sobrien  abort ();
158033965Sjdp  return BFD_RELOC_NONE;
158133965Sjdp}
158233965Sjdp
158377311Sobrien/* Here we decide which fixups can be adjusted to make them relative to
158477311Sobrien   the beginning of the section instead of the symbol.  Basically we need
158577311Sobrien   to make sure that the dynamic relocations are done correctly, so in
158677311Sobrien   some cases we force the original symbol to be used.  */
158777311Sobrien
158833965Sjdpint
1589218822Sdimtc_i386_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED)
159033965Sjdp{
159177311Sobrien#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
1592218822Sdim  if (!IS_ELF)
1593104848Sobrien    return 1;
1594104848Sobrien
1595130570Sobrien  /* Don't adjust pc-relative references to merge sections in 64-bit
1596130570Sobrien     mode.  */
1597130570Sobrien  if (use_rela_relocations
1598130570Sobrien      && (S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0
1599130570Sobrien      && fixP->fx_pcrel)
160033965Sjdp    return 0;
1601104848Sobrien
1602130570Sobrien  /* The x86_64 GOTPCREL are represented as 32bit PCrel relocations
1603130570Sobrien     and changed later by validate_fix.  */
1604130570Sobrien  if (GOT_symbol && fixP->fx_subsy == GOT_symbol
1605130570Sobrien      && fixP->fx_r_type == BFD_RELOC_32_PCREL)
1606130570Sobrien    return 0;
1607130570Sobrien
160877311Sobrien  /* adjust_reloc_syms doesn't know about the GOT.  */
160933965Sjdp  if (fixP->fx_r_type == BFD_RELOC_386_GOTOFF
161033965Sjdp      || fixP->fx_r_type == BFD_RELOC_386_PLT32
161160519Sobrien      || fixP->fx_r_type == BFD_RELOC_386_GOT32
1612104848Sobrien      || fixP->fx_r_type == BFD_RELOC_386_TLS_GD
1613104848Sobrien      || fixP->fx_r_type == BFD_RELOC_386_TLS_LDM
1614104848Sobrien      || fixP->fx_r_type == BFD_RELOC_386_TLS_LDO_32
1615104848Sobrien      || fixP->fx_r_type == BFD_RELOC_386_TLS_IE_32
1616104848Sobrien      || fixP->fx_r_type == BFD_RELOC_386_TLS_IE
1617104848Sobrien      || fixP->fx_r_type == BFD_RELOC_386_TLS_GOTIE
1618104848Sobrien      || fixP->fx_r_type == BFD_RELOC_386_TLS_LE_32
1619104848Sobrien      || fixP->fx_r_type == BFD_RELOC_386_TLS_LE
1620218822Sdim      || fixP->fx_r_type == BFD_RELOC_386_TLS_GOTDESC
1621218822Sdim      || fixP->fx_r_type == BFD_RELOC_386_TLS_DESC_CALL
162277311Sobrien      || fixP->fx_r_type == BFD_RELOC_X86_64_PLT32
162377311Sobrien      || fixP->fx_r_type == BFD_RELOC_X86_64_GOT32
162477311Sobrien      || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL
1625130570Sobrien      || fixP->fx_r_type == BFD_RELOC_X86_64_TLSGD
1626130570Sobrien      || fixP->fx_r_type == BFD_RELOC_X86_64_TLSLD
1627130570Sobrien      || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF32
1628218822Sdim      || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF64
1629130570Sobrien      || fixP->fx_r_type == BFD_RELOC_X86_64_GOTTPOFF
1630130570Sobrien      || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF32
1631218822Sdim      || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF64
1632218822Sdim      || fixP->fx_r_type == BFD_RELOC_X86_64_GOTOFF64
1633218822Sdim      || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPC32_TLSDESC
1634218822Sdim      || fixP->fx_r_type == BFD_RELOC_X86_64_TLSDESC_CALL
163560519Sobrien      || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
163660519Sobrien      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
163733965Sjdp    return 0;
1638104848Sobrien#endif
163933965Sjdp  return 1;
164033965Sjdp}
164133965Sjdp
164260519Sobrienstatic int
1643218822Sdimintel_float_operand (const char *mnemonic)
164460519Sobrien{
1645218822Sdim  /* Note that the value returned is meaningful only for opcodes with (memory)
1646218822Sdim     operands, hence the code here is free to improperly handle opcodes that
1647218822Sdim     have no operands (for better performance and smaller code). */
164860519Sobrien
1649218822Sdim  if (mnemonic[0] != 'f')
1650218822Sdim    return 0; /* non-math */
165160519Sobrien
1652218822Sdim  switch (mnemonic[1])
1653218822Sdim    {
1654218822Sdim    /* fclex, fdecstp, fdisi, femms, feni, fincstp, finit, fsetpm, and
1655218822Sdim       the fs segment override prefix not currently handled because no
1656218822Sdim       call path can make opcodes without operands get here */
1657218822Sdim    case 'i':
1658218822Sdim      return 2 /* integer op */;
1659218822Sdim    case 'l':
1660218822Sdim      if (mnemonic[2] == 'd' && (mnemonic[3] == 'c' || mnemonic[3] == 'e'))
1661218822Sdim	return 3; /* fldcw/fldenv */
1662218822Sdim      break;
1663218822Sdim    case 'n':
1664218822Sdim      if (mnemonic[2] != 'o' /* fnop */)
1665218822Sdim	return 3; /* non-waiting control op */
1666218822Sdim      break;
1667218822Sdim    case 'r':
1668218822Sdim      if (mnemonic[2] == 's')
1669218822Sdim	return 3; /* frstor/frstpm */
1670218822Sdim      break;
1671218822Sdim    case 's':
1672218822Sdim      if (mnemonic[2] == 'a')
1673218822Sdim	return 3; /* fsave */
1674218822Sdim      if (mnemonic[2] == 't')
1675218822Sdim	{
1676218822Sdim	  switch (mnemonic[3])
1677218822Sdim	    {
1678218822Sdim	    case 'c': /* fstcw */
1679218822Sdim	    case 'd': /* fstdw */
1680218822Sdim	    case 'e': /* fstenv */
1681218822Sdim	    case 's': /* fsts[gw] */
1682218822Sdim	      return 3;
1683218822Sdim	    }
1684218822Sdim	}
1685218822Sdim      break;
1686218822Sdim    case 'x':
1687218822Sdim      if (mnemonic[2] == 'r' || mnemonic[2] == 's')
1688218822Sdim	return 0; /* fxsave/fxrstor are not really math ops */
1689218822Sdim      break;
1690218822Sdim    }
1691218822Sdim
1692218822Sdim  return 1;
169360519Sobrien}
169460519Sobrien
169533965Sjdp/* This is the guts of the machine-dependent assembler.  LINE points to a
169633965Sjdp   machine dependent instruction.  This function is supposed to emit
169733965Sjdp   the frags/bytes it assembles to.  */
169833965Sjdp
169933965Sjdpvoid
170033965Sjdpmd_assemble (line)
170133965Sjdp     char *line;
170233965Sjdp{
170333965Sjdp  int j;
170460519Sobrien  char mnemonic[MAX_MNEM_SIZE];
170538891Sjdp
170677311Sobrien  /* Initialize globals.  */
170733965Sjdp  memset (&i, '\0', sizeof (i));
170833965Sjdp  for (j = 0; j < MAX_OPERANDS; j++)
170978840Sobrien    i.reloc[j] = NO_RELOC;
171033965Sjdp  memset (disp_expressions, '\0', sizeof (disp_expressions));
171133965Sjdp  memset (im_expressions, '\0', sizeof (im_expressions));
171277311Sobrien  save_stack_p = save_stack;
171333965Sjdp
171460519Sobrien  /* First parse an instruction mnemonic & call i386_operand for the operands.
171533965Sjdp     We assume that the scrubber has arranged it so that line[0] is the valid
171677311Sobrien     start of a (possibly prefixed) mnemonic.  */
171733965Sjdp
171894546Sobrien  line = parse_insn (line, mnemonic);
171994546Sobrien  if (line == NULL)
172094546Sobrien    return;
172160519Sobrien
172294546Sobrien  line = parse_operands (line, mnemonic);
172394546Sobrien  if (line == NULL)
172494546Sobrien    return;
172560519Sobrien
1726218822Sdim  /* The order of the immediates should be reversed
1727218822Sdim     for 2 immediates extrq and insertq instructions */
1728218822Sdim  if ((i.imm_operands == 2)
1729218822Sdim      && ((strcmp (mnemonic, "extrq") == 0)
1730218822Sdim	  || (strcmp (mnemonic, "insertq") == 0)))
1731218822Sdim    {
1732218822Sdim      swap_2_operands (0, 1);
1733218822Sdim      /* "extrq" and insertq" are the only two instructions whose operands
1734218822Sdim	 have to be reversed even though they have two immediate operands.
1735218822Sdim      */
1736218822Sdim      if (intel_syntax)
1737218822Sdim	swap_operands ();
1738218822Sdim    }
1739218822Sdim
174094546Sobrien  /* Now we've parsed the mnemonic into a set of templates, and have the
174194546Sobrien     operands at hand.  */
174260519Sobrien
174394546Sobrien  /* All intel opcodes have reversed operands except for "bound" and
174494546Sobrien     "enter".  We also don't reverse intersegment "jmp" and "call"
174594546Sobrien     instructions with 2 immediate operands so that the immediate segment
1746218822Sdim     precedes the offset, as it does when in AT&T mode. */
1747218822Sdim  if (intel_syntax
1748218822Sdim      && i.operands > 1
174994546Sobrien      && (strcmp (mnemonic, "bound") != 0)
1750218822Sdim      && (strcmp (mnemonic, "invlpga") != 0)
175194546Sobrien      && !((i.types[0] & Imm) && (i.types[1] & Imm)))
175294546Sobrien    swap_operands ();
175333965Sjdp
175494546Sobrien  if (i.imm_operands)
175594546Sobrien    optimize_imm ();
175660519Sobrien
1757218822Sdim  /* Don't optimize displacement for movabs since it only takes 64bit
1758218822Sdim     displacement.  */
1759218822Sdim  if (i.disp_operands
1760218822Sdim      && (flag_code != CODE_64BIT
1761218822Sdim	  || strcmp (mnemonic, "movabs") != 0))
176294546Sobrien    optimize_disp ();
176333965Sjdp
176494546Sobrien  /* Next, we find a template that matches the given insn,
176594546Sobrien     making sure the overlap of the given operands types is consistent
176694546Sobrien     with the template operand types.  */
176777311Sobrien
176894546Sobrien  if (!match_template ())
176994546Sobrien    return;
177089867Sobrien
1771104848Sobrien  if (intel_syntax)
1772104848Sobrien    {
1773104848Sobrien      /* Undo SYSV386_COMPAT brokenness when in Intel mode.  See i386.h  */
1774104848Sobrien      if (SYSV386_COMPAT
1775104848Sobrien	  && (i.tm.base_opcode & 0xfffffde0) == 0xdce0)
1776218822Sdim	i.tm.base_opcode ^= Opcode_FloatR;
177794546Sobrien
1778104848Sobrien      /* Zap movzx and movsx suffix.  The suffix may have been set from
1779104848Sobrien	 "word ptr" or "byte ptr" on the source operand, but we'll use
1780104848Sobrien	 the suffix later to choose the destination register.  */
1781104848Sobrien      if ((i.tm.base_opcode & ~9) == 0x0fb6)
1782218822Sdim	{
1783218822Sdim	  if (i.reg_operands < 2
1784218822Sdim	      && !i.suffix
1785218822Sdim	      && (~i.tm.opcode_modifier
1786218822Sdim		  & (No_bSuf
1787218822Sdim		     | No_wSuf
1788218822Sdim		     | No_lSuf
1789218822Sdim		     | No_sSuf
1790218822Sdim		     | No_xSuf
1791218822Sdim		     | No_qSuf)))
1792218822Sdim	    as_bad (_("ambiguous operand size for `%s'"), i.tm.name);
1793218822Sdim
1794218822Sdim	  i.suffix = 0;
1795218822Sdim	}
1796104848Sobrien    }
1797104848Sobrien
179894546Sobrien  if (i.tm.opcode_modifier & FWait)
179994546Sobrien    if (!add_prefix (FWAIT_OPCODE))
180094546Sobrien      return;
180194546Sobrien
180294546Sobrien  /* Check string instruction segment overrides.  */
180394546Sobrien  if ((i.tm.opcode_modifier & IsString) != 0 && i.mem_operands != 0)
180494546Sobrien    {
180594546Sobrien      if (!check_string ())
180633965Sjdp	return;
180794546Sobrien    }
180833965Sjdp
180994546Sobrien  if (!process_suffix ())
181094546Sobrien    return;
181160519Sobrien
181294546Sobrien  /* Make still unresolved immediate matches conform to size of immediate
181394546Sobrien     given in i.suffix.  */
181494546Sobrien  if (!finalize_imm ())
181594546Sobrien    return;
181660519Sobrien
181794546Sobrien  if (i.types[0] & Imm1)
181894546Sobrien    i.imm_operands = 0;	/* kludge for shift insns.  */
181994546Sobrien  if (i.types[0] & ImplicitRegister)
182094546Sobrien    i.reg_operands--;
182194546Sobrien  if (i.types[1] & ImplicitRegister)
182294546Sobrien    i.reg_operands--;
182394546Sobrien  if (i.types[2] & ImplicitRegister)
182494546Sobrien    i.reg_operands--;
182560519Sobrien
182694546Sobrien  if (i.tm.opcode_modifier & ImmExt)
182794546Sobrien    {
1828130570Sobrien      expressionS *exp;
1829130570Sobrien
1830261175Spfg      if ((i.tm.cpu_flags & (CpuSSE3|CpuSMAP)) && i.operands > 0)
1831130570Sobrien	{
1832218822Sdim	  /* Streaming SIMD extensions 3 Instructions have the fixed
1833130570Sobrien	     operands with an opcode suffix which is coded in the same
1834130570Sobrien	     place as an 8-bit immediate field would be. Here we check
1835130570Sobrien	     those operands and remove them afterwards.  */
1836130570Sobrien	  unsigned int x;
1837130570Sobrien
1838130570Sobrien	  for (x = 0; x < i.operands; x++)
1839130570Sobrien	    if (i.op[x].regs->reg_num != x)
1840218822Sdim	      as_bad (_("can't use register '%s%s' as operand %d in '%s'."),
1841218822Sdim		      register_prefix,
1842218822Sdim		      i.op[x].regs->reg_name,
1843218822Sdim		      x + 1,
1844218822Sdim		      i.tm.name);
1845130570Sobrien	  i.operands = 0;
1846130570Sobrien 	}
1847130570Sobrien
184894546Sobrien      /* These AMD 3DNow! and Intel Katmai New Instructions have an
184994546Sobrien	 opcode suffix which is coded in the same place as an 8-bit
185094546Sobrien	 immediate field would be.  Here we fake an 8-bit immediate
185194546Sobrien	 operand from the opcode suffix stored in tm.extension_opcode.  */
185260519Sobrien
185394546Sobrien      assert (i.imm_operands == 0 && i.operands <= 2 && 2 < MAX_OPERANDS);
185433965Sjdp
185594546Sobrien      exp = &im_expressions[i.imm_operands++];
185694546Sobrien      i.op[i.operands].imms = exp;
185794546Sobrien      i.types[i.operands++] = Imm8;
185894546Sobrien      exp->X_op = O_constant;
185994546Sobrien      exp->X_add_number = i.tm.extension_opcode;
186094546Sobrien      i.tm.extension_opcode = None;
186194546Sobrien    }
186233965Sjdp
186394546Sobrien  /* For insns with operands there are more diddles to do to the opcode.  */
186494546Sobrien  if (i.operands)
186594546Sobrien    {
186694546Sobrien      if (!process_operands ())
186794546Sobrien	return;
186894546Sobrien    }
186994546Sobrien  else if (!quiet_warnings && (i.tm.opcode_modifier & Ugh) != 0)
187094546Sobrien    {
187194546Sobrien      /* UnixWare fsub no args is alias for fsubp, fadd -> faddp, etc.  */
187294546Sobrien      as_warn (_("translating to `%sp'"), i.tm.name);
187394546Sobrien    }
187433965Sjdp
187594546Sobrien  /* Handle conversion of 'int $3' --> special int3 insn.  */
187694546Sobrien  if (i.tm.base_opcode == INT_OPCODE && i.op[0].imms->X_add_number == 3)
187794546Sobrien    {
187894546Sobrien      i.tm.base_opcode = INT3_OPCODE;
187994546Sobrien      i.imm_operands = 0;
188094546Sobrien    }
188133965Sjdp
188294546Sobrien  if ((i.tm.opcode_modifier & (Jump | JumpByte | JumpDword))
188394546Sobrien      && i.op[0].disps->X_op == O_constant)
188494546Sobrien    {
188594546Sobrien      /* Convert "jmp constant" (and "call constant") to a jump (call) to
188694546Sobrien	 the absolute address given by the constant.  Since ix86 jumps and
188794546Sobrien	 calls are pc relative, we need to generate a reloc.  */
188894546Sobrien      i.op[0].disps->X_add_symbol = &abs_symbol;
188994546Sobrien      i.op[0].disps->X_op = O_symbol;
189094546Sobrien    }
189133965Sjdp
189294546Sobrien  if ((i.tm.opcode_modifier & Rex64) != 0)
1893218822Sdim    i.rex |= REX_W;
189433965Sjdp
189594546Sobrien  /* For 8 bit registers we need an empty rex prefix.  Also if the
189694546Sobrien     instruction already has a prefix, we need to convert old
189794546Sobrien     registers to new ones.  */
189860519Sobrien
189994546Sobrien  if (((i.types[0] & Reg8) != 0
190094546Sobrien       && (i.op[0].regs->reg_flags & RegRex64) != 0)
190194546Sobrien      || ((i.types[1] & Reg8) != 0
190294546Sobrien	  && (i.op[1].regs->reg_flags & RegRex64) != 0)
190394546Sobrien      || (((i.types[0] & Reg8) != 0 || (i.types[1] & Reg8) != 0)
190494546Sobrien	  && i.rex != 0))
190594546Sobrien    {
190694546Sobrien      int x;
190760519Sobrien
190894546Sobrien      i.rex |= REX_OPCODE;
190994546Sobrien      for (x = 0; x < 2; x++)
191094546Sobrien	{
191194546Sobrien	  /* Look for 8 bit operand that uses old registers.  */
191294546Sobrien	  if ((i.types[x] & Reg8) != 0
191394546Sobrien	      && (i.op[x].regs->reg_flags & RegRex64) == 0)
191494546Sobrien	    {
191594546Sobrien	      /* In case it is "hi" register, give up.  */
191694546Sobrien	      if (i.op[x].regs->reg_num > 3)
1917218822Sdim		as_bad (_("can't encode register '%s%s' in an "
1918218822Sdim			  "instruction requiring REX prefix."),
1919218822Sdim			register_prefix, i.op[x].regs->reg_name);
192060519Sobrien
192194546Sobrien	      /* Otherwise it is equivalent to the extended register.
192294546Sobrien		 Since the encoding doesn't change this is merely
192394546Sobrien		 cosmetic cleanup for debug output.  */
192460519Sobrien
192594546Sobrien	      i.op[x].regs = i.op[x].regs + 8;
192694546Sobrien	    }
192794546Sobrien	}
192894546Sobrien    }
192960519Sobrien
193094546Sobrien  if (i.rex != 0)
193194546Sobrien    add_prefix (REX_OPCODE | i.rex);
193294546Sobrien
193394546Sobrien  /* We are ready to output the insn.  */
193494546Sobrien  output_insn ();
193594546Sobrien}
193694546Sobrien
193794546Sobrienstatic char *
1938218822Sdimparse_insn (char *line, char *mnemonic)
193994546Sobrien{
194094546Sobrien  char *l = line;
194194546Sobrien  char *token_start = l;
194294546Sobrien  char *mnem_p;
1943218822Sdim  int supported;
1944218822Sdim  const template *t;
194594546Sobrien
194694546Sobrien  /* Non-zero if we found a prefix only acceptable with string insns.  */
194794546Sobrien  const char *expecting_string_instruction = NULL;
194894546Sobrien
194994546Sobrien  while (1)
195094546Sobrien    {
195194546Sobrien      mnem_p = mnemonic;
195294546Sobrien      while ((*mnem_p = mnemonic_chars[(unsigned char) *l]) != 0)
195394546Sobrien	{
195494546Sobrien	  mnem_p++;
195594546Sobrien	  if (mnem_p >= mnemonic + MAX_MNEM_SIZE)
195660519Sobrien	    {
195794546Sobrien	      as_bad (_("no such instruction: `%s'"), token_start);
195894546Sobrien	      return NULL;
195994546Sobrien	    }
196094546Sobrien	  l++;
196194546Sobrien	}
196294546Sobrien      if (!is_space_char (*l)
196394546Sobrien	  && *l != END_OF_INSN
1964218822Sdim	  && (intel_syntax
1965218822Sdim	      || (*l != PREFIX_SEPARATOR
1966218822Sdim		  && *l != ',')))
196794546Sobrien	{
196894546Sobrien	  as_bad (_("invalid character %s in mnemonic"),
196994546Sobrien		  output_invalid (*l));
197094546Sobrien	  return NULL;
197194546Sobrien	}
197294546Sobrien      if (token_start == l)
197394546Sobrien	{
1974218822Sdim	  if (!intel_syntax && *l == PREFIX_SEPARATOR)
197594546Sobrien	    as_bad (_("expecting prefix; got nothing"));
197694546Sobrien	  else
197794546Sobrien	    as_bad (_("expecting mnemonic; got nothing"));
197894546Sobrien	  return NULL;
197994546Sobrien	}
198077311Sobrien
198194546Sobrien      /* Look up instruction (or prefix) via hash table.  */
198294546Sobrien      current_templates = hash_find (op_hash, mnemonic);
198394546Sobrien
198494546Sobrien      if (*l != END_OF_INSN
198594546Sobrien	  && (!is_space_char (*l) || l[1] != END_OF_INSN)
198694546Sobrien	  && current_templates
198794546Sobrien	  && (current_templates->start->opcode_modifier & IsPrefix))
198894546Sobrien	{
1989218822Sdim	  if (current_templates->start->cpu_flags
1990218822Sdim	      & (flag_code != CODE_64BIT ? Cpu64 : CpuNo64))
1991218822Sdim	    {
1992218822Sdim	      as_bad ((flag_code != CODE_64BIT
1993218822Sdim		       ? _("`%s' is only supported in 64-bit mode")
1994218822Sdim		       : _("`%s' is not supported in 64-bit mode")),
1995218822Sdim		      current_templates->start->name);
1996218822Sdim	      return NULL;
1997218822Sdim	    }
199894546Sobrien	  /* If we are in 16-bit mode, do not allow addr16 or data16.
199994546Sobrien	     Similarly, in 32-bit mode, do not allow addr32 or data32.  */
200094546Sobrien	  if ((current_templates->start->opcode_modifier & (Size16 | Size32))
200194546Sobrien	      && flag_code != CODE_64BIT
200294546Sobrien	      && (((current_templates->start->opcode_modifier & Size32) != 0)
200394546Sobrien		  ^ (flag_code == CODE_16BIT)))
200494546Sobrien	    {
200594546Sobrien	      as_bad (_("redundant %s prefix"),
200694546Sobrien		      current_templates->start->name);
200794546Sobrien	      return NULL;
200877311Sobrien	    }
200994546Sobrien	  /* Add prefix, checking for repeated prefixes.  */
201094546Sobrien	  switch (add_prefix (current_templates->start->base_opcode))
201194546Sobrien	    {
201294546Sobrien	    case 0:
201394546Sobrien	      return NULL;
201494546Sobrien	    case 2:
201594546Sobrien	      expecting_string_instruction = current_templates->start->name;
201694546Sobrien	      break;
201794546Sobrien	    }
201894546Sobrien	  /* Skip past PREFIX_SEPARATOR and reset token_start.  */
201994546Sobrien	  token_start = ++l;
202094546Sobrien	}
202194546Sobrien      else
202294546Sobrien	break;
202394546Sobrien    }
202460519Sobrien
202594546Sobrien  if (!current_templates)
202694546Sobrien    {
202794546Sobrien      /* See if we can get a match by trimming off a suffix.  */
202894546Sobrien      switch (mnem_p[-1])
202994546Sobrien	{
203094546Sobrien	case WORD_MNEM_SUFFIX:
2031218822Sdim	  if (intel_syntax && (intel_float_operand (mnemonic) & 2))
2032218822Sdim	    i.suffix = SHORT_MNEM_SUFFIX;
2033218822Sdim	  else
203494546Sobrien	case BYTE_MNEM_SUFFIX:
203594546Sobrien	case QWORD_MNEM_SUFFIX:
203694546Sobrien	  i.suffix = mnem_p[-1];
203794546Sobrien	  mnem_p[-1] = '\0';
203894546Sobrien	  current_templates = hash_find (op_hash, mnemonic);
203994546Sobrien	  break;
204094546Sobrien	case SHORT_MNEM_SUFFIX:
204194546Sobrien	case LONG_MNEM_SUFFIX:
204294546Sobrien	  if (!intel_syntax)
204394546Sobrien	    {
204494546Sobrien	      i.suffix = mnem_p[-1];
204594546Sobrien	      mnem_p[-1] = '\0';
204694546Sobrien	      current_templates = hash_find (op_hash, mnemonic);
204794546Sobrien	    }
204894546Sobrien	  break;
204977311Sobrien
205094546Sobrien	  /* Intel Syntax.  */
205194546Sobrien	case 'd':
205294546Sobrien	  if (intel_syntax)
205377311Sobrien	    {
2054218822Sdim	      if (intel_float_operand (mnemonic) == 1)
205594546Sobrien		i.suffix = SHORT_MNEM_SUFFIX;
205694546Sobrien	      else
205794546Sobrien		i.suffix = LONG_MNEM_SUFFIX;
205894546Sobrien	      mnem_p[-1] = '\0';
205994546Sobrien	      current_templates = hash_find (op_hash, mnemonic);
206094546Sobrien	    }
206194546Sobrien	  break;
206294546Sobrien	}
206394546Sobrien      if (!current_templates)
206494546Sobrien	{
206594546Sobrien	  as_bad (_("no such instruction: `%s'"), token_start);
206694546Sobrien	  return NULL;
206794546Sobrien	}
206894546Sobrien    }
206977311Sobrien
207094546Sobrien  if (current_templates->start->opcode_modifier & (Jump | JumpByte))
207194546Sobrien    {
207294546Sobrien      /* Check for a branch hint.  We allow ",pt" and ",pn" for
207394546Sobrien	 predict taken and predict not taken respectively.
207494546Sobrien	 I'm not sure that branch hints actually do anything on loop
207594546Sobrien	 and jcxz insns (JumpByte) for current Pentium4 chips.  They
207694546Sobrien	 may work in the future and it doesn't hurt to accept them
207794546Sobrien	 now.  */
207894546Sobrien      if (l[0] == ',' && l[1] == 'p')
207994546Sobrien	{
208094546Sobrien	  if (l[2] == 't')
208194546Sobrien	    {
208294546Sobrien	      if (!add_prefix (DS_PREFIX_OPCODE))
208394546Sobrien		return NULL;
208494546Sobrien	      l += 3;
208594546Sobrien	    }
208694546Sobrien	  else if (l[2] == 'n')
208794546Sobrien	    {
208894546Sobrien	      if (!add_prefix (CS_PREFIX_OPCODE))
208994546Sobrien		return NULL;
209094546Sobrien	      l += 3;
209194546Sobrien	    }
209294546Sobrien	}
209394546Sobrien    }
209494546Sobrien  /* Any other comma loses.  */
209594546Sobrien  if (*l == ',')
209694546Sobrien    {
209794546Sobrien      as_bad (_("invalid character %s in mnemonic"),
209894546Sobrien	      output_invalid (*l));
209994546Sobrien      return NULL;
210094546Sobrien    }
210177311Sobrien
210294546Sobrien  /* Check if instruction is supported on specified architecture.  */
2103218822Sdim  supported = 0;
2104218822Sdim  for (t = current_templates->start; t < current_templates->end; ++t)
210594546Sobrien    {
2106218822Sdim      if (!((t->cpu_flags & ~(Cpu64 | CpuNo64))
2107218822Sdim	    & ~(cpu_arch_flags & ~(Cpu64 | CpuNo64))))
2108218822Sdim	supported |= 1;
2109218822Sdim      if (!(t->cpu_flags & (flag_code == CODE_64BIT ? CpuNo64 : Cpu64)))
2110218822Sdim	supported |= 2;
211194546Sobrien    }
2112218822Sdim  if (!(supported & 2))
2113218822Sdim    {
2114218822Sdim      as_bad (flag_code == CODE_64BIT
2115218822Sdim	      ? _("`%s' is not supported in 64-bit mode")
2116218822Sdim	      : _("`%s' is only supported in 64-bit mode"),
2117218822Sdim	      current_templates->start->name);
2118218822Sdim      return NULL;
2119218822Sdim    }
2120218822Sdim  if (!(supported & 1))
2121218822Sdim    {
2122218822Sdim      as_warn (_("`%s' is not supported on `%s%s'"),
2123218822Sdim	       current_templates->start->name,
2124218822Sdim	       cpu_arch_name,
2125218822Sdim	       cpu_sub_arch_name ? cpu_sub_arch_name : "");
2126218822Sdim    }
212794546Sobrien  else if ((Cpu386 & ~cpu_arch_flags) && (flag_code != CODE_16BIT))
212894546Sobrien    {
212994546Sobrien      as_warn (_("use .code16 to ensure correct addressing mode"));
213094546Sobrien    }
213194546Sobrien
213294546Sobrien  /* Check for rep/repne without a string instruction.  */
2133218822Sdim  if (expecting_string_instruction)
213494546Sobrien    {
2135218822Sdim      static templates override;
2136218822Sdim
2137218822Sdim      for (t = current_templates->start; t < current_templates->end; ++t)
2138218822Sdim	if (t->opcode_modifier & IsString)
2139218822Sdim	  break;
2140218822Sdim      if (t >= current_templates->end)
2141218822Sdim	{
2142218822Sdim	  as_bad (_("expecting string instruction after `%s'"),
2143218822Sdim		  expecting_string_instruction);
2144218822Sdim	  return NULL;
2145218822Sdim	}
2146218822Sdim      for (override.start = t; t < current_templates->end; ++t)
2147218822Sdim	if (!(t->opcode_modifier & IsString))
2148218822Sdim	  break;
2149218822Sdim      override.end = t;
2150218822Sdim      current_templates = &override;
215194546Sobrien    }
215294546Sobrien
215394546Sobrien  return l;
215494546Sobrien}
215594546Sobrien
215694546Sobrienstatic char *
2157218822Sdimparse_operands (char *l, const char *mnemonic)
215894546Sobrien{
215994546Sobrien  char *token_start;
216094546Sobrien
216194546Sobrien  /* 1 if operand is pending after ','.  */
216294546Sobrien  unsigned int expecting_operand = 0;
216394546Sobrien
216494546Sobrien  /* Non-zero if operand parens not balanced.  */
216594546Sobrien  unsigned int paren_not_balanced;
216694546Sobrien
216794546Sobrien  while (*l != END_OF_INSN)
216894546Sobrien    {
216994546Sobrien      /* Skip optional white space before operand.  */
217094546Sobrien      if (is_space_char (*l))
217194546Sobrien	++l;
217294546Sobrien      if (!is_operand_char (*l) && *l != END_OF_INSN)
217394546Sobrien	{
217494546Sobrien	  as_bad (_("invalid character %s before operand %d"),
217594546Sobrien		  output_invalid (*l),
217694546Sobrien		  i.operands + 1);
217794546Sobrien	  return NULL;
217894546Sobrien	}
217994546Sobrien      token_start = l;	/* after white space */
218094546Sobrien      paren_not_balanced = 0;
218194546Sobrien      while (paren_not_balanced || *l != ',')
218294546Sobrien	{
218394546Sobrien	  if (*l == END_OF_INSN)
218494546Sobrien	    {
218594546Sobrien	      if (paren_not_balanced)
218677311Sobrien		{
218794546Sobrien		  if (!intel_syntax)
218894546Sobrien		    as_bad (_("unbalanced parenthesis in operand %d."),
218994546Sobrien			    i.operands + 1);
219094546Sobrien		  else
219194546Sobrien		    as_bad (_("unbalanced brackets in operand %d."),
219294546Sobrien			    i.operands + 1);
219394546Sobrien		  return NULL;
219477311Sobrien		}
219594546Sobrien	      else
219694546Sobrien		break;	/* we are done */
219760519Sobrien	    }
219894546Sobrien	  else if (!is_operand_char (*l) && !is_space_char (*l))
219994546Sobrien	    {
220094546Sobrien	      as_bad (_("invalid character %s in operand %d"),
220194546Sobrien		      output_invalid (*l),
220294546Sobrien		      i.operands + 1);
220394546Sobrien	      return NULL;
220494546Sobrien	    }
220594546Sobrien	  if (!intel_syntax)
220694546Sobrien	    {
220794546Sobrien	      if (*l == '(')
220894546Sobrien		++paren_not_balanced;
220994546Sobrien	      if (*l == ')')
221094546Sobrien		--paren_not_balanced;
221194546Sobrien	    }
221294546Sobrien	  else
221394546Sobrien	    {
221494546Sobrien	      if (*l == '[')
221594546Sobrien		++paren_not_balanced;
221694546Sobrien	      if (*l == ']')
221794546Sobrien		--paren_not_balanced;
221894546Sobrien	    }
221994546Sobrien	  l++;
222094546Sobrien	}
222194546Sobrien      if (l != token_start)
222294546Sobrien	{			/* Yes, we've read in another operand.  */
222394546Sobrien	  unsigned int operand_ok;
222494546Sobrien	  this_operand = i.operands++;
222594546Sobrien	  if (i.operands > MAX_OPERANDS)
222694546Sobrien	    {
222794546Sobrien	      as_bad (_("spurious operands; (%d operands/instruction max)"),
222894546Sobrien		      MAX_OPERANDS);
222994546Sobrien	      return NULL;
223094546Sobrien	    }
223194546Sobrien	  /* Now parse operand adding info to 'i' as we go along.  */
223294546Sobrien	  END_STRING_AND_SAVE (l);
223360519Sobrien
223494546Sobrien	  if (intel_syntax)
223594546Sobrien	    operand_ok =
223694546Sobrien	      i386_intel_operand (token_start,
223794546Sobrien				  intel_float_operand (mnemonic));
223894546Sobrien	  else
223994546Sobrien	    operand_ok = i386_operand (token_start);
224060519Sobrien
224194546Sobrien	  RESTORE_END_STRING (l);
224294546Sobrien	  if (!operand_ok)
224394546Sobrien	    return NULL;
224494546Sobrien	}
224594546Sobrien      else
224694546Sobrien	{
224794546Sobrien	  if (expecting_operand)
224894546Sobrien	    {
224994546Sobrien	    expecting_operand_after_comma:
225094546Sobrien	      as_bad (_("expecting operand after ','; got nothing"));
225194546Sobrien	      return NULL;
225294546Sobrien	    }
225394546Sobrien	  if (*l == ',')
225494546Sobrien	    {
225594546Sobrien	      as_bad (_("expecting operand before ','; got nothing"));
225694546Sobrien	      return NULL;
225794546Sobrien	    }
225894546Sobrien	}
225960519Sobrien
226094546Sobrien      /* Now *l must be either ',' or END_OF_INSN.  */
226194546Sobrien      if (*l == ',')
226294546Sobrien	{
226394546Sobrien	  if (*++l == END_OF_INSN)
226494546Sobrien	    {
226594546Sobrien	      /* Just skip it, if it's \n complain.  */
226694546Sobrien	      goto expecting_operand_after_comma;
226794546Sobrien	    }
226894546Sobrien	  expecting_operand = 1;
226994546Sobrien	}
227094546Sobrien    }
227194546Sobrien  return l;
227294546Sobrien}
227360519Sobrien
227494546Sobrienstatic void
2275218822Sdimswap_2_operands (int xchg1, int xchg2)
227694546Sobrien{
227794546Sobrien  union i386_op temp_op;
227894546Sobrien  unsigned int temp_type;
2279130570Sobrien  enum bfd_reloc_code_real temp_reloc;
228094546Sobrien
228194546Sobrien  temp_type = i.types[xchg2];
228294546Sobrien  i.types[xchg2] = i.types[xchg1];
228394546Sobrien  i.types[xchg1] = temp_type;
228494546Sobrien  temp_op = i.op[xchg2];
228594546Sobrien  i.op[xchg2] = i.op[xchg1];
228694546Sobrien  i.op[xchg1] = temp_op;
228794546Sobrien  temp_reloc = i.reloc[xchg2];
228894546Sobrien  i.reloc[xchg2] = i.reloc[xchg1];
228994546Sobrien  i.reloc[xchg1] = temp_reloc;
2290218822Sdim}
229194546Sobrien
2292218822Sdimstatic void
2293218822Sdimswap_operands (void)
2294218822Sdim{
2295218822Sdim  switch (i.operands)
2296218822Sdim    {
2297218822Sdim    case 4:
2298218822Sdim      swap_2_operands (1, i.operands - 2);
2299218822Sdim    case 3:
2300218822Sdim    case 2:
2301218822Sdim      swap_2_operands (0, i.operands - 1);
2302218822Sdim      break;
2303218822Sdim    default:
2304218822Sdim      abort ();
2305218822Sdim    }
2306218822Sdim
230794546Sobrien  if (i.mem_operands == 2)
230894546Sobrien    {
230994546Sobrien      const seg_entry *temp_seg;
231094546Sobrien      temp_seg = i.seg[0];
231194546Sobrien      i.seg[0] = i.seg[1];
231294546Sobrien      i.seg[1] = temp_seg;
231394546Sobrien    }
231494546Sobrien}
231594546Sobrien
231694546Sobrien/* Try to ensure constant immediates are represented in the smallest
231794546Sobrien   opcode possible.  */
231894546Sobrienstatic void
2319218822Sdimoptimize_imm (void)
232094546Sobrien{
232194546Sobrien  char guess_suffix = 0;
232294546Sobrien  int op;
232394546Sobrien
232494546Sobrien  if (i.suffix)
232594546Sobrien    guess_suffix = i.suffix;
232694546Sobrien  else if (i.reg_operands)
232794546Sobrien    {
232894546Sobrien      /* Figure out a suffix from the last register operand specified.
232994546Sobrien	 We can't do this properly yet, ie. excluding InOutPortReg,
233094546Sobrien	 but the following works for instructions with immediates.
233194546Sobrien	 In any case, we can't set i.suffix yet.  */
233294546Sobrien      for (op = i.operands; --op >= 0;)
233394546Sobrien	if (i.types[op] & Reg)
233477311Sobrien	  {
233594546Sobrien	    if (i.types[op] & Reg8)
233694546Sobrien	      guess_suffix = BYTE_MNEM_SUFFIX;
233794546Sobrien	    else if (i.types[op] & Reg16)
233894546Sobrien	      guess_suffix = WORD_MNEM_SUFFIX;
233994546Sobrien	    else if (i.types[op] & Reg32)
234094546Sobrien	      guess_suffix = LONG_MNEM_SUFFIX;
234194546Sobrien	    else if (i.types[op] & Reg64)
234294546Sobrien	      guess_suffix = QWORD_MNEM_SUFFIX;
234377311Sobrien	    break;
234477311Sobrien	  }
234594546Sobrien    }
234694546Sobrien  else if ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0))
234794546Sobrien    guess_suffix = WORD_MNEM_SUFFIX;
234833965Sjdp
234994546Sobrien  for (op = i.operands; --op >= 0;)
235094546Sobrien    if (i.types[op] & Imm)
235194546Sobrien      {
235294546Sobrien	switch (i.op[op].imms->X_op)
235333965Sjdp	  {
235494546Sobrien	  case O_constant:
235594546Sobrien	    /* If a suffix is given, this operand may be shortened.  */
235694546Sobrien	    switch (guess_suffix)
235733965Sjdp	      {
235894546Sobrien	      case LONG_MNEM_SUFFIX:
235994546Sobrien		i.types[op] |= Imm32 | Imm64;
236094546Sobrien		break;
236194546Sobrien	      case WORD_MNEM_SUFFIX:
236294546Sobrien		i.types[op] |= Imm16 | Imm32S | Imm32 | Imm64;
236394546Sobrien		break;
236494546Sobrien	      case BYTE_MNEM_SUFFIX:
236594546Sobrien		i.types[op] |= Imm16 | Imm8 | Imm8S | Imm32S | Imm32 | Imm64;
236694546Sobrien		break;
236794546Sobrien	      }
236833965Sjdp
236994546Sobrien	    /* If this operand is at most 16 bits, convert it
237094546Sobrien	       to a signed 16 bit number before trying to see
237194546Sobrien	       whether it will fit in an even smaller size.
237294546Sobrien	       This allows a 16-bit operand such as $0xffe0 to
237394546Sobrien	       be recognised as within Imm8S range.  */
237494546Sobrien	    if ((i.types[op] & Imm16)
237594546Sobrien		&& (i.op[op].imms->X_add_number & ~(offsetT) 0xffff) == 0)
237694546Sobrien	      {
237794546Sobrien		i.op[op].imms->X_add_number =
237894546Sobrien		  (((i.op[op].imms->X_add_number & 0xffff) ^ 0x8000) - 0x8000);
237960519Sobrien	      }
238094546Sobrien	    if ((i.types[op] & Imm32)
238194546Sobrien		&& ((i.op[op].imms->X_add_number & ~(((offsetT) 2 << 31) - 1))
238294546Sobrien		    == 0))
238333965Sjdp	      {
238494546Sobrien		i.op[op].imms->X_add_number = ((i.op[op].imms->X_add_number
238594546Sobrien						^ ((offsetT) 1 << 31))
238694546Sobrien					       - ((offsetT) 1 << 31));
238794546Sobrien	      }
238894546Sobrien	    i.types[op] |= smallest_imm_type (i.op[op].imms->X_add_number);
238960519Sobrien
239094546Sobrien	    /* We must avoid matching of Imm32 templates when 64bit
239194546Sobrien	       only immediate is available.  */
239294546Sobrien	    if (guess_suffix == QWORD_MNEM_SUFFIX)
239394546Sobrien	      i.types[op] &= ~Imm32;
239494546Sobrien	    break;
239594546Sobrien
239694546Sobrien	  case O_absent:
239794546Sobrien	  case O_register:
239894546Sobrien	    abort ();
239994546Sobrien
240094546Sobrien	    /* Symbols and expressions.  */
240194546Sobrien	  default:
2402218822Sdim	    /* Convert symbolic operand to proper sizes for matching, but don't
2403218822Sdim	       prevent matching a set of insns that only supports sizes other
2404218822Sdim	       than those matching the insn suffix.  */
2405218822Sdim	    {
2406218822Sdim	      unsigned int mask, allowed = 0;
2407218822Sdim	      const template *t;
2408218822Sdim
2409218822Sdim	      for (t = current_templates->start;
2410218822Sdim		   t < current_templates->end;
2411218822Sdim		   ++t)
2412218822Sdim		allowed |= t->operand_types[op];
2413218822Sdim	      switch (guess_suffix)
2414218822Sdim		{
2415218822Sdim		case QWORD_MNEM_SUFFIX:
2416218822Sdim		  mask = Imm64 | Imm32S;
2417218822Sdim		  break;
2418218822Sdim		case LONG_MNEM_SUFFIX:
2419218822Sdim		  mask = Imm32;
2420218822Sdim		  break;
2421218822Sdim		case WORD_MNEM_SUFFIX:
2422218822Sdim		  mask = Imm16;
2423218822Sdim		  break;
2424218822Sdim		case BYTE_MNEM_SUFFIX:
2425218822Sdim		  mask = Imm8;
2426218822Sdim		  break;
2427218822Sdim		default:
2428218822Sdim		  mask = 0;
2429218822Sdim		  break;
2430218822Sdim		}
2431218822Sdim	      if (mask & allowed)
2432218822Sdim		i.types[op] &= mask;
2433218822Sdim	    }
243494546Sobrien	    break;
243533965Sjdp	  }
243677311Sobrien      }
243794546Sobrien}
243894546Sobrien
243994546Sobrien/* Try to use the smallest displacement type too.  */
244094546Sobrienstatic void
2441218822Sdimoptimize_disp (void)
244294546Sobrien{
244394546Sobrien  int op;
244494546Sobrien
244594546Sobrien  for (op = i.operands; --op >= 0;)
2446218822Sdim    if (i.types[op] & Disp)
244777311Sobrien      {
2448218822Sdim	if (i.op[op].disps->X_op == O_constant)
244977311Sobrien	  {
2450218822Sdim	    offsetT disp = i.op[op].disps->X_add_number;
245194546Sobrien
2452218822Sdim	    if ((i.types[op] & Disp16)
2453218822Sdim		&& (disp & ~(offsetT) 0xffff) == 0)
2454218822Sdim	      {
2455218822Sdim		/* If this operand is at most 16 bits, convert
2456218822Sdim		   to a signed 16 bit number and don't use 64bit
2457218822Sdim		   displacement.  */
2458218822Sdim		disp = (((disp & 0xffff) ^ 0x8000) - 0x8000);
2459218822Sdim		i.types[op] &= ~Disp64;
2460218822Sdim	      }
2461218822Sdim	    if ((i.types[op] & Disp32)
2462218822Sdim		&& (disp & ~(((offsetT) 2 << 31) - 1)) == 0)
2463218822Sdim	      {
2464218822Sdim		/* If this operand is at most 32 bits, convert
2465218822Sdim		   to a signed 32 bit number and don't use 64bit
2466218822Sdim		   displacement.  */
2467218822Sdim		disp &= (((offsetT) 2 << 31) - 1);
2468218822Sdim		disp = (disp ^ ((offsetT) 1 << 31)) - ((addressT) 1 << 31);
2469218822Sdim		i.types[op] &= ~Disp64;
2470218822Sdim	      }
2471218822Sdim	    if (!disp && (i.types[op] & BaseIndex))
2472218822Sdim	      {
2473218822Sdim		i.types[op] &= ~Disp;
2474218822Sdim		i.op[op].disps = 0;
2475218822Sdim		i.disp_operands--;
2476218822Sdim	      }
2477218822Sdim	    else if (flag_code == CODE_64BIT)
2478218822Sdim	      {
2479218822Sdim		if (fits_in_signed_long (disp))
2480218822Sdim		  {
2481218822Sdim		    i.types[op] &= ~Disp64;
2482218822Sdim		    i.types[op] |= Disp32S;
2483218822Sdim		  }
2484218822Sdim		if (fits_in_unsigned_long (disp))
2485218822Sdim		  i.types[op] |= Disp32;
2486218822Sdim	      }
2487218822Sdim	    if ((i.types[op] & (Disp32 | Disp32S | Disp16))
2488218822Sdim		&& fits_in_signed_byte (disp))
2489218822Sdim	      i.types[op] |= Disp8;
249077311Sobrien	  }
2491218822Sdim	else if (i.reloc[op] == BFD_RELOC_386_TLS_DESC_CALL
2492218822Sdim		 || i.reloc[op] == BFD_RELOC_X86_64_TLSDESC_CALL)
249377311Sobrien	  {
2494218822Sdim	    fix_new_exp (frag_now, frag_more (0) - frag_now->fr_literal, 0,
2495218822Sdim			 i.op[op].disps, 0, i.reloc[op]);
2496218822Sdim	    i.types[op] &= ~Disp;
249777311Sobrien	  }
2498218822Sdim 	else
2499218822Sdim	  /* We only support 64bit displacement on constants.  */
2500218822Sdim	  i.types[op] &= ~Disp64;
250160519Sobrien      }
250294546Sobrien}
250360519Sobrien
250494546Sobrienstatic int
2505218822Sdimmatch_template (void)
250694546Sobrien{
250794546Sobrien  /* Points to template once we've found it.  */
250894546Sobrien  const template *t;
2509218822Sdim  unsigned int overlap0, overlap1, overlap2, overlap3;
251094546Sobrien  unsigned int found_reverse_match;
251194546Sobrien  int suffix_check;
2512218822Sdim  unsigned int operand_types [MAX_OPERANDS];
2513218822Sdim  int addr_prefix_disp;
2514218822Sdim  unsigned int j;
251560519Sobrien
2516218822Sdim#if MAX_OPERANDS != 4
2517218822Sdim# error "MAX_OPERANDS must be 4."
2518218822Sdim#endif
2519218822Sdim
252094546Sobrien#define MATCH(overlap, given, template)				\
252194546Sobrien  ((overlap & ~JumpAbsolute)					\
252294546Sobrien   && (((given) & (BaseIndex | JumpAbsolute))			\
252394546Sobrien       == ((overlap) & (BaseIndex | JumpAbsolute))))
252460519Sobrien
252594546Sobrien  /* If given types r0 and r1 are registers they must be of the same type
252694546Sobrien     unless the expected operand type register overlap is null.
252794546Sobrien     Note that Acc in a template matches every size of reg.  */
252894546Sobrien#define CONSISTENT_REGISTER_MATCH(m0, g0, t0, m1, g1, t1)	\
252994546Sobrien  (((g0) & Reg) == 0 || ((g1) & Reg) == 0			\
253094546Sobrien   || ((g0) & Reg) == ((g1) & Reg)				\
253194546Sobrien   || ((((m0) & Acc) ? Reg : (t0)) & (((m1) & Acc) ? Reg : (t1)) & Reg) == 0 )
253238891Sjdp
253394546Sobrien  overlap0 = 0;
253494546Sobrien  overlap1 = 0;
253594546Sobrien  overlap2 = 0;
2536218822Sdim  overlap3 = 0;
253794546Sobrien  found_reverse_match = 0;
2538218822Sdim  for (j = 0; j < MAX_OPERANDS; j++)
2539218822Sdim    operand_types [j] = 0;
2540218822Sdim  addr_prefix_disp = -1;
254194546Sobrien  suffix_check = (i.suffix == BYTE_MNEM_SUFFIX
254294546Sobrien		  ? No_bSuf
254394546Sobrien		  : (i.suffix == WORD_MNEM_SUFFIX
254494546Sobrien		     ? No_wSuf
254594546Sobrien		     : (i.suffix == SHORT_MNEM_SUFFIX
254694546Sobrien			? No_sSuf
254794546Sobrien			: (i.suffix == LONG_MNEM_SUFFIX
254894546Sobrien			   ? No_lSuf
254994546Sobrien			   : (i.suffix == QWORD_MNEM_SUFFIX
255094546Sobrien			      ? No_qSuf
255194546Sobrien			      : (i.suffix == LONG_DOUBLE_MNEM_SUFFIX
255294546Sobrien				 ? No_xSuf : 0))))));
255360519Sobrien
2554218822Sdim  for (t = current_templates->start; t < current_templates->end; t++)
255594546Sobrien    {
2556218822Sdim      addr_prefix_disp = -1;
2557218822Sdim
255894546Sobrien      /* Must have right number of operands.  */
255994546Sobrien      if (i.operands != t->operands)
256094546Sobrien	continue;
256160519Sobrien
256294546Sobrien      /* Check the suffix, except for some instructions in intel mode.  */
256394546Sobrien      if ((t->opcode_modifier & suffix_check)
256494546Sobrien	  && !(intel_syntax
2565218822Sdim	       && (t->opcode_modifier & IgnoreSize)))
256694546Sobrien	continue;
256794546Sobrien
2568218822Sdim      for (j = 0; j < MAX_OPERANDS; j++)
2569218822Sdim	operand_types [j] = t->operand_types [j];
2570218822Sdim
2571218822Sdim      /* In general, don't allow 64-bit operands in 32-bit mode.  */
2572218822Sdim      if (i.suffix == QWORD_MNEM_SUFFIX
2573218822Sdim	  && flag_code != CODE_64BIT
2574218822Sdim	  && (intel_syntax
2575218822Sdim	      ? (!(t->opcode_modifier & IgnoreSize)
2576218822Sdim		 && !intel_float_operand (t->name))
2577218822Sdim	      : intel_float_operand (t->name) != 2)
2578218822Sdim	  && (!(operand_types[0] & (RegMMX | RegXMM))
2579218822Sdim	      || !(operand_types[t->operands > 1] & (RegMMX | RegXMM)))
2580218822Sdim	  && (t->base_opcode != 0x0fc7
2581218822Sdim	      || t->extension_opcode != 1 /* cmpxchg8b */))
2582218822Sdim	continue;
2583218822Sdim
258494546Sobrien      /* Do not verify operands when there are none.  */
258594546Sobrien      else if (!t->operands)
258694546Sobrien	{
258794546Sobrien	  if (t->cpu_flags & ~cpu_arch_flags)
258894546Sobrien	    continue;
258994546Sobrien	  /* We've found a match; break out of loop.  */
259094546Sobrien	  break;
259194546Sobrien	}
259294546Sobrien
2593218822Sdim      /* Address size prefix will turn Disp64/Disp32/Disp16 operand
2594218822Sdim	 into Disp32/Disp16/Disp32 operand.  */
2595218822Sdim      if (i.prefix[ADDR_PREFIX] != 0)
2596218822Sdim	  {
2597218822Sdim	    unsigned int DispOn = 0, DispOff = 0;
2598218822Sdim
2599218822Sdim	    switch (flag_code)
2600218822Sdim	    {
2601218822Sdim	    case CODE_16BIT:
2602218822Sdim	      DispOn = Disp32;
2603218822Sdim	      DispOff = Disp16;
2604218822Sdim	      break;
2605218822Sdim	    case CODE_32BIT:
2606218822Sdim	      DispOn = Disp16;
2607218822Sdim	      DispOff = Disp32;
2608218822Sdim	      break;
2609218822Sdim	    case CODE_64BIT:
2610218822Sdim	      DispOn = Disp32;
2611218822Sdim	      DispOff = Disp64;
2612218822Sdim	      break;
2613218822Sdim	    }
2614218822Sdim
2615218822Sdim	    for (j = 0; j < MAX_OPERANDS; j++)
2616218822Sdim	      {
2617218822Sdim		/* There should be only one Disp operand.  */
2618218822Sdim		if ((operand_types[j] & DispOff))
2619218822Sdim		  {
2620218822Sdim		    addr_prefix_disp = j;
2621218822Sdim		    operand_types[j] |= DispOn;
2622218822Sdim		    operand_types[j] &= ~DispOff;
2623218822Sdim		    break;
2624218822Sdim		  }
2625218822Sdim	      }
2626218822Sdim	  }
2627218822Sdim
2628218822Sdim      overlap0 = i.types[0] & operand_types[0];
262994546Sobrien      switch (t->operands)
263094546Sobrien	{
263194546Sobrien	case 1:
2632218822Sdim	  if (!MATCH (overlap0, i.types[0], operand_types[0]))
263394546Sobrien	    continue;
263494546Sobrien	  break;
263594546Sobrien	case 2:
2636218822Sdim	  /* xchg %eax, %eax is a special case. It is an aliase for nop
2637218822Sdim	     only in 32bit mode and we can use opcode 0x90.  In 64bit
2638218822Sdim	     mode, we can't use 0x90 for xchg %eax, %eax since it should
2639218822Sdim	     zero-extend %eax to %rax.  */
2640218822Sdim	  if (flag_code == CODE_64BIT
2641218822Sdim	      && t->base_opcode == 0x90
2642218822Sdim	      && i.types [0] == (Acc | Reg32)
2643218822Sdim	      && i.types [1] == (Acc | Reg32))
2644218822Sdim	    continue;
264594546Sobrien	case 3:
2646218822Sdim	case 4:
2647218822Sdim	  overlap1 = i.types[1] & operand_types[1];
2648218822Sdim	  if (!MATCH (overlap0, i.types[0], operand_types[0])
2649218822Sdim	      || !MATCH (overlap1, i.types[1], operand_types[1])
2650218822Sdim	      /* monitor in SSE3 is a very special case.  The first
2651218822Sdim		 register and the second register may have different
2652218822Sdim		 sizes.  The same applies to crc32 in SSE4.2.  */
2653218822Sdim	      || !((t->base_opcode == 0x0f01
2654218822Sdim		    && t->extension_opcode == 0xc8)
2655218822Sdim		   || t->base_opcode == 0xf20f38f1
2656218822Sdim		   || CONSISTENT_REGISTER_MATCH (overlap0, i.types[0],
2657218822Sdim						 operand_types[0],
2658218822Sdim						 overlap1, i.types[1],
2659218822Sdim						 operand_types[1])))
266094546Sobrien	    {
266194546Sobrien	      /* Check if other direction is valid ...  */
266294546Sobrien	      if ((t->opcode_modifier & (D | FloatD)) == 0)
266394546Sobrien		continue;
266494546Sobrien
266594546Sobrien	      /* Try reversing direction of operands.  */
2666218822Sdim	      overlap0 = i.types[0] & operand_types[1];
2667218822Sdim	      overlap1 = i.types[1] & operand_types[0];
2668218822Sdim	      if (!MATCH (overlap0, i.types[0], operand_types[1])
2669218822Sdim		  || !MATCH (overlap1, i.types[1], operand_types[0])
267094546Sobrien		  || !CONSISTENT_REGISTER_MATCH (overlap0, i.types[0],
2671218822Sdim						 operand_types[1],
267294546Sobrien						 overlap1, i.types[1],
2673218822Sdim						 operand_types[0]))
267494546Sobrien		{
267594546Sobrien		  /* Does not match either direction.  */
267694546Sobrien		  continue;
267794546Sobrien		}
267894546Sobrien	      /* found_reverse_match holds which of D or FloatDR
267994546Sobrien		 we've found.  */
2680218822Sdim	      if ((t->opcode_modifier & D))
2681218822Sdim		found_reverse_match = Opcode_D;
2682218822Sdim	      else if ((t->opcode_modifier & FloatD))
2683218822Sdim		found_reverse_match = Opcode_FloatD;
2684218822Sdim	      else
2685218822Sdim		found_reverse_match = 0;
2686218822Sdim	      if ((t->opcode_modifier & FloatR))
2687218822Sdim		found_reverse_match |= Opcode_FloatR;
268894546Sobrien	    }
2689218822Sdim	  else
269094546Sobrien	    {
2691218822Sdim	      /* Found a forward 2 operand match here.  */
2692218822Sdim	      switch (t->operands)
2693218822Sdim		{
2694218822Sdim		case 4:
2695218822Sdim		  overlap3 = i.types[3] & operand_types[3];
2696218822Sdim		case 3:
2697218822Sdim		  overlap2 = i.types[2] & operand_types[2];
2698218822Sdim		  break;
2699218822Sdim		}
270094546Sobrien
2701218822Sdim	      switch (t->operands)
2702218822Sdim		{
2703218822Sdim		case 4:
2704218822Sdim		  if (!MATCH (overlap3, i.types[3], operand_types[3])
2705218822Sdim		      || !CONSISTENT_REGISTER_MATCH (overlap2,
2706218822Sdim						     i.types[2],
2707218822Sdim						     operand_types[2],
2708218822Sdim						     overlap3,
2709218822Sdim						     i.types[3],
2710218822Sdim						     operand_types[3]))
2711218822Sdim		    continue;
2712218822Sdim		case 3:
2713218822Sdim		  /* Here we make use of the fact that there are no
2714218822Sdim		     reverse match 3 operand instructions, and all 3
2715218822Sdim		     operand instructions only need to be checked for
2716218822Sdim		     register consistency between operands 2 and 3.  */
2717218822Sdim		  if (!MATCH (overlap2, i.types[2], operand_types[2])
2718218822Sdim		      || !CONSISTENT_REGISTER_MATCH (overlap1,
2719218822Sdim						     i.types[1],
2720218822Sdim						     operand_types[1],
2721218822Sdim						     overlap2,
2722218822Sdim						     i.types[2],
2723218822Sdim						     operand_types[2]))
2724218822Sdim		    continue;
2725218822Sdim		  break;
2726218822Sdim		}
272794546Sobrien	    }
2728218822Sdim	  /* Found either forward/reverse 2, 3 or 4 operand match here:
272994546Sobrien	     slip through to break.  */
273094546Sobrien	}
273194546Sobrien      if (t->cpu_flags & ~cpu_arch_flags)
273294546Sobrien	{
273394546Sobrien	  found_reverse_match = 0;
273494546Sobrien	  continue;
273594546Sobrien	}
273694546Sobrien      /* We've found a match; break out of loop.  */
273794546Sobrien      break;
273894546Sobrien    }
273994546Sobrien
274094546Sobrien  if (t == current_templates->end)
274194546Sobrien    {
274294546Sobrien      /* We found no match.  */
274394546Sobrien      as_bad (_("suffix or operands invalid for `%s'"),
274494546Sobrien	      current_templates->start->name);
274594546Sobrien      return 0;
274694546Sobrien    }
274794546Sobrien
274894546Sobrien  if (!quiet_warnings)
274994546Sobrien    {
275094546Sobrien      if (!intel_syntax
275194546Sobrien	  && ((i.types[0] & JumpAbsolute)
2752218822Sdim	      != (operand_types[0] & JumpAbsolute)))
275394546Sobrien	{
275494546Sobrien	  as_warn (_("indirect %s without `*'"), t->name);
275594546Sobrien	}
275694546Sobrien
275794546Sobrien      if ((t->opcode_modifier & (IsPrefix | IgnoreSize))
275894546Sobrien	  == (IsPrefix | IgnoreSize))
275994546Sobrien	{
276094546Sobrien	  /* Warn them that a data or address size prefix doesn't
276194546Sobrien	     affect assembly of the next line of code.  */
276294546Sobrien	  as_warn (_("stand-alone `%s' prefix"), t->name);
276394546Sobrien	}
276494546Sobrien    }
276594546Sobrien
276694546Sobrien  /* Copy the template we found.  */
276794546Sobrien  i.tm = *t;
2768218822Sdim
2769218822Sdim  if (addr_prefix_disp != -1)
2770218822Sdim    i.tm.operand_types[addr_prefix_disp]
2771218822Sdim      = operand_types[addr_prefix_disp];
2772218822Sdim
277394546Sobrien  if (found_reverse_match)
277494546Sobrien    {
277594546Sobrien      /* If we found a reverse match we must alter the opcode
277694546Sobrien	 direction bit.  found_reverse_match holds bits to change
277794546Sobrien	 (different for int & float insns).  */
277894546Sobrien
277994546Sobrien      i.tm.base_opcode ^= found_reverse_match;
278094546Sobrien
2781218822Sdim      i.tm.operand_types[0] = operand_types[1];
2782218822Sdim      i.tm.operand_types[1] = operand_types[0];
278394546Sobrien    }
278494546Sobrien
278594546Sobrien  return 1;
278694546Sobrien}
278794546Sobrien
278894546Sobrienstatic int
2789218822Sdimcheck_string (void)
279094546Sobrien{
279194546Sobrien  int mem_op = (i.types[0] & AnyMem) ? 0 : 1;
279294546Sobrien  if ((i.tm.operand_types[mem_op] & EsSeg) != 0)
279394546Sobrien    {
279494546Sobrien      if (i.seg[0] != NULL && i.seg[0] != &es)
279594546Sobrien	{
279694546Sobrien	  as_bad (_("`%s' operand %d must use `%%es' segment"),
279794546Sobrien		  i.tm.name,
279894546Sobrien		  mem_op + 1);
279994546Sobrien	  return 0;
280094546Sobrien	}
280194546Sobrien      /* There's only ever one segment override allowed per instruction.
280294546Sobrien	 This instruction possibly has a legal segment override on the
280394546Sobrien	 second operand, so copy the segment to where non-string
280494546Sobrien	 instructions store it, allowing common code.  */
280594546Sobrien      i.seg[0] = i.seg[1];
280694546Sobrien    }
280794546Sobrien  else if ((i.tm.operand_types[mem_op + 1] & EsSeg) != 0)
280894546Sobrien    {
280994546Sobrien      if (i.seg[1] != NULL && i.seg[1] != &es)
281094546Sobrien	{
281194546Sobrien	  as_bad (_("`%s' operand %d must use `%%es' segment"),
281294546Sobrien		  i.tm.name,
281394546Sobrien		  mem_op + 2);
281494546Sobrien	  return 0;
281594546Sobrien	}
281694546Sobrien    }
281794546Sobrien  return 1;
281894546Sobrien}
281994546Sobrien
282094546Sobrienstatic int
2821218822Sdimprocess_suffix (void)
282294546Sobrien{
282394546Sobrien  /* If matched instruction specifies an explicit instruction mnemonic
282494546Sobrien     suffix, use it.  */
282594546Sobrien  if (i.tm.opcode_modifier & (Size16 | Size32 | Size64))
282694546Sobrien    {
282794546Sobrien      if (i.tm.opcode_modifier & Size16)
282894546Sobrien	i.suffix = WORD_MNEM_SUFFIX;
282994546Sobrien      else if (i.tm.opcode_modifier & Size64)
283094546Sobrien	i.suffix = QWORD_MNEM_SUFFIX;
283194546Sobrien      else
283294546Sobrien	i.suffix = LONG_MNEM_SUFFIX;
283394546Sobrien    }
283494546Sobrien  else if (i.reg_operands)
283594546Sobrien    {
283694546Sobrien      /* If there's no instruction mnemonic suffix we try to invent one
283794546Sobrien	 based on register operands.  */
283894546Sobrien      if (!i.suffix)
283994546Sobrien	{
284094546Sobrien	  /* We take i.suffix from the last register operand specified,
284194546Sobrien	     Destination register type is more significant than source
2842218822Sdim	     register type.  crc32 in SSE4.2 prefers source register
2843218822Sdim	     type. */
2844218822Sdim	  if (i.tm.base_opcode == 0xf20f38f1)
2845218822Sdim	    {
2846218822Sdim	      if ((i.types[0] & Reg))
2847218822Sdim		i.suffix = ((i.types[0] & Reg16) ? WORD_MNEM_SUFFIX :
284894546Sobrien			    LONG_MNEM_SUFFIX);
2849218822Sdim	    }
2850218822Sdim	  else if (i.tm.base_opcode == 0xf20f38f0)
2851218822Sdim	    {
2852218822Sdim	      if ((i.types[0] & Reg8))
2853218822Sdim		i.suffix = BYTE_MNEM_SUFFIX;
2854218822Sdim	    }
2855218822Sdim
2856218822Sdim	  if (!i.suffix)
2857218822Sdim	    {
2858218822Sdim	      int op;
2859218822Sdim
2860218822Sdim	      if (i.tm.base_opcode == 0xf20f38f1
2861218822Sdim		  || i.tm.base_opcode == 0xf20f38f0)
2862218822Sdim		{
2863218822Sdim		  /* We have to know the operand size for crc32.  */
2864218822Sdim		  as_bad (_("ambiguous memory operand size for `%s`"),
2865218822Sdim			  i.tm.name);
2866218822Sdim		  return 0;
2867218822Sdim		}
2868218822Sdim
2869218822Sdim	      for (op = i.operands; --op >= 0;)
2870218822Sdim		if ((i.types[op] & Reg)
2871218822Sdim		    && !(i.tm.operand_types[op] & InOutPortReg))
2872218822Sdim		  {
2873218822Sdim		    i.suffix = ((i.types[op] & Reg8) ? BYTE_MNEM_SUFFIX :
2874218822Sdim				(i.types[op] & Reg16) ? WORD_MNEM_SUFFIX :
2875218822Sdim				(i.types[op] & Reg64) ? QWORD_MNEM_SUFFIX :
2876218822Sdim				LONG_MNEM_SUFFIX);
2877218822Sdim		    break;
2878218822Sdim		  }
2879218822Sdim	    }
288094546Sobrien	}
288194546Sobrien      else if (i.suffix == BYTE_MNEM_SUFFIX)
288294546Sobrien	{
288394546Sobrien	  if (!check_byte_reg ())
288494546Sobrien	    return 0;
288594546Sobrien	}
288694546Sobrien      else if (i.suffix == LONG_MNEM_SUFFIX)
288794546Sobrien	{
288894546Sobrien	  if (!check_long_reg ())
288994546Sobrien	    return 0;
289094546Sobrien	}
289194546Sobrien      else if (i.suffix == QWORD_MNEM_SUFFIX)
289294546Sobrien	{
289394546Sobrien	  if (!check_qword_reg ())
289494546Sobrien	    return 0;
289594546Sobrien	}
289694546Sobrien      else if (i.suffix == WORD_MNEM_SUFFIX)
289794546Sobrien	{
289894546Sobrien	  if (!check_word_reg ())
289994546Sobrien	    return 0;
290094546Sobrien	}
290194546Sobrien      else if (intel_syntax && (i.tm.opcode_modifier & IgnoreSize))
290294546Sobrien	/* Do nothing if the instruction is going to ignore the prefix.  */
290394546Sobrien	;
290494546Sobrien      else
290594546Sobrien	abort ();
290694546Sobrien    }
2907218822Sdim  else if ((i.tm.opcode_modifier & DefaultSize)
2908218822Sdim	   && !i.suffix
2909218822Sdim	   /* exclude fldenv/frstor/fsave/fstenv */
2910218822Sdim	   && (i.tm.opcode_modifier & No_sSuf))
291194546Sobrien    {
291294546Sobrien      i.suffix = stackop_size;
291394546Sobrien    }
2914218822Sdim  else if (intel_syntax
2915218822Sdim	   && !i.suffix
2916218822Sdim	   && ((i.tm.operand_types[0] & JumpAbsolute)
2917218822Sdim	       || (i.tm.opcode_modifier & (JumpByte|JumpInterSegment))
2918218822Sdim	       || (i.tm.base_opcode == 0x0f01 /* [ls][gi]dt */
2919218822Sdim		   && i.tm.extension_opcode <= 3)))
2920218822Sdim    {
2921218822Sdim      switch (flag_code)
2922218822Sdim	{
2923218822Sdim	case CODE_64BIT:
2924218822Sdim	  if (!(i.tm.opcode_modifier & No_qSuf))
2925218822Sdim	    {
2926218822Sdim	      i.suffix = QWORD_MNEM_SUFFIX;
2927218822Sdim	      break;
2928218822Sdim	    }
2929218822Sdim	case CODE_32BIT:
2930218822Sdim	  if (!(i.tm.opcode_modifier & No_lSuf))
2931218822Sdim	    i.suffix = LONG_MNEM_SUFFIX;
2932218822Sdim	  break;
2933218822Sdim	case CODE_16BIT:
2934218822Sdim	  if (!(i.tm.opcode_modifier & No_wSuf))
2935218822Sdim	    i.suffix = WORD_MNEM_SUFFIX;
2936218822Sdim	  break;
2937218822Sdim	}
2938218822Sdim    }
293933965Sjdp
2940218822Sdim  if (!i.suffix)
2941218822Sdim    {
2942218822Sdim      if (!intel_syntax)
2943218822Sdim	{
2944218822Sdim	  if (i.tm.opcode_modifier & W)
2945218822Sdim	    {
2946218822Sdim	      as_bad (_("no instruction mnemonic suffix given and "
2947218822Sdim			"no register operands; can't size instruction"));
2948218822Sdim	      return 0;
2949218822Sdim	    }
2950218822Sdim	}
2951218822Sdim      else
2952218822Sdim	{
2953218822Sdim	  unsigned int suffixes = (~i.tm.opcode_modifier
2954218822Sdim				   & (No_bSuf
2955218822Sdim				      | No_wSuf
2956218822Sdim				      | No_lSuf
2957218822Sdim				      | No_sSuf
2958218822Sdim				      | No_xSuf
2959218822Sdim				      | No_qSuf));
296094546Sobrien
2961218822Sdim	  if ((i.tm.opcode_modifier & W)
2962218822Sdim	      || ((suffixes & (suffixes - 1))
2963218822Sdim		  && !(i.tm.opcode_modifier & (DefaultSize | IgnoreSize))))
2964218822Sdim	    {
2965218822Sdim	      as_bad (_("ambiguous operand size for `%s'"), i.tm.name);
2966218822Sdim	      return 0;
2967218822Sdim	    }
2968218822Sdim	}
296994546Sobrien    }
297094546Sobrien
2971218822Sdim  /* Change the opcode based on the operand size given by i.suffix;
2972218822Sdim     We don't need to change things for byte insns.  */
2973218822Sdim
297494546Sobrien  if (i.suffix && i.suffix != BYTE_MNEM_SUFFIX)
297594546Sobrien    {
297694546Sobrien      /* It's not a byte, select word/dword operation.  */
297794546Sobrien      if (i.tm.opcode_modifier & W)
297894546Sobrien	{
297994546Sobrien	  if (i.tm.opcode_modifier & ShortForm)
298094546Sobrien	    i.tm.base_opcode |= 8;
298194546Sobrien	  else
298294546Sobrien	    i.tm.base_opcode |= 1;
298394546Sobrien	}
298499468Sobrien
298594546Sobrien      /* Now select between word & dword operations via the operand
298694546Sobrien	 size prefix, except for instructions that will ignore this
298794546Sobrien	 prefix anyway.  */
2988218822Sdim      if (i.tm.base_opcode == 0x0f01 && i.tm.extension_opcode == 0xc8)
298994546Sobrien	{
2990218822Sdim	  /* monitor in SSE3 is a very special case. The default size
2991218822Sdim	     of AX is the size of mode. The address size override
2992218822Sdim	     prefix will change the size of AX.  */
2993218822Sdim	  if (i.op->regs[0].reg_type &
2994218822Sdim	      (flag_code == CODE_32BIT ? Reg16 : Reg32))
2995218822Sdim	    if (!add_prefix (ADDR_PREFIX_OPCODE))
2996218822Sdim	      return 0;
2997218822Sdim	}
2998218822Sdim      else if (i.suffix != QWORD_MNEM_SUFFIX
2999218822Sdim	       && i.suffix != LONG_DOUBLE_MNEM_SUFFIX
3000218822Sdim	       && !(i.tm.opcode_modifier & (IgnoreSize | FloatMF))
3001218822Sdim	       && ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT)
3002218822Sdim		   || (flag_code == CODE_64BIT
3003218822Sdim		       && (i.tm.opcode_modifier & JumpByte))))
3004218822Sdim	{
300594546Sobrien	  unsigned int prefix = DATA_PREFIX_OPCODE;
3006218822Sdim
300794546Sobrien	  if (i.tm.opcode_modifier & JumpByte) /* jcxz, loop */
300894546Sobrien	    prefix = ADDR_PREFIX_OPCODE;
300933965Sjdp
301094546Sobrien	  if (!add_prefix (prefix))
301194546Sobrien	    return 0;
301294546Sobrien	}
301394546Sobrien
301494546Sobrien      /* Set mode64 for an operand.  */
301594546Sobrien      if (i.suffix == QWORD_MNEM_SUFFIX
3016104848Sobrien	  && flag_code == CODE_64BIT
301794546Sobrien	  && (i.tm.opcode_modifier & NoRex64) == 0)
3018218822Sdim	{
3019218822Sdim	  /* Special case for xchg %rax,%rax.  It is NOP and doesn't
3020218822Sdim	     need rex64.  */
3021218822Sdim	  if (i.operands != 2
3022218822Sdim	      || i.types [0] != (Acc | Reg64)
3023218822Sdim	      || i.types [1] != (Acc | Reg64)
3024218822Sdim	      || i.tm.base_opcode != 0x90)
3025218822Sdim	    i.rex |= REX_W;
3026218822Sdim	}
302794546Sobrien
302894546Sobrien      /* Size floating point instruction.  */
302994546Sobrien      if (i.suffix == LONG_MNEM_SUFFIX)
3030218822Sdim	if (i.tm.opcode_modifier & FloatMF)
3031218822Sdim	  i.tm.base_opcode ^= 4;
303294546Sobrien    }
303394546Sobrien
303494546Sobrien  return 1;
303594546Sobrien}
303694546Sobrien
303794546Sobrienstatic int
3038218822Sdimcheck_byte_reg (void)
303994546Sobrien{
304094546Sobrien  int op;
3041218822Sdim
304294546Sobrien  for (op = i.operands; --op >= 0;)
304394546Sobrien    {
304494546Sobrien      /* If this is an eight bit register, it's OK.  If it's the 16 or
304594546Sobrien	 32 bit version of an eight bit register, we will just use the
304694546Sobrien	 low portion, and that's OK too.  */
304794546Sobrien      if (i.types[op] & Reg8)
304894546Sobrien	continue;
304994546Sobrien
305094546Sobrien      /* movzx and movsx should not generate this warning.  */
305194546Sobrien      if (intel_syntax
305294546Sobrien	  && (i.tm.base_opcode == 0xfb7
305394546Sobrien	      || i.tm.base_opcode == 0xfb6
305494546Sobrien	      || i.tm.base_opcode == 0x63
305594546Sobrien	      || i.tm.base_opcode == 0xfbe
305694546Sobrien	      || i.tm.base_opcode == 0xfbf))
305794546Sobrien	continue;
305894546Sobrien
3059218822Sdim      /* crc32 doesn't generate this warning.  */
3060218822Sdim      if (i.tm.base_opcode == 0xf20f38f0)
3061218822Sdim	continue;
3062218822Sdim
3063218822Sdim      if ((i.types[op] & WordReg) && i.op[op].regs->reg_num < 4)
306494546Sobrien	{
306594546Sobrien	  /* Prohibit these changes in the 64bit mode, since the
306694546Sobrien	     lowering is more complicated.  */
306794546Sobrien	  if (flag_code == CODE_64BIT
306894546Sobrien	      && (i.tm.operand_types[op] & InOutPortReg) == 0)
306994546Sobrien	    {
3070218822Sdim	      as_bad (_("Incorrect register `%s%s' used with `%c' suffix"),
3071218822Sdim		      register_prefix, i.op[op].regs->reg_name,
307294546Sobrien		      i.suffix);
307394546Sobrien	      return 0;
307494546Sobrien	    }
307560519Sobrien#if REGISTER_WARNINGS
307694546Sobrien	  if (!quiet_warnings
307794546Sobrien	      && (i.tm.operand_types[op] & InOutPortReg) == 0)
3078218822Sdim	    as_warn (_("using `%s%s' instead of `%s%s' due to `%c' suffix"),
3079218822Sdim		     register_prefix,
308094546Sobrien		     (i.op[op].regs + (i.types[op] & Reg16
308194546Sobrien				       ? REGNAM_AL - REGNAM_AX
308294546Sobrien				       : REGNAM_AL - REGNAM_EAX))->reg_name,
3083218822Sdim		     register_prefix,
308494546Sobrien		     i.op[op].regs->reg_name,
308594546Sobrien		     i.suffix);
308660519Sobrien#endif
308794546Sobrien	  continue;
308894546Sobrien	}
308994546Sobrien      /* Any other register is bad.  */
309094546Sobrien      if (i.types[op] & (Reg | RegMMX | RegXMM
309194546Sobrien			 | SReg2 | SReg3
309294546Sobrien			 | Control | Debug | Test
309394546Sobrien			 | FloatReg | FloatAcc))
309494546Sobrien	{
3095218822Sdim	  as_bad (_("`%s%s' not allowed with `%s%c'"),
3096218822Sdim		  register_prefix,
309794546Sobrien		  i.op[op].regs->reg_name,
309894546Sobrien		  i.tm.name,
309994546Sobrien		  i.suffix);
310094546Sobrien	  return 0;
310194546Sobrien	}
310294546Sobrien    }
310394546Sobrien  return 1;
310494546Sobrien}
310577311Sobrien
310694546Sobrienstatic int
3107218822Sdimcheck_long_reg (void)
310894546Sobrien{
310994546Sobrien  int op;
311077311Sobrien
311194546Sobrien  for (op = i.operands; --op >= 0;)
311294546Sobrien    /* Reject eight bit registers, except where the template requires
311394546Sobrien       them. (eg. movzb)  */
311494546Sobrien    if ((i.types[op] & Reg8) != 0
311594546Sobrien	&& (i.tm.operand_types[op] & (Reg16 | Reg32 | Acc)) != 0)
311660519Sobrien      {
3117218822Sdim	as_bad (_("`%s%s' not allowed with `%s%c'"),
3118218822Sdim		register_prefix,
311994546Sobrien		i.op[op].regs->reg_name,
312094546Sobrien		i.tm.name,
312194546Sobrien		i.suffix);
312294546Sobrien	return 0;
312360519Sobrien      }
312494546Sobrien  /* Warn if the e prefix on a general reg is missing.  */
312594546Sobrien    else if ((!quiet_warnings || flag_code == CODE_64BIT)
312694546Sobrien	     && (i.types[op] & Reg16) != 0
312794546Sobrien	     && (i.tm.operand_types[op] & (Reg32 | Acc)) != 0)
312833965Sjdp      {
312994546Sobrien	/* Prohibit these changes in the 64bit mode, since the
313094546Sobrien	   lowering is more complicated.  */
313194546Sobrien	if (flag_code == CODE_64BIT)
313233965Sjdp	  {
3133218822Sdim	    as_bad (_("Incorrect register `%s%s' used with `%c' suffix"),
3134218822Sdim		    register_prefix, i.op[op].regs->reg_name,
313594546Sobrien		    i.suffix);
313694546Sobrien	    return 0;
313760519Sobrien	  }
313894546Sobrien#if REGISTER_WARNINGS
313994546Sobrien	else
3140218822Sdim	  as_warn (_("using `%s%s' instead of `%s%s' due to `%c' suffix"),
3141218822Sdim		   register_prefix,
314294546Sobrien		   (i.op[op].regs + REGNAM_EAX - REGNAM_AX)->reg_name,
3143218822Sdim		   register_prefix,
314494546Sobrien		   i.op[op].regs->reg_name,
314594546Sobrien		   i.suffix);
314694546Sobrien#endif
314733965Sjdp      }
314894546Sobrien  /* Warn if the r prefix on a general reg is missing.  */
314994546Sobrien    else if ((i.types[op] & Reg64) != 0
315094546Sobrien	     && (i.tm.operand_types[op] & (Reg32 | Acc)) != 0)
315133965Sjdp      {
3152218822Sdim	as_bad (_("Incorrect register `%s%s' used with `%c' suffix"),
3153218822Sdim		register_prefix, i.op[op].regs->reg_name,
315494546Sobrien		i.suffix);
315594546Sobrien	return 0;
315633965Sjdp      }
315794546Sobrien  return 1;
315894546Sobrien}
315933965Sjdp
316094546Sobrienstatic int
3161218822Sdimcheck_qword_reg (void)
316294546Sobrien{
316394546Sobrien  int op;
316460519Sobrien
316594546Sobrien  for (op = i.operands; --op >= 0; )
316694546Sobrien    /* Reject eight bit registers, except where the template requires
316794546Sobrien       them. (eg. movzb)  */
316894546Sobrien    if ((i.types[op] & Reg8) != 0
316994546Sobrien	&& (i.tm.operand_types[op] & (Reg16 | Reg32 | Acc)) != 0)
317033965Sjdp      {
3171218822Sdim	as_bad (_("`%s%s' not allowed with `%s%c'"),
3172218822Sdim		register_prefix,
317394546Sobrien		i.op[op].regs->reg_name,
317494546Sobrien		i.tm.name,
317594546Sobrien		i.suffix);
317694546Sobrien	return 0;
317733965Sjdp      }
317894546Sobrien  /* Warn if the e prefix on a general reg is missing.  */
317994546Sobrien    else if (((i.types[op] & Reg16) != 0
318094546Sobrien	      || (i.types[op] & Reg32) != 0)
318194546Sobrien	     && (i.tm.operand_types[op] & (Reg32 | Acc)) != 0)
318294546Sobrien      {
318394546Sobrien	/* Prohibit these changes in the 64bit mode, since the
318494546Sobrien	   lowering is more complicated.  */
3185218822Sdim	as_bad (_("Incorrect register `%s%s' used with `%c' suffix"),
3186218822Sdim		register_prefix, i.op[op].regs->reg_name,
318794546Sobrien		i.suffix);
318894546Sobrien	return 0;
318994546Sobrien      }
319094546Sobrien  return 1;
319194546Sobrien}
319233965Sjdp
319394546Sobrienstatic int
3194218822Sdimcheck_word_reg (void)
319594546Sobrien{
319694546Sobrien  int op;
319794546Sobrien  for (op = i.operands; --op >= 0;)
319894546Sobrien    /* Reject eight bit registers, except where the template requires
319994546Sobrien       them. (eg. movzb)  */
320094546Sobrien    if ((i.types[op] & Reg8) != 0
320194546Sobrien	&& (i.tm.operand_types[op] & (Reg16 | Reg32 | Acc)) != 0)
320233965Sjdp      {
3203218822Sdim	as_bad (_("`%s%s' not allowed with `%s%c'"),
3204218822Sdim		register_prefix,
320594546Sobrien		i.op[op].regs->reg_name,
320694546Sobrien		i.tm.name,
320794546Sobrien		i.suffix);
320894546Sobrien	return 0;
320994546Sobrien      }
321094546Sobrien  /* Warn if the e prefix on a general reg is present.  */
321194546Sobrien    else if ((!quiet_warnings || flag_code == CODE_64BIT)
321294546Sobrien	     && (i.types[op] & Reg32) != 0
321394546Sobrien	     && (i.tm.operand_types[op] & (Reg16 | Acc)) != 0)
321494546Sobrien      {
321594546Sobrien	/* Prohibit these changes in the 64bit mode, since the
321694546Sobrien	   lowering is more complicated.  */
321794546Sobrien	if (flag_code == CODE_64BIT)
321833965Sjdp	  {
3219218822Sdim	    as_bad (_("Incorrect register `%s%s' used with `%c' suffix"),
3220218822Sdim		    register_prefix, i.op[op].regs->reg_name,
322194546Sobrien		    i.suffix);
322294546Sobrien	    return 0;
322333965Sjdp	  }
322494546Sobrien	else
322594546Sobrien#if REGISTER_WARNINGS
3226218822Sdim	  as_warn (_("using `%s%s' instead of `%s%s' due to `%c' suffix"),
3227218822Sdim		   register_prefix,
322894546Sobrien		   (i.op[op].regs + REGNAM_AX - REGNAM_EAX)->reg_name,
3229218822Sdim		   register_prefix,
323094546Sobrien		   i.op[op].regs->reg_name,
323194546Sobrien		   i.suffix);
323294546Sobrien#endif
323394546Sobrien      }
323494546Sobrien  return 1;
323594546Sobrien}
323660519Sobrien
323794546Sobrienstatic int
3238218822Sdimfinalize_imm (void)
323994546Sobrien{
324094546Sobrien  unsigned int overlap0, overlap1, overlap2;
324177311Sobrien
324294546Sobrien  overlap0 = i.types[0] & i.tm.operand_types[0];
3243218822Sdim  if ((overlap0 & (Imm8 | Imm8S | Imm16 | Imm32 | Imm32S | Imm64))
324494546Sobrien      && overlap0 != Imm8 && overlap0 != Imm8S
324594546Sobrien      && overlap0 != Imm16 && overlap0 != Imm32S
324694546Sobrien      && overlap0 != Imm32 && overlap0 != Imm64)
324794546Sobrien    {
324894546Sobrien      if (i.suffix)
324994546Sobrien	{
325094546Sobrien	  overlap0 &= (i.suffix == BYTE_MNEM_SUFFIX
325194546Sobrien		       ? Imm8 | Imm8S
325294546Sobrien		       : (i.suffix == WORD_MNEM_SUFFIX
325394546Sobrien			  ? Imm16
325494546Sobrien			  : (i.suffix == QWORD_MNEM_SUFFIX
325594546Sobrien			     ? Imm64 | Imm32S
325694546Sobrien			     : Imm32)));
325794546Sobrien	}
325894546Sobrien      else if (overlap0 == (Imm16 | Imm32S | Imm32)
325994546Sobrien	       || overlap0 == (Imm16 | Imm32)
326094546Sobrien	       || overlap0 == (Imm16 | Imm32S))
326194546Sobrien	{
326294546Sobrien	  overlap0 = ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0)
326394546Sobrien		      ? Imm16 : Imm32S);
326494546Sobrien	}
326594546Sobrien      if (overlap0 != Imm8 && overlap0 != Imm8S
326694546Sobrien	  && overlap0 != Imm16 && overlap0 != Imm32S
326794546Sobrien	  && overlap0 != Imm32 && overlap0 != Imm64)
326894546Sobrien	{
3269218822Sdim	  as_bad (_("no instruction mnemonic suffix given; "
3270218822Sdim		    "can't determine immediate size"));
327194546Sobrien	  return 0;
327294546Sobrien	}
327394546Sobrien    }
327494546Sobrien  i.types[0] = overlap0;
327591054Sobrien
327694546Sobrien  overlap1 = i.types[1] & i.tm.operand_types[1];
3277218822Sdim  if ((overlap1 & (Imm8 | Imm8S | Imm16 | Imm32S | Imm32 | Imm64))
327894546Sobrien      && overlap1 != Imm8 && overlap1 != Imm8S
327994546Sobrien      && overlap1 != Imm16 && overlap1 != Imm32S
328094546Sobrien      && overlap1 != Imm32 && overlap1 != Imm64)
328194546Sobrien    {
328294546Sobrien      if (i.suffix)
328394546Sobrien	{
328494546Sobrien	  overlap1 &= (i.suffix == BYTE_MNEM_SUFFIX
328594546Sobrien		       ? Imm8 | Imm8S
328694546Sobrien		       : (i.suffix == WORD_MNEM_SUFFIX
328794546Sobrien			  ? Imm16
328894546Sobrien			  : (i.suffix == QWORD_MNEM_SUFFIX
328994546Sobrien			     ? Imm64 | Imm32S
329094546Sobrien			     : Imm32)));
329194546Sobrien	}
329294546Sobrien      else if (overlap1 == (Imm16 | Imm32 | Imm32S)
329394546Sobrien	       || overlap1 == (Imm16 | Imm32)
329494546Sobrien	       || overlap1 == (Imm16 | Imm32S))
329594546Sobrien	{
329694546Sobrien	  overlap1 = ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0)
329794546Sobrien		      ? Imm16 : Imm32S);
329894546Sobrien	}
329994546Sobrien      if (overlap1 != Imm8 && overlap1 != Imm8S
330094546Sobrien	  && overlap1 != Imm16 && overlap1 != Imm32S
330194546Sobrien	  && overlap1 != Imm32 && overlap1 != Imm64)
330294546Sobrien	{
3303218822Sdim	  as_bad (_("no instruction mnemonic suffix given; "
3304218822Sdim		    "can't determine immediate size %x %c"),
3305218822Sdim		  overlap1, i.suffix);
330694546Sobrien	  return 0;
330794546Sobrien	}
330894546Sobrien    }
330994546Sobrien  i.types[1] = overlap1;
331077311Sobrien
331194546Sobrien  overlap2 = i.types[2] & i.tm.operand_types[2];
331294546Sobrien  assert ((overlap2 & Imm) == 0);
331394546Sobrien  i.types[2] = overlap2;
331433965Sjdp
331594546Sobrien  return 1;
331694546Sobrien}
331760519Sobrien
331894546Sobrienstatic int
3319218822Sdimprocess_operands (void)
332094546Sobrien{
332194546Sobrien  /* Default segment register this instruction will use for memory
332294546Sobrien     accesses.  0 means unknown.  This is only for optimizing out
332394546Sobrien     unnecessary segment overrides.  */
332494546Sobrien  const seg_entry *default_seg = 0;
332560519Sobrien
332694546Sobrien  /* The imul $imm, %reg instruction is converted into
332794546Sobrien     imul $imm, %reg, %reg, and the clr %reg instruction
332894546Sobrien     is converted into xor %reg, %reg.  */
3329218822Sdim  if (i.tm.opcode_modifier & RegKludge)
333094546Sobrien    {
3331218822Sdim       if ((i.tm.cpu_flags & CpuSSE4_1))
3332218822Sdim	 {
3333218822Sdim	   /* The first operand in instruction blendvpd, blendvps and
3334218822Sdim	      pblendvb in SSE4.1 is implicit and must be xmm0.  */
3335218822Sdim	   assert (i.operands == 3
3336218822Sdim		   && i.reg_operands >= 2
3337218822Sdim		   && i.types[0] == RegXMM);
3338218822Sdim	   if (i.op[0].regs->reg_num != 0)
3339218822Sdim	     {
3340218822Sdim	       if (intel_syntax)
3341218822Sdim		 as_bad (_("the last operand of `%s' must be `%sxmm0'"),
3342218822Sdim			 i.tm.name, register_prefix);
3343218822Sdim	       else
3344218822Sdim		 as_bad (_("the first operand of `%s' must be `%sxmm0'"),
3345218822Sdim			 i.tm.name, register_prefix);
3346218822Sdim	       return 0;
3347218822Sdim	     }
3348218822Sdim	   i.op[0] = i.op[1];
3349218822Sdim	   i.op[1] = i.op[2];
3350218822Sdim	   i.types[0] = i.types[1];
3351218822Sdim	   i.types[1] = i.types[2];
3352218822Sdim	   i.operands--;
3353218822Sdim	   i.reg_operands--;
3354218822Sdim
3355218822Sdim	   /* We need to adjust fields in i.tm since they are used by
3356218822Sdim	      build_modrm_byte.  */
3357218822Sdim	   i.tm.operand_types [0] = i.tm.operand_types [1];
3358218822Sdim	   i.tm.operand_types [1] = i.tm.operand_types [2];
3359218822Sdim	   i.tm.operands--;
3360218822Sdim	 }
3361218822Sdim       else
3362218822Sdim	 {
3363218822Sdim	   unsigned int first_reg_op = (i.types[0] & Reg) ? 0 : 1;
3364218822Sdim	   /* Pretend we saw the extra register operand.  */
3365218822Sdim	   assert (i.reg_operands == 1
3366218822Sdim		   && i.op[first_reg_op + 1].regs == 0);
3367218822Sdim	   i.op[first_reg_op + 1].regs = i.op[first_reg_op].regs;
3368218822Sdim	   i.types[first_reg_op + 1] = i.types[first_reg_op];
3369218822Sdim	   i.operands++;
3370218822Sdim	   i.reg_operands++;
3371218822Sdim	 }
337294546Sobrien    }
337360519Sobrien
337494546Sobrien  if (i.tm.opcode_modifier & ShortForm)
337594546Sobrien    {
3376218822Sdim      if (i.types[0] & (SReg2 | SReg3))
337794546Sobrien	{
3378218822Sdim	  if (i.tm.base_opcode == POP_SEG_SHORT
3379218822Sdim	      && i.op[0].regs->reg_num == 1)
338094546Sobrien	    {
3381218822Sdim	      as_bad (_("you can't `pop %%cs'"));
3382218822Sdim	      return 0;
338394546Sobrien	    }
3384218822Sdim	  i.tm.base_opcode |= (i.op[0].regs->reg_num << 3);
3385218822Sdim	  if ((i.op[0].regs->reg_flags & RegRex) != 0)
3386218822Sdim	    i.rex |= REX_B;
3387218822Sdim	}
3388218822Sdim      else
3389218822Sdim	{
3390218822Sdim	  /* The register or float register operand is in operand 0 or 1.  */
3391218822Sdim	  unsigned int op = (i.types[0] & (Reg | FloatReg)) ? 0 : 1;
3392218822Sdim	  /* Register goes in low 3 bits of opcode.  */
3393218822Sdim	  i.tm.base_opcode |= i.op[op].regs->reg_num;
3394218822Sdim	  if ((i.op[op].regs->reg_flags & RegRex) != 0)
3395218822Sdim	    i.rex |= REX_B;
3396218822Sdim	  if (!quiet_warnings && (i.tm.opcode_modifier & Ugh) != 0)
339794546Sobrien	    {
3398218822Sdim	      /* Warn about some common errors, but press on regardless.
3399218822Sdim		 The first case can be generated by gcc (<= 2.8.1).  */
3400218822Sdim	      if (i.operands == 2)
3401218822Sdim		{
3402218822Sdim		  /* Reversed arguments on faddp, fsubp, etc.  */
3403218822Sdim		  as_warn (_("translating to `%s %s%s,%s%s'"), i.tm.name,
3404218822Sdim			   register_prefix, i.op[1].regs->reg_name,
3405218822Sdim			   register_prefix, i.op[0].regs->reg_name);
3406218822Sdim		}
3407218822Sdim	      else
3408218822Sdim		{
3409218822Sdim		  /* Extraneous `l' suffix on fp insn.  */
3410218822Sdim		  as_warn (_("translating to `%s %s%s'"), i.tm.name,
3411218822Sdim			   register_prefix, i.op[0].regs->reg_name);
3412218822Sdim		}
341394546Sobrien	    }
341494546Sobrien	}
341594546Sobrien    }
341694546Sobrien  else if (i.tm.opcode_modifier & Modrm)
341794546Sobrien    {
341894546Sobrien      /* The opcode is completed (modulo i.tm.extension_opcode which
3419104848Sobrien	 must be put into the modrm byte).  Now, we make the modrm and
3420104848Sobrien	 index base bytes based on all the info we've collected.  */
342160519Sobrien
342294546Sobrien      default_seg = build_modrm_byte ();
342394546Sobrien    }
3424218822Sdim  else if ((i.tm.base_opcode & ~0x3) == MOV_AX_DISP32)
342594546Sobrien    {
342694546Sobrien      default_seg = &ds;
342794546Sobrien    }
342894546Sobrien  else if ((i.tm.opcode_modifier & IsString) != 0)
342994546Sobrien    {
343094546Sobrien      /* For the string instructions that allow a segment override
343194546Sobrien	 on one of their operands, the default segment is ds.  */
343294546Sobrien      default_seg = &ds;
343394546Sobrien    }
343433965Sjdp
3435218822Sdim  if ((i.tm.base_opcode == 0x8d /* lea */
3436218822Sdim       || (i.tm.cpu_flags & CpuSVME))
3437218822Sdim      && i.seg[0] && !quiet_warnings)
3438218822Sdim    as_warn (_("segment override on `%s' is ineffectual"), i.tm.name);
3439104848Sobrien
3440104848Sobrien  /* If a segment was explicitly specified, and the specified segment
3441104848Sobrien     is not the default, use an opcode prefix to select it.  If we
3442104848Sobrien     never figured out what the default segment is, then default_seg
3443104848Sobrien     will be zero at this point, and the specified segment prefix will
3444104848Sobrien     always be used.  */
344594546Sobrien  if ((i.seg[0]) && (i.seg[0] != default_seg))
344694546Sobrien    {
344794546Sobrien      if (!add_prefix (i.seg[0]->seg_prefix))
344894546Sobrien	return 0;
344994546Sobrien    }
345094546Sobrien  return 1;
345194546Sobrien}
345233965Sjdp
345394546Sobrienstatic const seg_entry *
3454218822Sdimbuild_modrm_byte (void)
345594546Sobrien{
345694546Sobrien  const seg_entry *default_seg = 0;
345733965Sjdp
345894546Sobrien  /* i.reg_operands MUST be the number of real register operands;
345994546Sobrien     implicit registers do not count.  */
346094546Sobrien  if (i.reg_operands == 2)
346194546Sobrien    {
346294546Sobrien      unsigned int source, dest;
3463218822Sdim
3464218822Sdim      switch (i.operands)
3465218822Sdim	{
3466218822Sdim	case 2:
3467218822Sdim	  source = 0;
3468218822Sdim	  break;
3469218822Sdim	case 3:
3470218822Sdim	  /* When there are 3 operands, one of them may be immediate,
3471218822Sdim	     which may be the first or the last operand.  Otherwise,
3472218822Sdim	     the first operand must be shift count register (cl). */
3473218822Sdim	  assert (i.imm_operands == 1
3474218822Sdim		  || (i.imm_operands == 0
3475218822Sdim		      && (i.types[0] & ShiftCount)));
3476218822Sdim	  source = (i.types[0] & (Imm | ShiftCount)) ? 1 : 0;
3477218822Sdim	  break;
3478218822Sdim	case 4:
3479218822Sdim	  /* When there are 4 operands, the first two must be immediate
3480218822Sdim	     operands. The source operand will be the 3rd one.  */
3481218822Sdim	  assert (i.imm_operands == 2
3482218822Sdim		  && (i.types[0] & Imm)
3483218822Sdim		  && (i.types[1] & Imm));
3484218822Sdim	  source = 2;
3485218822Sdim	  break;
3486218822Sdim	default:
3487218822Sdim	  abort ();
3488218822Sdim	}
3489218822Sdim
349094546Sobrien      dest = source + 1;
349160519Sobrien
349294546Sobrien      i.rm.mode = 3;
349394546Sobrien      /* One of the register operands will be encoded in the i.tm.reg
349494546Sobrien	 field, the other in the combined i.tm.mode and i.tm.regmem
349594546Sobrien	 fields.  If no form of this instruction supports a memory
349694546Sobrien	 destination operand, then we assume the source operand may
349794546Sobrien	 sometimes be a memory operand and so we need to store the
349894546Sobrien	 destination in the i.rm.reg field.  */
3499218822Sdim      if ((i.tm.operand_types[dest] & (AnyMem | RegMem)) == 0)
350094546Sobrien	{
350194546Sobrien	  i.rm.reg = i.op[dest].regs->reg_num;
350294546Sobrien	  i.rm.regmem = i.op[source].regs->reg_num;
350394546Sobrien	  if ((i.op[dest].regs->reg_flags & RegRex) != 0)
3504218822Sdim	    i.rex |= REX_R;
350594546Sobrien	  if ((i.op[source].regs->reg_flags & RegRex) != 0)
3506218822Sdim	    i.rex |= REX_B;
350794546Sobrien	}
350894546Sobrien      else
350994546Sobrien	{
351094546Sobrien	  i.rm.reg = i.op[source].regs->reg_num;
351194546Sobrien	  i.rm.regmem = i.op[dest].regs->reg_num;
351294546Sobrien	  if ((i.op[dest].regs->reg_flags & RegRex) != 0)
3513218822Sdim	    i.rex |= REX_B;
351494546Sobrien	  if ((i.op[source].regs->reg_flags & RegRex) != 0)
3515218822Sdim	    i.rex |= REX_R;
351694546Sobrien	}
3517218822Sdim      if (flag_code != CODE_64BIT && (i.rex & (REX_R | REX_B)))
3518218822Sdim	{
3519218822Sdim	  if (!((i.types[0] | i.types[1]) & Control))
3520218822Sdim	    abort ();
3521218822Sdim	  i.rex &= ~(REX_R | REX_B);
3522218822Sdim	  add_prefix (LOCK_PREFIX_OPCODE);
3523218822Sdim	}
352494546Sobrien    }
352594546Sobrien  else
352694546Sobrien    {			/* If it's not 2 reg operands...  */
352794546Sobrien      if (i.mem_operands)
352894546Sobrien	{
352994546Sobrien	  unsigned int fake_zero_displacement = 0;
3530218822Sdim	  unsigned int op;
353133965Sjdp
3532218822Sdim	  for (op = 0; op < i.operands; op++)
3533218822Sdim	    if ((i.types[op] & AnyMem))
3534218822Sdim	      break;
3535218822Sdim	  assert (op < i.operands);
3536218822Sdim
353794546Sobrien	  default_seg = &ds;
353833965Sjdp
353994546Sobrien	  if (i.base_reg == 0)
354094546Sobrien	    {
354194546Sobrien	      i.rm.mode = 0;
354294546Sobrien	      if (!i.disp_operands)
354394546Sobrien		fake_zero_displacement = 1;
354494546Sobrien	      if (i.index_reg == 0)
354594546Sobrien		{
354694546Sobrien		  /* Operand is just <disp>  */
3547218822Sdim		  if (flag_code == CODE_64BIT)
354894546Sobrien		    {
354994546Sobrien		      /* 64bit mode overwrites the 32bit absolute
355094546Sobrien			 addressing by RIP relative addressing and
355194546Sobrien			 absolute addressing is encoded by one of the
355294546Sobrien			 redundant SIB forms.  */
355394546Sobrien		      i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
355494546Sobrien		      i.sib.base = NO_BASE_REGISTER;
355594546Sobrien		      i.sib.index = NO_INDEX_REGISTER;
3556218822Sdim		      i.types[op] = ((i.prefix[ADDR_PREFIX] == 0)
3557218822Sdim				     ? Disp32S : Disp32);
355894546Sobrien		    }
3559218822Sdim		  else if ((flag_code == CODE_16BIT)
3560218822Sdim			   ^ (i.prefix[ADDR_PREFIX] != 0))
3561218822Sdim		    {
3562218822Sdim		      i.rm.regmem = NO_BASE_REGISTER_16;
3563218822Sdim		      i.types[op] = Disp16;
3564218822Sdim		    }
3565218822Sdim		  else
3566218822Sdim		    {
3567218822Sdim		      i.rm.regmem = NO_BASE_REGISTER;
3568218822Sdim		      i.types[op] = Disp32;
3569218822Sdim		    }
357094546Sobrien		}
357194546Sobrien	      else /* !i.base_reg && i.index_reg  */
357294546Sobrien		{
357394546Sobrien		  i.sib.index = i.index_reg->reg_num;
357494546Sobrien		  i.sib.base = NO_BASE_REGISTER;
357594546Sobrien		  i.sib.scale = i.log2_scale_factor;
357694546Sobrien		  i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
357794546Sobrien		  i.types[op] &= ~Disp;
357894546Sobrien		  if (flag_code != CODE_64BIT)
357994546Sobrien		    i.types[op] |= Disp32;	/* Must be 32 bit */
358094546Sobrien		  else
358194546Sobrien		    i.types[op] |= Disp32S;
358294546Sobrien		  if ((i.index_reg->reg_flags & RegRex) != 0)
3583218822Sdim		    i.rex |= REX_X;
358494546Sobrien		}
358594546Sobrien	    }
358694546Sobrien	  /* RIP addressing for 64bit mode.  */
358794546Sobrien	  else if (i.base_reg->reg_type == BaseIndex)
358894546Sobrien	    {
358994546Sobrien	      i.rm.regmem = NO_BASE_REGISTER;
3590218822Sdim	      i.types[op] &= ~ Disp;
359194546Sobrien	      i.types[op] |= Disp32S;
3592218822Sdim	      i.flags[op] |= Operand_PCrel;
3593218822Sdim	      if (! i.disp_operands)
3594218822Sdim		fake_zero_displacement = 1;
359594546Sobrien	    }
359694546Sobrien	  else if (i.base_reg->reg_type & Reg16)
359794546Sobrien	    {
359894546Sobrien	      switch (i.base_reg->reg_num)
359994546Sobrien		{
360094546Sobrien		case 3: /* (%bx)  */
360194546Sobrien		  if (i.index_reg == 0)
360294546Sobrien		    i.rm.regmem = 7;
360394546Sobrien		  else /* (%bx,%si) -> 0, or (%bx,%di) -> 1  */
360494546Sobrien		    i.rm.regmem = i.index_reg->reg_num - 6;
360594546Sobrien		  break;
360694546Sobrien		case 5: /* (%bp)  */
360794546Sobrien		  default_seg = &ss;
360894546Sobrien		  if (i.index_reg == 0)
360994546Sobrien		    {
361094546Sobrien		      i.rm.regmem = 6;
361194546Sobrien		      if ((i.types[op] & Disp) == 0)
361294546Sobrien			{
361394546Sobrien			  /* fake (%bp) into 0(%bp)  */
361494546Sobrien			  i.types[op] |= Disp8;
361560519Sobrien			  fake_zero_displacement = 1;
361694546Sobrien			}
361794546Sobrien		    }
361894546Sobrien		  else /* (%bp,%si) -> 2, or (%bp,%di) -> 3  */
361994546Sobrien		    i.rm.regmem = i.index_reg->reg_num - 6 + 2;
362094546Sobrien		  break;
362194546Sobrien		default: /* (%si) -> 4 or (%di) -> 5  */
362294546Sobrien		  i.rm.regmem = i.base_reg->reg_num - 6 + 4;
362394546Sobrien		}
362494546Sobrien	      i.rm.mode = mode_from_disp_size (i.types[op]);
362594546Sobrien	    }
362694546Sobrien	  else /* i.base_reg and 32/64 bit mode  */
362794546Sobrien	    {
362894546Sobrien	      if (flag_code == CODE_64BIT
362994546Sobrien		  && (i.types[op] & Disp))
3630218822Sdim		i.types[op] = ((i.types[op] & Disp8)
3631218822Sdim			       | (i.prefix[ADDR_PREFIX] == 0
3632218822Sdim				  ? Disp32S : Disp32));
3633218822Sdim
363494546Sobrien	      i.rm.regmem = i.base_reg->reg_num;
363594546Sobrien	      if ((i.base_reg->reg_flags & RegRex) != 0)
3636218822Sdim		i.rex |= REX_B;
363794546Sobrien	      i.sib.base = i.base_reg->reg_num;
363894546Sobrien	      /* x86-64 ignores REX prefix bit here to avoid decoder
363994546Sobrien		 complications.  */
364094546Sobrien	      if ((i.base_reg->reg_num & 7) == EBP_REG_NUM)
364194546Sobrien		{
364294546Sobrien		  default_seg = &ss;
364394546Sobrien		  if (i.disp_operands == 0)
364494546Sobrien		    {
364594546Sobrien		      fake_zero_displacement = 1;
364694546Sobrien		      i.types[op] |= Disp8;
364794546Sobrien		    }
364894546Sobrien		}
364994546Sobrien	      else if (i.base_reg->reg_num == ESP_REG_NUM)
365094546Sobrien		{
365194546Sobrien		  default_seg = &ss;
365294546Sobrien		}
365394546Sobrien	      i.sib.scale = i.log2_scale_factor;
365494546Sobrien	      if (i.index_reg == 0)
365594546Sobrien		{
365694546Sobrien		  /* <disp>(%esp) becomes two byte modrm with no index
365794546Sobrien		     register.  We've already stored the code for esp
365894546Sobrien		     in i.rm.regmem ie. ESCAPE_TO_TWO_BYTE_ADDRESSING.
365994546Sobrien		     Any base register besides %esp will not use the
366094546Sobrien		     extra modrm byte.  */
366194546Sobrien		  i.sib.index = NO_INDEX_REGISTER;
366294546Sobrien#if !SCALE1_WHEN_NO_INDEX
366394546Sobrien		  /* Another case where we force the second modrm byte.  */
366494546Sobrien		  if (i.log2_scale_factor)
366594546Sobrien		    i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
366660519Sobrien#endif
366794546Sobrien		}
366894546Sobrien	      else
366994546Sobrien		{
367094546Sobrien		  i.sib.index = i.index_reg->reg_num;
367194546Sobrien		  i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
367294546Sobrien		  if ((i.index_reg->reg_flags & RegRex) != 0)
3673218822Sdim		    i.rex |= REX_X;
367494546Sobrien		}
3675218822Sdim
3676218822Sdim	      if (i.disp_operands
3677218822Sdim		  && (i.reloc[op] == BFD_RELOC_386_TLS_DESC_CALL
3678218822Sdim		      || i.reloc[op] == BFD_RELOC_X86_64_TLSDESC_CALL))
3679218822Sdim		i.rm.mode = 0;
3680218822Sdim	      else
3681218822Sdim		i.rm.mode = mode_from_disp_size (i.types[op]);
368294546Sobrien	    }
368360519Sobrien
368494546Sobrien	  if (fake_zero_displacement)
368594546Sobrien	    {
368694546Sobrien	      /* Fakes a zero displacement assuming that i.types[op]
368794546Sobrien		 holds the correct displacement size.  */
368894546Sobrien	      expressionS *exp;
368960519Sobrien
369094546Sobrien	      assert (i.op[op].disps == 0);
369194546Sobrien	      exp = &disp_expressions[i.disp_operands++];
369294546Sobrien	      i.op[op].disps = exp;
369394546Sobrien	      exp->X_op = O_constant;
369494546Sobrien	      exp->X_add_number = 0;
369594546Sobrien	      exp->X_add_symbol = (symbolS *) 0;
369694546Sobrien	      exp->X_op_symbol = (symbolS *) 0;
369794546Sobrien	    }
369894546Sobrien	}
369933965Sjdp
370094546Sobrien      /* Fill in i.rm.reg or i.rm.regmem field with register operand
370194546Sobrien	 (if any) based on i.tm.extension_opcode.  Again, we must be
370294546Sobrien	 careful to make sure that segment/control/debug/test/MMX
370394546Sobrien	 registers are coded into the i.rm.reg field.  */
370494546Sobrien      if (i.reg_operands)
370594546Sobrien	{
3706218822Sdim	  unsigned int op;
3707218822Sdim
3708218822Sdim	  for (op = 0; op < i.operands; op++)
3709218822Sdim	    if ((i.types[op] & (Reg | RegMMX | RegXMM
3710218822Sdim				| SReg2 | SReg3
3711218822Sdim				| Control | Debug | Test)))
3712218822Sdim	      break;
3713218822Sdim	  assert (op < i.operands);
3714218822Sdim
371594546Sobrien	  /* If there is an extension opcode to put here, the register
371694546Sobrien	     number must be put into the regmem field.  */
371794546Sobrien	  if (i.tm.extension_opcode != None)
371894546Sobrien	    {
371994546Sobrien	      i.rm.regmem = i.op[op].regs->reg_num;
372094546Sobrien	      if ((i.op[op].regs->reg_flags & RegRex) != 0)
3721218822Sdim		i.rex |= REX_B;
372294546Sobrien	    }
372394546Sobrien	  else
372494546Sobrien	    {
372594546Sobrien	      i.rm.reg = i.op[op].regs->reg_num;
372694546Sobrien	      if ((i.op[op].regs->reg_flags & RegRex) != 0)
3727218822Sdim		i.rex |= REX_R;
372894546Sobrien	    }
372933965Sjdp
373094546Sobrien	  /* Now, if no memory operand has set i.rm.mode = 0, 1, 2 we
373194546Sobrien	     must set it to 3 to indicate this is a register operand
373294546Sobrien	     in the regmem field.  */
373394546Sobrien	  if (!i.mem_operands)
373494546Sobrien	    i.rm.mode = 3;
373594546Sobrien	}
373633965Sjdp
373794546Sobrien      /* Fill in i.rm.reg field with extension opcode (if any).  */
373894546Sobrien      if (i.tm.extension_opcode != None)
373994546Sobrien	i.rm.reg = i.tm.extension_opcode;
374094546Sobrien    }
374194546Sobrien  return default_seg;
374294546Sobrien}
374333965Sjdp
374494546Sobrienstatic void
3745218822Sdimoutput_branch (void)
374694546Sobrien{
374794546Sobrien  char *p;
374894546Sobrien  int code16;
374994546Sobrien  int prefix;
375094546Sobrien  relax_substateT subtype;
375194546Sobrien  symbolS *sym;
375294546Sobrien  offsetT off;
375333965Sjdp
375494546Sobrien  code16 = 0;
375594546Sobrien  if (flag_code == CODE_16BIT)
375694546Sobrien    code16 = CODE16;
375794546Sobrien
375894546Sobrien  prefix = 0;
375994546Sobrien  if (i.prefix[DATA_PREFIX] != 0)
376033965Sjdp    {
376194546Sobrien      prefix = 1;
376294546Sobrien      i.prefixes -= 1;
376394546Sobrien      code16 ^= CODE16;
376433965Sjdp    }
376594546Sobrien  /* Pentium4 branch hints.  */
376694546Sobrien  if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */
376794546Sobrien      || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE /* taken */)
376860519Sobrien    {
376994546Sobrien      prefix++;
377094546Sobrien      i.prefixes--;
377160519Sobrien    }
377294546Sobrien  if (i.prefix[REX_PREFIX] != 0)
377394546Sobrien    {
377494546Sobrien      prefix++;
377594546Sobrien      i.prefixes--;
377694546Sobrien    }
377760519Sobrien
377894546Sobrien  if (i.prefixes != 0 && !intel_syntax)
377994546Sobrien    as_warn (_("skipping prefixes on this instruction"));
378077311Sobrien
378194546Sobrien  /* It's always a symbol;  End frag & setup for relax.
378294546Sobrien     Make sure there is enough room in this frag for the largest
378394546Sobrien     instruction we may generate in md_convert_frag.  This is 2
378494546Sobrien     bytes for the opcode and room for the prefix and largest
378594546Sobrien     displacement.  */
378694546Sobrien  frag_grow (prefix + 2 + 4);
378794546Sobrien  /* Prefix and 1 opcode byte go in fr_fix.  */
378894546Sobrien  p = frag_more (prefix + 1);
378994546Sobrien  if (i.prefix[DATA_PREFIX] != 0)
379094546Sobrien    *p++ = DATA_PREFIX_OPCODE;
379194546Sobrien  if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE
379294546Sobrien      || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE)
379394546Sobrien    *p++ = i.prefix[SEG_PREFIX];
379494546Sobrien  if (i.prefix[REX_PREFIX] != 0)
379594546Sobrien    *p++ = i.prefix[REX_PREFIX];
379694546Sobrien  *p = i.tm.base_opcode;
379777311Sobrien
379894546Sobrien  if ((unsigned char) *p == JUMP_PC_RELATIVE)
379994546Sobrien    subtype = ENCODE_RELAX_STATE (UNCOND_JUMP, SMALL);
380094546Sobrien  else if ((cpu_arch_flags & Cpu386) != 0)
380194546Sobrien    subtype = ENCODE_RELAX_STATE (COND_JUMP, SMALL);
380294546Sobrien  else
380394546Sobrien    subtype = ENCODE_RELAX_STATE (COND_JUMP86, SMALL);
380494546Sobrien  subtype |= code16;
380577311Sobrien
380694546Sobrien  sym = i.op[0].disps->X_add_symbol;
380794546Sobrien  off = i.op[0].disps->X_add_number;
380877311Sobrien
380994546Sobrien  if (i.op[0].disps->X_op != O_constant
381094546Sobrien      && i.op[0].disps->X_op != O_symbol)
381194546Sobrien    {
381294546Sobrien      /* Handle complex expressions.  */
381394546Sobrien      sym = make_expr_symbol (i.op[0].disps);
381494546Sobrien      off = 0;
381577311Sobrien    }
381677311Sobrien
381794546Sobrien  /* 1 possible extra opcode + 4 byte displacement go in var part.
381894546Sobrien     Pass reloc in fr_var.  */
381994546Sobrien  frag_var (rs_machine_dependent, 5, i.reloc[0], subtype, sym, off, p);
382094546Sobrien}
382177311Sobrien
382294546Sobrienstatic void
3823218822Sdimoutput_jump (void)
382494546Sobrien{
382594546Sobrien  char *p;
382694546Sobrien  int size;
3827104848Sobrien  fixS *fixP;
382833965Sjdp
382994546Sobrien  if (i.tm.opcode_modifier & JumpByte)
383094546Sobrien    {
383194546Sobrien      /* This is a loop or jecxz type instruction.  */
383294546Sobrien      size = 1;
383394546Sobrien      if (i.prefix[ADDR_PREFIX] != 0)
383494546Sobrien	{
383594546Sobrien	  FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE);
383694546Sobrien	  i.prefixes -= 1;
383794546Sobrien	}
383894546Sobrien      /* Pentium4 branch hints.  */
383994546Sobrien      if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */
384094546Sobrien	  || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE /* taken */)
384194546Sobrien	{
384294546Sobrien	  FRAG_APPEND_1_CHAR (i.prefix[SEG_PREFIX]);
384394546Sobrien	  i.prefixes--;
384494546Sobrien	}
384594546Sobrien    }
384694546Sobrien  else
384794546Sobrien    {
384894546Sobrien      int code16;
384978840Sobrien
385094546Sobrien      code16 = 0;
385194546Sobrien      if (flag_code == CODE_16BIT)
385294546Sobrien	code16 = CODE16;
385333965Sjdp
385494546Sobrien      if (i.prefix[DATA_PREFIX] != 0)
385594546Sobrien	{
385694546Sobrien	  FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE);
385794546Sobrien	  i.prefixes -= 1;
385894546Sobrien	  code16 ^= CODE16;
385994546Sobrien	}
386060519Sobrien
386194546Sobrien      size = 4;
386294546Sobrien      if (code16)
386394546Sobrien	size = 2;
386494546Sobrien    }
386533965Sjdp
386694546Sobrien  if (i.prefix[REX_PREFIX] != 0)
386794546Sobrien    {
386894546Sobrien      FRAG_APPEND_1_CHAR (i.prefix[REX_PREFIX]);
386994546Sobrien      i.prefixes -= 1;
387094546Sobrien    }
387133965Sjdp
387294546Sobrien  if (i.prefixes != 0 && !intel_syntax)
387394546Sobrien    as_warn (_("skipping prefixes on this instruction"));
387489867Sobrien
387594546Sobrien  p = frag_more (1 + size);
387694546Sobrien  *p++ = i.tm.base_opcode;
387789867Sobrien
3878104848Sobrien  fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size,
3879104848Sobrien		      i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0]));
3880104848Sobrien
3881104848Sobrien  /* All jumps handled here are signed, but don't use a signed limit
3882104848Sobrien     check for 32 and 16 bit jumps as we want to allow wrap around at
3883104848Sobrien     4G and 64k respectively.  */
3884104848Sobrien  if (size == 1)
3885104848Sobrien    fixP->fx_signed = 1;
388694546Sobrien}
388789867Sobrien
388894546Sobrienstatic void
3889218822Sdimoutput_interseg_jump (void)
389094546Sobrien{
389194546Sobrien  char *p;
389294546Sobrien  int size;
389394546Sobrien  int prefix;
389494546Sobrien  int code16;
389589867Sobrien
389694546Sobrien  code16 = 0;
389794546Sobrien  if (flag_code == CODE_16BIT)
389894546Sobrien    code16 = CODE16;
389933965Sjdp
390094546Sobrien  prefix = 0;
390194546Sobrien  if (i.prefix[DATA_PREFIX] != 0)
390294546Sobrien    {
390394546Sobrien      prefix = 1;
390494546Sobrien      i.prefixes -= 1;
390594546Sobrien      code16 ^= CODE16;
390694546Sobrien    }
390794546Sobrien  if (i.prefix[REX_PREFIX] != 0)
390894546Sobrien    {
390994546Sobrien      prefix++;
391094546Sobrien      i.prefixes -= 1;
391194546Sobrien    }
391238891Sjdp
391394546Sobrien  size = 4;
391494546Sobrien  if (code16)
391594546Sobrien    size = 2;
391638891Sjdp
391794546Sobrien  if (i.prefixes != 0 && !intel_syntax)
391894546Sobrien    as_warn (_("skipping prefixes on this instruction"));
391933965Sjdp
392094546Sobrien  /* 1 opcode; 2 segment; offset  */
392194546Sobrien  p = frag_more (prefix + 1 + 2 + size);
392233965Sjdp
392394546Sobrien  if (i.prefix[DATA_PREFIX] != 0)
392494546Sobrien    *p++ = DATA_PREFIX_OPCODE;
392577311Sobrien
392694546Sobrien  if (i.prefix[REX_PREFIX] != 0)
392794546Sobrien    *p++ = i.prefix[REX_PREFIX];
392860519Sobrien
392994546Sobrien  *p++ = i.tm.base_opcode;
393094546Sobrien  if (i.op[1].imms->X_op == O_constant)
393194546Sobrien    {
393294546Sobrien      offsetT n = i.op[1].imms->X_add_number;
393333965Sjdp
393494546Sobrien      if (size == 2
393594546Sobrien	  && !fits_in_unsigned_word (n)
393694546Sobrien	  && !fits_in_signed_word (n))
393794546Sobrien	{
393894546Sobrien	  as_bad (_("16-bit jump out of range"));
393994546Sobrien	  return;
394094546Sobrien	}
394194546Sobrien      md_number_to_chars (p, n, size);
394294546Sobrien    }
394394546Sobrien  else
394494546Sobrien    fix_new_exp (frag_now, p - frag_now->fr_literal, size,
394594546Sobrien		 i.op[1].imms, 0, reloc (size, 0, 0, i.reloc[1]));
394694546Sobrien  if (i.op[0].imms->X_op != O_constant)
394794546Sobrien    as_bad (_("can't handle non absolute segment in `%s'"),
394894546Sobrien	    i.tm.name);
394994546Sobrien  md_number_to_chars (p + size, (valueT) i.op[0].imms->X_add_number, 2);
395094546Sobrien}
395160519Sobrien
395294546Sobrienstatic void
3953218822Sdimoutput_insn (void)
395494546Sobrien{
3955104848Sobrien  fragS *insn_start_frag;
3956104848Sobrien  offsetT insn_start_off;
3957104848Sobrien
395894546Sobrien  /* Tie dwarf2 debug info to the address at the start of the insn.
395994546Sobrien     We can't do this after the insn has been output as the current
396094546Sobrien     frag may have been closed off.  eg. by frag_var.  */
396194546Sobrien  dwarf2_emit_insn (0);
396260519Sobrien
3963104848Sobrien  insn_start_frag = frag_now;
3964104848Sobrien  insn_start_off = frag_now_fix ();
3965104848Sobrien
396694546Sobrien  /* Output jumps.  */
396794546Sobrien  if (i.tm.opcode_modifier & Jump)
396894546Sobrien    output_branch ();
396994546Sobrien  else if (i.tm.opcode_modifier & (JumpByte | JumpDword))
397094546Sobrien    output_jump ();
397194546Sobrien  else if (i.tm.opcode_modifier & JumpInterSegment)
397294546Sobrien    output_interseg_jump ();
397394546Sobrien  else
397494546Sobrien    {
397594546Sobrien      /* Output normal instructions here.  */
397694546Sobrien      char *p;
397794546Sobrien      unsigned char *q;
3978218822Sdim      unsigned int prefix;
397933965Sjdp
3980218822Sdim      /* All opcodes on i386 have either 1 or 2 bytes.  SSSE3 and
3981218822Sdim	 SSE4 instructions have 3 bytes.  We may use one more higher
3982218822Sdim	 byte to specify a prefix the instruction requires.  Exclude
3983218822Sdim	 instructions which are in both SSE4 and ABM.  */
3984247012Sjmg      if ((i.tm.cpu_flags & (CpuSSSE3 | CpuSSE4 | CpuAES | CpuPCLMUL)) != 0
3985218822Sdim	  && (i.tm.cpu_flags & CpuABM) == 0)
3986218822Sdim	{
3987218822Sdim	  if (i.tm.base_opcode & 0xff000000)
3988218822Sdim	    {
3989218822Sdim	      prefix = (i.tm.base_opcode >> 24) & 0xff;
3990218822Sdim	      goto check_prefix;
3991218822Sdim	    }
3992218822Sdim	}
3993255192Sjhb      else if (i.tm.base_opcode == 0x660f3880 || i.tm.base_opcode == 0x660f3881
3994255192Sjhb	  || i.tm.base_opcode == 0x660f3882)
3995238167Sjhb	{
3996238167Sjhb	  /* invept and invvpid are 3 byte instructions with a
3997238167Sjhb	     mandatory prefix. */
3998238167Sjhb	  if (i.tm.base_opcode & 0xff000000)
3999238167Sjhb	    {
4000238167Sjhb	      prefix = (i.tm.base_opcode >> 24) & 0xff;
4001238167Sjhb	      add_prefix (prefix);
4002238167Sjhb	    }
4003238167Sjhb	}
4004218822Sdim      else if ((i.tm.base_opcode & 0xff0000) != 0)
4005218822Sdim	{
4006218822Sdim	  prefix = (i.tm.base_opcode >> 16) & 0xff;
4007218822Sdim	  if ((i.tm.cpu_flags & CpuPadLock) != 0)
4008218822Sdim	    {
4009218822Sdim	    check_prefix:
4010218822Sdim	      if (prefix != REPE_PREFIX_OPCODE
4011218822Sdim		  || i.prefix[LOCKREP_PREFIX] != REPE_PREFIX_OPCODE)
4012218822Sdim		add_prefix (prefix);
4013218822Sdim	    }
4014218822Sdim	  else
4015130570Sobrien	    add_prefix (prefix);
4016130570Sobrien	}
4017130570Sobrien
401894546Sobrien      /* The prefix bytes.  */
401994546Sobrien      for (q = i.prefix;
402094546Sobrien	   q < i.prefix + sizeof (i.prefix) / sizeof (i.prefix[0]);
402194546Sobrien	   q++)
402294546Sobrien	{
402394546Sobrien	  if (*q)
402494546Sobrien	    {
402594546Sobrien	      p = frag_more (1);
402694546Sobrien	      md_number_to_chars (p, (valueT) *q, 1);
402794546Sobrien	    }
402894546Sobrien	}
402960519Sobrien
403094546Sobrien      /* Now the opcode; be careful about word order here!  */
403194546Sobrien      if (fits_in_unsigned_byte (i.tm.base_opcode))
403294546Sobrien	{
403394546Sobrien	  FRAG_APPEND_1_CHAR (i.tm.base_opcode);
403494546Sobrien	}
403594546Sobrien      else
403694546Sobrien	{
4037247012Sjmg	  if ((i.tm.cpu_flags & (CpuSSSE3 | CpuSSE4 | CpuAES | CpuPCLMUL)) != 0
4038218822Sdim	      && (i.tm.cpu_flags & CpuABM) == 0)
4039130570Sobrien	    {
4040130570Sobrien	      p = frag_more (3);
4041130570Sobrien	      *p++ = (i.tm.base_opcode >> 16) & 0xff;
4042130570Sobrien	    }
4043238167Sjhb	  else if (i.tm.base_opcode == 0x660f3880 ||
4044255192Sjhb		   i.tm.base_opcode == 0x660f3881 ||
4045255192Sjhb		   i.tm.base_opcode == 0x660f3882)
4046238167Sjhb	    {
4047238167Sjhb	      p = frag_more (3);
4048238167Sjhb	      *p++ = (i.tm.base_opcode >> 16) & 0xff;
4049238167Sjhb	    }
4050130570Sobrien	  else
4051130570Sobrien	    p = frag_more (2);
4052130570Sobrien
405394546Sobrien	  /* Put out high byte first: can't use md_number_to_chars!  */
405494546Sobrien	  *p++ = (i.tm.base_opcode >> 8) & 0xff;
405594546Sobrien	  *p = i.tm.base_opcode & 0xff;
405694546Sobrien	}
405777311Sobrien
405894546Sobrien      /* Now the modrm byte and sib byte (if present).  */
405994546Sobrien      if (i.tm.opcode_modifier & Modrm)
406094546Sobrien	{
406194546Sobrien	  p = frag_more (1);
406294546Sobrien	  md_number_to_chars (p,
406394546Sobrien			      (valueT) (i.rm.regmem << 0
406494546Sobrien					| i.rm.reg << 3
406594546Sobrien					| i.rm.mode << 6),
406694546Sobrien			      1);
406794546Sobrien	  /* If i.rm.regmem == ESP (4)
406894546Sobrien	     && i.rm.mode != (Register mode)
406994546Sobrien	     && not 16 bit
407094546Sobrien	     ==> need second modrm byte.  */
407194546Sobrien	  if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING
407294546Sobrien	      && i.rm.mode != 3
407394546Sobrien	      && !(i.base_reg && (i.base_reg->reg_type & Reg16) != 0))
407494546Sobrien	    {
407594546Sobrien	      p = frag_more (1);
407694546Sobrien	      md_number_to_chars (p,
407794546Sobrien				  (valueT) (i.sib.base << 0
407894546Sobrien					    | i.sib.index << 3
407994546Sobrien					    | i.sib.scale << 6),
408094546Sobrien				  1);
408194546Sobrien	    }
408294546Sobrien	}
408377311Sobrien
408494546Sobrien      if (i.disp_operands)
4085104848Sobrien	output_disp (insn_start_frag, insn_start_off);
408677311Sobrien
408794546Sobrien      if (i.imm_operands)
4088104848Sobrien	output_imm (insn_start_frag, insn_start_off);
408994546Sobrien    }
409060519Sobrien
409194546Sobrien#ifdef DEBUG386
409294546Sobrien  if (flag_debug)
409394546Sobrien    {
4094218822Sdim      pi ("" /*line*/, &i);
409594546Sobrien    }
409694546Sobrien#endif /* DEBUG386  */
409794546Sobrien}
409833965Sjdp
4099218822Sdim/* Return the size of the displacement operand N.  */
4100218822Sdim
4101218822Sdimstatic int
4102218822Sdimdisp_size (unsigned int n)
4103218822Sdim{
4104218822Sdim  int size = 4;
4105218822Sdim  if (i.types[n] & (Disp8 | Disp16 | Disp64))
4106218822Sdim    {
4107218822Sdim      size = 2;
4108218822Sdim      if (i.types[n] & Disp8)
4109218822Sdim	size = 1;
4110218822Sdim      if (i.types[n] & Disp64)
4111218822Sdim	size = 8;
4112218822Sdim    }
4113218822Sdim  return size;
4114218822Sdim}
4115218822Sdim
4116218822Sdim/* Return the size of the immediate operand N.  */
4117218822Sdim
4118218822Sdimstatic int
4119218822Sdimimm_size (unsigned int n)
4120218822Sdim{
4121218822Sdim  int size = 4;
4122218822Sdim  if (i.types[n] & (Imm8 | Imm8S | Imm16 | Imm64))
4123218822Sdim    {
4124218822Sdim      size = 2;
4125218822Sdim      if (i.types[n] & (Imm8 | Imm8S))
4126218822Sdim	size = 1;
4127218822Sdim      if (i.types[n] & Imm64)
4128218822Sdim	size = 8;
4129218822Sdim    }
4130218822Sdim  return size;
4131218822Sdim}
4132218822Sdim
413394546Sobrienstatic void
4134218822Sdimoutput_disp (fragS *insn_start_frag, offsetT insn_start_off)
413594546Sobrien{
413694546Sobrien  char *p;
413794546Sobrien  unsigned int n;
413877311Sobrien
413994546Sobrien  for (n = 0; n < i.operands; n++)
414094546Sobrien    {
414194546Sobrien      if (i.types[n] & Disp)
414294546Sobrien	{
414394546Sobrien	  if (i.op[n].disps->X_op == O_constant)
414494546Sobrien	    {
4145218822Sdim	      int size = disp_size (n);
414694546Sobrien	      offsetT val;
414733965Sjdp
414894546Sobrien	      val = offset_in_range (i.op[n].disps->X_add_number,
414994546Sobrien				     size);
415094546Sobrien	      p = frag_more (size);
415194546Sobrien	      md_number_to_chars (p, val, size);
415294546Sobrien	    }
415394546Sobrien	  else
415494546Sobrien	    {
4155130570Sobrien	      enum bfd_reloc_code_real reloc_type;
4156218822Sdim	      int size = disp_size (n);
4157218822Sdim	      int sign = (i.types[n] & Disp32S) != 0;
415894546Sobrien	      int pcrel = (i.flags[n] & Operand_PCrel) != 0;
415933965Sjdp
4160218822Sdim	      /* We can't have 8 bit displacement here.  */
4161218822Sdim	      assert ((i.types[n] & Disp8) == 0);
4162218822Sdim
416394546Sobrien	      /* The PC relative address is computed relative
416494546Sobrien		 to the instruction boundary, so in case immediate
416594546Sobrien		 fields follows, we need to adjust the value.  */
416694546Sobrien	      if (pcrel && i.imm_operands)
416794546Sobrien		{
416894546Sobrien		  unsigned int n1;
4169218822Sdim		  int sz = 0;
417033965Sjdp
417194546Sobrien		  for (n1 = 0; n1 < i.operands; n1++)
417294546Sobrien		    if (i.types[n1] & Imm)
417333965Sjdp		      {
4174218822Sdim			/* Only one immediate is allowed for PC
4175218822Sdim			   relative address.  */
4176218822Sdim			assert (sz == 0);
4177218822Sdim			sz = imm_size (n1);
4178218822Sdim			i.op[n].disps->X_add_number -= sz;
417933965Sjdp		      }
418094546Sobrien		  /* We should find the immediate.  */
4181218822Sdim		  assert (sz != 0);
418294546Sobrien		}
418360519Sobrien
418494546Sobrien	      p = frag_more (size);
4185104848Sobrien	      reloc_type = reloc (size, pcrel, sign, i.reloc[n]);
4186218822Sdim	      if (GOT_symbol
4187104848Sobrien		  && GOT_symbol == i.op[n].disps->X_add_symbol
4188218822Sdim		  && (((reloc_type == BFD_RELOC_32
4189218822Sdim			|| reloc_type == BFD_RELOC_X86_64_32S
4190218822Sdim			|| (reloc_type == BFD_RELOC_64
4191218822Sdim			    && object_64bit))
4192218822Sdim		       && (i.op[n].disps->X_op == O_symbol
4193218822Sdim			   || (i.op[n].disps->X_op == O_add
4194218822Sdim			       && ((symbol_get_value_expression
4195218822Sdim				    (i.op[n].disps->X_op_symbol)->X_op)
4196218822Sdim				   == O_subtract))))
4197218822Sdim		      || reloc_type == BFD_RELOC_32_PCREL))
4198104848Sobrien		{
4199104848Sobrien		  offsetT add;
4200104848Sobrien
4201104848Sobrien		  if (insn_start_frag == frag_now)
4202104848Sobrien		    add = (p - frag_now->fr_literal) - insn_start_off;
4203104848Sobrien		  else
4204104848Sobrien		    {
4205104848Sobrien		      fragS *fr;
4206104848Sobrien
4207104848Sobrien		      add = insn_start_frag->fr_fix - insn_start_off;
4208104848Sobrien		      for (fr = insn_start_frag->fr_next;
4209104848Sobrien			   fr && fr != frag_now; fr = fr->fr_next)
4210104848Sobrien			add += fr->fr_fix;
4211104848Sobrien		      add += p - frag_now->fr_literal;
4212104848Sobrien		    }
4213104848Sobrien
4214218822Sdim		  if (!object_64bit)
4215218822Sdim		    {
4216218822Sdim		      reloc_type = BFD_RELOC_386_GOTPC;
4217218822Sdim		      i.op[n].imms->X_add_number += add;
4218218822Sdim		    }
4219218822Sdim		  else if (reloc_type == BFD_RELOC_64)
4220218822Sdim		    reloc_type = BFD_RELOC_X86_64_GOTPC64;
4221218822Sdim		  else
4222218822Sdim		    /* Don't do the adjustment for x86-64, as there
4223218822Sdim		       the pcrel addressing is relative to the _next_
4224218822Sdim		       insn, and that is taken care of in other code.  */
4225218822Sdim		    reloc_type = BFD_RELOC_X86_64_GOTPC32;
4226104848Sobrien		}
422799468Sobrien	      fix_new_exp (frag_now, p - frag_now->fr_literal, size,
4228104848Sobrien			   i.op[n].disps, pcrel, reloc_type);
422994546Sobrien	    }
423094546Sobrien	}
423194546Sobrien    }
423294546Sobrien}
423377311Sobrien
423494546Sobrienstatic void
4235218822Sdimoutput_imm (fragS *insn_start_frag, offsetT insn_start_off)
423694546Sobrien{
423794546Sobrien  char *p;
423894546Sobrien  unsigned int n;
423977311Sobrien
424094546Sobrien  for (n = 0; n < i.operands; n++)
424194546Sobrien    {
424294546Sobrien      if (i.types[n] & Imm)
424394546Sobrien	{
424494546Sobrien	  if (i.op[n].imms->X_op == O_constant)
424594546Sobrien	    {
4246218822Sdim	      int size = imm_size (n);
424794546Sobrien	      offsetT val;
424833965Sjdp
424994546Sobrien	      val = offset_in_range (i.op[n].imms->X_add_number,
425094546Sobrien				     size);
425194546Sobrien	      p = frag_more (size);
425294546Sobrien	      md_number_to_chars (p, val, size);
425394546Sobrien	    }
425494546Sobrien	  else
425594546Sobrien	    {
425694546Sobrien	      /* Not absolute_section.
425794546Sobrien		 Need a 32-bit fixup (don't support 8bit
425894546Sobrien		 non-absolute imms).  Try to support other
425994546Sobrien		 sizes ...  */
4260130570Sobrien	      enum bfd_reloc_code_real reloc_type;
4261218822Sdim	      int size = imm_size (n);
4262218822Sdim	      int sign;
426333965Sjdp
426494546Sobrien	      if ((i.types[n] & (Imm32S))
4265218822Sdim		  && (i.suffix == QWORD_MNEM_SUFFIX
4266218822Sdim		      || (!i.suffix && (i.tm.opcode_modifier & No_lSuf))))
426794546Sobrien		sign = 1;
4268218822Sdim	      else
4269218822Sdim		sign = 0;
427060519Sobrien
427194546Sobrien	      p = frag_more (size);
427294546Sobrien	      reloc_type = reloc (size, 0, sign, i.reloc[n]);
4273130570Sobrien
4274104848Sobrien	      /*   This is tough to explain.  We end up with this one if we
4275104848Sobrien	       * have operands that look like
4276104848Sobrien	       * "_GLOBAL_OFFSET_TABLE_+[.-.L284]".  The goal here is to
4277104848Sobrien	       * obtain the absolute address of the GOT, and it is strongly
4278104848Sobrien	       * preferable from a performance point of view to avoid using
4279104848Sobrien	       * a runtime relocation for this.  The actual sequence of
4280104848Sobrien	       * instructions often look something like:
4281104848Sobrien	       *
4282104848Sobrien	       *	call	.L66
4283104848Sobrien	       * .L66:
4284104848Sobrien	       *	popl	%ebx
4285104848Sobrien	       *	addl	$_GLOBAL_OFFSET_TABLE_+[.-.L66],%ebx
4286104848Sobrien	       *
4287104848Sobrien	       *   The call and pop essentially return the absolute address
4288104848Sobrien	       * of the label .L66 and store it in %ebx.  The linker itself
4289104848Sobrien	       * will ultimately change the first operand of the addl so
4290104848Sobrien	       * that %ebx points to the GOT, but to keep things simple, the
4291104848Sobrien	       * .o file must have this operand set so that it generates not
4292104848Sobrien	       * the absolute address of .L66, but the absolute address of
4293104848Sobrien	       * itself.  This allows the linker itself simply treat a GOTPC
4294104848Sobrien	       * relocation as asking for a pcrel offset to the GOT to be
4295104848Sobrien	       * added in, and the addend of the relocation is stored in the
4296104848Sobrien	       * operand field for the instruction itself.
4297104848Sobrien	       *
4298104848Sobrien	       *   Our job here is to fix the operand so that it would add
4299104848Sobrien	       * the correct offset so that %ebx would point to itself.  The
4300104848Sobrien	       * thing that is tricky is that .-.L66 will point to the
4301104848Sobrien	       * beginning of the instruction, so we need to further modify
4302104848Sobrien	       * the operand so that it will point to itself.  There are
4303104848Sobrien	       * other cases where you have something like:
4304104848Sobrien	       *
4305104848Sobrien	       *	.long	$_GLOBAL_OFFSET_TABLE_+[.-.L66]
4306104848Sobrien	       *
4307104848Sobrien	       * and here no correction would be required.  Internally in
4308104848Sobrien	       * the assembler we treat operands of this form as not being
4309104848Sobrien	       * pcrel since the '.' is explicitly mentioned, and I wonder
4310104848Sobrien	       * whether it would simplify matters to do it this way.  Who
4311104848Sobrien	       * knows.  In earlier versions of the PIC patches, the
4312104848Sobrien	       * pcrel_adjust field was used to store the correction, but
4313104848Sobrien	       * since the expression is not pcrel, I felt it would be
4314104848Sobrien	       * confusing to do it this way.  */
4315104848Sobrien
4316218822Sdim	      if ((reloc_type == BFD_RELOC_32
4317218822Sdim		   || reloc_type == BFD_RELOC_X86_64_32S
4318218822Sdim		   || reloc_type == BFD_RELOC_64)
431994546Sobrien		  && GOT_symbol
432094546Sobrien		  && GOT_symbol == i.op[n].imms->X_add_symbol
432194546Sobrien		  && (i.op[n].imms->X_op == O_symbol
432294546Sobrien		      || (i.op[n].imms->X_op == O_add
432394546Sobrien			  && ((symbol_get_value_expression
432494546Sobrien			       (i.op[n].imms->X_op_symbol)->X_op)
432594546Sobrien			      == O_subtract))))
432694546Sobrien		{
4327104848Sobrien		  offsetT add;
4328104848Sobrien
4329104848Sobrien		  if (insn_start_frag == frag_now)
4330104848Sobrien		    add = (p - frag_now->fr_literal) - insn_start_off;
4331104848Sobrien		  else
4332104848Sobrien		    {
4333104848Sobrien		      fragS *fr;
4334104848Sobrien
4335104848Sobrien		      add = insn_start_frag->fr_fix - insn_start_off;
4336104848Sobrien		      for (fr = insn_start_frag->fr_next;
4337104848Sobrien			   fr && fr != frag_now; fr = fr->fr_next)
4338104848Sobrien			add += fr->fr_fix;
4339104848Sobrien		      add += p - frag_now->fr_literal;
4340104848Sobrien		    }
4341104848Sobrien
4342218822Sdim		  if (!object_64bit)
4343218822Sdim		    reloc_type = BFD_RELOC_386_GOTPC;
4344218822Sdim		  else if (size == 4)
4345218822Sdim		    reloc_type = BFD_RELOC_X86_64_GOTPC32;
4346218822Sdim		  else if (size == 8)
4347218822Sdim		    reloc_type = BFD_RELOC_X86_64_GOTPC64;
4348104848Sobrien		  i.op[n].imms->X_add_number += add;
434994546Sobrien		}
435094546Sobrien	      fix_new_exp (frag_now, p - frag_now->fr_literal, size,
435194546Sobrien			   i.op[n].imms, 0, reloc_type);
435294546Sobrien	    }
435394546Sobrien	}
435494546Sobrien    }
435533965Sjdp}
435633965Sjdp
4357218822Sdim/* x86_cons_fix_new is called via the expression parsing code when a
4358218822Sdim   reloc is needed.  We use this hook to get the correct .got reloc.  */
4359218822Sdimstatic enum bfd_reloc_code_real got_reloc = NO_RELOC;
4360218822Sdimstatic int cons_sign = -1;
436178840Sobrien
4362218822Sdimvoid
4363218822Sdimx86_cons_fix_new (fragS *frag, unsigned int off, unsigned int len,
4364218822Sdim		  expressionS *exp)
4365218822Sdim{
4366218822Sdim  enum bfd_reloc_code_real r = reloc (len, 0, cons_sign, got_reloc);
4367218822Sdim
4368218822Sdim  got_reloc = NO_RELOC;
4369218822Sdim
4370218822Sdim#ifdef TE_PE
4371218822Sdim  if (exp->X_op == O_secrel)
4372218822Sdim    {
4373218822Sdim      exp->X_op = O_symbol;
4374218822Sdim      r = BFD_RELOC_32_SECREL;
4375218822Sdim    }
4376218822Sdim#endif
4377218822Sdim
4378218822Sdim  fix_new_exp (frag, off, len, exp, 0, r);
4379218822Sdim}
4380218822Sdim
4381218822Sdim#if (!defined (OBJ_ELF) && !defined (OBJ_MAYBE_ELF)) || defined (LEX_AT)
4382218822Sdim# define lex_got(reloc, adjust, types) NULL
4383218822Sdim#else
438478840Sobrien/* Parse operands of the form
438578840Sobrien   <symbol>@GOTOFF+<nnn>
438678840Sobrien   and similar .plt or .got references.
438778840Sobrien
438878840Sobrien   If we find one, set up the correct relocation in RELOC and copy the
438978840Sobrien   input string, minus the `@GOTOFF' into a malloc'd buffer for
439078840Sobrien   parsing by the calling routine.  Return this buffer, and if ADJUST
439178840Sobrien   is non-null set it to the length of the string we removed from the
439278840Sobrien   input line.  Otherwise return NULL.  */
439378840Sobrienstatic char *
4394218822Sdimlex_got (enum bfd_reloc_code_real *reloc,
4395218822Sdim	 int *adjust,
4396218822Sdim	 unsigned int *types)
439778840Sobrien{
4398218822Sdim  /* Some of the relocations depend on the size of what field is to
4399218822Sdim     be relocated.  But in our callers i386_immediate and i386_displacement
4400218822Sdim     we don't yet know the operand size (this will be set by insn
4401218822Sdim     matching).  Hence we record the word32 relocation here,
4402218822Sdim     and adjust the reloc according to the real size in reloc().  */
440378840Sobrien  static const struct {
440478840Sobrien    const char *str;
4405218822Sdim    const enum bfd_reloc_code_real rel[2];
4406218822Sdim    const unsigned int types64;
440778840Sobrien  } gotrel[] = {
4408218822Sdim    { "PLTOFF",   { 0,
4409218822Sdim		    BFD_RELOC_X86_64_PLTOFF64 },
4410218822Sdim      Imm64 },
4411218822Sdim    { "PLT",      { BFD_RELOC_386_PLT32,
4412218822Sdim		    BFD_RELOC_X86_64_PLT32    },
4413218822Sdim      Imm32 | Imm32S | Disp32 },
4414218822Sdim    { "GOTPLT",   { 0,
4415218822Sdim		    BFD_RELOC_X86_64_GOTPLT64 },
4416218822Sdim      Imm64 | Disp64 },
4417218822Sdim    { "GOTOFF",   { BFD_RELOC_386_GOTOFF,
4418218822Sdim		    BFD_RELOC_X86_64_GOTOFF64 },
4419218822Sdim      Imm64 | Disp64 },
4420218822Sdim    { "GOTPCREL", { 0,
4421218822Sdim		    BFD_RELOC_X86_64_GOTPCREL },
4422218822Sdim      Imm32 | Imm32S | Disp32 },
4423218822Sdim    { "TLSGD",    { BFD_RELOC_386_TLS_GD,
4424218822Sdim		    BFD_RELOC_X86_64_TLSGD    },
4425218822Sdim      Imm32 | Imm32S | Disp32 },
4426218822Sdim    { "TLSLDM",   { BFD_RELOC_386_TLS_LDM,
4427218822Sdim		    0                         },
4428218822Sdim      0 },
4429218822Sdim    { "TLSLD",    { 0,
4430218822Sdim		    BFD_RELOC_X86_64_TLSLD    },
4431218822Sdim      Imm32 | Imm32S | Disp32 },
4432218822Sdim    { "GOTTPOFF", { BFD_RELOC_386_TLS_IE_32,
4433218822Sdim		    BFD_RELOC_X86_64_GOTTPOFF },
4434218822Sdim      Imm32 | Imm32S | Disp32 },
4435218822Sdim    { "TPOFF",    { BFD_RELOC_386_TLS_LE_32,
4436218822Sdim		    BFD_RELOC_X86_64_TPOFF32  },
4437218822Sdim      Imm32 | Imm32S | Imm64 | Disp32 | Disp64 },
4438218822Sdim    { "NTPOFF",   { BFD_RELOC_386_TLS_LE,
4439218822Sdim		    0                         },
4440218822Sdim      0 },
4441218822Sdim    { "DTPOFF",   { BFD_RELOC_386_TLS_LDO_32,
4442218822Sdim		    BFD_RELOC_X86_64_DTPOFF32 },
4443218822Sdim      Imm32 | Imm32S | Imm64 | Disp32 | Disp64 },
4444218822Sdim    { "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE,
4445218822Sdim		    0                         },
4446218822Sdim      0 },
4447218822Sdim    { "INDNTPOFF",{ BFD_RELOC_386_TLS_IE,
4448218822Sdim		    0                         },
4449218822Sdim      0 },
4450218822Sdim    { "GOT",      { BFD_RELOC_386_GOT32,
4451218822Sdim		    BFD_RELOC_X86_64_GOT32    },
4452218822Sdim      Imm32 | Imm32S | Disp32 | Imm64 },
4453218822Sdim    { "TLSDESC",  { BFD_RELOC_386_TLS_GOTDESC,
4454218822Sdim		    BFD_RELOC_X86_64_GOTPC32_TLSDESC },
4455218822Sdim      Imm32 | Imm32S | Disp32 },
4456218822Sdim    { "TLSCALL",  { BFD_RELOC_386_TLS_DESC_CALL,
4457218822Sdim		    BFD_RELOC_X86_64_TLSDESC_CALL },
4458218822Sdim      Imm32 | Imm32S | Disp32 }
445978840Sobrien  };
446078840Sobrien  char *cp;
446178840Sobrien  unsigned int j;
446278840Sobrien
4463218822Sdim  if (!IS_ELF)
4464218822Sdim    return NULL;
4465218822Sdim
446678840Sobrien  for (cp = input_line_pointer; *cp != '@'; cp++)
446778840Sobrien    if (is_end_of_line[(unsigned char) *cp])
446878840Sobrien      return NULL;
446978840Sobrien
447078840Sobrien  for (j = 0; j < sizeof (gotrel) / sizeof (gotrel[0]); j++)
447178840Sobrien    {
447278840Sobrien      int len;
447378840Sobrien
447478840Sobrien      len = strlen (gotrel[j].str);
447589867Sobrien      if (strncasecmp (cp + 1, gotrel[j].str, len) == 0)
447678840Sobrien	{
4477218822Sdim	  if (gotrel[j].rel[object_64bit] != 0)
447878840Sobrien	    {
447989867Sobrien	      int first, second;
448089867Sobrien	      char *tmpbuf, *past_reloc;
448178840Sobrien
4482218822Sdim	      *reloc = gotrel[j].rel[object_64bit];
448389867Sobrien	      if (adjust)
448489867Sobrien		*adjust = len;
448578840Sobrien
4486218822Sdim	      if (types)
4487218822Sdim		{
4488218822Sdim		  if (flag_code != CODE_64BIT)
4489218822Sdim		    *types = Imm32 | Disp32;
4490218822Sdim		  else
4491218822Sdim		    *types = gotrel[j].types64;
4492218822Sdim		}
4493218822Sdim
449478840Sobrien	      if (GOT_symbol == NULL)
449578840Sobrien		GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
449678840Sobrien
449789867Sobrien	      /* The length of the first part of our input line.  */
449878840Sobrien	      first = cp - input_line_pointer;
449989867Sobrien
450089867Sobrien	      /* The second part goes from after the reloc token until
450189867Sobrien		 (and including) an end_of_line char.  Don't use strlen
450289867Sobrien		 here as the end_of_line char may not be a NUL.  */
450389867Sobrien	      past_reloc = cp + 1 + len;
450489867Sobrien	      for (cp = past_reloc; !is_end_of_line[(unsigned char) *cp++]; )
450589867Sobrien		;
450689867Sobrien	      second = cp - past_reloc;
450789867Sobrien
450889867Sobrien	      /* Allocate and copy string.  The trailing NUL shouldn't
450989867Sobrien		 be necessary, but be safe.  */
451089867Sobrien	      tmpbuf = xmalloc (first + second + 2);
451178840Sobrien	      memcpy (tmpbuf, input_line_pointer, first);
4512218822Sdim	      if (second != 0 && *past_reloc != ' ')
4513218822Sdim		/* Replace the relocation token with ' ', so that
4514218822Sdim		   errors like foo@GOTOFF1 will be detected.  */
4515218822Sdim		tmpbuf[first++] = ' ';
4516218822Sdim	      memcpy (tmpbuf + first, past_reloc, second);
4517218822Sdim	      tmpbuf[first + second] = '\0';
451878840Sobrien	      return tmpbuf;
451978840Sobrien	    }
452078840Sobrien
4521218822Sdim	  as_bad (_("@%s reloc is not supported with %d-bit output format"),
4522218822Sdim		  gotrel[j].str, 1 << (5 + object_64bit));
452378840Sobrien	  return NULL;
452478840Sobrien	}
452578840Sobrien    }
452678840Sobrien
452778840Sobrien  /* Might be a symbol version string.  Don't as_bad here.  */
452878840Sobrien  return NULL;
452978840Sobrien}
453078840Sobrien
453178840Sobrienvoid
4532218822Sdimx86_cons (expressionS *exp, int size)
453378840Sobrien{
4534218822Sdim  if (size == 4 || (object_64bit && size == 8))
453578840Sobrien    {
453678840Sobrien      /* Handle @GOTOFF and the like in an expression.  */
453778840Sobrien      char *save;
453878840Sobrien      char *gotfree_input_line;
453978840Sobrien      int adjust;
454078840Sobrien
454178840Sobrien      save = input_line_pointer;
4542218822Sdim      gotfree_input_line = lex_got (&got_reloc, &adjust, NULL);
454378840Sobrien      if (gotfree_input_line)
454478840Sobrien	input_line_pointer = gotfree_input_line;
454578840Sobrien
454678840Sobrien      expression (exp);
454778840Sobrien
454878840Sobrien      if (gotfree_input_line)
454978840Sobrien	{
455078840Sobrien	  /* expression () has merrily parsed up to the end of line,
455178840Sobrien	     or a comma - in the wrong buffer.  Transfer how far
455278840Sobrien	     input_line_pointer has moved to the right buffer.  */
455378840Sobrien	  input_line_pointer = (save
455478840Sobrien				+ (input_line_pointer - gotfree_input_line)
455578840Sobrien				+ adjust);
455678840Sobrien	  free (gotfree_input_line);
455778840Sobrien	}
455878840Sobrien    }
455978840Sobrien  else
456078840Sobrien    expression (exp);
456178840Sobrien}
456278840Sobrien#endif
456378840Sobrien
4564218822Sdimstatic void signed_cons (int size)
4565218822Sdim{
4566218822Sdim  if (flag_code == CODE_64BIT)
4567218822Sdim    cons_sign = 1;
4568218822Sdim  cons (size);
4569218822Sdim  cons_sign = -1;
4570218822Sdim}
457160519Sobrien
4572218822Sdim#ifdef TE_PE
4573218822Sdimstatic void
4574218822Sdimpe_directive_secrel (dummy)
4575218822Sdim     int dummy ATTRIBUTE_UNUSED;
4576218822Sdim{
4577218822Sdim  expressionS exp;
4578218822Sdim
4579218822Sdim  do
4580218822Sdim    {
4581218822Sdim      expression (&exp);
4582218822Sdim      if (exp.X_op == O_symbol)
4583218822Sdim	exp.X_op = O_secrel;
4584218822Sdim
4585218822Sdim      emit_expr (&exp, 4);
4586218822Sdim    }
4587218822Sdim  while (*input_line_pointer++ == ',');
4588218822Sdim
4589218822Sdim  input_line_pointer--;
4590218822Sdim  demand_empty_rest_of_line ();
4591218822Sdim}
4592218822Sdim#endif
4593218822Sdim
459460519Sobrienstatic int
4595218822Sdimi386_immediate (char *imm_start)
459660519Sobrien{
459760519Sobrien  char *save_input_line_pointer;
459878840Sobrien  char *gotfree_input_line;
459960519Sobrien  segT exp_seg = 0;
460077311Sobrien  expressionS *exp;
4601218822Sdim  unsigned int types = ~0U;
460260519Sobrien
460360519Sobrien  if (i.imm_operands == MAX_IMMEDIATE_OPERANDS)
460460519Sobrien    {
4605218822Sdim      as_bad (_("at most %d immediate operands are allowed"),
4606218822Sdim	      MAX_IMMEDIATE_OPERANDS);
460760519Sobrien      return 0;
460860519Sobrien    }
460960519Sobrien
461060519Sobrien  exp = &im_expressions[i.imm_operands++];
461160519Sobrien  i.op[this_operand].imms = exp;
461260519Sobrien
461360519Sobrien  if (is_space_char (*imm_start))
461460519Sobrien    ++imm_start;
461560519Sobrien
461660519Sobrien  save_input_line_pointer = input_line_pointer;
461760519Sobrien  input_line_pointer = imm_start;
461860519Sobrien
4619218822Sdim  gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types);
462078840Sobrien  if (gotfree_input_line)
462178840Sobrien    input_line_pointer = gotfree_input_line;
462260519Sobrien
462360519Sobrien  exp_seg = expression (exp);
462460519Sobrien
462560519Sobrien  SKIP_WHITESPACE ();
462660519Sobrien  if (*input_line_pointer)
462778840Sobrien    as_bad (_("junk `%s' after expression"), input_line_pointer);
462860519Sobrien
462960519Sobrien  input_line_pointer = save_input_line_pointer;
463078840Sobrien  if (gotfree_input_line)
463178840Sobrien    free (gotfree_input_line);
463260519Sobrien
463360519Sobrien  if (exp->X_op == O_absent || exp->X_op == O_big)
463460519Sobrien    {
463577311Sobrien      /* Missing or bad expr becomes absolute 0.  */
463660519Sobrien      as_bad (_("missing or invalid immediate expression `%s' taken as 0"),
463760519Sobrien	      imm_start);
463860519Sobrien      exp->X_op = O_constant;
463960519Sobrien      exp->X_add_number = 0;
464060519Sobrien      exp->X_add_symbol = (symbolS *) 0;
464160519Sobrien      exp->X_op_symbol = (symbolS *) 0;
464260519Sobrien    }
464377311Sobrien  else if (exp->X_op == O_constant)
464460519Sobrien    {
464577311Sobrien      /* Size it properly later.  */
464677311Sobrien      i.types[this_operand] |= Imm64;
464777311Sobrien      /* If BFD64, sign extend val.  */
4648218822Sdim      if (!use_rela_relocations
4649218822Sdim	  && (exp->X_add_number & ~(((addressT) 2 << 31) - 1)) == 0)
4650218822Sdim	exp->X_add_number
4651218822Sdim	  = (exp->X_add_number ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31);
465260519Sobrien    }
465360519Sobrien#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
4654130570Sobrien  else if (OUTPUT_FLAVOR == bfd_target_aout_flavour
4655104848Sobrien	   && exp_seg != absolute_section
465677311Sobrien	   && exp_seg != text_section
465760519Sobrien	   && exp_seg != data_section
465860519Sobrien	   && exp_seg != bss_section
465960519Sobrien	   && exp_seg != undefined_section
4660130570Sobrien	   && !bfd_is_com_section (exp_seg))
466160519Sobrien    {
466260519Sobrien      as_bad (_("unimplemented segment %s in operand"), exp_seg->name);
466360519Sobrien      return 0;
466460519Sobrien    }
466560519Sobrien#endif
4666218822Sdim  else if (!intel_syntax && exp->X_op == O_register)
4667218822Sdim    {
4668218822Sdim      as_bad (_("illegal immediate register operand %s"), imm_start);
4669218822Sdim      return 0;
4670218822Sdim    }
467160519Sobrien  else
467260519Sobrien    {
467360519Sobrien      /* This is an address.  The size of the address will be
467460519Sobrien	 determined later, depending on destination register,
467577311Sobrien	 suffix, or the default for the section.  */
467677311Sobrien      i.types[this_operand] |= Imm8 | Imm16 | Imm32 | Imm32S | Imm64;
4677218822Sdim      i.types[this_operand] &= types;
467860519Sobrien    }
467960519Sobrien
468060519Sobrien  return 1;
468160519Sobrien}
468260519Sobrien
468378840Sobrienstatic char *
4684218822Sdimi386_scale (char *scale)
468560519Sobrien{
468678840Sobrien  offsetT val;
468778840Sobrien  char *save = input_line_pointer;
468860519Sobrien
468978840Sobrien  input_line_pointer = scale;
469078840Sobrien  val = get_absolute_expression ();
469178840Sobrien
469278840Sobrien  switch (val)
469360519Sobrien    {
469478840Sobrien    case 1:
469560519Sobrien      i.log2_scale_factor = 0;
469660519Sobrien      break;
469778840Sobrien    case 2:
469860519Sobrien      i.log2_scale_factor = 1;
469960519Sobrien      break;
470078840Sobrien    case 4:
470160519Sobrien      i.log2_scale_factor = 2;
470260519Sobrien      break;
470378840Sobrien    case 8:
470460519Sobrien      i.log2_scale_factor = 3;
470560519Sobrien      break;
470660519Sobrien    default:
4707218822Sdim      {
4708218822Sdim	char sep = *input_line_pointer;
4709218822Sdim
4710218822Sdim	*input_line_pointer = '\0';
4711218822Sdim	as_bad (_("expecting scale factor of 1, 2, 4, or 8: got `%s'"),
4712218822Sdim		scale);
4713218822Sdim	*input_line_pointer = sep;
4714218822Sdim	input_line_pointer = save;
4715218822Sdim	return NULL;
4716218822Sdim      }
471760519Sobrien    }
471894546Sobrien  if (i.log2_scale_factor != 0 && i.index_reg == 0)
471960519Sobrien    {
472060519Sobrien      as_warn (_("scale factor of %d without an index register"),
472160519Sobrien	       1 << i.log2_scale_factor);
472260519Sobrien#if SCALE1_WHEN_NO_INDEX
472360519Sobrien      i.log2_scale_factor = 0;
472460519Sobrien#endif
472560519Sobrien    }
472678840Sobrien  scale = input_line_pointer;
472778840Sobrien  input_line_pointer = save;
472878840Sobrien  return scale;
472960519Sobrien}
473060519Sobrien
473160519Sobrienstatic int
4732218822Sdimi386_displacement (char *disp_start, char *disp_end)
473360519Sobrien{
473494546Sobrien  expressionS *exp;
473560519Sobrien  segT exp_seg = 0;
473660519Sobrien  char *save_input_line_pointer;
473778840Sobrien  char *gotfree_input_line;
4738218822Sdim  int bigdisp, override;
4739218822Sdim  unsigned int types = Disp;
474060519Sobrien
4741218822Sdim  if (i.disp_operands == MAX_MEMORY_OPERANDS)
4742218822Sdim    {
4743218822Sdim      as_bad (_("at most %d displacement operands are allowed"),
4744218822Sdim	      MAX_MEMORY_OPERANDS);
4745218822Sdim      return 0;
4746218822Sdim    }
4747218822Sdim
4748218822Sdim  if ((i.types[this_operand] & JumpAbsolute)
4749218822Sdim      || !(current_templates->start->opcode_modifier & (Jump | JumpDword)))
4750218822Sdim    {
4751218822Sdim      bigdisp = Disp32;
4752218822Sdim      override = (i.prefix[ADDR_PREFIX] != 0);
4753218822Sdim    }
4754218822Sdim  else
4755218822Sdim    {
4756218822Sdim      /* For PC-relative branches, the width of the displacement
4757218822Sdim	 is dependent upon data size, not address size.  */
4758218822Sdim      bigdisp = 0;
4759218822Sdim      override = (i.prefix[DATA_PREFIX] != 0);
4760218822Sdim    }
476191054Sobrien  if (flag_code == CODE_64BIT)
476291054Sobrien    {
4763218822Sdim      if (!bigdisp)
4764218822Sdim	bigdisp = ((override || i.suffix == WORD_MNEM_SUFFIX)
4765218822Sdim		   ? Disp16
4766218822Sdim		   : Disp32S | Disp32);
4767218822Sdim      else if (!override)
4768218822Sdim	bigdisp = Disp64 | Disp32S | Disp32;
476991054Sobrien    }
4770218822Sdim  else
4771218822Sdim    {
4772218822Sdim      if (!bigdisp)
4773218822Sdim	{
4774218822Sdim	  if (!override)
4775218822Sdim	    override = (i.suffix == (flag_code != CODE_16BIT
4776218822Sdim				     ? WORD_MNEM_SUFFIX
4777218822Sdim				     : LONG_MNEM_SUFFIX));
4778218822Sdim	  bigdisp = Disp32;
4779218822Sdim	}
4780218822Sdim      if ((flag_code == CODE_16BIT) ^ override)
4781218822Sdim	bigdisp = Disp16;
4782218822Sdim    }
478360519Sobrien  i.types[this_operand] |= bigdisp;
478460519Sobrien
478560519Sobrien  exp = &disp_expressions[i.disp_operands];
478660519Sobrien  i.op[this_operand].disps = exp;
478760519Sobrien  i.disp_operands++;
478860519Sobrien  save_input_line_pointer = input_line_pointer;
478960519Sobrien  input_line_pointer = disp_start;
479060519Sobrien  END_STRING_AND_SAVE (disp_end);
479160519Sobrien
479260519Sobrien#ifndef GCC_ASM_O_HACK
479360519Sobrien#define GCC_ASM_O_HACK 0
479460519Sobrien#endif
479560519Sobrien#if GCC_ASM_O_HACK
479660519Sobrien  END_STRING_AND_SAVE (disp_end + 1);
479760519Sobrien  if ((i.types[this_operand] & BaseIndex) != 0
479860519Sobrien      && displacement_string_end[-1] == '+')
479960519Sobrien    {
480060519Sobrien      /* This hack is to avoid a warning when using the "o"
480160519Sobrien	 constraint within gcc asm statements.
480260519Sobrien	 For instance:
480360519Sobrien
480460519Sobrien	 #define _set_tssldt_desc(n,addr,limit,type) \
480560519Sobrien	 __asm__ __volatile__ ( \
480660519Sobrien	 "movw %w2,%0\n\t" \
480760519Sobrien	 "movw %w1,2+%0\n\t" \
480860519Sobrien	 "rorl $16,%1\n\t" \
480960519Sobrien	 "movb %b1,4+%0\n\t" \
481060519Sobrien	 "movb %4,5+%0\n\t" \
481160519Sobrien	 "movb $0,6+%0\n\t" \
481260519Sobrien	 "movb %h1,7+%0\n\t" \
481360519Sobrien	 "rorl $16,%1" \
481460519Sobrien	 : "=o"(*(n)) : "q" (addr), "ri"(limit), "i"(type))
481560519Sobrien
481660519Sobrien	 This works great except that the output assembler ends
481760519Sobrien	 up looking a bit weird if it turns out that there is
481860519Sobrien	 no offset.  You end up producing code that looks like:
481960519Sobrien
482060519Sobrien	 #APP
482160519Sobrien	 movw $235,(%eax)
482260519Sobrien	 movw %dx,2+(%eax)
482360519Sobrien	 rorl $16,%edx
482460519Sobrien	 movb %dl,4+(%eax)
482560519Sobrien	 movb $137,5+(%eax)
482660519Sobrien	 movb $0,6+(%eax)
482760519Sobrien	 movb %dh,7+(%eax)
482860519Sobrien	 rorl $16,%edx
482960519Sobrien	 #NO_APP
483060519Sobrien
483177311Sobrien	 So here we provide the missing zero.  */
483260519Sobrien
483360519Sobrien      *displacement_string_end = '0';
483460519Sobrien    }
483560519Sobrien#endif
4836218822Sdim  gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types);
483778840Sobrien  if (gotfree_input_line)
483878840Sobrien    input_line_pointer = gotfree_input_line;
483960519Sobrien
484078840Sobrien  exp_seg = expression (exp);
484160519Sobrien
484278840Sobrien  SKIP_WHITESPACE ();
484378840Sobrien  if (*input_line_pointer)
484478840Sobrien    as_bad (_("junk `%s' after expression"), input_line_pointer);
484578840Sobrien#if GCC_ASM_O_HACK
484678840Sobrien  RESTORE_END_STRING (disp_end + 1);
484760519Sobrien#endif
484878840Sobrien  RESTORE_END_STRING (disp_end);
484978840Sobrien  input_line_pointer = save_input_line_pointer;
485078840Sobrien  if (gotfree_input_line)
485178840Sobrien    free (gotfree_input_line);
485260519Sobrien
485360519Sobrien  /* We do this to make sure that the section symbol is in
485460519Sobrien     the symbol table.  We will ultimately change the relocation
485577311Sobrien     to be relative to the beginning of the section.  */
485678840Sobrien  if (i.reloc[this_operand] == BFD_RELOC_386_GOTOFF
4857218822Sdim      || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL
4858218822Sdim      || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTOFF64)
485960519Sobrien    {
486078840Sobrien      if (exp->X_op != O_symbol)
486178840Sobrien	{
486278840Sobrien	  as_bad (_("bad expression used with @%s"),
486378840Sobrien		  (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL
486478840Sobrien		   ? "GOTPCREL"
486578840Sobrien		   : "GOTOFF"));
486678840Sobrien	  return 0;
486778840Sobrien	}
486878840Sobrien
486977311Sobrien      if (S_IS_LOCAL (exp->X_add_symbol)
487060519Sobrien	  && S_GET_SEGMENT (exp->X_add_symbol) != undefined_section)
487160519Sobrien	section_symbol (S_GET_SEGMENT (exp->X_add_symbol));
487260519Sobrien      exp->X_op = O_subtract;
487360519Sobrien      exp->X_op_symbol = GOT_symbol;
487478840Sobrien      if (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL)
487594546Sobrien	i.reloc[this_operand] = BFD_RELOC_32_PCREL;
4876218822Sdim      else if (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTOFF64)
4877218822Sdim	i.reloc[this_operand] = BFD_RELOC_64;
487877311Sobrien      else
487994546Sobrien	i.reloc[this_operand] = BFD_RELOC_32;
488060519Sobrien    }
488160519Sobrien
488260519Sobrien  if (exp->X_op == O_absent || exp->X_op == O_big)
488360519Sobrien    {
488477311Sobrien      /* Missing or bad expr becomes absolute 0.  */
488560519Sobrien      as_bad (_("missing or invalid displacement expression `%s' taken as 0"),
488660519Sobrien	      disp_start);
488760519Sobrien      exp->X_op = O_constant;
488860519Sobrien      exp->X_add_number = 0;
488960519Sobrien      exp->X_add_symbol = (symbolS *) 0;
489060519Sobrien      exp->X_op_symbol = (symbolS *) 0;
489160519Sobrien    }
489260519Sobrien
489360519Sobrien#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
489477311Sobrien  if (exp->X_op != O_constant
489577311Sobrien      && OUTPUT_FLAVOR == bfd_target_aout_flavour
4896104848Sobrien      && exp_seg != absolute_section
489777311Sobrien      && exp_seg != text_section
489877311Sobrien      && exp_seg != data_section
489977311Sobrien      && exp_seg != bss_section
4900104848Sobrien      && exp_seg != undefined_section
4901130570Sobrien      && !bfd_is_com_section (exp_seg))
490260519Sobrien    {
490360519Sobrien      as_bad (_("unimplemented segment %s in operand"), exp_seg->name);
490460519Sobrien      return 0;
490560519Sobrien    }
490660519Sobrien#endif
4907218822Sdim
4908218822Sdim  if (!(i.types[this_operand] & ~Disp))
4909218822Sdim    i.types[this_operand] &= types;
4910218822Sdim
491160519Sobrien  return 1;
491260519Sobrien}
491360519Sobrien
491477311Sobrien/* Make sure the memory operand we've been dealt is valid.
491577311Sobrien   Return 1 on success, 0 on a failure.  */
491677311Sobrien
491760519Sobrienstatic int
4918218822Sdimi386_index_check (const char *operand_string)
491960519Sobrien{
492077311Sobrien  int ok;
492177311Sobrien#if INFER_ADDR_PREFIX
492277311Sobrien  int fudged = 0;
492360519Sobrien
492477311Sobrien tryprefix:
492577311Sobrien#endif
492677311Sobrien  ok = 1;
4927218822Sdim  if ((current_templates->start->cpu_flags & CpuSVME)
4928218822Sdim      && current_templates->end[-1].operand_types[0] == AnyMem)
492960519Sobrien    {
4930218822Sdim      /* Memory operands of SVME insns are special in that they only allow
4931218822Sdim	 rAX as their memory address and ignore any segment override.  */
4932218822Sdim      unsigned RegXX;
4933218822Sdim
4934218822Sdim      /* SKINIT is even more restrictive: it always requires EAX.  */
4935218822Sdim      if (strcmp (current_templates->start->name, "skinit") == 0)
4936218822Sdim	RegXX = Reg32;
4937218822Sdim      else if (flag_code == CODE_64BIT)
4938218822Sdim	RegXX = i.prefix[ADDR_PREFIX] == 0 ? Reg64 : Reg32;
493991054Sobrien      else
4940218822Sdim	RegXX = ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0)
4941218822Sdim		 ? Reg16
4942218822Sdim		 : Reg32);
4943218822Sdim      if (!i.base_reg
4944218822Sdim	  || !(i.base_reg->reg_type & Acc)
4945218822Sdim	  || !(i.base_reg->reg_type & RegXX)
4946218822Sdim	  || i.index_reg
4947218822Sdim	  || (i.types[0] & Disp))
4948218822Sdim	ok = 0;
494960519Sobrien    }
4950218822Sdim  else if (flag_code == CODE_64BIT)
4951218822Sdim    {
4952218822Sdim      unsigned RegXX = (i.prefix[ADDR_PREFIX] == 0 ? Reg64 : Reg32);
4953218822Sdim
4954218822Sdim      if ((i.base_reg
4955218822Sdim	   && ((i.base_reg->reg_type & RegXX) == 0)
4956218822Sdim	   && (i.base_reg->reg_type != BaseIndex
4957218822Sdim	       || i.index_reg))
4958218822Sdim	  || (i.index_reg
4959218822Sdim	      && ((i.index_reg->reg_type & (RegXX | BaseIndex))
4960218822Sdim		  != (RegXX | BaseIndex))))
4961218822Sdim	ok = 0;
4962218822Sdim    }
496360519Sobrien  else
496460519Sobrien    {
496577311Sobrien      if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0))
496660519Sobrien	{
496777311Sobrien	  /* 16bit checks.  */
496877311Sobrien	  if ((i.base_reg
496994546Sobrien	       && ((i.base_reg->reg_type & (Reg16 | BaseIndex | RegRex))
497094546Sobrien		   != (Reg16 | BaseIndex)))
497177311Sobrien	      || (i.index_reg
497294546Sobrien		  && (((i.index_reg->reg_type & (Reg16 | BaseIndex))
497394546Sobrien		       != (Reg16 | BaseIndex))
497494546Sobrien		      || !(i.base_reg
497594546Sobrien			   && i.base_reg->reg_num < 6
497694546Sobrien			   && i.index_reg->reg_num >= 6
497794546Sobrien			   && i.log2_scale_factor == 0))))
497877311Sobrien	    ok = 0;
497960519Sobrien	}
498077311Sobrien      else
498177311Sobrien	{
498277311Sobrien	  /* 32bit checks.  */
498377311Sobrien	  if ((i.base_reg
498477311Sobrien	       && (i.base_reg->reg_type & (Reg32 | RegRex)) != Reg32)
498577311Sobrien	      || (i.index_reg
498694546Sobrien		  && ((i.index_reg->reg_type & (Reg32 | BaseIndex | RegRex))
498794546Sobrien		      != (Reg32 | BaseIndex))))
498877311Sobrien	    ok = 0;
498977311Sobrien	}
499060519Sobrien    }
499177311Sobrien  if (!ok)
499260519Sobrien    {
499360519Sobrien#if INFER_ADDR_PREFIX
4994218822Sdim      if (i.prefix[ADDR_PREFIX] == 0)
499560519Sobrien	{
499660519Sobrien	  i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;
499760519Sobrien	  i.prefixes += 1;
499860519Sobrien	  /* Change the size of any displacement too.  At most one of
499960519Sobrien	     Disp16 or Disp32 is set.
500060519Sobrien	     FIXME.  There doesn't seem to be any real need for separate
500160519Sobrien	     Disp16 and Disp32 flags.  The same goes for Imm16 and Imm32.
500277311Sobrien	     Removing them would probably clean up the code quite a lot.  */
5003218822Sdim	  if (flag_code != CODE_64BIT
5004218822Sdim	      && (i.types[this_operand] & (Disp16 | Disp32)))
5005218822Sdim	    i.types[this_operand] ^= (Disp16 | Disp32);
500660519Sobrien	  fudged = 1;
500760519Sobrien	  goto tryprefix;
500860519Sobrien	}
500960519Sobrien      if (fudged)
501060519Sobrien	as_bad (_("`%s' is not a valid base/index expression"),
501160519Sobrien		operand_string);
501260519Sobrien      else
501360519Sobrien#endif
501460519Sobrien	as_bad (_("`%s' is not a valid %s bit base/index expression"),
501560519Sobrien		operand_string,
501677311Sobrien		flag_code_names[flag_code]);
501760519Sobrien    }
5018218822Sdim  return ok;
501960519Sobrien}
502060519Sobrien
502133965Sjdp/* Parse OPERAND_STRING into the i386_insn structure I.  Returns non-zero
502277311Sobrien   on error.  */
502333965Sjdp
502433965Sjdpstatic int
5025218822Sdimi386_operand (char *operand_string)
502633965Sjdp{
502760519Sobrien  const reg_entry *r;
502860519Sobrien  char *end_op;
502960519Sobrien  char *op_string = operand_string;
503033965Sjdp
503160519Sobrien  if (is_space_char (*op_string))
503260519Sobrien    ++op_string;
503333965Sjdp
503433965Sjdp  /* We check for an absolute prefix (differentiating,
503577311Sobrien     for example, 'jmp pc_relative_label' from 'jmp *absolute_label'.  */
503633965Sjdp  if (*op_string == ABSOLUTE_PREFIX)
503733965Sjdp    {
503860519Sobrien      ++op_string;
503960519Sobrien      if (is_space_char (*op_string))
504060519Sobrien	++op_string;
504133965Sjdp      i.types[this_operand] |= JumpAbsolute;
504233965Sjdp    }
504333965Sjdp
504477311Sobrien  /* Check if operand is a register.  */
5045218822Sdim  if ((r = parse_register (op_string, &end_op)) != NULL)
504633965Sjdp    {
504760519Sobrien      /* Check for a segment override by searching for ':' after a
504860519Sobrien	 segment register.  */
504960519Sobrien      op_string = end_op;
505060519Sobrien      if (is_space_char (*op_string))
505160519Sobrien	++op_string;
505260519Sobrien      if (*op_string == ':' && (r->reg_type & (SReg2 | SReg3)))
505333965Sjdp	{
505433965Sjdp	  switch (r->reg_num)
505533965Sjdp	    {
505633965Sjdp	    case 0:
505760519Sobrien	      i.seg[i.mem_operands] = &es;
505833965Sjdp	      break;
505933965Sjdp	    case 1:
506060519Sobrien	      i.seg[i.mem_operands] = &cs;
506133965Sjdp	      break;
506233965Sjdp	    case 2:
506360519Sobrien	      i.seg[i.mem_operands] = &ss;
506433965Sjdp	      break;
506533965Sjdp	    case 3:
506660519Sobrien	      i.seg[i.mem_operands] = &ds;
506733965Sjdp	      break;
506833965Sjdp	    case 4:
506960519Sobrien	      i.seg[i.mem_operands] = &fs;
507033965Sjdp	      break;
507133965Sjdp	    case 5:
507260519Sobrien	      i.seg[i.mem_operands] = &gs;
507333965Sjdp	      break;
507433965Sjdp	    }
507560519Sobrien
507660519Sobrien	  /* Skip the ':' and whitespace.  */
507760519Sobrien	  ++op_string;
507860519Sobrien	  if (is_space_char (*op_string))
507960519Sobrien	    ++op_string;
508060519Sobrien
508160519Sobrien	  if (!is_digit_char (*op_string)
508260519Sobrien	      && !is_identifier_char (*op_string)
508360519Sobrien	      && *op_string != '('
508460519Sobrien	      && *op_string != ABSOLUTE_PREFIX)
508533965Sjdp	    {
508660519Sobrien	      as_bad (_("bad memory operand `%s'"), op_string);
508733965Sjdp	      return 0;
508833965Sjdp	    }
508977311Sobrien	  /* Handle case of %es:*foo.  */
509033965Sjdp	  if (*op_string == ABSOLUTE_PREFIX)
509133965Sjdp	    {
509260519Sobrien	      ++op_string;
509360519Sobrien	      if (is_space_char (*op_string))
509460519Sobrien		++op_string;
509533965Sjdp	      i.types[this_operand] |= JumpAbsolute;
509633965Sjdp	    }
509733965Sjdp	  goto do_memory_reference;
509833965Sjdp	}
509960519Sobrien      if (*op_string)
510060519Sobrien	{
510160519Sobrien	  as_bad (_("junk `%s' after register"), op_string);
510260519Sobrien	  return 0;
510360519Sobrien	}
510460519Sobrien      i.types[this_operand] |= r->reg_type & ~BaseIndex;
510560519Sobrien      i.op[this_operand].regs = r;
510633965Sjdp      i.reg_operands++;
510733965Sjdp    }
510860519Sobrien  else if (*op_string == REGISTER_PREFIX)
510960519Sobrien    {
511060519Sobrien      as_bad (_("bad register name `%s'"), op_string);
511160519Sobrien      return 0;
511260519Sobrien    }
511333965Sjdp  else if (*op_string == IMMEDIATE_PREFIX)
511477311Sobrien    {
511560519Sobrien      ++op_string;
511660519Sobrien      if (i.types[this_operand] & JumpAbsolute)
511733965Sjdp	{
511860519Sobrien	  as_bad (_("immediate operand illegal with absolute jump"));
511933965Sjdp	  return 0;
512033965Sjdp	}
512160519Sobrien      if (!i386_immediate (op_string))
512260519Sobrien	return 0;
512333965Sjdp    }
512460519Sobrien  else if (is_digit_char (*op_string)
512560519Sobrien	   || is_identifier_char (*op_string)
512677311Sobrien	   || *op_string == '(')
512733965Sjdp    {
512877311Sobrien      /* This is a memory reference of some sort.  */
512960519Sobrien      char *base_string;
513033965Sjdp
513177311Sobrien      /* Start and end of displacement string expression (if found).  */
513260519Sobrien      char *displacement_string_start;
513360519Sobrien      char *displacement_string_end;
513460519Sobrien
513533965Sjdp    do_memory_reference:
513660519Sobrien      if ((i.mem_operands == 1
513760519Sobrien	   && (current_templates->start->opcode_modifier & IsString) == 0)
513860519Sobrien	  || i.mem_operands == 2)
513933965Sjdp	{
514060519Sobrien	  as_bad (_("too many memory references for `%s'"),
514160519Sobrien		  current_templates->start->name);
514233965Sjdp	  return 0;
514333965Sjdp	}
514433965Sjdp
514533965Sjdp      /* Check for base index form.  We detect the base index form by
514633965Sjdp	 looking for an ')' at the end of the operand, searching
514733965Sjdp	 for the '(' matching it, and finding a REGISTER_PREFIX or ','
514860519Sobrien	 after the '('.  */
514960519Sobrien      base_string = op_string + strlen (op_string);
515060519Sobrien
515160519Sobrien      --base_string;
515260519Sobrien      if (is_space_char (*base_string))
515360519Sobrien	--base_string;
515460519Sobrien
515577311Sobrien      /* If we only have a displacement, set-up for it to be parsed later.  */
515660519Sobrien      displacement_string_start = op_string;
515760519Sobrien      displacement_string_end = base_string + 1;
515860519Sobrien
515933965Sjdp      if (*base_string == ')')
516033965Sjdp	{
516160519Sobrien	  char *temp_string;
516233965Sjdp	  unsigned int parens_balanced = 1;
516333965Sjdp	  /* We've already checked that the number of left & right ()'s are
516477311Sobrien	     equal, so this loop will not be infinite.  */
516533965Sjdp	  do
516633965Sjdp	    {
516733965Sjdp	      base_string--;
516833965Sjdp	      if (*base_string == ')')
516933965Sjdp		parens_balanced++;
517033965Sjdp	      if (*base_string == '(')
517133965Sjdp		parens_balanced--;
517233965Sjdp	    }
517333965Sjdp	  while (parens_balanced);
517433965Sjdp
517560519Sobrien	  temp_string = base_string;
517633965Sjdp
517760519Sobrien	  /* Skip past '(' and whitespace.  */
517860519Sobrien	  ++base_string;
517960519Sobrien	  if (is_space_char (*base_string))
518060519Sobrien	    ++base_string;
518133965Sjdp
518260519Sobrien	  if (*base_string == ','
5183218822Sdim	      || ((i.base_reg = parse_register (base_string, &end_op))
5184218822Sdim		  != NULL))
518533965Sjdp	    {
518660519Sobrien	      displacement_string_end = temp_string;
518733965Sjdp
518860519Sobrien	      i.types[this_operand] |= BaseIndex;
518960519Sobrien
519060519Sobrien	      if (i.base_reg)
519133965Sjdp		{
519260519Sobrien		  base_string = end_op;
519360519Sobrien		  if (is_space_char (*base_string))
519460519Sobrien		    ++base_string;
519533965Sjdp		}
519660519Sobrien
519760519Sobrien	      /* There may be an index reg or scale factor here.  */
519860519Sobrien	      if (*base_string == ',')
519933965Sjdp		{
520060519Sobrien		  ++base_string;
520160519Sobrien		  if (is_space_char (*base_string))
520260519Sobrien		    ++base_string;
520333965Sjdp
5204218822Sdim		  if ((i.index_reg = parse_register (base_string, &end_op))
5205218822Sdim		      != NULL)
520660519Sobrien		    {
520760519Sobrien		      base_string = end_op;
520860519Sobrien		      if (is_space_char (*base_string))
520960519Sobrien			++base_string;
521060519Sobrien		      if (*base_string == ',')
521160519Sobrien			{
521260519Sobrien			  ++base_string;
521360519Sobrien			  if (is_space_char (*base_string))
521460519Sobrien			    ++base_string;
521560519Sobrien			}
521677311Sobrien		      else if (*base_string != ')')
521760519Sobrien			{
5218218822Sdim			  as_bad (_("expecting `,' or `)' "
5219218822Sdim				    "after index register in `%s'"),
522060519Sobrien				  operand_string);
522160519Sobrien			  return 0;
522260519Sobrien			}
522360519Sobrien		    }
522460519Sobrien		  else if (*base_string == REGISTER_PREFIX)
522560519Sobrien		    {
522660519Sobrien		      as_bad (_("bad register name `%s'"), base_string);
522760519Sobrien		      return 0;
522860519Sobrien		    }
522933965Sjdp
523077311Sobrien		  /* Check for scale factor.  */
523178840Sobrien		  if (*base_string != ')')
523260519Sobrien		    {
523378840Sobrien		      char *end_scale = i386_scale (base_string);
523478840Sobrien
523578840Sobrien		      if (!end_scale)
523660519Sobrien			return 0;
523733965Sjdp
523878840Sobrien		      base_string = end_scale;
523960519Sobrien		      if (is_space_char (*base_string))
524060519Sobrien			++base_string;
524160519Sobrien		      if (*base_string != ')')
524260519Sobrien			{
5243218822Sdim			  as_bad (_("expecting `)' "
5244218822Sdim				    "after scale factor in `%s'"),
524560519Sobrien				  operand_string);
524660519Sobrien			  return 0;
524760519Sobrien			}
524860519Sobrien		    }
524960519Sobrien		  else if (!i.index_reg)
525060519Sobrien		    {
5251218822Sdim		      as_bad (_("expecting index register or scale factor "
5252218822Sdim				"after `,'; got '%c'"),
525360519Sobrien			      *base_string);
525460519Sobrien		      return 0;
525560519Sobrien		    }
525633965Sjdp		}
525760519Sobrien	      else if (*base_string != ')')
525833965Sjdp		{
5259218822Sdim		  as_bad (_("expecting `,' or `)' "
5260218822Sdim			    "after base register in `%s'"),
526160519Sobrien			  operand_string);
526233965Sjdp		  return 0;
526333965Sjdp		}
526433965Sjdp	    }
526560519Sobrien	  else if (*base_string == REGISTER_PREFIX)
526633965Sjdp	    {
526760519Sobrien	      as_bad (_("bad register name `%s'"), base_string);
526860519Sobrien	      return 0;
526933965Sjdp	    }
527033965Sjdp	}
527133965Sjdp
527260519Sobrien      /* If there's an expression beginning the operand, parse it,
527360519Sobrien	 assuming displacement_string_start and
527460519Sobrien	 displacement_string_end are meaningful.  */
527560519Sobrien      if (displacement_string_start != displacement_string_end)
527633965Sjdp	{
527760519Sobrien	  if (!i386_displacement (displacement_string_start,
527860519Sobrien				  displacement_string_end))
527960519Sobrien	    return 0;
528033965Sjdp	}
528133965Sjdp
528260519Sobrien      /* Special case for (%dx) while doing input/output op.  */
528360519Sobrien      if (i.base_reg
528460519Sobrien	  && i.base_reg->reg_type == (Reg16 | InOutPortReg)
528560519Sobrien	  && i.index_reg == 0
528660519Sobrien	  && i.log2_scale_factor == 0
528760519Sobrien	  && i.seg[i.mem_operands] == 0
528860519Sobrien	  && (i.types[this_operand] & Disp) == 0)
528933965Sjdp	{
529060519Sobrien	  i.types[this_operand] = InOutPortReg;
529133965Sjdp	  return 1;
529233965Sjdp	}
529360519Sobrien
529460519Sobrien      if (i386_index_check (operand_string) == 0)
529560519Sobrien	return 0;
529660519Sobrien      i.mem_operands++;
529733965Sjdp    }
529833965Sjdp  else
529977311Sobrien    {
530077311Sobrien      /* It's not a memory operand; argh!  */
530160519Sobrien      as_bad (_("invalid char %s beginning operand %d `%s'"),
530260519Sobrien	      output_invalid (*op_string),
530360519Sobrien	      this_operand + 1,
530433965Sjdp	      op_string);
530533965Sjdp      return 0;
530633965Sjdp    }
530777311Sobrien  return 1;			/* Normal return.  */
530833965Sjdp}
530933965Sjdp
531061847Sobrien/* md_estimate_size_before_relax()
531161847Sobrien
531261847Sobrien   Called just before relax() for rs_machine_dependent frags.  The x86
531361847Sobrien   assembler uses these frags to handle variable size jump
531461847Sobrien   instructions.
531561847Sobrien
531661847Sobrien   Any symbol that is now undefined will not become defined.
531761847Sobrien   Return the correct fr_subtype in the frag.
531861847Sobrien   Return the initial "guess for variable size of frag" to caller.
531961847Sobrien   The guess is actually the growth beyond the fixed part.  Whatever
532061847Sobrien   we do to grow the fixed or variable part contributes to our
532161847Sobrien   returned value.  */
532261847Sobrien
532333965Sjdpint
532433965Sjdpmd_estimate_size_before_relax (fragP, segment)
532594546Sobrien     fragS *fragP;
532694546Sobrien     segT segment;
532733965Sjdp{
532860519Sobrien  /* We've already got fragP->fr_subtype right;  all we have to do is
532961847Sobrien     check for un-relaxable symbols.  On an ELF system, we can't relax
533061847Sobrien     an externally visible symbol, because it may be overridden by a
533161847Sobrien     shared library.  */
533261847Sobrien  if (S_GET_SEGMENT (fragP->fr_symbol) != segment
533377311Sobrien#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
5334218822Sdim      || (IS_ELF
5335104848Sobrien	  && (S_IS_EXTERNAL (fragP->fr_symbol)
5336104848Sobrien	      || S_IS_WEAK (fragP->fr_symbol)))
533761847Sobrien#endif
533861847Sobrien      )
533933965Sjdp    {
534061847Sobrien      /* Symbol is undefined in this segment, or we need to keep a
534161847Sobrien	 reloc so that weak symbols can be overridden.  */
534261847Sobrien      int size = (fragP->fr_subtype & CODE16) ? 2 : 4;
5343130570Sobrien      enum bfd_reloc_code_real reloc_type;
534461847Sobrien      unsigned char *opcode;
534561847Sobrien      int old_fr_fix;
534660519Sobrien
534761847Sobrien      if (fragP->fr_var != NO_RELOC)
534861847Sobrien	reloc_type = fragP->fr_var;
534961847Sobrien      else if (size == 2)
535060519Sobrien	reloc_type = BFD_RELOC_16_PCREL;
535160519Sobrien      else
535260519Sobrien	reloc_type = BFD_RELOC_32_PCREL;
535360519Sobrien
535461847Sobrien      old_fr_fix = fragP->fr_fix;
535561847Sobrien      opcode = (unsigned char *) fragP->fr_opcode;
535661847Sobrien
535778840Sobrien      switch (TYPE_FROM_RELAX_STATE (fragP->fr_subtype))
535833965Sjdp	{
535978840Sobrien	case UNCOND_JUMP:
536078840Sobrien	  /* Make jmp (0xeb) a (d)word displacement jump.  */
536177311Sobrien	  opcode[0] = 0xe9;
536260519Sobrien	  fragP->fr_fix += size;
536399468Sobrien	  fix_new (fragP, old_fr_fix, size,
536499468Sobrien		   fragP->fr_symbol,
536599468Sobrien		   fragP->fr_offset, 1,
536699468Sobrien		   reloc_type);
536733965Sjdp	  break;
536833965Sjdp
536978840Sobrien	case COND_JUMP86:
537099468Sobrien	  if (size == 2
537199468Sobrien	      && (!no_cond_jump_promotion || fragP->fr_var != NO_RELOC))
537278840Sobrien	    {
537378840Sobrien	      /* Negate the condition, and branch past an
537478840Sobrien		 unconditional jump.  */
537578840Sobrien	      opcode[0] ^= 1;
537678840Sobrien	      opcode[1] = 3;
537778840Sobrien	      /* Insert an unconditional jump.  */
537878840Sobrien	      opcode[2] = 0xe9;
537978840Sobrien	      /* We added two extra opcode bytes, and have a two byte
538078840Sobrien		 offset.  */
538178840Sobrien	      fragP->fr_fix += 2 + 2;
538299468Sobrien	      fix_new (fragP, old_fr_fix + 2, 2,
538399468Sobrien		       fragP->fr_symbol,
538499468Sobrien		       fragP->fr_offset, 1,
538599468Sobrien		       reloc_type);
538678840Sobrien	      break;
538778840Sobrien	    }
538878840Sobrien	  /* Fall through.  */
538978840Sobrien
539078840Sobrien	case COND_JUMP:
539199468Sobrien	  if (no_cond_jump_promotion && fragP->fr_var == NO_RELOC)
539299468Sobrien	    {
5393104848Sobrien	      fixS *fixP;
5394104848Sobrien
539599468Sobrien	      fragP->fr_fix += 1;
5396104848Sobrien	      fixP = fix_new (fragP, old_fr_fix, 1,
5397104848Sobrien			      fragP->fr_symbol,
5398104848Sobrien			      fragP->fr_offset, 1,
5399104848Sobrien			      BFD_RELOC_8_PCREL);
5400104848Sobrien	      fixP->fx_signed = 1;
540199468Sobrien	      break;
540299468Sobrien	    }
540378840Sobrien
540460519Sobrien	  /* This changes the byte-displacement jump 0x7N
540578840Sobrien	     to the (d)word-displacement jump 0x0f,0x8N.  */
540633965Sjdp	  opcode[1] = opcode[0] + 0x10;
540760519Sobrien	  opcode[0] = TWO_BYTE_OPCODE_ESCAPE;
540877311Sobrien	  /* We've added an opcode byte.  */
540977311Sobrien	  fragP->fr_fix += 1 + size;
541099468Sobrien	  fix_new (fragP, old_fr_fix + 1, size,
541199468Sobrien		   fragP->fr_symbol,
541299468Sobrien		   fragP->fr_offset, 1,
541399468Sobrien		   reloc_type);
541433965Sjdp	  break;
541578840Sobrien
541678840Sobrien	default:
541778840Sobrien	  BAD_CASE (fragP->fr_subtype);
541878840Sobrien	  break;
541933965Sjdp	}
542033965Sjdp      frag_wane (fragP);
542161847Sobrien      return fragP->fr_fix - old_fr_fix;
542233965Sjdp    }
542378840Sobrien
542478840Sobrien  /* Guess size depending on current relax state.  Initially the relax
542578840Sobrien     state will correspond to a short jump and we return 1, because
542678840Sobrien     the variable part of the frag (the branch offset) is one byte
542778840Sobrien     long.  However, we can relax a section more than once and in that
542878840Sobrien     case we must either set fr_subtype back to the unrelaxed state,
542978840Sobrien     or return the value for the appropriate branch.  */
543078840Sobrien  return md_relax_table[fragP->fr_subtype].rlx_length;
543161847Sobrien}
543261847Sobrien
543377311Sobrien/* Called after relax() is finished.
543477311Sobrien
543577311Sobrien   In:	Address of frag.
543677311Sobrien	fr_type == rs_machine_dependent.
543777311Sobrien	fr_subtype is what the address relaxed to.
543877311Sobrien
543977311Sobrien   Out:	Any fixSs and constants are set up.
544077311Sobrien	Caller will turn frag into a ".space 0".  */
544177311Sobrien
544233965Sjdpvoid
544333965Sjdpmd_convert_frag (abfd, sec, fragP)
544460519Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
544560519Sobrien     segT sec ATTRIBUTE_UNUSED;
544694546Sobrien     fragS *fragP;
544733965Sjdp{
544894546Sobrien  unsigned char *opcode;
544933965Sjdp  unsigned char *where_to_put_displacement = NULL;
545077311Sobrien  offsetT target_address;
545177311Sobrien  offsetT opcode_address;
545233965Sjdp  unsigned int extension = 0;
545377311Sobrien  offsetT displacement_from_opcode_start;
545433965Sjdp
545533965Sjdp  opcode = (unsigned char *) fragP->fr_opcode;
545633965Sjdp
545777311Sobrien  /* Address we want to reach in file space.  */
545833965Sjdp  target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
545933965Sjdp
546077311Sobrien  /* Address opcode resides at in file space.  */
546133965Sjdp  opcode_address = fragP->fr_address + fragP->fr_fix;
546233965Sjdp
546377311Sobrien  /* Displacement from opcode start to fill into instruction.  */
546433965Sjdp  displacement_from_opcode_start = target_address - opcode_address;
546533965Sjdp
546678840Sobrien  if ((fragP->fr_subtype & BIG) == 0)
546733965Sjdp    {
546877311Sobrien      /* Don't have to change opcode.  */
546977311Sobrien      extension = 1;		/* 1 opcode + 1 displacement  */
547033965Sjdp      where_to_put_displacement = &opcode[1];
547178840Sobrien    }
547278840Sobrien  else
547378840Sobrien    {
547478840Sobrien      if (no_cond_jump_promotion
547578840Sobrien	  && TYPE_FROM_RELAX_STATE (fragP->fr_subtype) != UNCOND_JUMP)
5476218822Sdim	as_warn_where (fragP->fr_file, fragP->fr_line,
5477218822Sdim		       _("long jump required"));
547833965Sjdp
547978840Sobrien      switch (fragP->fr_subtype)
548078840Sobrien	{
548178840Sobrien	case ENCODE_RELAX_STATE (UNCOND_JUMP, BIG):
548278840Sobrien	  extension = 4;		/* 1 opcode + 4 displacement  */
548378840Sobrien	  opcode[0] = 0xe9;
548478840Sobrien	  where_to_put_displacement = &opcode[1];
548578840Sobrien	  break;
548633965Sjdp
548778840Sobrien	case ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16):
548878840Sobrien	  extension = 2;		/* 1 opcode + 2 displacement  */
548978840Sobrien	  opcode[0] = 0xe9;
549078840Sobrien	  where_to_put_displacement = &opcode[1];
549178840Sobrien	  break;
549233965Sjdp
549378840Sobrien	case ENCODE_RELAX_STATE (COND_JUMP, BIG):
549478840Sobrien	case ENCODE_RELAX_STATE (COND_JUMP86, BIG):
549578840Sobrien	  extension = 5;		/* 2 opcode + 4 displacement  */
549678840Sobrien	  opcode[1] = opcode[0] + 0x10;
549778840Sobrien	  opcode[0] = TWO_BYTE_OPCODE_ESCAPE;
549878840Sobrien	  where_to_put_displacement = &opcode[2];
549978840Sobrien	  break;
550033965Sjdp
550178840Sobrien	case ENCODE_RELAX_STATE (COND_JUMP, BIG16):
550278840Sobrien	  extension = 3;		/* 2 opcode + 2 displacement  */
550378840Sobrien	  opcode[1] = opcode[0] + 0x10;
550478840Sobrien	  opcode[0] = TWO_BYTE_OPCODE_ESCAPE;
550578840Sobrien	  where_to_put_displacement = &opcode[2];
550678840Sobrien	  break;
550733965Sjdp
550878840Sobrien	case ENCODE_RELAX_STATE (COND_JUMP86, BIG16):
550978840Sobrien	  extension = 4;
551078840Sobrien	  opcode[0] ^= 1;
551178840Sobrien	  opcode[1] = 3;
551278840Sobrien	  opcode[2] = 0xe9;
551378840Sobrien	  where_to_put_displacement = &opcode[3];
551478840Sobrien	  break;
551578840Sobrien
551678840Sobrien	default:
551778840Sobrien	  BAD_CASE (fragP->fr_subtype);
551878840Sobrien	  break;
551978840Sobrien	}
552033965Sjdp    }
552178840Sobrien
5522218822Sdim  /* If size if less then four we are sure that the operand fits,
5523218822Sdim     but if it's 4, then it could be that the displacement is larger
5524218822Sdim     then -/+ 2GB.  */
5525218822Sdim  if (DISP_SIZE_FROM_RELAX_STATE (fragP->fr_subtype) == 4
5526218822Sdim      && object_64bit
5527218822Sdim      && ((addressT) (displacement_from_opcode_start - extension
5528218822Sdim		      + ((addressT) 1 << 31))
5529218822Sdim	  > (((addressT) 2 << 31) - 1)))
5530218822Sdim    {
5531218822Sdim      as_bad_where (fragP->fr_file, fragP->fr_line,
5532218822Sdim		    _("jump target out of range"));
5533218822Sdim      /* Make us emit 0.  */
5534218822Sdim      displacement_from_opcode_start = extension;
5535218822Sdim    }
553677311Sobrien  /* Now put displacement after opcode.  */
553733965Sjdp  md_number_to_chars ((char *) where_to_put_displacement,
553833965Sjdp		      (valueT) (displacement_from_opcode_start - extension),
553978840Sobrien		      DISP_SIZE_FROM_RELAX_STATE (fragP->fr_subtype));
554033965Sjdp  fragP->fr_fix += extension;
554133965Sjdp}
554233965Sjdp
554377311Sobrien/* Size of byte displacement jmp.  */
554477311Sobrienint md_short_jump_size = 2;
554533965Sjdp
554677311Sobrien/* Size of dword displacement jmp.  */
554777311Sobrienint md_long_jump_size = 5;
554833965Sjdp
554933965Sjdpvoid
555033965Sjdpmd_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
555133965Sjdp     char *ptr;
555233965Sjdp     addressT from_addr, to_addr;
555360519Sobrien     fragS *frag ATTRIBUTE_UNUSED;
555460519Sobrien     symbolS *to_symbol ATTRIBUTE_UNUSED;
555533965Sjdp{
555677311Sobrien  offsetT offset;
555733965Sjdp
555833965Sjdp  offset = to_addr - (from_addr + 2);
555977311Sobrien  /* Opcode for byte-disp jump.  */
556077311Sobrien  md_number_to_chars (ptr, (valueT) 0xeb, 1);
556133965Sjdp  md_number_to_chars (ptr + 1, (valueT) offset, 1);
556233965Sjdp}
556333965Sjdp
556433965Sjdpvoid
556533965Sjdpmd_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
556633965Sjdp     char *ptr;
556733965Sjdp     addressT from_addr, to_addr;
556877311Sobrien     fragS *frag ATTRIBUTE_UNUSED;
556977311Sobrien     symbolS *to_symbol ATTRIBUTE_UNUSED;
557033965Sjdp{
557177311Sobrien  offsetT offset;
557233965Sjdp
557377311Sobrien  offset = to_addr - (from_addr + 5);
557477311Sobrien  md_number_to_chars (ptr, (valueT) 0xe9, 1);
557577311Sobrien  md_number_to_chars (ptr + 1, (valueT) offset, 4);
557633965Sjdp}
557733965Sjdp
557833965Sjdp/* Apply a fixup (fixS) to segment data, once it has been determined
557933965Sjdp   by our caller that we have all the info we need to fix it up.
558033965Sjdp
558133965Sjdp   On the 386, immediates, displacements, and data pointers are all in
558233965Sjdp   the same (little-endian) format, so we don't need to care about which
558333965Sjdp   we are handling.  */
558433965Sjdp
558589867Sobrienvoid
5586218822Sdimmd_apply_fix (fixP, valP, seg)
558777311Sobrien     /* The fix we're to put in.  */
558877311Sobrien     fixS *fixP;
558977311Sobrien     /* Pointer to the value of the bits.  */
5590104848Sobrien     valueT *valP;
559177311Sobrien     /* Segment fix is from.  */
559277311Sobrien     segT seg ATTRIBUTE_UNUSED;
559333965Sjdp{
559489867Sobrien  char *p = fixP->fx_where + fixP->fx_frag->fr_literal;
5595104848Sobrien  valueT value = *valP;
559633965Sjdp
5597130570Sobrien#if !defined (TE_Mach)
559860519Sobrien  if (fixP->fx_pcrel)
559933965Sjdp    {
560060519Sobrien      switch (fixP->fx_r_type)
560160519Sobrien	{
560260519Sobrien	default:
560360519Sobrien	  break;
560460519Sobrien
5605218822Sdim	case BFD_RELOC_64:
5606218822Sdim	  fixP->fx_r_type = BFD_RELOC_64_PCREL;
5607218822Sdim	  break;
560860519Sobrien	case BFD_RELOC_32:
5609218822Sdim	case BFD_RELOC_X86_64_32S:
561060519Sobrien	  fixP->fx_r_type = BFD_RELOC_32_PCREL;
561160519Sobrien	  break;
561260519Sobrien	case BFD_RELOC_16:
561360519Sobrien	  fixP->fx_r_type = BFD_RELOC_16_PCREL;
561460519Sobrien	  break;
561560519Sobrien	case BFD_RELOC_8:
561660519Sobrien	  fixP->fx_r_type = BFD_RELOC_8_PCREL;
561760519Sobrien	  break;
561860519Sobrien	}
561960519Sobrien    }
562060519Sobrien
5621130570Sobrien  if (fixP->fx_addsy != NULL
5622104848Sobrien      && (fixP->fx_r_type == BFD_RELOC_32_PCREL
5623218822Sdim	  || fixP->fx_r_type == BFD_RELOC_64_PCREL
5624104848Sobrien	  || fixP->fx_r_type == BFD_RELOC_16_PCREL
5625104848Sobrien	  || fixP->fx_r_type == BFD_RELOC_8_PCREL)
5626104848Sobrien      && !use_rela_relocations)
562760519Sobrien    {
5628104848Sobrien      /* This is a hack.  There should be a better way to handle this.
5629104848Sobrien	 This covers for the fact that bfd_install_relocation will
5630104848Sobrien	 subtract the current location (for partial_inplace, PC relative
5631104848Sobrien	 relocations); see more below.  */
563233965Sjdp#ifndef OBJ_AOUT
5633218822Sdim      if (IS_ELF
563460519Sobrien#ifdef TE_PE
563560519Sobrien	  || OUTPUT_FLAVOR == bfd_target_coff_flavour
563660519Sobrien#endif
563760519Sobrien	  )
563833965Sjdp	value += fixP->fx_where + fixP->fx_frag->fr_address;
563933965Sjdp#endif
564033965Sjdp#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
5641218822Sdim      if (IS_ELF)
564233965Sjdp	{
5643130570Sobrien	  segT sym_seg = S_GET_SEGMENT (fixP->fx_addsy);
564460519Sobrien
5645130570Sobrien	  if ((sym_seg == seg
564660519Sobrien	       || (symbol_section_p (fixP->fx_addsy)
5647130570Sobrien		   && sym_seg != absolute_section))
5648130570Sobrien	      && !generic_force_reloc (fixP))
564960519Sobrien	    {
565060519Sobrien	      /* Yes, we add the values in twice.  This is because
5651130570Sobrien		 bfd_install_relocation subtracts them out again.  I think
5652130570Sobrien		 bfd_install_relocation is broken, but I don't dare change
565360519Sobrien		 it.  FIXME.  */
565460519Sobrien	      value += fixP->fx_where + fixP->fx_frag->fr_address;
565560519Sobrien	    }
565633965Sjdp	}
565733965Sjdp#endif
565838891Sjdp#if defined (OBJ_COFF) && defined (TE_PE)
5659218822Sdim      /* For some reason, the PE format does not store a
5660218822Sdim	 section address offset for a PC relative symbol.  */
5661218822Sdim      if (S_GET_SEGMENT (fixP->fx_addsy) != seg
5662218822Sdim	  || S_IS_WEAK (fixP->fx_addsy))
566338891Sjdp	value += md_pcrel_from (fixP);
566438891Sjdp#endif
566533965Sjdp    }
566633965Sjdp
566733965Sjdp  /* Fix a few things - the dynamic linker expects certain values here,
5668130570Sobrien     and we must not disappoint it.  */
566933965Sjdp#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
5670218822Sdim  if (IS_ELF && fixP->fx_addsy)
567177311Sobrien    switch (fixP->fx_r_type)
567277311Sobrien      {
567377311Sobrien      case BFD_RELOC_386_PLT32:
567477311Sobrien      case BFD_RELOC_X86_64_PLT32:
567577311Sobrien	/* Make the jump instruction point to the address of the operand.  At
567677311Sobrien	   runtime we merely add the offset to the actual PLT entry.  */
567777311Sobrien	value = -4;
567877311Sobrien	break;
567977311Sobrien
5680104848Sobrien      case BFD_RELOC_386_TLS_GD:
5681104848Sobrien      case BFD_RELOC_386_TLS_LDM:
5682104848Sobrien      case BFD_RELOC_386_TLS_IE_32:
5683104848Sobrien      case BFD_RELOC_386_TLS_IE:
5684104848Sobrien      case BFD_RELOC_386_TLS_GOTIE:
5685218822Sdim      case BFD_RELOC_386_TLS_GOTDESC:
5686130570Sobrien      case BFD_RELOC_X86_64_TLSGD:
5687130570Sobrien      case BFD_RELOC_X86_64_TLSLD:
5688130570Sobrien      case BFD_RELOC_X86_64_GOTTPOFF:
5689218822Sdim      case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
5690130570Sobrien	value = 0; /* Fully resolved at runtime.  No addend.  */
5691130570Sobrien	/* Fallthrough */
5692130570Sobrien      case BFD_RELOC_386_TLS_LE:
5693130570Sobrien      case BFD_RELOC_386_TLS_LDO_32:
5694130570Sobrien      case BFD_RELOC_386_TLS_LE_32:
5695130570Sobrien      case BFD_RELOC_X86_64_DTPOFF32:
5696218822Sdim      case BFD_RELOC_X86_64_DTPOFF64:
5697130570Sobrien      case BFD_RELOC_X86_64_TPOFF32:
5698218822Sdim      case BFD_RELOC_X86_64_TPOFF64:
5699130570Sobrien	S_SET_THREAD_LOCAL (fixP->fx_addsy);
5700130570Sobrien	break;
5701130570Sobrien
5702218822Sdim      case BFD_RELOC_386_TLS_DESC_CALL:
5703218822Sdim      case BFD_RELOC_X86_64_TLSDESC_CALL:
5704218822Sdim	value = 0; /* Fully resolved at runtime.  No addend.  */
5705218822Sdim	S_SET_THREAD_LOCAL (fixP->fx_addsy);
5706218822Sdim	fixP->fx_done = 0;
5707218822Sdim	return;
5708218822Sdim
5709130570Sobrien      case BFD_RELOC_386_GOT32:
571077311Sobrien      case BFD_RELOC_X86_64_GOT32:
571177311Sobrien	value = 0; /* Fully resolved at runtime.  No addend.  */
571277311Sobrien	break;
571360519Sobrien
571477311Sobrien      case BFD_RELOC_VTABLE_INHERIT:
571577311Sobrien      case BFD_RELOC_VTABLE_ENTRY:
571677311Sobrien	fixP->fx_done = 0;
571789867Sobrien	return;
571877311Sobrien
571977311Sobrien      default:
572077311Sobrien	break;
572177311Sobrien      }
572277311Sobrien#endif /* defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)  */
5723104848Sobrien  *valP = value;
5724130570Sobrien#endif /* !defined (TE_Mach)  */
572577311Sobrien
572677311Sobrien  /* Are we finished with this relocation now?  */
5727104848Sobrien  if (fixP->fx_addsy == NULL)
572877311Sobrien    fixP->fx_done = 1;
572977311Sobrien  else if (use_rela_relocations)
573077311Sobrien    {
573177311Sobrien      fixP->fx_no_overflow = 1;
573299468Sobrien      /* Remember value for tc_gen_reloc.  */
573399468Sobrien      fixP->fx_addnumber = value;
573477311Sobrien      value = 0;
573577311Sobrien    }
5736130570Sobrien
573777311Sobrien  md_number_to_chars (p, value, fixP->fx_size);
573833965Sjdp}
573933965Sjdp
574033965Sjdp#define MAX_LITTLENUMS 6
574133965Sjdp
574277311Sobrien/* Turn the string pointed to by litP into a floating point constant
574377311Sobrien   of type TYPE, and emit the appropriate bytes.  The number of
574477311Sobrien   LITTLENUMS emitted is stored in *SIZEP.  An error message is
574577311Sobrien   returned, or NULL on OK.  */
574677311Sobrien
574733965Sjdpchar *
574833965Sjdpmd_atof (type, litP, sizeP)
574960519Sobrien     int type;
575033965Sjdp     char *litP;
575133965Sjdp     int *sizeP;
575233965Sjdp{
575333965Sjdp  int prec;
575433965Sjdp  LITTLENUM_TYPE words[MAX_LITTLENUMS];
575533965Sjdp  LITTLENUM_TYPE *wordP;
575633965Sjdp  char *t;
575733965Sjdp
575833965Sjdp  switch (type)
575933965Sjdp    {
576033965Sjdp    case 'f':
576133965Sjdp    case 'F':
576233965Sjdp      prec = 2;
576333965Sjdp      break;
576433965Sjdp
576533965Sjdp    case 'd':
576633965Sjdp    case 'D':
576733965Sjdp      prec = 4;
576833965Sjdp      break;
576933965Sjdp
577033965Sjdp    case 'x':
577133965Sjdp    case 'X':
577233965Sjdp      prec = 5;
577333965Sjdp      break;
577433965Sjdp
577533965Sjdp    default:
577633965Sjdp      *sizeP = 0;
577760519Sobrien      return _("Bad call to md_atof ()");
577833965Sjdp    }
577933965Sjdp  t = atof_ieee (input_line_pointer, type, words);
578033965Sjdp  if (t)
578133965Sjdp    input_line_pointer = t;
578233965Sjdp
578333965Sjdp  *sizeP = prec * sizeof (LITTLENUM_TYPE);
578433965Sjdp  /* This loops outputs the LITTLENUMs in REVERSE order; in accord with
578533965Sjdp     the bigendian 386.  */
578633965Sjdp  for (wordP = words + prec - 1; prec--;)
578733965Sjdp    {
578833965Sjdp      md_number_to_chars (litP, (valueT) (*wordP--), sizeof (LITTLENUM_TYPE));
578933965Sjdp      litP += sizeof (LITTLENUM_TYPE);
579033965Sjdp    }
579133965Sjdp  return 0;
579233965Sjdp}
579333965Sjdp
5794218822Sdimstatic char output_invalid_buf[sizeof (unsigned char) * 2 + 6];
579533965Sjdp
579633965Sjdpstatic char *
5797218822Sdimoutput_invalid (int c)
579833965Sjdp{
579989867Sobrien  if (ISPRINT (c))
5800218822Sdim    snprintf (output_invalid_buf, sizeof (output_invalid_buf),
5801218822Sdim	      "'%c'", c);
580233965Sjdp  else
5803218822Sdim    snprintf (output_invalid_buf, sizeof (output_invalid_buf),
5804218822Sdim	      "(0x%x)", (unsigned char) c);
580533965Sjdp  return output_invalid_buf;
580633965Sjdp}
580733965Sjdp
580860519Sobrien/* REG_STRING starts *before* REGISTER_PREFIX.  */
580960519Sobrien
581060519Sobrienstatic const reg_entry *
5811218822Sdimparse_real_register (char *reg_string, char **end_op)
581233965Sjdp{
581360519Sobrien  char *s = reg_string;
581460519Sobrien  char *p;
581560519Sobrien  char reg_name_given[MAX_REG_NAME_SIZE + 1];
581660519Sobrien  const reg_entry *r;
581733965Sjdp
581860519Sobrien  /* Skip possible REGISTER_PREFIX and possible whitespace.  */
581960519Sobrien  if (*s == REGISTER_PREFIX)
582060519Sobrien    ++s;
582160519Sobrien
582260519Sobrien  if (is_space_char (*s))
582360519Sobrien    ++s;
582460519Sobrien
582560519Sobrien  p = reg_name_given;
582660519Sobrien  while ((*p++ = register_chars[(unsigned char) *s]) != '\0')
582733965Sjdp    {
582833965Sjdp      if (p >= reg_name_given + MAX_REG_NAME_SIZE)
582960519Sobrien	return (const reg_entry *) NULL;
583060519Sobrien      s++;
583133965Sjdp    }
583260519Sobrien
583377311Sobrien  /* For naked regs, make sure that we are not dealing with an identifier.
583477311Sobrien     This prevents confusing an identifier like `eax_var' with register
583577311Sobrien     `eax'.  */
583677311Sobrien  if (allow_naked_reg && identifier_chars[(unsigned char) *s])
583777311Sobrien    return (const reg_entry *) NULL;
583877311Sobrien
583960519Sobrien  *end_op = s;
584060519Sobrien
584160519Sobrien  r = (const reg_entry *) hash_find (reg_hash, reg_name_given);
584260519Sobrien
584360519Sobrien  /* Handle floating point regs, allowing spaces in the (i) part.  */
584477311Sobrien  if (r == i386_regtab /* %st is first entry of table  */)
584560519Sobrien    {
584660519Sobrien      if (is_space_char (*s))
584760519Sobrien	++s;
584860519Sobrien      if (*s == '(')
584960519Sobrien	{
585060519Sobrien	  ++s;
585160519Sobrien	  if (is_space_char (*s))
585260519Sobrien	    ++s;
585360519Sobrien	  if (*s >= '0' && *s <= '7')
585460519Sobrien	    {
5855218822Sdim	      int fpr = *s - '0';
585660519Sobrien	      ++s;
585760519Sobrien	      if (is_space_char (*s))
585860519Sobrien		++s;
585960519Sobrien	      if (*s == ')')
586060519Sobrien		{
586160519Sobrien		  *end_op = s + 1;
5862218822Sdim		  r = hash_find (reg_hash, "st(0)");
5863218822Sdim		  know (r);
5864218822Sdim		  return r + fpr;
586560519Sobrien		}
586660519Sobrien	    }
586777311Sobrien	  /* We have "%st(" then garbage.  */
586860519Sobrien	  return (const reg_entry *) NULL;
586960519Sobrien	}
587060519Sobrien    }
587160519Sobrien
587285824Sobrien  if (r != NULL
5873218822Sdim      && ((r->reg_flags & (RegRex64 | RegRex)) | (r->reg_type & Reg64)) != 0
5874218822Sdim      && (r->reg_type != Control || !(cpu_arch_flags & CpuSledgehammer))
587585824Sobrien      && flag_code != CODE_64BIT)
5876218822Sdim    return (const reg_entry *) NULL;
5877218822Sdim
5878218822Sdim  return r;
5879218822Sdim}
5880218822Sdim
5881218822Sdim/* REG_STRING starts *before* REGISTER_PREFIX.  */
5882218822Sdim
5883218822Sdimstatic const reg_entry *
5884218822Sdimparse_register (char *reg_string, char **end_op)
5885218822Sdim{
5886218822Sdim  const reg_entry *r;
5887218822Sdim
5888218822Sdim  if (*reg_string == REGISTER_PREFIX || allow_naked_reg)
5889218822Sdim    r = parse_real_register (reg_string, end_op);
5890218822Sdim  else
5891218822Sdim    r = NULL;
5892218822Sdim  if (!r)
589385824Sobrien    {
5894218822Sdim      char *save = input_line_pointer;
5895218822Sdim      char c;
5896218822Sdim      symbolS *symbolP;
5897218822Sdim
5898218822Sdim      input_line_pointer = reg_string;
5899218822Sdim      c = get_symbol_end ();
5900218822Sdim      symbolP = symbol_find (reg_string);
5901218822Sdim      if (symbolP && S_GET_SEGMENT (symbolP) == reg_section)
5902218822Sdim	{
5903218822Sdim	  const expressionS *e = symbol_get_value_expression (symbolP);
5904218822Sdim
5905218822Sdim	  know (e->X_op == O_register);
5906218822Sdim	  know (e->X_add_number >= 0
5907218822Sdim		&& (valueT) e->X_add_number < i386_regtab_size);
5908218822Sdim	  r = i386_regtab + e->X_add_number;
5909218822Sdim	  *end_op = input_line_pointer;
5910218822Sdim	}
5911218822Sdim      *input_line_pointer = c;
5912218822Sdim      input_line_pointer = save;
591385824Sobrien    }
591460519Sobrien  return r;
591533965Sjdp}
5916218822Sdim
5917218822Sdimint
5918218822Sdimi386_parse_name (char *name, expressionS *e, char *nextcharP)
5919218822Sdim{
5920218822Sdim  const reg_entry *r;
5921218822Sdim  char *end = input_line_pointer;
5922218822Sdim
5923218822Sdim  *end = *nextcharP;
5924218822Sdim  r = parse_register (name, &input_line_pointer);
5925218822Sdim  if (r && end <= input_line_pointer)
5926218822Sdim    {
5927218822Sdim      *nextcharP = *input_line_pointer;
5928218822Sdim      *input_line_pointer = 0;
5929218822Sdim      e->X_op = O_register;
5930218822Sdim      e->X_add_number = r - i386_regtab;
5931218822Sdim      return 1;
5932218822Sdim    }
5933218822Sdim  input_line_pointer = end;
5934218822Sdim  *end = 0;
5935218822Sdim  return 0;
5936218822Sdim}
5937218822Sdim
5938218822Sdimvoid
5939218822Sdimmd_operand (expressionS *e)
5940218822Sdim{
5941218822Sdim  if (*input_line_pointer == REGISTER_PREFIX)
5942218822Sdim    {
5943218822Sdim      char *end;
5944218822Sdim      const reg_entry *r = parse_real_register (input_line_pointer, &end);
5945218822Sdim
5946218822Sdim      if (r)
5947218822Sdim	{
5948218822Sdim	  e->X_op = O_register;
5949218822Sdim	  e->X_add_number = r - i386_regtab;
5950218822Sdim	  input_line_pointer = end;
5951218822Sdim	}
5952218822Sdim    }
5953218822Sdim}
5954218822Sdim
595533965Sjdp
595660519Sobrien#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
5957130570Sobrienconst char *md_shortopts = "kVQ:sqn";
595833965Sjdp#else
5959130570Sobrienconst char *md_shortopts = "qn";
596033965Sjdp#endif
596177311Sobrien
596277311Sobrien#define OPTION_32 (OPTION_MD_BASE + 0)
5963218822Sdim#define OPTION_64 (OPTION_MD_BASE + 1)
5964218822Sdim#define OPTION_DIVIDE (OPTION_MD_BASE + 2)
5965218822Sdim#define OPTION_MARCH (OPTION_MD_BASE + 3)
5966218822Sdim#define OPTION_MTUNE (OPTION_MD_BASE + 4)
5967218822Sdim
5968218822Sdimstruct option md_longopts[] =
5969218822Sdim{
597077311Sobrien  {"32", no_argument, NULL, OPTION_32},
5971218822Sdim#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined(TE_PEP)
597277311Sobrien  {"64", no_argument, NULL, OPTION_64},
597377311Sobrien#endif
5974218822Sdim  {"divide", no_argument, NULL, OPTION_DIVIDE},
5975218822Sdim  {"march", required_argument, NULL, OPTION_MARCH},
5976218822Sdim  {"mtune", required_argument, NULL, OPTION_MTUNE},
597733965Sjdp  {NULL, no_argument, NULL, 0}
597833965Sjdp};
597960519Sobriensize_t md_longopts_size = sizeof (md_longopts);
598033965Sjdp
598133965Sjdpint
5982218822Sdimmd_parse_option (int c, char *arg)
598333965Sjdp{
5984218822Sdim  unsigned int i;
5985218822Sdim
598633965Sjdp  switch (c)
598733965Sjdp    {
5988130570Sobrien    case 'n':
5989130570Sobrien      optimize_align_code = 0;
5990130570Sobrien      break;
5991130570Sobrien
599277311Sobrien    case 'q':
599377311Sobrien      quiet_warnings = 1;
599433965Sjdp      break;
599533965Sjdp
599633965Sjdp#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
599777311Sobrien      /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
599877311Sobrien	 should be emitted or not.  FIXME: Not implemented.  */
599977311Sobrien    case 'Q':
600033965Sjdp      break;
600133965Sjdp
600233965Sjdp      /* -V: SVR4 argument to print version ID.  */
600333965Sjdp    case 'V':
600433965Sjdp      print_version_id ();
600533965Sjdp      break;
600633965Sjdp
600777311Sobrien      /* -k: Ignore for FreeBSD compatibility.  */
600877311Sobrien    case 'k':
600933965Sjdp      break;
601060519Sobrien
601160519Sobrien    case 's':
601260519Sobrien      /* -s: On i386 Solaris, this tells the native assembler to use
601394546Sobrien	 .stab instead of .stab.excl.  We always use .stab anyhow.  */
601460519Sobrien      break;
6015218822Sdim#endif
6016218822Sdim#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined(TE_PEP)
601777311Sobrien    case OPTION_64:
601877311Sobrien      {
601977311Sobrien	const char **list, **l;
602077311Sobrien
602177311Sobrien	list = bfd_target_list ();
602277311Sobrien	for (l = list; *l != NULL; l++)
6023218822Sdim	  if (CONST_STRNEQ (*l, "elf64-x86-64")
6024218822Sdim	      || strcmp (*l, "coff-x86-64") == 0
6025218822Sdim	      || strcmp (*l, "pe-x86-64") == 0
6026218822Sdim	      || strcmp (*l, "pei-x86-64") == 0)
602777311Sobrien	    {
602877311Sobrien	      default_arch = "x86_64";
602977311Sobrien	      break;
603077311Sobrien	    }
603177311Sobrien	if (*l == NULL)
603277311Sobrien	  as_fatal (_("No compiled in support for x86_64"));
603377311Sobrien	free (list);
603477311Sobrien      }
603560519Sobrien      break;
603633965Sjdp#endif
603733965Sjdp
603877311Sobrien    case OPTION_32:
603977311Sobrien      default_arch = "i386";
604077311Sobrien      break;
604177311Sobrien
6042218822Sdim    case OPTION_DIVIDE:
6043218822Sdim#ifdef SVR4_COMMENT_CHARS
6044218822Sdim      {
6045218822Sdim	char *n, *t;
6046218822Sdim	const char *s;
6047218822Sdim
6048218822Sdim	n = (char *) xmalloc (strlen (i386_comment_chars) + 1);
6049218822Sdim	t = n;
6050218822Sdim	for (s = i386_comment_chars; *s != '\0'; s++)
6051218822Sdim	  if (*s != '/')
6052218822Sdim	    *t++ = *s;
6053218822Sdim	*t = '\0';
6054218822Sdim	i386_comment_chars = n;
6055218822Sdim      }
6056218822Sdim#endif
6057218822Sdim      break;
6058218822Sdim
6059218822Sdim    case OPTION_MARCH:
6060218822Sdim      if (*arg == '.')
6061218822Sdim	as_fatal (_("Invalid -march= option: `%s'"), arg);
6062218822Sdim      for (i = 0; i < ARRAY_SIZE (cpu_arch); i++)
6063218822Sdim	{
6064218822Sdim	  if (strcmp (arg, cpu_arch [i].name) == 0)
6065218822Sdim	    {
6066218822Sdim	      cpu_arch_isa = cpu_arch[i].type;
6067218822Sdim	      cpu_arch_isa_flags = cpu_arch[i].flags;
6068218822Sdim	      if (!cpu_arch_tune_set)
6069218822Sdim		{
6070218822Sdim		  cpu_arch_tune = cpu_arch_isa;
6071218822Sdim		  cpu_arch_tune_flags = cpu_arch_isa_flags;
6072218822Sdim		}
6073218822Sdim	      break;
6074218822Sdim	    }
6075218822Sdim	}
6076218822Sdim      if (i >= ARRAY_SIZE (cpu_arch))
6077218822Sdim	as_fatal (_("Invalid -march= option: `%s'"), arg);
6078218822Sdim      break;
6079218822Sdim
6080218822Sdim    case OPTION_MTUNE:
6081218822Sdim      if (*arg == '.')
6082218822Sdim	as_fatal (_("Invalid -mtune= option: `%s'"), arg);
6083218822Sdim      for (i = 0; i < ARRAY_SIZE (cpu_arch); i++)
6084218822Sdim	{
6085218822Sdim	  if (strcmp (arg, cpu_arch [i].name) == 0)
6086218822Sdim	    {
6087218822Sdim	      cpu_arch_tune_set = 1;
6088218822Sdim	      cpu_arch_tune = cpu_arch [i].type;
6089218822Sdim	      cpu_arch_tune_flags = cpu_arch[i].flags;
6090218822Sdim	      break;
6091218822Sdim	    }
6092218822Sdim	}
6093218822Sdim      if (i >= ARRAY_SIZE (cpu_arch))
6094218822Sdim	as_fatal (_("Invalid -mtune= option: `%s'"), arg);
6095218822Sdim      break;
6096218822Sdim
609733965Sjdp    default:
609833965Sjdp      return 0;
609933965Sjdp    }
610033965Sjdp  return 1;
610133965Sjdp}
610233965Sjdp
610333965Sjdpvoid
610433965Sjdpmd_show_usage (stream)
610533965Sjdp     FILE *stream;
610633965Sjdp{
610760519Sobrien#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
610860519Sobrien  fprintf (stream, _("\
610977311Sobrien  -Q                      ignored\n\
611077311Sobrien  -V                      print assembler version number\n\
6111218822Sdim  -k                      ignored\n"));
6112218822Sdim#endif
6113218822Sdim  fprintf (stream, _("\
6114130570Sobrien  -n                      Do not optimize code alignment\n\
6115218822Sdim  -q                      quieten some warnings\n"));
6116218822Sdim#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
6117218822Sdim  fprintf (stream, _("\
611877311Sobrien  -s                      ignored\n"));
6119218822Sdim#endif
6120218822Sdim#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined(TE_PEP)
6121218822Sdim  fprintf (stream, _("\
6122218822Sdim  --32/--64               generate 32bit/64bit code\n"));
6123218822Sdim#endif
6124218822Sdim#ifdef SVR4_COMMENT_CHARS
6125218822Sdim  fprintf (stream, _("\
6126218822Sdim  --divide                do not treat `/' as a comment character\n"));
612777311Sobrien#else
612877311Sobrien  fprintf (stream, _("\
6129218822Sdim  --divide                ignored\n"));
613060519Sobrien#endif
6131218822Sdim  fprintf (stream, _("\
6132218822Sdim  -march=CPU/-mtune=CPU   generate code/optimize for CPU, where CPU is one of:\n\
6133218822Sdim                           i386, i486, pentium, pentiumpro, pentium4, nocona,\n\
6134218822Sdim                           core, core2, k6, athlon, k8, generic32, generic64\n"));
6135218822Sdim
613633965Sjdp}
613733965Sjdp
6138218822Sdim#if defined(TE_PEP)
6139218822Sdimconst char *
6140218822Sdimx86_64_target_format (void)
6141218822Sdim{
6142218822Sdim  if (strcmp (default_arch, "x86_64") == 0)
6143218822Sdim    {
6144218822Sdim      set_code_flag (CODE_64BIT);
6145218822Sdim      return COFF_TARGET_FORMAT;
6146218822Sdim    }
6147218822Sdim  else if (strcmp (default_arch, "i386") == 0)
6148218822Sdim    {
6149218822Sdim      set_code_flag (CODE_32BIT);
6150218822Sdim      return "coff-i386";
6151218822Sdim    }
6152218822Sdim
6153218822Sdim  as_fatal (_("Unknown architecture"));
6154218822Sdim  return NULL;
6155218822Sdim}
6156218822Sdim#endif
6157218822Sdim
615877311Sobrien#if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \
615977311Sobrien     || defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF))
616033965Sjdp
616133965Sjdp/* Pick the target format to use.  */
616233965Sjdp
616377311Sobrienconst char *
6164218822Sdimi386_target_format (void)
616533965Sjdp{
616677311Sobrien  if (!strcmp (default_arch, "x86_64"))
6167218822Sdim    {
6168218822Sdim      set_code_flag (CODE_64BIT);
6169218822Sdim      if (cpu_arch_isa_flags == 0)
6170218822Sdim	cpu_arch_isa_flags = Cpu186|Cpu286|Cpu386|Cpu486
6171218822Sdim			     |Cpu586|Cpu686|CpuP4|CpuMMX|CpuMMX2
6172218822Sdim			     |CpuSSE|CpuSSE2;
6173218822Sdim      if (cpu_arch_tune_flags == 0)
6174218822Sdim	cpu_arch_tune_flags = Cpu186|Cpu286|Cpu386|Cpu486
6175218822Sdim			      |Cpu586|Cpu686|CpuP4|CpuMMX|CpuMMX2
6176218822Sdim			      |CpuSSE|CpuSSE2;
6177218822Sdim    }
617877311Sobrien  else if (!strcmp (default_arch, "i386"))
6179218822Sdim    {
6180218822Sdim      set_code_flag (CODE_32BIT);
6181218822Sdim      if (cpu_arch_isa_flags == 0)
6182218822Sdim	cpu_arch_isa_flags = Cpu186|Cpu286|Cpu386;
6183218822Sdim      if (cpu_arch_tune_flags == 0)
6184218822Sdim	cpu_arch_tune_flags = Cpu186|Cpu286|Cpu386;
6185218822Sdim    }
618677311Sobrien  else
618777311Sobrien    as_fatal (_("Unknown architecture"));
618833965Sjdp  switch (OUTPUT_FLAVOR)
618933965Sjdp    {
619060519Sobrien#ifdef OBJ_MAYBE_AOUT
619160519Sobrien    case bfd_target_aout_flavour:
619277311Sobrien      return AOUT_TARGET_FORMAT;
619360519Sobrien#endif
619460519Sobrien#ifdef OBJ_MAYBE_COFF
619533965Sjdp    case bfd_target_coff_flavour:
619633965Sjdp      return "coff-i386";
619760519Sobrien#endif
619877311Sobrien#if defined (OBJ_MAYBE_ELF) || defined (OBJ_ELF)
619933965Sjdp    case bfd_target_elf_flavour:
620077311Sobrien      {
620177311Sobrien	if (flag_code == CODE_64BIT)
6202218822Sdim	  {
6203218822Sdim	    object_64bit = 1;
6204218822Sdim	    use_rela_relocations = 1;
6205218822Sdim	  }
6206218822Sdim	return flag_code == CODE_64BIT ? ELF_TARGET_FORMAT64 : ELF_TARGET_FORMAT;
620777311Sobrien      }
620860519Sobrien#endif
620933965Sjdp    default:
621033965Sjdp      abort ();
621133965Sjdp      return NULL;
621233965Sjdp    }
621333965Sjdp}
621433965Sjdp
621577311Sobrien#endif /* OBJ_MAYBE_ more than one  */
621689867Sobrien
621789867Sobrien#if (defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF))
6218218822Sdimvoid
6219218822Sdimi386_elf_emit_arch_note (void)
622089867Sobrien{
6221218822Sdim  if (IS_ELF && cpu_arch_name != NULL)
622289867Sobrien    {
622389867Sobrien      char *p;
622489867Sobrien      asection *seg = now_seg;
622589867Sobrien      subsegT subseg = now_subseg;
622689867Sobrien      Elf_Internal_Note i_note;
622789867Sobrien      Elf_External_Note e_note;
622889867Sobrien      asection *note_secp;
622989867Sobrien      int len;
623089867Sobrien
623189867Sobrien      /* Create the .note section.  */
623289867Sobrien      note_secp = subseg_new (".note", 0);
623389867Sobrien      bfd_set_section_flags (stdoutput,
623489867Sobrien			     note_secp,
623589867Sobrien			     SEC_HAS_CONTENTS | SEC_READONLY);
623689867Sobrien
623789867Sobrien      /* Process the arch string.  */
623889867Sobrien      len = strlen (cpu_arch_name);
623989867Sobrien
624089867Sobrien      i_note.namesz = len + 1;
624189867Sobrien      i_note.descsz = 0;
624289867Sobrien      i_note.type = NT_ARCH;
624389867Sobrien      p = frag_more (sizeof (e_note.namesz));
624489867Sobrien      md_number_to_chars (p, (valueT) i_note.namesz, sizeof (e_note.namesz));
624589867Sobrien      p = frag_more (sizeof (e_note.descsz));
624689867Sobrien      md_number_to_chars (p, (valueT) i_note.descsz, sizeof (e_note.descsz));
624789867Sobrien      p = frag_more (sizeof (e_note.type));
624889867Sobrien      md_number_to_chars (p, (valueT) i_note.type, sizeof (e_note.type));
624989867Sobrien      p = frag_more (len + 1);
625089867Sobrien      strcpy (p, cpu_arch_name);
625189867Sobrien
625289867Sobrien      frag_align (2, 0, 0);
625389867Sobrien
625489867Sobrien      subseg_set (seg, subseg);
625589867Sobrien    }
625689867Sobrien}
625789867Sobrien#endif
625833965Sjdp
625933965SjdpsymbolS *
626033965Sjdpmd_undefined_symbol (name)
626133965Sjdp     char *name;
626233965Sjdp{
626360519Sobrien  if (name[0] == GLOBAL_OFFSET_TABLE_NAME[0]
626460519Sobrien      && name[1] == GLOBAL_OFFSET_TABLE_NAME[1]
626560519Sobrien      && name[2] == GLOBAL_OFFSET_TABLE_NAME[2]
626660519Sobrien      && strcmp (name, GLOBAL_OFFSET_TABLE_NAME) == 0)
626760519Sobrien    {
626860519Sobrien      if (!GOT_symbol)
626960519Sobrien	{
627060519Sobrien	  if (symbol_find (name))
627160519Sobrien	    as_bad (_("GOT already in symbol table"));
627260519Sobrien	  GOT_symbol = symbol_new (name, undefined_section,
627360519Sobrien				   (valueT) 0, &zero_address_frag);
627460519Sobrien	};
627560519Sobrien      return GOT_symbol;
627660519Sobrien    }
627733965Sjdp  return 0;
627833965Sjdp}
627933965Sjdp
628033965Sjdp/* Round up a section size to the appropriate boundary.  */
628177311Sobrien
628233965SjdpvalueT
628333965Sjdpmd_section_align (segment, size)
628460519Sobrien     segT segment ATTRIBUTE_UNUSED;
628533965Sjdp     valueT size;
628633965Sjdp{
628760519Sobrien#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
628860519Sobrien  if (OUTPUT_FLAVOR == bfd_target_aout_flavour)
628960519Sobrien    {
629060519Sobrien      /* For a.out, force the section size to be aligned.  If we don't do
629160519Sobrien	 this, BFD will align it for us, but it will not write out the
629260519Sobrien	 final bytes of the section.  This may be a bug in BFD, but it is
629360519Sobrien	 easier to fix it here since that is how the other a.out targets
629460519Sobrien	 work.  */
629560519Sobrien      int align;
629633965Sjdp
629760519Sobrien      align = bfd_get_section_alignment (stdoutput, segment);
629860519Sobrien      size = ((size + (1 << align) - 1) & ((valueT) -1 << align));
629960519Sobrien    }
630033965Sjdp#endif
630133965Sjdp
630233965Sjdp  return size;
630333965Sjdp}
630433965Sjdp
630560519Sobrien/* On the i386, PC-relative offsets are relative to the start of the
630660519Sobrien   next instruction.  That is, the address of the offset, plus its
630760519Sobrien   size, since the offset is always the last part of the insn.  */
630860519Sobrien
630933965Sjdplong
6310218822Sdimmd_pcrel_from (fixS *fixP)
631133965Sjdp{
631233965Sjdp  return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
631333965Sjdp}
631433965Sjdp
631533965Sjdp#ifndef I386COFF
631633965Sjdp
631733965Sjdpstatic void
6318218822Sdims_bss (int ignore ATTRIBUTE_UNUSED)
631933965Sjdp{
632094546Sobrien  int temp;
632133965Sjdp
6322218822Sdim#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
6323218822Sdim  if (IS_ELF)
6324218822Sdim    obj_elf_section_change_hook ();
6325218822Sdim#endif
632633965Sjdp  temp = get_absolute_expression ();
632733965Sjdp  subseg_set (bss_section, (subsegT) temp);
632833965Sjdp  demand_empty_rest_of_line ();
632933965Sjdp}
633033965Sjdp
633133965Sjdp#endif
633233965Sjdp
633333965Sjdpvoid
6334218822Sdimi386_validate_fix (fixS *fixp)
633533965Sjdp{
633633965Sjdp  if (fixp->fx_subsy && fixp->fx_subsy == GOT_symbol)
633733965Sjdp    {
633877311Sobrien      if (fixp->fx_r_type == BFD_RELOC_32_PCREL)
633977311Sobrien	{
6340218822Sdim	  if (!object_64bit)
634177311Sobrien	    abort ();
634277311Sobrien	  fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL;
634377311Sobrien	}
634477311Sobrien      else
634577311Sobrien	{
6346218822Sdim	  if (!object_64bit)
6347218822Sdim	    fixp->fx_r_type = BFD_RELOC_386_GOTOFF;
6348218822Sdim	  else
6349218822Sdim	    fixp->fx_r_type = BFD_RELOC_X86_64_GOTOFF64;
635077311Sobrien	}
635133965Sjdp      fixp->fx_subsy = 0;
635233965Sjdp    }
635333965Sjdp}
635433965Sjdp
635533965Sjdparelent *
635633965Sjdptc_gen_reloc (section, fixp)
635760519Sobrien     asection *section ATTRIBUTE_UNUSED;
635833965Sjdp     fixS *fixp;
635933965Sjdp{
636033965Sjdp  arelent *rel;
636133965Sjdp  bfd_reloc_code_real_type code;
636233965Sjdp
636360519Sobrien  switch (fixp->fx_r_type)
636433965Sjdp    {
636577311Sobrien    case BFD_RELOC_X86_64_PLT32:
636677311Sobrien    case BFD_RELOC_X86_64_GOT32:
636777311Sobrien    case BFD_RELOC_X86_64_GOTPCREL:
636833965Sjdp    case BFD_RELOC_386_PLT32:
636933965Sjdp    case BFD_RELOC_386_GOT32:
637033965Sjdp    case BFD_RELOC_386_GOTOFF:
637133965Sjdp    case BFD_RELOC_386_GOTPC:
6372104848Sobrien    case BFD_RELOC_386_TLS_GD:
6373104848Sobrien    case BFD_RELOC_386_TLS_LDM:
6374104848Sobrien    case BFD_RELOC_386_TLS_LDO_32:
6375104848Sobrien    case BFD_RELOC_386_TLS_IE_32:
6376104848Sobrien    case BFD_RELOC_386_TLS_IE:
6377104848Sobrien    case BFD_RELOC_386_TLS_GOTIE:
6378104848Sobrien    case BFD_RELOC_386_TLS_LE_32:
6379104848Sobrien    case BFD_RELOC_386_TLS_LE:
6380218822Sdim    case BFD_RELOC_386_TLS_GOTDESC:
6381218822Sdim    case BFD_RELOC_386_TLS_DESC_CALL:
6382130570Sobrien    case BFD_RELOC_X86_64_TLSGD:
6383130570Sobrien    case BFD_RELOC_X86_64_TLSLD:
6384130570Sobrien    case BFD_RELOC_X86_64_DTPOFF32:
6385218822Sdim    case BFD_RELOC_X86_64_DTPOFF64:
6386130570Sobrien    case BFD_RELOC_X86_64_GOTTPOFF:
6387130570Sobrien    case BFD_RELOC_X86_64_TPOFF32:
6388218822Sdim    case BFD_RELOC_X86_64_TPOFF64:
6389218822Sdim    case BFD_RELOC_X86_64_GOTOFF64:
6390218822Sdim    case BFD_RELOC_X86_64_GOTPC32:
6391218822Sdim    case BFD_RELOC_X86_64_GOT64:
6392218822Sdim    case BFD_RELOC_X86_64_GOTPCREL64:
6393218822Sdim    case BFD_RELOC_X86_64_GOTPC64:
6394218822Sdim    case BFD_RELOC_X86_64_GOTPLT64:
6395218822Sdim    case BFD_RELOC_X86_64_PLTOFF64:
6396218822Sdim    case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
6397218822Sdim    case BFD_RELOC_X86_64_TLSDESC_CALL:
639838891Sjdp    case BFD_RELOC_RVA:
639960519Sobrien    case BFD_RELOC_VTABLE_ENTRY:
640060519Sobrien    case BFD_RELOC_VTABLE_INHERIT:
6401218822Sdim#ifdef TE_PE
6402218822Sdim    case BFD_RELOC_32_SECREL:
6403218822Sdim#endif
640433965Sjdp      code = fixp->fx_r_type;
640533965Sjdp      break;
6406218822Sdim    case BFD_RELOC_X86_64_32S:
6407218822Sdim      if (!fixp->fx_pcrel)
6408218822Sdim	{
6409218822Sdim	  /* Don't turn BFD_RELOC_X86_64_32S into BFD_RELOC_32.  */
6410218822Sdim	  code = fixp->fx_r_type;
6411218822Sdim	  break;
6412218822Sdim	}
641333965Sjdp    default:
641460519Sobrien      if (fixp->fx_pcrel)
641533965Sjdp	{
641660519Sobrien	  switch (fixp->fx_size)
641760519Sobrien	    {
641860519Sobrien	    default:
641989867Sobrien	      as_bad_where (fixp->fx_file, fixp->fx_line,
642089867Sobrien			    _("can not do %d byte pc-relative relocation"),
642189867Sobrien			    fixp->fx_size);
642260519Sobrien	      code = BFD_RELOC_32_PCREL;
642360519Sobrien	      break;
642460519Sobrien	    case 1: code = BFD_RELOC_8_PCREL;  break;
642560519Sobrien	    case 2: code = BFD_RELOC_16_PCREL; break;
642660519Sobrien	    case 4: code = BFD_RELOC_32_PCREL; break;
6427218822Sdim#ifdef BFD64
6428218822Sdim	    case 8: code = BFD_RELOC_64_PCREL; break;
6429218822Sdim#endif
643060519Sobrien	    }
643133965Sjdp	}
643260519Sobrien      else
643360519Sobrien	{
643460519Sobrien	  switch (fixp->fx_size)
643560519Sobrien	    {
643660519Sobrien	    default:
643789867Sobrien	      as_bad_where (fixp->fx_file, fixp->fx_line,
643889867Sobrien			    _("can not do %d byte relocation"),
643989867Sobrien			    fixp->fx_size);
644060519Sobrien	      code = BFD_RELOC_32;
644160519Sobrien	      break;
644260519Sobrien	    case 1: code = BFD_RELOC_8;  break;
644360519Sobrien	    case 2: code = BFD_RELOC_16; break;
644460519Sobrien	    case 4: code = BFD_RELOC_32; break;
644594546Sobrien#ifdef BFD64
644677311Sobrien	    case 8: code = BFD_RELOC_64; break;
644794546Sobrien#endif
644860519Sobrien	    }
644960519Sobrien	}
645060519Sobrien      break;
645133965Sjdp    }
645233965Sjdp
6453218822Sdim  if ((code == BFD_RELOC_32
6454218822Sdim       || code == BFD_RELOC_32_PCREL
6455218822Sdim       || code == BFD_RELOC_X86_64_32S)
645633965Sjdp      && GOT_symbol
645733965Sjdp      && fixp->fx_addsy == GOT_symbol)
645877311Sobrien    {
6459218822Sdim      if (!object_64bit)
6460218822Sdim	code = BFD_RELOC_386_GOTPC;
6461218822Sdim      else
6462218822Sdim	code = BFD_RELOC_X86_64_GOTPC32;
646377311Sobrien    }
6464218822Sdim  if ((code == BFD_RELOC_64 || code == BFD_RELOC_64_PCREL)
6465218822Sdim      && GOT_symbol
6466218822Sdim      && fixp->fx_addsy == GOT_symbol)
6467218822Sdim    {
6468218822Sdim      code = BFD_RELOC_X86_64_GOTPC64;
6469218822Sdim    }
647033965Sjdp
647133965Sjdp  rel = (arelent *) xmalloc (sizeof (arelent));
647260519Sobrien  rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
647360519Sobrien  *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
647460519Sobrien
647533965Sjdp  rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
6476218822Sdim
647777311Sobrien  if (!use_rela_relocations)
647877311Sobrien    {
647977311Sobrien      /* HACK: Since i386 ELF uses Rel instead of Rela, encode the
648077311Sobrien	 vtable entry to be used in the relocation's section offset.  */
648177311Sobrien      if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
648277311Sobrien	rel->address = fixp->fx_offset;
648360519Sobrien
6484104848Sobrien      rel->addend = 0;
648577311Sobrien    }
648677311Sobrien  /* Use the rela in 64bit mode.  */
648733965Sjdp  else
648877311Sobrien    {
648999468Sobrien      if (!fixp->fx_pcrel)
649099468Sobrien	rel->addend = fixp->fx_offset;
649199468Sobrien      else
649299468Sobrien	switch (code)
649399468Sobrien	  {
649499468Sobrien	  case BFD_RELOC_X86_64_PLT32:
649599468Sobrien	  case BFD_RELOC_X86_64_GOT32:
649699468Sobrien	  case BFD_RELOC_X86_64_GOTPCREL:
6497130570Sobrien	  case BFD_RELOC_X86_64_TLSGD:
6498130570Sobrien	  case BFD_RELOC_X86_64_TLSLD:
6499130570Sobrien	  case BFD_RELOC_X86_64_GOTTPOFF:
6500218822Sdim	  case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
6501218822Sdim	  case BFD_RELOC_X86_64_TLSDESC_CALL:
650299468Sobrien	    rel->addend = fixp->fx_offset - fixp->fx_size;
650399468Sobrien	    break;
650499468Sobrien	  default:
650599468Sobrien	    rel->addend = (section->vma
650699468Sobrien			   - fixp->fx_size
650799468Sobrien			   + fixp->fx_addnumber
650899468Sobrien			   + md_pcrel_from (fixp));
650999468Sobrien	    break;
651099468Sobrien	  }
651177311Sobrien    }
651233965Sjdp
651333965Sjdp  rel->howto = bfd_reloc_type_lookup (stdoutput, code);
651433965Sjdp  if (rel->howto == NULL)
651533965Sjdp    {
651633965Sjdp      as_bad_where (fixp->fx_file, fixp->fx_line,
651760519Sobrien		    _("cannot represent relocation type %s"),
651833965Sjdp		    bfd_get_reloc_code_name (code));
651933965Sjdp      /* Set howto to a garbage value so that we can keep going.  */
652033965Sjdp      rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
652133965Sjdp      assert (rel->howto != NULL);
652233965Sjdp    }
652333965Sjdp
652433965Sjdp  return rel;
652533965Sjdp}
652633965Sjdp
652733965Sjdp
652877311Sobrien/* Parse operands using Intel syntax. This implements a recursive descent
652977311Sobrien   parser based on the BNF grammar published in Appendix B of the MASM 6.1
653077311Sobrien   Programmer's Guide.
653177311Sobrien
653277311Sobrien   FIXME: We do not recognize the full operand grammar defined in the MASM
653377311Sobrien	  documentation.  In particular, all the structure/union and
653477311Sobrien	  high-level macro operands are missing.
653577311Sobrien
653677311Sobrien   Uppercase words are terminals, lower case words are non-terminals.
653777311Sobrien   Objects surrounded by double brackets '[[' ']]' are optional. Vertical
653877311Sobrien   bars '|' denote choices. Most grammar productions are implemented in
653977311Sobrien   functions called 'intel_<production>'.
654077311Sobrien
654177311Sobrien   Initial production is 'expr'.
654277311Sobrien
654377311Sobrien    addOp		+ | -
654477311Sobrien
654577311Sobrien    alpha		[a-zA-Z]
654677311Sobrien
6547218822Sdim    binOp		& | AND | \| | OR | ^ | XOR
6548218822Sdim
654977311Sobrien    byteRegister	AL | AH | BL | BH | CL | CH | DL | DH
655077311Sobrien
655177311Sobrien    constant		digits [[ radixOverride ]]
655277311Sobrien
6553218822Sdim    dataType		BYTE | WORD | DWORD | FWORD | QWORD | TBYTE | OWORD | XMMWORD
655477311Sobrien
655577311Sobrien    digits		decdigit
655677311Sobrien			| digits decdigit
655777311Sobrien			| digits hexdigit
655877311Sobrien
655977311Sobrien    decdigit		[0-9]
656077311Sobrien
6561218822Sdim    e04			e04 addOp e05
6562218822Sdim			| e05
6563218822Sdim
6564218822Sdim    e05			e05 binOp e06
656577311Sobrien			| e06
656677311Sobrien
656777311Sobrien    e06			e06 mulOp e09
656877311Sobrien			| e09
656977311Sobrien
657077311Sobrien    e09			OFFSET e10
6571218822Sdim			| SHORT e10
6572218822Sdim			| + e10
6573218822Sdim			| - e10
6574218822Sdim			| ~ e10
6575218822Sdim			| NOT e10
657677311Sobrien			| e09 PTR e10
657777311Sobrien			| e09 : e10
657877311Sobrien			| e10
657977311Sobrien
658077311Sobrien    e10			e10 [ expr ]
658177311Sobrien			| e11
658277311Sobrien
658377311Sobrien    e11			( expr )
658477311Sobrien			| [ expr ]
658577311Sobrien			| constant
658677311Sobrien			| dataType
658777311Sobrien			| id
658877311Sobrien			| $
658977311Sobrien			| register
659077311Sobrien
6591218822Sdim => expr		expr cmpOp e04
6592218822Sdim			| e04
659377311Sobrien
659477311Sobrien    gpRegister		AX | EAX | BX | EBX | CX | ECX | DX | EDX
659577311Sobrien			| BP | EBP | SP | ESP | DI | EDI | SI | ESI
659677311Sobrien
659777311Sobrien    hexdigit		a | b | c | d | e | f
659877311Sobrien			| A | B | C | D | E | F
659977311Sobrien
660077311Sobrien    id			alpha
660177311Sobrien			| id alpha
660277311Sobrien			| id decdigit
660377311Sobrien
6604218822Sdim    mulOp		* | / | % | MOD | << | SHL | >> | SHR
660577311Sobrien
660677311Sobrien    quote		" | '
660777311Sobrien
660877311Sobrien    register		specialRegister
660977311Sobrien			| gpRegister
661077311Sobrien			| byteRegister
661177311Sobrien
661277311Sobrien    segmentRegister	CS | DS | ES | FS | GS | SS
661377311Sobrien
6614218822Sdim    specialRegister	CR0 | CR2 | CR3 | CR4
661577311Sobrien			| DR0 | DR1 | DR2 | DR3 | DR6 | DR7
661677311Sobrien			| TR3 | TR4 | TR5 | TR6 | TR7
661777311Sobrien
661877311Sobrien    We simplify the grammar in obvious places (e.g., register parsing is
661977311Sobrien    done by calling parse_register) and eliminate immediate left recursion
662077311Sobrien    to implement a recursive-descent parser.
662177311Sobrien
6622218822Sdim    expr	e04 expr'
662377311Sobrien
6624218822Sdim    expr'	cmpOp e04 expr'
6625218822Sdim		| Empty
6626218822Sdim
6627218822Sdim    e04		e05 e04'
6628218822Sdim
6629218822Sdim    e04'	addOp e05 e04'
6630218822Sdim		| Empty
6631218822Sdim
663277311Sobrien    e05		e06 e05'
663377311Sobrien
6634218822Sdim    e05'	binOp e06 e05'
663577311Sobrien		| Empty
663677311Sobrien
663777311Sobrien    e06		e09 e06'
663877311Sobrien
663977311Sobrien    e06'	mulOp e09 e06'
664077311Sobrien		| Empty
664177311Sobrien
664277311Sobrien    e09		OFFSET e10 e09'
6643218822Sdim		| SHORT e10'
6644218822Sdim		| + e10'
6645218822Sdim		| - e10'
6646218822Sdim		| ~ e10'
6647218822Sdim		| NOT e10'
664877311Sobrien		| e10 e09'
664977311Sobrien
665077311Sobrien    e09'	PTR e10 e09'
665177311Sobrien		| : e10 e09'
665277311Sobrien		| Empty
665377311Sobrien
665477311Sobrien    e10		e11 e10'
665577311Sobrien
665677311Sobrien    e10'	[ expr ] e10'
665777311Sobrien		| Empty
665877311Sobrien
665977311Sobrien    e11		( expr )
666077311Sobrien		| [ expr ]
666177311Sobrien		| BYTE
666277311Sobrien		| WORD
666377311Sobrien		| DWORD
6664218822Sdim		| FWORD
666577311Sobrien		| QWORD
6666218822Sdim		| TBYTE
6667218822Sdim		| OWORD
6668218822Sdim		| XMMWORD
666977311Sobrien		| .
667077311Sobrien		| $
667177311Sobrien		| register
667277311Sobrien		| id
667377311Sobrien		| constant  */
667477311Sobrien
667577311Sobrien/* Parsing structure for the intel syntax parser. Used to implement the
667677311Sobrien   semantic actions for the operand grammar.  */
667777311Sobrienstruct intel_parser_s
667877311Sobrien  {
667977311Sobrien    char *op_string;		/* The string being parsed.  */
668077311Sobrien    int got_a_float;		/* Whether the operand is a float.  */
668177311Sobrien    int op_modifier;		/* Operand modifier.  */
668277311Sobrien    int is_mem;			/* 1 if operand is memory reference.  */
6683218822Sdim    int in_offset;		/* >=1 if parsing operand of offset.  */
6684218822Sdim    int in_bracket;		/* >=1 if parsing operand in brackets.  */
668577311Sobrien    const reg_entry *reg;	/* Last register reference found.  */
668677311Sobrien    char *disp;			/* Displacement string being built.  */
6687218822Sdim    char *next_operand;		/* Resume point when splitting operands.  */
668877311Sobrien  };
668977311Sobrien
669077311Sobrienstatic struct intel_parser_s intel_parser;
669177311Sobrien
669277311Sobrien/* Token structure for parsing intel syntax.  */
669377311Sobrienstruct intel_token
669477311Sobrien  {
669577311Sobrien    int code;			/* Token code.  */
669677311Sobrien    const reg_entry *reg;	/* Register entry for register tokens.  */
669777311Sobrien    char *str;			/* String representation.  */
669877311Sobrien  };
669977311Sobrien
670077311Sobrienstatic struct intel_token cur_token, prev_token;
670177311Sobrien
670277311Sobrien/* Token codes for the intel parser. Since T_SHORT is already used
670377311Sobrien   by COFF, undefine it first to prevent a warning.  */
670477311Sobrien#define T_NIL		-1
670577311Sobrien#define T_CONST		1
670677311Sobrien#define T_REG		2
670777311Sobrien#define T_BYTE		3
670877311Sobrien#define T_WORD		4
6709218822Sdim#define T_DWORD		5
6710218822Sdim#define T_FWORD		6
6711218822Sdim#define T_QWORD		7
6712218822Sdim#define T_TBYTE		8
6713218822Sdim#define T_XMMWORD	9
671477311Sobrien#undef  T_SHORT
6715218822Sdim#define T_SHORT		10
6716218822Sdim#define T_OFFSET	11
6717218822Sdim#define T_PTR		12
6718218822Sdim#define T_ID		13
6719218822Sdim#define T_SHL		14
6720218822Sdim#define T_SHR		15
672177311Sobrien
672277311Sobrien/* Prototypes for intel parser functions.  */
6723218822Sdimstatic int intel_match_token (int);
6724218822Sdimstatic void intel_putback_token	(void);
6725218822Sdimstatic void intel_get_token (void);
6726218822Sdimstatic int intel_expr (void);
6727218822Sdimstatic int intel_e04 (void);
6728218822Sdimstatic int intel_e05 (void);
6729218822Sdimstatic int intel_e06 (void);
6730218822Sdimstatic int intel_e09 (void);
6731218822Sdimstatic int intel_e10 (void);
6732218822Sdimstatic int intel_e11 (void);
673377311Sobrien
673477311Sobrienstatic int
6735218822Sdimi386_intel_operand (char *operand_string, int got_a_float)
673677311Sobrien{
673777311Sobrien  int ret;
673877311Sobrien  char *p;
673977311Sobrien
6740218822Sdim  p = intel_parser.op_string = xstrdup (operand_string);
6741218822Sdim  intel_parser.disp = (char *) xmalloc (strlen (operand_string) + 1);
674277311Sobrien
6743218822Sdim  for (;;)
6744218822Sdim    {
6745218822Sdim      /* Initialize token holders.  */
6746218822Sdim      cur_token.code = prev_token.code = T_NIL;
6747218822Sdim      cur_token.reg = prev_token.reg = NULL;
6748218822Sdim      cur_token.str = prev_token.str = NULL;
674977311Sobrien
6750218822Sdim      /* Initialize parser structure.  */
6751218822Sdim      intel_parser.got_a_float = got_a_float;
6752218822Sdim      intel_parser.op_modifier = 0;
6753218822Sdim      intel_parser.is_mem = 0;
6754218822Sdim      intel_parser.in_offset = 0;
6755218822Sdim      intel_parser.in_bracket = 0;
6756218822Sdim      intel_parser.reg = NULL;
6757218822Sdim      intel_parser.disp[0] = '\0';
6758218822Sdim      intel_parser.next_operand = NULL;
675977311Sobrien
6760218822Sdim      /* Read the first token and start the parser.  */
6761218822Sdim      intel_get_token ();
6762218822Sdim      ret = intel_expr ();
6763218822Sdim
6764218822Sdim      if (!ret)
6765218822Sdim	break;
6766218822Sdim
6767218822Sdim      if (cur_token.code != T_NIL)
6768218822Sdim	{
6769218822Sdim	  as_bad (_("invalid operand for '%s' ('%s' unexpected)"),
6770218822Sdim		  current_templates->start->name, cur_token.str);
6771218822Sdim	  ret = 0;
6772218822Sdim	}
677377311Sobrien      /* If we found a memory reference, hand it over to i386_displacement
677477311Sobrien	 to fill in the rest of the operand fields.  */
6775218822Sdim      else if (intel_parser.is_mem)
677677311Sobrien	{
677777311Sobrien	  if ((i.mem_operands == 1
677877311Sobrien	       && (current_templates->start->opcode_modifier & IsString) == 0)
677977311Sobrien	      || i.mem_operands == 2)
678077311Sobrien	    {
678177311Sobrien	      as_bad (_("too many memory references for '%s'"),
678277311Sobrien		      current_templates->start->name);
678377311Sobrien	      ret = 0;
678477311Sobrien	    }
678577311Sobrien	  else
678677311Sobrien	    {
678777311Sobrien	      char *s = intel_parser.disp;
678877311Sobrien	      i.mem_operands++;
678977311Sobrien
6790218822Sdim	      if (!quiet_warnings && intel_parser.is_mem < 0)
6791218822Sdim		/* See the comments in intel_bracket_expr.  */
6792218822Sdim		as_warn (_("Treating `%s' as memory reference"), operand_string);
6793218822Sdim
679477311Sobrien	      /* Add the displacement expression.  */
679577311Sobrien	      if (*s != '\0')
6796130570Sobrien		ret = i386_displacement (s, s + strlen (s));
6797130570Sobrien	      if (ret)
6798218822Sdim		{
6799218822Sdim		  /* Swap base and index in 16-bit memory operands like
6800218822Sdim		     [si+bx]. Since i386_index_check is also used in AT&T
6801218822Sdim		     mode we have to do that here.  */
6802218822Sdim		  if (i.base_reg
6803218822Sdim		      && i.index_reg
6804218822Sdim		      && (i.base_reg->reg_type & Reg16)
6805218822Sdim		      && (i.index_reg->reg_type & Reg16)
6806218822Sdim		      && i.base_reg->reg_num >= 6
6807218822Sdim		      && i.index_reg->reg_num < 6)
6808218822Sdim		    {
6809218822Sdim		      const reg_entry *base = i.index_reg;
6810218822Sdim
6811218822Sdim		      i.index_reg = i.base_reg;
6812218822Sdim		      i.base_reg = base;
6813218822Sdim		    }
6814218822Sdim		  ret = i386_index_check (operand_string);
6815218822Sdim		}
681677311Sobrien	    }
681777311Sobrien	}
681877311Sobrien
681977311Sobrien      /* Constant and OFFSET expressions are handled by i386_immediate.  */
6820218822Sdim      else if ((intel_parser.op_modifier & (1 << T_OFFSET))
682177311Sobrien	       || intel_parser.reg == NULL)
682277311Sobrien	ret = i386_immediate (intel_parser.disp);
6823218822Sdim
6824218822Sdim      if (intel_parser.next_operand && this_operand >= MAX_OPERANDS - 1)
6825218822Sdim	ret = 0;
6826218822Sdim      if (!ret || !intel_parser.next_operand)
6827218822Sdim	break;
6828218822Sdim      intel_parser.op_string = intel_parser.next_operand;
6829218822Sdim      this_operand = i.operands++;
683077311Sobrien    }
683177311Sobrien
683277311Sobrien  free (p);
683377311Sobrien  free (intel_parser.disp);
683477311Sobrien
683577311Sobrien  return ret;
683677311Sobrien}
683777311Sobrien
6838218822Sdim#define NUM_ADDRESS_REGS (!!i.base_reg + !!i.index_reg)
6839218822Sdim
6840218822Sdim/* expr	e04 expr'
6841218822Sdim
6842218822Sdim   expr'  cmpOp e04 expr'
6843218822Sdim	| Empty  */
684477311Sobrienstatic int
6845218822Sdimintel_expr (void)
684677311Sobrien{
6847218822Sdim  /* XXX Implement the comparison operators.  */
6848218822Sdim  return intel_e04 ();
6849218822Sdim}
6850218822Sdim
6851218822Sdim/* e04	e05 e04'
6852218822Sdim
6853218822Sdim   e04'	addOp e05 e04'
6854218822Sdim	| Empty  */
6855218822Sdimstatic int
6856218822Sdimintel_e04 (void)
6857218822Sdim{
6858218822Sdim  int nregs = -1;
6859218822Sdim
6860218822Sdim  for (;;)
686177311Sobrien    {
6862218822Sdim      if (!intel_e05())
6863218822Sdim	return 0;
686477311Sobrien
6865218822Sdim      if (nregs >= 0 && NUM_ADDRESS_REGS > nregs)
6866218822Sdim	i.base_reg = i386_regtab + REGNAM_AL; /* al is invalid as base */
6867218822Sdim
6868218822Sdim      if (cur_token.code == '+')
6869218822Sdim	nregs = -1;
6870218822Sdim      else if (cur_token.code == '-')
6871218822Sdim	nregs = NUM_ADDRESS_REGS;
6872218822Sdim      else
6873218822Sdim	return 1;
6874218822Sdim
6875218822Sdim      strcat (intel_parser.disp, cur_token.str);
6876218822Sdim      intel_match_token (cur_token.code);
687777311Sobrien    }
687877311Sobrien}
687977311Sobrien
688077311Sobrien/* e05	e06 e05'
688177311Sobrien
6882218822Sdim   e05'	binOp e06 e05'
688377311Sobrien	| Empty  */
688477311Sobrienstatic int
6885218822Sdimintel_e05 (void)
688677311Sobrien{
6887218822Sdim  int nregs = ~NUM_ADDRESS_REGS;
688877311Sobrien
6889218822Sdim  for (;;)
689077311Sobrien    {
6891218822Sdim      if (!intel_e06())
6892218822Sdim	return 0;
6893218822Sdim
6894218822Sdim      if (cur_token.code == '&'
6895218822Sdim	  || cur_token.code == '|'
6896218822Sdim	  || cur_token.code == '^')
6897218822Sdim	{
6898218822Sdim	  char str[2];
6899218822Sdim
6900218822Sdim	  str[0] = cur_token.code;
6901218822Sdim	  str[1] = 0;
6902218822Sdim	  strcat (intel_parser.disp, str);
6903218822Sdim	}
6904218822Sdim      else
6905218822Sdim	break;
6906218822Sdim
690777311Sobrien      intel_match_token (cur_token.code);
690877311Sobrien
6909218822Sdim      if (nregs < 0)
6910218822Sdim	nregs = ~nregs;
691177311Sobrien    }
6912218822Sdim  if (nregs >= 0 && NUM_ADDRESS_REGS > nregs)
6913218822Sdim    i.base_reg = i386_regtab + REGNAM_AL + 1; /* cl is invalid as base */
6914218822Sdim  return 1;
691577311Sobrien}
691677311Sobrien
691777311Sobrien/* e06	e09 e06'
691877311Sobrien
691977311Sobrien   e06'	mulOp e09 e06'
692077311Sobrien	| Empty  */
692177311Sobrienstatic int
6922218822Sdimintel_e06 (void)
692377311Sobrien{
6924218822Sdim  int nregs = ~NUM_ADDRESS_REGS;
692577311Sobrien
6926218822Sdim  for (;;)
692777311Sobrien    {
6928218822Sdim      if (!intel_e09())
6929218822Sdim	return 0;
6930218822Sdim
6931218822Sdim      if (cur_token.code == '*'
6932218822Sdim	  || cur_token.code == '/'
6933218822Sdim	  || cur_token.code == '%')
6934218822Sdim	{
6935218822Sdim	  char str[2];
6936218822Sdim
6937218822Sdim	  str[0] = cur_token.code;
6938218822Sdim	  str[1] = 0;
6939218822Sdim	  strcat (intel_parser.disp, str);
6940218822Sdim	}
6941218822Sdim      else if (cur_token.code == T_SHL)
6942218822Sdim	strcat (intel_parser.disp, "<<");
6943218822Sdim      else if (cur_token.code == T_SHR)
6944218822Sdim	strcat (intel_parser.disp, ">>");
6945218822Sdim      else
6946218822Sdim	break;
6947218822Sdim
694877311Sobrien      intel_match_token (cur_token.code);
694977311Sobrien
6950218822Sdim      if (nregs < 0)
6951218822Sdim	nregs = ~nregs;
695277311Sobrien    }
6953218822Sdim  if (nregs >= 0 && NUM_ADDRESS_REGS > nregs)
6954218822Sdim    i.base_reg = i386_regtab + REGNAM_AL + 2; /* dl is invalid as base */
6955218822Sdim  return 1;
695677311Sobrien}
695777311Sobrien
6958218822Sdim/* e09	OFFSET e09
6959218822Sdim	| SHORT e09
6960218822Sdim	| + e09
6961218822Sdim	| - e09
6962218822Sdim	| ~ e09
6963218822Sdim	| NOT e09
696477311Sobrien	| e10 e09'
696577311Sobrien
696677311Sobrien   e09'	PTR e10 e09'
696777311Sobrien	| : e10 e09'
696877311Sobrien	| Empty */
696977311Sobrienstatic int
6970218822Sdimintel_e09 (void)
697177311Sobrien{
6972218822Sdim  int nregs = ~NUM_ADDRESS_REGS;
6973218822Sdim  int in_offset = 0;
6974218822Sdim
6975218822Sdim  for (;;)
697677311Sobrien    {
6977218822Sdim      /* Don't consume constants here.  */
6978218822Sdim      if (cur_token.code == '+' || cur_token.code == '-')
6979218822Sdim	{
6980218822Sdim	  /* Need to look one token ahead - if the next token
6981218822Sdim	     is a constant, the current token is its sign.  */
6982218822Sdim	  int next_code;
698377311Sobrien
6984218822Sdim	  intel_match_token (cur_token.code);
6985218822Sdim	  next_code = cur_token.code;
6986218822Sdim	  intel_putback_token ();
6987218822Sdim	  if (next_code == T_CONST)
6988218822Sdim	    break;
6989218822Sdim	}
699077311Sobrien
6991218822Sdim      /* e09  OFFSET e09  */
6992218822Sdim      if (cur_token.code == T_OFFSET)
6993218822Sdim	{
6994218822Sdim	  if (!in_offset++)
6995218822Sdim	    ++intel_parser.in_offset;
6996218822Sdim	}
699777311Sobrien
6998218822Sdim      /* e09  SHORT e09  */
6999218822Sdim      else if (cur_token.code == T_SHORT)
7000218822Sdim	intel_parser.op_modifier |= 1 << T_SHORT;
700177311Sobrien
7002218822Sdim      /* e09  + e09  */
7003218822Sdim      else if (cur_token.code == '+')
7004218822Sdim	strcat (intel_parser.disp, "+");
7005218822Sdim
7006218822Sdim      /* e09  - e09
7007218822Sdim	      | ~ e09
7008218822Sdim	      | NOT e09  */
7009218822Sdim      else if (cur_token.code == '-' || cur_token.code == '~')
701077311Sobrien	{
7011218822Sdim	  char str[2];
7012218822Sdim
7013218822Sdim	  if (nregs < 0)
7014218822Sdim	    nregs = ~nregs;
7015218822Sdim	  str[0] = cur_token.code;
7016218822Sdim	  str[1] = 0;
7017218822Sdim	  strcat (intel_parser.disp, str);
701877311Sobrien	}
701977311Sobrien
7020218822Sdim      /* e09  e10 e09'  */
7021218822Sdim      else
7022218822Sdim	break;
7023218822Sdim
7024218822Sdim      intel_match_token (cur_token.code);
7025218822Sdim    }
7026218822Sdim
7027218822Sdim  for (;;)
7028218822Sdim    {
7029218822Sdim      if (!intel_e10 ())
7030218822Sdim	return 0;
7031218822Sdim
7032218822Sdim      /* e09'  PTR e10 e09' */
7033218822Sdim      if (cur_token.code == T_PTR)
703477311Sobrien	{
7035218822Sdim	  char suffix;
7036218822Sdim
7037218822Sdim	  if (prev_token.code == T_BYTE)
7038218822Sdim	    suffix = BYTE_MNEM_SUFFIX;
7039218822Sdim
7040218822Sdim	  else if (prev_token.code == T_WORD)
7041218822Sdim	    {
7042218822Sdim	      if (current_templates->start->name[0] == 'l'
7043218822Sdim		  && current_templates->start->name[2] == 's'
7044218822Sdim		  && current_templates->start->name[3] == 0)
7045218822Sdim		suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */
7046218822Sdim	      else if (intel_parser.got_a_float == 2)	/* "fi..." */
7047218822Sdim		suffix = SHORT_MNEM_SUFFIX;
7048218822Sdim	      else
7049218822Sdim		suffix = WORD_MNEM_SUFFIX;
7050218822Sdim	    }
7051218822Sdim
7052218822Sdim	  else if (prev_token.code == T_DWORD)
7053218822Sdim	    {
7054218822Sdim	      if (current_templates->start->name[0] == 'l'
7055218822Sdim		  && current_templates->start->name[2] == 's'
7056218822Sdim		  && current_templates->start->name[3] == 0)
7057218822Sdim		suffix = WORD_MNEM_SUFFIX;
7058218822Sdim	      else if (flag_code == CODE_16BIT
7059218822Sdim		       && (current_templates->start->opcode_modifier
7060218822Sdim			   & (Jump | JumpDword)))
7061218822Sdim		suffix = LONG_DOUBLE_MNEM_SUFFIX;
7062218822Sdim	      else if (intel_parser.got_a_float == 1)	/* "f..." */
7063218822Sdim		suffix = SHORT_MNEM_SUFFIX;
7064218822Sdim	      else
7065218822Sdim		suffix = LONG_MNEM_SUFFIX;
7066218822Sdim	    }
7067218822Sdim
7068218822Sdim	  else if (prev_token.code == T_FWORD)
7069218822Sdim	    {
7070218822Sdim	      if (current_templates->start->name[0] == 'l'
7071218822Sdim		  && current_templates->start->name[2] == 's'
7072218822Sdim		  && current_templates->start->name[3] == 0)
7073218822Sdim		suffix = LONG_MNEM_SUFFIX;
7074218822Sdim	      else if (!intel_parser.got_a_float)
7075218822Sdim		{
7076218822Sdim		  if (flag_code == CODE_16BIT)
7077218822Sdim		    add_prefix (DATA_PREFIX_OPCODE);
7078218822Sdim		  suffix = LONG_DOUBLE_MNEM_SUFFIX;
7079218822Sdim		}
7080218822Sdim	      else
7081218822Sdim		suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */
7082218822Sdim	    }
7083218822Sdim
7084218822Sdim	  else if (prev_token.code == T_QWORD)
7085218822Sdim	    {
7086218822Sdim	      if (intel_parser.got_a_float == 1)	/* "f..." */
7087218822Sdim		suffix = LONG_MNEM_SUFFIX;
7088218822Sdim	      else
7089218822Sdim		suffix = QWORD_MNEM_SUFFIX;
7090218822Sdim	    }
7091218822Sdim
7092218822Sdim	  else if (prev_token.code == T_TBYTE)
7093218822Sdim	    {
7094218822Sdim	      if (intel_parser.got_a_float == 1)
7095218822Sdim		suffix = LONG_DOUBLE_MNEM_SUFFIX;
7096218822Sdim	      else
7097218822Sdim		suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */
7098218822Sdim	    }
7099218822Sdim
7100218822Sdim	  else if (prev_token.code == T_XMMWORD)
7101218822Sdim	    {
7102218822Sdim	      /* XXX ignored for now, but accepted since gcc uses it */
7103218822Sdim	      suffix = 0;
7104218822Sdim	    }
7105218822Sdim
710677311Sobrien	  else
7107218822Sdim	    {
7108218822Sdim	      as_bad (_("Unknown operand modifier `%s'"), prev_token.str);
7109218822Sdim	      return 0;
7110218822Sdim	    }
7111218822Sdim
7112218822Sdim	  /* Operands for jump/call using 'ptr' notation denote absolute
7113218822Sdim	     addresses.  */
7114218822Sdim	  if (current_templates->start->opcode_modifier & (Jump | JumpDword))
7115218822Sdim	    i.types[this_operand] |= JumpAbsolute;
7116218822Sdim
7117218822Sdim	  if (current_templates->start->base_opcode == 0x8d /* lea */)
7118218822Sdim	    ;
7119218822Sdim	  else if (!i.suffix)
7120218822Sdim	    i.suffix = suffix;
7121218822Sdim	  else if (i.suffix != suffix)
7122218822Sdim	    {
7123218822Sdim	      as_bad (_("Conflicting operand modifiers"));
7124218822Sdim	      return 0;
7125218822Sdim	    }
7126218822Sdim
712777311Sobrien	}
712877311Sobrien
7129218822Sdim      /* e09'  : e10 e09'  */
7130218822Sdim      else if (cur_token.code == ':')
713177311Sobrien	{
7132218822Sdim	  if (prev_token.code != T_REG)
7133218822Sdim	    {
7134218822Sdim	      /* While {call,jmp} SSSS:OOOO is MASM syntax only when SSSS is a
7135218822Sdim		 segment/group identifier (which we don't have), using comma
7136218822Sdim		 as the operand separator there is even less consistent, since
7137218822Sdim		 there all branches only have a single operand.  */
7138218822Sdim	      if (this_operand != 0
7139218822Sdim		  || intel_parser.in_offset
7140218822Sdim		  || intel_parser.in_bracket
7141218822Sdim		  || (!(current_templates->start->opcode_modifier
7142218822Sdim			& (Jump|JumpDword|JumpInterSegment))
7143218822Sdim		      && !(current_templates->start->operand_types[0]
7144218822Sdim			   & JumpAbsolute)))
7145218822Sdim		return intel_match_token (T_NIL);
7146218822Sdim	      /* Remember the start of the 2nd operand and terminate 1st
7147218822Sdim		 operand here.
7148218822Sdim		 XXX This isn't right, yet (when SSSS:OOOO is right operand of
7149218822Sdim		 another expression), but it gets at least the simplest case
7150218822Sdim		 (a plain number or symbol on the left side) right.  */
7151218822Sdim	      intel_parser.next_operand = intel_parser.op_string;
7152218822Sdim	      *--intel_parser.op_string = '\0';
7153218822Sdim	      return intel_match_token (':');
7154218822Sdim	    }
715577311Sobrien	}
715677311Sobrien
7157218822Sdim      /* e09'  Empty  */
7158218822Sdim      else
7159218822Sdim	break;
716077311Sobrien
7161218822Sdim      intel_match_token (cur_token.code);
7162218822Sdim
7163218822Sdim    }
7164218822Sdim
7165218822Sdim  if (in_offset)
7166218822Sdim    {
7167218822Sdim      --intel_parser.in_offset;
7168218822Sdim      if (nregs < 0)
7169218822Sdim	nregs = ~nregs;
7170218822Sdim      if (NUM_ADDRESS_REGS > nregs)
717177311Sobrien	{
7172218822Sdim	  as_bad (_("Invalid operand to `OFFSET'"));
717377311Sobrien	  return 0;
717477311Sobrien	}
7175218822Sdim      intel_parser.op_modifier |= 1 << T_OFFSET;
7176218822Sdim    }
717777311Sobrien
7178218822Sdim  if (nregs >= 0 && NUM_ADDRESS_REGS > nregs)
7179218822Sdim    i.base_reg = i386_regtab + REGNAM_AL + 3; /* bl is invalid as base */
7180218822Sdim  return 1;
7181218822Sdim}
718277311Sobrien
7183218822Sdimstatic int
7184218822Sdimintel_bracket_expr (void)
7185218822Sdim{
7186218822Sdim  int was_offset = intel_parser.op_modifier & (1 << T_OFFSET);
7187218822Sdim  const char *start = intel_parser.op_string;
7188218822Sdim  int len;
7189218822Sdim
7190218822Sdim  if (i.op[this_operand].regs)
7191218822Sdim    return intel_match_token (T_NIL);
7192218822Sdim
7193218822Sdim  intel_match_token ('[');
7194218822Sdim
7195218822Sdim  /* Mark as a memory operand only if it's not already known to be an
7196218822Sdim     offset expression.  If it's an offset expression, we need to keep
7197218822Sdim     the brace in.  */
7198218822Sdim  if (!intel_parser.in_offset)
7199218822Sdim    {
7200218822Sdim      ++intel_parser.in_bracket;
7201218822Sdim
7202218822Sdim      /* Operands for jump/call inside brackets denote absolute addresses.  */
7203218822Sdim      if (current_templates->start->opcode_modifier & (Jump | JumpDword))
7204218822Sdim	i.types[this_operand] |= JumpAbsolute;
7205218822Sdim
7206218822Sdim      /* Unfortunately gas always diverged from MASM in a respect that can't
7207218822Sdim	 be easily fixed without risking to break code sequences likely to be
7208218822Sdim	 encountered (the testsuite even check for this): MASM doesn't consider
7209218822Sdim	 an expression inside brackets unconditionally as a memory reference.
7210218822Sdim	 When that is e.g. a constant, an offset expression, or the sum of the
7211218822Sdim	 two, this is still taken as a constant load. gas, however, always
7212218822Sdim	 treated these as memory references. As a compromise, we'll try to make
7213218822Sdim	 offset expressions inside brackets work the MASM way (since that's
7214218822Sdim	 less likely to be found in real world code), but make constants alone
7215218822Sdim	 continue to work the traditional gas way. In either case, issue a
7216218822Sdim	 warning.  */
7217218822Sdim      intel_parser.op_modifier &= ~was_offset;
721877311Sobrien    }
7219218822Sdim  else
7220218822Sdim    strcat (intel_parser.disp, "[");
722177311Sobrien
7222218822Sdim  /* Add a '+' to the displacement string if necessary.  */
7223218822Sdim  if (*intel_parser.disp != '\0'
7224218822Sdim      && *(intel_parser.disp + strlen (intel_parser.disp) - 1) != '+')
7225218822Sdim    strcat (intel_parser.disp, "+");
7226218822Sdim
7227218822Sdim  if (intel_expr ()
7228218822Sdim      && (len = intel_parser.op_string - start - 1,
7229218822Sdim	  intel_match_token (']')))
723077311Sobrien    {
7231218822Sdim      /* Preserve brackets when the operand is an offset expression.  */
7232218822Sdim      if (intel_parser.in_offset)
7233218822Sdim	strcat (intel_parser.disp, "]");
7234218822Sdim      else
7235218822Sdim	{
7236218822Sdim	  --intel_parser.in_bracket;
7237218822Sdim	  if (i.base_reg || i.index_reg)
7238218822Sdim	    intel_parser.is_mem = 1;
7239218822Sdim	  if (!intel_parser.is_mem)
7240218822Sdim	    {
7241218822Sdim	      if (!(intel_parser.op_modifier & (1 << T_OFFSET)))
7242218822Sdim		/* Defer the warning until all of the operand was parsed.  */
7243218822Sdim		intel_parser.is_mem = -1;
7244218822Sdim	      else if (!quiet_warnings)
7245218822Sdim		as_warn (_("`[%.*s]' taken to mean just `%.*s'"),
7246218822Sdim			 len, start, len, start);
7247218822Sdim	    }
7248218822Sdim	}
7249218822Sdim      intel_parser.op_modifier |= was_offset;
725077311Sobrien
7251218822Sdim      return 1;
725277311Sobrien    }
7253218822Sdim  return 0;
725477311Sobrien}
725577311Sobrien
725677311Sobrien/* e10	e11 e10'
725777311Sobrien
725877311Sobrien   e10'	[ expr ] e10'
725977311Sobrien	| Empty  */
726077311Sobrienstatic int
7261218822Sdimintel_e10 (void)
726277311Sobrien{
7263218822Sdim  if (!intel_e11 ())
7264218822Sdim    return 0;
726577311Sobrien
7266218822Sdim  while (cur_token.code == '[')
726777311Sobrien    {
7268218822Sdim      if (!intel_bracket_expr ())
726977311Sobrien	return 0;
727077311Sobrien    }
727177311Sobrien
7272218822Sdim  return 1;
727377311Sobrien}
727477311Sobrien
727577311Sobrien/* e11	( expr )
727677311Sobrien	| [ expr ]
727777311Sobrien	| BYTE
727877311Sobrien	| WORD
727977311Sobrien	| DWORD
7280218822Sdim	| FWORD
728177311Sobrien	| QWORD
7282218822Sdim	| TBYTE
7283218822Sdim	| OWORD
7284218822Sdim	| XMMWORD
728577311Sobrien	| $
728677311Sobrien	| .
728777311Sobrien	| register
728877311Sobrien	| id
728977311Sobrien	| constant  */
729077311Sobrienstatic int
7291218822Sdimintel_e11 (void)
729277311Sobrien{
7293218822Sdim  switch (cur_token.code)
729477311Sobrien    {
7295218822Sdim    /* e11  ( expr ) */
7296218822Sdim    case '(':
729777311Sobrien      intel_match_token ('(');
729877311Sobrien      strcat (intel_parser.disp, "(");
729977311Sobrien
730077311Sobrien      if (intel_expr () && intel_match_token (')'))
730177311Sobrien	{
730277311Sobrien	  strcat (intel_parser.disp, ")");
730377311Sobrien	  return 1;
730477311Sobrien	}
7305218822Sdim      return 0;
730677311Sobrien
7307218822Sdim    /* e11  [ expr ] */
7308218822Sdim    case '[':
7309218822Sdim      return intel_bracket_expr ();
731077311Sobrien
7311218822Sdim    /* e11  $
7312218822Sdim	    | .  */
7313218822Sdim    case '.':
731477311Sobrien      strcat (intel_parser.disp, cur_token.str);
731577311Sobrien      intel_match_token (cur_token.code);
731677311Sobrien
731777311Sobrien      /* Mark as a memory operand only if it's not already known to be an
731877311Sobrien	 offset expression.  */
7319218822Sdim      if (!intel_parser.in_offset)
732077311Sobrien	intel_parser.is_mem = 1;
732177311Sobrien
732277311Sobrien      return 1;
732377311Sobrien
7324218822Sdim    /* e11  register  */
7325218822Sdim    case T_REG:
7326218822Sdim      {
7327218822Sdim	const reg_entry *reg = intel_parser.reg = cur_token.reg;
732877311Sobrien
7329218822Sdim	intel_match_token (T_REG);
733077311Sobrien
7331218822Sdim	/* Check for segment change.  */
7332218822Sdim	if (cur_token.code == ':')
7333218822Sdim	  {
7334218822Sdim	    if (!(reg->reg_type & (SReg2 | SReg3)))
7335218822Sdim	      {
7336218822Sdim		as_bad (_("`%s' is not a valid segment register"),
7337218822Sdim			reg->reg_name);
7338218822Sdim		return 0;
7339218822Sdim	      }
7340218822Sdim	    else if (i.seg[i.mem_operands])
7341218822Sdim	      as_warn (_("Extra segment override ignored"));
7342218822Sdim	    else
7343218822Sdim	      {
7344218822Sdim		if (!intel_parser.in_offset)
7345218822Sdim		  intel_parser.is_mem = 1;
7346218822Sdim		switch (reg->reg_num)
7347218822Sdim		  {
7348218822Sdim		  case 0:
7349218822Sdim		    i.seg[i.mem_operands] = &es;
7350218822Sdim		    break;
7351218822Sdim		  case 1:
7352218822Sdim		    i.seg[i.mem_operands] = &cs;
7353218822Sdim		    break;
7354218822Sdim		  case 2:
7355218822Sdim		    i.seg[i.mem_operands] = &ss;
7356218822Sdim		    break;
7357218822Sdim		  case 3:
7358218822Sdim		    i.seg[i.mem_operands] = &ds;
7359218822Sdim		    break;
7360218822Sdim		  case 4:
7361218822Sdim		    i.seg[i.mem_operands] = &fs;
7362218822Sdim		    break;
7363218822Sdim		  case 5:
7364218822Sdim		    i.seg[i.mem_operands] = &gs;
7365218822Sdim		    break;
7366218822Sdim		  }
7367218822Sdim	      }
7368218822Sdim	  }
736977311Sobrien
7370218822Sdim	/* Not a segment register. Check for register scaling.  */
7371218822Sdim	else if (cur_token.code == '*')
7372218822Sdim	  {
7373218822Sdim	    if (!intel_parser.in_bracket)
7374218822Sdim	      {
7375218822Sdim		as_bad (_("Register scaling only allowed in memory operands"));
7376218822Sdim		return 0;
7377218822Sdim	      }
7378218822Sdim
7379218822Sdim	    if (reg->reg_type & Reg16) /* Disallow things like [si*1]. */
7380218822Sdim	      reg = i386_regtab + REGNAM_AX + 4; /* sp is invalid as index */
7381218822Sdim	    else if (i.index_reg)
7382218822Sdim	      reg = i386_regtab + REGNAM_EAX + 4; /* esp is invalid as index */
7383218822Sdim
7384218822Sdim	    /* What follows must be a valid scale.  */
7385218822Sdim	    intel_match_token ('*');
7386218822Sdim	    i.index_reg = reg;
7387218822Sdim	    i.types[this_operand] |= BaseIndex;
7388218822Sdim
7389218822Sdim	    /* Set the scale after setting the register (otherwise,
7390218822Sdim	       i386_scale will complain)  */
7391218822Sdim	    if (cur_token.code == '+' || cur_token.code == '-')
7392218822Sdim	      {
7393218822Sdim		char *str, sign = cur_token.code;
7394218822Sdim		intel_match_token (cur_token.code);
7395218822Sdim		if (cur_token.code != T_CONST)
7396218822Sdim		  {
7397218822Sdim		    as_bad (_("Syntax error: Expecting a constant, got `%s'"),
7398218822Sdim			    cur_token.str);
7399218822Sdim		    return 0;
7400218822Sdim		  }
7401218822Sdim		str = (char *) xmalloc (strlen (cur_token.str) + 2);
7402218822Sdim		strcpy (str + 1, cur_token.str);
7403218822Sdim		*str = sign;
7404218822Sdim		if (!i386_scale (str))
7405218822Sdim		  return 0;
7406218822Sdim		free (str);
7407218822Sdim	      }
7408218822Sdim	    else if (!i386_scale (cur_token.str))
740977311Sobrien	      return 0;
7410218822Sdim	    intel_match_token (cur_token.code);
7411218822Sdim	  }
741277311Sobrien
7413218822Sdim	/* No scaling. If this is a memory operand, the register is either a
7414218822Sdim	   base register (first occurrence) or an index register (second
7415218822Sdim	   occurrence).  */
7416218822Sdim	else if (intel_parser.in_bracket)
7417218822Sdim	  {
7418218822Sdim
7419218822Sdim	    if (!i.base_reg)
7420218822Sdim	      i.base_reg = reg;
7421218822Sdim	    else if (!i.index_reg)
742277311Sobrien	      i.index_reg = reg;
7423218822Sdim	    else
7424218822Sdim	      {
7425218822Sdim		as_bad (_("Too many register references in memory operand"));
7426218822Sdim		return 0;
7427218822Sdim	      }
742877311Sobrien
7429218822Sdim	    i.types[this_operand] |= BaseIndex;
7430218822Sdim	  }
743177311Sobrien
7432218822Sdim	/* It's neither base nor index.  */
7433218822Sdim	else if (!intel_parser.in_offset && !intel_parser.is_mem)
7434218822Sdim	  {
7435218822Sdim	    i.types[this_operand] |= reg->reg_type & ~BaseIndex;
7436218822Sdim	    i.op[this_operand].regs = reg;
7437218822Sdim	    i.reg_operands++;
7438218822Sdim	  }
7439218822Sdim	else
7440218822Sdim	  {
7441218822Sdim	    as_bad (_("Invalid use of register"));
7442218822Sdim	    return 0;
7443218822Sdim	  }
744477311Sobrien
7445218822Sdim	/* Since registers are not part of the displacement string (except
7446218822Sdim	   when we're parsing offset operands), we may need to remove any
7447218822Sdim	   preceding '+' from the displacement string.  */
7448218822Sdim	if (*intel_parser.disp != '\0'
7449218822Sdim	    && !intel_parser.in_offset)
7450218822Sdim	  {
7451218822Sdim	    char *s = intel_parser.disp;
7452218822Sdim	    s += strlen (s) - 1;
7453218822Sdim	    if (*s == '+')
7454218822Sdim	      *s = '\0';
7455218822Sdim	  }
745677311Sobrien
7457218822Sdim	return 1;
7458218822Sdim      }
745977311Sobrien
7460218822Sdim    /* e11  BYTE
7461218822Sdim	    | WORD
7462218822Sdim	    | DWORD
7463218822Sdim	    | FWORD
7464218822Sdim	    | QWORD
7465218822Sdim	    | TBYTE
7466218822Sdim	    | OWORD
7467218822Sdim	    | XMMWORD  */
7468218822Sdim    case T_BYTE:
7469218822Sdim    case T_WORD:
7470218822Sdim    case T_DWORD:
7471218822Sdim    case T_FWORD:
7472218822Sdim    case T_QWORD:
7473218822Sdim    case T_TBYTE:
7474218822Sdim    case T_XMMWORD:
7475218822Sdim      intel_match_token (cur_token.code);
747677311Sobrien
7477218822Sdim      if (cur_token.code == T_PTR)
7478218822Sdim	return 1;
7479218822Sdim
7480218822Sdim      /* It must have been an identifier.  */
7481218822Sdim      intel_putback_token ();
7482218822Sdim      cur_token.code = T_ID;
7483218822Sdim      /* FALLTHRU */
7484218822Sdim
7485218822Sdim    /* e11  id
7486218822Sdim	    | constant  */
7487218822Sdim    case T_ID:
7488218822Sdim      if (!intel_parser.in_offset && intel_parser.is_mem <= 0)
748977311Sobrien	{
7490218822Sdim	  symbolS *symbolP;
749177311Sobrien
7492218822Sdim	  /* The identifier represents a memory reference only if it's not
7493218822Sdim	     preceded by an offset modifier and if it's not an equate.  */
7494218822Sdim	  symbolP = symbol_find(cur_token.str);
7495218822Sdim	  if (!symbolP || S_GET_SEGMENT(symbolP) != absolute_section)
7496218822Sdim	    intel_parser.is_mem = 1;
749777311Sobrien	}
7498218822Sdim	/* FALLTHRU */
749977311Sobrien
7500218822Sdim    case T_CONST:
7501218822Sdim    case '-':
7502218822Sdim    case '+':
7503218822Sdim      {
7504218822Sdim	char *save_str, sign = 0;
750577311Sobrien
7506218822Sdim	/* Allow constants that start with `+' or `-'.  */
7507218822Sdim	if (cur_token.code == '-' || cur_token.code == '+')
7508218822Sdim	  {
7509218822Sdim	    sign = cur_token.code;
7510218822Sdim	    intel_match_token (cur_token.code);
7511218822Sdim	    if (cur_token.code != T_CONST)
7512218822Sdim	      {
7513218822Sdim		as_bad (_("Syntax error: Expecting a constant, got `%s'"),
7514218822Sdim			cur_token.str);
7515218822Sdim		return 0;
7516218822Sdim	      }
7517218822Sdim	  }
751877311Sobrien
7519218822Sdim	save_str = (char *) xmalloc (strlen (cur_token.str) + 2);
7520218822Sdim	strcpy (save_str + !!sign, cur_token.str);
7521218822Sdim	if (sign)
7522218822Sdim	  *save_str = sign;
752377311Sobrien
7524218822Sdim	/* Get the next token to check for register scaling.  */
7525218822Sdim	intel_match_token (cur_token.code);
752677311Sobrien
7527218822Sdim	/* Check if this constant is a scaling factor for an
7528218822Sdim	   index register.  */
7529218822Sdim	if (cur_token.code == '*')
7530218822Sdim	  {
7531218822Sdim	    if (intel_match_token ('*') && cur_token.code == T_REG)
7532218822Sdim	      {
7533218822Sdim		const reg_entry *reg = cur_token.reg;
753477311Sobrien
7535218822Sdim		if (!intel_parser.in_bracket)
7536218822Sdim		  {
7537218822Sdim		    as_bad (_("Register scaling only allowed "
7538218822Sdim			      "in memory operands"));
7539218822Sdim		    return 0;
7540218822Sdim		  }
754177311Sobrien
7542218822Sdim		 /* Disallow things like [1*si].
7543218822Sdim		    sp and esp are invalid as index.  */
7544218822Sdim		if (reg->reg_type & Reg16)
7545218822Sdim		  reg = i386_regtab + REGNAM_AX + 4;
7546218822Sdim		else if (i.index_reg)
7547218822Sdim		  reg = i386_regtab + REGNAM_EAX + 4;
754877311Sobrien
7549218822Sdim		/* The constant is followed by `* reg', so it must be
7550218822Sdim		   a valid scale.  */
7551218822Sdim		i.index_reg = reg;
7552218822Sdim		i.types[this_operand] |= BaseIndex;
755377311Sobrien
7554218822Sdim		/* Set the scale after setting the register (otherwise,
7555218822Sdim		   i386_scale will complain)  */
7556218822Sdim		if (!i386_scale (save_str))
755777311Sobrien		  return 0;
7558218822Sdim		intel_match_token (T_REG);
755977311Sobrien
7560218822Sdim		/* Since registers are not part of the displacement
7561218822Sdim		   string, we may need to remove any preceding '+' from
7562218822Sdim		   the displacement string.  */
7563218822Sdim		if (*intel_parser.disp != '\0')
7564218822Sdim		  {
7565218822Sdim		    char *s = intel_parser.disp;
7566218822Sdim		    s += strlen (s) - 1;
7567218822Sdim		    if (*s == '+')
7568218822Sdim		      *s = '\0';
7569218822Sdim		  }
757077311Sobrien
7571218822Sdim		free (save_str);
757277311Sobrien
7573218822Sdim		return 1;
7574218822Sdim	      }
757577311Sobrien
7576218822Sdim	    /* The constant was not used for register scaling. Since we have
7577218822Sdim	       already consumed the token following `*' we now need to put it
7578218822Sdim	       back in the stream.  */
757977311Sobrien	    intel_putback_token ();
7580218822Sdim	  }
758177311Sobrien
7582218822Sdim	/* Add the constant to the displacement string.  */
7583218822Sdim	strcat (intel_parser.disp, save_str);
7584218822Sdim	free (save_str);
758577311Sobrien
7586218822Sdim	return 1;
7587218822Sdim      }
758877311Sobrien    }
758977311Sobrien
759077311Sobrien  as_bad (_("Unrecognized token '%s'"), cur_token.str);
759177311Sobrien  return 0;
759277311Sobrien}
759377311Sobrien
759477311Sobrien/* Match the given token against cur_token. If they match, read the next
759577311Sobrien   token from the operand string.  */
759677311Sobrienstatic int
7597218822Sdimintel_match_token (int code)
759877311Sobrien{
759977311Sobrien  if (cur_token.code == code)
760077311Sobrien    {
760177311Sobrien      intel_get_token ();
760277311Sobrien      return 1;
760377311Sobrien    }
760477311Sobrien  else
760577311Sobrien    {
7606218822Sdim      as_bad (_("Unexpected token `%s'"), cur_token.str);
760777311Sobrien      return 0;
760877311Sobrien    }
760977311Sobrien}
761077311Sobrien
761177311Sobrien/* Read a new token from intel_parser.op_string and store it in cur_token.  */
761277311Sobrienstatic void
7613218822Sdimintel_get_token (void)
761477311Sobrien{
761577311Sobrien  char *end_op;
761677311Sobrien  const reg_entry *reg;
761777311Sobrien  struct intel_token new_token;
761877311Sobrien
761977311Sobrien  new_token.code = T_NIL;
762077311Sobrien  new_token.reg = NULL;
762177311Sobrien  new_token.str = NULL;
762277311Sobrien
762377311Sobrien  /* Free the memory allocated to the previous token and move
762477311Sobrien     cur_token to prev_token.  */
762577311Sobrien  if (prev_token.str)
762677311Sobrien    free (prev_token.str);
762777311Sobrien
762877311Sobrien  prev_token = cur_token;
762977311Sobrien
763077311Sobrien  /* Skip whitespace.  */
763177311Sobrien  while (is_space_char (*intel_parser.op_string))
763277311Sobrien    intel_parser.op_string++;
763377311Sobrien
763477311Sobrien  /* Return an empty token if we find nothing else on the line.  */
763577311Sobrien  if (*intel_parser.op_string == '\0')
763677311Sobrien    {
763777311Sobrien      cur_token = new_token;
763877311Sobrien      return;
763977311Sobrien    }
764077311Sobrien
764177311Sobrien  /* The new token cannot be larger than the remainder of the operand
764277311Sobrien     string.  */
7643218822Sdim  new_token.str = (char *) xmalloc (strlen (intel_parser.op_string) + 1);
764477311Sobrien  new_token.str[0] = '\0';
764577311Sobrien
764677311Sobrien  if (strchr ("0123456789", *intel_parser.op_string))
764777311Sobrien    {
764877311Sobrien      char *p = new_token.str;
764977311Sobrien      char *q = intel_parser.op_string;
765077311Sobrien      new_token.code = T_CONST;
765177311Sobrien
765277311Sobrien      /* Allow any kind of identifier char to encompass floating point and
765377311Sobrien	 hexadecimal numbers.  */
765477311Sobrien      while (is_identifier_char (*q))
765577311Sobrien	*p++ = *q++;
765677311Sobrien      *p = '\0';
765777311Sobrien
765877311Sobrien      /* Recognize special symbol names [0-9][bf].  */
765977311Sobrien      if (strlen (intel_parser.op_string) == 2
766077311Sobrien	  && (intel_parser.op_string[1] == 'b'
766177311Sobrien	      || intel_parser.op_string[1] == 'f'))
766277311Sobrien	new_token.code = T_ID;
766377311Sobrien    }
766477311Sobrien
7665218822Sdim  else if ((reg = parse_register (intel_parser.op_string, &end_op)) != NULL)
766677311Sobrien    {
7667218822Sdim      size_t len = end_op - intel_parser.op_string;
766877311Sobrien
766977311Sobrien      new_token.code = T_REG;
767077311Sobrien      new_token.reg = reg;
767177311Sobrien
7672218822Sdim      memcpy (new_token.str, intel_parser.op_string, len);
7673218822Sdim      new_token.str[len] = '\0';
767477311Sobrien    }
767577311Sobrien
767677311Sobrien  else if (is_identifier_char (*intel_parser.op_string))
767777311Sobrien    {
767877311Sobrien      char *p = new_token.str;
767977311Sobrien      char *q = intel_parser.op_string;
768077311Sobrien
768177311Sobrien      /* A '.' or '$' followed by an identifier char is an identifier.
768277311Sobrien	 Otherwise, it's operator '.' followed by an expression.  */
768377311Sobrien      if ((*q == '.' || *q == '$') && !is_identifier_char (*(q + 1)))
768477311Sobrien	{
7685218822Sdim	  new_token.code = '.';
7686218822Sdim	  new_token.str[0] = '.';
768777311Sobrien	  new_token.str[1] = '\0';
768877311Sobrien	}
768977311Sobrien      else
769077311Sobrien	{
769177311Sobrien	  while (is_identifier_char (*q) || *q == '@')
769277311Sobrien	    *p++ = *q++;
769377311Sobrien	  *p = '\0';
769477311Sobrien
7695218822Sdim	  if (strcasecmp (new_token.str, "NOT") == 0)
7696218822Sdim	    new_token.code = '~';
7697218822Sdim
7698218822Sdim	  else if (strcasecmp (new_token.str, "MOD") == 0)
7699218822Sdim	    new_token.code = '%';
7700218822Sdim
7701218822Sdim	  else if (strcasecmp (new_token.str, "AND") == 0)
7702218822Sdim	    new_token.code = '&';
7703218822Sdim
7704218822Sdim	  else if (strcasecmp (new_token.str, "OR") == 0)
7705218822Sdim	    new_token.code = '|';
7706218822Sdim
7707218822Sdim	  else if (strcasecmp (new_token.str, "XOR") == 0)
7708218822Sdim	    new_token.code = '^';
7709218822Sdim
7710218822Sdim	  else if (strcasecmp (new_token.str, "SHL") == 0)
7711218822Sdim	    new_token.code = T_SHL;
7712218822Sdim
7713218822Sdim	  else if (strcasecmp (new_token.str, "SHR") == 0)
7714218822Sdim	    new_token.code = T_SHR;
7715218822Sdim
7716218822Sdim	  else if (strcasecmp (new_token.str, "BYTE") == 0)
771777311Sobrien	    new_token.code = T_BYTE;
771877311Sobrien
771977311Sobrien	  else if (strcasecmp (new_token.str, "WORD") == 0)
772077311Sobrien	    new_token.code = T_WORD;
772177311Sobrien
772277311Sobrien	  else if (strcasecmp (new_token.str, "DWORD") == 0)
772377311Sobrien	    new_token.code = T_DWORD;
772477311Sobrien
7725218822Sdim	  else if (strcasecmp (new_token.str, "FWORD") == 0)
7726218822Sdim	    new_token.code = T_FWORD;
7727218822Sdim
772877311Sobrien	  else if (strcasecmp (new_token.str, "QWORD") == 0)
772977311Sobrien	    new_token.code = T_QWORD;
773077311Sobrien
7731218822Sdim	  else if (strcasecmp (new_token.str, "TBYTE") == 0
7732218822Sdim		   /* XXX remove (gcc still uses it) */
7733218822Sdim		   || strcasecmp (new_token.str, "XWORD") == 0)
7734218822Sdim	    new_token.code = T_TBYTE;
773577311Sobrien
7736218822Sdim	  else if (strcasecmp (new_token.str, "XMMWORD") == 0
7737218822Sdim		   || strcasecmp (new_token.str, "OWORD") == 0)
7738218822Sdim	    new_token.code = T_XMMWORD;
7739218822Sdim
774077311Sobrien	  else if (strcasecmp (new_token.str, "PTR") == 0)
774177311Sobrien	    new_token.code = T_PTR;
774277311Sobrien
774377311Sobrien	  else if (strcasecmp (new_token.str, "SHORT") == 0)
774477311Sobrien	    new_token.code = T_SHORT;
774577311Sobrien
774677311Sobrien	  else if (strcasecmp (new_token.str, "OFFSET") == 0)
774777311Sobrien	    {
774877311Sobrien	      new_token.code = T_OFFSET;
774977311Sobrien
775077311Sobrien	      /* ??? This is not mentioned in the MASM grammar but gcc
775177311Sobrien		     makes use of it with -mintel-syntax.  OFFSET may be
775277311Sobrien		     followed by FLAT:  */
775377311Sobrien	      if (strncasecmp (q, " FLAT:", 6) == 0)
775477311Sobrien		strcat (new_token.str, " FLAT:");
775577311Sobrien	    }
775677311Sobrien
775777311Sobrien	  /* ??? This is not mentioned in the MASM grammar.  */
775877311Sobrien	  else if (strcasecmp (new_token.str, "FLAT") == 0)
7759218822Sdim	    {
7760218822Sdim	      new_token.code = T_OFFSET;
7761218822Sdim	      if (*q == ':')
7762218822Sdim		strcat (new_token.str, ":");
7763218822Sdim	      else
7764218822Sdim		as_bad (_("`:' expected"));
7765218822Sdim	    }
776677311Sobrien
776777311Sobrien	  else
776877311Sobrien	    new_token.code = T_ID;
776977311Sobrien	}
777077311Sobrien    }
777177311Sobrien
7772218822Sdim  else if (strchr ("+-/*%|&^:[]()~", *intel_parser.op_string))
7773218822Sdim    {
7774218822Sdim      new_token.code = *intel_parser.op_string;
7775218822Sdim      new_token.str[0] = *intel_parser.op_string;
7776218822Sdim      new_token.str[1] = '\0';
7777218822Sdim    }
7778218822Sdim
7779218822Sdim  else if (strchr ("<>", *intel_parser.op_string)
7780218822Sdim	   && *intel_parser.op_string == *(intel_parser.op_string + 1))
7781218822Sdim    {
7782218822Sdim      new_token.code = *intel_parser.op_string == '<' ? T_SHL : T_SHR;
7783218822Sdim      new_token.str[0] = *intel_parser.op_string;
7784218822Sdim      new_token.str[1] = *intel_parser.op_string;
7785218822Sdim      new_token.str[2] = '\0';
7786218822Sdim    }
7787218822Sdim
778877311Sobrien  else
7789218822Sdim    as_bad (_("Unrecognized token `%s'"), intel_parser.op_string);
779077311Sobrien
779177311Sobrien  intel_parser.op_string += strlen (new_token.str);
779277311Sobrien  cur_token = new_token;
779377311Sobrien}
779477311Sobrien
779577311Sobrien/* Put cur_token back into the token stream and make cur_token point to
779677311Sobrien   prev_token.  */
779777311Sobrienstatic void
7798218822Sdimintel_putback_token (void)
779977311Sobrien{
7800218822Sdim  if (cur_token.code != T_NIL)
7801218822Sdim    {
7802218822Sdim      intel_parser.op_string -= strlen (cur_token.str);
7803218822Sdim      free (cur_token.str);
7804218822Sdim    }
780577311Sobrien  cur_token = prev_token;
780677311Sobrien
780777311Sobrien  /* Forget prev_token.  */
780877311Sobrien  prev_token.code = T_NIL;
780977311Sobrien  prev_token.reg = NULL;
781077311Sobrien  prev_token.str = NULL;
781177311Sobrien}
7812130570Sobrien
7813130570Sobrienint
7814218822Sdimtc_x86_regname_to_dw2regnum (char *regname)
7815130570Sobrien{
7816130570Sobrien  unsigned int regnum;
7817130570Sobrien  unsigned int regnames_count;
7818218822Sdim  static const char *const regnames_32[] =
7819130570Sobrien    {
7820130570Sobrien      "eax", "ecx", "edx", "ebx",
7821130570Sobrien      "esp", "ebp", "esi", "edi",
7822218822Sdim      "eip", "eflags", NULL,
7823218822Sdim      "st0", "st1", "st2", "st3",
7824218822Sdim      "st4", "st5", "st6", "st7",
7825218822Sdim      NULL, NULL,
7826218822Sdim      "xmm0", "xmm1", "xmm2", "xmm3",
7827218822Sdim      "xmm4", "xmm5", "xmm6", "xmm7",
7828218822Sdim      "mm0", "mm1", "mm2", "mm3",
7829218822Sdim      "mm4", "mm5", "mm6", "mm7",
7830218822Sdim      "fcw", "fsw", "mxcsr",
7831218822Sdim      "es", "cs", "ss", "ds", "fs", "gs", NULL, NULL,
7832218822Sdim      "tr", "ldtr"
7833130570Sobrien    };
7834218822Sdim  static const char *const regnames_64[] =
7835130570Sobrien    {
7836218822Sdim      "rax", "rdx", "rcx", "rbx",
7837218822Sdim      "rsi", "rdi", "rbp", "rsp",
7838218822Sdim      "r8",  "r9",  "r10", "r11",
7839130570Sobrien      "r12", "r13", "r14", "r15",
7840218822Sdim      "rip",
7841218822Sdim      "xmm0",  "xmm1",  "xmm2",  "xmm3",
7842218822Sdim      "xmm4",  "xmm5",  "xmm6",  "xmm7",
7843218822Sdim      "xmm8",  "xmm9",  "xmm10", "xmm11",
7844218822Sdim      "xmm12", "xmm13", "xmm14", "xmm15",
7845218822Sdim      "st0", "st1", "st2", "st3",
7846218822Sdim      "st4", "st5", "st6", "st7",
7847218822Sdim      "mm0", "mm1", "mm2", "mm3",
7848218822Sdim      "mm4", "mm5", "mm6", "mm7",
7849218822Sdim      "rflags",
7850218822Sdim      "es", "cs", "ss", "ds", "fs", "gs", NULL, NULL,
7851218822Sdim      "fs.base", "gs.base", NULL, NULL,
7852218822Sdim      "tr", "ldtr",
7853218822Sdim      "mxcsr", "fcw", "fsw"
7854130570Sobrien    };
7855218822Sdim  const char *const *regnames;
7856130570Sobrien
7857130570Sobrien  if (flag_code == CODE_64BIT)
7858130570Sobrien    {
7859130570Sobrien      regnames = regnames_64;
7860130570Sobrien      regnames_count = ARRAY_SIZE (regnames_64);
7861130570Sobrien    }
7862130570Sobrien  else
7863130570Sobrien    {
7864130570Sobrien      regnames = regnames_32;
7865130570Sobrien      regnames_count = ARRAY_SIZE (regnames_32);
7866130570Sobrien    }
7867130570Sobrien
7868130570Sobrien  for (regnum = 0; regnum < regnames_count; regnum++)
7869218822Sdim    if (regnames[regnum] != NULL
7870218822Sdim	&& strcmp (regname, regnames[regnum]) == 0)
7871130570Sobrien      return regnum;
7872130570Sobrien
7873130570Sobrien  return -1;
7874130570Sobrien}
7875130570Sobrien
7876130570Sobrienvoid
7877130570Sobrientc_x86_frame_initial_instructions (void)
7878130570Sobrien{
7879130570Sobrien  static unsigned int sp_regno;
7880130570Sobrien
7881130570Sobrien  if (!sp_regno)
7882130570Sobrien    sp_regno = tc_x86_regname_to_dw2regnum (flag_code == CODE_64BIT
7883130570Sobrien					    ? "rsp" : "esp");
7884130570Sobrien
7885130570Sobrien  cfi_add_CFA_def_cfa (sp_regno, -x86_cie_data_alignment);
7886130570Sobrien  cfi_add_CFA_offset (x86_dwarf2_return_column, x86_cie_data_alignment);
7887130570Sobrien}
7888218822Sdim
7889218822Sdimint
7890218822Sdimi386_elf_section_type (const char *str, size_t len)
7891218822Sdim{
7892218822Sdim  if (flag_code == CODE_64BIT
7893218822Sdim      && len == sizeof ("unwind") - 1
7894218822Sdim      && strncmp (str, "unwind", 6) == 0)
7895218822Sdim    return SHT_X86_64_UNWIND;
7896218822Sdim
7897218822Sdim  return -1;
7898218822Sdim}
7899218822Sdim
7900218822Sdim#ifdef TE_PE
7901218822Sdimvoid
7902218822Sdimtc_pe_dwarf2_emit_offset (symbolS *symbol, unsigned int size)
7903218822Sdim{
7904218822Sdim  expressionS expr;
7905218822Sdim
7906218822Sdim  expr.X_op = O_secrel;
7907218822Sdim  expr.X_add_symbol = symbol;
7908218822Sdim  expr.X_add_number = 0;
7909218822Sdim  emit_expr (&expr, size);
7910218822Sdim}
7911218822Sdim#endif
7912218822Sdim
7913218822Sdim#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
7914218822Sdim/* For ELF on x86-64, add support for SHF_X86_64_LARGE.  */
7915218822Sdim
7916218822Sdimint
7917218822Sdimx86_64_section_letter (int letter, char **ptr_msg)
7918218822Sdim{
7919218822Sdim  if (flag_code == CODE_64BIT)
7920218822Sdim    {
7921218822Sdim      if (letter == 'l')
7922218822Sdim	return SHF_X86_64_LARGE;
7923218822Sdim
7924218822Sdim      *ptr_msg = _("Bad .section directive: want a,l,w,x,M,S,G,T in string");
7925218822Sdim    }
7926218822Sdim  else
7927218822Sdim    *ptr_msg = _("Bad .section directive: want a,w,x,M,S,G,T in string");
7928218822Sdim  return -1;
7929218822Sdim}
7930218822Sdim
7931218822Sdimint
7932218822Sdimx86_64_section_word (char *str, size_t len)
7933218822Sdim{
7934218822Sdim  if (len == 5 && flag_code == CODE_64BIT && CONST_STRNEQ (str, "large"))
7935218822Sdim    return SHF_X86_64_LARGE;
7936218822Sdim
7937218822Sdim  return -1;
7938218822Sdim}
7939218822Sdim
7940218822Sdimstatic void
7941218822Sdimhandle_large_common (int small ATTRIBUTE_UNUSED)
7942218822Sdim{
7943218822Sdim  if (flag_code != CODE_64BIT)
7944218822Sdim    {
7945218822Sdim      s_comm_internal (0, elf_common_parse);
7946218822Sdim      as_warn (_(".largecomm supported only in 64bit mode, producing .comm"));
7947218822Sdim    }
7948218822Sdim  else
7949218822Sdim    {
7950218822Sdim      static segT lbss_section;
7951218822Sdim      asection *saved_com_section_ptr = elf_com_section_ptr;
7952218822Sdim      asection *saved_bss_section = bss_section;
7953218822Sdim
7954218822Sdim      if (lbss_section == NULL)
7955218822Sdim	{
7956218822Sdim	  flagword applicable;
7957218822Sdim	  segT seg = now_seg;
7958218822Sdim	  subsegT subseg = now_subseg;
7959218822Sdim
7960218822Sdim	  /* The .lbss section is for local .largecomm symbols.  */
7961218822Sdim	  lbss_section = subseg_new (".lbss", 0);
7962218822Sdim	  applicable = bfd_applicable_section_flags (stdoutput);
7963218822Sdim	  bfd_set_section_flags (stdoutput, lbss_section,
7964218822Sdim				 applicable & SEC_ALLOC);
7965218822Sdim	  seg_info (lbss_section)->bss = 1;
7966218822Sdim
7967218822Sdim	  subseg_set (seg, subseg);
7968218822Sdim	}
7969218822Sdim
7970218822Sdim      elf_com_section_ptr = &_bfd_elf_large_com_section;
7971218822Sdim      bss_section = lbss_section;
7972218822Sdim
7973218822Sdim      s_comm_internal (0, elf_common_parse);
7974218822Sdim
7975218822Sdim      elf_com_section_ptr = saved_com_section_ptr;
7976218822Sdim      bss_section = saved_bss_section;
7977218822Sdim    }
7978218822Sdim}
7979218822Sdim#endif /* OBJ_ELF || OBJ_MAYBE_ELF */
7980