From a17faf3c491171684a1e6595a21d275e22b1eb33 Mon Sep 17 00:00:00 2001 From: Peter Veenstra Date: Fri, 15 Apr 2005 14:20:42 +0000 Subject: [PATCH] idiv and friends shouldn't touch registers if an overflow occurs. (Thanks wd!) Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2175 --- src/cpu/core_dyn_x86/helpers.h | 46 +++++++++++++++++++++------------- src/cpu/instructions.h | 46 +++++++++++++++++++++------------- 2 files changed, 58 insertions(+), 34 deletions(-) diff --git a/src/cpu/core_dyn_x86/helpers.h b/src/cpu/core_dyn_x86/helpers.h index 6fa75b3a..b1e67759 100644 --- a/src/cpu/core_dyn_x86/helpers.h +++ b/src/cpu/core_dyn_x86/helpers.h @@ -1,18 +1,22 @@ 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; + Bit8u rem=(Bit8u)(reg_ax % val); + Bit8u quo8=(Bit8u)(quo&0xff); if (quo>0xff) return CPU_PrepareException(0,0); + reg_ah=rem; + reg_al=quo8; return false; } 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 CPU_PrepareException(0,0); + Bit8s rem=(Bit8s)((Bit16s)reg_ax % val); + Bit8s quo8s=(Bit8s)(quo&0xff); + if (quo!=(Bit16s)quo8s) return CPU_PrepareException(0,0); + reg_ah=rem; + reg_al=quo8s; return false; } @@ -20,9 +24,11 @@ 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 CPU_PrepareException(0,0); + Bit16u rem=(Bit16u)(num % val); + Bit16u quo16=(Bit16u)(quo&0xffff); + if (quo!=(Bit32u)quo16) return CPU_PrepareException(0,0); + reg_dx=rem; + reg_ax=quo16; return false; } @@ -30,9 +36,11 @@ 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 CPU_PrepareException(0,0); + Bit16s rem=(Bit16s)(num % val); + Bit16s quo16s=(Bit16s)quo; + if (quo!=(Bit32s)quo16s) return CPU_PrepareException(0,0); + reg_dx=rem; + reg_ax=quo16s; return false; } @@ -40,9 +48,11 @@ 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 CPU_PrepareException(0,0); + Bit32u rem=(Bit32u)(num % val); + Bit32u quo32=(Bit32u)(quo&0xffffffff); + if (quo!=(Bit64u)quo32) return CPU_PrepareException(0,0); + reg_edx=rem; + reg_eax=quo32; return false; } @@ -50,8 +60,10 @@ 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 CPU_PrepareException(0,0); + Bit32s rem=(Bit32s)(num % val); + Bit32s quo32s=(Bit32s)(quo&0xffffffff); + if (quo!=(Bit64s)quo32s) return CPU_PrepareException(0,0); + reg_edx=rem; + reg_eax=quo32s; return false; } diff --git a/src/cpu/instructions.h b/src/cpu/instructions.h index a6994f5f..563c401b 100644 --- a/src/cpu/instructions.h +++ b/src/cpu/instructions.h @@ -599,9 +599,11 @@ Bitu val=load(op1); \ if (val==0) EXCEPTION(0); \ Bitu quo=reg_ax / val; \ - reg_ah=(Bit8u)(reg_ax % val); \ - reg_al=(Bit8u)quo; \ + Bit8u rem=(Bit8u)(reg_ax % val); \ + Bit8u quo8=(Bit8u)(quo&0xff); \ if (quo>0xff) EXCEPTION(0); \ + reg_ah=rem; \ + reg_al=quo8; \ } @@ -611,9 +613,11 @@ if (val==0) EXCEPTION(0); \ Bitu num=(reg_dx<<16)|reg_ax; \ Bitu quo=num/val; \ - reg_dx=(Bit16u)(num % val); \ - reg_ax=(Bit16u)quo; \ - if (quo>0xffff) EXCEPTION(0); \ + Bit16u rem=(Bit16u)(num % val); \ + Bit16u quo16=(Bit16u)(quo&0xffff); \ + if (quo!=(Bit32u)quo16) EXCEPTION(0); \ + reg_dx=rem; \ + reg_ax=quo16; \ } #define DIVD(op1,load,save) \ @@ -622,9 +626,11 @@ if (!val) EXCEPTION(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) EXCEPTION(0); \ + Bit32u rem=(Bit32u)(num % val); \ + Bit32u quo32=(Bit32u)(quo&0xffffffff); \ + if (quo!=(Bit64u)quo32) EXCEPTION(0); \ + reg_edx=rem; \ + reg_eax=quo32; \ } @@ -633,9 +639,11 @@ Bits val=(Bit8s)(load(op1)); \ if (val==0) EXCEPTION(0); \ Bits quo=((Bit16s)reg_ax) / val; \ - reg_ah=(Bit8s)(((Bit16s)reg_ax) % val); \ - reg_al=(Bit8s)quo; \ - if (quo!=(Bit8s)reg_al) EXCEPTION(0); \ + Bit8s rem=(Bit8s)((Bit16s)reg_ax % val); \ + Bit8s quo8s=(Bit8s)(quo&0xff); \ + if (quo!=(Bit16s)quo8s) EXCEPTION(0); \ + reg_ah=rem; \ + reg_al=quo8s; \ } @@ -645,9 +653,11 @@ if (!val) EXCEPTION(0); \ Bits num=(Bit32s)((reg_dx<<16)|reg_ax); \ Bits quo=num/val; \ - reg_dx=(Bit16u)(num % val); \ - reg_ax=(Bit16s)quo; \ - if (quo!=(Bit16s)reg_ax) EXCEPTION(0); \ + Bit16s rem=(Bit16s)(num % val); \ + Bit16s quo16s=(Bit16s)quo; \ + if (quo!=(Bit32s)quo16s) EXCEPTION(0); \ + reg_dx=rem; \ + reg_ax=quo16s; \ } #define IDIVD(op1,load,save) \ @@ -656,9 +666,11 @@ if (!val) EXCEPTION(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)) EXCEPTION(0); \ + Bit32s rem=(Bit32s)(num % val); \ + Bit32s quo32s=(Bit32s)(quo&0xffffffff); \ + if (quo!=(Bit64s)quo32s) EXCEPTION(0); \ + reg_edx=rem; \ + reg_eax=quo32s; \ } #define IMULB(op1,load,save) \