Hacky workaround to make lar work.

This commit is contained in:
David Given 2022-08-10 00:15:40 +02:00
parent b868c1ece9
commit 967b46e98e

View file

@ -10,8 +10,8 @@
void ea_1_16(int param) void ea_1_16(int param)
{ {
reg_1 &= 0377; reg_1 &= 0377;
if ((reg_1 & 070) || (param & ~070)) { if (param & ~070) {
serror("bad operand"); serror("bad operand");
} }
emit1(reg_1 | param); emit1(reg_1 | param);
@ -39,542 +39,545 @@ void ea_1_16(int param)
} }
void ea_1(int param) { void ea_1(int param) {
if (! address_long) { if (! address_long) {
ea_1_16(param); ea_1_16(param);
return; return;
} }
if (is_expr(reg_1)) { if (is_expr(reg_1)) {
serror("bad operand"); serror("bad operand");
return; return;
} }
if (is_reg(reg_1)) { if (is_reg(reg_1)) {
emit1(0300 | param | (reg_1&07)); emit1(0300 | param | (reg_1&07));
return; return;
} }
if (rm_1 == 04) { if (rm_1 == 04) {
/* sib field use here */ /* sib field use here */
emit1(mod_1 << 6 | param | 04); emit1(mod_1 << 6 | param | 04);
emit1(sib_1 | reg_1); emit1(sib_1 | reg_1);
} }
else emit1(mod_1<<6 | param | (reg_1&07)); else emit1(mod_1<<6 | param | (reg_1&07));
if ((mod_1 == 0 && reg_1 == 5) || mod_1 == 2) { if ((mod_1 == 0 && reg_1 == 5) || mod_1 == 2) {
/* ??? should this be protected by a call to "small" ??? */ /* ??? should this be protected by a call to "small" ??? */
#ifdef RELOCATION #ifdef RELOCATION
RELOMOVE(relonami, rel_1); RELOMOVE(relonami, rel_1);
newrelo(exp_1.typ, RELO4); newrelo(exp_1.typ, RELO4);
#endif #endif
emit4((long)(exp_1.val)); emit4((long)(exp_1.val));
} }
else if (mod_1 == 1) { else if (mod_1 == 1) {
emit1((int)(exp_1.val)); emit1((int)(exp_1.val));
} }
} }
void ea_2(int param) { void ea_2(int param) {
op_1 = op_2; op_1 = op_2;
RELOMOVE(rel_1, rel_2); RELOMOVE(rel_1, rel_2);
ea_1(param); ea_1(param);
} }
int checkscale(valu_t val) int checkscale(valu_t val)
{ {
int v = val; int v = val;
if (! address_long) { if (! address_long) {
serror("scaling not allowed in 16-bit mode"); serror("scaling not allowed in 16-bit mode");
return 0; return 0;
} }
if (v != val) v = 0; if (v != val) v = 0;
switch(v) { switch(v) {
case 1: case 1:
return 0; return 0;
case 2: case 2:
return 1 << 6; return 1 << 6;
case 4: case 4:
return 2 << 6; return 2 << 6;
case 8: case 8:
return 3 << 6; return 3 << 6;
default: default:
serror("bad scale"); serror("bad scale");
return 0; return 0;
} }
/*NOTREACHED*/ /*NOTREACHED*/
} }
void reverse(void) { void reverse(void) {
struct operand op; struct operand op;
#ifdef RELOCATION #ifdef RELOCATION
int r = rel_1; int r = rel_1;
rel_1 = rel_2; rel_2 = r; rel_1 = rel_2; rel_2 = r;
#endif #endif
op = op_1; op_1 = op_2; op_2 = op; op = op_1; op_1 = op_2; op_2 = op;
} }
void badsyntax(void) void badsyntax(void)
{ {
serror("bad operands"); serror("bad operands");
} }
void regsize(int sz) void regsize(int sz)
{ {
register int bit; register int bit;
bit = (sz&1) ? 0 : IS_R8; bit = (sz&1) ? 0 : IS_R8;
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) { if (! address_long) {
reg_1 &= ~010; reg_1 &= ~010;
reg_2 &= ~010; reg_2 &= ~010;
} }
} }
void indexed(void) { void indexed(void) {
if (address_long) { if (address_long) {
mod_2 = 0; mod_2 = 0;
if (sib_2 == -1) if (sib_2 == -1)
serror("register error"); serror("register error");
if (rm_2 == 0 && reg_2 == 4) { if (rm_2 == 0 && reg_2 == 4) {
/* base register sp, no index register; use /* base register sp, no index register; use
indexed mode without index register indexed mode without index register
*/ */
rm_2 = 04; rm_2 = 04;
sib_2 = 044; sib_2 = 044;
} }
if (reg_2 == 015) { if (reg_2 == 015) {
reg_2 = 05; reg_2 = 05;
return; return;
} }
if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 3)) { if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 3)) {
if (small(exp_2.val == 0 && reg_2 != 5, 1)) { if (small(exp_2.val == 0 && reg_2 != 5, 1)) {
} }
else mod_2 = 01; else mod_2 = 01;
} }
else if (small(0, 1)) { else if (small(0, 1)) {
} }
else mod_2 = 02; else mod_2 = 02;
} }
else { else {
if (reg_2 & ~7) if (reg_2 & ~7)
serror("register error"); serror("register error");
if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 1)) { if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 1)) {
if (small(exp_2.val == 0 && reg_2 != 6, 1)) { if (small(exp_2.val == 0 && reg_2 != 6, 1)) {
} }
else reg_2 |= 0100; else reg_2 |= 0100;
} }
else if (small(0, 1)) { else if (small(0, 1)) {
} }
else reg_2 |= 0200; else reg_2 |= 0200;
} }
} }
void ebranch(register int opc,expr_t exp) void ebranch(register int opc,expr_t exp)
{ {
/* Conditional branching; Full displacements are available /* Conditional branching; Full displacements are available
on the 80386, so the welknown trick with the reverse branch on the 80386, so the welknown trick with the reverse branch
over a jump is not needed here. over a jump is not needed here.
The only complication here is with the address size, which The only complication here is with the address size, which
can be set with a prefix. In this case, the user gets what can be set with a prefix. In this case, the user gets what
he asked for. he asked for.
*/ */
register int sm; register int sm;
register long dist; register long dist;
int saving = address_long ? 4 : 2; int saving = address_long ? 4 : 2;
if (opc == 0353) saving--; if (opc == 0353) saving--;
dist = exp.val - (DOTVAL + 2); dist = exp.val - (DOTVAL + 2);
if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT)) if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT))
dist -= DOTGAIN; dist -= DOTGAIN;
sm = dist > 0 ? fitb(dist-saving) : fitb(dist); sm = dist > 0 ? fitb(dist-saving) : fitb(dist);
if ((exp.typ & ~S_DOT) != DOTTYP) if ((exp.typ & ~S_DOT) != DOTTYP)
sm = 0; sm = 0;
if ((sm = small(sm,saving)) == 0) { if ((sm = small(sm,saving)) == 0) {
if (opc == 0353) { if (opc == 0353) {
emit1(0xe9); emit1(0xe9);
} }
else { else {
emit1(0xF); emit1(0xF);
emit1(opc | 0x80); emit1(opc | 0x80);
} }
dist -= saving; dist -= saving;
exp.val = dist; exp.val = dist;
adsize_exp(exp, RELPC); adsize_exp(exp, RELPC);
} }
else { else {
if (opc == 0353) { if (opc == 0353) {
emit1(opc); emit1(opc);
} }
else { else {
emit1(opc | 0x70); emit1(opc | 0x70);
} }
emit1((int)dist); emit1((int)dist);
} }
} }
void branch(register int opc,expr_t exp) void branch(register int opc,expr_t exp)
{ {
/* LOOP, JCXZ, etc. branch instructions. /* LOOP, JCXZ, etc. branch instructions.
Here, the offset just must fit in a byte. Here, the offset just must fit in a byte.
*/ */
register long dist; register long dist;
dist = exp.val - (DOTVAL + 2); dist = exp.val - (DOTVAL + 2);
if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT)) if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT))
dist -= DOTGAIN; dist -= DOTGAIN;
fit((exp.typ & ~S_DOT) == DOTTYP && fitb(dist)); fit((exp.typ & ~S_DOT) == DOTTYP && fitb(dist));
emit1(opc); emit1(opc);
emit1((int)dist); emit1((int)dist);
} }
void pushop(register int opc) void pushop(register int opc)
{ {
regsize(1); regsize(1);
if (is_segreg(reg_1)) { if (is_segreg(reg_1)) {
/* segment register */ /* segment register */
if ((reg_1 & 07) <= 3) if ((reg_1 & 07) <= 3)
emit1(6 | opc | (reg_1&7)<<3); emit1(6 | opc | (reg_1&7)<<3);
else { else {
emit1(0xF); emit1(0xF);
emit1(0200 | opc | ((reg_1&7)<<3)); emit1(0200 | opc | ((reg_1&7)<<3));
} }
} else if (is_reg(reg_1)) { } else if (is_reg(reg_1)) {
/* normal register */ /* normal register */
emit1(0120 | opc<<3 | (reg_1&7)); emit1(0120 | opc<<3 | (reg_1&7));
} else if (opc == 0) { } else if (opc == 0) {
if (is_expr(reg_1)) { if (is_expr(reg_1)) {
if (small(exp_1.typ == S_ABS && fitb(exp_1.val), if (small(exp_1.typ == S_ABS && fitb(exp_1.val),
operand_long ? 3 : 1)) { operand_long ? 3 : 1)) {
emit1(0152); emit1(0152);
emit1((int)(exp_1.val)); emit1((int)(exp_1.val));
} }
else { else {
emit1(0150); emit1(0150);
RELOMOVE(relonami, rel_1); RELOMOVE(relonami, rel_1);
opsize_exp(exp_1, 1); opsize_exp(exp_1, 1);
} }
} }
else { else {
emit1(0377); ea_1(6<<3); emit1(0377); ea_1(6<<3);
} }
} else { } else {
emit1(0217); ea_1(0<<3); emit1(0217); ea_1(0<<3);
} }
} }
void opsize_exp(expr_t exp, int nobyte) void opsize_exp(expr_t exp, int nobyte)
{ {
if (! nobyte) { if (! nobyte) {
#ifdef RELOCATION #ifdef RELOCATION
newrelo(exp.typ, RELO1); newrelo(exp.typ, RELO1);
#endif #endif
emit1((int)(exp.val)); emit1((int)(exp.val));
} }
else if (operand_long) { else if (operand_long) {
#ifdef RELOCATION #ifdef RELOCATION
newrelo(exp.typ, RELO4); newrelo(exp.typ, RELO4);
#endif #endif
emit4((long)(exp.val)); emit4((long)(exp.val));
} }
else { else {
#ifdef RELOCATION #ifdef RELOCATION
newrelo(exp.typ, RELO2); newrelo(exp.typ, RELO2);
#endif #endif
emit2((int)(exp.val)); emit2((int)(exp.val));
} }
} }
void adsize_exp(expr_t exp, int relpc) void adsize_exp(expr_t exp, int relpc)
{ {
if (address_long) { if (address_long) {
#ifdef RELOCATION #ifdef RELOCATION
newrelo(exp.typ, RELO4 | relpc); newrelo(exp.typ, RELO4 | relpc);
#endif #endif
emit4((long)(exp.val)); emit4((long)(exp.val));
} }
else { else {
#ifdef RELOCATION #ifdef RELOCATION
newrelo(exp.typ, RELO2 | relpc); newrelo(exp.typ, RELO2 | relpc);
#endif #endif
emit2((int)(exp.val)); emit2((int)(exp.val));
} }
} }
void addop(register int opc) void addop(register int opc)
{ {
regsize(opc); regsize(opc);
if (is_reg(reg_2)) { if (is_reg(reg_2)) {
/* Add register to register or memory */ /* Add register to register or memory */
emit1(opc); ea_1((reg_2&7)<<3); emit1(opc); ea_1((reg_2&7)<<3);
} else if (is_acc(reg_1) && is_expr(reg_2)) { } else if (is_acc(reg_1) && is_expr(reg_2)) {
/* Add immediate to accumulator */ /* Add immediate to accumulator */
emit1(opc | 4); emit1(opc | 4);
RELOMOVE(relonami, rel_2); RELOMOVE(relonami, rel_2);
opsize_exp(exp_2, (opc&1)); opsize_exp(exp_2, (opc&1));
} else if (is_expr(reg_2)) { } else if (is_expr(reg_2)) {
/* Add immediate to register or memory */ /* Add immediate to register or memory */
if ((opc&1) == 0) { if ((opc&1) == 0) {
emit1(0200); emit1(0200);
} else if (! small(exp_2.typ == S_ABS && fitb(exp_2.val), } else if (! small(exp_2.typ == S_ABS && fitb(exp_2.val),
operand_long ? 3 : 1)) { operand_long ? 3 : 1)) {
emit1(0201); emit1(0201);
} else { } else {
emit1(0203); opc &= ~1; emit1(0203); opc &= ~1;
} }
ea_1(opc & 070); ea_1(opc & 070);
RELOMOVE(relonami, rel_2); RELOMOVE(relonami, rel_2);
opsize_exp(exp_2, (opc&1)); opsize_exp(exp_2, (opc&1));
} else if (is_reg(reg_1)) { } else if (is_reg(reg_1)) {
/* Add register or memory to register */ /* Add register or memory to register */
emit1(opc | 2); emit1(opc | 2);
ea_2((reg_1&7)<<3); ea_2((reg_1&7)<<3);
} else } else
badsyntax(); badsyntax();
} }
void rolop(register int opc) void rolop(register int opc)
{ {
register int oreg; register int oreg;
oreg = reg_2; oreg = reg_2;
reg_2 = reg_1; reg_2 = reg_1;
regsize(opc); regsize(opc);
if (oreg == (IS_R8 | 1 | (address_long ? 0 : 0300))) { 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)) { } else if (is_expr(oreg)) {
if (small(exp_2.typ == S_ABS && exp_2.val == 1, 1)) { if (small(exp_2.typ == S_ABS && exp_2.val == 1, 1)) {
/* shift by 1 */ /* shift by 1 */
emit1(0320 | (opc&1)); ea_1(opc&070); emit1(0320 | (opc&1)); ea_1(opc&070);
} else { } else {
/* shift by byte count */ /* shift by byte count */
emit1(0300 | (opc & 1)); emit1(0300 | (opc & 1));
ea_1(opc & 070); ea_1(opc & 070);
#ifdef RELOCATION #ifdef RELOCATION
RELOMOVE(relonami, rel_2); RELOMOVE(relonami, rel_2);
newrelo(exp_2.typ, RELO1); newrelo(exp_2.typ, RELO1);
#endif #endif
emit1((int)(exp_2.val)); emit1((int)(exp_2.val));
} }
} }
else else
badsyntax(); badsyntax();
} }
void incop(register int opc) void incop(register int opc)
{ {
regsize(opc); regsize(opc);
if ((opc&1) && is_reg(reg_1)) { if ((opc&1) && is_reg(reg_1)) {
/* word register */ /* word register */
emit1(0100 | (opc&010) | (reg_1&7)); emit1(0100 | (opc&010) | (reg_1&7));
} else { } else {
emit1(0376 | (opc&1)); emit1(0376 | (opc&1));
ea_1(opc & 010); ea_1(opc & 010);
} }
} }
void callop(register int opc) void callop(register int opc)
{ {
regsize(1); regsize(1);
if (is_expr(reg_1)) { if (is_expr(reg_1)) {
if (opc == (040+(0351<<8))) { if (opc == (040+(0351<<8))) {
RELOMOVE(relonami, rel_1); RELOMOVE(relonami, rel_1);
ebranch(0353,exp_1); ebranch(0353,exp_1);
} else { } else {
exp_1.val -= (DOTVAL+3 + (address_long ? 2 : 0)); exp_1.val -= (DOTVAL+3 + (address_long ? 2 : 0));
emit1(opc>>8); emit1(opc>>8);
RELOMOVE(relonami, rel_1); RELOMOVE(relonami, rel_1);
adsize_exp(exp_1, RELPC); adsize_exp(exp_1, RELPC);
} }
} else { } else {
emit1(0377); ea_1(opc&070); emit1(0377); ea_1(opc&070);
} }
} }
void xchg(register int opc) void xchg(register int opc)
{ {
regsize(opc); regsize(opc);
if (! is_reg(reg_1) || is_acc(reg_2)) { if (! is_reg(reg_1) || is_acc(reg_2)) {
reverse(); reverse();
} }
if (opc == 1 && is_acc(reg_1) && is_reg(reg_2)) { if (opc == 1 && is_acc(reg_1) && is_reg(reg_2)) {
emit1(0220 | (reg_2&7)); emit1(0220 | (reg_2&7));
} else if (is_reg(reg_1)) { } else if (is_reg(reg_1)) {
emit1(0206 | opc); ea_2((reg_1&7)<<3); emit1(0206 | opc); ea_2((reg_1&7)<<3);
} else } else
badsyntax(); badsyntax();
} }
void test(register int opc) void test(register int opc)
{ {
regsize(opc); regsize(opc);
if (is_reg(reg_2) || is_expr(reg_1)) if (is_reg(reg_2) || is_expr(reg_1))
reverse(); reverse();
if (is_expr(reg_2)) { if (is_expr(reg_2)) {
if (is_acc(reg_1)) { if (is_acc(reg_1)) {
emit1(0250 | opc); emit1(0250 | opc);
RELOMOVE(relonami, rel_2); RELOMOVE(relonami, rel_2);
opsize_exp(exp_2, (opc&1)); opsize_exp(exp_2, (opc&1));
} }
else { else {
emit1(0366 | opc); emit1(0366 | opc);
ea_1(0<<3); ea_1(0<<3);
RELOMOVE(relonami, rel_2); RELOMOVE(relonami, rel_2);
opsize_exp(exp_2, (opc&1)); opsize_exp(exp_2, (opc&1));
} }
} else if (is_reg(reg_1)) { } else if (is_reg(reg_1)) {
emit1(0204 | opc); ea_2((reg_1&7)<<3); emit1(0204 | opc); ea_2((reg_1&7)<<3);
} else } else
badsyntax(); badsyntax();
} }
void mov(register int opc) void mov(register int 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&07)<<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&07)<<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)) {
/* to register */ /* to register */
emit1(0260 | opc<<3 | (reg_1&7)); emit1(0260 | opc<<3 | (reg_1&7));
} else { } else {
/* to memory */ /* to memory */
emit1(0306 | opc); ea_1(0<<3); emit1(0306 | opc); ea_1(0<<3);
} }
RELOMOVE(relonami, rel_2); RELOMOVE(relonami, rel_2);
opsize_exp(exp_2, (opc&1)); opsize_exp(exp_2, (opc&1));
} else if (rm_1 == 05 && is_acc(reg_2)) { } else if (rm_1 == 05 && is_acc(reg_2)) {
/* from accumulator to memory (displacement) */ /* from accumulator to memory (displacement) */
emit1(0242 | opc); emit1(0242 | opc);
RELOMOVE(relonami, rel_1); RELOMOVE(relonami, rel_1);
adsize_exp(exp_1, 0); adsize_exp(exp_1, 0);
} else if (rm_2 == 05 && is_acc(reg_1)) { } else if (rm_2 == 05 && is_acc(reg_1)) {
/* from memory (displacement) to accumulator */ /* from memory (displacement) to accumulator */
emit1(0240 | opc); emit1(0240 | opc);
RELOMOVE(relonami, rel_2); RELOMOVE(relonami, rel_2);
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&07)<<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&07)<<3); emit1(0212 | opc); ea_2((reg_1&07)<<3);
} else } else
badsyntax(); badsyntax();
} }
void extshft(int opc, int reg) void extshft(int opc, int reg)
{ {
int oreg2 = reg_2; int oreg2 = reg_2;
reg_2 = reg_1; reg_2 = reg_1;
regsize(1); regsize(1);
emit1(0xF); emit1(0xF);
if (oreg2 == (IS_R8 | 1 | (address_long ? 0 : 0300))) { 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);
} }
else if (is_expr(oreg2)) { else if (is_expr(oreg2)) {
emit1(opc); emit1(opc);
ea_1(reg << 3); ea_1(reg << 3);
#ifdef RELOCATION #ifdef RELOCATION
RELOMOVE(relonami, rel_2); RELOMOVE(relonami, rel_2);
newrelo(exp_2.typ, RELO1); newrelo(exp_2.typ, RELO1);
#endif #endif
emit1((int)(exp_2.val)); emit1((int)(exp_2.val));
} }
else badsyntax(); else badsyntax();
} }
void bittestop(int opc) void bittestop(int opc)
{ {
regsize(1); regsize(1);
emit1(0xF); emit1(0xF);
if (is_expr(reg_2)) { if (is_expr(reg_2)) {
emit1(0272); emit1(0272);
ea_1(opc << 3); ea_1(opc << 3);
#ifdef RELOCATION #ifdef RELOCATION
RELOMOVE(relonami, rel_2); RELOMOVE(relonami, rel_2);
newrelo(exp_2.typ, RELO1); newrelo(exp_2.typ, RELO1);
#endif #endif
emit1((int)(exp_2.val)); emit1((int)(exp_2.val));
} }
else if (is_reg(reg_2)) { else if (is_reg(reg_2)) {
emit1(0203 | (opc<<3)); emit1(0203 | (opc<<3));
ea_1((reg_2&7)<<3); ea_1((reg_2&7)<<3);
} }
else badsyntax(); else badsyntax();
} }
void imul(int reg) void imul(int reg)
{ {
/* This instruction is more elaborate on the 80386. Its most /* This instruction is more elaborate on the 80386. Its most
general form is: general form is:
imul reg, reg_or_mem, immediate. imul reg, reg_or_mem, immediate.
This is the form processed here. This is the form processed here.
*/ */
regsize(1); regsize(1);
if (is_expr(reg_1)) { if (is_expr(reg_1)) {
/* To also handle /* To also handle
imul reg, immediate, reg_or_mem imul reg, immediate, reg_or_mem
*/ */
reverse(); reverse();
} }
if (is_expr(reg_2)) { if (is_expr(reg_2)) {
/* The immediate form; two cases: */ /* The immediate form; two cases: */
if (small(exp_2.typ == S_ABS && fitb(exp_2.val), if (small(exp_2.typ == S_ABS && fitb(exp_2.val),
operand_long ? 3 : 1)) { operand_long ? 3 : 1)) {
/* case 1: 1 byte encoding of immediate */ /* case 1: 1 byte encoding of immediate */
emit1(0153); emit1(0153);
ea_1((reg & 07) << 3); ea_1((reg & 07) << 3);
emit1((int)(exp_2.val)); emit1((int)(exp_2.val));
} }
else { else {
/* case 2: WORD or DWORD encoding of immediate */ /* case 2: WORD or DWORD encoding of immediate */
emit1(0151); emit1(0151);
ea_1((reg & 07) << 3); ea_1((reg & 07) << 3);
RELOMOVE(relonami, rel_2); RELOMOVE(relonami, rel_2);
opsize_exp(exp_2, 1); opsize_exp(exp_2, 1);
} }
} }
else if (is_reg(reg_1) && ((reg_1&7) == (reg & 07))) { else if (is_reg(reg_1) && ((reg_1&7) == (reg & 07))) {
/* the "reg" field and the "reg_or_mem" field are the same, /* the "reg" field and the "reg_or_mem" field are the same,
and the 3rd operand is not an immediate ... and the 3rd operand is not an immediate ...
*/ */
if (reg == 0) { if (reg == 0) {
/* how lucky we are, the target is the ax register */ /* how lucky we are, the target is the ax register */
/* However, we cannot make an optimization for f.i. /* However, we cannot make an optimization for f.i.
imul eax, blablabla imul eax, blablabla
because the latter does not affect edx, whereas because the latter does not affect edx, whereas
imul blablabla imul blablabla
does! Therefore, "reg" is or-ed with 0x10 in the does! Therefore, "reg" is or-ed with 0x10 in the
former case, so that the test above fails. former case, so that the test above fails.
*/ */
emit1(0367); emit1(0367);
ea_2(050); ea_2(050);
} }
else { else {
/* another register ... */ /* another register ... */
emit1(0xF); emit1(0xF);
emit1(0257); emit1(0257);
ea_2((reg & 07) << 3); ea_2((reg & 07) << 3);
} }
} }
else badsyntax(); else badsyntax();
} }
// vim: ts=8 sw=8 et