mirror of https://github.com/xqemu/xqemu.git
division by zero FPU exception support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@795 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
28c3ee3fed
commit
2ee73ac3a8
|
@ -143,6 +143,7 @@
|
||||||
#define CR0_MP_MASK (1 << 1)
|
#define CR0_MP_MASK (1 << 1)
|
||||||
#define CR0_EM_MASK (1 << 2)
|
#define CR0_EM_MASK (1 << 2)
|
||||||
#define CR0_TS_MASK (1 << 3)
|
#define CR0_TS_MASK (1 << 3)
|
||||||
|
#define CR0_ET_MASK (1 << 4)
|
||||||
#define CR0_NE_MASK (1 << 5)
|
#define CR0_NE_MASK (1 << 5)
|
||||||
#define CR0_WP_MASK (1 << 16)
|
#define CR0_WP_MASK (1 << 16)
|
||||||
#define CR0_AM_MASK (1 << 18)
|
#define CR0_AM_MASK (1 << 18)
|
||||||
|
@ -373,6 +374,8 @@ CPUX86State *cpu_x86_init(void);
|
||||||
int cpu_x86_exec(CPUX86State *s);
|
int cpu_x86_exec(CPUX86State *s);
|
||||||
void cpu_x86_close(CPUX86State *s);
|
void cpu_x86_close(CPUX86State *s);
|
||||||
int cpu_get_pic_interrupt(CPUX86State *s);
|
int cpu_get_pic_interrupt(CPUX86State *s);
|
||||||
|
/* MSDOS compatibility mode FPU exception support */
|
||||||
|
void cpu_set_ferr(CPUX86State *s);
|
||||||
|
|
||||||
/* this function must always be used to load data in the segment
|
/* this function must always be used to load data in the segment
|
||||||
cache: it synchronizes the hflags with the segment cache values */
|
cache: it synchronizes the hflags with the segment cache values */
|
||||||
|
|
|
@ -478,10 +478,24 @@ static inline void helper_fstt(CPU86_LDouble f, uint8_t *ptr)
|
||||||
|
|
||||||
#endif /* USE_X86LDOUBLE */
|
#endif /* USE_X86LDOUBLE */
|
||||||
|
|
||||||
|
#define FPUS_IE (1 << 0)
|
||||||
|
#define FPUS_DE (1 << 1)
|
||||||
|
#define FPUS_ZE (1 << 2)
|
||||||
|
#define FPUS_OE (1 << 3)
|
||||||
|
#define FPUS_UE (1 << 4)
|
||||||
|
#define FPUS_PE (1 << 5)
|
||||||
|
#define FPUS_SF (1 << 6)
|
||||||
|
#define FPUS_SE (1 << 7)
|
||||||
|
#define FPUS_B (1 << 15)
|
||||||
|
|
||||||
|
#define FPUC_EM 0x3f
|
||||||
|
|
||||||
const CPU86_LDouble f15rk[7];
|
const CPU86_LDouble f15rk[7];
|
||||||
|
|
||||||
void helper_fldt_ST0_A0(void);
|
void helper_fldt_ST0_A0(void);
|
||||||
void helper_fstt_ST0_A0(void);
|
void helper_fstt_ST0_A0(void);
|
||||||
|
void fpu_raise_exception(void);
|
||||||
|
CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b);
|
||||||
void helper_fbld_ST0_A0(void);
|
void helper_fbld_ST0_A0(void);
|
||||||
void helper_fbst_ST0_A0(void);
|
void helper_fbst_ST0_A0(void);
|
||||||
void helper_f2xm1(void);
|
void helper_f2xm1(void);
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#if 0
|
#if 0
|
||||||
#define raise_exception_err(a, b)\
|
#define raise_exception_err(a, b)\
|
||||||
do {\
|
do {\
|
||||||
printf("raise_exception line=%d\n", __LINE__);\
|
fprintf(logfile, "raise_exception line=%d\n", __LINE__);\
|
||||||
(raise_exception_err)(a, b);\
|
(raise_exception_err)(a, b);\
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
@ -859,10 +859,11 @@ void do_interrupt(int intno, int is_int, int error_code,
|
||||||
if (loglevel & (CPU_LOG_PCALL | CPU_LOG_INT)) {
|
if (loglevel & (CPU_LOG_PCALL | CPU_LOG_INT)) {
|
||||||
if ((env->cr[0] & CR0_PE_MASK)) {
|
if ((env->cr[0] & CR0_PE_MASK)) {
|
||||||
static int count;
|
static int count;
|
||||||
fprintf(logfile, "%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:%08x SP=%04x:%08x",
|
fprintf(logfile, "%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:%08x pc=%08x SP=%04x:%08x",
|
||||||
count, intno, error_code, is_int,
|
count, intno, error_code, is_int,
|
||||||
env->hflags & HF_CPL_MASK,
|
env->hflags & HF_CPL_MASK,
|
||||||
env->segs[R_CS].selector, EIP,
|
env->segs[R_CS].selector, EIP,
|
||||||
|
(int)env->segs[R_CS].base + EIP,
|
||||||
env->segs[R_SS].selector, ESP);
|
env->segs[R_SS].selector, ESP);
|
||||||
if (intno == 0x0e) {
|
if (intno == 0x0e) {
|
||||||
fprintf(logfile, " CR2=%08x", env->cr[2]);
|
fprintf(logfile, " CR2=%08x", env->cr[2]);
|
||||||
|
@ -1990,6 +1991,32 @@ void helper_fstt_ST0_A0(void)
|
||||||
helper_fstt(ST0, (uint8_t *)A0);
|
helper_fstt(ST0, (uint8_t *)A0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fpu_set_exception(int mask)
|
||||||
|
{
|
||||||
|
env->fpus |= mask;
|
||||||
|
if (env->fpus & (~env->fpuc & FPUC_EM))
|
||||||
|
env->fpus |= FPUS_SE | FPUS_B;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
|
||||||
|
{
|
||||||
|
if (b == 0.0)
|
||||||
|
fpu_set_exception(FPUS_ZE);
|
||||||
|
return a / b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fpu_raise_exception(void)
|
||||||
|
{
|
||||||
|
if (env->cr[0] & CR0_NE_MASK) {
|
||||||
|
raise_exception(EXCP10_COPR);
|
||||||
|
}
|
||||||
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
|
else {
|
||||||
|
cpu_set_ferr(env);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* BCD ops */
|
/* BCD ops */
|
||||||
|
|
||||||
void helper_fbld_ST0_A0(void)
|
void helper_fbld_ST0_A0(void)
|
||||||
|
|
|
@ -1738,12 +1738,12 @@ void OPPROTO op_fsubr_ST0_FT0(void)
|
||||||
|
|
||||||
void OPPROTO op_fdiv_ST0_FT0(void)
|
void OPPROTO op_fdiv_ST0_FT0(void)
|
||||||
{
|
{
|
||||||
ST0 /= FT0;
|
ST0 = helper_fdiv(ST0, FT0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OPPROTO op_fdivr_ST0_FT0(void)
|
void OPPROTO op_fdivr_ST0_FT0(void)
|
||||||
{
|
{
|
||||||
ST0 = FT0 / ST0;
|
ST0 = helper_fdiv(FT0, ST0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fp operations between STN and ST0 */
|
/* fp operations between STN and ST0 */
|
||||||
|
@ -1772,14 +1772,16 @@ void OPPROTO op_fsubr_STN_ST0(void)
|
||||||
|
|
||||||
void OPPROTO op_fdiv_STN_ST0(void)
|
void OPPROTO op_fdiv_STN_ST0(void)
|
||||||
{
|
{
|
||||||
ST(PARAM1) /= ST0;
|
CPU86_LDouble *p;
|
||||||
|
p = &ST(PARAM1);
|
||||||
|
*p = helper_fdiv(*p, ST0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OPPROTO op_fdivr_STN_ST0(void)
|
void OPPROTO op_fdivr_STN_ST0(void)
|
||||||
{
|
{
|
||||||
CPU86_LDouble *p;
|
CPU86_LDouble *p;
|
||||||
p = &ST(PARAM1);
|
p = &ST(PARAM1);
|
||||||
*p = ST0 / *p;
|
*p = helper_fdiv(ST0, *p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* misc FPU operations */
|
/* misc FPU operations */
|
||||||
|
@ -1959,6 +1961,13 @@ void OPPROTO op_fclex(void)
|
||||||
env->fpus &= 0x7f00;
|
env->fpus &= 0x7f00;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OPPROTO op_fwait(void)
|
||||||
|
{
|
||||||
|
if (env->fpus & FPUS_SE)
|
||||||
|
fpu_raise_exception();
|
||||||
|
FORCE_RET();
|
||||||
|
}
|
||||||
|
|
||||||
void OPPROTO op_fninit(void)
|
void OPPROTO op_fninit(void)
|
||||||
{
|
{
|
||||||
env->fpus = 0;
|
env->fpus = 0;
|
||||||
|
|
|
@ -3761,6 +3761,11 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
||||||
if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
|
if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
|
||||||
(HF_MP_MASK | HF_TS_MASK)) {
|
(HF_MP_MASK | HF_TS_MASK)) {
|
||||||
gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
|
gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
|
||||||
|
} else {
|
||||||
|
if (s->cc_op != CC_OP_DYNAMIC)
|
||||||
|
gen_op_set_cc_op(s->cc_op);
|
||||||
|
gen_op_jmp_im(pc_start - s->cs_base);
|
||||||
|
gen_op_fwait();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xcc: /* int3 */
|
case 0xcc: /* int3 */
|
||||||
|
|
Loading…
Reference in New Issue