Hacky workaround to make lar work.
This commit is contained in:
parent
b868c1ece9
commit
967b46e98e
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue