Added 16-bit mode

This commit is contained in:
ceriel 1990-03-12 16:24:58 +00:00
parent 9a5ac60946
commit 2c7496a525
5 changed files with 146 additions and 32 deletions

View file

@ -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

View file

@ -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

View file

@ -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",

View file

@ -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) {

View file

@ -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