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