1
0
Fork 0

Fix branches getting out of range with div/idiv exceptions

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1776
This commit is contained in:
Sjoerd van der Berg 2004-04-24 09:16:08 +00:00
parent 48a86f7e97
commit 498ed26525
2 changed files with 46 additions and 69 deletions

View file

@ -298,6 +298,25 @@ static void dyn_fill_ea(bool addseg=true) {
#include "helpers.h"
#include "string.h"
static void DynRunException(void) {
CPU_Exception(cpu.exception.which,cpu.exception.error);
}
static void dyn_check_bool_exception(DynReg * check) {
Bit8u * branch;DynState state;
gen_dop_byte(DOP_OR,check,0,check,0);
branch=gen_create_branch(BR_Z);
dyn_savestate(&state);
dyn_flags_gen_to_host();
dyn_reduce_cycles();
dyn_set_eip_last();
dyn_save_critical_regs();
gen_call_function(&DynRunException,"");
gen_return(BR_Normal);
dyn_loadstate(&state);
gen_fill_branch(branch);
}
static void dyn_dop_ebgb(DualOps op) {
dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];
if (decode.modrm.mod<3) {
@ -589,7 +608,6 @@ static void dyn_grp2_ev(grp2_types type) {
}
static void dyn_grp3_eb(void) {
DynState state;Bit8u * branch;
dyn_get_modrm();DynReg * src;Bit8u src_i;
if (decode.modrm.mod<3) {
dyn_fill_ea();
@ -623,18 +641,7 @@ static void dyn_grp3_eb(void) {
gen_releasereg(DREG(EAX));
gen_call_function((decode.modrm.reg==6) ? (void *)&dyn_helper_divb : (void *)&dyn_helper_idivb,
"%Rd%Drl",DREG(TMPB),DREG(TMPB));
gen_dop_word(DOP_OR,true,DREG(TMPB),DREG(TMPB));
branch=gen_create_branch(BR_Z);
dyn_savestate(&state);
dyn_reduce_cycles();
dyn_set_eip_last();
dyn_flags_gen_to_host();
dyn_save_critical_regs();
gen_call_function((void *)&CPU_Exception,"%Id%Id",0,0);
dyn_flags_host_to_gen();
gen_return(BR_Normal);
dyn_loadstate(&state);
gen_fill_branch(branch);
dyn_check_bool_exception(DREG(TMPB));
goto skipsave;
}
/* Save the result if memory op */
@ -644,7 +651,6 @@ skipsave:
}
static void dyn_grp3_ev(void) {
DynState state;Bit8u * branch;
dyn_get_modrm();DynReg * src;
if (decode.modrm.mod<3) {
dyn_fill_ea();src=DREG(TMPW);
@ -675,19 +681,8 @@ static void dyn_grp3_ev(void) {
void * func=(decode.modrm.reg==6) ?
(decode.big_op ? (void *)&dyn_helper_divd : (void *)&dyn_helper_divw) :
(decode.big_op ? (void *)&dyn_helper_idivd : (void *)&dyn_helper_idivw);
gen_call_function(func,"%Rd%Drd",DREG(TMPW),DREG(TMPW));
gen_dop_word(DOP_OR,true,DREG(TMPW),DREG(TMPW));
branch=gen_create_branch(BR_Z);
dyn_savestate(&state);
dyn_reduce_cycles();
dyn_set_eip_last();
dyn_flags_gen_to_host();
dyn_save_critical_regs();
gen_call_function((void *)&CPU_Exception,"%Id%Id",0,0);
dyn_flags_host_to_gen();
gen_return(BR_Normal);
dyn_loadstate(&state);
gen_fill_branch(branch);
gen_call_function(func,"%Rd%Drd",DREG(TMPB),DREG(TMPW));
dyn_check_bool_exception(DREG(TMPB));
goto skipsave;
}
/* Save the result if memory op */
@ -714,24 +709,6 @@ static void dyn_synch_eip(void) {
gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),decode.code-decode.code_start);
}
static void DynRunException(void) {
CPU_Exception(cpu.exception.which,cpu.exception.error);
}
static void dyn_check_bool_exception(DynReg * check) {
Bit8u * branch;DynState state;
gen_dop_byte(DOP_OR,check,0,check,0);
branch=gen_create_branch(BR_Z);
dyn_savestate(&state);
dyn_flags_gen_to_host();
dyn_reduce_cycles();
dyn_set_eip_last();
dyn_save_critical_regs();
gen_call_function((void *)&DynRunException,"");
gen_return(BR_Normal);
dyn_loadstate(&state);
gen_fill_branch(branch);
}
static void dyn_load_seg(SegNames seg,DynReg * src) {
if (cpu.pmode) {
gen_call_function((void *)&CPU_SetSegGeneral,"%Rd%Id%Drw",DREG(TMPB),seg,src);

View file

@ -1,57 +1,57 @@
static Bitu dyn_helper_divb(Bit8u val) {
if (!val) return 1;
static bool dyn_helper_divb(Bit8u val) {
if (!val) return CPU_PrepareException(0,0);
Bitu quo=reg_ax / val;
reg_ah=(Bit8u)(reg_ax % val);
reg_al=(Bit8u)quo;
if (quo>0xff) return 1;
return 0;
if (quo>0xff) return CPU_PrepareException(0,0);
return false;
}
static Bitu dyn_helper_idivb(Bit8s val) {
if (!val) return 1;
static bool dyn_helper_idivb(Bit8s val) {
if (!val) return CPU_PrepareException(0,0);
Bits quo=(Bit16s)reg_ax / val;
reg_ah=(Bit8s)((Bit16s)reg_ax % val);
reg_al=(Bit8s)quo;
if (quo!=(Bit8s)reg_al) return 1;
return 0;
if (quo!=(Bit8s)reg_al) return CPU_PrepareException(0,0);
return false;
}
static Bitu dyn_helper_divw(Bit16u val) {
if (!val) return 1;
static bool dyn_helper_divw(Bit16u val) {
if (!val) return CPU_PrepareException(0,0);
Bitu num=(reg_dx<<16)|reg_ax;
Bitu quo=num/val;
reg_dx=(Bit16u)(num % val);
reg_ax=(Bit16u)quo;
if (quo!=reg_ax) return 1;
return 0;
if (quo!=reg_ax) return CPU_PrepareException(0,0);
return false;
}
static Bitu dyn_helper_idivw(Bit16s val) {
if (!val) return 1;
static bool dyn_helper_idivw(Bit16s val) {
if (!val) return CPU_PrepareException(0,0);
Bits num=(reg_dx<<16)|reg_ax;
Bits quo=num/val;
reg_dx=(Bit16s)(num % val);
reg_ax=(Bit16s)quo;
if (quo!=(Bit16s)reg_ax) return 1;
return 0;
if (quo!=(Bit16s)reg_ax) return CPU_PrepareException(0,0);
return false;
}
static Bitu dyn_helper_divd(Bit32u val) {
if (!val) return 1;
static bool dyn_helper_divd(Bit32u val) {
if (!val) return CPU_PrepareException(0,0);
Bit64u num=(((Bit64u)reg_edx)<<32)|reg_eax;
Bit64u quo=num/val;
reg_edx=(Bit32u)(num % val);
reg_eax=(Bit32u)quo;
if (quo!=(Bit64u)reg_eax) return 1;
return 0;
if (quo!=(Bit64u)reg_eax) return CPU_PrepareException(0,0);
return false;
}
static Bitu dyn_helper_idivd(Bit32s val) {
if (!val) return 1;
static bool dyn_helper_idivd(Bit32s val) {
if (!val) return CPU_PrepareException(0,0);
Bit64s num=(((Bit64u)reg_edx)<<32)|reg_eax;
Bit64s quo=num/val;
reg_edx=(Bit32s)(num % val);
reg_eax=(Bit32s)(quo);
if (quo!=(Bit64s)((Bit32s)reg_eax)) return 1;
return 0;
if (quo!=(Bit64s)((Bit32s)reg_eax)) return CPU_PrepareException(0,0);
return false;
}