Add IMUL Gv,Ev
Add LES,LDS,LFS,LGS Add POP FS/GS PUSH FS/GS Add MOVZX/MOVSX Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1541
This commit is contained in:
parent
c663205a59
commit
df06393f64
2 changed files with 134 additions and 2 deletions
|
@ -286,6 +286,24 @@ static void dyn_dop_evgv(DualOps op) {
|
|||
}
|
||||
}
|
||||
|
||||
static void dyn_imul_gvev(Bitu immsize) {
|
||||
dyn_get_modrm();DynReg * src;
|
||||
DynReg * rm_reg=&DynRegs[decode.modrm.reg];
|
||||
if (decode.modrm.mod<3) {
|
||||
dyn_fill_ea();dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op);
|
||||
src=DREG(TMPW);gen_releasereg(DREG(EA));
|
||||
} else {
|
||||
src=&DynRegs[decode.modrm.rm];
|
||||
}
|
||||
switch (immsize) {
|
||||
case 0:gen_imul_word(decode.big_op,rm_reg,src);break;
|
||||
case 1:gen_imul_word_imm(decode.big_op,rm_reg,src,(Bit8s)decode_fetchb());break;
|
||||
case 2:gen_imul_word_imm(decode.big_op,rm_reg,src,(Bit16s)decode_fetchw());break;
|
||||
case 4:gen_imul_word_imm(decode.big_op,rm_reg,src,(Bit32s)decode_fetchd());break;
|
||||
}
|
||||
gen_releasereg(DREG(TMPW));
|
||||
}
|
||||
|
||||
static void dyn_dop_gvev(DualOps op) {
|
||||
dyn_get_modrm();
|
||||
DynReg * rm_reg=&DynRegs[decode.modrm.reg];
|
||||
|
@ -334,6 +352,34 @@ static void dyn_mov_eviv(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static void dyn_mov_ev_gb(bool sign) {
|
||||
dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg];
|
||||
if (decode.modrm.mod<3) {
|
||||
dyn_fill_ea();
|
||||
dyn_read_byte(DREG(EA),DREG(TMPB),false);
|
||||
gen_releasereg(DREG(EA));
|
||||
gen_extend_byte(sign,decode.big_op,rm_reg,DREG(TMPB),0);
|
||||
} else {
|
||||
gen_extend_byte(sign,decode.big_op,rm_reg,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
|
||||
}
|
||||
}
|
||||
|
||||
static void dyn_mov_ev_gw(bool sign) {
|
||||
if (!decode.big_op) {
|
||||
dyn_mov_evgv();
|
||||
return;
|
||||
}
|
||||
dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg];
|
||||
if (decode.modrm.mod<3) {
|
||||
dyn_fill_ea();
|
||||
dyn_read_word(DREG(EA),DREG(TMPW),false);
|
||||
gen_releasereg(DREG(EA));
|
||||
gen_extend_word(sign,rm_reg,DREG(TMPW));
|
||||
} else {
|
||||
gen_extend_word(sign,rm_reg,&DynRegs[decode.modrm.rm]);
|
||||
}
|
||||
}
|
||||
|
||||
static void dyn_dshift_ev_gv(bool left,bool immediate) {
|
||||
dyn_get_modrm();
|
||||
DynReg * rm_reg=&DynRegs[decode.modrm.reg];
|
||||
|
@ -552,7 +598,6 @@ skipsave:
|
|||
gen_releasereg(DREG(TMPW));gen_releasereg(DREG(EA));
|
||||
}
|
||||
|
||||
|
||||
static void dyn_mov_ev_seg(void) {
|
||||
dyn_get_modrm();
|
||||
gen_load_host(&Segs.val[decode.modrm.reg],DREG(TMPW),2);
|
||||
|
@ -593,6 +638,20 @@ static void dyn_load_seg(SegNames seg,DynReg * src,bool withpop) {
|
|||
if (seg==ss) gen_releasereg(DREG(SMASK));
|
||||
}
|
||||
|
||||
static void dyn_load_seg_off_ea(SegNames seg) {
|
||||
dyn_get_modrm();
|
||||
if (decode.modrm.mod<3) {
|
||||
dyn_fill_ea();
|
||||
gen_lea(DREG(TMPW),DREG(EA),0,0,decode.big_op ? 4:2);
|
||||
dyn_read_word(DREG(TMPW),DREG(TMPW),false);
|
||||
dyn_load_seg(seg,DREG(TMPW),false);
|
||||
dyn_read_word(DREG(EA),&DynRegs[decode.modrm.reg],decode.big_op);
|
||||
gen_releasereg(DREG(EA));
|
||||
} else {
|
||||
IllegalOption();
|
||||
}
|
||||
}
|
||||
|
||||
static void dyn_mov_seg_ev(void) {
|
||||
dyn_get_modrm();
|
||||
SegNames seg=(SegNames)decode.modrm.reg;
|
||||
|
@ -893,12 +952,30 @@ restart_prefix:
|
|||
dyn_branched_exit((BranchTypes)(dual_code&0xf),
|
||||
decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw());
|
||||
return decode.block;
|
||||
/* PUSH/POP FS */
|
||||
case 0xa0:dyn_push_seg(fs);break;
|
||||
case 0xa1:dyn_pop_seg(fs);break;
|
||||
/* SHLD Imm/cl*/
|
||||
case 0xa4:dyn_dshift_ev_gv(true,true);break;
|
||||
case 0xa5:dyn_dshift_ev_gv(true,false);break;
|
||||
/* PUSH/POP GS */
|
||||
case 0xa8:dyn_push_seg(gs);break;
|
||||
case 0xa9:dyn_pop_seg(gs);break;
|
||||
/* SHRD Imm/cl*/
|
||||
case 0xac:dyn_dshift_ev_gv(false,true);break;
|
||||
case 0xad:dyn_dshift_ev_gv(false,false);break;
|
||||
case 0xad:dyn_dshift_ev_gv(false,false);break;
|
||||
/* Imul Ev,Gv */
|
||||
case 0xaf:dyn_imul_gvev(0);break;
|
||||
/* LFS,LGS */
|
||||
case 0xb4:dyn_load_seg_off_ea(fs);break;
|
||||
case 0xb5:dyn_load_seg_off_ea(gs);break;
|
||||
/* MOVZX Gv,Eb/Ew */
|
||||
case 0xb6:dyn_mov_ev_gb(false);break;
|
||||
case 0xb7:dyn_mov_ev_gw(false);break;
|
||||
/* MOVSX Gv,Eb/Ew */
|
||||
case 0xbe:dyn_mov_ev_gb(true);break;
|
||||
case 0xbf:dyn_mov_ev_gw(true);break;
|
||||
|
||||
default:
|
||||
DYN_LOG("Unhandled dual opcode 0F%02X",dual_code);
|
||||
goto illegalopcode;
|
||||
|
@ -1002,11 +1079,15 @@ restart_prefix:
|
|||
dyn_push(DREG(TMPW));
|
||||
gen_releasereg(DREG(TMPW));
|
||||
break;
|
||||
/* Imul Ivx */
|
||||
case 0x69:dyn_imul_gvev(decode.big_op ? 4 : 2);break;
|
||||
case 0x6a: /* PUSH Ibx */
|
||||
gen_dop_word_imm(DOP_MOV,true,DREG(TMPW),(Bit8s)decode_fetchb());
|
||||
dyn_push(DREG(TMPW));
|
||||
gen_releasereg(DREG(TMPW));
|
||||
break;
|
||||
/* Imul Ibx */
|
||||
case 0x6b:dyn_imul_gvev(1);break;
|
||||
/* Short conditional jumps */
|
||||
case 0x70:case 0x71:case 0x72:case 0x73:case 0x74:case 0x75:case 0x76:case 0x77:
|
||||
case 0x78:case 0x79:case 0x7a:case 0x7b:case 0x7c:case 0x7d:case 0x7e:case 0x7f:
|
||||
|
@ -1049,8 +1130,15 @@ restart_prefix:
|
|||
break;
|
||||
/* CBW/CWDE */
|
||||
case 0x98:
|
||||
/*
|
||||
if (decode.big_op) gen_extend_word(true,DREG(EAX),DREG(EAX));
|
||||
else gen_extend_byte(true,false,DREG(EAX),DREG(EAX),0);
|
||||
*/
|
||||
gen_cbw(decode.big_op,DREG(EAX));
|
||||
break;
|
||||
/* CWD/CDQ */
|
||||
case 0x99:
|
||||
gen_cwd(decode.big_op,DREG(EAX),DREG(EDX));
|
||||
break;
|
||||
/* CALL FAR Ip */
|
||||
case 0x9a:dyn_call_far_imm();return decode.block;
|
||||
|
@ -1100,6 +1188,9 @@ restart_prefix:
|
|||
//RET near Iw / Ret
|
||||
case 0xc2:dyn_ret_near(decode_fetchw());return decode.block;
|
||||
case 0xc3:dyn_ret_near(0);return decode.block;
|
||||
//LES/LDS
|
||||
case 0xc4:dyn_load_seg_off_ea(es);break;
|
||||
case 0xc5:dyn_load_seg_off_ea(ds);break;
|
||||
// MOV Eb/Ev,Ib/Iv
|
||||
case 0xc6:dyn_mov_ebib();break;
|
||||
case 0xc7:dyn_mov_eviv();break;
|
||||
|
|
|
@ -423,6 +423,32 @@ static void gen_dop_word_imm(DualOps op,bool dword,DynReg * dr1,Bits imm) {
|
|||
if (dword) cache_addd(imm);
|
||||
else cache_addw(imm);
|
||||
}
|
||||
|
||||
static void gen_imul_word(bool dword,DynReg * dr1,DynReg * dr2) {
|
||||
GenReg * gr1=FindDynReg(dr1);GenReg * gr2=FindDynReg(dr2);
|
||||
if (!dword) cache_addb(0x66);
|
||||
cache_addw(0xaf0f);
|
||||
cache_addb(0xc0+(gr1->index<<3)+gr2->index);
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_imul_word_imm(bool dword,DynReg * dr1,DynReg * dr2,Bits imm) {
|
||||
GenReg * gr1=FindDynReg(dr1);GenReg * gr2=FindDynReg(dr2);
|
||||
if (!dword) cache_addb(0x66);
|
||||
if ((imm>=-128 && imm<=127)) {
|
||||
cache_addb(0x6b);
|
||||
cache_addb(0xc0+(gr1->index<<3)+gr2->index);
|
||||
cache_addb(imm);
|
||||
} else {
|
||||
cache_addb(0x69);
|
||||
cache_addb(0xc0+(gr1->index<<3)+gr2->index);
|
||||
if (dword) cache_addd(imm);
|
||||
else cache_addw(imm);
|
||||
}
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
|
||||
static void gen_sop_word(SingleOps op,bool dword,DynReg * dr1) {
|
||||
GenReg * gr1=FindDynReg(dr1);
|
||||
if (!dword) cache_addb(0x66);
|
||||
|
@ -472,6 +498,21 @@ static void gen_shift_word(ShiftOps op,DynReg * drecx,bool dword,DynReg * dr1) {
|
|||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_cbw(bool dword,DynReg * dyn_ax) {
|
||||
ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax);
|
||||
if (!dword) cache_addb(0x66);
|
||||
cache_addb(0x98);
|
||||
dyn_ax->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_cwd(bool dword,DynReg * dyn_ax,DynReg * dyn_dx) {
|
||||
ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax);
|
||||
ForceDynReg(x86gen.regs[X86_REG_EDX],dyn_dx);
|
||||
if (!dword) cache_addb(0x66);
|
||||
cache_addb(0x99);
|
||||
dyn_ax->flags|=DYNFLG_CHANGED;
|
||||
dyn_dx->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_mul_byte(bool imul,DynReg * dyn_ax,DynReg * dr1,Bit8u di1) {
|
||||
ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax);
|
||||
|
|
Loading…
Add table
Reference in a new issue