Added 16-bit mode
This commit is contained in:
parent
9a5ac60946
commit
2c7496a525
5 changed files with 146 additions and 32 deletions
|
@ -75,3 +75,28 @@ char regindex_ind[8][8] = {
|
|||
#endif
|
||||
|
||||
extern int address_long INIT(1), operand_long INIT(1);
|
||||
extern int use32 INIT(1);
|
||||
|
||||
/* For 16-bit addressing: copied from i86 assembler */
|
||||
#ifndef extern
|
||||
extern char sr_m[8];
|
||||
#else
|
||||
char sr_m[8] = {
|
||||
-1, -1, -1, 7, -1, 6, 4, 5
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef extern
|
||||
extern char dr_m[8][8];
|
||||
#else
|
||||
char dr_m[8][8] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, 0, 1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, 2, 3,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
* INTEL 80386 tokens
|
||||
*/
|
||||
|
||||
%token <y_word> ATOGGLE
|
||||
%token <y_word> OTOGGLE
|
||||
%token <y_word> USE16
|
||||
%token <y_word> USE32
|
||||
%token <y_word> R32
|
||||
%token <y_word> R16
|
||||
%token <y_word> R8
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
* No system registers for now ...
|
||||
*/
|
||||
|
||||
0, USE16, 0, ".use16",
|
||||
0, USE32, 0, ".use32",
|
||||
0, R32, 0, "ax",
|
||||
0, R32, 1, "cx",
|
||||
0, R32, 2, "dx",
|
||||
|
@ -213,10 +215,10 @@
|
|||
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, OTOGGLE, 0146, "o16", /* operand size toggle */
|
||||
0, OTOGGLE, 0346, "o32", /* operand size toggle */
|
||||
0, ATOGGLE, 0147, "a16", /* address size toggle */
|
||||
0, ATOGGLE, 0347, "a32", /* address size toggle */
|
||||
0, PREFIX, 0360, "lock",
|
||||
0, PREFIX, 0362, "rep",
|
||||
0, PREFIX, 0362, "repne",
|
||||
|
|
|
@ -8,18 +8,37 @@
|
|||
|
||||
operation
|
||||
:
|
||||
prefix oper
|
||||
{ address_long = 1; operand_long = 1; }
|
||||
USE16
|
||||
{ use32 = 0; address_long = 0; operand_long = 0; }
|
||||
|
|
||||
USE32
|
||||
{ use32 = 1; address_long = 1; operand_long = 1; }
|
||||
| prefix oper
|
||||
{ address_long = use32; operand_long = use32; }
|
||||
| prefix1 /* to allow for only prefixes on a line */
|
||||
;
|
||||
prefix : /* empty */
|
||||
| prefix1
|
||||
;
|
||||
prefix1: prefix PREFIX
|
||||
{ if ($2 == 0146) operand_long = ! operand_long;
|
||||
if ($2 == 0147) address_long = ! address_long;
|
||||
emit1($2);
|
||||
}
|
||||
prefix1: prefix PREFIX { emit1($2); }
|
||||
|
|
||||
prefix ATOGGLE
|
||||
{ if ((($2&0200) >> 7) == address_long) {
|
||||
if (pass == PASS_3) warning("address size toggle ignored");
|
||||
} else {
|
||||
emit1($2 & 0177);
|
||||
address_long = ! address_long;
|
||||
}
|
||||
}
|
||||
|
|
||||
prefix OTOGGLE
|
||||
{ if ((($2&0200) >> 7) == operand_long) {
|
||||
if (pass == PASS_3) warning("operand size toggle ignored");
|
||||
} else {
|
||||
emit1($2 & 0177);
|
||||
operand_long = ! operand_long;
|
||||
}
|
||||
}
|
||||
;
|
||||
oper : NOOP_1
|
||||
{ emit1($1);}
|
||||
|
@ -177,8 +196,15 @@ st_i : ST '(' absexp ')'
|
|||
|
||||
;
|
||||
mem : '(' expr ')'
|
||||
{ rm_2 = 05; exp_2 = $2; reg_2 = 05; mod_2 = 0;
|
||||
{ if (address_long) {
|
||||
rm_2 = 05; reg_2 = 05; mod_2 = 0;
|
||||
}
|
||||
else {
|
||||
reg_2 = 06;
|
||||
}
|
||||
exp_2 = $2;
|
||||
RELOMOVE(rel_2, relonami);
|
||||
|
||||
}
|
||||
| bases
|
||||
{ exp_2.val = 0; exp_2.typ = S_ABS; indexed();}
|
||||
|
@ -188,10 +214,20 @@ mem : '(' expr ')'
|
|||
}
|
||||
;
|
||||
bases : '(' R32 ')'
|
||||
{ reg_2 = $2; sib_2 = 0; rm_2 = 0;}
|
||||
{ if (address_long) {
|
||||
reg_2 = $2; sib_2 = 0; rm_2 = 0;
|
||||
}
|
||||
else reg_2 = sr_m[$2];
|
||||
}
|
||||
| '(' R32 ')' '(' R32 scale ')'
|
||||
{ rm_2 = 04; sib_2 |= regindex_ind[$2][$5];
|
||||
reg_2 = $2;
|
||||
{ if (address_long) {
|
||||
rm_2 = 04;
|
||||
sib_2 |= regindex_ind[$2][$5];
|
||||
reg_2 = $2;
|
||||
}
|
||||
else {
|
||||
reg_2 = dr_m[$2][$5];
|
||||
}
|
||||
}
|
||||
| '(' R32 '*' absexp ')'
|
||||
{ if ($4 == 1) {
|
||||
|
|
|
@ -8,7 +8,40 @@
|
|||
* INTEL 80386 special routines
|
||||
*/
|
||||
|
||||
ea_1_16(param)
|
||||
{
|
||||
if ((reg_1 & 070) || (param & ~070)) {
|
||||
serror("bad operand");
|
||||
}
|
||||
emit1(reg_1 | param);
|
||||
switch(reg_1 >> 6) {
|
||||
case 0:
|
||||
if (reg_1 == 6 || (reg_1 & 040)) {
|
||||
#ifdef RELOCATION
|
||||
RELOMOVE(relonami, rel_1);
|
||||
newrelo(exp_1.typ, RELO2);
|
||||
#endif
|
||||
emit2(exp_1.val);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
emit1(exp_1.val);
|
||||
break;
|
||||
case 2:
|
||||
#ifdef RELOCATION
|
||||
RELOMOVE(relonami, rel_1);
|
||||
newrelo(exp_1.typ, RELO2);
|
||||
#endif
|
||||
emit2(exp_1.val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ea_1(param) {
|
||||
if (! address_long) {
|
||||
ea_1_16(param);
|
||||
return;
|
||||
}
|
||||
if (is_expr(reg_1)) {
|
||||
serror("bad operand");
|
||||
return;
|
||||
|
@ -49,6 +82,10 @@ checkscale(val)
|
|||
{
|
||||
int v = val;
|
||||
|
||||
if (! address_long) {
|
||||
serror("scaling not allowed in 16-bit mode");
|
||||
return 0;
|
||||
}
|
||||
if (v != val) v = 0;
|
||||
switch(v) {
|
||||
case 1:
|
||||
|
@ -93,24 +130,34 @@ regsize(sz)
|
|||
}
|
||||
|
||||
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 (address_long) {
|
||||
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;
|
||||
}
|
||||
if (reg_2 == 015) {
|
||||
reg_2 = 05;
|
||||
return;
|
||||
else {
|
||||
if (reg_2 & ~7)
|
||||
serror("register error");
|
||||
if (exp_2.typ != S_ABS || fitb(exp_2.val) == 0)
|
||||
reg_2 |= 0200;
|
||||
else if (exp_2.val != 0 || reg_2 == 6)
|
||||
reg_2 |= 0100;
|
||||
}
|
||||
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)
|
||||
|
@ -245,7 +292,7 @@ adsize_exp(exp, relpc)
|
|||
emit4((long)(exp.val));
|
||||
}
|
||||
else {
|
||||
if (! fitw(exp.val)) {
|
||||
if (! fitw(exp.val) && pass == PASS_3) {
|
||||
warning("offset does not fit in 2 bytes; remove prefix");
|
||||
}
|
||||
#ifdef RELOCATION
|
||||
|
|
Loading…
Reference in a new issue