Merge branch 'svn/trunk' r4301
This commit is contained in:
commit
61511a4bdf
7 changed files with 228 additions and 195 deletions
|
@ -1,3 +1,34 @@
|
|||
0.74-3
|
||||
- Implement basic file access control for files available from within
|
||||
the emulation, so that programs running inside DOSBox can't access
|
||||
/proc (e.g. /proc/self/mem). (CVE-2019-12594)
|
||||
- Unify unmounting code and add some protections against out of bound access
|
||||
when DOS_DRIVES is not 26.
|
||||
- Use correct type for return value of strlen.
|
||||
- Change scan3x to a bit brighter.
|
||||
- Fix unitialized access to some isoDrive fields and improve stability
|
||||
when switching CD images.
|
||||
- Small fix to hq3x.
|
||||
- Fix 256 colour mode encoding in zmbv.dll.
|
||||
- Some small aliassing fix.
|
||||
- Change SET to check the size of the MCB when adding variables. Fixes
|
||||
hangs with Norton Commander.
|
||||
- Check buffer length before doing tab completion.
|
||||
- Correct buffer overflow with very long lines in bat files. (CVE-2019-7165)
|
||||
- Correct the boundary check for the internal programs array.
|
||||
- Increase stability in max cycles mode by increasing the lower bound.
|
||||
- Fix command prompt in windows 3.11 with dynrec core.
|
||||
- Fix Win64 dynrec core.
|
||||
- Always clear buffers before drawing in OpenGL mode. Fixes artifacts with
|
||||
drivers that have more than 2 buffers and overlays.
|
||||
- Fix red border that appeared when scaling the image in OpenGL
|
||||
mode with Nvidia on Linux and Mac.
|
||||
- Change default output to opengl on Mac, as surface is very slow there in 64 bit.
|
||||
- Add workaround for the mouse unlocking problem with X.org 1.20.1.
|
||||
- Fix table access when USE_FULL_TLB is undefined (non-default configuration).
|
||||
- Several fixes to prevent compilation errors.
|
||||
- Update Visual studio file to fix missing files from 0.74-2.
|
||||
|
||||
0.74-2
|
||||
- Rewrite auto/max cycles algorithm to work better with windows 7, other
|
||||
OSes might benefit as well.
|
||||
|
|
|
@ -1,3 +1,17 @@
|
|||
0.74-3
|
||||
A security release for DOSBox 0.74:
|
||||
- Fixed that a very long line inside a bat file would overflow the parsing
|
||||
buffer (CVE-2019-7165 by Alexandre Bartel)
|
||||
- Added a basic permission system so that a program running inside DOSBox
|
||||
can't access the contents of /proc (e.g. /proc/self/mem) when / or /proc
|
||||
were (to be) mounted (CVE-2019-12594 by Alexandre Bartel)
|
||||
- Several other fixes for out of bounds access and buffer overflows.
|
||||
- Some fixes to the OpenGL rendering.
|
||||
|
||||
It's recommended to use config -securemode when dealing with untrusted
|
||||
files.
|
||||
See the Changelog for all the changes.
|
||||
|
||||
0.74-2
|
||||
A maintenance release for DOSBox 0.74, which solves the following problems:
|
||||
|
||||
|
|
|
@ -158,9 +158,7 @@ static struct {
|
|||
Bit32u ea,tmpb,tmpd,stack,shift,newesp;
|
||||
} extra_regs;
|
||||
|
||||
static void IllegalOption(const char* msg) {
|
||||
E_Exit("DynCore: illegal option in %s",msg);
|
||||
}
|
||||
#define IllegalOption(msg) E_Exit("DYNX86: illegal option in " msg)
|
||||
|
||||
#include "core_dyn_x86/cache.h"
|
||||
|
||||
|
|
|
@ -421,13 +421,13 @@ static void dyn_fill_blocks(void) {
|
|||
|
||||
|
||||
#if !defined(X86_INLINED_MEMACCESS)
|
||||
static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) {
|
||||
static void dyn_read_byte(DynReg * addr,DynReg * dst,bool high) {
|
||||
gen_protectflags();
|
||||
gen_call_function((void *)&mem_readb_checked,"%Dd%Ip",addr,&core_dyn.readdata);
|
||||
dyn_check_bool_exception_al();
|
||||
gen_mov_host(&core_dyn.readdata,dst,1,high);
|
||||
gen_mov_host(&core_dyn.readdata,dst,1,high?4:0);
|
||||
}
|
||||
static void dyn_write_byte(DynReg * addr,DynReg * val,Bitu high) {
|
||||
static void dyn_write_byte(DynReg * addr,DynReg * val,bool high) {
|
||||
gen_protectflags();
|
||||
if (high) gen_call_function((void *)&mem_writeb_checked,"%Dd%Dh",addr,val);
|
||||
else gen_call_function((void *)&mem_writeb_checked,"%Dd%Dd",addr,val);
|
||||
|
@ -446,13 +446,13 @@ static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) {
|
|||
else gen_call_function((void *)&mem_writew_checked,"%Dd%Dd",addr,val);
|
||||
dyn_check_bool_exception_al();
|
||||
}
|
||||
static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) {
|
||||
static void dyn_read_byte_release(DynReg * addr,DynReg * dst,bool high) {
|
||||
gen_protectflags();
|
||||
gen_call_function((void *)&mem_readb_checked,"%Drd%Ip",addr,&core_dyn.readdata);
|
||||
dyn_check_bool_exception_al();
|
||||
gen_mov_host(&core_dyn.readdata,dst,1,high);
|
||||
gen_mov_host(&core_dyn.readdata,dst,1,high?4:0);
|
||||
}
|
||||
static void dyn_write_byte_release(DynReg * addr,DynReg * val,Bitu high) {
|
||||
static void dyn_write_byte_release(DynReg * addr,DynReg * val,bool high) {
|
||||
gen_protectflags();
|
||||
if (high) gen_call_function((void *)&mem_writeb_checked,"%Drd%Dh",addr,val);
|
||||
else gen_call_function((void *)&mem_writeb_checked,"%Drd%Dd",addr,val);
|
||||
|
@ -516,7 +516,7 @@ static bool mem_readb_checked_dcx86(PhysPt address) {
|
|||
return get_tlb_readhandler(address)->readb_checked(address, (Bit8u*)(&core_dyn.readdata));
|
||||
}
|
||||
|
||||
static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high,bool release=false) {
|
||||
static void dyn_read_byte(DynReg * addr,DynReg * dst,bool high,bool release=false) {
|
||||
dyn_read_intro(addr,release);
|
||||
|
||||
cache_addw(0xe8c1); // shr eax,0x0c
|
||||
|
@ -554,10 +554,6 @@ static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high,bool release=fals
|
|||
dst->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) {
|
||||
dyn_read_byte(addr,dst,high,true);
|
||||
}
|
||||
|
||||
static bool mem_readd_checked_dcx86(PhysPt address) {
|
||||
if ((address & 0xfff)<0xffd) {
|
||||
HostPt tlb_addr=get_tlb_read(address);
|
||||
|
@ -636,10 +632,6 @@ static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword,bool release=fal
|
|||
gen_fill_jump(jmp_loc);
|
||||
}
|
||||
|
||||
static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) {
|
||||
dyn_read_word(addr,dst,dword,true);
|
||||
}
|
||||
|
||||
static void dyn_write_intro(DynReg * addr,bool release_addr=true) {
|
||||
gen_protectflags();
|
||||
|
||||
|
@ -710,10 +702,6 @@ static void dyn_write_byte(DynReg * addr,DynReg * val,bool high,bool release=fal
|
|||
gen_fill_jump(jmp_loc);
|
||||
}
|
||||
|
||||
static void dyn_write_byte_release(DynReg * addr,DynReg * val,bool high) {
|
||||
dyn_write_byte(addr,val,high,true);
|
||||
}
|
||||
|
||||
static void dyn_write_word(DynReg * addr,DynReg * val,bool dword,bool release=false) {
|
||||
dyn_write_intro(addr,release);
|
||||
|
||||
|
@ -759,9 +747,6 @@ static void dyn_write_word(DynReg * addr,DynReg * val,bool dword,bool release=fa
|
|||
gen_fill_jump(jmp_loc);
|
||||
}
|
||||
|
||||
static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) {
|
||||
dyn_write_word(addr,val,dword,true);
|
||||
}
|
||||
#else // X86_64
|
||||
static bool mem_readd_checked_dcx64(PhysPt address, Bit32u* dst) {
|
||||
return get_tlb_readhandler(address)->readd_checked(address, dst);
|
||||
|
@ -782,54 +767,60 @@ static bool mem_writeb_checked_dcx64(PhysPt address, Bitu val) {
|
|||
return get_tlb_writehandler(address)->writeb_checked(address, val);
|
||||
}
|
||||
|
||||
static void dyn_read_word_internal(DynReg * addr,DynReg * dst,bool dword,bool release) {
|
||||
static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword,bool release=false) {
|
||||
DynState callstate;
|
||||
gen_protectflags();
|
||||
Bit8u tmp;
|
||||
|
||||
x64gen.regs[X64_REG_RAX]->Clear();
|
||||
x64gen.regs[X64_REG_RAX]->notusable = true;
|
||||
gen_protectflags();
|
||||
GenReg *gensrc = FindDynReg(addr);
|
||||
if (dword && release) gen_releasereg(addr);
|
||||
GenReg *gendst = FindDynReg(dst,dword);
|
||||
if (!dword && release) gen_releasereg(addr);
|
||||
x64gen.regs[X64_REG_RAX]->notusable = false;
|
||||
gensrc->notusable = true;
|
||||
x64gen.regs[reg_args[0]]->notusable=true;
|
||||
x64gen.regs[reg_args[1]]->notusable=true;
|
||||
tmp = GetNextReg();
|
||||
gensrc->notusable = false;
|
||||
x64gen.regs[reg_args[0]]->notusable=false;
|
||||
x64gen.regs[reg_args[1]]->notusable=false;
|
||||
dyn_savestate(&callstate);
|
||||
|
||||
Bit8u *page_brk;
|
||||
opcode(0).set64().setea(gensrc->index,-1,0,dword?3:1).Emit8(0x8D); // lea rax, [dst+(dword?3:1)]
|
||||
opcode(tmp).set64().setea(gensrc->index,-1,0,dword?3:1).Emit8(0x8D); // lea tmp, [dst+(dword?3:1)]
|
||||
if (dword) {
|
||||
opcode(0).set64().setimm(~0xFFF,4).Emit8Reg(0x25); // and rax, ~0xFFF
|
||||
opcode(gensrc->index).set64().setrm(0).Emit8(0x39); // cmp rax,src
|
||||
opcode(4).set64().setimm(~0xFFF,4).setrm(tmp).Emit8(0x81); // and tmp, ~0xFFF
|
||||
opcode(gensrc->index).set64().setrm(tmp).Emit8(0x39); // cmp tmp,src
|
||||
page_brk=gen_create_branch(BR_NBE);
|
||||
} else {
|
||||
opcode(0,false).setimm(0xFFF,2).Emit8Reg(0xA9); // test ax,0xFFF
|
||||
opcode(0,false).setimm(0xFFF,2).setrm(tmp).Emit8(0xF7); // test tmpw,0xFFF
|
||||
page_brk=gen_create_branch(BR_Z);
|
||||
}
|
||||
|
||||
opcode(5).setrm(0).setimm(12,1).Emit8(0xC1); // shr eax,12
|
||||
// mov rax, [8*rax+paging.tlb.read(rbp)]
|
||||
opcode(0).set64().setea(5,0,3,(Bits)paging.tlb.read-(Bits)&cpu_regs).Emit8(0x8B);
|
||||
opcode(0).set64().setrm(0).Emit8(0x85); // test rax,rax
|
||||
opcode(5).setrm(tmp).setimm(12,1).Emit8(0xC1); // shr tmpd,12
|
||||
// mov tmp, [8*tmp+paging.tlb.read(rbp)]
|
||||
opcode(tmp).set64().setea(5,tmp,3,(Bits)paging.tlb.read-(Bits)&cpu_regs).Emit8(0x8B);
|
||||
opcode(tmp).set64().setrm(tmp).Emit8(0x85); // test tmp,tmp
|
||||
Bit8u *nomap=gen_create_branch(BR_Z);
|
||||
//mov dst, [RAX+src]
|
||||
opcode(gendst->index,dword).setea(0,gensrc->index).Emit8(0x8B);
|
||||
//mov dst, [tmp+src]
|
||||
opcode(gendst->index,dword).setea(tmp,gensrc->index).Emit8(0x8B);
|
||||
Bit8u* jmp_loc = gen_create_short_jump();
|
||||
|
||||
gen_fill_branch(page_brk);
|
||||
gen_load_imm(0, (Bitu)(dword?(void*)mem_unalignedreadd_checked:(void*)mem_unalignedreadw_checked));
|
||||
gen_load_imm(tmp, (Bitu)(dword?(void*)mem_unalignedreadd_checked:(void*)mem_unalignedreadw_checked));
|
||||
Bit8u* page_jmp = gen_create_short_jump();
|
||||
|
||||
gen_fill_branch(nomap);
|
||||
gen_load_imm(0, (Bitu)(dword?(void*)mem_readd_checked_dcx64:(void*)mem_readw_checked_dcx64));
|
||||
gen_load_imm(tmp, (Bitu)(dword?(void*)mem_readd_checked_dcx64:(void*)mem_readw_checked_dcx64));
|
||||
gen_fill_short_jump(page_jmp);
|
||||
|
||||
if (gensrc->index != ARG0_REG) {
|
||||
x64gen.regs[reg_args[0]]->Clear();
|
||||
opcode(ARG0_REG).setrm(gensrc->index).Emit8(0x8B);
|
||||
}
|
||||
gendst->Clear();
|
||||
x64gen.regs[reg_args[1]]->Clear();
|
||||
gen_load_imm(ARG1_REG, (Bitu)dst->data);
|
||||
gendst->Clear();
|
||||
gen_call_ptr();
|
||||
gen_call_ptr(NULL, tmp);
|
||||
dyn_check_bool_exception_al();
|
||||
|
||||
dyn_synchstate(&callstate);
|
||||
|
@ -837,40 +828,33 @@ static void dyn_read_word_internal(DynReg * addr,DynReg * dst,bool dword,bool re
|
|||
gen_fill_short_jump(jmp_loc);
|
||||
}
|
||||
|
||||
static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) {
|
||||
dyn_read_word_internal(addr,dst,dword,false);
|
||||
}
|
||||
static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) {
|
||||
dyn_read_word_internal(addr,dst,dword,true);
|
||||
}
|
||||
static void dyn_read_byte_internal(DynReg * addr,DynReg * dst,bool high,bool release) {
|
||||
static void dyn_read_byte(DynReg * addr,DynReg * dst,bool high,bool release=false) {
|
||||
DynState callstate;
|
||||
gen_protectflags();
|
||||
Bit8u tmp;
|
||||
|
||||
x64gen.regs[X64_REG_RAX]->Clear();
|
||||
x64gen.regs[X64_REG_RAX]->notusable = true;
|
||||
gen_protectflags();
|
||||
GenReg *gensrc = FindDynReg(addr);
|
||||
GenReg *gendst = FindDynReg(dst);
|
||||
tmp = GetNextReg(high);
|
||||
if (release) gen_releasereg(addr);
|
||||
x64gen.regs[X64_REG_RAX]->notusable = false;
|
||||
dyn_savestate(&callstate);
|
||||
|
||||
if (gendst->index>3) IllegalOption("dyn_read_byte");
|
||||
|
||||
opcode(0).setrm(gensrc->index).Emit8(0x8B); // mov eax, src
|
||||
opcode(5).setrm(0).setimm(12,1).Emit8(0xC1); // shr eax,12
|
||||
// mov rax, [8*rax+paging.tlb.read(rbp)]
|
||||
opcode(0).set64().setea(5,0,3,(Bits)paging.tlb.read-(Bits)&cpu_regs).Emit8(0x8B);
|
||||
opcode(0).set64().setrm(0).Emit8(0x85); // test rax,rax
|
||||
opcode(tmp).setrm(gensrc->index).Emit8(0x8B); // mov tmp, src
|
||||
opcode(5).setrm(tmp).setimm(12,1).Emit8(0xC1); // shr tmp,12
|
||||
// mov tmp, [8*tmp+paging.tlb.read(rbp)]
|
||||
opcode(tmp).set64().setea(5,tmp,3,(Bits)paging.tlb.read-(Bits)&cpu_regs).Emit8(0x8B);
|
||||
opcode(tmp).set64().setrm(tmp).Emit8(0x85); // test tmp,tmp
|
||||
Bit8u *nomap=gen_create_branch(BR_Z);
|
||||
|
||||
int src = gensrc->index;
|
||||
if (high && src>=8) { // can't use REX prefix with high-byte reg
|
||||
opcode(0).set64().setrm(src).Emit8(0x03); // add rax, src
|
||||
opcode(tmp).set64().setrm(src).Emit8(0x03); // add tmp, src
|
||||
src = -1;
|
||||
}
|
||||
// mov dst, byte [rax+src]
|
||||
opcode(gendst->index,true,high?4:0).setea(0,src).Emit8(0x8A);
|
||||
// mov dst, byte [tmp+src]
|
||||
opcode(gendst->index,true,high?4:0).setea(tmp,src).Emit8(0x8A);
|
||||
Bit8u* jmp_loc=gen_create_short_jump();
|
||||
|
||||
gen_fill_branch(nomap);
|
||||
|
@ -888,49 +872,47 @@ static void dyn_read_byte_internal(DynReg * addr,DynReg * dst,bool high,bool rel
|
|||
dst->flags |= DYNFLG_CHANGED;
|
||||
gen_fill_short_jump(jmp_loc);
|
||||
}
|
||||
static void dyn_read_byte(DynReg * addr,DynReg * dst,bool high) {
|
||||
dyn_read_byte_internal(addr,dst,high,false);
|
||||
}
|
||||
static void dyn_read_byte_release(DynReg * addr,DynReg * dst,bool high) {
|
||||
dyn_read_byte_internal(addr,dst,high,true);
|
||||
}
|
||||
static void dyn_write_word_internal(DynReg * addr,DynReg * val,bool dword,bool release) {
|
||||
DynState callstate;
|
||||
gen_protectflags();
|
||||
|
||||
x64gen.regs[X64_REG_RAX]->Clear();
|
||||
x64gen.regs[X64_REG_RAX]->notusable = true;
|
||||
static void dyn_write_word(DynReg * addr,DynReg * val,bool dword,bool release=false) {
|
||||
DynState callstate;
|
||||
Bit8u tmp;
|
||||
|
||||
gen_protectflags();
|
||||
GenReg *gendst = FindDynReg(addr);
|
||||
GenReg *genval = FindDynReg(val);
|
||||
x64gen.regs[reg_args[0]]->notusable=true;
|
||||
x64gen.regs[reg_args[1]]->notusable=true;
|
||||
tmp = GetNextReg();
|
||||
x64gen.regs[reg_args[0]]->notusable=false;
|
||||
x64gen.regs[reg_args[1]]->notusable=false;
|
||||
if (release) gen_releasereg(addr);
|
||||
x64gen.regs[X64_REG_RAX]->notusable = false;
|
||||
dyn_savestate(&callstate);
|
||||
|
||||
Bit8u *page_brk;
|
||||
opcode(0).set64().setea(gendst->index,-1,0,dword?3:1).Emit8(0x8D); // lea rax, [dst+(dword?3:1)]
|
||||
opcode(tmp).set64().setea(gendst->index,-1,0,dword?3:1).Emit8(0x8D); // lea tmp, [dst+(dword?3:1)]
|
||||
if (dword) {
|
||||
opcode(0).set64().setimm(~0xFFF,4).Emit8Reg(0x25); // and rax, ~0xFFF
|
||||
opcode(gendst->index).set64().setrm(0).Emit8(0x39); // cmp rax,dst
|
||||
opcode(4).set64().setimm(~0xFFF,4).setrm(tmp).Emit8(0x81); // and tmp, ~0xFFF
|
||||
opcode(gendst->index).set64().setrm(tmp).Emit8(0x39); // cmp tmp,dst
|
||||
page_brk=gen_create_branch(BR_NBE);
|
||||
} else {
|
||||
opcode(0,false).setimm(0xFFF,2).Emit8Reg(0xA9); // test ax,0xFFF
|
||||
opcode(0,false).setimm(0xFFF,2).setrm(tmp).Emit8(0xF7); // test tmpw,0xFFF
|
||||
page_brk=gen_create_branch(BR_Z);
|
||||
}
|
||||
|
||||
opcode(5).setrm(0).setimm(12,1).Emit8(0xC1); // shr eax,12
|
||||
// mov rax, [8*rax+paging.tlb.write(rbp)]
|
||||
opcode(0).set64().setea(5,0,3,(Bits)paging.tlb.write-(Bits)&cpu_regs).Emit8(0x8B);
|
||||
opcode(0).set64().setrm(0).Emit8(0x85); // test rax,rax
|
||||
opcode(5).setrm(tmp).setimm(12,1).Emit8(0xC1); // shr tmpd,12
|
||||
// mov tmp, [8*tmp+paging.tlb.write(rbp)]
|
||||
opcode(tmp).set64().setea(5,tmp,3,(Bits)paging.tlb.write-(Bits)&cpu_regs).Emit8(0x8B);
|
||||
opcode(tmp).set64().setrm(tmp).Emit8(0x85); // test tmp,tmp
|
||||
Bit8u *nomap=gen_create_branch(BR_Z);
|
||||
//mov [RAX+src], dst
|
||||
opcode(genval->index,dword).setea(0,gendst->index).Emit8(0x89);
|
||||
//mov [tmp+src], dst
|
||||
opcode(genval->index,dword).setea(tmp,gendst->index).Emit8(0x89);
|
||||
Bit8u* jmp_loc = gen_create_short_jump();
|
||||
|
||||
gen_fill_branch(page_brk);
|
||||
gen_load_imm(0, (Bitu)(dword?(void*)mem_unalignedwrited_checked:(void*)mem_unalignedwritew_checked));
|
||||
gen_load_imm(tmp, (Bitu)(dword?(void*)mem_unalignedwrited_checked:(void*)mem_unalignedwritew_checked));
|
||||
Bit8u* page_jmp = gen_create_short_jump();
|
||||
gen_fill_branch(nomap);
|
||||
gen_load_imm(0, (Bitu)(dword?(void*)mem_writed_checked_dcx64:(void*)mem_writew_checked_dcx64));
|
||||
gen_load_imm(tmp, (Bitu)(dword?(void*)mem_writed_checked_dcx64:(void*)mem_writew_checked_dcx64));
|
||||
gen_fill_short_jump(page_jmp);
|
||||
|
||||
if (gendst->index != ARG0_REG) {
|
||||
|
@ -938,45 +920,39 @@ static void dyn_write_word_internal(DynReg * addr,DynReg * val,bool dword,bool r
|
|||
opcode(ARG0_REG).setrm(gendst->index).Emit8(0x8B);
|
||||
}
|
||||
gen_load_arg_reg(1, val, dword ? "d":"w");
|
||||
gen_call_ptr();
|
||||
gen_call_ptr(NULL, tmp);
|
||||
dyn_check_bool_exception_al();
|
||||
dyn_synchstate(&callstate);
|
||||
gen_fill_short_jump(jmp_loc);
|
||||
}
|
||||
static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) {
|
||||
dyn_write_word_internal(addr, val, dword, false);
|
||||
}
|
||||
static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) {
|
||||
dyn_write_word_internal(addr, val, dword, true);
|
||||
}
|
||||
static void dyn_write_byte_internal(DynReg * addr,DynReg * val,bool high,bool release) {
|
||||
DynState callstate;
|
||||
gen_protectflags();
|
||||
|
||||
x64gen.regs[X64_REG_RAX]->Clear();
|
||||
x64gen.regs[X64_REG_RAX]->notusable = true;
|
||||
static void dyn_write_byte(DynReg * addr,DynReg * val,bool high,bool release=false) {
|
||||
DynState callstate;
|
||||
Bit8u tmp;
|
||||
|
||||
gen_protectflags();
|
||||
GenReg *gendst = FindDynReg(addr);
|
||||
GenReg *genval = FindDynReg(val);
|
||||
tmp = GetNextReg(high);
|
||||
if (release) gen_releasereg(addr);
|
||||
x64gen.regs[X64_REG_RAX]->notusable = false;
|
||||
dyn_savestate(&callstate);
|
||||
|
||||
if (genval->index>3) IllegalOption("dyn_write_byte");
|
||||
|
||||
opcode(0).setrm(gendst->index).Emit8(0x8B); // mov eax, dst
|
||||
opcode(5).setrm(0).setimm(12,1).Emit8(0xC1); // shr eax,12
|
||||
// mov rax, [8*rax+paging.tlb.write(rbp)]
|
||||
opcode(0).set64().setea(5,0,3,(Bits)paging.tlb.write-(Bits)&cpu_regs).Emit8(0x8B);
|
||||
opcode(0).set64().setrm(0).Emit8(0x85); // test rax,rax
|
||||
opcode(tmp).setrm(gendst->index).Emit8(0x8B); // mov tmpd, dst
|
||||
opcode(5).setrm(tmp).setimm(12,1).Emit8(0xC1); // shr tmpd,12
|
||||
// mov tmp, [8*tmp+paging.tlb.write(rbp)]
|
||||
opcode(tmp).set64().setea(5,tmp,3,(Bits)paging.tlb.write-(Bits)&cpu_regs).Emit8(0x8B);
|
||||
opcode(tmp).set64().setrm(tmp).Emit8(0x85); // test tmp,tmp
|
||||
Bit8u *nomap=gen_create_branch(BR_Z);
|
||||
|
||||
int dst = gendst->index;
|
||||
if (high && dst>=8) { // can't use REX prefix with high-byte reg
|
||||
opcode(0).set64().setrm(dst).Emit8(0x03); // add rax, dst
|
||||
opcode(tmp).set64().setrm(dst).Emit8(0x03); // add tmp, dst
|
||||
dst = -1;
|
||||
}
|
||||
// mov byte [rax+src], val
|
||||
opcode(genval->index,true,high?4:0).setea(0,dst).Emit8(0x88);
|
||||
// mov byte [tmp+src], val
|
||||
opcode(genval->index,true,high?4:0).setea(tmp,dst).Emit8(0x88);
|
||||
|
||||
Bit8u* jmp_loc=gen_create_short_jump();
|
||||
gen_fill_branch(nomap);
|
||||
|
@ -992,14 +968,21 @@ static void dyn_write_byte_internal(DynReg * addr,DynReg * val,bool high,bool re
|
|||
dyn_synchstate(&callstate);
|
||||
gen_fill_short_jump(jmp_loc);
|
||||
}
|
||||
static void dyn_write_byte(DynReg * addr,DynReg * src,bool high) {
|
||||
dyn_write_byte_internal(addr,src,high,false);
|
||||
|
||||
#endif
|
||||
static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) {
|
||||
dyn_read_word(addr,dst,dword,addr!=dst);
|
||||
}
|
||||
static void dyn_read_byte_release(DynReg * addr,DynReg * dst,bool high) {
|
||||
dyn_read_byte(addr,dst,high,addr!=dst);
|
||||
}
|
||||
static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) {
|
||||
dyn_write_word(addr,val,dword,true);
|
||||
}
|
||||
static void dyn_write_byte_release(DynReg * addr,DynReg * src,bool high) {
|
||||
dyn_write_byte_internal(addr,src,high,true);
|
||||
dyn_write_byte(addr,src,high,true);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
static void dyn_push_unchecked(DynReg * dynreg) {
|
||||
|
@ -1325,7 +1308,7 @@ static void dyn_mov_ebgb(void) {
|
|||
DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];Bitu rm_regi=decode.modrm.reg&4;
|
||||
if (decode.modrm.mod<3) {
|
||||
dyn_fill_ea();
|
||||
dyn_write_byte_release(DREG(EA),rm_reg,rm_regi==4);
|
||||
dyn_write_byte_release(DREG(EA),rm_reg,rm_regi!=0);
|
||||
} else {
|
||||
gen_dop_byte(DOP_MOV,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,rm_reg,rm_regi);
|
||||
}
|
||||
|
@ -1336,7 +1319,7 @@ static void dyn_mov_gbeb(void) {
|
|||
DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];Bitu rm_regi=decode.modrm.reg&4;
|
||||
if (decode.modrm.mod<3) {
|
||||
dyn_fill_ea();
|
||||
dyn_read_byte_release(DREG(EA),rm_reg,rm_regi);
|
||||
dyn_read_byte_release(DREG(EA),rm_reg,rm_regi!=0);
|
||||
} else {
|
||||
gen_dop_byte(DOP_MOV,rm_reg,rm_regi,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
|
||||
}
|
||||
|
|
|
@ -39,14 +39,14 @@ enum {
|
|||
static const int reg_args[4] = {X64_REG_RCX, X64_REG_RDX, X64_REG_R8, X64_REG_R9};
|
||||
#define ARG0_REG 1
|
||||
#define ARG1_REG 2
|
||||
#define CALLSTACK 32
|
||||
#define CALLSTACK 40
|
||||
#else
|
||||
enum {
|
||||
// (high)byte-accessible
|
||||
X64_REG_RAX,
|
||||
X64_REG_RBX,
|
||||
X64_REG_RCX,
|
||||
X64_REG_RDX,
|
||||
X64_REG_RAX,
|
||||
// volatiles
|
||||
X64_REG_RSI,
|
||||
X64_REG_RDI,
|
||||
|
@ -65,7 +65,7 @@ enum {
|
|||
static const int reg_args[4] = {X64_REG_RDI, X64_REG_RSI, X64_REG_RDX, X64_REG_RCX};
|
||||
#define ARG0_REG 7
|
||||
#define ARG1_REG 6
|
||||
#define CALLSTACK 0
|
||||
#define CALLSTACK 8
|
||||
#endif
|
||||
|
||||
static struct {
|
||||
|
@ -77,7 +77,7 @@ static struct {
|
|||
class opcode {
|
||||
public:
|
||||
opcode(void) : is_word(false), imm_size(0), rex(0) {}
|
||||
opcode(int reg,bool dword=true,Bit8u acc=1) : is_word(!dword), imm_size(0), rex(0) {
|
||||
opcode(int reg,bool dword=true,Bitu acc=1) : is_word(!dword), imm_size(0), rex(0) {
|
||||
setreg(reg, acc);
|
||||
}
|
||||
|
||||
|
@ -85,10 +85,10 @@ public:
|
|||
opcode& set64(void) {rex|=0x48;return *this;}
|
||||
opcode& setimm(Bit64u _imm, int size) {imm=_imm;imm_size=size;return *this;}
|
||||
|
||||
opcode& setreg(int r, Bit8u acc=1); // acc: 0=low byte, 1=word/dword, 4=high byte
|
||||
opcode& setrm(int r, Bit8u acc=1);
|
||||
opcode& setreg(int r, Bitu acc=1); // acc: 0=low byte, 1=word/dword, 4=high byte
|
||||
opcode& setrm(int r, Bitu acc=1);
|
||||
opcode& setabsaddr(void* addr);
|
||||
opcode& setea(int rbase, int rscale=-1, int scale=0, Bit32s off=0);
|
||||
opcode& setea(int rbase, int rscale=-1, Bitu scale=0, Bits off=0);
|
||||
|
||||
void Emit8Reg(Bit8u op);
|
||||
void Emit8(Bit8u op);
|
||||
|
@ -160,7 +160,7 @@ void opcode::Emit16(Bit16u op) {
|
|||
EmitSibOffImm();
|
||||
}
|
||||
|
||||
opcode& opcode::setreg(int r, Bit8u acc) {
|
||||
opcode& opcode::setreg(int r, Bitu acc) {
|
||||
if (acc==4) {
|
||||
if (r>3 || rex) IllegalOption("opcode::setreg: cannot encode high byte");
|
||||
r += 4;
|
||||
|
@ -170,7 +170,7 @@ opcode& opcode::setreg(int r, Bit8u acc) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
opcode& opcode::setrm(int r, Bit8u acc) {
|
||||
opcode& opcode::setrm(int r, Bitu acc) {
|
||||
if (reg>=8) rex |= 0x44;
|
||||
if (r>=8) rex |= 0x41;
|
||||
if (acc==4) {
|
||||
|
@ -202,7 +202,7 @@ opcode& opcode::setabsaddr(void* addr) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
opcode& opcode::setea(int rbase, int rscale, int scale, Bit32s off) {
|
||||
opcode& opcode::setea(int rbase, int rscale, Bitu scale, Bits off) {
|
||||
if (reg>=8) rex |= 0x44;
|
||||
if (rbase>=8) rex |= 0x41, rbase &= 7;
|
||||
if (rscale>=8) rex |= 0x42, rscale &= 7;
|
||||
|
@ -211,7 +211,7 @@ opcode& opcode::setea(int rbase, int rscale, int scale, Bit32s off) {
|
|||
|
||||
if (rbase<0 || rscale>=0 || rbase==4) { // sib required
|
||||
modrm += 4;
|
||||
if (rscale>=0) sib = (scale<<6)+(rscale<<3);
|
||||
if (rscale>=0) sib = (Bit8u)((scale<<6)+(rscale<<3));
|
||||
else sib = 4<<3;
|
||||
if (rbase>=0) sib += rbase;
|
||||
else sib += 5;
|
||||
|
@ -299,8 +299,8 @@ static BlockReturn gen_runcodeInit(Bit8u *code) {
|
|||
opcode(4).set64().setrm(4).setimm(~15,1).Emit8(0x83); // and rsp, ~15
|
||||
opcode(15).Emit8Reg(0x50); // push r15
|
||||
opcode(2).Emit8Reg(0x50); // push rdx
|
||||
opcode(5).set64().setrm(4).setimm(CALLSTACK*2+16,1).Emit8(0x83); // sub rsp, 16/80
|
||||
opcode(0).setea(4,-1,0,CALLSTACK+8).Emit8(0x89); // mov [rsp+8/40], eax
|
||||
opcode(5).set64().setrm(4).setimm(CALLSTACK*2,1).Emit8(0x83); // sub rsp, 16/80
|
||||
opcode(0).setea(4,-1,0,CALLSTACK).Emit8(0x89); // mov [rsp+8/40], eax
|
||||
opcode(4).setrm(ARG0_REG).Emit8(0xFF); // jmp ARG0
|
||||
|
||||
*(Bit32u*)diff = (Bit32u)(cache.pos - diff - 4);
|
||||
|
@ -309,7 +309,7 @@ static BlockReturn gen_runcodeInit(Bit8u *code) {
|
|||
opcode(4).setrm(1).setimm(FMASK_TEST,4).Emit8(0x81); // and ecx,FMASK_TEST
|
||||
opcode(1).setea(5,-1,0,offsetof(CPU_Regs,flags)).Emit8(0x31); // xor reg_flags, ecx
|
||||
|
||||
opcode(4).set64().setea(4,-1,0,CALLSTACK+8).Emit8(0x8B); // mov rsp, [rsp+8/40]
|
||||
opcode(4).set64().setea(4,-1,0,CALLSTACK).Emit8(0x8B); // mov rsp, [rsp+8/40]
|
||||
#if defined(_WIN64)
|
||||
opcode(6).Emit8Reg(0x58); // pop rsi
|
||||
opcode(7).Emit8Reg(0x58); // pop rdi
|
||||
|
@ -448,7 +448,7 @@ static void gen_synchreg(DynReg * dnew,DynReg * dsynch) {
|
|||
static void gen_needflags(void) {
|
||||
if (!x64gen.flagsactive) {
|
||||
x64gen.flagsactive=true;
|
||||
opcode(0).set64().setrm(4).setimm(CALLSTACK+8,1).Emit8(0x83); // add rsp,8/40
|
||||
opcode(0).set64().setrm(4).setimm(CALLSTACK,1).Emit8(0x83); // add rsp,8/40
|
||||
cache_addb(0x9d); //POPFQ
|
||||
}
|
||||
}
|
||||
|
@ -457,29 +457,33 @@ static void gen_protectflags(void) {
|
|||
if (x64gen.flagsactive) {
|
||||
x64gen.flagsactive=false;
|
||||
cache_addb(0x9c); //PUSHFQ
|
||||
opcode(4).set64().setea(4,-1,0,-(CALLSTACK+8)).Emit8(0x8D); // lea rsp, [rsp-8/40]
|
||||
opcode(4).set64().setea(4,-1,0,-(CALLSTACK)).Emit8(0x8D); // lea rsp, [rsp-8/40]
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_discardflags(void) {
|
||||
if (!x64gen.flagsactive) {
|
||||
x64gen.flagsactive=true;
|
||||
opcode(0).set64().setrm(4).setimm(CALLSTACK+16,1).Emit8(0x83); // add rsp,16/48
|
||||
opcode(0).set64().setrm(4).setimm(CALLSTACK+8,1).Emit8(0x83); // add rsp,16/48
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_needcarry(void) {
|
||||
gen_needflags();
|
||||
if (!x64gen.flagsactive) {
|
||||
x64gen.flagsactive=true;
|
||||
opcode(4).setea(4,-1,0,CALLSTACK).setimm(0,1).Emit16(0xBA0F); // bt [rsp+8/40], 0
|
||||
opcode(4).set64().setea(4,-1,0,CALLSTACK+8).Emit8(0x8D); // lea rsp, [rsp+16/48]
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_setzeroflag(void) {
|
||||
if (x64gen.flagsactive) IllegalOption("gen_setzeroflag");
|
||||
opcode(1).setea(4,-1,0,CALLSTACK+8).setimm(0x40,1).Emit8(0x83); // or dword [rsp+8/40],0x40
|
||||
opcode(1).setea(4,-1,0,CALLSTACK).setimm(0x40,1).Emit8(0x83); // or dword [rsp+8/40],0x40
|
||||
}
|
||||
|
||||
static void gen_clearzeroflag(void) {
|
||||
if (x64gen.flagsactive) IllegalOption("gen_clearzeroflag");
|
||||
opcode(4).setea(4,-1,0,CALLSTACK+8).setimm(~0x40,1).Emit8(0x83); // and dword [rsp+8/40],~0x40
|
||||
opcode(4).setea(4,-1,0,CALLSTACK).setimm(~0x40,1).Emit8(0x83); // and dword [rsp+8/40],~0x40
|
||||
}
|
||||
|
||||
static bool skip_flags=false;
|
||||
|
@ -515,7 +519,7 @@ static void gen_load_host(void * data,DynReg * dr1,Bitu size) {
|
|||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_mov_host(void * data,DynReg * dr1,Bitu size,Bit8u di1=0) {
|
||||
static void gen_mov_host(void * data,DynReg * dr1,Bitu size,Bitu di1=0) {
|
||||
int idx = FindDynReg(dr1,size==4)->index;
|
||||
opcode op;
|
||||
Bit8u tmp = 0x00;
|
||||
|
@ -583,13 +587,13 @@ static void gen_load_imm(int index,Bitu imm) {
|
|||
opcode(index).setrm(index).Emit8(0x33); // xor r32,r32
|
||||
else if ((Bit32u)imm==imm)
|
||||
opcode(index).setimm(imm,4).Emit8Reg(0xB8); // MOV r32, imm32
|
||||
else if ((Bit32s)imm==imm)
|
||||
else if ((Bit32s)imm==(Bits)imm)
|
||||
opcode(0).set64().setimm(imm,4).setrm(index).Emit8(0xC7); // mov r64, simm32
|
||||
else
|
||||
opcode(index).set64().setabsaddr((void*)imm).Emit8(0x8D); // lea r64, [imm]
|
||||
}
|
||||
|
||||
static void gen_dop_byte(DualOps op,DynReg * dr1,Bit8u di1,DynReg * dr2,Bit8u di2) {
|
||||
static void gen_dop_byte(DualOps op,DynReg * dr1,Bitu di1,DynReg * dr2,Bitu di2) {
|
||||
Bit8u tmp;
|
||||
opcode i(FindDynReg(dr1)->index,true,di1);
|
||||
i.setrm(FindDynReg(dr2)->index,di2);
|
||||
|
@ -614,7 +618,7 @@ nochange:
|
|||
i.Emit8(tmp);
|
||||
}
|
||||
|
||||
static void gen_dop_byte_imm(DualOps op,DynReg * dr1,Bit8u di1,Bitu imm) {
|
||||
static void gen_dop_byte_imm(DualOps op,DynReg * dr1,Bitu di1,Bitu imm) {
|
||||
Bit8u tmp=0x80;
|
||||
int dst = FindDynReg(dr1)->index;
|
||||
opcode i;
|
||||
|
@ -642,7 +646,7 @@ nochange:
|
|||
i.setrm(dst,di1).Emit8(tmp);
|
||||
}
|
||||
|
||||
static void gen_dop_byte_imm_mem(DualOps op,DynReg * dr1,Bit8u di1,void* data) {
|
||||
static void gen_dop_byte_imm_mem(DualOps op,DynReg * dr1,Bitu di1,void* data) {
|
||||
opcode i;
|
||||
Bits addr = (Bits)data;
|
||||
Bits rbpdiff = addr - (Bits)&cpu_regs;
|
||||
|
@ -653,7 +657,7 @@ static void gen_dop_byte_imm_mem(DualOps op,DynReg * dr1,Bit8u di1,void* data) {
|
|||
else {
|
||||
GenReg* dst = FindDynReg(dr1);
|
||||
dst->notusable=true;
|
||||
int src = GetNextReg(di1);
|
||||
int src = GetNextReg(di1!=0);
|
||||
dst->notusable=false;
|
||||
if ((Bit32u)addr == (Bitu)addr) opcode(src).setimm(addr,4).Emit8Reg(0xB8);
|
||||
else opcode(src).setimm(addr,8).set64().Emit8Reg(0xB8);
|
||||
|
@ -680,7 +684,7 @@ nochange:
|
|||
i.Emit8(tmp);
|
||||
}
|
||||
|
||||
static void gen_sop_byte(SingleOps op,DynReg * dr1,Bit8u di1) {
|
||||
static void gen_sop_byte(SingleOps op,DynReg * dr1,Bitu di1) {
|
||||
Bit8u tmp;
|
||||
int dst = FindDynReg(dr1)->index;
|
||||
opcode i;
|
||||
|
@ -710,7 +714,7 @@ static void gen_extend_word(bool sign,DynReg * ddr,DynReg * dsr) {
|
|||
ddr->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_extend_byte(bool sign,bool dword,DynReg * ddr,DynReg * dsr,Bit8u dsi) {
|
||||
static void gen_extend_byte(bool sign,bool dword,DynReg * ddr,DynReg * dsr,Bitu dsi) {
|
||||
if (ddr==dsr && dword && dsr->genreg==NULL) {
|
||||
opcode op = opcode(FindDynReg(ddr,true)->index);
|
||||
if (dsi) op.setabsaddr((void*)(((Bit8u*)dsr->data)+1));
|
||||
|
@ -735,7 +739,7 @@ static void gen_extend_byte(bool sign,bool dword,DynReg * ddr,DynReg * dsr,Bit8u
|
|||
ddr->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_lea(DynReg * ddr,DynReg * dsr1,DynReg * dsr2,Bitu scale,Bit32s imm) {
|
||||
static void gen_lea(DynReg * ddr,DynReg * dsr1,DynReg * dsr2,Bitu scale,Bits imm) {
|
||||
if (ddr==dsr1 && dsr2==NULL && !imm)
|
||||
return;
|
||||
if (ddr==dsr2 && dsr1==NULL) {
|
||||
|
@ -767,11 +771,6 @@ static void gen_lea(DynReg * ddr,DynReg * dsr1,DynReg * dsr2,Bitu scale,Bit32s i
|
|||
ddr->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_lea_imm_mem(DynReg * ddr,DynReg * dsr,void* data) {
|
||||
gen_load_host(data, ddr, 4);
|
||||
gen_lea(ddr, ddr, dsr, 0, 0);
|
||||
}
|
||||
|
||||
static void gen_dop_word(DualOps op,bool dword,DynReg * dr1,DynReg * dr2) {
|
||||
Bit8u tmp;
|
||||
GenReg *gr2 = FindDynReg(dr2);
|
||||
|
@ -810,7 +809,10 @@ static void gen_dop_word_imm(DualOps op,bool dword,DynReg * dr1,Bits imm) {
|
|||
Bit8u tmp=0x81;
|
||||
int dst = FindDynReg(dr1,dword && op==DOP_MOV)->index;
|
||||
opcode i;
|
||||
if (!dword) i.setword();
|
||||
if (!dword) {
|
||||
i.setword();
|
||||
imm = (Bit16s)imm;
|
||||
} else imm = (Bit32s)imm;
|
||||
if (op <= DOP_OR && (Bit8s)imm==imm) {
|
||||
i.setimm(imm, 1);
|
||||
tmp = 0x83;
|
||||
|
@ -891,6 +893,11 @@ static void gen_dop_word_imm_mem(DualOps op,bool dword,DynReg * dr1,void* data)
|
|||
gen_dop_word(op,dr1,i);
|
||||
}
|
||||
|
||||
static void gen_lea_imm_mem(DynReg * ddr,DynReg * dsr,void* data) {
|
||||
gen_dop_word_imm_mem(DOP_MOV,true,ddr,data);
|
||||
gen_lea(ddr, ddr, dsr, 0, 0);
|
||||
}
|
||||
|
||||
static void gen_imul_word(bool dword,DynReg * dr1,DynReg * dr2) {
|
||||
// dr1 = dr1*dr2
|
||||
opcode(FindDynReg(dr1)->index,dword).setrm(FindDynReg(dr2)->index).Emit16(0xAF0F);
|
||||
|
@ -926,14 +933,14 @@ static void gen_sop_word(SingleOps op,bool dword,DynReg * dr1) {
|
|||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_shift_byte_cl(Bitu op,DynReg * dr1,Bit8u di1,DynReg * drecx) {
|
||||
static void gen_shift_byte_cl(Bitu op,DynReg * dr1,Bitu di1,DynReg * drecx) {
|
||||
ForceDynReg(x64gen.regs[X64_REG_RCX],drecx);
|
||||
opcode(op).setrm(FindDynReg(dr1)->index,di1).Emit8(0xD2);
|
||||
opcode((int)op).setrm(FindDynReg(dr1)->index,di1).Emit8(0xD2);
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_shift_byte_imm(Bitu op,DynReg * dr1,Bit8u di1,Bit8u imm) {
|
||||
opcode inst = opcode(op).setrm(FindDynReg(dr1)->index,di1);
|
||||
static void gen_shift_byte_imm(Bitu op,DynReg * dr1,Bitu di1,Bit8u imm) {
|
||||
opcode inst = opcode((int)op).setrm(FindDynReg(dr1)->index,di1);
|
||||
if (imm==1) inst.Emit8(0xD0);
|
||||
else inst.setimm(imm,1).Emit8(0xC0);
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
|
@ -941,12 +948,12 @@ static void gen_shift_byte_imm(Bitu op,DynReg * dr1,Bit8u di1,Bit8u imm) {
|
|||
|
||||
static void gen_shift_word_cl(Bitu op,bool dword,DynReg * dr1,DynReg * drecx) {
|
||||
ForceDynReg(x64gen.regs[X64_REG_RCX],drecx);
|
||||
opcode(op,dword).setrm(FindDynReg(dr1)->index).Emit8(0xD3);
|
||||
opcode((int)op,dword).setrm(FindDynReg(dr1)->index).Emit8(0xD3);
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_shift_word_imm(Bitu op,bool dword,DynReg * dr1,Bit8u imm) {
|
||||
opcode inst = opcode(op,dword).setrm(FindDynReg(dr1)->index);
|
||||
opcode inst = opcode((int)op,dword).setrm(FindDynReg(dr1)->index);
|
||||
if (imm==1) inst.Emit8(0xD1);
|
||||
else inst.setimm(imm,1).Emit8(0xC1);
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
|
@ -970,7 +977,7 @@ static void gen_cwd(bool dword,DynReg * dyn_ax,DynReg * dyn_dx) {
|
|||
else cache_addb(0x99);
|
||||
}
|
||||
|
||||
static void gen_mul_byte(bool imul,DynReg * dyn_ax,DynReg * dr1,Bit8u di1) {
|
||||
static void gen_mul_byte(bool imul,DynReg * dyn_ax,DynReg * dr1,Bitu di1) {
|
||||
ForceDynReg(x64gen.regs[X64_REG_RAX],dyn_ax);
|
||||
opcode(imul?5:4).setrm(FindDynReg(dr1)->index,di1).Emit8(0xF6);
|
||||
dyn_ax->flags|=DYNFLG_CHANGED;
|
||||
|
@ -1001,7 +1008,7 @@ static void gen_dshift_cl(bool dword,bool left,DynReg * dr1,DynReg * dr2,DynReg
|
|||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_call_ptr(void *func=NULL) {
|
||||
static void gen_call_ptr(void *func=NULL, Bit8u ptr=0) {
|
||||
x64gen.regs[X64_REG_RAX]->Clear();
|
||||
x64gen.regs[X64_REG_RCX]->Clear();
|
||||
x64gen.regs[X64_REG_RDX]->Clear();
|
||||
|
@ -1015,19 +1022,19 @@ static void gen_call_ptr(void *func=NULL) {
|
|||
x64gen.regs[X64_REG_R11]->Clear();
|
||||
|
||||
/* Do the actual call to the procedure */
|
||||
if (func==NULL) cache_addw(0xD0FF); // call rax
|
||||
else {
|
||||
if (func!=NULL) {
|
||||
Bits diff = (Bits)func - (Bits)cache.pos - 5;
|
||||
if ((Bit32s)diff == diff) opcode(0).setimm(diff,4).Emit8Reg(0xE8); // call rel32
|
||||
else {
|
||||
gen_load_imm(0, (Bitu)func);
|
||||
cache_addw(0xD0FF);
|
||||
if ((Bit32s)diff == diff) {
|
||||
opcode(0).setimm(diff,4).Emit8Reg(0xE8); // call rel32
|
||||
return;
|
||||
}
|
||||
gen_load_imm(ptr, (Bitu)func);
|
||||
}
|
||||
opcode(2).setrm(ptr).Emit8(0xFF); // call ptr
|
||||
}
|
||||
|
||||
static void gen_call_function(void * func,const char* ops,...) {
|
||||
Bits paramcount=0;
|
||||
Bitu paramcount=0;
|
||||
va_list params;
|
||||
DynReg *dynret=NULL;
|
||||
char rettype;
|
||||
|
@ -1047,7 +1054,7 @@ static void gen_call_function(void * func,const char* ops,...) {
|
|||
else gen_load_imm(gen->index,va_arg(params,Bitu));
|
||||
break;
|
||||
case 'D': /* Dynamic register */
|
||||
gen_load_arg_reg(paramcount++, va_arg(params,DynReg*), ops++);
|
||||
gen_load_arg_reg((int)paramcount++, va_arg(params,DynReg*), ops++);
|
||||
break;
|
||||
case 'R': /* Dynamic register for returned value */
|
||||
dynret = va_arg(params,DynReg*);
|
||||
|
@ -1056,8 +1063,9 @@ static void gen_call_function(void * func,const char* ops,...) {
|
|||
case 'F': /* arg is flags, release */
|
||||
gen = x64gen.regs[reg_args[paramcount++]];
|
||||
gen->Clear();
|
||||
opcode(gen->index).setea(4,-1,0,CALLSTACK+8).Emit8(0x8B); // mov reg, [rsp+8/40]
|
||||
opcode(0).set64().setimm(CALLSTACK+16,1).setrm(4).Emit8(0x83); // add rsp,16/48
|
||||
gen_protectflags();
|
||||
opcode(gen->index).setea(4,-1,0,CALLSTACK).Emit8(0x8B); // mov reg, [rsp+8/40]
|
||||
opcode(0).set64().setimm(CALLSTACK+8,1).setrm(4).Emit8(0x83); // add rsp,16/48
|
||||
break;
|
||||
default:
|
||||
IllegalOption("gen_call_function unknown param");
|
||||
|
@ -1129,7 +1137,7 @@ static void gen_fill_branch(Bit8u * data,Bit8u * from=cache.pos) {
|
|||
if (len>127)
|
||||
LOG_MSG("Big jump %d",len);
|
||||
#endif
|
||||
*data=(from-data-1);
|
||||
*data=(Bit8u)(from-data-1);
|
||||
}
|
||||
|
||||
static Bit8u * gen_create_branch_long(BranchTypes type) {
|
||||
|
@ -1139,18 +1147,18 @@ static Bit8u * gen_create_branch_long(BranchTypes type) {
|
|||
}
|
||||
|
||||
static void gen_fill_branch_long(Bit8u * data,Bit8u * from=cache.pos) {
|
||||
*(Bit32u*)data=(from-data-4);
|
||||
*(Bit32u*)data=(Bit32u)(from-data-4);
|
||||
}
|
||||
|
||||
static Bit8u * gen_create_jump(Bit8u * to=0) {
|
||||
/* First free all registers */
|
||||
cache_addb(0xe9);
|
||||
cache_addd(to-(cache.pos+4));
|
||||
cache_addd((Bit32u)(to-(cache.pos+4)));
|
||||
return (cache.pos-4);
|
||||
}
|
||||
|
||||
static void gen_fill_jump(Bit8u * data,Bit8u * to=cache.pos) {
|
||||
*(Bit32u*)data=(to-data-4);
|
||||
*(Bit32u*)data=(Bit32u)(to-data-4);
|
||||
}
|
||||
|
||||
static Bit8u * gen_create_short_jump(void) {
|
||||
|
@ -1165,7 +1173,7 @@ static void gen_fill_short_jump(Bit8u * data, Bit8u * to=cache.pos) {
|
|||
if (len>127)
|
||||
LOG_MSG("Big jump %d",len);
|
||||
#endif
|
||||
data[0] = to-data-1;
|
||||
data[0] = (Bit8u)(to-data-1);
|
||||
}
|
||||
|
||||
static void gen_jmp_ptr(void * _ptr,Bit32s imm=0) {
|
||||
|
@ -1179,17 +1187,17 @@ static void gen_jmp_ptr(void * _ptr,Bit32s imm=0) {
|
|||
|
||||
static void gen_save_flags(DynReg * dynreg) {
|
||||
if (GCC_UNLIKELY(x64gen.flagsactive)) IllegalOption("gen_save_flags");
|
||||
opcode(FindDynReg(dynreg)->index).setea(4,-1,0,CALLSTACK+8).Emit8(0x8B); // mov reg32, [rsp+8/40]
|
||||
opcode(FindDynReg(dynreg)->index).setea(4,-1,0,CALLSTACK).Emit8(0x8B); // mov reg32, [rsp+8/40]
|
||||
dynreg->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_load_flags(DynReg * dynreg) {
|
||||
if (GCC_UNLIKELY(x64gen.flagsactive)) IllegalOption("gen_load_flags");
|
||||
opcode(FindDynReg(dynreg)->index).setea(4,-1,0,CALLSTACK+8).Emit8(0x89); // mov [rsp+8/40],reg32
|
||||
opcode(FindDynReg(dynreg)->index).setea(4,-1,0,CALLSTACK).Emit8(0x89); // mov [rsp+8/40],reg32
|
||||
}
|
||||
|
||||
static void gen_save_host_direct(void *data,Bitu imm) {
|
||||
if ((Bit32s)imm != imm) {
|
||||
if ((Bit32s)imm != (Bits)imm) {
|
||||
opcode(0).setimm(imm,4).setabsaddr(data).Emit8(0xC7); // mov dword[], imm32 (low dword)
|
||||
opcode(0).setimm(imm>>32,4).setabsaddr((Bit8u*)data+4).Emit8(0xC7); // high dword
|
||||
} else
|
||||
|
@ -1198,28 +1206,28 @@ static void gen_save_host_direct(void *data,Bitu imm) {
|
|||
|
||||
static void gen_return(BlockReturn retcode) {
|
||||
gen_protectflags();
|
||||
opcode(1).setea(4,-1,0,CALLSTACK+8).Emit8(0x8B); // mov ecx, [rsp+8/40]
|
||||
opcode(0).set64().setrm(4).setimm(CALLSTACK+16,1).Emit8(0x83); // add rsp,16/48
|
||||
opcode(1).setea(4,-1,0,CALLSTACK).Emit8(0x8B); // mov ecx, [rsp+8/40]
|
||||
opcode(0).set64().setrm(4).setimm(CALLSTACK+8,1).Emit8(0x83); // add rsp,16/48
|
||||
if (retcode==0) cache_addw(0xc033); // xor eax,eax
|
||||
else {
|
||||
cache_addb(0xb8); //MOV EAX, retcode
|
||||
cache_addd(retcode);
|
||||
}
|
||||
opcode(4).setea(4,-1,0,CALLSTACK).Emit8(0xFF); // jmp [rsp+CALLSTACK]
|
||||
opcode(4).setea(4,-1,0,CALLSTACK-8).Emit8(0xFF); // jmp [rsp+CALLSTACK-8]
|
||||
}
|
||||
|
||||
static void gen_return_fast(BlockReturn retcode,bool ret_exception=false) {
|
||||
if (GCC_UNLIKELY(x64gen.flagsactive)) IllegalOption("gen_return_fast");
|
||||
opcode(1).setabsaddr(®_flags).Emit8(0x8B); // mov ECX, [cpu_regs.flags]
|
||||
if (!ret_exception) {
|
||||
opcode(0).set64().setrm(4).setimm(CALLSTACK+16,1).Emit8(0x83); // add rsp,16/48
|
||||
opcode(0).set64().setrm(4).setimm(CALLSTACK+8,1).Emit8(0x83); // add rsp,16/48
|
||||
if (retcode==0) cache_addw(0xc033); // xor eax,eax
|
||||
else {
|
||||
cache_addb(0xb8); //MOV EAX, retcode
|
||||
cache_addd(retcode);
|
||||
}
|
||||
}
|
||||
opcode(4).setea(4,-1,0,CALLSTACK).Emit8(0xFF); // jmp [rsp+CALLSTACK]
|
||||
opcode(4).setea(4,-1,0,CALLSTACK-8).Emit8(0xFF); // jmp [rsp+CALLSTACK]
|
||||
}
|
||||
|
||||
static void gen_init(void) {
|
||||
|
|
|
@ -312,7 +312,7 @@ static void gen_load_host(void * data,DynReg * dr1,Bitu size) {
|
|||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_mov_host(void * data,DynReg * dr1,Bitu size,Bit8u di1=0) {
|
||||
static void gen_mov_host(void * data,DynReg * dr1,Bitu size,Bitu di1=0) {
|
||||
GenReg * gr1=FindDynReg(dr1,(size==4));
|
||||
switch (size) {
|
||||
case 1:cache_addb(0x8a);break; //mov byte
|
||||
|
@ -321,7 +321,7 @@ static void gen_mov_host(void * data,DynReg * dr1,Bitu size,Bit8u di1=0) {
|
|||
default:
|
||||
IllegalOption("gen_mov_host");
|
||||
}
|
||||
cache_addb(0x5+((gr1->index+(di1?4:0))<<3));
|
||||
cache_addb(0x5+((gr1->index+di1)<<3));
|
||||
cache_addd((Bit32u)data);
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
|
|
@ -201,30 +201,29 @@ bool Overlay_Drive::TestDir(char * dir) {
|
|||
class OverlayFile: public localFile {
|
||||
public:
|
||||
OverlayFile(const char* name, FILE * handle):localFile(name,handle){
|
||||
overlay_active = false;
|
||||
if (logoverlay) LOG_MSG("constructing OverlayFile: %s",name);
|
||||
}
|
||||
bool Write(Bit8u * data,Bit16u * size) {
|
||||
Bit32u f = real_flags&0xf;
|
||||
Bit32u f = flags&0xf;
|
||||
if (!overlay_active && (f == OPEN_READWRITE || f == OPEN_WRITE)) {
|
||||
if (logoverlay) LOG_MSG("write detected, switching file for %s",GetName());
|
||||
if (*data == 0) {
|
||||
if (logoverlay) LOG_MSG("OPTIMISE: truncate on switch!!!!");
|
||||
}
|
||||
Bitu a = GetTicks();
|
||||
Bit32u a = GetTicks();
|
||||
bool r = create_copy();
|
||||
if (GetTicks()-a >2) {
|
||||
if (logoverlay) LOG_MSG("OPTIMISE: switching took %d",GetTicks()-a);
|
||||
}
|
||||
if (!r) return false;
|
||||
overlay_active = true;
|
||||
flags = real_flags;
|
||||
|
||||
}
|
||||
return localFile::Write(data,size);
|
||||
}
|
||||
bool create_copy();
|
||||
//private:
|
||||
Bit32u real_flags;
|
||||
bool overlay_active;
|
||||
};
|
||||
|
||||
|
@ -298,6 +297,7 @@ static OverlayFile* ccc(DOS_File* file) {
|
|||
//Create an overlayFile
|
||||
OverlayFile* ret = new OverlayFile(l->GetName(),l->fhandle);
|
||||
ret->flags = l->flags;
|
||||
ret->refCtr = l->refCtr;
|
||||
delete l;
|
||||
return ret;
|
||||
}
|
||||
|
@ -440,14 +440,13 @@ bool Overlay_Drive::FileOpen(DOS_File * * file,char * name,Bit32u flags) {
|
|||
//TODO take care of file being marked deleted.
|
||||
|
||||
if (!fileopened && !is_deleted_file(name)) fileopened = localDrive::FileOpen(file,name, OPEN_READ);
|
||||
|
||||
|
||||
|
||||
|
||||
if (fileopened) {
|
||||
if (logoverlay) LOG_MSG("file opened %s",name);
|
||||
//Convert file to OverlayFile
|
||||
OverlayFile* f = ccc(*file);
|
||||
//Store original flags, as with overlay the files are opened read only and they switch on write
|
||||
f->real_flags = flags;
|
||||
f->flags = flags; //ccc copies the flags of the localfile, which were not correct in this case
|
||||
f->overlay_active = overlayed; //No need to switch if already in overlayed.
|
||||
*file = f;
|
||||
}
|
||||
|
@ -471,7 +470,7 @@ bool Overlay_Drive::FileCreate(DOS_File * * file,char * name,Bit16u /*attributes
|
|||
(*file)->flags = OPEN_READWRITE;
|
||||
OverlayFile* of = ccc(*file);
|
||||
of->overlay_active = true;
|
||||
of->real_flags = OPEN_READWRITE;
|
||||
of->flags = OPEN_READWRITE;
|
||||
*file = of;
|
||||
//create fake name for the drive cache
|
||||
char fakename[CROSS_LEN];
|
||||
|
@ -543,7 +542,7 @@ bool Overlay_Drive::Sync_leading_dirs(const char* dos_filename){
|
|||
return true;
|
||||
}
|
||||
void Overlay_Drive::update_cache(bool read_directory_contents) {
|
||||
Bitu a = GetTicks();
|
||||
Bit32u a = GetTicks();
|
||||
std::vector<std::string> specials;
|
||||
std::vector<std::string> dirnames;
|
||||
std::vector<std::string> filenames;
|
||||
|
@ -821,7 +820,7 @@ again:
|
|||
|
||||
bool Overlay_Drive::FileUnlink(char * name) {
|
||||
//TODO check the basedir for file existence in order if we need to add the file to deleted file list.
|
||||
Bitu a = GetTicks();
|
||||
Bit32u a = GetTicks();
|
||||
if (logoverlay) LOG_MSG("calling unlink on %s",name);
|
||||
char basename[CROSS_LEN];
|
||||
strcpy(basename,basedir);
|
||||
|
@ -1088,7 +1087,7 @@ bool Overlay_Drive::Rename(char * oldname,char * newname) {
|
|||
E_Exit("renaming directory %s to %s . Not yet supported in Overlay",oldname,newname); //TODO
|
||||
}
|
||||
|
||||
Bitu a = GetTicks();
|
||||
Bit32u a = GetTicks();
|
||||
//First generate overlay names.
|
||||
char overlaynameold[CROSS_LEN];
|
||||
strcpy(overlaynameold,overlaydir);
|
||||
|
@ -1111,7 +1110,7 @@ bool Overlay_Drive::Rename(char * oldname,char * newname) {
|
|||
//TODO CHECK if base has a file with same oldname!!!!! if it does mark it as deleted!!
|
||||
if (localDrive::FileExists(oldname)) add_deleted_file(oldname,true);
|
||||
} else {
|
||||
Bitu aa = GetTicks();
|
||||
Bit32u aa = GetTicks();
|
||||
//File exists in the basedrive. Make a copy and mark old one as deleted.
|
||||
char newold[CROSS_LEN];
|
||||
strcpy(newold,basedir);
|
||||
|
|
Loading…
Add table
Reference in a new issue