xref: /csrg-svn/contrib/gas-1.38/config/i386.c (revision 49402)
1*49402Sbostic /*-
2*49402Sbostic  * This code is derived from software copyrighted by the Free Software
3*49402Sbostic  * Foundation.
4*49402Sbostic  *
5*49402Sbostic  * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
6*49402Sbostic  */
747460Sdonn 
8*49402Sbostic #ifndef lint
9*49402Sbostic static char sccsid[] = "@(#)i386.c	6.4 (Berkeley) 05/08/91";
10*49402Sbostic #endif /* not lint */
1147460Sdonn 
1247270Sdonn /* i386.c -- Assemble code for the Intel 80386
1347270Sdonn    Copyright (C) 1989, Free Software Foundation.
1447270Sdonn 
1547270Sdonn This file is part of GAS, the GNU Assembler.
1647270Sdonn 
1747270Sdonn GAS is free software; you can redistribute it and/or modify
1847270Sdonn it under the terms of the GNU General Public License as published by
1947270Sdonn the Free Software Foundation; either version 1, or (at your option)
2047270Sdonn any later version.
2147270Sdonn 
2247270Sdonn GAS is distributed in the hope that it will be useful,
2347270Sdonn but WITHOUT ANY WARRANTY; without even the implied warranty of
2447270Sdonn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2547270Sdonn GNU General Public License for more details.
2647270Sdonn 
2747270Sdonn You should have received a copy of the GNU General Public License
2847270Sdonn along with GAS; see the file COPYING.  If not, write to
2947270Sdonn the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
3047270Sdonn 
3147270Sdonn /*
3247270Sdonn   Intel 80386 machine specific gas.
3347270Sdonn   Written by Eliot Dresselhaus (eliot@mgm.mit.edu).
3447270Sdonn   Bugs & suggestions are completely welcome.  This is free software.
3547270Sdonn   Please help us make it better.
3647270Sdonn */
3747270Sdonn 
3847270Sdonn #include <stdio.h>
3947270Sdonn #include <varargs.h>
4047270Sdonn #include <ctype.h>
4147270Sdonn 
4247270Sdonn #ifdef __GNUC__
4347270Sdonn #define alloca __builtin_alloca
4447270Sdonn #else
4547270Sdonn extern char *alloca();
4647270Sdonn #endif
4747270Sdonn #ifdef USG
4847270Sdonn #define index strchr
4947270Sdonn #endif
5047270Sdonn 
5147270Sdonn #include "as.h"
5247270Sdonn #include "read.h"
5347270Sdonn #include "flonum.h"
5447270Sdonn #include "obstack.h"
5547270Sdonn #include "frags.h"
5647270Sdonn #include "struc-symbol.h"
5747270Sdonn #include "expr.h"
5847270Sdonn #include "symbols.h"
5947270Sdonn #include "hash.h"
6047270Sdonn #include "md.h"
6147270Sdonn #include "i386.h"
6247270Sdonn #include "i386-opcode.h"
6347270Sdonn 
6447270Sdonn long omagic = OMAGIC;
6547270Sdonn char FLT_CHARS[] = "fFdDxX";
6647270Sdonn char EXP_CHARS[] = "eE";
6747270Sdonn char line_comment_chars[] = "#";
6847459Sdonn char comment_chars[] = "#";
6947270Sdonn 
7047270Sdonn /* tables for lexical analysis */
7147270Sdonn static char opcode_chars[256];
7247270Sdonn static char register_chars[256];
7347270Sdonn static char operand_chars[256];
7447270Sdonn static char space_chars[256];
7547270Sdonn static char identifier_chars[256];
7647270Sdonn static char digit_chars[256];
7747270Sdonn 
7847270Sdonn /* lexical macros */
7947270Sdonn #define is_opcode_char(x) (opcode_chars[(unsigned char) x])
8047270Sdonn #define is_operand_char(x) (operand_chars[(unsigned char) x])
8147270Sdonn #define is_register_char(x) (register_chars[(unsigned char) x])
8247270Sdonn #define is_space_char(x) (space_chars[(unsigned char) x])
8347270Sdonn #define is_identifier_char(x) (identifier_chars[(unsigned char) x])
8447270Sdonn #define is_digit_char(x) (digit_chars[(unsigned char) x])
8547270Sdonn 
8647270Sdonn /* put here all non-digit non-letter charcters that may occur in an operand */
8747270Sdonn static char operand_special_chars[] = "%$-+(,)*._~/<>|&^!:";
8847270Sdonn 
8947270Sdonn static char *ordinal_names[] = { "first", "second", "third" };	/* for printfs */
9047270Sdonn 
9147270Sdonn /* md_assemble() always leaves the strings it's passed unaltered.  To
9247270Sdonn    effect this we maintain a stack of saved characters that we've smashed
9347270Sdonn    with '\0's (indicating end of strings for various sub-fields of the
9447270Sdonn    assembler instruction). */
9547270Sdonn static char save_stack[32];
9647270Sdonn static char *save_stack_p;	/* stack pointer */
9747270Sdonn #define END_STRING_AND_SAVE(s)      *save_stack_p++ = *s; *s = '\0'
9847270Sdonn #define RESTORE_END_STRING(s)       *s = *--save_stack_p
9947270Sdonn 
10047270Sdonn /* The instruction we're assembling. */
10147270Sdonn static i386_insn i;
10247270Sdonn 
10347270Sdonn /* Per instruction expressionS buffers: 2 displacements & 2 immediate max. */
10447270Sdonn static expressionS disp_expressions[2], im_expressions[2];
10547270Sdonn 
10647270Sdonn /* pointers to ebp & esp entries in reg_hash hash table */
10747270Sdonn static reg_entry *ebp, *esp;
10847270Sdonn 
10947270Sdonn static int this_operand;	/* current operand we are working on */
11047270Sdonn 
11147270Sdonn /*
11247270Sdonn Interface to relax_segment.
11347270Sdonn There are 2 relax states for 386 jump insns: one for conditional & one
11447270Sdonn for unconditional jumps.  This is because the these two types of jumps
11547270Sdonn add different sizes to frags when we're figuring out what sort of jump
11647270Sdonn to choose to reach a given label.  */
11747270Sdonn 
11847270Sdonn /* types */
11947270Sdonn #define COND_JUMP 1		/* conditional jump */
12047270Sdonn #define UNCOND_JUMP 2		/* unconditional jump */
12147270Sdonn /* sizes */
12247270Sdonn #define BYTE 0
12347270Sdonn #define WORD 1
12447270Sdonn #define DWORD 2
12547270Sdonn #define UNKNOWN_SIZE 3
12647270Sdonn 
12747270Sdonn #define ENCODE_RELAX_STATE(type,size) ((type<<2) | (size))
12847270Sdonn #define SIZE_FROM_RELAX_STATE(s) \
12947270Sdonn   ( (((s) & 0x3) == BYTE ? 1 : (((s) & 0x3) == WORD ? 2 : 4)) )
13047270Sdonn 
13147270Sdonn const relax_typeS md_relax_table[] = {
13247270Sdonn /*
13347270Sdonn   The fields are:
13447270Sdonn    1) most positive reach of this state,
13547270Sdonn    2) most negative reach of this state,
13647270Sdonn    3) how many bytes this mode will add to the size of the current frag
13747270Sdonn    4) which index into the table to try if we can't fit into this one.
13847270Sdonn */
13947270Sdonn   {1, 1, 0, 0},
14047270Sdonn   {1, 1, 0, 0},
14147270Sdonn   {1, 1, 0, 0},
14247270Sdonn   {1, 1, 0, 0},
14347270Sdonn 
14447270Sdonn   /* For now we don't use word displacement jumps:  they may be
14547270Sdonn      untrustworthy. */
14647270Sdonn   {127+1, -128+1, 0, ENCODE_RELAX_STATE(COND_JUMP,DWORD) },
14747270Sdonn   /* word conditionals add 3 bytes to frag:
14847270Sdonn          2 opcode prefix; 1 displacement bytes */
14947270Sdonn   {32767+2, -32768+2, 3, ENCODE_RELAX_STATE(COND_JUMP,DWORD) },
15047270Sdonn   /* dword conditionals adds 4 bytes to frag:
15147270Sdonn          1 opcode prefix; 3 displacement bytes */
15247270Sdonn   {0, 0, 4, 0},
15347270Sdonn   {1, 1, 0, 0},
15447270Sdonn 
15547270Sdonn   {127+1, -128+1, 0, ENCODE_RELAX_STATE(UNCOND_JUMP,DWORD) },
15647270Sdonn   /* word jmp adds 2 bytes to frag:
15747270Sdonn          1 opcode prefix; 1 displacement bytes */
15847270Sdonn   {32767+2, -32768+2, 2, ENCODE_RELAX_STATE(UNCOND_JUMP,DWORD) },
15947270Sdonn   /* dword jmp adds 3 bytes to frag:
16047270Sdonn          0 opcode prefix; 3 displacement bytes */
16147270Sdonn   {0, 0, 3, 0},
16247270Sdonn   {1, 1, 0, 0},
16347270Sdonn 
16447270Sdonn };
16547270Sdonn 
16647270Sdonn void float_cons (), cons ();
16747270Sdonn 
16847270Sdonn /* Ignore certain directives generated by gcc. This probably should
16947270Sdonn    not be here. */
dummy()17047270Sdonn void dummy ()
17147270Sdonn {
17247270Sdonn   while (*input_line_pointer && *input_line_pointer != '\n')
17347270Sdonn     input_line_pointer++;
17447270Sdonn }
17547270Sdonn 
17647270Sdonn const pseudo_typeS md_pseudo_table[] = {
17747270Sdonn 	{ "ffloat",	float_cons,	'f' },
17847270Sdonn 	{ "dfloat",	float_cons,	'd' },
17947270Sdonn 	{ "tfloat",	float_cons,	'x' },
18047270Sdonn 	{ "value",      cons,           2 },
18147270Sdonn 	{ "ident",      dummy,          0   }, /* ignore these directives */
18247270Sdonn 	{ "def",        dummy,          0   },
18347270Sdonn 	{ "optim",	dummy,		0   }, /* For sun386i cc */
18447270Sdonn 	{ "version",    dummy,          0   },
18547270Sdonn 	{ "ln",    dummy,          0   },
18647270Sdonn 	{ 0, 0, 0 }
18747270Sdonn };
18847270Sdonn 
18947270Sdonn /* for interface with expression () */
19047270Sdonn extern char * input_line_pointer;
19147270Sdonn char * index ();
19247270Sdonn 
19347270Sdonn char * output_invalid ();
19447270Sdonn reg_entry * parse_register ();
19547270Sdonn 
19647270Sdonn /* obstack for constructing various things in md_begin */
19747270Sdonn struct obstack o;
19847270Sdonn 
19947270Sdonn /* hash table for opcode lookup */
20047270Sdonn static struct hash_control *op_hash = (struct hash_control *) 0;
20147270Sdonn /* hash table for register lookup */
20247270Sdonn static struct hash_control *reg_hash = (struct hash_control *) 0;
20347270Sdonn /* hash table for prefix lookup */
20447270Sdonn static struct hash_control *prefix_hash = (struct hash_control *) 0;
20547270Sdonn 
20647270Sdonn 
md_begin()20747270Sdonn void md_begin ()
20847270Sdonn {
20947270Sdonn   char * hash_err;
21047270Sdonn 
21147270Sdonn   obstack_begin (&o,4096);
21247270Sdonn 
21347270Sdonn   /* initialize op_hash hash table */
21447270Sdonn   op_hash = hash_new();		/* xmalloc handles error */
21547270Sdonn 
21647270Sdonn   {
21747270Sdonn     register template *optab;
21847270Sdonn     register templates *core_optab;
21947270Sdonn     char *prev_name;
22047270Sdonn 
22147270Sdonn     optab = i386_optab;		/* setup for loop */
22247270Sdonn     prev_name = optab->name;
22347270Sdonn     obstack_grow (&o, optab, sizeof(template));
22447270Sdonn     core_optab = (templates *) xmalloc (sizeof (templates));
22547270Sdonn 
22647270Sdonn     for (optab++; optab < i386_optab_end; optab++) {
22747270Sdonn       if (! strcmp (optab->name, prev_name)) {
22847270Sdonn 	/* same name as before --> append to current template list */
22947270Sdonn 	obstack_grow (&o, optab, sizeof(template));
23047270Sdonn       } else {
23147270Sdonn 	/* different name --> ship out current template list;
23247270Sdonn 	   add to hash table; & begin anew */
23347270Sdonn 	/* Note: end must be set before start! since obstack_next_free changes
23447270Sdonn 	   upon opstack_finish */
23547270Sdonn 	core_optab->end = (template *) obstack_next_free(&o);
23647270Sdonn 	core_optab->start = (template *) obstack_finish(&o);
23747270Sdonn 	hash_err = hash_insert (op_hash, prev_name, (char *) core_optab);
23847270Sdonn 	if (hash_err && *hash_err) {
23947270Sdonn 	hash_error:
24047270Sdonn 	  as_fatal("Internal Error:  Can't hash %s: %s",prev_name, hash_err);
24147270Sdonn 	}
24247270Sdonn 	prev_name = optab->name;
24347270Sdonn 	core_optab = (templates *) xmalloc (sizeof(templates));
24447270Sdonn 	obstack_grow (&o, optab, sizeof(template));
24547270Sdonn       }
24647270Sdonn     }
24747270Sdonn   }
24847270Sdonn 
24947270Sdonn   /* initialize reg_hash hash table */
25047270Sdonn   reg_hash = hash_new();
25147270Sdonn   {
25247270Sdonn     register reg_entry *regtab;
25347270Sdonn 
25447270Sdonn     for (regtab = i386_regtab; regtab < i386_regtab_end; regtab++) {
25547270Sdonn       hash_err = hash_insert (reg_hash, regtab->reg_name, regtab);
25647270Sdonn       if (hash_err && *hash_err) goto hash_error;
25747270Sdonn     }
25847270Sdonn   }
25947270Sdonn 
26047270Sdonn   esp = (reg_entry *) hash_find (reg_hash, "esp");
26147270Sdonn   ebp = (reg_entry *) hash_find (reg_hash, "ebp");
26247270Sdonn 
26347270Sdonn   /* initialize reg_hash hash table */
26447270Sdonn   prefix_hash = hash_new();
26547270Sdonn   {
26647270Sdonn     register prefix_entry *prefixtab;
26747270Sdonn 
26847270Sdonn     for (prefixtab = i386_prefixtab;
26947270Sdonn 	 prefixtab < i386_prefixtab_end; prefixtab++) {
27047270Sdonn       hash_err = hash_insert (prefix_hash, prefixtab->prefix_name, prefixtab);
27147270Sdonn       if (hash_err && *hash_err) goto hash_error;
27247270Sdonn     }
27347270Sdonn   }
27447270Sdonn 
27547270Sdonn   /* fill in lexical tables:  opcode_chars, operand_chars, space_chars */
27647270Sdonn   {
27747270Sdonn     register unsigned int c;
27847270Sdonn 
27947270Sdonn     bzero (opcode_chars, sizeof(opcode_chars));
28047270Sdonn     bzero (operand_chars, sizeof(operand_chars));
28147270Sdonn     bzero (space_chars, sizeof(space_chars));
28247270Sdonn     bzero (identifier_chars, sizeof(identifier_chars));
28347270Sdonn     bzero (digit_chars, sizeof(digit_chars));
28447270Sdonn 
28547270Sdonn     for (c = 0; c < 256; c++) {
28647270Sdonn       if (islower(c) || isdigit(c)) {
28747270Sdonn 	opcode_chars[c] = c;
28847270Sdonn 	register_chars[c] = c;
28947270Sdonn       } else if (isupper(c)) {
29047270Sdonn 	opcode_chars[c] = tolower(c);
29147270Sdonn 	register_chars[c] = opcode_chars[c];
29247270Sdonn       } else if (c == PREFIX_SEPERATOR) {
29347270Sdonn 	opcode_chars[c] = c;
29447270Sdonn       } else if (c == ')' || c == '(') {
29547270Sdonn 	register_chars[c] = c;
29647270Sdonn       }
29747270Sdonn 
29847270Sdonn       if (isupper(c) || islower(c) || isdigit(c))
29947270Sdonn 	operand_chars[c] = c;
30047270Sdonn       else if (c && index(operand_special_chars, c))
30147270Sdonn 	  operand_chars[c] = c;
30247270Sdonn 
30347270Sdonn       if (isdigit(c) || c == '-') digit_chars[c] = c;
30447270Sdonn 
30547270Sdonn       if (isalpha(c) || c == '_' || c == '.' || isdigit(c))
30647270Sdonn 	identifier_chars[c] = c;
30747270Sdonn 
30847270Sdonn       if (c == ' ' || c == '\t') space_chars[c] = c;
30947270Sdonn     }
31047270Sdonn   }
31147270Sdonn }
31247270Sdonn 
md_end()31347270Sdonn void md_end() {}		/* not much to do here. */
31447270Sdonn 
31547270Sdonn 
31647270Sdonn #ifdef DEBUG386
31747270Sdonn 
31847270Sdonn /* debugging routines for md_assemble */
31947270Sdonn static void pi (), pte (), pt (), pe (), ps ();
32047270Sdonn 
pi(line,x)32147270Sdonn static void pi (line, x)
32247270Sdonn      char * line;
32347270Sdonn      i386_insn *x;
32447270Sdonn {
32547270Sdonn   register template *p;
32647270Sdonn   int i;
32747270Sdonn 
32847270Sdonn   fprintf (stdout, "%s: template ", line);
32947270Sdonn   pte (&x->tm);
33047270Sdonn   fprintf (stdout, "  modrm:  mode %x  reg %x  reg/mem %x",
33147270Sdonn 	   x->rm.mode, x->rm.reg, x->rm.regmem);
33247270Sdonn   fprintf (stdout, " base %x  index %x  scale %x\n",
33347270Sdonn 	   x->bi.base, x->bi.index, x->bi.scale);
33447270Sdonn   for (i = 0; i < x->operands; i++) {
33547270Sdonn     fprintf (stdout, "    #%d:  ", i+1);
33647270Sdonn     pt (x->types[i]);
33747270Sdonn     fprintf (stdout, "\n");
33847270Sdonn     if (x->types[i] & Reg) fprintf (stdout, "%s\n", x->regs[i]->reg_name);
33947270Sdonn     if (x->types[i] & Imm) pe (x->imms[i]);
34047270Sdonn     if (x->types[i] & (Disp|Abs)) pe (x->disps[i]);
34147270Sdonn   }
34247270Sdonn }
34347270Sdonn 
pte(t)34447270Sdonn static void pte (t)
34547270Sdonn      template *t;
34647270Sdonn {
34747270Sdonn   int i;
34847270Sdonn   fprintf (stdout, " %d operands ", t->operands);
34947270Sdonn   fprintf (stdout, "opcode %x ",
35047270Sdonn 	   t->base_opcode);
35147270Sdonn   if (t->extension_opcode != None)
35247270Sdonn     fprintf (stdout, "ext %x ", t->extension_opcode);
35347270Sdonn   if (t->opcode_modifier&D)
35447270Sdonn     fprintf (stdout, "D");
35547270Sdonn   if (t->opcode_modifier&W)
35647270Sdonn     fprintf (stdout, "W");
35747270Sdonn   fprintf (stdout, "\n");
35847270Sdonn   for (i = 0; i < t->operands; i++) {
35947270Sdonn     fprintf (stdout, "    #%d type ", i+1);
36047270Sdonn     pt (t->operand_types[i]);
36147270Sdonn     fprintf (stdout, "\n");
36247270Sdonn   }
36347270Sdonn }
36447270Sdonn 
36547270Sdonn char *seg_names[] = {
36647270Sdonn "SEG_ABSOLUTE", "SEG_TEXT", "SEG_DATA", "SEG_BSS", "SEG_UNKNOWN",
36747270Sdonn "SEG_NONE", "SEG_PASS1", "SEG_GOOF", "SEG_BIG", "SEG_DIFFERENCE" };
36847270Sdonn 
pe(e)36947270Sdonn static void pe (e)
37047270Sdonn      expressionS *e;
37147270Sdonn {
37247270Sdonn   fprintf (stdout, "    segment       %s\n", seg_names[(int) e->X_seg]);
37347270Sdonn   fprintf (stdout, "    add_number    %d (%x)\n",
37447270Sdonn 	   e->X_add_number, e->X_add_number);
37547270Sdonn   if (e->X_add_symbol) {
37647270Sdonn     fprintf (stdout, "    add_symbol    ");
37747270Sdonn     ps (e->X_add_symbol);
37847270Sdonn     fprintf (stdout, "\n");
37947270Sdonn   }
38047270Sdonn   if (e->X_subtract_symbol) {
38147270Sdonn     fprintf (stdout, "    sub_symbol    ");
38247270Sdonn     ps (e->X_subtract_symbol);
38347270Sdonn     fprintf (stdout, "\n");
38447270Sdonn   }
38547270Sdonn }
38647270Sdonn 
38747270Sdonn #define SYMBOL_TYPE(t) \
38847270Sdonn   (((t&N_TYPE) == N_UNDF) ? "UNDEFINED" : \
38947270Sdonn    (((t&N_TYPE) == N_ABS) ? "ABSOLUTE" : \
39047270Sdonn     (((t&N_TYPE) == N_TEXT) ? "TEXT" : \
39147270Sdonn      (((t&N_TYPE) == N_DATA) ? "DATA" : \
39247270Sdonn       (((t&N_TYPE) == N_BSS) ? "BSS" : "Bad n_type!")))))
39347270Sdonn 
ps(s)39447270Sdonn static void ps (s)
39547270Sdonn      symbolS *s;
39647270Sdonn {
39747270Sdonn   fprintf (stdout, "%s type %s%s",
39847270Sdonn 	   s->sy_nlist.n_un.n_name,
39947270Sdonn 	   (s->sy_nlist.n_type&N_EXT) ? "EXTERNAL " : "",
40047270Sdonn 	   SYMBOL_TYPE (s->sy_nlist.n_type));
40147270Sdonn }
40247270Sdonn 
40347270Sdonn struct type_name {
40447270Sdonn   uint mask;
40547270Sdonn   char *tname;
40647270Sdonn } type_names[] = {
40747270Sdonn   { Reg8, "r8" }, { Reg16, "r16" }, { Reg32, "r32" }, { Imm8, "i8" },
40847270Sdonn   { Imm8S, "i8s" },
40947270Sdonn   { Imm16, "i16" }, { Imm32, "i32" }, { Mem8, "Mem8"}, { Mem16, "Mem16"},
41047270Sdonn   { Mem32, "Mem32"}, { BaseIndex, "BaseIndex" },
41147270Sdonn   { Abs8, "Abs8" }, { Abs16, "Abs16" }, { Abs32, "Abs32" },
41247270Sdonn   { Disp8, "d8" }, { Disp16, "d16" },
41347270Sdonn   { Disp32, "d32" }, { SReg2, "SReg2" }, { SReg3, "SReg3" }, { Acc, "Acc" },
41447270Sdonn   { InOutPortReg, "InOutPortReg" }, { ShiftCount, "ShiftCount" },
41547270Sdonn   { Imm1, "i1" }, { Control, "control reg" }, {Test, "test reg"},
41647270Sdonn   { FloatReg, "FReg"}, {FloatAcc, "FAcc"},
41747270Sdonn   { JumpAbsolute, "Jump Absolute"},
41847270Sdonn   { 0, "" }
41947270Sdonn };
42047270Sdonn 
pt(t)42147270Sdonn static void pt (t)
42247270Sdonn      uint t;
42347270Sdonn {
42447270Sdonn   register struct type_name *ty;
42547270Sdonn 
42647270Sdonn   if (t == Unknown) {
42747270Sdonn     fprintf (stdout, "Unknown");
42847270Sdonn   } else {
42947270Sdonn     for (ty = type_names; ty->mask; ty++)
43047270Sdonn       if (t & ty->mask) fprintf (stdout, "%s, ", ty->tname);
43147270Sdonn   }
43247270Sdonn   fflush (stdout);
43347270Sdonn }
43447270Sdonn 
43547270Sdonn #endif /* DEBUG386 */
43647270Sdonn 
43747270Sdonn /*
43847270Sdonn   This is the guts of the machine-dependent assembler.  LINE points to a
43947270Sdonn   machine dependent instruction.  This funciton is supposed to emit
44047270Sdonn   the frags/bytes it assembles to.
44147270Sdonn  */
md_assemble(line)44247270Sdonn void md_assemble (line)
44347270Sdonn      char *line;
44447270Sdonn {
44547270Sdonn   /* Holds temlate once we've found it. */
44647270Sdonn   register template * t;
44747270Sdonn 
44847270Sdonn   /* Possible templates for current insn */
44947270Sdonn   templates *current_templates = (templates *) 0;
45047270Sdonn 
45147270Sdonn   /* Initialize globals. */
45247270Sdonn   bzero (&i, sizeof(i));
45347270Sdonn   bzero (disp_expressions, sizeof(disp_expressions));
45447270Sdonn   bzero (im_expressions, sizeof(im_expressions));
45547270Sdonn   save_stack_p = save_stack;	/* reset stack pointer */
45647270Sdonn 
45747270Sdonn   /* Fist parse an opcode & call i386_operand for the operands.
45847270Sdonn      We assume that the scrubber has arranged it so that line[0] is the valid
45947270Sdonn      start of a (possibly prefixed) opcode. */
46047270Sdonn   {
46147270Sdonn     register char *l = line;		/* Fast place to put LINE. */
46247270Sdonn 
46347270Sdonn     /* TRUE if operand is pending after ','. */
46447270Sdonn     uint expecting_operand = 0;
46547270Sdonn     /* TRUE if we found a prefix only acceptable with string insns. */
46647270Sdonn     uint expecting_string_instruction = 0;
46747270Sdonn     /* Non-zero if operand parens not balenced. */
46847270Sdonn     uint paren_not_balenced;
46947270Sdonn     char * token_start = l;
47047270Sdonn 
47147270Sdonn     while (! is_space_char(*l) && *l != END_OF_INSN) {
47247270Sdonn       if (! is_opcode_char(*l)) {
47347270Sdonn 	as_bad ("invalid character %s in opcode", output_invalid(*l));
47447270Sdonn 	return;
47547270Sdonn       } else if (*l != PREFIX_SEPERATOR) {
47647270Sdonn 	*l = opcode_chars[(unsigned char) *l];	/* fold case of opcodes */
47747270Sdonn 	l++;
47847270Sdonn       } else {      /* this opcode's got a prefix */
47947270Sdonn 	register int q;
48047270Sdonn 	register prefix_entry * prefix;
48147270Sdonn 
48247270Sdonn 	if (l == token_start) {
48347270Sdonn 	  as_bad ("expecting prefix; got nothing");
48447270Sdonn 	  return;
48547270Sdonn 	}
48647270Sdonn 	END_STRING_AND_SAVE (l);
48747270Sdonn 	prefix = (prefix_entry *) hash_find (prefix_hash, token_start);
48847270Sdonn 	if (! prefix) {
48947270Sdonn 	  as_bad ("no such opcode prefix ('%s')", token_start);
49047270Sdonn 	  return;
49147270Sdonn 	}
49247270Sdonn 	RESTORE_END_STRING (l);
49347270Sdonn 	/* check for repeated prefix */
49447270Sdonn 	for (q = 0; q < i.prefixes; q++)
49547270Sdonn 	  if (i.prefix[q] == prefix->prefix_code) {
49647270Sdonn 	    as_bad ("same prefix used twice; you don't really want this!");
49747270Sdonn 	    return;
49847270Sdonn 	  }
49947270Sdonn 	if (i.prefixes == MAX_PREFIXES) {
50047270Sdonn 	  as_bad ("too many opcode prefixes");
50147270Sdonn 	  return;
50247270Sdonn 	}
50347270Sdonn 	i.prefix[i.prefixes++] = prefix->prefix_code;
50447270Sdonn 	if (prefix->prefix_code == REPE || prefix->prefix_code == REPNE)
50547270Sdonn 	  expecting_string_instruction = TRUE;
50647270Sdonn 	/* skip past PREFIX_SEPERATOR and reset token_start */
50747270Sdonn 	token_start = ++l;
50847270Sdonn       }
50947270Sdonn     }
51047270Sdonn     END_STRING_AND_SAVE (l);
51147270Sdonn     if (token_start == l) {
51247270Sdonn       as_bad ("expecting opcode; got nothing");
51347270Sdonn       return;
51447270Sdonn     }
51547270Sdonn 
51647270Sdonn     /* Lookup insn in hash; try intel & att naming conventions if appropriate;
51747270Sdonn        that is:  we only use the opcode suffix 'b' 'w' or 'l' if we need to. */
51847270Sdonn     current_templates = (templates *) hash_find (op_hash, token_start);
51947270Sdonn     if (! current_templates) {
52047270Sdonn       int last_index = strlen(token_start) - 1;
52147270Sdonn       char last_char = token_start[last_index];
52247270Sdonn       switch (last_char) {
52347270Sdonn       case DWORD_OPCODE_SUFFIX:
52447270Sdonn       case WORD_OPCODE_SUFFIX:
52547270Sdonn       case BYTE_OPCODE_SUFFIX:
52647270Sdonn 	token_start[last_index] = '\0';
52747270Sdonn 	current_templates = (templates *) hash_find (op_hash, token_start);
52847270Sdonn 	token_start[last_index] = last_char;
52947270Sdonn 	i.suffix = last_char;
53047270Sdonn       }
53147270Sdonn       if (!current_templates) {
53247270Sdonn 	as_bad ("no such 386 instruction: `%s'", token_start); return;
53347270Sdonn       }
53447270Sdonn     }
53547270Sdonn     RESTORE_END_STRING (l);
53647270Sdonn 
53747270Sdonn     /* check for rep/repne without a string instruction */
53847270Sdonn     if (expecting_string_instruction &&
53947270Sdonn 	! IS_STRING_INSTRUCTION (current_templates->
54047270Sdonn 				 start->base_opcode)) {
54147270Sdonn       as_bad ("expecting string instruction after rep/repne");
54247270Sdonn       return;
54347270Sdonn     }
54447270Sdonn 
54547270Sdonn     /* There may be operands to parse. */
54647270Sdonn     if (*l != END_OF_INSN &&
54747270Sdonn 	/* For string instructions, we ignore any operands if given.  This
54847270Sdonn 	   kludges, for example, 'rep/movsb %ds:(%esi), %es:(%edi)' where
54947270Sdonn 	   the operands are always going to be the same, and are not really
55047270Sdonn 	   encoded in machine code. */
55147270Sdonn 	! IS_STRING_INSTRUCTION (current_templates->
55247270Sdonn 				 start->base_opcode)) {
55347270Sdonn       /* parse operands */
55447270Sdonn       do {
55547270Sdonn 	/* skip optional white space before operand */
55647270Sdonn 	while (! is_operand_char(*l) && *l != END_OF_INSN) {
55747270Sdonn 	  if (! is_space_char(*l)) {
55847270Sdonn 	    as_bad ("invalid character %s before %s operand",
55947270Sdonn 		     output_invalid(*l),
56047270Sdonn 		     ordinal_names[i.operands]);
56147270Sdonn 	    return;
56247270Sdonn 	  }
56347270Sdonn 	  l++;
56447270Sdonn 	}
56547270Sdonn 	token_start = l;		/* after white space */
56647270Sdonn 	paren_not_balenced = 0;
56747270Sdonn 	while (paren_not_balenced || *l != ',') {
56847270Sdonn 	  if (*l == END_OF_INSN) {
56947270Sdonn 	    if (paren_not_balenced) {
57047270Sdonn 	      as_bad ("unbalenced parenthesis in %s operand.",
57147270Sdonn 		       ordinal_names[i.operands]);
57247270Sdonn 	      return;
57347270Sdonn 	    } else break;		/* we are done */
57447270Sdonn 	  } else if (! is_operand_char(*l)) {
57547270Sdonn 	    as_bad ("invalid character %s in %s operand",
57647270Sdonn 		     output_invalid(*l),
57747270Sdonn 		     ordinal_names[i.operands]);
57847270Sdonn 	    return;
57947270Sdonn 	  }
58047270Sdonn 	  if (*l == '(') ++paren_not_balenced;
58147270Sdonn 	  if (*l == ')') --paren_not_balenced;
58247270Sdonn 	  l++;
58347270Sdonn 	}
58447270Sdonn 	if (l != token_start) {	/* yes, we've read in another operand */
58547270Sdonn 	  uint operand_ok;
58647270Sdonn 	  this_operand = i.operands++;
58747270Sdonn 	  if (i.operands > MAX_OPERANDS) {
58847270Sdonn 	    as_bad ("spurious operands; (%d operands/instruction max)",
58947270Sdonn 		     MAX_OPERANDS);
59047270Sdonn 	    return;
59147270Sdonn 	  }
59247270Sdonn 	  /* now parse operand adding info to 'i' as we go along */
59347270Sdonn 	  END_STRING_AND_SAVE (l);
59447270Sdonn 	  operand_ok = i386_operand (token_start);
59547270Sdonn 	  RESTORE_END_STRING (l);	/* restore old contents */
59647270Sdonn 	  if (!operand_ok) return;
59747270Sdonn 	} else {
59847270Sdonn 	  if (expecting_operand) {
59947270Sdonn 	  expecting_operand_after_comma:
60047270Sdonn 	    as_bad ("expecting operand after ','; got nothing");
60147270Sdonn 	    return;
60247270Sdonn 	  }
60347270Sdonn 	  if (*l == ',') {
60447270Sdonn 	    as_bad ("expecting operand before ','; got nothing");
60547270Sdonn 	    return;
60647270Sdonn 	  }
60747270Sdonn 	}
60847270Sdonn 
60947270Sdonn 	/* now *l must be either ',' or END_OF_INSN */
61047270Sdonn 	if (*l == ',') {
61147270Sdonn 	  if (*++l == END_OF_INSN) {		/* just skip it, if it's \n complain */
61247270Sdonn 	    goto expecting_operand_after_comma;
61347270Sdonn 	  }
61447270Sdonn 	  expecting_operand = TRUE;
61547270Sdonn 	}
61647270Sdonn       } while (*l != END_OF_INSN);		/* until we get end of insn */
61747270Sdonn     }
61847270Sdonn   }
61947270Sdonn 
62047270Sdonn   /* Now we've parsed the opcode into a set of templates, and have the
62147270Sdonn      operands at hand.
62247270Sdonn      Next, we find a template that matches the given insn,
62347270Sdonn      making sure the overlap of the given operands types is consistent
62447270Sdonn      with the template operand types. */
62547270Sdonn 
62647270Sdonn #define MATCH(overlap,given_type) \
62747270Sdonn   (overlap && \
62847270Sdonn    (overlap & (JumpAbsolute|BaseIndex|Mem8)) \
62947270Sdonn    == (given_type & (JumpAbsolute|BaseIndex|Mem8)))
63047270Sdonn 
63147270Sdonn     /* If m0 and m1 are register matches they must be consistent
63247270Sdonn        with the expected operand types t0 and t1.
63347270Sdonn      That is, if both m0 & m1 are register matches
63447270Sdonn          i.e. ( ((m0 & (Reg)) && (m1 & (Reg)) ) ?
63547270Sdonn      then, either 1. or 2. must be true:
63647270Sdonn          1. the expected operand type register overlap is null:
63747270Sdonn 	             (t0 & t1 & Reg) == 0
63847270Sdonn 	 AND
63947270Sdonn 	    the given register overlap is null:
64047270Sdonn                      (m0 & m1 & Reg) == 0
64147270Sdonn 	 2. the expected operand type register overlap == the given
64247270Sdonn 	    operand type overlap:  (t0 & t1 & m0 & m1 & Reg).
64347270Sdonn      */
64447270Sdonn #define CONSISTENT_REGISTER_MATCH(m0, m1, t0, t1) \
64547270Sdonn     ( ((m0 & (Reg)) && (m1 & (Reg))) ? \
64647270Sdonn       ( ((t0 & t1 & (Reg)) == 0 && (m0 & m1 & (Reg)) == 0) || \
64747270Sdonn         ((t0 & t1) & (m0 & m1) & (Reg)) \
64847270Sdonn        ) : 1)
64947270Sdonn   {
65047270Sdonn     register uint overlap0, overlap1;
65147270Sdonn     expressionS * exp;
65247270Sdonn     uint overlap2;
65347270Sdonn     uint found_reverse_match;
65447270Sdonn 
65547270Sdonn     overlap0 = overlap1 = overlap2 = found_reverse_match = 0;
65647270Sdonn     for (t = current_templates->start;
65747270Sdonn 	 t < current_templates->end;
65847270Sdonn 	 t++) {
65947270Sdonn 
66047270Sdonn       /* must have right number of operands */
66147270Sdonn       if (i.operands != t->operands) continue;
66247270Sdonn       else if (!t->operands) break;	/* 0 operands always matches */
66347270Sdonn 
66447270Sdonn       overlap0 = i.types[0] & t->operand_types[0];
66547270Sdonn       switch (t->operands) {
66647270Sdonn       case 1:
66747270Sdonn 	if (! MATCH (overlap0,i.types[0])) continue;
66847270Sdonn 	break;
66947270Sdonn       case 2: case 3:
67047270Sdonn 	overlap1 = i.types[1] & t->operand_types[1];
67147270Sdonn 	if (! MATCH (overlap0,i.types[0]) ||
67247270Sdonn 	    ! MATCH (overlap1,i.types[1]) ||
67347270Sdonn 	    ! CONSISTENT_REGISTER_MATCH(overlap0, overlap1,
67447270Sdonn 					t->operand_types[0],
67547270Sdonn 					t->operand_types[1])) {
67647270Sdonn 
67747270Sdonn 	  /* check if other direction is valid ... */
67847270Sdonn 	  if (! (t->opcode_modifier & COMES_IN_BOTH_DIRECTIONS))
67947270Sdonn 	    continue;
68047270Sdonn 
68147270Sdonn 	  /* try reversing direction of operands */
68247270Sdonn 	  overlap0 = i.types[0] & t->operand_types[1];
68347270Sdonn 	  overlap1 = i.types[1] & t->operand_types[0];
68447270Sdonn 	  if (! MATCH (overlap0,i.types[0]) ||
68547270Sdonn 	      ! MATCH (overlap1,i.types[1]) ||
68647270Sdonn 	      ! CONSISTENT_REGISTER_MATCH (overlap0, overlap1,
68747270Sdonn 					   t->operand_types[0],
68847270Sdonn 					   t->operand_types[1])) {
68947270Sdonn 	    /* does not match either direction */
69047270Sdonn 	    continue;
69147270Sdonn 	  }
69247270Sdonn 	  /* found a reverse match here -- slip through */
69347270Sdonn 	  /* found_reverse_match holds which of D or FloatD we've found */
69447270Sdonn 	  found_reverse_match = t->opcode_modifier & COMES_IN_BOTH_DIRECTIONS;
69547270Sdonn 	}				/* endif: not forward match */
69647270Sdonn 	/* found either forward/reverse 2 operand match here */
69747270Sdonn 	if (t->operands == 3) {
69847270Sdonn 	  overlap2 = i.types[2] & t->operand_types[2];
69947270Sdonn 	  if (! MATCH (overlap2,i.types[2]) ||
70047270Sdonn 	      ! CONSISTENT_REGISTER_MATCH (overlap0, overlap2,
70147270Sdonn 					   t->operand_types[0],
70247270Sdonn 					   t->operand_types[2]) ||
70347270Sdonn 	      ! CONSISTENT_REGISTER_MATCH (overlap1, overlap2,
70447270Sdonn 					   t->operand_types[1],
70547270Sdonn 					   t->operand_types[2]))
70647270Sdonn 	    continue;
70747270Sdonn 	}
70847270Sdonn 	/* found either forward/reverse 2 or 3 operand match here:
70947270Sdonn 	   slip through to break */
71047270Sdonn       }
71147270Sdonn       break;			/* we've found a match; break out of loop */
71247270Sdonn     }				/* for (t = ... */
71347270Sdonn     if (t == current_templates->end) { /* we found no match */
71447270Sdonn       as_bad ("operands given don't match any known 386 instruction");
71547270Sdonn       return;
71647270Sdonn     }
71747270Sdonn 
71847270Sdonn     /* Copy the template we found (we may change it!). */
71947270Sdonn     bcopy (t, &i.tm, sizeof (template));
72047270Sdonn     t = &i.tm;			/* alter new copy of template */
72147270Sdonn 
72247270Sdonn     /* If there's no opcode suffix we try to invent one based on register
72347270Sdonn        operands. */
72447270Sdonn     if (! i.suffix && i.reg_operands) {
72547270Sdonn       /* We take i.suffix from the LAST register operand specified.  This
72647270Sdonn 	 assumes that the last register operands is the destination register
72747270Sdonn 	 operand. */
72847270Sdonn       int o;
72947270Sdonn       for (o = 0; o < MAX_OPERANDS; o++)
73047270Sdonn 	if (i.types[o] & Reg) {
73147270Sdonn 	  i.suffix = (i.types[o] == Reg8) ? BYTE_OPCODE_SUFFIX :
73247270Sdonn 	    (i.types[o] == Reg16) ? WORD_OPCODE_SUFFIX :
73347270Sdonn 	      DWORD_OPCODE_SUFFIX;
73447270Sdonn 	}
73547270Sdonn     }
73647270Sdonn 
73747270Sdonn     /* Make still unresolved immediate matches conform to size of immediate
73847270Sdonn        given in i.suffix. Note:  overlap2 cannot be an immediate!
73947270Sdonn        We assume this. */
74047270Sdonn     if ((overlap0 & (Imm8|Imm8S|Imm16|Imm32))
74147270Sdonn 	&& overlap0 != Imm8 && overlap0 != Imm8S
74247270Sdonn 	&& overlap0 != Imm16 && overlap0 != Imm32) {
74347270Sdonn       if (! i.suffix) {
74447270Sdonn 	as_bad ("no opcode suffix given; can't determine immediate size");
74547270Sdonn 	return;
74647270Sdonn       }
74747270Sdonn       overlap0 &= (i.suffix == BYTE_OPCODE_SUFFIX ? (Imm8|Imm8S) :
74847270Sdonn 		   (i.suffix == WORD_OPCODE_SUFFIX ? Imm16 : Imm32));
74947270Sdonn     }
75047270Sdonn     if ((overlap1 & (Imm8|Imm8S|Imm16|Imm32))
75147270Sdonn 	&& overlap1 != Imm8 && overlap1 != Imm8S
75247270Sdonn 	&& overlap1 != Imm16 && overlap1 != Imm32) {
75347270Sdonn       if (! i.suffix) {
75447270Sdonn 	as_bad ("no opcode suffix given; can't determine immediate size");
75547270Sdonn 	return;
75647270Sdonn       }
75747270Sdonn       overlap1 &= (i.suffix == BYTE_OPCODE_SUFFIX ? (Imm8|Imm8S) :
75847270Sdonn 		   (i.suffix == WORD_OPCODE_SUFFIX ? Imm16 : Imm32));
75947270Sdonn     }
76047270Sdonn 
76147270Sdonn     i.types[0] = overlap0;
76247270Sdonn     i.types[1] = overlap1;
76347270Sdonn     i.types[2] = overlap2;
76447270Sdonn 
76547270Sdonn     if (overlap0 & ImplicitRegister) i.reg_operands--;
76647270Sdonn     if (overlap1 & ImplicitRegister) i.reg_operands--;
76747270Sdonn     if (overlap2 & ImplicitRegister) i.reg_operands--;
76847270Sdonn     if (overlap0 & Imm1) i.imm_operands = 0; /* kludge for shift insns */
76947270Sdonn 
77047270Sdonn     if (found_reverse_match) {
77147270Sdonn       uint save;
77247270Sdonn       save = t->operand_types[0];
77347270Sdonn       t->operand_types[0] = t->operand_types[1];
77447270Sdonn       t->operand_types[1] = save;
77547270Sdonn     }
77647270Sdonn 
77747270Sdonn     /* Finalize opcode.  First, we change the opcode based on the operand
77847270Sdonn        size given by i.suffix: we never have to change things for byte insns,
77947270Sdonn        or when no opcode suffix is need to size the operands. */
78047270Sdonn 
78147270Sdonn     if (! i.suffix && (t->opcode_modifier & W)) {
78247270Sdonn       as_bad ("no opcode suffix given and no register operands; can't size instruction");
78347270Sdonn       return;
78447270Sdonn     }
78547270Sdonn 
78647270Sdonn     if (i.suffix && i.suffix != BYTE_OPCODE_SUFFIX) {
78747270Sdonn       /* Select between byte and word/dword operations. */
78847270Sdonn       if (t->opcode_modifier & W)
78947270Sdonn 	t->base_opcode |= W;
79047270Sdonn       /* Now select between word & dword operations via the
79147270Sdonn 	 operand size prefix. */
79247270Sdonn       if (i.suffix == WORD_OPCODE_SUFFIX) {
79347270Sdonn 	if (i.prefixes == MAX_PREFIXES) {
79447270Sdonn 	  as_bad ("%d prefixes given and 'w' opcode suffix gives too many prefixes",
79547270Sdonn 		   MAX_PREFIXES);
79647270Sdonn 	  return;
79747270Sdonn 	}
79847270Sdonn 	i.prefix[i.prefixes++] = WORD_PREFIX_OPCODE;
79947270Sdonn       }
80047270Sdonn     }
80147270Sdonn 
80247270Sdonn     /* For insns with operands there are more diddles to do to the opcode. */
80347270Sdonn     if (i.operands) {
80447270Sdonn       /* If we found a reverse match we must alter the opcode direction bit
80547270Sdonn 	 found_reverse_match holds bit to set (different for int &
80647270Sdonn 	 float insns). */
80747270Sdonn 
80847270Sdonn       if (found_reverse_match) {
80947270Sdonn 	t->base_opcode |= found_reverse_match;
81047270Sdonn       }
81147270Sdonn 
81247270Sdonn       /*
81347270Sdonn 	The imul $imm, %reg instruction is converted into
81447270Sdonn 	imul $imm, %reg, %reg. */
81547270Sdonn       if (t->opcode_modifier & imulKludge) {
81647270Sdonn 	  i.regs[2] = i.regs[1]; /* Pretend we saw the 3 operand case. */
81747270Sdonn 	  i.reg_operands = 2;
81847270Sdonn       }
81947270Sdonn 
82047270Sdonn       /* Certain instructions expect the destination to be in the i.rm.reg
82147270Sdonn 	 field.  This is by far the exceptional case.  For these instructions,
82247270Sdonn 	 if the source operand is a register, we must reverse the i.rm.reg
82347270Sdonn 	 and i.rm.regmem fields.  We accomplish this by faking that the
82447270Sdonn 	 two register operands were given in the reverse order. */
82547270Sdonn       if ((t->opcode_modifier & ReverseRegRegmem) && i.reg_operands == 2) {
82647270Sdonn 	uint first_reg_operand = (i.types[0] & Reg) ? 0 : 1;
82747270Sdonn 	uint second_reg_operand = first_reg_operand + 1;
82847270Sdonn 	reg_entry *tmp = i.regs[first_reg_operand];
82947270Sdonn 	i.regs[first_reg_operand] = i.regs[second_reg_operand];
83047270Sdonn 	i.regs[second_reg_operand] = tmp;
83147270Sdonn       }
83247270Sdonn 
83347270Sdonn       if (t->opcode_modifier & ShortForm) {
83447270Sdonn 	/* The register or float register operand is in operand 0 or 1. */
83547270Sdonn 	uint o = (i.types[0] & (Reg|FloatReg)) ? 0 : 1;
83647270Sdonn 	/* Register goes in low 3 bits of opcode. */
83747270Sdonn 	t->base_opcode |= i.regs[o]->reg_num;
83847270Sdonn       } else if (t->opcode_modifier & ShortFormW) {
83947270Sdonn 	/* Short form with 0x8 width bit.  Register is always dest. operand */
84047270Sdonn 	t->base_opcode |= i.regs[1]->reg_num;
84147270Sdonn 	if (i.suffix == WORD_OPCODE_SUFFIX ||
84247270Sdonn 	    i.suffix == DWORD_OPCODE_SUFFIX)
84347270Sdonn 	  t->base_opcode |= 0x8;
84447270Sdonn       } else if (t->opcode_modifier & Seg2ShortForm) {
84547270Sdonn 	if (t->base_opcode == POP_SEG_SHORT && i.regs[0]->reg_num == 1) {
84647270Sdonn 	  as_bad ("you can't 'pop cs' on the 386.");
84747270Sdonn 	  return;
84847270Sdonn 	}
84947270Sdonn 	t->base_opcode |= (i.regs[0]->reg_num << 3);
85047270Sdonn       } else if (t->opcode_modifier & Seg3ShortForm) {
85147270Sdonn 	/* 'push %fs' is 0x0fa0; 'pop %fs' is 0x0fa1.
85247270Sdonn 	   'push %gs' is 0x0fa8; 'pop %fs' is 0x0fa9.
85347270Sdonn 	   So, only if i.regs[0]->reg_num == 5 (%gs) do we need
85447270Sdonn 	   to change the opcode. */
85547270Sdonn 	if (i.regs[0]->reg_num == 5)
85647270Sdonn 	  t->base_opcode |= 0x08;
85747270Sdonn       } else if (t->opcode_modifier & Modrm) {
85847270Sdonn 	/* The opcode is completed (modulo t->extension_opcode which must
85947270Sdonn 	   be put into the modrm byte.
86047270Sdonn 	   Now, we make the modrm & index base bytes based on all the info
86147270Sdonn 	   we've collected. */
86247270Sdonn 
86347270Sdonn 	/* i.reg_operands MUST be the number of real register operands;
86447270Sdonn 	   implicit registers do not count. */
86547270Sdonn 	if (i.reg_operands == 2) {
86647270Sdonn 	  uint source, dest;
86747270Sdonn 	  source = (i.types[0] & (Reg|SReg2|SReg3|Control|Debug|Test)) ? 0 : 1;
86847270Sdonn 	  dest = source + 1;
86947270Sdonn 	  i.rm.mode = 3;
87047270Sdonn 	  /* We must be careful to make sure that all segment/control/test/
87147270Sdonn 	     debug registers go into the i.rm.reg field (despite the whether
87247270Sdonn 	     they are source or destination operands). */
87347270Sdonn 	  if (i.regs[dest]->reg_type & (SReg2|SReg3|Control|Debug|Test)) {
87447270Sdonn 	    i.rm.reg = i.regs[dest]->reg_num;
87547270Sdonn 	    i.rm.regmem = i.regs[source]->reg_num;
87647270Sdonn 	  } else {
87747270Sdonn 	    i.rm.reg = i.regs[source]->reg_num;
87847270Sdonn 	    i.rm.regmem = i.regs[dest]->reg_num;
87947270Sdonn 	  }
88047270Sdonn 	} else {		/* if it's not 2 reg operands... */
88147270Sdonn 	  if (i.mem_operands) {
88247270Sdonn 	    uint fake_zero_displacement = FALSE;
88347270Sdonn 	    uint o = (i.types[0] & Mem) ? 0 : ((i.types[1] & Mem) ? 1 : 2);
88447270Sdonn 
88547270Sdonn 	    /* Encode memory operand into modrm byte and base index byte. */
88647270Sdonn 
88747270Sdonn 	    if (i.base_reg == esp && ! i.index_reg) {
88847270Sdonn 	      /* <disp>(%esp) becomes two byte modrm with no index register. */
88947270Sdonn 	      i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
89047270Sdonn 	      i.rm.mode = MODE_FROM_DISP_SIZE (i.types[o]);
89147270Sdonn 	      i.bi.base = ESP_REG_NUM;
89247270Sdonn 	      i.bi.index = NO_INDEX_REGISTER;
89347270Sdonn 	      i.bi.scale = 0;		/* Must be zero! */
89447270Sdonn 	    } else if (i.base_reg == ebp && !i.index_reg) {
89547270Sdonn 	      if (! (i.types[o] & Disp)) {
89647270Sdonn 		/* Must fake a zero byte displacement.
89747270Sdonn 		   There is no direct way to code '(%ebp)' directly. */
89847270Sdonn 		fake_zero_displacement = TRUE;
89947270Sdonn 		/* fake_zero_displacement code does not set this. */
90047270Sdonn 		i.types[o] |= Disp8;
90147270Sdonn 	      }
90247270Sdonn 	      i.rm.mode = MODE_FROM_DISP_SIZE (i.types[o]);
90347270Sdonn 	      i.rm.regmem = EBP_REG_NUM;
90447270Sdonn 	    } else if (! i.base_reg && (i.types[o] & BaseIndex)) {
90547270Sdonn 	      /* There are three cases here.
90647270Sdonn 		 Case 1:  '<32bit disp>(,1)' -- indirect absolute.
90747270Sdonn 		 (Same as cases 2 & 3 with NO index register)
90847270Sdonn 		 Case 2:  <32bit disp> (,<index>) -- no base register with disp
90947270Sdonn 		 Case 3:  (, <index>)       --- no base register;
91047270Sdonn 		 no disp (must add 32bit 0 disp). */
91147270Sdonn 	      i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
91247270Sdonn 	      i.rm.mode = 0;		/* 32bit mode */
91347270Sdonn 	      i.bi.base = NO_BASE_REGISTER;
91447270Sdonn 	      i.types[o] &= ~Disp;
91547270Sdonn 	      i.types[o] |= Disp32;	/* Must be 32bit! */
91647270Sdonn 	      if (i.index_reg) {		/* case 2 or case 3 */
91747270Sdonn 		i.bi.index = i.index_reg->reg_num;
91847270Sdonn 		i.bi.scale = i.log2_scale_factor;
91947270Sdonn 		if (i.disp_operands == 0)
92047270Sdonn 		  fake_zero_displacement = TRUE; /* case 3 */
92147270Sdonn 	      } else {
92247270Sdonn 		i.bi.index = NO_INDEX_REGISTER;
92347270Sdonn 		i.bi.scale = 0;
92447270Sdonn 	      }
92547270Sdonn 	    } else if (i.disp_operands && !i.base_reg && !i.index_reg) {
92647270Sdonn 	      /* Operand is just <32bit disp> */
92747270Sdonn 	      i.rm.regmem = EBP_REG_NUM;
92847270Sdonn 	      i.rm.mode = 0;
92947270Sdonn 	      i.types[o] &= ~Disp;
93047270Sdonn 	      i.types[o] |= Disp32;
93147270Sdonn 	    } else {
93247270Sdonn 	      /* It's not a special case; rev'em up. */
93347270Sdonn 	      i.rm.regmem = i.base_reg->reg_num;
93447270Sdonn 	      i.rm.mode = MODE_FROM_DISP_SIZE (i.types[o]);
93547270Sdonn 	      if (i.index_reg) {
93647270Sdonn 		i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
93747270Sdonn 		i.bi.base = i.base_reg->reg_num;
93847270Sdonn 		i.bi.index = i.index_reg->reg_num;
93947270Sdonn 		i.bi.scale = i.log2_scale_factor;
94047270Sdonn 		if (i.base_reg == ebp && i.disp_operands == 0) { /* pace */
94147270Sdonn 		  fake_zero_displacement = TRUE;
94247270Sdonn 		  i.types[o] |= Disp8;
94347270Sdonn 		  i.rm.mode = MODE_FROM_DISP_SIZE (i.types[o]);
94447270Sdonn 		}
94547270Sdonn 	      }
94647270Sdonn 	    }
94747270Sdonn 	    if (fake_zero_displacement) {
94847270Sdonn 	      /* Fakes a zero displacement assuming that i.types[o] holds
94947270Sdonn 		 the correct displacement size. */
95047270Sdonn 	      exp = &disp_expressions[i.disp_operands++];
95147270Sdonn 	      i.disps[o] = exp;
95247270Sdonn 	      exp->X_seg = SEG_ABSOLUTE;
95347270Sdonn 	      exp->X_add_number = 0;
95447270Sdonn 	      exp->X_add_symbol = (symbolS *) 0;
95547270Sdonn 	      exp->X_subtract_symbol = (symbolS *) 0;
95647270Sdonn 	    }
95747270Sdonn 
95847270Sdonn 	    /* Select the correct segment for the memory operand. */
95947270Sdonn 	    if (i.seg) {
96047270Sdonn 	      uint seg_index;
96147270Sdonn 	      seg_entry * default_seg;
96247270Sdonn 
96347270Sdonn 	      if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING) {
96447270Sdonn 		seg_index = (i.rm.mode<<3) | i.bi.base;
96547270Sdonn 		default_seg = two_byte_segment_defaults [seg_index];
96647270Sdonn 	      } else {
96747270Sdonn 		seg_index = (i.rm.mode<<3) | i.rm.regmem;
96847270Sdonn 		default_seg = one_byte_segment_defaults [seg_index];
96947270Sdonn 	      }
97047270Sdonn 	      /* If the specified segment is not the default, use an
97147270Sdonn 		 opcode prefix to select it */
97247270Sdonn 	      if (i.seg != default_seg) {
97347270Sdonn 		if (i.prefixes == MAX_PREFIXES) {
97447270Sdonn 		  as_bad ("%d prefixes given and %s segment override gives too many prefixes",
97547270Sdonn 			   MAX_PREFIXES, i.seg->seg_name);
97647270Sdonn 		  return;
97747270Sdonn 		}
97847270Sdonn 		i.prefix[i.prefixes++] = i.seg->seg_prefix;
97947270Sdonn 	      }
98047270Sdonn 	    }
98147270Sdonn 	  }
98247270Sdonn 
98347270Sdonn 	  /* Fill in i.rm.reg or i.rm.regmem field with register operand
98447270Sdonn 	     (if any) based on t->extension_opcode. Again, we must be careful
98547270Sdonn 	     to make sure that segment/control/debug/test registers are coded
98647270Sdonn 	     into the i.rm.reg field. */
98747270Sdonn 	  if (i.reg_operands) {
98847270Sdonn 	    uint o =
98947270Sdonn 	      (i.types[0] & (Reg|SReg2|SReg3|Control|Debug|Test)) ? 0 :
99047270Sdonn 		(i.types[1] & (Reg|SReg2|SReg3|Control|Debug|Test)) ? 1 : 2;
99147270Sdonn 	    /* If there is an extension opcode to put here, the register number
99247270Sdonn 	       must be put into the regmem field. */
99347270Sdonn 	    if (t->extension_opcode != None)
99447270Sdonn 	      i.rm.regmem = i.regs[o]->reg_num;
99547270Sdonn 	    else i.rm.reg = i.regs[o]->reg_num;
99647270Sdonn 
99747270Sdonn 	    /* Now, if no memory operand has set i.rm.mode = 0, 1, 2
99847270Sdonn 	       we must set it to 3 to indicate this is a register operand
99947270Sdonn 	       int the regmem field */
100047270Sdonn 	    if (! i.mem_operands) i.rm.mode = 3;
100147270Sdonn 	  }
100247270Sdonn 
100347270Sdonn 	  /* Fill in i.rm.reg field with extension opcode (if any). */
100447270Sdonn 	  if (t->extension_opcode != None)
100547270Sdonn 	    i.rm.reg = t->extension_opcode;
100647270Sdonn 	}
100747270Sdonn       }
100847270Sdonn     }
100947270Sdonn   }
101047270Sdonn 
101147270Sdonn   /* Handle conversion of 'int $3' --> special int3 insn. */
101247270Sdonn   if (t->base_opcode == INT_OPCODE && i.imms[0]->X_add_number == 3) {
101347270Sdonn     t->base_opcode = INT3_OPCODE;
101447270Sdonn     i.imm_operands = 0;
101547270Sdonn   }
101647270Sdonn 
101747270Sdonn   /* We are ready to output the insn. */
101847270Sdonn   {
101947270Sdonn     register char * p;
102047270Sdonn 
102147270Sdonn     /* Output jumps. */
102247270Sdonn     if (t->opcode_modifier & Jump) {
102347270Sdonn       int n = i.disps[0]->X_add_number;
102447270Sdonn 
102547270Sdonn       switch (i.disps[0]->X_seg) {
102647270Sdonn       case SEG_ABSOLUTE:
102747270Sdonn 	if (FITS_IN_SIGNED_BYTE (n)) {
102847270Sdonn 	  p = frag_more (2);
102947270Sdonn 	  p[0] = t->base_opcode;
103047270Sdonn 	  p[1] = n;
103147270Sdonn #if 0 /* leave out 16 bit jumps - pace */
103247270Sdonn 	} else if (FITS_IN_SIGNED_WORD (n)) {
103347270Sdonn 	  p = frag_more (4);
103447270Sdonn 	  p[0] = WORD_PREFIX_OPCODE;
103547270Sdonn 	  p[1] = t->base_opcode;
103647270Sdonn 	  md_number_to_chars (&p[2], n, 2);
103747270Sdonn #endif
103847270Sdonn 	} else {		/* It's an absolute dword displacement. */
103947270Sdonn 	  if (t->base_opcode == JUMP_PC_RELATIVE) { /* pace */
104047270Sdonn 	    /* unconditional jump */
104147270Sdonn 	    p = frag_more (5);
104247270Sdonn 	    p[0] = 0xe9;
104347270Sdonn 	    md_number_to_chars (&p[1], n, 4);
104447270Sdonn 	  } else {
104547270Sdonn 	    /* conditional jump */
104647270Sdonn 	    p = frag_more (6);
104747270Sdonn 	    p[0] = TWO_BYTE_OPCODE_ESCAPE;
104847270Sdonn 	    p[1] = t->base_opcode + 0x10;
104947270Sdonn 	    md_number_to_chars (&p[2], n, 4);
105047270Sdonn 	  }
105147270Sdonn 	}
105247270Sdonn 	break;
105347270Sdonn       default:
105447270Sdonn 	/* It's a symbol; end frag & setup for relax.
105547270Sdonn 	   Make sure there are 6 chars left in the current frag; if not
105647270Sdonn 	   we'll have to start a new one. */
105747270Sdonn 	/* I caught it failing with obstack_room == 6,
105847270Sdonn 	   so I changed to <=   pace */
105947270Sdonn 	if (obstack_room (&frags) <= 6) {
106047270Sdonn 		frag_wane(frag_now);
106147270Sdonn 		frag_new (0);
106247270Sdonn 	}
106347270Sdonn 	p = frag_more (1);
106447270Sdonn 	p[0] = t->base_opcode;
106547270Sdonn 	frag_var (rs_machine_dependent,
106647270Sdonn 		  6,		/* 2 opcode/prefix + 4 displacement */
106747270Sdonn 		  1,
106847270Sdonn 		  ((uchar) *p == JUMP_PC_RELATIVE
106947270Sdonn 		   ? ENCODE_RELAX_STATE (UNCOND_JUMP, BYTE)
107047270Sdonn 		   : ENCODE_RELAX_STATE (COND_JUMP, BYTE)),
107147270Sdonn 		  i.disps[0]->X_add_symbol,
107247270Sdonn 		  n, p);
107347270Sdonn 	break;
107447270Sdonn       }
107547270Sdonn     } else if (t->opcode_modifier & (JumpByte|JumpDword)) {
107647270Sdonn       int size = (t->opcode_modifier & JumpByte) ? 1 : 4;
107747270Sdonn       int n = i.disps[0]->X_add_number;
107847270Sdonn 
107947270Sdonn       if (FITS_IN_UNSIGNED_BYTE(t->base_opcode)) {
108047270Sdonn 	FRAG_APPEND_1_CHAR (t->base_opcode);
108147270Sdonn       } else {
108247270Sdonn 	p = frag_more (2);	/* opcode can be at most two bytes */
108347270Sdonn 	/* put out high byte first: can't use md_number_to_chars! */
108447270Sdonn 	*p++ = (t->base_opcode >> 8) & 0xff;
108547270Sdonn 	*p = t->base_opcode & 0xff;
108647270Sdonn       }
108747270Sdonn 
108847270Sdonn       p =  frag_more (size);
108947270Sdonn       switch (i.disps[0]->X_seg) {
109047270Sdonn       case SEG_ABSOLUTE:
109147270Sdonn 	md_number_to_chars (p, n, size);
109247270Sdonn 	if (size == 1 && ! FITS_IN_SIGNED_BYTE (n)) {
109347270Sdonn 	  as_bad ("loop/jecx only takes byte displacement; %d shortened to %d",
109447270Sdonn 		   n, *p);
109547270Sdonn 	}
109647270Sdonn 	break;
109747270Sdonn       default:
109847270Sdonn 	fix_new (frag_now, p - frag_now->fr_literal, size,
109947270Sdonn 		 i.disps[0]->X_add_symbol, i.disps[0]->X_subtract_symbol,
110047270Sdonn 		 i.disps[0]->X_add_number, 1);
110147270Sdonn 	break;
110247270Sdonn       }
110347270Sdonn     } else if (t->opcode_modifier & JumpInterSegment) {
110447270Sdonn       p =  frag_more (1 + 2 + 4);	/* 1 opcode; 2 segment; 4 offset */
110547270Sdonn       p[0] = t->base_opcode;
110647270Sdonn       if (i.imms[1]->X_seg == SEG_ABSOLUTE)
110747270Sdonn 	md_number_to_chars (p + 1, i.imms[1]->X_add_number, 4);
110847270Sdonn       else
110947270Sdonn 	fix_new (frag_now, p + 1 -  frag_now->fr_literal, 4,
111047270Sdonn 		 i.imms[1]->X_add_symbol,
111147270Sdonn 		 i.imms[1]->X_subtract_symbol,
111247270Sdonn 		 i.imms[1]->X_add_number, 0);
111347270Sdonn       if (i.imms[0]->X_seg != SEG_ABSOLUTE)
111447270Sdonn 	as_bad ("can't handle non absolute segment in long call/jmp");
111547270Sdonn       md_number_to_chars (p + 5, i.imms[0]->X_add_number, 2);
111647270Sdonn     } else {
111747270Sdonn       /* Output normal instructions here. */
111847270Sdonn       register char *q;
111947270Sdonn 
112047270Sdonn       /* First the prefix bytes. */
112147270Sdonn       for (q = i.prefix; q < i.prefix + i.prefixes; q++) {
112247270Sdonn 	p =  frag_more (1);
112347270Sdonn 	md_number_to_chars (p, (uint) *q, 1);
112447270Sdonn       }
112547270Sdonn 
112647270Sdonn       /* Now the opcode; be careful about word order here! */
112747270Sdonn       if (FITS_IN_UNSIGNED_BYTE(t->base_opcode)) {
112847270Sdonn 	FRAG_APPEND_1_CHAR (t->base_opcode);
112947270Sdonn       } else if (FITS_IN_UNSIGNED_WORD(t->base_opcode)) {
113047270Sdonn 	p =  frag_more (2);
113147270Sdonn 	/* put out high byte first: can't use md_number_to_chars! */
113247270Sdonn 	*p++ = (t->base_opcode >> 8) & 0xff;
113347270Sdonn 	*p = t->base_opcode & 0xff;
113447270Sdonn       } else {			/* opcode is either 3 or 4 bytes */
113547270Sdonn 	if (t->base_opcode & 0xff000000) {
113647270Sdonn 	  p = frag_more (4);
113747270Sdonn 	  *p++ = (t->base_opcode >> 24) & 0xff;
113847270Sdonn 	} else p = frag_more (3);
113947270Sdonn 	*p++ = (t->base_opcode >> 16) & 0xff;
114047270Sdonn 	*p++ = (t->base_opcode >>  8) & 0xff;
114147270Sdonn 	*p =   (t->base_opcode      ) & 0xff;
114247270Sdonn       }
114347270Sdonn 
114447270Sdonn       /* Now the modrm byte and base index byte (if present). */
114547270Sdonn       if (t->opcode_modifier & Modrm) {
114647270Sdonn 	p =  frag_more (1);
114747270Sdonn 	/* md_number_to_chars (p, i.rm, 1); */
114847270Sdonn 	md_number_to_chars (p, (i.rm.regmem<<0 | i.rm.reg<<3 | i.rm.mode<<6), 1);
114947270Sdonn 	/* If i.rm.regmem == ESP (4) && i.rm.mode != Mode 3 (Register mode)
115047270Sdonn 	   ==> need second modrm byte. */
115147270Sdonn 	if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING && i.rm.mode != 3) {
115247270Sdonn 	  p =  frag_more (1);
115347270Sdonn 	  /* md_number_to_chars (p, i.bi, 1); */
115447270Sdonn 	  md_number_to_chars (p,(i.bi.base<<0 | i.bi.index<<3 | i.bi.scale<<6), 1);
115547270Sdonn 	}
115647270Sdonn       }
115747270Sdonn 
115847270Sdonn       if (i.disp_operands) {
115947270Sdonn 	register int n;
116047270Sdonn 
116147270Sdonn 	for (n = 0; n < i.operands; n++) {
116247270Sdonn 	  if (i.disps[n]) {
116347270Sdonn 	    if (i.disps[n]->X_seg == SEG_ABSOLUTE) {
116447270Sdonn 	      if (i.types[n] & (Disp8|Abs8)) {
116547270Sdonn 		p =  frag_more (1);
116647270Sdonn 		md_number_to_chars (p, i.disps[n]->X_add_number, 1);
116747270Sdonn 	      } else if (i.types[n] & (Disp16|Abs16)) {
116847270Sdonn 		p =  frag_more (2);
116947270Sdonn 		md_number_to_chars (p, i.disps[n]->X_add_number, 2);
117047270Sdonn 	      } else {		/* Disp32|Abs32 */
117147270Sdonn 		p =  frag_more (4);
117247270Sdonn 		md_number_to_chars (p, i.disps[n]->X_add_number, 4);
117347270Sdonn 	      }
117447270Sdonn 	    } else {			/* not SEG_ABSOLUTE */
117547270Sdonn 	      /* need a 32-bit fixup (don't support 8bit non-absolute disps) */
117647270Sdonn 	      p =  frag_more (4);
117747270Sdonn 	      fix_new (frag_now, p -  frag_now->fr_literal, 4,
117847270Sdonn 		       i.disps[n]->X_add_symbol, i.disps[n]->X_subtract_symbol,
117947270Sdonn 		       i.disps[n]->X_add_number, 0);
118047270Sdonn 	    }
118147270Sdonn 	  }
118247270Sdonn 	}
118347270Sdonn       }				/* end displacement output */
118447270Sdonn 
118547270Sdonn       /* output immediate */
118647270Sdonn       if (i.imm_operands) {
118747270Sdonn 	register int n;
118847270Sdonn 
118947270Sdonn 	for (n = 0; n < i.operands; n++) {
119047270Sdonn 	  if (i.imms[n]) {
119147270Sdonn 	    if (i.imms[n]->X_seg == SEG_ABSOLUTE) {
119247270Sdonn 	      if (i.types[n] & (Imm8|Imm8S)) {
119347270Sdonn 		p =  frag_more (1);
119447270Sdonn 		md_number_to_chars (p, i.imms[n]->X_add_number, 1);
119547270Sdonn 	      } else if (i.types[n] & Imm16) {
119647270Sdonn 		p =  frag_more (2);
119747270Sdonn 		md_number_to_chars (p, i.imms[n]->X_add_number, 2);
119847270Sdonn 	      } else {
119947270Sdonn 		p =  frag_more (4);
120047270Sdonn 		md_number_to_chars (p, i.imms[n]->X_add_number, 4);
120147270Sdonn 	      }
120247270Sdonn 	    } else {			/* not SEG_ABSOLUTE */
120347270Sdonn 	      /* need a 32-bit fixup (don't support 8bit non-absolute ims) */
120447270Sdonn 	      /* try to support other sizes ... */
120547270Sdonn 	      int size;
120647270Sdonn 	      if (i.types[n] & (Imm8|Imm8S))
120747270Sdonn 		size = 1;
120847270Sdonn 	      else if (i.types[n] & Imm16)
120947270Sdonn 		size = 2;
121047270Sdonn 	      else
121147270Sdonn 		size = 4;
121247270Sdonn 	      p = frag_more (size);
121347270Sdonn 	      fix_new (frag_now, p - frag_now->fr_literal, size,
121447270Sdonn 		       i.imms[n]->X_add_symbol, i.imms[n]->X_subtract_symbol,
121547270Sdonn 		       i.imms[n]->X_add_number, 0);
121647270Sdonn 	    }
121747270Sdonn 	  }
121847270Sdonn 	}
121947270Sdonn       }				/* end immediate output */
122047270Sdonn     }
122147270Sdonn 
122247270Sdonn #ifdef DEBUG386
122347270Sdonn     if (flagseen ['D']) {
122447270Sdonn       pi (line, &i);
122547270Sdonn     }
122647270Sdonn #endif /* DEBUG386 */
122747270Sdonn 
122847270Sdonn   }
122947270Sdonn   return;
123047270Sdonn }
123147270Sdonn 
123247270Sdonn /* Parse OPERAND_STRING into the i386_insn structure I.  Returns non-zero
123347270Sdonn    on error. */
123447270Sdonn 
i386_operand(operand_string)123547270Sdonn int i386_operand (operand_string)
123647270Sdonn      char *operand_string;
123747270Sdonn {
123847270Sdonn   register char *op_string = operand_string;
123947270Sdonn 
124047270Sdonn   /* Address of '\0' at end of operand_string. */
124147270Sdonn   char * end_of_operand_string = operand_string + strlen(operand_string);
124247270Sdonn 
124347270Sdonn   /* Start and end of displacement string expression (if found). */
124447270Sdonn   char * displacement_string_start = 0;
124547270Sdonn   char * displacement_string_end;
124647270Sdonn 
124747270Sdonn   /* We check for an absolute prefix (differentiating,
124847270Sdonn      for example, 'jmp pc_relative_label' from 'jmp *absolute_label'. */
124947270Sdonn   if (*op_string == ABSOLUTE_PREFIX) {
125047270Sdonn     op_string++;
125147270Sdonn     i.types[this_operand] |= JumpAbsolute;
125247270Sdonn   }
125347270Sdonn 
125447270Sdonn   /* Check if operand is a register. */
125547270Sdonn   if (*op_string == REGISTER_PREFIX) {
125647270Sdonn     register reg_entry * r;
125747270Sdonn     if (! (r = parse_register (op_string))) {
125847270Sdonn       as_bad ("bad register name ('%s')", op_string);
125947270Sdonn       return 0;
126047270Sdonn     }
126147270Sdonn     /* Check for segment override, rather than segment register by
126247270Sdonn        searching for ':' after %<x>s where <x> = s, c, d, e, f, g. */
126347270Sdonn     if ((r->reg_type & (SReg2|SReg3)) && op_string[3] == ':') {
126447270Sdonn       switch (r->reg_num) {
126547270Sdonn       case 0:
126647270Sdonn 	i.seg = &es; break;
126747270Sdonn       case 1:
126847270Sdonn 	i.seg = &cs; break;
126947270Sdonn       case 2:
127047270Sdonn 	i.seg = &ss; break;
127147270Sdonn       case 3:
127247270Sdonn 	i.seg = &ds; break;
127347270Sdonn       case 4:
127447270Sdonn 	i.seg = &fs; break;
127547270Sdonn       case 5:
127647270Sdonn 	i.seg = &gs; break;
127747270Sdonn       }
127847270Sdonn       op_string += 4;		/* skip % <x> s : */
127947270Sdonn       operand_string = op_string; /* Pretend given string starts here. */
128047270Sdonn       if (!is_digit_char(*op_string) && !is_identifier_char(*op_string)
128147270Sdonn 	  && *op_string != '(' && *op_string != ABSOLUTE_PREFIX) {
128247270Sdonn 	as_bad ("bad memory operand after segment override");
128347270Sdonn 	return 0;
128447270Sdonn       }
128547270Sdonn       /* Handle case of %es:*foo. */
128647270Sdonn       if (*op_string == ABSOLUTE_PREFIX) {
128747270Sdonn 	op_string++;
128847270Sdonn 	i.types[this_operand] |= JumpAbsolute;
128947270Sdonn       }
129047270Sdonn       goto do_memory_reference;
129147270Sdonn     }
129247270Sdonn     i.types[this_operand] |= r->reg_type;
129347270Sdonn     i.regs[this_operand] = r;
129447270Sdonn     i.reg_operands++;
129547270Sdonn   } else if (*op_string == IMMEDIATE_PREFIX) { /* ... or an immediate */
129647270Sdonn     char * save_input_line_pointer;
129747270Sdonn     register expressionS *exp;
129847270Sdonn     segT exp_seg;
129947270Sdonn     if (i.imm_operands == MAX_IMMEDIATE_OPERANDS) {
130047270Sdonn       as_bad ("only 1 or 2 immediate operands are allowed");
130147270Sdonn       return 0;
130247270Sdonn     }
130347270Sdonn     exp = &im_expressions[i.imm_operands++];
130447270Sdonn     i.imms [this_operand] = exp;
130547270Sdonn     save_input_line_pointer = input_line_pointer;
130647270Sdonn     input_line_pointer = ++op_string;        /* must advance op_string! */
130747270Sdonn     exp_seg = expression (exp);
130847270Sdonn     input_line_pointer = save_input_line_pointer;
130947270Sdonn     switch (exp_seg) {
131047270Sdonn     case SEG_NONE:    /* missing or bad expr becomes absolute 0 */
131147270Sdonn       as_bad ("missing or invalid immediate expression '%s' taken as 0",
131247270Sdonn 	       operand_string);
131347270Sdonn       exp->X_seg = SEG_ABSOLUTE;
131447270Sdonn       exp->X_add_number = 0;
131547270Sdonn       exp->X_add_symbol = (symbolS *) 0;
131647270Sdonn       exp->X_subtract_symbol = (symbolS *) 0;
131747270Sdonn       i.types[this_operand] |= Imm;
131847270Sdonn       break;
131947270Sdonn     case SEG_ABSOLUTE:
132047270Sdonn       i.types[this_operand] |= SMALLEST_IMM_TYPE (exp->X_add_number);
132147270Sdonn       break;
132247270Sdonn     case SEG_TEXT: case SEG_DATA: case SEG_BSS: case SEG_UNKNOWN:
132347270Sdonn       i.types[this_operand] |= Imm32; /* this is an address ==> 32bit */
132447270Sdonn       break;
132547270Sdonn     default:
132647270Sdonn seg_unimplemented:
132747270Sdonn       as_bad ("Unimplemented segment type %d in parse_operand", exp_seg);
132847270Sdonn       return 0;
132947270Sdonn     }
133047270Sdonn     /* shorten this type of this operand if the instruction wants
133147270Sdonn      * fewer bits than are present in the immediate.  The bit field
133247270Sdonn      * code can put out 'andb $0xffffff, %al', for example.   pace
133347270Sdonn      * also 'movw $foo,(%eax)'
133447270Sdonn      */
133547270Sdonn     switch (i.suffix) {
133647270Sdonn     case WORD_OPCODE_SUFFIX:
133747270Sdonn       i.types[this_operand] |= Imm16;
133847270Sdonn       break;
133947270Sdonn     case BYTE_OPCODE_SUFFIX:
134047270Sdonn       i.types[this_operand] |= Imm16 | Imm8 | Imm8S;
134147270Sdonn       break;
134247270Sdonn     }
134347270Sdonn   } else if (is_digit_char(*op_string) || is_identifier_char(*op_string)
134447270Sdonn 	     || *op_string == '(') {
134547270Sdonn     /* This is a memory reference of some sort. */
134647270Sdonn     register char * base_string;
134747270Sdonn     uint found_base_index_form;
134847270Sdonn 
134947270Sdonn   do_memory_reference:
135047270Sdonn     if (i.mem_operands == MAX_MEMORY_OPERANDS) {
135147270Sdonn       as_bad ("more than 1 memory reference in instruction");
135247270Sdonn       return 0;
135347270Sdonn     }
135447270Sdonn     i.mem_operands++;
135547270Sdonn 
135647270Sdonn     /* Determine type of memory operand from opcode_suffix;
135747270Sdonn        no opcode suffix implies general memory references. */
135847270Sdonn     switch (i.suffix) {
135947270Sdonn     case BYTE_OPCODE_SUFFIX:
136047270Sdonn       i.types[this_operand] |= Mem8;
136147270Sdonn       break;
136247270Sdonn     case WORD_OPCODE_SUFFIX:
136347270Sdonn       i.types[this_operand] |= Mem16;
136447270Sdonn       break;
136547270Sdonn     case DWORD_OPCODE_SUFFIX:
136647270Sdonn     default:
136747270Sdonn       i.types[this_operand] |= Mem32;
136847270Sdonn     }
136947270Sdonn 
137047270Sdonn     /*  Check for base index form.  We detect the base index form by
137147270Sdonn 	looking for an ')' at the end of the operand, searching
137247270Sdonn 	for the '(' matching it, and finding a REGISTER_PREFIX or ','
137347270Sdonn 	after it. */
137447270Sdonn     base_string = end_of_operand_string - 1;
137547270Sdonn     found_base_index_form = FALSE;
137647270Sdonn     if (*base_string == ')') {
137747270Sdonn       uint parens_balenced = 1;
137847270Sdonn       /* We've already checked that the number of left & right ()'s are equal,
137947270Sdonn 	 so this loop will not be infinite. */
138047270Sdonn       do {
138147270Sdonn 	base_string--;
138247270Sdonn 	if (*base_string == ')') parens_balenced++;
138347270Sdonn 	if (*base_string == '(') parens_balenced--;
138447270Sdonn       } while (parens_balenced);
138547270Sdonn       base_string++;			/* Skip past '('. */
138647270Sdonn       if (*base_string == REGISTER_PREFIX || *base_string == ',')
138747270Sdonn 	found_base_index_form = TRUE;
138847270Sdonn     }
138947270Sdonn 
139047270Sdonn     /* If we can't parse a base index register expression, we've found
139147270Sdonn        a pure displacement expression.  We set up displacement_string_start
139247270Sdonn        and displacement_string_end for the code below. */
139347270Sdonn     if (! found_base_index_form) {
139447270Sdonn 	displacement_string_start = op_string;
139547270Sdonn 	displacement_string_end = end_of_operand_string;
139647270Sdonn     } else {
139747270Sdonn       char *base_reg_name, *index_reg_name, *num_string;
139847270Sdonn       int num;
139947270Sdonn 
140047270Sdonn       i.types[this_operand] |= BaseIndex;
140147270Sdonn 
140247270Sdonn       /* If there is a displacement set-up for it to be parsed later. */
140347270Sdonn       if (base_string != op_string + 1) {
140447270Sdonn 	displacement_string_start = op_string;
140547270Sdonn 	displacement_string_end = base_string - 1;
140647270Sdonn       }
140747270Sdonn 
140847270Sdonn       /* Find base register (if any). */
140947270Sdonn       if (*base_string != ',') {
141047270Sdonn 	base_reg_name = base_string++;
141147270Sdonn 	/* skip past register name & parse it */
141247270Sdonn 	while (isalpha(*base_string)) base_string++;
141347270Sdonn 	if (base_string == base_reg_name+1) {
141447270Sdonn 	  as_bad ("can't find base register name after '(%c'",
141547270Sdonn 		   REGISTER_PREFIX);
141647270Sdonn 	  return 0;
141747270Sdonn 	}
141847270Sdonn 	END_STRING_AND_SAVE (base_string);
141947270Sdonn 	if (! (i.base_reg = parse_register (base_reg_name))) {
142047270Sdonn 	  as_bad ("bad base register name ('%s')", base_reg_name);
142147270Sdonn 	  return 0;
142247270Sdonn 	}
142347270Sdonn 	RESTORE_END_STRING (base_string);
142447270Sdonn       }
142547270Sdonn 
142647270Sdonn       /* Now check seperator; must be ',' ==> index reg
142747270Sdonn 	 OR num ==> no index reg. just scale factor
142847270Sdonn 	 OR ')' ==> end. (scale factor = 1) */
142947270Sdonn       if (*base_string != ',' && *base_string != ')') {
143047270Sdonn 	as_bad ("expecting ',' or ')' after base register in `%s'",
143147270Sdonn 		 operand_string);
143247270Sdonn 	return 0;
143347270Sdonn       }
143447270Sdonn 
143547270Sdonn       /* There may index reg here; and there may be a scale factor. */
143647270Sdonn       if (*base_string == ',' && *(base_string+1) == REGISTER_PREFIX) {
143747270Sdonn 	index_reg_name = ++base_string;
143847270Sdonn 	while (isalpha(*++base_string));
143947270Sdonn 	END_STRING_AND_SAVE (base_string);
144047270Sdonn 	if (! (i.index_reg = parse_register(index_reg_name))) {
144147270Sdonn 	  as_bad ("bad index register name ('%s')", index_reg_name);
144247270Sdonn 	  return 0;
144347270Sdonn 	}
144447270Sdonn 	RESTORE_END_STRING (base_string);
144547270Sdonn       }
144647270Sdonn 
144747270Sdonn       /* Check for scale factor. */
144847270Sdonn       if (*base_string == ',' && isdigit(*(base_string+1))) {
144947270Sdonn 	num_string = ++base_string;
145047270Sdonn 	while (is_digit_char(*base_string)) base_string++;
145147270Sdonn 	if (base_string == num_string) {
145247270Sdonn 	  as_bad ("can't find a scale factor after ','");
145347270Sdonn 	  return 0;
145447270Sdonn 	}
145547270Sdonn 	END_STRING_AND_SAVE (base_string);
145647270Sdonn 	/* We've got a scale factor. */
145747270Sdonn 	if (! sscanf (num_string, "%d", &num)) {
145847270Sdonn 	  as_bad ("can't parse scale factor from '%s'", num_string);
145947270Sdonn 	  return 0;
146047270Sdonn 	}
146147270Sdonn 	RESTORE_END_STRING (base_string);
146247270Sdonn 	switch (num) {	/* must be 1 digit scale */
146347270Sdonn 	case 1: i.log2_scale_factor = 0; break;
146447270Sdonn 	case 2: i.log2_scale_factor = 1; break;
146547270Sdonn 	case 4: i.log2_scale_factor = 2; break;
146647270Sdonn 	case 8: i.log2_scale_factor = 3; break;
146747270Sdonn 	default:
146847270Sdonn 	  as_bad ("expecting scale factor of 1, 2, 4, 8; got %d", num);
146947270Sdonn 	  return 0;
147047270Sdonn 	}
147147270Sdonn       } else {
147247270Sdonn 	if (! i.index_reg && *base_string == ',') {
147347270Sdonn 	  as_bad ("expecting index register or scale factor after ','; got '%c'",
147447270Sdonn 		   *(base_string+1));
147547270Sdonn 	  return 0;
147647270Sdonn 	}
147747270Sdonn       }
147847270Sdonn     }
147947270Sdonn 
148047270Sdonn     /* If there's an expression begining the operand, parse it,
148147270Sdonn        assuming displacement_string_start and displacement_string_end
148247270Sdonn        are meaningful. */
148347270Sdonn     if (displacement_string_start) {
148447270Sdonn       register expressionS * exp;
148547270Sdonn       segT exp_seg;
148647270Sdonn       char * save_input_line_pointer;
148747270Sdonn       exp = &disp_expressions[i.disp_operands];
148847270Sdonn       i.disps [this_operand] = exp;
148947270Sdonn       i.disp_operands++;
149047270Sdonn       save_input_line_pointer = input_line_pointer;
149147270Sdonn       input_line_pointer = displacement_string_start;
149247270Sdonn       END_STRING_AND_SAVE (displacement_string_end);
149347270Sdonn       exp_seg = expression (exp);
149447270Sdonn       if(*input_line_pointer)
149547270Sdonn 	as_bad("Ignoring junk '%s' after expression",input_line_pointer);
149647270Sdonn       RESTORE_END_STRING (displacement_string_end);
149747270Sdonn       input_line_pointer = save_input_line_pointer;
149847270Sdonn       switch (exp_seg) {
149947270Sdonn       case SEG_NONE:
150047270Sdonn 	/* missing expr becomes absolute 0 */
150147270Sdonn 	as_bad ("missing or invalid displacement '%s' taken as 0",
150247270Sdonn 		 operand_string);
150347270Sdonn 	i.types[this_operand] |= (Disp|Abs);
150447270Sdonn 	exp->X_seg = SEG_ABSOLUTE;
150547270Sdonn 	exp->X_add_number = 0;
150647270Sdonn 	exp->X_add_symbol = (symbolS *) 0;
150747270Sdonn 	exp->X_subtract_symbol = (symbolS *) 0;
150847270Sdonn 	break;
150947270Sdonn       case SEG_ABSOLUTE:
151047270Sdonn 	i.types[this_operand] |= SMALLEST_DISP_TYPE (exp->X_add_number);
151147270Sdonn 	break;
151247270Sdonn       case SEG_TEXT: case SEG_DATA: case SEG_BSS:
151347270Sdonn       case SEG_UNKNOWN:	/* must be 32 bit displacement (i.e. address) */
151447270Sdonn 	i.types[this_operand] |= Disp32;
151547270Sdonn 	break;
151647270Sdonn       default:
151747270Sdonn 	goto seg_unimplemented;
151847270Sdonn       }
151947270Sdonn     }
152047270Sdonn 
152147270Sdonn     /* Make sure the memory operand we've been dealt is valid. */
152247270Sdonn     if (i.base_reg && i.index_reg &&
152347270Sdonn 	! (i.base_reg->reg_type & i.index_reg->reg_type & Reg)) {
152447270Sdonn       as_bad ("register size mismatch in (base,index,scale) expression");
152547270Sdonn       return 0;
152647270Sdonn     }
152747270Sdonn     if ((i.base_reg && (i.base_reg->reg_type & Reg32) == 0) ||
152847270Sdonn 	(i.index_reg && (i.index_reg->reg_type & Reg32) == 0)) {
152947270Sdonn       as_bad ("base/index register must be 32 bit register");
153047270Sdonn       return 0;
153147270Sdonn     }
153247270Sdonn     if (i.index_reg && i.index_reg == esp) {
153347270Sdonn       as_bad ("%s may not be used as an index register", esp->reg_name);
153447270Sdonn       return 0;
153547270Sdonn     }
153647270Sdonn   } else {			/* it's not a memory operand; argh! */
153747270Sdonn     as_bad ("invalid char %s begining %s operand '%s'",
153847270Sdonn 	     output_invalid(*op_string), ordinal_names[this_operand],
153947270Sdonn 	     op_string);
154047270Sdonn     return 0;
154147270Sdonn   }
154247270Sdonn   return 1;			/* normal return */
154347270Sdonn }
154447270Sdonn 
154547270Sdonn /*
154647270Sdonn  *			md_estimate_size_before_relax()
154747270Sdonn  *
154847270Sdonn  * Called just before relax().
154947270Sdonn  * Any symbol that is now undefined will not become defined.
155047270Sdonn  * Return the correct fr_subtype in the frag.
155147270Sdonn  * Return the initial "guess for fr_var" to caller.
155247270Sdonn  * The guess for fr_var is ACTUALLY the growth beyond fr_fix.
155347270Sdonn  * Whatever we do to grow fr_fix or fr_var contributes to our returned value.
155447270Sdonn  * Although it may not be explicit in the frag, pretend fr_var starts with a
155547270Sdonn  * 0 value.
155647270Sdonn  */
155747270Sdonn int
md_estimate_size_before_relax(fragP,segment_type)155847270Sdonn md_estimate_size_before_relax (fragP, segment_type)
155947270Sdonn      register fragS *	fragP;
156047270Sdonn      register int	segment_type; /* N_DATA or N_TEXT. */
156147270Sdonn {
156247270Sdonn   register uchar *	opcode;
156347270Sdonn   register int		old_fr_fix;
156447270Sdonn 
156547270Sdonn   old_fr_fix = fragP -> fr_fix;
156647270Sdonn   opcode = (uchar *) fragP -> fr_opcode;
156747270Sdonn   /* We've already got fragP->fr_subtype right;  all we have to do is check
156847270Sdonn      for un-relaxable symbols. */
156947270Sdonn   if ((fragP -> fr_symbol -> sy_type & N_TYPE) != segment_type) {
157047270Sdonn     /* symbol is undefined in this segment */
157147270Sdonn     switch (opcode[0]) {
157247270Sdonn     case JUMP_PC_RELATIVE:	/* make jmp (0xeb) a dword displacement jump */
157347270Sdonn       opcode[0] = 0xe9;		/* dword disp jmp */
157447270Sdonn       fragP -> fr_fix += 4;
157547270Sdonn       fix_new (fragP, old_fr_fix, 4,
157647270Sdonn 	       fragP -> fr_symbol,
157747270Sdonn 	       (symbolS *) 0,
157847270Sdonn 	       fragP -> fr_offset, 1);
157947270Sdonn       break;
158047270Sdonn 
158147270Sdonn     default:
158247270Sdonn       /* This changes the byte-displacement jump 0x7N -->
158347270Sdonn 	 the dword-displacement jump 0x0f8N */
158447270Sdonn       opcode[1] = opcode[0] + 0x10;
158547270Sdonn       opcode[0] = TWO_BYTE_OPCODE_ESCAPE;		/* two-byte escape */
158647270Sdonn       fragP -> fr_fix += 1 + 4;	/* we've added an opcode byte */
158747270Sdonn       fix_new (fragP, old_fr_fix + 1, 4,
158847270Sdonn 	       fragP -> fr_symbol,
158947270Sdonn 	       (symbolS *) 0,
159047270Sdonn 	       fragP -> fr_offset, 1);
159147270Sdonn       break;
159247270Sdonn     }
159347270Sdonn     frag_wane (fragP);
159447270Sdonn   }
159547270Sdonn   return (fragP -> fr_var + fragP -> fr_fix - old_fr_fix);
159647270Sdonn }				/* md_estimate_size_before_relax() */
159747270Sdonn 
159847270Sdonn /*
159947270Sdonn  *			md_convert_frag();
160047270Sdonn  *
160147270Sdonn  * Called after relax() is finished.
160247270Sdonn  * In:	Address of frag.
160347270Sdonn  *	fr_type == rs_machine_dependent.
160447270Sdonn  *	fr_subtype is what the address relaxed to.
160547270Sdonn  *
160647270Sdonn  * Out:	Any fixSs and constants are set up.
160747270Sdonn  *	Caller will turn frag into a ".space 0".
160847270Sdonn  */
160947270Sdonn void
md_convert_frag(fragP)161047270Sdonn md_convert_frag (fragP)
161147270Sdonn      register fragS *	fragP;
161247270Sdonn {
161347270Sdonn   register uchar * opcode;
161447270Sdonn   uchar * where_to_put_displacement;
161547270Sdonn   uint target_address, opcode_address;
161647270Sdonn   uint extension;
161747270Sdonn   int displacement_from_opcode_start;
161847270Sdonn 
161947270Sdonn   opcode = (uchar *) fragP -> fr_opcode;
162047270Sdonn 
162147270Sdonn   /* Address we want to reach in file space. */
162247270Sdonn   target_address = fragP->fr_symbol->sy_value + fragP->fr_offset;
162347270Sdonn 
162447270Sdonn   /* Address opcode resides at in file space. */
162547270Sdonn   opcode_address = fragP->fr_address + fragP->fr_fix;
162647270Sdonn 
162747270Sdonn   /* Displacement from opcode start to fill into instruction. */
162847270Sdonn   displacement_from_opcode_start = target_address - opcode_address;
162947270Sdonn 
163047270Sdonn   switch (fragP->fr_subtype) {
163147270Sdonn   case ENCODE_RELAX_STATE (COND_JUMP, BYTE):
163247270Sdonn   case ENCODE_RELAX_STATE (UNCOND_JUMP, BYTE):
163347270Sdonn     /* don't have to change opcode */
163447270Sdonn     extension = 1;		/* 1 opcode + 1 displacement */
163547270Sdonn     where_to_put_displacement = &opcode[1];
163647270Sdonn     break;
163747270Sdonn 
163847270Sdonn   case ENCODE_RELAX_STATE (COND_JUMP, WORD):
163947270Sdonn     opcode[1] = TWO_BYTE_OPCODE_ESCAPE;
164047270Sdonn     opcode[2] = opcode[0] + 0x10;
164147270Sdonn     opcode[0] = WORD_PREFIX_OPCODE;
164247270Sdonn     extension = 4;		/* 3 opcode + 2 displacement */
164347270Sdonn     where_to_put_displacement = &opcode[3];
164447270Sdonn     break;
164547270Sdonn 
164647270Sdonn   case ENCODE_RELAX_STATE (UNCOND_JUMP, WORD):
164747270Sdonn     opcode[1] = 0xe9;
164847270Sdonn     opcode[0] = WORD_PREFIX_OPCODE;
164947270Sdonn     extension = 3;		/* 2 opcode + 2 displacement */
165047270Sdonn     where_to_put_displacement = &opcode[2];
165147270Sdonn     break;
165247270Sdonn 
165347270Sdonn   case ENCODE_RELAX_STATE (COND_JUMP, DWORD):
165447270Sdonn     opcode[1] = opcode[0] + 0x10;
165547270Sdonn     opcode[0] = TWO_BYTE_OPCODE_ESCAPE;
165647270Sdonn     extension = 5;		/* 2 opcode + 4 displacement */
165747270Sdonn     where_to_put_displacement = &opcode[2];
165847270Sdonn     break;
165947270Sdonn 
166047270Sdonn   case ENCODE_RELAX_STATE (UNCOND_JUMP, DWORD):
166147270Sdonn     opcode[0] = 0xe9;
166247270Sdonn     extension = 4;		/* 1 opcode + 4 displacement */
166347270Sdonn     where_to_put_displacement = &opcode[1];
166447270Sdonn     break;
166547270Sdonn 
166647270Sdonn   default:
166747270Sdonn     BAD_CASE(fragP -> fr_subtype);
166847270Sdonn     break;
166947270Sdonn   }
167047270Sdonn   /* now put displacement after opcode */
167147270Sdonn   md_number_to_chars (where_to_put_displacement,
167247270Sdonn 		      displacement_from_opcode_start - extension,
167347270Sdonn 		      SIZE_FROM_RELAX_STATE (fragP->fr_subtype));
167447270Sdonn   fragP -> fr_fix += extension;
167547270Sdonn }
167647270Sdonn 
167747270Sdonn 
167847270Sdonn int md_short_jump_size = 2;	/* size of byte displacement jmp */
167947270Sdonn int md_long_jump_size  = 5;	/* size of dword displacement jmp */
168047270Sdonn 
md_create_short_jump(ptr,from_addr,to_addr)168147270Sdonn void md_create_short_jump(ptr, from_addr, to_addr)
168247270Sdonn      char	*ptr;
168347270Sdonn      long	from_addr, to_addr;
168447270Sdonn {
168547270Sdonn   long offset;
168647270Sdonn 
168747270Sdonn   offset = to_addr - (from_addr + 2);
168847270Sdonn   md_number_to_chars (ptr, (long) 0xeb, 1); /* opcode for byte-disp jump */
168947270Sdonn   md_number_to_chars (ptr + 1, offset, 1);
169047270Sdonn }
169147270Sdonn 
md_create_long_jump(ptr,from_addr,to_addr,frag,to_symbol)169247270Sdonn void md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
169347270Sdonn      char	*ptr;
169447270Sdonn      long	from_addr, to_addr;
169547270Sdonn      fragS	*frag;
169647270Sdonn      symbolS	*to_symbol;
169747270Sdonn {
169847270Sdonn   long offset;
169947270Sdonn 
170047270Sdonn   if (flagseen['m']) {
170147270Sdonn     offset = to_addr - to_symbol->sy_value;
170247270Sdonn     md_number_to_chars (ptr, 0xe9, 1); /* opcode for long jmp */
170347270Sdonn     md_number_to_chars (ptr + 1, offset, 4);
170447270Sdonn     fix_new (frag, (ptr+1) - frag->fr_literal, 4,
170547270Sdonn 	     to_symbol, (symbolS *) 0, (long int) 0, 0);
170647270Sdonn   } else {
170747270Sdonn     offset = to_addr - (from_addr + 5);
170847270Sdonn     md_number_to_chars(ptr, (long) 0xe9, 1);
170947270Sdonn     md_number_to_chars(ptr + 1, offset, 4);
171047270Sdonn   }
171147270Sdonn }
171247270Sdonn 
171347270Sdonn int
md_parse_option(argP,cntP,vecP)171447270Sdonn md_parse_option(argP,cntP,vecP)
171547270Sdonn char **argP;
171647270Sdonn int *cntP;
171747270Sdonn char ***vecP;
171847270Sdonn {
171947270Sdonn 	return 1;
172047270Sdonn }
172147270Sdonn 
172247270Sdonn void				/* Knows about order of bytes in address. */
md_number_to_chars(con,value,nbytes)172347270Sdonn md_number_to_chars (con, value, nbytes)
172447270Sdonn      char	con [];	/* Return 'nbytes' of chars here. */
172547270Sdonn      long int	value;		/* The value of the bits. */
172647270Sdonn      int	nbytes;		/* Number of bytes in the output. */
172747270Sdonn {
172847270Sdonn   register char * p = con;
172947270Sdonn 
173047270Sdonn   switch (nbytes) {
173147270Sdonn   case 1:
173247270Sdonn     p[0] = value & 0xff;
173347270Sdonn     break;
173447270Sdonn   case 2:
173547270Sdonn     p[0] = value & 0xff;
173647270Sdonn     p[1] = (value >> 8) & 0xff;
173747270Sdonn     break;
173847270Sdonn   case 4:
173947270Sdonn     p[0] = value & 0xff;
174047270Sdonn     p[1] = (value>>8) & 0xff;
174147270Sdonn     p[2] = (value>>16) & 0xff;
174247270Sdonn     p[3] = (value>>24) & 0xff;
174347270Sdonn     break;
174447270Sdonn   default:
174547270Sdonn     BAD_CASE (nbytes);
174647270Sdonn   }
174747270Sdonn }
174847270Sdonn 
174947270Sdonn void				/* Knows about order of bytes in address. */
md_number_to_disp(con,value,nbytes)175047270Sdonn md_number_to_disp (con, value, nbytes)
175147270Sdonn      char	con [];	/* Return 'nbytes' of chars here. */
175247270Sdonn      long int	value;		/* The value of the bits. */
175347270Sdonn      int	nbytes;		/* Number of bytes in the output. */
175447270Sdonn {
175547270Sdonn   char * answer = alloca (nbytes);
175647270Sdonn   register char * p = answer;
175747270Sdonn 
175847270Sdonn   switch (nbytes) {
175947270Sdonn   case 1:
176047270Sdonn     *p = value;
176147270Sdonn     break;
176247270Sdonn   case 2:
176347270Sdonn     *p++   = value;
176447270Sdonn     *p = (value>>8);
176547270Sdonn     break;
176647270Sdonn   case 4:
176747270Sdonn     *p++ = value;
176847270Sdonn     *p++ = (value>>8);
176947270Sdonn     *p++ = (value>>16);
177047270Sdonn     *p = (value>>24);
177147270Sdonn     break;
177247270Sdonn   default:
177347270Sdonn     BAD_CASE (nbytes);
177447270Sdonn   }
177547270Sdonn   bcopy (answer, con, nbytes);
177647270Sdonn }
177747270Sdonn 
177847270Sdonn void				/* Knows about order of bytes in address. */
md_number_to_imm(con,value,nbytes)177947270Sdonn md_number_to_imm (con, value, nbytes)
178047270Sdonn      char	con [];	/* Return 'nbytes' of chars here. */
178147270Sdonn      long int	value;		/* The value of the bits. */
178247270Sdonn      int	nbytes;		/* Number of bytes in the output. */
178347270Sdonn {
178447270Sdonn   char * answer = alloca (nbytes);
178547270Sdonn   register char * p = answer;
178647270Sdonn 
178747270Sdonn   switch (nbytes) {
178847270Sdonn   case 1:
178947270Sdonn     *p = value;
179047270Sdonn     break;
179147270Sdonn   case 2:
179247270Sdonn     *p++   = value;
179347270Sdonn     *p = (value>>8);
179447270Sdonn     break;
179547270Sdonn   case 4:
179647270Sdonn     *p++ = value;
179747270Sdonn     *p++ = (value>>8);
179847270Sdonn     *p++ = (value>>16);
179947270Sdonn     *p = (value>>24);
180047270Sdonn     break;
180147270Sdonn   default:
180247270Sdonn     BAD_CASE (nbytes);
180347270Sdonn   }
180447270Sdonn   bcopy (answer, con, nbytes);
180547270Sdonn }
180647270Sdonn 
180747270Sdonn void				/* Knows about order of bytes in address. */
md_number_to_field(con,value,nbytes)180847270Sdonn md_number_to_field (con, value, nbytes)
180947270Sdonn      char	con [];	/* Return 'nbytes' of chars here. */
181047270Sdonn      long int	value;		/* The value of the bits. */
181147270Sdonn      int	nbytes;		/* Number of bytes in the output. */
181247270Sdonn {
181347270Sdonn   char * answer = alloca (nbytes);
181447270Sdonn   register char * p = answer;
181547270Sdonn 
181647270Sdonn   switch (nbytes) {
181747270Sdonn   case 1:
181847270Sdonn     *p = value;
181947270Sdonn     break;
182047270Sdonn   case 2:
182147270Sdonn     *p++   = value;
182247270Sdonn     *p = (value>>8);
182347270Sdonn     break;
182447270Sdonn   case 4:
182547270Sdonn     *p++ = value;
182647270Sdonn     *p++ = (value>>8);
182747270Sdonn     *p++ = (value>>16);
182847270Sdonn     *p = (value>>24);
182947270Sdonn     break;
183047270Sdonn   default:
183147270Sdonn     BAD_CASE (nbytes);
183247270Sdonn   }
183347270Sdonn   bcopy (answer, con, nbytes);
183447270Sdonn }
183547270Sdonn 
183647270Sdonn long int			/* Knows about the byte order in a word. */
md_chars_to_number(con,nbytes)183747270Sdonn md_chars_to_number (con, nbytes)
183847270Sdonn unsigned     char	con[];	/* Low order byte 1st. */
183947270Sdonn      int	nbytes;		/* Number of bytes in the input. */
184047270Sdonn {
184147270Sdonn   long int	retval;
184247270Sdonn   for (retval=0, con+=nbytes-1; nbytes--; con--)
184347270Sdonn     {
184447270Sdonn       retval <<= BITS_PER_CHAR;
184547270Sdonn       retval |= *con;
184647270Sdonn     }
184747270Sdonn   return retval;
184847270Sdonn }
184947270Sdonn 
md_ri_to_chars(ri_p,ri)185047270Sdonn void md_ri_to_chars(ri_p, ri)
185147270Sdonn      struct relocation_info *ri_p, ri;
185247270Sdonn {
185347270Sdonn   unsigned char the_bytes[8];
185447270Sdonn 
185547270Sdonn   /* this is easy */
185647270Sdonn   md_number_to_chars(the_bytes, ri.r_address, sizeof(ri.r_address));
185747270Sdonn   /* now the fun stuff */
185847270Sdonn   the_bytes[6] = (ri.r_symbolnum >> 16) & 0x0ff;
185947270Sdonn   the_bytes[5] = (ri.r_symbolnum >> 8) & 0x0ff;
186047270Sdonn   the_bytes[4] = ri.r_symbolnum & 0x0ff;
186147270Sdonn   the_bytes[7] = (((ri.r_extern << 3)  & 0x08) | ((ri.r_length << 1) & 0x06) |
186247270Sdonn     ((ri.r_pcrel << 0)  & 0x01)) & 0x0F;
186347270Sdonn   /* now put it back where you found it */
186447270Sdonn   bcopy (the_bytes, (char *)ri_p, sizeof(struct relocation_info));
186547270Sdonn }
186647270Sdonn 
186747270Sdonn 
186847270Sdonn #define MAX_LITTLENUMS 6
186947270Sdonn 
187047270Sdonn /* Turn the string pointed to by litP into a floating point constant of type
187147270Sdonn    type, and emit the appropriate bytes.  The number of LITTLENUMS emitted
187247270Sdonn    is stored in *sizeP .  An error message is returned, or NULL on OK.
187347270Sdonn  */
187447270Sdonn char *
md_atof(type,litP,sizeP)187547270Sdonn md_atof(type,litP,sizeP)
187647270Sdonn      char type;
187747270Sdonn      char *litP;
187847270Sdonn      int *sizeP;
187947270Sdonn {
188047270Sdonn   int	prec;
188147270Sdonn   LITTLENUM_TYPE words[MAX_LITTLENUMS];
188247270Sdonn   LITTLENUM_TYPE *wordP;
188347270Sdonn   char	*t;
188447270Sdonn   char	*atof_ieee();
188547270Sdonn 
188647270Sdonn   switch(type) {
188747270Sdonn   case 'f':
188847270Sdonn   case 'F':
188947270Sdonn     prec = 2;
189047270Sdonn     break;
189147270Sdonn 
189247270Sdonn   case 'd':
189347270Sdonn   case 'D':
189447270Sdonn     prec = 4;
189547270Sdonn     break;
189647270Sdonn 
189747270Sdonn   case 'x':
189847270Sdonn   case 'X':
189947270Sdonn     prec = 5;
190047270Sdonn     break;
190147270Sdonn 
190247270Sdonn   default:
190347270Sdonn     *sizeP=0;
190447270Sdonn     return "Bad call to md_atof ()";
190547270Sdonn   }
190647270Sdonn   t = atof_ieee (input_line_pointer,type,words);
190747270Sdonn   if(t)
190847270Sdonn     input_line_pointer=t;
190947270Sdonn 
191047270Sdonn   *sizeP = prec * sizeof(LITTLENUM_TYPE);
191147270Sdonn   /* this loops outputs the LITTLENUMs in REVERSE order; in accord with
191247270Sdonn      the bigendian 386 */
191347270Sdonn   for(wordP = words + prec - 1;prec--;) {
191447270Sdonn     md_number_to_chars (litP, (long) (*wordP--), sizeof(LITTLENUM_TYPE));
191547270Sdonn     litP += sizeof(LITTLENUM_TYPE);
191647270Sdonn   }
191747270Sdonn   return "";	/* Someone should teach Dean about null pointers */
191847270Sdonn }
191947270Sdonn 
192047270Sdonn char output_invalid_buf[8];
192147270Sdonn 
output_invalid(c)192247270Sdonn char * output_invalid (c)
192347270Sdonn      char c;
192447270Sdonn {
192547270Sdonn   if (isprint(c)) sprintf (output_invalid_buf, "'%c'", c);
192647270Sdonn   else sprintf (output_invalid_buf, "(0x%x)", c);
192747270Sdonn   return output_invalid_buf;
192847270Sdonn }
192947270Sdonn 
parse_register(reg_string)193047270Sdonn reg_entry *parse_register (reg_string)
193147270Sdonn     char *reg_string;          /* reg_string starts *before* REGISTER_PREFIX */
193247270Sdonn {
193347270Sdonn   register char *s = reg_string;
193447270Sdonn   register char *p;
193547270Sdonn   char reg_name_given[MAX_REG_NAME_SIZE];
193647270Sdonn 
193747270Sdonn   s++;				/* skip REGISTER_PREFIX */
193847270Sdonn   for (p = reg_name_given; is_register_char (*s); p++, s++) {
193947270Sdonn     *p = register_chars [*s];
194047270Sdonn     if (p >= reg_name_given + MAX_REG_NAME_SIZE)
194147270Sdonn       return (reg_entry *) 0;
194247270Sdonn   }
194347270Sdonn   *p = '\0';
194447270Sdonn   return (reg_entry *) hash_find (reg_hash, reg_name_given);
194547270Sdonn }
194647270Sdonn 
1947