Initial revision

This commit is contained in:
ceriel 1989-01-19 16:20:46 +00:00
parent 4c76583aba
commit 6833adfb50
6 changed files with 1146 additions and 0 deletions

16
mach/i386/as/mach0.c Normal file
View file

@ -0,0 +1,16 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#define RCSID0 "$Header$"
/*
* INTEL 80386 options
*/
#define THREE_PASS /* branch and offset optimization */
#define LISTING /* enable listing facilities */
#define RELOCATION /* generate relocation info */
#define DEBUG 2
#undef valu_t
#define valu_t long

73
mach/i386/as/mach1.c Normal file
View file

@ -0,0 +1,73 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#define RCSID1 "$Header$"
/*
* INTEL 80386 C declarations
*/
#define low6(z) (z & 077)
#define fit6(z) (low6(z) == z)
#define ufitb(z) ((unsigned)(z) <= 255)
#define IS_R8 0x100
#define IS_R32 0x200
#define IS_EXPR 0x400
#define IS_RSEG 0x800
#define is_expr(reg) ((reg)&IS_EXPR)
#define is_segreg(reg) ((reg)&IS_RSEG)
#define is_reg(reg) (((reg)&(IS_R8|IS_R32)) != 0)
#define is_acc(reg) (((reg)&(IS_R8|IS_R32)) == (reg))
struct operand {
int mod;
int rm;
int reg;
int sib; /* scale-index-base */
expr_t exp;
};
extern struct operand op_1, op_2;
#define mod_1 op_1.mod
#define mod_2 op_2.mod
#define rm_1 op_1.rm
#define rm_2 op_2.rm
#define reg_1 op_1.reg
#define reg_2 op_2.reg
#define sib_1 op_1.sib
#define sib_2 op_2.sib
#define exp_1 op_1.exp
#define exp_2 op_2.exp
#ifdef RELOCATION
extern int rel_1, rel_2;
#endif
#ifndef extern
extern char regindex_ind[8][8];
#else
/* First index is base register; second index is index register;
sp cannot be an index register.
For base and index register indirect mode, bp cannot be the
base register, but this info is not included in this array.
This can always be handled by using the base and index register with
displacement mode.
*/
char regindex_ind[8][8] = {
000, 010, 020, 030, -1, 050, 060, 070,
001, 011, 021, 031, -1, 051, 061, 071,
002, 012, 022, 032, -1, 052, 062, 072,
003, 013, 023, 033, -1, 053, 063, 073,
004, 014, 024, 034, -1, 054, 064, 074,
005, 015, 025, 035, -1, 055, 065, 075,
006, 016, 026, 036, -1, 056, 066, 076,
007, 017, 027, 037, -1, 057, 067, 077,
};
#endif
extern int address_long INIT(1), operand_long INIT(1);

47
mach/i386/as/mach2.c Normal file
View file

@ -0,0 +1,47 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#define RCSID2 "$Header$"
/*
* INTEL 80386 tokens
*/
%token <y_word> R32
%token <y_word> R16
%token <y_word> R8
%token <y_word> RSEG
%token <y_word> RSYSCR
%token <y_word> RSYSDR
%token <y_word> RSYSTR
%token <y_word> PREFIX
%token <y_word> ADDOP
%token <y_word> BITTEST
%token <y_word> BOUND
%token <y_word> CALFOP
%token <y_word> CALLOP
%token <y_word> ENTER
%token <y_word> EXTEND
%token <y_word> EXTOP
%token <y_word> EXTOP1
%token <y_word> IMUL
%token <y_word> IMULB
%token <y_word> INCOP
%token <y_word> INT
%token <y_word> IOOP
%token <y_word> JOP
%token <y_word> JOP2
%token <y_word> LEAOP
%token <y_word> LEAOP2
%token <y_word> LSHFT
%token <y_word> MOV
%token <y_word> NOOP_1
%token <y_word> NOOP_2
%token <y_word> NOTOP
%token <y_word> PUSHOP
%token <y_word> RET
%token <y_word> ROLOP
%token <y_word> SETCC
%token <y_word> TEST
%token <y_word> XCHG

279
mach/i386/as/mach3.c Normal file
View file

@ -0,0 +1,279 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#define RCSID3 "$Header$"
/*
* INTEL 80386 keywords
*
* No system registers for now ...
*/
0, R32, 0, "ax",
0, R32, 1, "cx",
0, R32, 2, "dx",
0, R32, 3, "bx",
0, R32, 4, "sp",
0, R32, 5, "bp",
0, R32, 6, "si",
0, R32, 7, "di",
0, R32, 0, "eax",
0, R32, 1, "ecx",
0, R32, 2, "edx",
0, R32, 3, "ebx",
0, R32, 4, "esp",
0, R32, 5, "ebp",
0, R32, 6, "esi",
0, R32, 7, "edi",
0, R8, 0, "al",
0, R8, 1, "cl",
0, R8, 2, "dl",
0, R8, 3, "bl",
0, R8, 4, "ah",
0, R8, 5, "ch",
0, R8, 6, "dh",
0, R8, 7, "bh",
0, RSEG, 0, "es",
0, RSEG, 1, "cs",
0, RSEG, 2, "ss",
0, RSEG, 3, "ds",
0, RSEG, 4, "fs",
0, RSEG, 5, "gs",
0, RSYSCR, 0, "cr0",
0, RSYSCR, 2, "cr2",
0, RSYSCR, 3, "cr3",
0, RSYSDR, 0, "dr0",
0, RSYSDR, 1, "dr1",
0, RSYSDR, 2, "dr2",
0, RSYSDR, 3, "dr3",
0, RSYSDR, 6, "dr6",
0, RSYSDR, 7, "dr7",
0, RSYSTR, 6, "tr6",
0, RSYSTR, 7, "tr7",
0, ADDOP, 000, "addb",
0, ADDOP, 001, "add",
0, ADDOP, 010, "orb",
0, ADDOP, 011, "or",
0, ADDOP, 020, "adcb",
0, ADDOP, 021, "adc",
0, ADDOP, 030, "sbbb",
0, ADDOP, 031, "sbb",
0, ADDOP, 040, "andb",
0, ADDOP, 041, "and",
0, ADDOP, 050, "subb",
0, ADDOP, 051, "sub",
0, ADDOP, 060, "xorb",
0, ADDOP, 061, "xor",
0, ADDOP, 070, "cmpb",
0, ADDOP, 071, "cmp",
0, BITTEST, 04, "bt",
0, BITTEST, 05, "bts",
0, BITTEST, 06, "btr",
0, BITTEST, 07, "btc",
0, CALFOP, 030+(0232<<8), "callf",
0, CALFOP, 050+(0352<<8), "jmpf",
0, CALLOP, 020+(0350<<8), "call",
0, CALLOP, 040+(0351<<8), "jmp",
0, ENTER, 0310, "enter",
0, EXTEND, 0266, "movzx",
0, EXTEND, 0276, "movsx",
0, EXTOP, 0002, "lar",
0, EXTOP, 0003, "lsl",
0, EXTOP, 0274, "bsf",
0, EXTOP, 0275, "bsr",
0, EXTOP1, 0000, "sldt",
0, EXTOP1, 0001, "sgdt",
0, EXTOP1, 0010, "str",
0, EXTOP1, 0011, "sidt",
0, EXTOP1, 0020, "lldt",
0, EXTOP1, 0021, "lgdt",
0, EXTOP1, 0030, "ltr",
0, EXTOP1, 0031, "lidt",
0, EXTOP1, 0040, "verr",
0, EXTOP1, 0041, "smsw",
0, EXTOP1, 0050, "verw",
0, EXTOP1, 0061, "lmsw",
0, IMUL, 0, "imul",
0, IMULB, 0, "imulb",
0, INCOP, 000, "incb",
0, INCOP, 001, "inc",
0, INCOP, 010, "decb",
0, INCOP, 011, "dec",
0, INT, 0, "int",
0, IOOP, 0344, "inb",
0, IOOP, 0345, "in",
0, IOOP, 0346, "outb",
0, IOOP, 0347, "out",
0, JOP, 0340, "loopne",
0, JOP, 0340, "loopnz",
0, JOP, 0341, "loope",
0, JOP, 0341, "loopz",
0, JOP, 0342, "loop",
0, JOP, 0343, "jcxz",
0, JOP, 0343, "jecxz",
0, JOP2, 0000, "jo",
0, JOP2, 0001, "jno",
0, JOP2, 0002, "jb",
0, JOP2, 0002, "jnae",
0, JOP2, 0003, "jae",
0, JOP2, 0003, "jnb",
0, JOP2, 0004, "je",
0, JOP2, 0004, "jz",
0, JOP2, 0005, "jne",
0, JOP2, 0005, "jnz",
0, JOP2, 0006, "jbe",
0, JOP2, 0006, "jna",
0, JOP2, 0007, "ja",
0, JOP2, 0007, "jnbe",
0, JOP2, 0010, "js",
0, JOP2, 0011, "jns",
0, JOP2, 0012, "jp",
0, JOP2, 0012, "jpe",
0, JOP2, 0013, "jnp",
0, JOP2, 0013, "jpo",
0, JOP2, 0014, "jl",
0, JOP2, 0014, "jnge",
0, JOP2, 0015, "jge",
0, JOP2, 0015, "jnl",
0, JOP2, 0016, "jle",
0, JOP2, 0016, "jng",
0, JOP2, 0017, "jg",
0, JOP2, 0017, "jnle",
0, LEAOP, 0142, "bound",
0, LEAOP, 0215, "lea",
0, LEAOP, 0304, "les",
0, LEAOP, 0305, "lds",
0, LEAOP2, 0262, "lss",
0, LEAOP2, 0264, "lfs",
0, LEAOP2, 0265, "lgs",
0, LSHFT, 0244, "shld",
0, LSHFT, 0254, "shrd",
0, MOV, 0, "movb",
0, MOV, 1, "mov",
0, NOOP_1, 0140, "pusha",
0, NOOP_1, 0140, "pushad",
0, NOOP_1, 0141, "popa",
0, NOOP_1, 0141, "popad",
0, NOOP_1, 0156, "outsb",
0, NOOP_1, 0157, "outs",
0, NOOP_1, 0220, "nop",
0, NOOP_1, 0230, "cbw",
0, NOOP_1, 0230, "cwde", /* same opcode as cbw! */
0, NOOP_1, 0231, "cdq", /* same opcode as cwd! */
0, NOOP_1, 0231, "cwd",
0, NOOP_1, 0233, "wait",
0, NOOP_1, 0234, "pushf",
0, NOOP_1, 0235, "popf",
0, NOOP_1, 0236, "sahf",
0, NOOP_1, 0237, "lahf",
0, NOOP_1, 0244, "movsb",
0, NOOP_1, 0245, "movs",
0, NOOP_1, 0246, "cmpsb",
0, NOOP_1, 0246, "insb",
0, NOOP_1, 0247, "cmps",
0, NOOP_1, 0247, "ins",
0, NOOP_1, 0252, "stosb",
0, NOOP_1, 0253, "stos",
0, NOOP_1, 0254, "lodsb",
0, NOOP_1, 0255, "lods",
0, NOOP_1, 0256, "scasb",
0, NOOP_1, 0257, "scas",
0, NOOP_1, 0311, "leave",
0, NOOP_1, 0316, "into",
0, NOOP_1, 0317, "iret",
0, NOOP_1, 0317, "iretd",
0, NOOP_1, 0327, "xlat",
0, NOOP_1, 0364, "hlt",
0, NOOP_1, 0365, "cmc",
0, NOOP_1, 0370, "clc",
0, NOOP_1, 0371, "stc",
0, NOOP_1, 0372, "cli",
0, NOOP_1, 0373, "sti",
0, NOOP_1, 0374, "cld",
0, NOOP_1, 0375, "std",
0, NOOP_1, 047, "daa",
0, NOOP_1, 057, "das",
0, NOOP_1, 067, "aaa",
0, NOOP_1, 077, "aas",
0, NOOP_2, 017+06<<8, "clts",
0, NOOP_2, 0324+012<<8, "aam",
0, NOOP_2, 0325+012<<8, "aad",
0, NOTOP, 020, "notb",
0, NOTOP, 021, "not",
0, NOTOP, 030, "negb",
0, NOTOP, 031, "neg",
0, NOTOP, 040, "mulb",
0, NOTOP, 041, "mul",
0, NOTOP, 060, "divb",
0, NOTOP, 061, "div",
0, NOTOP, 070, "idivb",
0, NOTOP, 071, "idiv",
0, PREFIX, 0144, "fseg",
0, PREFIX, 0145, "gseg",
0, PREFIX, 0146, "o16", /* operand size toggle */
0, PREFIX, 0146, "o32", /* operand size toggle */
0, PREFIX, 0147, "a16", /* address size toggle */
0, PREFIX, 0147, "a32", /* address size toggle */
0, PREFIX, 0360, "lock",
0, PREFIX, 0362, "rep",
0, PREFIX, 0362, "repne",
0, PREFIX, 0362, "repnz",
0, PREFIX, 0363, "repe",
0, PREFIX, 0363, "repz",
0, PREFIX, 046, "eseg",
0, PREFIX, 056, "cseg",
0, PREFIX, 066, "sseg",
0, PREFIX, 076, "dseg",
0, PUSHOP, 0, "push",
0, PUSHOP, 1, "pop",
0, RET, 0303, "ret",
0, RET, 0313, "retf",
0, ROLOP, 000, "rolb",
0, ROLOP, 001, "rol",
0, ROLOP, 010, "rorb",
0, ROLOP, 011, "ror",
0, ROLOP, 020, "rclb",
0, ROLOP, 021, "rcl",
0, ROLOP, 030, "rcrb",
0, ROLOP, 031, "rcr",
0, ROLOP, 040, "salb",
0, ROLOP, 040, "shlb",
0, ROLOP, 041, "sal",
0, ROLOP, 041, "shl",
0, ROLOP, 050, "shrb",
0, ROLOP, 051, "shr",
0, ROLOP, 070, "sarb",
0, ROLOP, 071, "sar",
0, SETCC, 0000, "seto",
0, SETCC, 0001, "setno",
0, SETCC, 0002, "setb",
0, SETCC, 0002, "setnae",
0, SETCC, 0003, "setae",
0, SETCC, 0003, "setnb",
0, SETCC, 0004, "sete",
0, SETCC, 0004, "setz",
0, SETCC, 0005, "setne",
0, SETCC, 0005, "setnz",
0, SETCC, 0006, "setbe",
0, SETCC, 0006, "setna",
0, SETCC, 0007, "seta",
0, SETCC, 0007, "setnbe",
0, SETCC, 0010, "sets",
0, SETCC, 0011, "setns",
0, SETCC, 0012, "setp",
0, SETCC, 0012, "setpe",
0, SETCC, 0013, "setnp",
0, SETCC, 0013, "setpo",
0, SETCC, 0014, "setl",
0, SETCC, 0014, "setnge",
0, SETCC, 0015, "setge",
0, SETCC, 0015, "setnl",
0, SETCC, 0016, "setle",
0, SETCC, 0016, "setng",
0, SETCC, 0017, "setg",
0, SETCC, 0017, "setnle",
0, TEST, 0, "testb",
0, TEST, 1, "test",
0, XCHG, 0, "xchgb",
0, XCHG, 1, "xchg",

198
mach/i386/as/mach4.c Normal file
View file

@ -0,0 +1,198 @@
#define RCSID4 "$Header$"
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*
*/
operation
: { address_long = 1; operand_long = 1; }
prefix oper
;
prefix : /* empty */
| prefix PREFIX
{ if ($2 == 0146) operand_long = ! operand_long;
if ($2 == 0147) address_long = ! address_long;
emit1($2);
}
;
oper : NOOP_1
{ emit1($1);}
| NOOP_2
{ emit2($1);}
| JOP expr
{ branch($1,$2);}
| JOP2 expr
{ ebranch($1,$2);}
| PUSHOP ea_1
{ pushop($1);}
| IOOP absexp
{ emit1($1);
fit(ufitb($2));
emit1((int)$2);
}
| IOOP R32
{ if ($2!=2) serror("register error");
emit1($1+010);
}
| BITTEST ea_ea
{ bittestop($1);}
| BOUND R32 ',' mem
{ emit1($1); ea_2($2<<3); }
| ADDOP ea_ea
{ addop($1);}
| ROLOP ea_ea
{ rolop($1);}
| INCOP ea_1
{ incop($1);}
| NOTOP ea_1
{ regsize($1); emit1(0366|($1&1)); ea_1($1&070);}
| CALLOP ea_1
{ callop($1&0xFFFF);}
| CALFOP expr ':' expr
{ emit1($1>>8);
#ifdef RELOCATION
newrelo($4.typ, RELO4);
#endif
emit4((long)($4.val));
#ifdef RELOCATION
newrelo($2.typ, RELO2);
#endif
emit2((int)($2.val));
}
| CALFOP mem
{ emit1(0377); ea_2($1&0xFF);}
| ENTER absexp ',' absexp
{ fit(fitw($2)); fit(fitb($4));
emit1($1); emit2((int)$2); emit1((int)$4);
}
| LEAOP R32 ',' mem
{ emit1($1); ea_2($2<<3);}
| LEAOP2 R32 ',' mem
{ emit1(0xF); emit1($1); ea_2($2<<3);}
| LSHFT ea_1 ',' R32 ',' ea_2
{ extshft($1, $4);}
| EXTEND R32 ',' ea_2
{ emit1(0xF); emit1($1|1); ea_2($2<<3);}
| EXTOP R32 ',' ea_2
{ emit1(0xF); emit1($1); ea_2($2<<3);}
| EXTOP1 ea_1
{ emit1(0xF); emit1($1&07); ea_1($1&070);}
| IMULB ea_1
{ regsize(0); emit1(0366); ea_1($1&070);}
| IMUL ea_2
{ reg_1 = IS_R32; imul(0); }
| IMUL R32 ',' ea_2
{ reg_1 = $2 | IS_R32; imul($2); }
| IMUL R32 ',' ea_ea
{ imul($2);}
| INT absexp
{ if ($2==3)
emit1(0314);
else {
fit(ufitb($2));
emit1(0315); emit1((int)$2);
}
}
| RET
{ emit1($1);}
| RET expr
{ emit1($1-1);
#ifdef RELOCATION
newrelo($2.typ, RELO2);
#endif
emit2((int)($2.val));
}
| SETCC ea_2
{ emit1(0xF); emit1($1); ea_2(0);}
| XCHG ea_ea
{ xchg($1);}
| TEST ea_ea
{ test($1);}
| MOV ea_ea
{ mov($1);}
| /* What is really needed is just
MOV R32 ',' RSYSCR
but this gives a bad yacc conflict
*/
MOV ea_1 ',' RSYSCR
{
if ($1 != 1 || !(reg_1 & IS_R32))
serror("syntax error");
emit1(0xF); emit1(042); emit1(0200|($4<<3)|(reg_1&07));}
| MOV ea_1 ',' RSYSDR
{
if ($1 != 1 || !(reg_1 & IS_R32))
serror("syntax error");
emit1(0xF); emit1(043); emit1(0200|($4<<3)|(reg_1&07));}
| MOV ea_1 ',' RSYSTR
{
if ($1 != 1 || !(reg_1 & IS_R32))
serror("syntax error");
emit1(0xF); emit1(046); emit1(0200|($4<<3)|(reg_1&07));}
| MOV RSYSCR ',' R32
{
if ($1 != 1) serror("syntax error");
emit1(0xF); emit1(040); emit1(0200|($4<<3)|$2);}
| MOV RSYSDR ',' R32
{
if ($1 != 1) serror("syntax error");
emit1(0xF); emit1(041); emit1(0200|($4<<3)|$2);}
| MOV RSYSTR ',' R32
{
if ($1 != 1) serror("syntax error");
emit1(0xF); emit1(044); emit1(0200|($4<<3)|$2);}
;
mem : '(' expr ')'
{ rm_2 = 05; exp_2 = $2; reg_2 = 05; mod_2 = 0;
RELOMOVE(rel_2, relonami);
}
| bases
{ exp_2.val = 0; exp_2.typ = S_ABS; indexed();}
| expr bases
{ exp_2 = $1; indexed();
RELOMOVE(rel_2, relonami);
}
;
bases : '(' R32 ')'
{ reg_2 = $2; sib_2 = 0; rm_2 = 0;}
| '(' R32 ')' '(' R32 scale ')'
{ rm_2 = 04; sib_2 |= regindex_ind[$2][$5];
reg_2 = $2;
}
| '(' R32 '*' absexp ')'
{ if ($4 == 1) {
reg_2 = $2; sib_2 = 0; rm_2 = 0;
}
else {
rm_2 = 04;
sib_2 = checkscale($4) | regindex_ind[05][$2];
reg_2 = 015;
}
}
;
scale : /* empty */
{ sib_2 = 0;}
| '*' absexp
{ sib_2 = checkscale($2);}
;
ea_2 : mem
| R8
{ reg_2 = $1 | IS_R8; rm_2 = 0;}
| R32
{ reg_2 = $1 | IS_R32; rm_2 = 0;}
| RSEG
{ reg_2 = $1 | IS_RSEG; rm_2 = 0;}
| expr
{ reg_2 = IS_EXPR; exp_2 = $1; rm_2 = 0;
RELOMOVE(rel_2, relonami);
}
;
ea_1 : ea_2
{ op_1 = op_2;
RELOMOVE(rel_1, rel_2);
}
;
ea_ea : ea_1 ',' ea_2
;

533
mach/i386/as/mach5.c Normal file
View file

@ -0,0 +1,533 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
#define RCSID5 "$Header$"
/*
* INTEL 80386 special routines
*/
ea_1(param) {
if (is_expr(reg_1)) {
serror("bad operand");
return;
}
if (is_reg(reg_1)) {
switch(reg_1&07) {
case 4:
emit1(0300 | param | 04);
emit1(0300 | 0100);
default:
emit1(0300 | param | (reg_1&07));
}
return;
}
if (rm_1 == 04) {
/* sib field use here */
emit1(mod_1 << 6 | param | 04);
emit1(sib_1 | reg_1);
if ((mod_1 == 0 && reg_1 == 5) || mod_1 == 2) {
#ifdef RELOCATION
RELOMOVE(relonami, rel_1);
newrelo(exp_1.typ, RELO4);
#endif
emit4((long)(exp_1.val));
}
else if (mod_1 == 1) emit1((int)(exp_1.val));
return;
}
emit1(mod_1<<6 | param | (reg_1&07));
if ((mod_1 == 0 && reg_1 == 5) || mod_1 == 2) {
#ifdef RELOCATION
RELOMOVE(relonami, rel_1);
newrelo(exp_1.typ, RELO4);
#endif
emit4((long)(exp_1.val));
}
else if (mod_1 == 1) {
emit1((int)(exp_1.val));
}
}
ea_2(param) {
op_1 = op_2;
RELOMOVE(rel_1, rel_2);
ea_1(param);
}
int
checkscale(val)
valu_t val;
{
int v = val;
if (v != val) v = 0;
switch(v) {
case 1:
return 0;
case 2:
return 1 << 6;
case 4:
return 2 << 6;
case 8:
return 3 << 6;
default:
serror("bad scale");
return 0;
}
/*NOTREACHED*/
}
reverse() {
struct operand op;
#ifdef RELOCATION
int r = rel_1;
rel_1 = rel_2; rel_2 = r;
#endif
op = op_1; op_1 = op_2; op_2 = op;
}
badsyntax() {
serror("bad operands");
}
regsize(sz)
int sz;
{
register int bit;
bit = (sz&1) ? 0 : IS_R8;
if ((is_reg(reg_1) && (reg_1 & IS_R8) != bit) ||
(is_reg(reg_2) && (reg_2 & IS_R8) != bit))
serror("register error");
}
indexed() {
mod_2 = 0;
if (sib_2 == -1)
serror("register error");
if (rm_2 == 0 && reg_2 == 4) {
/* base register sp, no index register; use
indexed mode without index register
*/
rm_2 = 04;
sib_2 = 044;
}
if (reg_2 == 015) {
reg_2 = 05;
return;
}
if (exp_2.typ != S_ABS || fitb(exp_2.val) == 0)
mod_2 = 02;
else if (exp_2.val != 0 || reg_2 == 5)
mod_2 = 01;
}
ebranch(opc,exp)
register int opc;
expr_t exp;
{
/* Conditional branching; Full displacements are available
on the 80386, so the welknown trick with the reverse branch
over a jump is not needed here.
The only complication here is with the address size, which
can be set with a prefix. In this case, the user gets what
he asked for.
*/
register int sm;
register long dist;
int saving = address_long ? 4 : 2;
dist = exp.val - (DOTVAL + 2);
if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT))
dist -= DOTGAIN;
sm = dist > 0 ? fitb(dist-saving) : fitb(dist);
if ((exp.typ & ~S_DOT) != DOTTYP)
sm = 0;
if ((sm = small(sm,saving)) == 0) {
emit1(0xF);
emit1(opc | 0x80);
dist -= 2;
exp.val = dist;
adsize_exp(exp);
}
else {
emit1(opc | 0x70);
emit1((int)dist);
}
}
branch(opc,exp)
register int opc;
expr_t exp;
{
/* LOOP, JCXZ, etc. branch instructions.
Here, the offset just must fit in a byte.
*/
register long dist;
dist = exp.val - (DOTVAL + 2);
if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT))
dist -= DOTGAIN;
fit((exp.typ & ~S_DOT) == DOTTYP && fitb(dist));
emit1(opc);
emit1((int)dist);
}
pushop(opc)
register int opc;
{
regsize(1);
if (is_segreg(reg_1)) {
/* segment register */
if ((reg_1 & 07) <= 3)
emit1(6 | opc | (reg_1&7)<<3);
else {
emit1(0xF);
emit1(0200 | opc | ((reg_1&7)<<3));
}
} else if (is_reg(reg_1)) {
/* normal register */
emit1(0120 | opc<<3 | (reg_1&7));
} else if (opc == 0) {
if (is_expr(reg_1)) {
if (exp_1.typ == S_ABS && fitb(exp_1.val)) {
emit1(0152);
emit1((int)(exp_1.val));
}
else {
emit1(0150);
RELOMOVE(relonami, rel_1);
opsize_exp(exp_1, 1);
}
}
else {
emit1(0377); ea_1(6<<3);
}
} else {
emit1(0217); ea_1(0<<3);
}
}
opsize_exp(exp, nobyte)
expr_t exp;
{
if (! nobyte) {
#ifdef RELOCATION
newrelo(exp.typ, RELO1);
#endif
emit1((int)(exp.val));
}
else if (operand_long) {
#ifdef RELOCATION
newrelo(exp.typ, RELO4);
#endif
emit4((long)(exp.val));
}
else {
#ifdef RELOCATION
newrelo(exp.typ, RELO2);
#endif
emit2((int)(exp.val));
}
}
adsize_exp(exp)
expr_t exp;
{
if (address_long) {
#ifdef RELOCATION
newrelo(exp.typ, RELO4 | RELPC);
#endif
emit4((long)(exp.val));
}
else {
if (! fitw(exp.val)) {
warning("offset does not fit in 2 bytes; remove prefix");
}
#ifdef RELOCATION
newrelo(exp.typ, RELO2 | RELPC);
#endif
emit2((int)(exp.val));
}
}
addop(opc)
register int opc;
{
regsize(opc);
if (is_reg(reg_2)) {
/* Add register to register or memory */
emit1(opc); ea_1((reg_2&7)<<3);
} else if (is_acc(reg_1) && is_expr(reg_2)) {
/* Add immediate to accumulator */
emit1(opc | 4);
RELOMOVE(relonami, rel_2);
opsize_exp(exp_2, (opc&1));
} else if (is_expr(reg_2)) {
/* Add immediate to register or memory */
if ((opc&1) == 0) {
emit1(0200);
} else if (exp_2.typ != S_ABS || fitb(exp_2.val) == 0) {
emit1(0201);
} else {
emit1(0203); opc &= ~1;
}
ea_1(opc & 070);
RELOMOVE(relonami, rel_2);
opsize_exp(exp_2, (opc&1));
} else if (is_reg(reg_1)) {
/* Add register or memory to register */
emit1(opc | 2);
ea_2((reg_1&7)<<3);
} else
badsyntax();
}
rolop(opc)
register int opc;
{
register int oreg;
oreg = reg_2;
reg_2 = reg_1;
regsize(opc);
if (oreg == (IS_R8 | 1)) {
/* cl register */
emit1(0322 | (opc&1)); ea_1(opc&070);
} else if (is_expr(oreg) && exp_2.typ == S_ABS && exp_2.val == 1) {
/* shift by 1 */
emit1(0320 | (opc&1)); ea_1(opc&070);
} else if (is_expr(oreg)) {
/* shift by byte count */
emit1(0300 | (opc & 1));
ea_1(opc & 070);
#ifdef RELOCATION
RELOMOVE(relonami, rel_2);
newrelo(exp_2.typ, RELO1);
#endif
emit1((int)(exp_2.val));
}
else
badsyntax();
}
incop(opc)
register int opc;
{
regsize(opc);
if ((opc&1) && is_reg(reg_1)) {
/* word register */
emit1(0100 | (opc&010) | (reg_1&7));
} else {
emit1(0376 | (opc&1));
ea_1(opc & 010);
}
}
callop(opc)
register int opc;
{
regsize(1);
if (is_expr(reg_1)) {
if (opc == (040+(0351<<8))) {
RELOMOVE(relonami, rel_1);
ebranch(0353,exp_1);
} else {
exp_1.val -= (DOTVAL+3);
emit1(opc>>8);
RELOMOVE(relonami, rel_1);
adsize_exp(exp_1);
}
} else {
emit1(0377); ea_1(opc&070);
}
}
xchg(opc)
register int opc;
{
regsize(opc);
if (! is_reg(reg_1) || is_acc(reg_2)) {
reverse();
}
if (opc == 1 && is_acc(reg_1) && is_reg(reg_2)) {
emit1(0220 | (reg_2&7));
} else if (is_reg(reg_1)) {
emit1(0206 | opc); ea_2((reg_1&7)<<3);
} else
badsyntax();
}
test(opc)
register int opc;
{
regsize(opc);
if (is_reg(reg_2) || is_expr(reg_1))
reverse();
if (is_expr(reg_2)) {
if (is_acc(reg_1)) {
emit1(0250 | opc);
RELOMOVE(relonami, rel_2);
opsize_exp(exp_2, (opc&1));
}
else {
emit1(0366 | opc);
ea_1(0<<3);
RELOMOVE(relonami, rel_2);
opsize_exp(exp_2, (opc&1));
}
} else if (is_reg(reg_1)) {
emit1(0204 | opc); ea_2((reg_1&7)<<3);
} else
badsyntax();
}
mov(opc)
register int opc;
{
regsize(opc);
if (is_segreg(reg_1)) {
/* to segment register */
emit1(0216); ea_2((reg_1&3)<<3);
} else if (is_segreg(reg_2)) {
/* from segment register */
emit1(0214); ea_1((reg_2&3)<<3);
} else if (is_expr(reg_2)) {
/* from immediate */
if (is_reg(reg_1)) {
/* to register */
emit1(0260 | opc<<3 | (reg_1&7));
} else {
/* to memory */
emit1(0306 | opc); ea_1(0<<3);
}
RELOMOVE(relonami, rel_2);
opsize_exp(exp_2, (opc&1));
} else if (rm_1 == 05 && is_acc(reg_2)) {
/* from accumulator to memory (displacement) */
emit1(0242 | opc);
RELOMOVE(relonami, rel_1);
adsize_exp(exp_1);
} else if (rm_2 == 05 && is_acc(reg_1)) {
/* from memory (displacement) to accumulator */
emit1(0240 | opc);
RELOMOVE(relonami, rel_2);
adsize_exp(exp_2);
} else if (is_reg(reg_2)) {
/* from register to memory or register */
emit1(0210 | opc); ea_1((reg_2&7)<<3);
} else if (is_reg(reg_1)) {
/* from memory or register to register */
emit1(0212 | opc); ea_2((reg_1&7)<<3);
} else
badsyntax();
}
extshft(opc, reg)
int opc;
{
int oreg2 = reg_2;
reg_2 = reg_1;
regsize(1);
emit1(0xF);
if (oreg2 == (IS_R8 | 1)) {
/* cl register */
emit1(opc|1);
ea_1(reg << 3);
}
else if (is_expr(oreg2)) {
emit1(opc);
ea_1(reg << 3);
#ifdef RELOCATION
RELOMOVE(relonami, rel_2);
newrelo(exp_2.typ, RELO1);
#endif
emit1((int)(exp_2.val));
}
else badsyntax();
}
bittestop(opc)
int opc;
{
regsize(1);
emit1(0xF);
if (is_expr(reg_2)) {
emit1(0272);
ea_1(opc << 3);
#ifdef RELOCATION
RELOMOVE(relonami, rel_2);
newrelo(exp_2.typ, RELO1);
#endif
emit1((int)(exp_2.val));
}
else if (is_reg(reg_2)) {
emit1(0203 | opc);
ea_1((reg_2&7)<<3);
}
else badsyntax();
}
imul(reg)
int reg;
{
/* This instruction is more elaborate on the 80386. Its most
general form is:
imul reg, reg_or_mem, immediate.
This is the form processed here.
*/
regsize(1);
if (is_expr(reg_1)) {
/* To also handle
imul reg, immediate, reg_or_mem
*/
reverse();
}
if (is_expr(reg_2)) {
/* The immediate form; two cases: */
if (exp_2.typ == S_ABS && fitb(exp_2.val)) {
/* case 1: 1 byte encoding of immediate */
emit1(0153);
ea_1(reg << 3);
emit1((int)(exp_2.val));
}
else {
/* case 2: WORD or DWORD encoding of immediate */
emit1(0151);
ea_1(reg << 3);
RELOMOVE(relonami, rel_2);
opsize_exp(exp_2, 1);
}
}
else if (is_reg(reg_1) && ((reg_1&7) == reg)) {
/* the "reg" field and the "reg_or_mem" field are the same,
and the 3rd operand is not an immediate ...
*/
if (reg == 0) {
/* how lucky we are, the target is the ax register */
emit1(0367);
ea_2(06 << 3);
}
else {
/* another register ... */
emit1(0xF);
emit1(0257);
ea_2(reg << 3);
}
}
else badsyntax();
}