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