Various (mostly) x86-64 related patches
PATCH 1/1 Various (mostly) x86-64 related patches
qemu-20050718-01-vaddr.patch
Fix TB virtual page map for x86-64 (at least 48bits of VA must
be honoured).
qemu-20050718-02-insns.patch
- Add support for AMD cache info MCR.
- Fix INVLPG instruction in 64bit mode.
- Implement the ENTER instruction for 64bit mode.
- Add dummy support for MCA, PAT, MTRR and CLFLUSH.
- Correct size of 16bit stack pushes in 64bit mode.
- Correct segment arithmetics for various instructions in 64bit
mode.
- Correctly honour the ADDR prefix for these instrutions:
maskmov; mov EAX, Ov; mov Ov, EAX
- Fix the implicit 64bit semantics for these instrutions:
ret im; lcall; lret
- Support the PREFETCHW instruction.
qemu-20050718-03-apic.patch
* vl.h (ioapic_init, ioapic_set_irq): Declare.
* hw/apic.c (apic_get_current_count, apic_timer_update):
Fix division by zero if s->initial_count == ~0. (apic_get_delivery_bitmask, apic_bus_deliver, apic_deliver, apic_mem_readl, apic_mem_writel):
Implent basic interrupt control and delivery (no arbitration). (ioapic_service, ioapic_set_irq, ioapic_mem_readl, ioapic_mem_writel, ioapic_mem_read, ioapic_mem_write, ioapic_init): Implement I/O APIC.
(apic_init): Automatically assign ID to the APIC and link it to local APIC list.
(apic_reset, ioapic_reset): Add reset handlers. (apic_save, apic_load, ioapic_save, ioapic_load):
Add save and load handlers.
* hw/i8259.c (pic_set_irq): Forward interrupts to I/O APIC.
* hw/pc.c (pc_init1): Initialize the I/O APIC. (cpu_get_pic_interrupt): Compile the APIC stuff even in non-x86-64 case.
qemu-20050718-04-doc.patch
Minor qemu-img documentation update.
qemu-20050718-05-sdl.patch
Don't make the SDL window resizable. It doesn't make sense to
mark it that way since we really don't handle it (either by scrolling or scaling).
Index: sdl.c
===================================================================
RCS file: /cvsroot/qemu/qemu/sdl.c,v
retrieving revision 1.21
sdl.c +0 -1
@@ -53,7 +53,6 @@// printf("resizing to %d %d\n", w, h); flags =SDL_HWSURFACE |SDL_ASYNCBLIT |SDL_HWACCEL ; - flags |=SDL_RESIZABLE ;if (gui_fullscreen) flags |=SDL_FULLSCREEN ; screen =SDL_SetVideoMode (w, h,0 , flags);
Index: exec.c
===================================================================
RCS file: /cvsroot/qemu/qemu/exec.c,v
retrieving revision 1.60
exec.c +27 -16
105 lines not on this page · raw message
Index: target-i386/cpu.h
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/cpu.h,v
retrieving revision 1.30
cpu.h +30 -19
68 lines not on this page · raw message
Index: target-i386/exec.h
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/exec.h,v
retrieving revision 1.24
exec.h +2 -2
@@ -157,11 +157,11 @@void helper_ltr_T0 (void );void helper_movl_crN_T0 (int reg);void helper_movl_drN_T0 (int reg); -void helper_invlpg (unsigned int addr); +void helper_invlpg (target_ulong addr);void cpu_x86_update_cr0 (CPUX86State *env,uint32_t new_cr0);void cpu_x86_update_cr3 (CPUX86State *env,target_ulong new_cr3);void cpu_x86_update_cr4 (CPUX86State *env,uint32_t new_cr4); -void cpu_x86_flush_tlb (CPUX86State *env,uint32_t addr); +void cpu_x86_flush_tlb (CPUX86State *env,target_ulong addr);int cpu_x86_handle_mmu_fault (CPUX86State *env,target_ulong addr,int is_write,int is_user,int is_softmmu); void tlb_fill(target_ulong addr, int is_write, int is_user,
Index: target-i386/helper.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/helper.c,v retrieving revision 1.49
helper.c +36 -2
@@ -1334,6 +1334,20 @@ECX = env->cpuid_model[(index -0x80000002 ) *4 +2 ];EDX = env->cpuid_model[(index -0x80000002 ) *4 +3 ];break ; +case 0x80000005 : +/* cache info (L1 cache) */ +EAX =0x01ff01ff ; +EBX =0x01ff01ff ; +ECX =0x40020140 ; +EDX =0x40020140 ; +break ; +case 0x80000006 : +/* cache info (L2 cache) */ +EAX =0 ; +EBX =0x42004200 ; +ECX =0x02008140 ; +EDX =0 ; +break ;case 0x80000008 :/* virtual & phys address size in low 2 bytes. */ EAX =0x00003028 ;
@@ -1354,12 +1368,26 @@void helper_enter_level (int level,int data32) {target_ulong ssp; -uint32_t esp_mask, esp, ebp; +uint32_t esp_mask; +target_ulong esp, ebp; esp_mask =get_sp_mask (env->segs[R_SS ].flags); ssp = env->segs[R_SS ].base; ebp =EBP ; esp =ESP ; +#ifdef TARGET_X86_64 +if (env->hflags &HF_CS64_MASK ) { +/* 64 bit */ + esp -=8 ; +while (--level) { + esp -=8 ; + ebp -=8 ; +stq (ssp + esp,ldq (ssp + ebp)); + } + esp -=8 ; +stq (ssp + esp,T1 ); + } else +#endif if (data32) {/* 32 bit */ esp -=4 ;
@@ -2271,7 +2299,7 @@ env->dr[reg] =T0 ; } -void helper_invlpg (unsigned int addr) +void helper_invlpg (target_ulong addr) {cpu_x86_flush_tlb (env, addr); }
@@ -2332,6 +2360,9 @@case MSR_STAR : env->star = val;break ; +case MSR_PAT : + env->pat = val; +break ;#ifdef TARGET_X86_64 case MSR_LSTAR : env->lstar = val;
@@ -2379,6 +2410,9 @@break ;case MSR_STAR : val = env->star; +break ; +case MSR_PAT : + val = env->pat;break ;#ifdef TARGET_X86_64 case MSR_LSTAR :
Index: target-i386/helper2.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/helper2.c,v retrieving revision 1.34
helper2.c +7 -2
@@ -106,7 +106,9 @@ env->cpuid_version = (family <<8 ) | (model <<4 ) | stepping; env->cpuid_features = (CPUID_FP87 |CPUID_DE |CPUID_PSE |CPUID_TSC |CPUID_MSR |CPUID_MCE | -CPUID_CX8 |CPUID_PGE |CPUID_CMOV ); +CPUID_CX8 |CPUID_PGE |CPUID_CMOV | +CPUID_PAT ); + env->pat =0x0007040600070406ULL ; env->cpuid_ext_features =0 ; env->cpuid_features |=CPUID_FXSR |CPUID_MMX |CPUID_SSE |CPUID_SSE2 |CPUID_PAE |CPUID_SEP ; env->cpuid_xlevel =0 ;
@@ -128,6 +130,9 @@ env->cpuid_ext2_features = (env->cpuid_features &0x0183F3FF ); env->cpuid_ext2_features |=CPUID_EXT2_LM |CPUID_EXT2_SYSCALL ; env->cpuid_xlevel =0x80000008 ; + +/* these features are needed for Win64 and aren't fully implemented */ + env->cpuid_features |=CPUID_MTRR |CPUID_CLFLUSH |CPUID_MCA ;#endif } cpu_single_env = env;
@@ -546,7 +551,7 @@ }/* XXX: also flush 4MB pages */ -void cpu_x86_flush_tlb (CPUX86State *env,uint32_t addr) +void cpu_x86_flush_tlb (CPUX86State *env,target_ulong addr) {tlb_flush_page (env, addr); }
Index: target-i386/op.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/op.c,v
retrieving revision 1.37
op.c +5 -0
@@ -898,6 +898,11 @@ }#ifdef TARGET_X86_64 +void op_subq_A0_2 (void ) +{ +A0 -=2 ; +} +void op_subq_A0_8 (void ) {A0 -=8 ;
Index: target-i386/translate.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/translate.c,v retrieving revision 1.49
translate.c +113 -33
286 lines not on this page · raw message
Index: vl.h
===================================================================
RCS file: /cvsroot/qemu/qemu/vl.h,v
retrieving revision 1.79
vl.h +2 -0
@@ -703,6 +703,8 @@/* APIC */ int apic_init (CPUState *env);int apic_get_interrupt (CPUState *env); +int ioapic_init (void ); +void ioapic_set_irq (uint32_t vector,int level);/* i8254.c */
Index: hw/apic.c
===================================================================
RCS file: /cvsroot/qemu/qemu/hw/apic.c,v
retrieving revision 1.2
apic.c +526 -40
729 lines not on this page · raw message
Index: hw/i8259.c
===================================================================
RCS file: /cvsroot/qemu/qemu/hw/i8259.c,v
retrieving revision 1.16
i8259.c +1 -0
@@ -186,6 +186,7 @@ }#endif pic_set_irq1 (&s->pics[irq >>3 ], irq &7 , level); +ioapic_set_irq (irq, level);pic_update_irq (s); }
Index: hw/pc.c
===================================================================
RCS file: /cvsroot/qemu/qemu/hw/pc.c,v
retrieving revision 1.38
pc.c +3 -3
@@ -70,7 +70,6 @@ {int intno; -#ifdef TARGET_X86_64 intno =apic_get_interrupt (env);if (intno >=0 ) {/* set irq request if a PIC irq is still pending */
@@ -78,7 +77,6 @@pic_update_irq (isa_pic);return intno; } -#endif /* read the irq from the PIC */ intno =pic_read_irq (isa_pic);return intno;
@@ -557,8 +555,10 @@register_ioport_read (0x92 ,1 ,1 , ioport92_read,NULL );register_ioport_write (0x92 ,1 ,1 , ioport92_write,NULL ); -if (pci_enabled) +if (pci_enabled) {apic_init (cpu_single_env); +ioapic_init (); + } isa_pic =pic_init (pic_irq_request, cpu_single_env); pit =pit_init (0x40 ,0 );
Index: qemu-img.texi
===================================================================
RCS file: /cvsroot/qemu/qemu/qemu-img.texi,v
retrieving revision 1.1
qemu-img.texi +1 -2
@@ -44,8 +44,7 @@ image format in QEMU. It is supported only for compatibility with previous versions. It does not work on win32. @item vmdk -VMware 3 and 4 compatible image format. Currently only supported as -read-only. +VMware 3 and 4 compatible image format. @item cloop Linux Compressed Loop image, useful only to reuse directly compressed CD-ROM images present for example in the Knoppix CD-ROMs.
Filip Navara wrote:
[snip]
Quoted 5 lines
qemu-20050718-02-insns.patch
- Add support for AMD cache info MCR.
- Fix INVLPG instruction in 64bit mode.
- Implement the ENTER instruction for 64bit mode.
- Add dummy support for MCA, PAT, MTRR and CLFLUSH.
Quoted 8 lines
- Correct size of 16bit stack pushes in 64bit mode.
- Correct segment arithmetics for various instructions in 64bit
mode.
- Correctly honour the ADDR prefix for these instrutions:
maskmov; mov EAX, Ov; mov Ov, EAX
- Fix the implicit 64bit semantics for these instrutions:
ret im; lcall; lret
- Support the PREFETCHW instruction.
This time with the correct patch (qemu-20050721-02-insns.patch).
Quoted 1 line
qemu-20050718-03-apic.patch
[snip]
I forgot to credit malc_ for his extensive testing, ideas and general help with this patch. Thanks!
- Filip
Index: target-i386/cpu.h
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/cpu.h,v
retrieving revision 1.30
cpu.h +30 -19
@@ -214,6 +214,12 @@#define MSR_IA32_SYSENTER_ESP 0x175#define MSR_IA32_SYSENTER_EIP 0x176 +#define MSR_MCG_CAP 0x179 +#define MSR_MCG_STATUS 0x17a +#define MSR_MCG_CTL 0x17b + +#define MSR_PAT 0x277 +#define MSR_EFER 0xc0000080#define MSR_EFER_SCE (1 << 0)
@@ -231,26 +237,29 @@#define MSR_KERNELGSBASE 0xc0000102/* cpuid_features bits */ -#define CPUID_FP87 (1 << 0) -#define CPUID_VME (1 << 1) -#define CPUID_DE (1 << 2) -#define CPUID_PSE (1 << 3) -#define CPUID_TSC (1 << 4) -#define CPUID_MSR (1 << 5) -#define CPUID_PAE (1 << 6) -#define CPUID_MCE (1 << 7) -#define CPUID_CX8 (1 << 8) -#define CPUID_APIC (1 << 9) -#define CPUID_SEP (1 << 11)/* sysenter/sysexit */ -#define CPUID_MTRR (1 << 12) -#define CPUID_PGE (1 << 13) -#define CPUID_MCA (1 << 14) -#define CPUID_CMOV (1 << 15) +#define CPUID_FP87 (1 << 0) +#define CPUID_VME (1 << 1) +#define CPUID_DE (1 << 2) +#define CPUID_PSE (1 << 3) +#define CPUID_TSC (1 << 4) +#define CPUID_MSR (1 << 5) +#define CPUID_PAE (1 << 6) +#define CPUID_MCE (1 << 7) +#define CPUID_CX8 (1 << 8) +#define CPUID_APIC (1 << 9) +#define CPUID_SEP (1 << 11)/* sysenter/sysexit */ +#define CPUID_MTRR (1 << 12) +#define CPUID_PGE (1 << 13) +#define CPUID_MCA (1 << 14) +#define CPUID_CMOV (1 << 15) +#define CPUID_PAT (1 << 16)/* ... */ -#define CPUID_MMX (1 << 23) -#define CPUID_FXSR (1 << 24) -#define CPUID_SSE (1 << 25) -#define CPUID_SSE2 (1 << 26) +#define CPUID_CLFLUSH (1 << 19) +/* ... */ +#define CPUID_MMX (1 << 23) +#define CPUID_FXSR (1 << 24) +#define CPUID_SSE (1 << 25) +#define CPUID_SSE2 (1 << 26)#define CPUID_EXT_SS3 (1 << 0)#define CPUID_EXT_MONITOR (1 << 3)
@@ -473,6 +482,8 @@target_ulong fmask;target_ulong kernelgsbase;#endif + +uint64_t pat;/* temporary data for USE_CODE_COPY mode */ #ifdef USE_CODE_COPY
Index: target-i386/exec.h
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/exec.h,v
retrieving revision 1.24
exec.h +2 -2
@@ -157,11 +157,11 @@void helper_ltr_T0 (void );void helper_movl_crN_T0 (int reg);void helper_movl_drN_T0 (int reg); -void helper_invlpg (unsigned int addr); +void helper_invlpg (target_ulong addr);void cpu_x86_update_cr0 (CPUX86State *env,uint32_t new_cr0);void cpu_x86_update_cr3 (CPUX86State *env,target_ulong new_cr3);void cpu_x86_update_cr4 (CPUX86State *env,uint32_t new_cr4); -void cpu_x86_flush_tlb (CPUX86State *env,uint32_t addr); +void cpu_x86_flush_tlb (CPUX86State *env,target_ulong addr);int cpu_x86_handle_mmu_fault (CPUX86State *env,target_ulong addr,int is_write,int is_user,int is_softmmu); void tlb_fill(target_ulong addr, int is_write, int is_user,
Index: target-i386/helper.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/helper.c,v retrieving revision 1.49
helper.c +36 -2
@@ -1334,6 +1334,20 @@ECX = env->cpuid_model[(index -0x80000002 ) *4 +2 ];EDX = env->cpuid_model[(index -0x80000002 ) *4 +3 ];break ; +case 0x80000005 : +/* cache info (L1 cache) */ +EAX =0x01ff01ff ; +EBX =0x01ff01ff ; +ECX =0x40020140 ; +EDX =0x40020140 ; +break ; +case 0x80000006 : +/* cache info (L2 cache) */ +EAX =0 ; +EBX =0x42004200 ; +ECX =0x02008140 ; +EDX =0 ; +break ;case 0x80000008 :/* virtual & phys address size in low 2 bytes. */ EAX =0x00003028 ;
@@ -1354,12 +1368,26 @@void helper_enter_level (int level,int data32) {target_ulong ssp; -uint32_t esp_mask, esp, ebp; +uint32_t esp_mask; +target_ulong esp, ebp; esp_mask =get_sp_mask (env->segs[R_SS ].flags); ssp = env->segs[R_SS ].base; ebp =EBP ; esp =ESP ; +#ifdef TARGET_X86_64 +if (env->hflags &HF_CS64_MASK ) { +/* 64 bit */ + esp -=8 ; +while (--level) { + esp -=8 ; + ebp -=8 ; +stq (ssp + esp,ldq (ssp + ebp)); + } + esp -=8 ; +stq (ssp + esp,T1 ); + } else +#endif if (data32) {/* 32 bit */ esp -=4 ;
@@ -2271,7 +2299,7 @@ env->dr[reg] =T0 ; } -void helper_invlpg (unsigned int addr) +void helper_invlpg (target_ulong addr) {cpu_x86_flush_tlb (env, addr); }
@@ -2332,6 +2360,9 @@case MSR_STAR : env->star = val;break ; +case MSR_PAT : + env->pat = val; +break ;#ifdef TARGET_X86_64 case MSR_LSTAR : env->lstar = val;
@@ -2379,6 +2410,9 @@break ;case MSR_STAR : val = env->star; +break ; +case MSR_PAT : + val = env->pat;break ;#ifdef TARGET_X86_64 case MSR_LSTAR :
Index: target-i386/helper2.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/helper2.c,v retrieving revision 1.34
helper2.c +7 -2
@@ -106,7 +106,9 @@ env->cpuid_version = (family <<8 ) | (model <<4 ) | stepping; env->cpuid_features = (CPUID_FP87 |CPUID_DE |CPUID_PSE |CPUID_TSC |CPUID_MSR |CPUID_MCE | -CPUID_CX8 |CPUID_PGE |CPUID_CMOV ); +CPUID_CX8 |CPUID_PGE |CPUID_CMOV | +CPUID_PAT ); + env->pat =0x0007040600070406ULL ; env->cpuid_ext_features =0 ; env->cpuid_features |=CPUID_FXSR |CPUID_MMX |CPUID_SSE |CPUID_SSE2 |CPUID_PAE |CPUID_SEP ; env->cpuid_xlevel =0 ;
@@ -128,6 +130,9 @@ env->cpuid_ext2_features = (env->cpuid_features &0x0183F3FF ); env->cpuid_ext2_features |=CPUID_EXT2_LM |CPUID_EXT2_SYSCALL ; env->cpuid_xlevel =0x80000008 ; + +/* these features are needed for Win64 and aren't fully implemented */ + env->cpuid_features |=CPUID_MTRR |CPUID_CLFLUSH |CPUID_MCA ;#endif } cpu_single_env = env;
@@ -546,7 +551,7 @@ }/* XXX: also flush 4MB pages */ -void cpu_x86_flush_tlb (CPUX86State *env,uint32_t addr) +void cpu_x86_flush_tlb (CPUX86State *env,target_ulong addr) {tlb_flush_page (env, addr); }
Index: target-i386/op.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/op.c,v
retrieving revision 1.37
op.c +5 -0
@@ -898,6 +898,11 @@ }#ifdef TARGET_X86_64 +void op_subq_A0_2 (void ) +{ +A0 -=2 ; +} +void op_subq_A0_8 (void ) {A0 -=8 ;
Index: target-i386/translate.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-i386/translate.c,v retrieving revision 1.49
translate.c +87 -32
236 lines not on this page · raw message
Two more patches...
qemu-20050723-05-apic.diff
EXTINT delivery mode support for I/O APIC.
qemu-20050723-06-div.diff
Raise #DE exception on DIV/IDIV overflows.
apic.c +18 -8
@@ -127,7 +127,7 @@ static void apic_bus_deliver(uint32_t dereturn ;case APIC_DM_EXTINT : -/* XXX: implement */ +/* handled in I/O APIC code */ break ;default :
@@ -742,24 +742,34 @@ int apic_init(CPUState *env)static void ioapic_service (IOAPICState *s) { +uint8_t i; +uint8_t trig_mode;uint8_t vector; +uint8_t delivery_mode;uint32_t mask;uint64_t entry;uint8_t dest;uint8_t dest_mode; +uint8_t polarity; -for (vector =0 ; vector <IOAPIC_NUM_PINS ; vector++) { - mask =1 << vector; +for (i =0 ; i <IOAPIC_NUM_PINS ; i++) { + mask =1 << i;if (s->irr & mask) { - entry = s->ioredtbl[vector]; + entry = s->ioredtbl[i];if (!(entry &APIC_LVT_MASKED )) { -if (!((entry >>15 ) &1 )) - s->irr &= ~mask; + trig_mode = ((entry >>15 ) &1 ); dest = entry >>56 ; dest_mode = (entry >>11 ) &1 ; + delivery_mode = (entry >>8 ) &7 ; + polarity = (entry >>13 ) &1 ; +if (trig_mode ==APIC_TRIGGER_EDGE ) + s->irr &= ~mask; +if (delivery_mode ==APIC_DM_EXTINT ) + vector =pic_read_irq (isa_pic); +else + vector = entry &0xff ;apic_bus_deliver (apic_get_delivery_bitmask (dest, dest_mode), - (entry >>8 ) &7 , entry &0xff , - (entry >>13 ) &1 , (entry >>15 ) &1 ); + delivery_mode, vector, polarity, trig_mode); } } }
helper.c +12 -6
@@ -1209,13 +1209,13 @@ void raise_exception(int exception_index#ifdef BUGGY_GCC_DIV64 /* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we call it from another function */ -uint32_t div32 (uint32_t *q_ptr,uint64_t num,uint32_t den) +uint32_t div32 (uint64_t *q_ptr,uint64_t num,uint32_t den) { *q_ptr = num / den;return num % den; } -int32_t idiv32 (int32_t *q_ptr,int64_t num,int32_t den) +int32_t idiv32 (int64_t *q_ptr,int64_t num,int32_t den) { *q_ptr = num / den;return num % den;
@@ -1224,8 +1224,8 @@ int32_t idiv32(int32_t *q_ptr, int64_t nvoid helper_divl_EAX_T0 (void ) { -unsigned int den, q, r; -uint64_t num; +unsigned int den, r; +uint64_t num, q; num = ((uint32_t )EAX ) | ((uint64_t )((uint32_t )EDX ) <<32 ); den =T0 ;
@@ -1238,14 +1238,17 @@ void helper_divl_EAX_T0(void) q = (num / den); r = (num % den);#endif +if (q >0xffffffff ) { +raise_exception (EXCP00_DIVZ ); + }EAX = (uint32_t )q;EDX = (uint32_t )r; }void helper_idivl_EAX_T0 (void ) { -int den, q, r; -int64_t num; +int den, r; +int64_t num, q; num = ((uint32_t )EAX ) | ((uint64_t )((uint32_t )EDX ) <<32 ); den =T0 ;
@@ -1258,6 +1262,9 @@ void helper_idivl_EAX_T0(void) q = (num / den); r = (num % den);#endif +if (q >0x7fffffff || q <-0x7fffffff ) { +raise_exception (EXCP00_DIVZ ); + }EAX = (uint32_t )q;EDX = (uint32_t )r; }
op.c +12 -1
@@ -328,7 +328,6 @@ void OPPROTO op_imulq_T0_T1(void)#endif /* division, flags are undefined */ -/* XXX: add exceptions for overflow */ void OPPROTO op_divb_AL_T0(void) {
@@ -341,6 +340,9 @@ void OPPROTO op_divb_AL_T0(void) } q = (num / den) &0xff ; r = (num % den) &0xff ; +if (q >0xff ) { +raise_exception (EXCP00_DIVZ ); + }EAX = (EAX & ~0xffff ) | (r <<8 ) | q; }
@@ -355,6 +357,9 @@ void OPPROTO op_idivb_AL_T0(void) } q = (num / den) &0xff ; r = (num % den) &0xff ; +if (q >0x7f || q <-0x7f ) { +raise_exception (EXCP00_DIVZ ); + }EAX = (EAX & ~0xffff ) | (r <<8 ) | q; }
@@ -369,6 +374,9 @@ void OPPROTO op_divw_AX_T0(void) } q = (num / den) &0xffff ; r = (num % den) &0xffff ; +if (q >0xffff ) { +raise_exception (EXCP00_DIVZ ); + }EAX = (EAX & ~0xffff ) | q;EDX = (EDX & ~0xffff ) | r; }
@@ -384,6 +392,9 @@ void OPPROTO op_idivw_AX_T0(void) } q = (num / den) &0xffff ; r = (num % den) &0xffff ; +if (q >0x7fff || q <-0x7fff ) { +raise_exception (EXCP00_DIVZ ); + }EAX = (EAX & ~0xffff ) | q;EDX = (EDX & ~0xffff ) | r; }