diff --git a/docs/upstream/ChangeLog b/docs/upstream/ChangeLog index d35031ae..c99e11b4 100644 --- a/docs/upstream/ChangeLog +++ b/docs/upstream/ChangeLog @@ -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. diff --git a/docs/upstream/NEWS b/docs/upstream/NEWS index bf6b7a13..c6030702 100644 --- a/docs/upstream/NEWS +++ b/docs/upstream/NEWS @@ -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: diff --git a/src/cpu/core_dyn_x86.cpp b/src/cpu/core_dyn_x86.cpp index 00a30b7b..be572528 100644 --- a/src/cpu/core_dyn_x86.cpp +++ b/src/cpu/core_dyn_x86.cpp @@ -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" diff --git a/src/cpu/core_dyn_x86/decoder.h b/src/cpu/core_dyn_x86/decoder.h index 785ab877..ccb7a204 100644 --- a/src/cpu/core_dyn_x86/decoder.h +++ b/src/cpu/core_dyn_x86/decoder.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); } diff --git a/src/cpu/core_dyn_x86/risc_x64.h b/src/cpu/core_dyn_x86/risc_x64.h index 731885f0..9b4f906b 100644 --- a/src/cpu/core_dyn_x86/risc_x64.h +++ b/src/cpu/core_dyn_x86/risc_x64.h @@ -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) { diff --git a/src/cpu/core_dyn_x86/risc_x86.h b/src/cpu/core_dyn_x86/risc_x86.h index 94795e9d..fb0421f8 100644 --- a/src/cpu/core_dyn_x86/risc_x86.h +++ b/src/cpu/core_dyn_x86/risc_x86.h @@ -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; } diff --git a/src/dos/drive_overlay.cpp b/src/dos/drive_overlay.cpp index c146fb28..926eaade 100644 --- a/src/dos/drive_overlay.cpp +++ b/src/dos/drive_overlay.cpp @@ -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 specials; std::vector dirnames; std::vector 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);