Add string operations for MOVS,STOS,LODS
Change the way temporary registers are handled with loading and saving Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1560
This commit is contained in:
parent
449d45643c
commit
2394f38514
4 changed files with 274 additions and 21 deletions
|
@ -70,7 +70,6 @@ enum DualOps {
|
|||
DOP_AND,DOP_OR,
|
||||
DOP_MOV,
|
||||
DOP_TEST,
|
||||
DOP_IMUL,
|
||||
DOP_XCHG,
|
||||
};
|
||||
|
||||
|
@ -108,8 +107,8 @@ enum BlockReturn {
|
|||
#define DYNFLG_HAS8 0x2 //Would like 16-bit host reg support
|
||||
#define DYNFLG_LOAD 0x4 //Load value when accessed
|
||||
#define DYNFLG_SAVE 0x8 //Needs to be saved back at the end of block
|
||||
#define DYNFLG_CHANGED 0x10 //Load value only once because of save
|
||||
#define DYNFLG_LOADONCE 0x20 //Load value only once because of save
|
||||
#define DYNFLG_CHANGED 0x10 //Value is in a register and changed from load
|
||||
#define DYNFLG_ACTIVE 0x20 //Register has an active value
|
||||
|
||||
class GenReg;
|
||||
class CodePageHandler;
|
||||
|
@ -325,7 +324,7 @@ void CPU_Core_Dyn_X86_Init(void) {
|
|||
DynRegs[G_STACK].data=&extra_regs.stack;
|
||||
DynRegs[G_STACK].flags=0;
|
||||
DynRegs[G_CYCLES].data=&CPU_Cycles;
|
||||
DynRegs[G_CYCLES].flags=DYNFLG_LOAD|DYNFLG_SAVE;;
|
||||
DynRegs[G_CYCLES].flags=DYNFLG_LOAD|DYNFLG_SAVE;
|
||||
DynRegs[G_TMPB].data=&extra_regs.tmpb;
|
||||
DynRegs[G_TMPB].flags=DYNFLG_HAS8|DYNFLG_HAS16;
|
||||
DynRegs[G_TMPW].data=&extra_regs.tmpd;
|
||||
|
|
|
@ -1,10 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2004 The DOSBox Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
enum REP_Type {
|
||||
REP_NONE=0,REP_NZ,REP_Z
|
||||
};
|
||||
|
||||
static struct DynDecode {
|
||||
PhysPt code;
|
||||
PhysPt code_start;
|
||||
PhysPt op_start;
|
||||
bool big_op;
|
||||
bool big_addr;
|
||||
bool rep;
|
||||
REP_Type rep;
|
||||
Bitu cycles;
|
||||
CacheBlock * block;
|
||||
struct {
|
||||
|
@ -16,8 +38,6 @@ static struct DynDecode {
|
|||
DynReg * segprefix;
|
||||
} decode;
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
static Bit8u INLINE decode_fetchb(void) {
|
||||
return mem_readb(decode.code++);
|
||||
}
|
||||
|
@ -49,6 +69,7 @@ static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) {
|
|||
else gen_call_function((void *)&mem_writew,"%Dd%Dw",addr,val);
|
||||
}
|
||||
|
||||
|
||||
static void dyn_reduce_cycles(void) {
|
||||
if (!decode.cycles) decode.cycles++;
|
||||
gen_lea(DREG(CYCLES),DREG(CYCLES),0,0,-(Bits)decode.cycles);
|
||||
|
@ -209,6 +230,9 @@ static void dyn_fill_ea(bool addseg=true) {
|
|||
}
|
||||
}
|
||||
|
||||
#include "helpers.h"
|
||||
#include "string.h"
|
||||
|
||||
static void dyn_dop_ebgb(DualOps op) {
|
||||
dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];
|
||||
if (decode.modrm.mod<3) {
|
||||
|
@ -359,6 +383,7 @@ static void dyn_mov_ev_gb(bool sign) {
|
|||
dyn_read_byte(DREG(EA),DREG(TMPB),false);
|
||||
gen_releasereg(DREG(EA));
|
||||
gen_extend_byte(sign,decode.big_op,rm_reg,DREG(TMPB),0);
|
||||
gen_releasereg(DREG(TMPB));
|
||||
} else {
|
||||
gen_extend_byte(sign,decode.big_op,rm_reg,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
|
||||
}
|
||||
|
@ -644,7 +669,7 @@ static void dyn_load_seg_off_ea(SegNames seg) {
|
|||
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_load_seg(seg,DREG(TMPW),false);gen_releasereg(DREG(TMPW));
|
||||
dyn_read_word(DREG(EA),&DynRegs[decode.modrm.reg],decode.big_op);
|
||||
gen_releasereg(DREG(EA));
|
||||
} else {
|
||||
|
@ -900,7 +925,7 @@ static CacheBlock * CreateCacheBlock(PhysPt start,bool big,Bitu max_opcodes) {
|
|||
decode.block=cache_openblock();
|
||||
gen_save_host_direct(&cache.block.running,(Bit32u)decode.block);
|
||||
for (i=0;i<G_MAX;i++) {
|
||||
DynRegs[i].flags&=~(DYNFLG_LOADONCE|DYNFLG_CHANGED);
|
||||
DynRegs[i].flags&=~(DYNFLG_ACTIVE|DYNFLG_CHANGED);
|
||||
DynRegs[i].genreg=0;
|
||||
}
|
||||
gen_reinit();
|
||||
|
@ -919,7 +944,7 @@ static CacheBlock * CreateCacheBlock(PhysPt start,bool big,Bitu max_opcodes) {
|
|||
decode.big_addr=big;
|
||||
decode.big_op=big;
|
||||
decode.segprefix=0;
|
||||
decode.rep=false;
|
||||
decode.rep=REP_NONE;
|
||||
decode.cycles++;
|
||||
decode.op_start=decode.code;
|
||||
restart_prefix:
|
||||
|
@ -1170,10 +1195,18 @@ restart_prefix:
|
|||
dyn_write_word(DREG(EA),DREG(EAX),decode.big_op);
|
||||
gen_releasereg(DREG(EA));
|
||||
break;
|
||||
/* MOVSB/W/D*/
|
||||
case 0xa4:dyn_string(STR_MOVSB);break;
|
||||
case 0xa5:dyn_string(decode.big_op ? STR_MOVSD : STR_MOVSW);break;
|
||||
/* TEST AL,AX Imm */
|
||||
case 0xa8:gen_dop_byte_imm(DOP_TEST,DREG(EAX),0,decode_fetchb());break;
|
||||
case 0xa9:gen_dop_word_imm(DOP_TEST,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());break;
|
||||
|
||||
/* STOSB/W/D*/
|
||||
case 0xaa:dyn_string(STR_STOSB);break;
|
||||
case 0xab:dyn_string(decode.big_op ? STR_STOSD : STR_STOSW);break;
|
||||
/* LODSB/W/D*/
|
||||
case 0xac:dyn_string(STR_LODSB);break;
|
||||
case 0xad:dyn_string(decode.big_op ? STR_LODSD : STR_LODSW);break;
|
||||
//Mov Byte reg,Imm byte
|
||||
case 0xb0:case 0xb1:case 0xb2:case 0xb3:case 0xb4:case 0xb5:case 0xb6:case 0xb7:
|
||||
gen_dop_byte_imm(DOP_MOV,&DynRegs[opcode&3],opcode&4,decode_fetchb());
|
||||
|
@ -1257,6 +1290,12 @@ restart_prefix:
|
|||
gen_call_function((void*)&IO_WriteW,"%Dw%Dw",DREG(EDX),DREG(EAX));
|
||||
}
|
||||
break;
|
||||
case 0xf2: //REPNE/NZ
|
||||
decode.rep=REP_NZ;
|
||||
goto restart_prefix;
|
||||
case 0xf3: //REPE/Z
|
||||
decode.rep=REP_Z;
|
||||
goto restart_prefix;
|
||||
/* Change carry flag */
|
||||
case 0xf5: //CMC
|
||||
case 0xf8: //CLC
|
||||
|
|
|
@ -1,4 +1,20 @@
|
|||
#define GEN_HAS_IMM 1
|
||||
/*
|
||||
* Copyright (C) 2002-2004 The DOSBox Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
static void gen_init(void);
|
||||
|
||||
|
@ -39,11 +55,11 @@ public:
|
|||
last_used=x86gen.last_used;
|
||||
dynreg->flags&=~DYNFLG_CHANGED;
|
||||
dynreg->genreg=this;
|
||||
if (dynreg->flags & (DYNFLG_LOAD|DYNFLG_LOADONCE)) {
|
||||
dynreg->flags&=~DYNFLG_LOADONCE;
|
||||
if (dynreg->flags & (DYNFLG_LOAD|DYNFLG_ACTIVE)) {
|
||||
cache_addw(0x058b+(index << (8+3))); //Mov reg,[data]
|
||||
cache_addd((Bit32u)dynreg->data);
|
||||
}
|
||||
dynreg->flags|=DYNFLG_ACTIVE;
|
||||
}
|
||||
void Save(void) {
|
||||
if (!dynreg) IllegalOption();
|
||||
|
@ -56,13 +72,12 @@ public:
|
|||
if (dynreg->flags&DYNFLG_CHANGED && dynreg->flags&DYNFLG_SAVE) {
|
||||
Save();
|
||||
}
|
||||
dynreg->flags&=~(DYNFLG_CHANGED|DYNFLG_LOADONCE);
|
||||
dynreg->flags&=~(DYNFLG_CHANGED|DYNFLG_ACTIVE);
|
||||
dynreg->genreg=0;dynreg=0;
|
||||
}
|
||||
void Clear(void) {
|
||||
if (!dynreg) return;
|
||||
if (dynreg->flags&DYNFLG_CHANGED) {
|
||||
dynreg->flags|=DYNFLG_LOADONCE;
|
||||
Save();
|
||||
}
|
||||
dynreg->genreg=0;dynreg=0;
|
||||
|
@ -176,10 +191,15 @@ static GenReg * ForceDynReg(GenReg * genreg,DynReg * dynreg) {
|
|||
genreg->Load(dynreg);
|
||||
return genreg;
|
||||
}
|
||||
|
||||
static void gen_preloadreg(DynReg * dynreg) {
|
||||
FindDynReg(dynreg);
|
||||
}
|
||||
|
||||
static void gen_releasereg(DynReg * dynreg) {
|
||||
GenReg * genreg=dynreg->genreg;
|
||||
if (genreg) genreg->Release();
|
||||
else dynreg->flags&=~(DYNFLG_LOADONCE|DYNFLG_CHANGED);
|
||||
else dynreg->flags&=~(DYNFLG_ACTIVE|DYNFLG_CHANGED);
|
||||
}
|
||||
|
||||
static void gen_setupreg(DynReg * dnew,DynReg * dsetup) {
|
||||
|
@ -203,12 +223,12 @@ static void gen_synchreg(DynReg * dnew,DynReg * dsynch) {
|
|||
}
|
||||
}
|
||||
/* Always use the loadonce flag from either state */
|
||||
dnew->flags|=(dsynch->flags & dnew->flags&DYNFLG_LOADONCE);
|
||||
dnew->flags|=(dsynch->flags & dnew->flags&DYNFLG_ACTIVE);
|
||||
if ((dnew->flags ^ dsynch->flags) & DYNFLG_CHANGED) {
|
||||
/* Ensure the changed value gets saved */
|
||||
if (dnew->flags & DYNFLG_CHANGED) {
|
||||
dnew->genreg->Save();
|
||||
}
|
||||
} else dnew->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -498,6 +518,24 @@ static void gen_shift_word(ShiftOps op,DynReg * drecx,bool dword,DynReg * dr1) {
|
|||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_shift_word_imm(ShiftOps op,bool dword,DynReg * dr1,Bit8u imm) {
|
||||
GenReg * gr1=FindDynReg(dr1);
|
||||
if (!dword) cache_addb(0x66);
|
||||
switch (op) {
|
||||
case SHIFT_ROL:cache_addw(0xc0c1+((gr1->index)<<8));break;
|
||||
case SHIFT_ROR:cache_addw(0xc8c1+((gr1->index)<<8));break;
|
||||
case SHIFT_RCL:cache_addw(0xd0c1+((gr1->index)<<8));break;
|
||||
case SHIFT_RCR:cache_addw(0xd8c1+((gr1->index)<<8));break;
|
||||
case SHIFT_SHL:cache_addw(0xe0c1+((gr1->index)<<8));break;
|
||||
case SHIFT_SHR:cache_addw(0xe8c1+((gr1->index)<<8));break;
|
||||
case SHIFT_SAR:cache_addw(0xf8c1+((gr1->index)<<8));break;
|
||||
default:
|
||||
IllegalOption();
|
||||
}
|
||||
cache_addb(imm);
|
||||
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);
|
||||
|
@ -678,10 +716,22 @@ static Bit8u * gen_create_branch(BranchTypes type) {
|
|||
return (cache.pos-1);
|
||||
}
|
||||
|
||||
static void gen_fill_branch(Bit8u * data) {
|
||||
*data=(cache.pos-data-1);
|
||||
static void gen_fill_branch(Bit8u * data,Bit8u * from=cache.pos) {
|
||||
*data=(from-data-1);
|
||||
}
|
||||
|
||||
static Bit8u * gen_create_jump(Bit8u * to=0) {
|
||||
/* First free all registers */
|
||||
cache_addb(0xe9);
|
||||
cache_addd(to-(cache.pos+4));
|
||||
return (cache.pos-4);
|
||||
}
|
||||
|
||||
static void gen_fill_jump(Bit8u * data,Bit8u * to=cache.pos) {
|
||||
*(Bit32u*)data=(to-data-4);
|
||||
}
|
||||
|
||||
|
||||
static void gen_jmp_ptr(void * ptr,Bits imm=0) {
|
||||
cache_addb(0xa1);
|
||||
cache_addd((Bit32u)ptr);
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2004 The DOSBox Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
enum STRING_OP {
|
||||
STR_OUTSB=0,STR_OUTSW,STR_OUTSD,
|
||||
STR_INSB=4,STR_INSW,STR_INSD,
|
||||
STR_MOVSB=8,STR_MOVSW,STR_MOVSD,
|
||||
STR_LODSB=12,STR_LODSW,STR_LODSD,
|
||||
STR_STOSB=16,STR_STOSW,STR_STOSD,
|
||||
STR_SCASB=20,STR_SCASW,STR_SCASD,
|
||||
STR_CMPSB=24,STR_CMPSW,STR_CMPSD,
|
||||
};
|
||||
|
||||
static void dyn_string(STRING_OP op) {
|
||||
DynReg * si_base=decode.segprefix ? decode.segprefix : DREG(DS);
|
||||
DynReg * di_base=DREG(ES);
|
||||
DynReg * tmp_reg;bool usesi;bool usedi;
|
||||
gen_storeflags();
|
||||
if (decode.rep) {
|
||||
gen_dop_word_imm(DOP_SUB,true,DREG(CYCLES),decode.cycles);
|
||||
gen_releasereg(DREG(CYCLES));
|
||||
decode.cycles=0;
|
||||
}
|
||||
/* Check what each string operation will be using */
|
||||
switch (op) {
|
||||
case STR_MOVSB: case STR_MOVSW: case STR_MOVSD:
|
||||
case STR_CMPSB: case STR_CMPSW: case STR_CMPSD:
|
||||
tmp_reg=DREG(TMPB);usesi=true;usedi=true;break;
|
||||
case STR_LODSB: case STR_LODSW: case STR_LODSD:
|
||||
tmp_reg=DREG(EAX);usesi=true;usedi=false;break;
|
||||
case STR_OUTSB: case STR_OUTSW: case STR_OUTSD:
|
||||
tmp_reg=DREG(TMPB);usesi=true;usedi=false;break;
|
||||
case STR_SCASB: case STR_SCASW: case STR_SCASD:
|
||||
case STR_STOSB: case STR_STOSW: case STR_STOSD:
|
||||
tmp_reg=DREG(EAX);usesi=false;usedi=true;break;
|
||||
case STR_INSB: case STR_INSW: case STR_INSD:
|
||||
tmp_reg=DREG(TMPB);usesi=false;usedi=true;break;
|
||||
default:
|
||||
IllegalOption();
|
||||
}
|
||||
gen_load_host(&cpu.direction,DREG(TMPW),4);
|
||||
switch (op & 3) {
|
||||
case 0:break;
|
||||
case 1:gen_shift_word_imm(SHIFT_SHL,true,DREG(TMPW),1);break;
|
||||
case 2:gen_shift_word_imm(SHIFT_SHL,true,DREG(TMPW),2);break;
|
||||
default:
|
||||
IllegalOption();
|
||||
|
||||
}
|
||||
if (usesi) {
|
||||
gen_preloadreg(DREG(ESI));
|
||||
DynRegs[G_ESI].flags|=DYNFLG_CHANGED;
|
||||
gen_preloadreg(si_base);
|
||||
}
|
||||
if (usedi) {
|
||||
gen_preloadreg(DREG(EDI));
|
||||
DynRegs[G_EDI].flags|=DYNFLG_CHANGED;
|
||||
gen_preloadreg(di_base);
|
||||
}
|
||||
if (decode.rep) {
|
||||
gen_preloadreg(DREG(ECX));
|
||||
DynRegs[G_ECX].flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
DynState rep_state;
|
||||
dyn_savestate(&rep_state);
|
||||
Bit8u * rep_start=cache.pos;
|
||||
Bit8u * rep_ecx_jmp;
|
||||
/* Check if ECX!=zero and decrease it */
|
||||
if (decode.rep) {
|
||||
gen_dop_word(DOP_OR,decode.big_addr,DREG(ECX),DREG(ECX));
|
||||
Bit8u * branch_ecx=gen_create_branch(BR_NZ);
|
||||
rep_ecx_jmp=gen_create_jump();
|
||||
gen_fill_branch(branch_ecx);
|
||||
gen_sop_word(SOP_DEC,decode.big_addr,DREG(ECX));
|
||||
}
|
||||
if (usesi) {
|
||||
if (!decode.big_addr) {
|
||||
gen_extend_word(false,DREG(EA),DREG(ESI));
|
||||
gen_lea(DREG(EA),si_base,DREG(EA),0,0);
|
||||
} else {
|
||||
gen_lea(DREG(EA),si_base,DREG(ESI),0,0);
|
||||
}
|
||||
gen_dop_word(DOP_ADD,decode.big_addr,DREG(ESI),DREG(TMPW));
|
||||
switch (op&3) {
|
||||
case 0:dyn_read_byte(DREG(EA),tmp_reg,false);break;
|
||||
case 1:dyn_read_word(DREG(EA),tmp_reg,false);break;
|
||||
case 2:dyn_read_word(DREG(EA),tmp_reg,true);break;
|
||||
}
|
||||
switch (op) {
|
||||
case STR_OUTSB:
|
||||
gen_call_function((void*)&IO_WriteB,"%Id%Dl",DREG(EDX),tmp_reg);break;
|
||||
case STR_OUTSW:
|
||||
gen_call_function((void*)&IO_WriteW,"%Id%Dw",DREG(EDX),tmp_reg);break;
|
||||
case STR_OUTSD:
|
||||
gen_call_function((void*)&IO_WriteD,"%Id%Dd",DREG(EDX),tmp_reg);break;
|
||||
}
|
||||
}
|
||||
if (usedi) {
|
||||
if (!decode.big_addr) {
|
||||
gen_extend_word(false,DREG(EA),DREG(EDI));
|
||||
gen_lea(DREG(EA),di_base,DREG(EA),0,0);
|
||||
} else {
|
||||
gen_lea(DREG(EA),di_base,DREG(EDI),0,0);
|
||||
}
|
||||
gen_dop_word(DOP_ADD,decode.big_addr,DREG(EDI),DREG(TMPW));
|
||||
/* Maybe something special to be done to fill the value */
|
||||
switch (op) {
|
||||
case STR_INSB:
|
||||
gen_call_function((void*)&IO_ReadB,"%Dw%Rl",DREG(EDX),tmp_reg);
|
||||
case STR_MOVSB:
|
||||
case STR_STOSB:
|
||||
dyn_write_byte(DREG(EA),tmp_reg,false);
|
||||
break;
|
||||
case STR_INSW:
|
||||
gen_call_function((void*)&IO_ReadW,"%Dw%Rw",DREG(EDX),tmp_reg);
|
||||
case STR_MOVSW:
|
||||
case STR_STOSW:
|
||||
dyn_write_word(DREG(EA),tmp_reg,false);
|
||||
break;
|
||||
case STR_INSD:
|
||||
gen_call_function((void*)&IO_ReadD,"%Dw%Rd",DREG(EDX),tmp_reg);
|
||||
case STR_MOVSD:
|
||||
case STR_STOSD:
|
||||
dyn_write_word(DREG(EA),tmp_reg,true);
|
||||
break;
|
||||
default:
|
||||
IllegalOption();
|
||||
}
|
||||
}
|
||||
gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPB));
|
||||
if (decode.rep) {
|
||||
DynState cycle_state;
|
||||
gen_sop_word(SOP_DEC,true,DREG(CYCLES));
|
||||
gen_releasereg(DREG(CYCLES));
|
||||
dyn_savestate(&cycle_state);
|
||||
Bit8u * cycle_branch=gen_create_branch(BR_NLE);
|
||||
gen_lea(DREG(EIP),DREG(EIP),0,0,decode.op_start-decode.code_start);
|
||||
dyn_releaseregs();
|
||||
gen_restoreflags(true);
|
||||
gen_return(BR_Cycles);
|
||||
gen_fill_branch(cycle_branch);
|
||||
dyn_loadstate(&cycle_state);
|
||||
dyn_synchstate(&rep_state);
|
||||
/* Jump back to start of ECX check */
|
||||
gen_create_jump(rep_start);
|
||||
gen_fill_jump(rep_ecx_jmp);
|
||||
}
|
||||
gen_releasereg(DREG(TMPW));
|
||||
gen_restoreflags();
|
||||
}
|
Loading…
Add table
Reference in a new issue