Пример #1
0
/* compare unsigned byte arrays */
uint32_t HELPER(clc)(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2)
{
    int i;
    unsigned char x, y;
    uint32_t cc;

    HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n",
               __func__, l, s1, s2);
    for (i = 0; i <= l; i++) {
        x = cpu_ldub_data(env, s1 + i);
        y = cpu_ldub_data(env, s2 + i);
        HELPER_LOG("%02x (%c)/%02x (%c) ", x, x, y, y);
        if (x < y) {
            cc = 1;
            goto done;
        } else if (x > y) {
            cc = 2;
            goto done;
        }
    }
    cc = 0;
 done:
    HELPER_LOG("\n");
    return cc;
}
Пример #2
0
/* compare logical under mask */
uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask,
                     uint64_t addr)
{
    uint8_t r, d;
    uint32_t cc;

    HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __func__, r1,
               mask, addr);
    cc = 0;
    while (mask) {
        if (mask & 8) {
            d = cpu_ldub_data(env, addr);
            r = (r1 & 0xff000000UL) >> 24;
            HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d,
                       addr);
            if (r < d) {
                cc = 1;
                break;
            } else if (r > d) {
                cc = 2;
                break;
            }
            addr++;
        }
        mask = (mask << 1) & 0xf;
        r1 <<= 8;
    }
Пример #3
0
/* xor on array */
uint32_t HELPER(xc)(CPUS390XState *env, uint32_t l, uint64_t dest,
                    uint64_t src)
{
    int i;
    unsigned char x;
    uint32_t cc = 0;

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

    /* xor with itself is the same as memset(0) */
    if (src == dest) {
        fast_memset(env, dest, 0, l + 1);
        return 0;
    }

    for (i = 0; i <= l; i++) {
        x = cpu_ldub_data(env, dest + i) ^ cpu_ldub_data(env, src + i);
        if (x) {
            cc = 1;
        }
        cpu_stb_data(env, dest + i, x);
    }
    return cc;
}
Пример #4
0
/* xor on array */
uint32_t HELPER(xc)(CPUS390XState *env, uint32_t l, uint64_t dest,
                    uint64_t src)
{
    int i;
    unsigned char x;
    uint32_t cc = 0;

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

#ifndef CONFIG_USER_ONLY
    /* xor with itself is the same as memset(0) */
    if ((l > 32) && (src == dest) &&
            (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK)) {
        mvc_fast_memset(env, l + 1, dest, 0);
        return 0;
    }
#else
    if (src == dest) {
        memset(g2h(dest), 0, l + 1);
        return 0;
    }
#endif

    for (i = 0; i <= l; i++) {
        x = cpu_ldub_data(env, dest + i) ^ cpu_ldub_data(env, src + i);
        if (x) {
            cc = 1;
        }
        cpu_stb_data(env, dest + i, x);
    }
    return cc;
}
Пример #5
0
/* memmove */
void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
{
    int i = 0;

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

    /* mvc with source pointing to the byte after the destination is the
       same as memset with the first source byte */
    if (dest == (src + 1)) {
        fast_memset(env, dest, cpu_ldub_data(env, src), l + 1);
        return;
    }

    /* mvc and memmove do not behave the same when areas overlap! */
    if ((dest < src) || (src + l < dest)) {
        fast_memmove(env, dest, src, l + 1);
        return;
    }

    /* slow version with byte accesses which always work */
    for (i = 0; i <= l; i++) {
        cpu_stb_data(env, dest + i, cpu_ldub_data(env, src + i));
    }
}
Пример #6
0
/* 64-bit FP multiply and subtract RR */
void HELPER(msdbr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
{
    HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3);
    env->fregs[f1].d = float64_sub(float64_mul(env->fregs[f2].d,
                                               env->fregs[f3].d,
                                               &env->fpu_status),
                                   env->fregs[f1].d, &env->fpu_status);
}
Пример #7
0
/* Raise an exception statically from a TB.  */
void HELPER(exception)(CPUS390XState *env, uint32_t excp)
{
    CPUState *cs = CPU(s390_env_get_cpu(env));

    HELPER_LOG("%s: exception %d\n", __func__, excp);
    cs->exception_index = excp;
    cpu_loop_exit(cs);
}
Пример #8
0
/* 64-bit FP subtraction RR */
uint32_t HELPER(sdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
{
    env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d,
                                   &env->fpu_status);
    HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n",
               __func__, env->fregs[f2].d, env->fregs[f1].d, f1);

    return set_cc_nz_f64(env->fregs[f1].d);
}
Пример #9
0
/* 32-bit FP compare RR */
uint32_t HELPER(cebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
{
    float32 v1 = env->fregs[f1].l.upper;
    float32 v2 = env->fregs[f2].l.upper;

    HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __func__,
               v1, f1, v2);
    return set_cc_f32(env, v1, v2);
}
Пример #10
0
/* 64-bit FP compare RR */
uint32_t HELPER(cdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
{
    float64 v1 = env->fregs[f1].d;
    float64 v2 = env->fregs[f2].d;

    HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __func__,
               v1, f1, v2);
    return set_cc_f64(env, v1, v2);
}
Пример #11
0
/* convert 128-bit float to 32-bit float */
void HELPER(lexbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
{
    CPU_QuadU x2;

    x2.ll.upper = env->fregs[f2].ll;
    x2.ll.lower = env->fregs[f2 + 2].ll;
    env->fregs[f1].l.upper = float128_to_float32(x2.q, &env->fpu_status);
    HELPER_LOG("%s: to 0x%d\n", __func__, env->fregs[f1].l.upper);
}
Пример #12
0
/* convert 64-bit int to 128-bit float */
void HELPER(cxgbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
{
    CPU_QuadU x1;

    x1.q = int64_to_float128(v2, &env->fpu_status);
    HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __func__, v2,
               x1.ll.upper, x1.ll.lower);
    env->fregs[f1].ll = x1.ll.upper;
    env->fregs[f1 + 2].ll = x1.ll.lower;
}
Пример #13
0
/* Set Prefix */
void HELPER(spx)(CPUS390XState *env, uint64_t a1)
{
    CPUState *cs = CPU(s390_env_get_cpu(env));
    uint32_t prefix = a1 & 0x7fffe000;

    env->psa = prefix;
    HELPER_LOG("prefix: %#x\n", prefix);
    tlb_flush_page(cs, 0);
    tlb_flush_page(cs, TARGET_PAGE_SIZE);
}
Пример #14
0
/* 32-bit FP multiplication RM */
void HELPER(meeb)(CPUS390XState *env, uint32_t f1, uint32_t val)
{
    float32 v1 = env->fregs[f1].l.upper;
    CPU_FloatU v2;

    v2.l = val;
    HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __func__,
               v1, f1, v2.f);
    env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status);
}
Пример #15
0
/* 32-bit FP subtraction RR */
uint32_t HELPER(sebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
{
    env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper,
                                         env->fregs[f2].l.upper,
                                         &env->fpu_status);
    HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__,
               env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);

    return set_cc_nz_f32(env->fregs[f1].l.upper);
}
Пример #16
0
/* absolute value 64-bit */
uint64_t HELPER(abs_i64)(int64_t val)
{
    HELPER_LOG("%s: val 0x%" PRIx64 "\n", __func__, val);

    if (val < 0) {
        return -val;
    } else {
        return val;
    }
}
Пример #17
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);
}
Пример #18
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);
}
Пример #19
0
/* 32-bit FP division RM */
void HELPER(deb)(CPUS390XState *env, uint32_t f1, uint32_t val)
{
    float32 v1 = env->fregs[f1].l.upper;
    CPU_FloatU v2;

    v2.l = val;
    HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __func__,
               v1, f1, v2.f);
    env->fregs[f1].l.upper = float32_div(v1, v2.f, &env->fpu_status);
}
Пример #20
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);
}
Пример #21
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);
}
Пример #22
0
/* or on array */
uint32_t HELPER(oc)(CPUS390XState *env, uint32_t l, uint64_t dest,
                    uint64_t src)
{
    int i;
    unsigned char x;
    uint32_t cc = 0;

    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
               __func__, l, dest, src);
    for (i = 0; i <= l; i++) {
        x = cpu_ldub_data(env, dest + i) | cpu_ldub_data(env, src + i);
        if (x) {
            cc = 1;
        }
        cpu_stb_data(env, dest + i, x);
    }
    return cc;
}
Пример #23
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));
    }
}
Пример #24
0
/* test data class 64-bit */
uint32_t HELPER(tcdb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
{
    float64 v1 = env->fregs[f1].d;
    int neg = float64_is_neg(v1);
    uint32_t cc = 0;

    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, v1, m2, neg);
    if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
        (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
        (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
        (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
        cc = 1;
    } else if (m2 & (1 << (9-neg))) {
        /* assume normalized number */
        cc = 1;
    }
    /* FIXME: denormalized? */
    return cc;
}
Пример #25
0
uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1,
                      uint64_t cpu_addr)
{
    int cc = 0;

    HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n",
               __func__, order_code, r1, cpu_addr);

    /* Remember: Use "R1 or R1 + 1, whichever is the odd-numbered register"
       as parameter (input). Status (output) is always R1. */

    switch (order_code) {
    case SIGP_SET_ARCH:
        /* switch arch */
        break;
    case SIGP_SENSE:
        /* enumerate CPU status */
        if (cpu_addr) {
            /* XXX implement when SMP comes */
            return 3;
        }
        env->regs[r1] &= 0xffffffff00000000ULL;
        cc = 1;
        break;
#if !defined(CONFIG_USER_ONLY)
    case SIGP_RESTART:
        qemu_system_reset_request();
        cpu_loop_exit(env);
        break;
    case SIGP_STOP:
        qemu_system_shutdown_request();
        cpu_loop_exit(env);
        break;
#endif
    default:
        /* unknown sigp */
        fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code);
        cc = 3;
    }

    return cc;
}
Пример #26
0
void HELPER(sacf)(CPUS390XState *env, uint64_t a1)
{
    HELPER_LOG("%s: %16" PRIx64 "\n", __func__, a1);

    switch (a1 & 0xf00) {
    case 0x000:
        env->psw.mask &= ~PSW_MASK_ASC;
        env->psw.mask |= PSW_ASC_PRIMARY;
        break;
    case 0x100:
        env->psw.mask &= ~PSW_MASK_ASC;
        env->psw.mask |= PSW_ASC_SECONDARY;
        break;
    case 0x300:
        env->psw.mask &= ~PSW_MASK_ASC;
        env->psw.mask |= PSW_ASC_HOME;
        break;
    default:
        qemu_log("unknown sacf mode: %" PRIx64 "\n", a1);
        program_interrupt(env, PGM_SPECIFICATION, 2);
        break;
    }
}
Пример #27
0
/* convert 64-bit int to 64-bit float */
void HELPER(cdgbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
{
    HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1);
    env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status);
}
Пример #28
0
/* convert 32-bit int to 32-bit float */
void HELPER(cefbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
{
    env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status);
    HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __func__, v2,
               env->fregs[f1].l.upper, f1);
}
Пример #29
0
/* raise an exception */
void HELPER(exception)(CPUS390XState *env, uint32_t excp)
{
    HELPER_LOG("%s: exception %d\n", __func__, excp);
    env->exception_index = excp;
    cpu_loop_exit(env);
}
Пример #30
0
static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
                                  uint64_t src, uint64_t dst, uint64_t vr)
{
    S390CPU *cpu = s390_env_get_cpu(env);
    uint32_t r = 0;

    switch (cc_op) {
    case CC_OP_CONST0:
    case CC_OP_CONST1:
    case CC_OP_CONST2:
    case CC_OP_CONST3:
        /* cc_op value _is_ cc */
        r = cc_op;
        break;
    case CC_OP_LTGT0_32:
        r = cc_calc_ltgt0_32(dst);
        break;
    case CC_OP_LTGT0_64:
        r =  cc_calc_ltgt0_64(dst);
        break;
    case CC_OP_LTGT_32:
        r =  cc_calc_ltgt_32(src, dst);
        break;
    case CC_OP_LTGT_64:
        r =  cc_calc_ltgt_64(src, dst);
        break;
    case CC_OP_LTUGTU_32:
        r =  cc_calc_ltugtu_32(src, dst);
        break;
    case CC_OP_LTUGTU_64:
        r =  cc_calc_ltugtu_64(src, dst);
        break;
    case CC_OP_TM_32:
        r =  cc_calc_tm_32(src, dst);
        break;
    case CC_OP_TM_64:
        r =  cc_calc_tm_64(src, dst);
        break;
    case CC_OP_NZ:
        r =  cc_calc_nz(dst);
        break;
    case CC_OP_ADD_64:
        r =  cc_calc_add_64(src, dst, vr);
        break;
    case CC_OP_ADDU_64:
        r =  cc_calc_addu_64(src, dst, vr);
        break;
    case CC_OP_ADDC_64:
        r =  cc_calc_addc_64(src, dst, vr);
        break;
    case CC_OP_SUB_64:
        r =  cc_calc_sub_64(src, dst, vr);
        break;
    case CC_OP_SUBU_64:
        r =  cc_calc_subu_64(src, dst, vr);
        break;
    case CC_OP_SUBB_64:
        r =  cc_calc_subb_64(src, dst, vr);
        break;
    case CC_OP_ABS_64:
        r =  cc_calc_abs_64(dst);
        break;
    case CC_OP_NABS_64:
        r =  cc_calc_nabs_64(dst);
        break;
    case CC_OP_COMP_64:
        r =  cc_calc_comp_64(dst);
        break;

    case CC_OP_ADD_32:
        r =  cc_calc_add_32(src, dst, vr);
        break;
    case CC_OP_ADDU_32:
        r =  cc_calc_addu_32(src, dst, vr);
        break;
    case CC_OP_ADDC_32:
        r =  cc_calc_addc_32(src, dst, vr);
        break;
    case CC_OP_SUB_32:
        r =  cc_calc_sub_32(src, dst, vr);
        break;
    case CC_OP_SUBU_32:
        r =  cc_calc_subu_32(src, dst, vr);
        break;
    case CC_OP_SUBB_32:
        r =  cc_calc_subb_32(src, dst, vr);
        break;
    case CC_OP_ABS_32:
        r =  cc_calc_abs_32(dst);
        break;
    case CC_OP_NABS_32:
        r =  cc_calc_nabs_32(dst);
        break;
    case CC_OP_COMP_32:
        r =  cc_calc_comp_32(dst);
        break;

    case CC_OP_ICM:
        r =  cc_calc_icm(src, dst);
        break;
    case CC_OP_SLA_32:
        r =  cc_calc_sla_32(src, dst);
        break;
    case CC_OP_SLA_64:
        r =  cc_calc_sla_64(src, dst);
        break;
    case CC_OP_FLOGR:
        r = cc_calc_flogr(dst);
        break;

    case CC_OP_NZ_F32:
        r = set_cc_nz_f32(dst);
        break;
    case CC_OP_NZ_F64:
        r = set_cc_nz_f64(dst);
        break;
    case CC_OP_NZ_F128:
        r = set_cc_nz_f128(make_float128(src, dst));
        break;

    default:
        cpu_abort(CPU(cpu), "Unknown CC operation: %s\n", cc_name(cc_op));
    }

    HELPER_LOG("%s: %15s 0x%016lx 0x%016lx 0x%016lx = %d\n", __func__,
               cc_name(cc_op), src, dst, vr, r);
    return r;
}