Commit cc33c5d6 authored by Pavel Dovgalyuk's avatar Pavel Dovgalyuk Committed by Richard Henderson
Browse files

target-i386: exception handling for div instructions



This patch fixes exception handling for div instructions
and removes obsolete PC update from translate.c.

Reviewed-by: default avatarRichard Henderson <rth@twiddle.net>
Reviewed-by: default avatarAurelien Jarno <aurelien@aurel32.net>

Signed-off-by: default avatarPavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
Signed-off-by: default avatarRichard Henderson <rth@twiddle.net>
parent 6cad09d2
Loading
Loading
Loading
Loading
+16 −16
Original line number Diff line number Diff line
@@ -48,11 +48,11 @@ void helper_divb_AL(CPUX86State *env, target_ulong t0)
    num = (env->regs[R_EAX] & 0xffff);
    den = (t0 & 0xff);
    if (den == 0) {
        raise_exception(env, EXCP00_DIVZ);
        raise_exception_ra(env, EXCP00_DIVZ, GETPC());
    }
    q = (num / den);
    if (q > 0xff) {
        raise_exception(env, EXCP00_DIVZ);
        raise_exception_ra(env, EXCP00_DIVZ, GETPC());
    }
    q &= 0xff;
    r = (num % den) & 0xff;
@@ -66,11 +66,11 @@ void helper_idivb_AL(CPUX86State *env, target_ulong t0)
    num = (int16_t)env->regs[R_EAX];
    den = (int8_t)t0;
    if (den == 0) {
        raise_exception(env, EXCP00_DIVZ);
        raise_exception_ra(env, EXCP00_DIVZ, GETPC());
    }
    q = (num / den);
    if (q != (int8_t)q) {
        raise_exception(env, EXCP00_DIVZ);
        raise_exception_ra(env, EXCP00_DIVZ, GETPC());
    }
    q &= 0xff;
    r = (num % den) & 0xff;
@@ -84,11 +84,11 @@ void helper_divw_AX(CPUX86State *env, target_ulong t0)
    num = (env->regs[R_EAX] & 0xffff) | ((env->regs[R_EDX] & 0xffff) << 16);
    den = (t0 & 0xffff);
    if (den == 0) {
        raise_exception(env, EXCP00_DIVZ);
        raise_exception_ra(env, EXCP00_DIVZ, GETPC());
    }
    q = (num / den);
    if (q > 0xffff) {
        raise_exception(env, EXCP00_DIVZ);
        raise_exception_ra(env, EXCP00_DIVZ, GETPC());
    }
    q &= 0xffff;
    r = (num % den) & 0xffff;
@@ -103,11 +103,11 @@ void helper_idivw_AX(CPUX86State *env, target_ulong t0)
    num = (env->regs[R_EAX] & 0xffff) | ((env->regs[R_EDX] & 0xffff) << 16);
    den = (int16_t)t0;
    if (den == 0) {
        raise_exception(env, EXCP00_DIVZ);
        raise_exception_ra(env, EXCP00_DIVZ, GETPC());
    }
    q = (num / den);
    if (q != (int16_t)q) {
        raise_exception(env, EXCP00_DIVZ);
        raise_exception_ra(env, EXCP00_DIVZ, GETPC());
    }
    q &= 0xffff;
    r = (num % den) & 0xffff;
@@ -123,12 +123,12 @@ void helper_divl_EAX(CPUX86State *env, target_ulong t0)
    num = ((uint32_t)env->regs[R_EAX]) | ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
    den = t0;
    if (den == 0) {
        raise_exception(env, EXCP00_DIVZ);
        raise_exception_ra(env, EXCP00_DIVZ, GETPC());
    }
    q = (num / den);
    r = (num % den);
    if (q > 0xffffffff) {
        raise_exception(env, EXCP00_DIVZ);
        raise_exception_ra(env, EXCP00_DIVZ, GETPC());
    }
    env->regs[R_EAX] = (uint32_t)q;
    env->regs[R_EDX] = (uint32_t)r;
@@ -142,12 +142,12 @@ void helper_idivl_EAX(CPUX86State *env, target_ulong t0)
    num = ((uint32_t)env->regs[R_EAX]) | ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
    den = t0;
    if (den == 0) {
        raise_exception(env, EXCP00_DIVZ);
        raise_exception_ra(env, EXCP00_DIVZ, GETPC());
    }
    q = (num / den);
    r = (num % den);
    if (q != (int32_t)q) {
        raise_exception(env, EXCP00_DIVZ);
        raise_exception_ra(env, EXCP00_DIVZ, GETPC());
    }
    env->regs[R_EAX] = (uint32_t)q;
    env->regs[R_EDX] = (uint32_t)r;
@@ -379,12 +379,12 @@ void helper_divq_EAX(CPUX86State *env, target_ulong t0)
    uint64_t r0, r1;

    if (t0 == 0) {
        raise_exception(env, EXCP00_DIVZ);
        raise_exception_ra(env, EXCP00_DIVZ, GETPC());
    }
    r0 = env->regs[R_EAX];
    r1 = env->regs[R_EDX];
    if (div64(&r0, &r1, t0)) {
        raise_exception(env, EXCP00_DIVZ);
        raise_exception_ra(env, EXCP00_DIVZ, GETPC());
    }
    env->regs[R_EAX] = r0;
    env->regs[R_EDX] = r1;
@@ -395,12 +395,12 @@ void helper_idivq_EAX(CPUX86State *env, target_ulong t0)
    uint64_t r0, r1;

    if (t0 == 0) {
        raise_exception(env, EXCP00_DIVZ);
        raise_exception_ra(env, EXCP00_DIVZ, GETPC());
    }
    r0 = env->regs[R_EAX];
    r1 = env->regs[R_EDX];
    if (idiv64(&r0, &r1, t0)) {
        raise_exception(env, EXCP00_DIVZ);
        raise_exception_ra(env, EXCP00_DIVZ, GETPC());
    }
    env->regs[R_EAX] = r0;
    env->regs[R_EDX] = r1;
+0 −8
Original line number Diff line number Diff line
@@ -4841,21 +4841,17 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
        case 6: /* div */
            switch(ot) {
            case MO_8:
                gen_jmp_im(pc_start - s->cs_base);
                gen_helper_divb_AL(cpu_env, cpu_T[0]);
                break;
            case MO_16:
                gen_jmp_im(pc_start - s->cs_base);
                gen_helper_divw_AX(cpu_env, cpu_T[0]);
                break;
            default:
            case MO_32:
                gen_jmp_im(pc_start - s->cs_base);
                gen_helper_divl_EAX(cpu_env, cpu_T[0]);
                break;
#ifdef TARGET_X86_64
            case MO_64:
                gen_jmp_im(pc_start - s->cs_base);
                gen_helper_divq_EAX(cpu_env, cpu_T[0]);
                break;
#endif
@@ -4864,21 +4860,17 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
        case 7: /* idiv */
            switch(ot) {
            case MO_8:
                gen_jmp_im(pc_start - s->cs_base);
                gen_helper_idivb_AL(cpu_env, cpu_T[0]);
                break;
            case MO_16:
                gen_jmp_im(pc_start - s->cs_base);
                gen_helper_idivw_AX(cpu_env, cpu_T[0]);
                break;
            default:
            case MO_32:
                gen_jmp_im(pc_start - s->cs_base);
                gen_helper_idivl_EAX(cpu_env, cpu_T[0]);
                break;
#ifdef TARGET_X86_64
            case MO_64:
                gen_jmp_im(pc_start - s->cs_base);
                gen_helper_idivq_EAX(cpu_env, cpu_T[0]);
                break;
#endif