Fixed 16-bit address mode bugs

This commit is contained in:
ceriel 1990-03-19 14:46:55 +00:00
parent 0b95807664
commit 71156a48ae
3 changed files with 39 additions and 33 deletions

View file

@ -25,7 +25,7 @@
#define is_expr(reg) ((reg)&IS_EXPR) #define is_expr(reg) ((reg)&IS_EXPR)
#define is_segreg(reg) ((reg)&IS_RSEG) #define is_segreg(reg) ((reg)&IS_RSEG)
#define is_reg(reg) (((reg)&(IS_R8|IS_R32)) != 0) #define is_reg(reg) (((reg)&(IS_R8|IS_R32)) != 0)
#define is_acc(reg) ((reg) != 0 && ((reg)&(IS_R8|IS_R32)) == (reg)) #define is_acc(reg) (is_reg(reg) && ((reg & 07) == 0))
struct operand { struct operand {
int mod; int mod;

View file

@ -102,9 +102,13 @@ oper : NOOP_1
| IMULB ea_1 | IMULB ea_1
{ regsize(0); emit1(0366); ea_1($1&070);} { regsize(0); emit1(0366); ea_1($1&070);}
| IMUL ea_2 | IMUL ea_2
{ reg_1 = IS_R32; imul(0); } { reg_1 = IS_R32 | (address_long ? 0 : 0310);
imul(0);
}
| IMUL R32 ',' ea_2 | IMUL R32 ',' ea_2
{ reg_1 = $2 | IS_R32; imul($2|0x10); } { reg_1 = $2 | IS_R32 | (address_long ? 0 : 0310);
imul($2|0x10);
}
| IMUL R32 ',' ea_ea | IMUL R32 ',' ea_ea
{ imul($2|0x10);} { imul($2|0x10);}
| INT absexp | INT absexp
@ -196,12 +200,10 @@ st_i : ST '(' absexp ')'
; ;
mem : '(' expr ')' mem : '(' expr ')'
{ if (address_long) { { if (address_long) reg_2 = 05;
rm_2 = 05; reg_2 = 05; mod_2 = 0; else reg_2 = 06;
} mod_2 = 0;
else { rm_2 = 05;
reg_2 = 06;
}
exp_2 = $2; exp_2 = $2;
RELOMOVE(rel_2, relonami); RELOMOVE(rel_2, relonami);
@ -214,20 +216,15 @@ mem : '(' expr ')'
} }
; ;
bases : '(' R32 ')' bases : '(' R32 ')'
{ if (address_long) { { if (address_long) reg_2 = $2;
reg_2 = $2; sib_2 = 0; rm_2 = 0;
}
else reg_2 = sr_m[$2]; else reg_2 = sr_m[$2];
sib_2 = 0; rm_2 = 0;
} }
| '(' R32 ')' '(' R32 scale ')' | '(' R32 ')' '(' R32 scale ')'
{ if (address_long) { { if (address_long) reg_2 = $2;
rm_2 = 04; else reg_2 = dr_m[$2][$5];
sib_2 |= regindex_ind[$2][$5]; rm_2 = 04;
reg_2 = $2; sib_2 |= regindex_ind[$2][$5];
}
else {
reg_2 = dr_m[$2][$5];
}
} }
| '(' R32 '*' absexp ')' | '(' R32 '*' absexp ')'
{ if ($4 == 1) { { if ($4 == 1) {
@ -247,13 +244,20 @@ scale : /* empty */
; ;
ea_2 : mem ea_2 : mem
| R8 | R8
{ reg_2 = $1 | IS_R8; rm_2 = 0;} { reg_2 = ($1 | IS_R8) | (address_long ? 0 : 0300);
rm_2 = 0;
}
| R32 | R32
{ reg_2 = $1 | IS_R32; rm_2 = 0;} { reg_2 = ($1 | IS_R32) | (address_long ? 0 : 0310);
rm_2 = 0;
}
| RSEG | RSEG
{ reg_2 = $1 | IS_RSEG; rm_2 = 0;} { reg_2 = ($1 | IS_RSEG) | (address_long ? 0 : 020);
rm_2 = 0;
}
| expr | expr
{ reg_2 = IS_EXPR; exp_2 = $1; rm_2 = 0; { reg_2 = IS_EXPR | (address_long ? 0 : 040);
exp_2 = $1; rm_2 = 0;
RELOMOVE(rel_2, relonami); RELOMOVE(rel_2, relonami);
} }
; ;

View file

@ -10,6 +10,7 @@
ea_1_16(param) ea_1_16(param)
{ {
reg_1 &= 0377;
if ((reg_1 & 070) || (param & ~070)) { if ((reg_1 & 070) || (param & ~070)) {
serror("bad operand"); serror("bad operand");
} }
@ -127,6 +128,10 @@ regsize(sz)
if ((is_reg(reg_1) && (reg_1 & IS_R8) != bit) || if ((is_reg(reg_1) && (reg_1 & IS_R8) != bit) ||
(is_reg(reg_2) && (reg_2 & IS_R8) != bit)) (is_reg(reg_2) && (reg_2 & IS_R8) != bit))
serror("register error"); serror("register error");
if (! address_long) {
reg_1 &= ~010;
reg_2 &= ~010;
}
} }
indexed() { indexed() {
@ -292,9 +297,6 @@ adsize_exp(exp, relpc)
emit4((long)(exp.val)); emit4((long)(exp.val));
} }
else { else {
if (! fitw(exp.val) && pass == PASS_3) {
warning("offset does not fit in 2 bytes; remove prefix");
}
#ifdef RELOCATION #ifdef RELOCATION
newrelo(exp.typ, RELO2 | relpc); newrelo(exp.typ, RELO2 | relpc);
#endif #endif
@ -344,7 +346,7 @@ rolop(opc)
oreg = reg_2; oreg = reg_2;
reg_2 = reg_1; reg_2 = reg_1;
regsize(opc); regsize(opc);
if (oreg == (IS_R8 | 1)) { if (oreg == (IS_R8 | 1 | (address_long ? 0 : 0300))) {
/* cl register */ /* cl register */
emit1(0322 | (opc&1)); ea_1(opc&070); emit1(0322 | (opc&1)); ea_1(opc&070);
} else if (is_expr(oreg) && exp_2.typ == S_ABS && exp_2.val == 1) { } else if (is_expr(oreg) && exp_2.typ == S_ABS && exp_2.val == 1) {
@ -446,10 +448,10 @@ mov(opc)
regsize(opc); regsize(opc);
if (is_segreg(reg_1)) { if (is_segreg(reg_1)) {
/* to segment register */ /* to segment register */
emit1(0216); ea_2((reg_1&3)<<3); emit1(0216); ea_2((reg_1&07)<<3);
} else if (is_segreg(reg_2)) { } else if (is_segreg(reg_2)) {
/* from segment register */ /* from segment register */
emit1(0214); ea_1((reg_2&3)<<3); emit1(0214); ea_1((reg_2&07)<<3);
} else if (is_expr(reg_2)) { } else if (is_expr(reg_2)) {
/* from immediate */ /* from immediate */
if (is_reg(reg_1)) { if (is_reg(reg_1)) {
@ -473,10 +475,10 @@ mov(opc)
adsize_exp(exp_2, 0); adsize_exp(exp_2, 0);
} else if (is_reg(reg_2)) { } else if (is_reg(reg_2)) {
/* from register to memory or register */ /* from register to memory or register */
emit1(0210 | opc); ea_1((reg_2&7)<<3); emit1(0210 | opc); ea_1((reg_2&07)<<3);
} else if (is_reg(reg_1)) { } else if (is_reg(reg_1)) {
/* from memory or register to register */ /* from memory or register to register */
emit1(0212 | opc); ea_2((reg_1&7)<<3); emit1(0212 | opc); ea_2((reg_1&07)<<3);
} else } else
badsyntax(); badsyntax();
} }
@ -490,7 +492,7 @@ extshft(opc, reg)
regsize(1); regsize(1);
emit1(0xF); emit1(0xF);
if (oreg2 == (IS_R8 | 1)) { if (oreg2 == (IS_R8 | 1 | (address_long ? 0 : 0300))) {
/* cl register */ /* cl register */
emit1(opc|1); emit1(opc|1);
ea_1(reg << 3); ea_1(reg << 3);