void helper_cmpxchg16b(CPUX86State *env, target_ulong a0)
{
    uint64_t d0, d1;
    int eflags;

    if ((a0 & 0xf) != 0) {
        raise_exception(env, EXCP0D_GPF);
    }
    eflags = cpu_cc_compute_all(env, CC_OP);
    d0 = cpu_ldq_data(env, a0);
    d1 = cpu_ldq_data(env, a0 + 8);
    if (d0 == EAX && d1 == EDX) {
        cpu_stq_data(env, a0, EBX);
        cpu_stq_data(env, a0 + 8, ECX);
        eflags |= CC_Z;
    } else {
        /* always do the store */
        cpu_stq_data(env, a0, d0);
        cpu_stq_data(env, a0 + 8, d1);
        EDX = d1;
        EAX = d0;
        eflags &= ~CC_Z;
    }
    CC_SRC = eflags;
}
Exemple #2
0
/* 64-bit FP subtraction RM */
uint32_t HELPER(sdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
{
    float64 v1 = env->fregs[f1].d;
    CPU_DoubleU v2;

    v2.ll = cpu_ldq_data(env, a2);
    env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status);
    return set_cc_nz_f64(v1);
}
Exemple #3
0
/* convert 64-bit float to 128-bit float */
void HELPER(lxdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
{
    CPU_DoubleU v2;
    CPU_QuadU v1;

    v2.ll = cpu_ldq_data(env, a2);
    v1.q = float64_to_float128(v2.d, &env->fpu_status);
    env->fregs[f1].ll = v1.ll.upper;
    env->fregs[f1 + 2].ll = v1.ll.lower;
}
Exemple #4
0
/* 64-bit FP division RM */
void HELPER(ddb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
{
    float64 v1 = env->fregs[f1].d;
    CPU_DoubleU v2;

    v2.ll = cpu_ldq_data(env, a2);
    HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __func__,
               v1, f1, v2.d);
    env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status);
}
Exemple #5
0
/* 64-bit FP compare RM */
uint32_t HELPER(cdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
{
    float64 v1 = env->fregs[f1].d;
    CPU_DoubleU v2;

    v2.ll = cpu_ldq_data(env, a2);
    HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __func__, v1,
               f1, v2.d);
    return set_cc_f64(env, v1, v2.d);
}
Exemple #6
0
/* 64-bit FP multiply and add RM */
void HELPER(madb)(CPUS390XState *env, uint32_t f1, uint64_t a2, uint32_t f3)
{
    CPU_DoubleU v2;

    HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __func__, f1, a2, f3);
    v2.ll = cpu_ldq_data(env, a2);
    env->fregs[f1].d = float64_add(env->fregs[f1].d,
                                   float64_mul(v2.d, env->fregs[f3].d,
                                               &env->fpu_status),
                                   &env->fpu_status);
}
Exemple #7
0
/* 64-bit FP addition RM */
uint32_t HELPER(adb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
{
    float64 v1 = env->fregs[f1].d;
    CPU_DoubleU v2;

    v2.ll = cpu_ldq_data(env, a2);
    HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __func__,
               v1, f1, v2.d);
    env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status);
    return set_cc_nz_f64(v1);
}
Exemple #8
0
/* Set CPU Timer */
void HELPER(spt)(CPUS390XState *env, uint64_t a1)
{
    uint64_t time = cpu_ldq_data(env, a1);

    if (time == -1ULL) {
        return;
    }

    /* nanoseconds */
    time = (time * 125) >> 9;

    qemu_mod_timer(env->cpu_timer, qemu_get_clock_ns(vm_clock) + time);
}
Exemple #9
0
/* Set Clock Comparator */
void HELPER(sckc)(CPUS390XState *env, uint64_t a1)
{
    uint64_t time = cpu_ldq_data(env, a1);

    if (time == -1ULL) {
        return;
    }

    /* difference between now and then */
    time -= clock_value(env);
    /* nanoseconds */
    time = (time * 125) >> 9;

    qemu_mod_timer(env->tod_timer, qemu_get_clock_ns(vm_clock) + time);
}
Exemple #10
0
/* memmove */
void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
{
    int i = 0;
    int x = 0;
    uint32_t l_64 = (l + 1) / 8;

    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
               __func__, l, dest, src);

#ifndef CONFIG_USER_ONLY
    if ((l > 32) &&
            (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK) &&
            (dest & TARGET_PAGE_MASK) == ((dest + l) & TARGET_PAGE_MASK)) {
        if (dest == (src + 1)) {
            mvc_fast_memset(env, l + 1, dest, cpu_ldub_data(env, src));
            return;
        } else if ((src & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
            mvc_fast_memmove(env, l + 1, dest, src);
            return;
        }
    }
#else
    if (dest == (src + 1)) {
        memset(g2h(dest), cpu_ldub_data(env, src), l + 1);
        return;
    } else {
        memmove(g2h(dest), g2h(src), l + 1);
        return;
    }
#endif

    /* handle the parts that fit into 8-byte loads/stores */
    if (dest != (src + 1)) {
        for (i = 0; i < l_64; i++) {
            cpu_stq_data(env, dest + x, cpu_ldq_data(env, src + x));
            x += 8;
        }
    }

    /* slow version crossing pages with byte accesses */
    for (i = x; i <= l; i++) {
        cpu_stb_data(env, dest + i, cpu_ldub_data(env, src + i));
    }
}
void helper_cmpxchg8b(CPUX86State *env, target_ulong a0)
{
    uint64_t d;
    int eflags;

    eflags = cpu_cc_compute_all(env, CC_OP);
    d = cpu_ldq_data(env, a0);
    if (d == (((uint64_t)EDX << 32) | (uint32_t)EAX)) {
        cpu_stq_data(env, a0, ((uint64_t)ECX << 32) | (uint32_t)EBX);
        eflags |= CC_Z;
    } else {
        /* always do the store */
        cpu_stq_data(env, a0, d);
        EDX = (uint32_t)(d >> 32);
        EAX = (uint32_t)d;
        eflags &= ~CC_Z;
    }
    CC_SRC = eflags;
}