From 498ed26525d50daeff5dadabe82ce218066d61a0 Mon Sep 17 00:00:00 2001 From: Sjoerd van der Berg Date: Sat, 24 Apr 2004 09:16:08 +0000 Subject: [PATCH] Fix branches getting out of range with div/idiv exceptions Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1776 --- src/cpu/core_dyn_x86/decoder.h | 67 +++++++++++----------------------- src/cpu/core_dyn_x86/helpers.h | 48 ++++++++++++------------ 2 files changed, 46 insertions(+), 69 deletions(-) diff --git a/src/cpu/core_dyn_x86/decoder.h b/src/cpu/core_dyn_x86/decoder.h index c7326058..36794259 100644 --- a/src/cpu/core_dyn_x86/decoder.h +++ b/src/cpu/core_dyn_x86/decoder.h @@ -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); diff --git a/src/cpu/core_dyn_x86/helpers.h b/src/cpu/core_dyn_x86/helpers.h index 7986540b..6fa75b3a 100644 --- a/src/cpu/core_dyn_x86/helpers.h +++ b/src/cpu/core_dyn_x86/helpers.h @@ -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; }