target-s390: Convert FP ADD, COMPARE, LOAD TEST/ROUND/LENGTHENED

Signed-off-by: Richard Henderson <rth@twiddle.net>
master
Richard Henderson 2012-08-23 10:48:20 -07:00
parent 7691c23b1f
commit 587626f8da
6 changed files with 281 additions and 315 deletions

View File

@ -505,18 +505,15 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
r = cc_calc_sla_64(src, dst);
break;
case CC_OP_LTGT_F32:
r = set_cc_f32(env, src, dst);
break;
case CC_OP_LTGT_F64:
r = set_cc_f64(env, src, 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(env, "Unknown CC operation: %s\n", cc_name(cc_op));

View File

@ -471,11 +471,9 @@ enum cc_op {
CC_OP_TM_32, /* test under mask (32bit) */
CC_OP_TM_64, /* test under mask (64bit) */
CC_OP_LTGT_F32, /* FP compare (32bit) */
CC_OP_LTGT_F64, /* FP compare (64bit) */
CC_OP_NZ_F32, /* FP dst != 0 (32bit) */
CC_OP_NZ_F64, /* FP dst != 0 (64bit) */
CC_OP_NZ_F128, /* FP dst != 0 (128bit) */
CC_OP_ICM, /* insert characters under mask */
CC_OP_SLA_32, /* Calculate shift left signed (32bit) */
@ -517,10 +515,9 @@ static const char *cc_names[] = {
[CC_OP_COMP_64] = "CC_OP_COMP_64",
[CC_OP_TM_32] = "CC_OP_TM_32",
[CC_OP_TM_64] = "CC_OP_TM_64",
[CC_OP_LTGT_F32] = "CC_OP_LTGT_F32",
[CC_OP_LTGT_F64] = "CC_OP_LTGT_F64",
[CC_OP_NZ_F32] = "CC_OP_NZ_F32",
[CC_OP_NZ_F64] = "CC_OP_NZ_F64",
[CC_OP_NZ_F128] = "CC_OP_NZ_F128",
[CC_OP_ICM] = "CC_OP_ICM",
[CC_OP_SLA_32] = "CC_OP_SLA_32",
[CC_OP_SLA_64] = "CC_OP_SLA_64",
@ -926,10 +923,9 @@ static inline void cpu_pc_from_tb(CPUS390XState *env, TranslationBlock* tb)
}
/* fpu_helper.c */
uint32_t set_cc_f32(CPUS390XState *env, float32 v1, float32 v2);
uint32_t set_cc_f64(CPUS390XState *env, float64 v1, float64 v2);
uint32_t set_cc_nz_f32(float32 v);
uint32_t set_cc_nz_f64(float64 v);
uint32_t set_cc_nz_f128(float128 v);
/* misc_helper.c */
void program_interrupt(CPUS390XState *env, uint32_t code, int ilen);

View File

@ -32,6 +32,52 @@
#define HELPER_LOG(x...)
#endif
#define RET128(F) (env->retxl = F.low, F.high)
#define convert_bit(mask, from, to) \
(to < from \
? (mask / (from / to)) & to \
: (mask & from) * (to / from))
static void ieee_exception(CPUS390XState *env, uint32_t dxc, uintptr_t retaddr)
{
/* Install the DXC code. */
env->fpc = (env->fpc & ~0xff00) | (dxc << 8);
/* Trap. */
runtime_exception(env, PGM_DATA, retaddr);
}
/* Should be called after any operation that may raise IEEE exceptions. */
static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
{
unsigned s390_exc, qemu_exc;
/* Get the exceptions raised by the current operation. Reset the
fpu_status contents so that the next operation has a clean slate. */
qemu_exc = env->fpu_status.float_exception_flags;
if (qemu_exc == 0) {
return;
}
env->fpu_status.float_exception_flags = 0;
/* Convert softfloat exception bits to s390 exception bits. */
s390_exc = 0;
s390_exc |= convert_bit(qemu_exc, float_flag_invalid, 0x80);
s390_exc |= convert_bit(qemu_exc, float_flag_divbyzero, 0x40);
s390_exc |= convert_bit(qemu_exc, float_flag_overflow, 0x20);
s390_exc |= convert_bit(qemu_exc, float_flag_underflow, 0x10);
s390_exc |= convert_bit(qemu_exc, float_flag_inexact, 0x08);
/* Install the exceptions that we raised. */
env->fpc |= s390_exc << 16;
/* Send signals for enabled exceptions. */
s390_exc &= env->fpc >> 24;
if (s390_exc) {
ieee_exception(env, s390_exc, retaddr);
}
}
static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
{
switch (float_compare) {
@ -48,19 +94,6 @@ static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
}
}
/* condition codes for binary FP ops */
uint32_t set_cc_f32(CPUS390XState *env, float32 v1, float32 v2)
{
return float_comp_to_cc(env, float32_compare_quiet(v1, v2,
&env->fpu_status));
}
uint32_t set_cc_f64(CPUS390XState *env, float64 v1, float64 v2)
{
return float_comp_to_cc(env, float64_compare_quiet(v1, v2,
&env->fpu_status));
}
/* condition codes for unary FP ops */
uint32_t set_cc_nz_f32(float32 v)
{
@ -88,7 +121,7 @@ uint32_t set_cc_nz_f64(float64 v)
}
}
static uint32_t set_cc_nz_f128(float128 v)
uint32_t set_cc_nz_f128(float128 v)
{
if (float128_is_any_nan(v)) {
return 3;
@ -152,27 +185,31 @@ void HELPER(cefbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
env->fregs[f1].l.upper, f1);
}
/* 32-bit FP addition RR */
uint32_t HELPER(aebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
/* 32-bit FP addition */
uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
env->fregs[f1].l.upper = float32_add(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);
float32 ret = float32_add(f1, f2, &env->fpu_status);
handle_exceptions(env, GETPC());
return ret;
}
/* 64-bit FP addition RR */
uint32_t HELPER(adbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
/* 64-bit FP addition */
uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d,
&env->fpu_status);
HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __func__,
env->fregs[f2].d, env->fregs[f1].d, f1);
float64 ret = float64_add(f1, f2, &env->fpu_status);
handle_exceptions(env, GETPC());
return ret;
}
return set_cc_nz_f64(env->fregs[f1].d);
/* 128-bit FP addition */
uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
uint64_t bh, uint64_t bl)
{
float128 ret = float128_add(make_float128(ah, al),
make_float128(bh, bl),
&env->fpu_status);
handle_exceptions(env, GETPC());
return RET128(ret);
}
/* 32-bit FP subtraction RR */
@ -246,50 +283,51 @@ void HELPER(mxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
}
/* convert 32-bit float to 64-bit float */
void HELPER(ldebr)(CPUS390XState *env, uint32_t r1, uint32_t r2)
uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
{
env->fregs[r1].d = float32_to_float64(env->fregs[r2].l.upper,
&env->fpu_status);
float64 ret = float32_to_float64(f2, &env->fpu_status);
handle_exceptions(env, GETPC());
return ret;
}
/* convert 128-bit float to 64-bit float */
void HELPER(ldxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
{
CPU_QuadU x2;
x2.ll.upper = env->fregs[f2].ll;
x2.ll.lower = env->fregs[f2 + 2].ll;
env->fregs[f1].d = float128_to_float64(x2.q, &env->fpu_status);
HELPER_LOG("%s: to 0x%ld\n", __func__, env->fregs[f1].d);
float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
handle_exceptions(env, GETPC());
return ret;
}
/* convert 64-bit float to 128-bit float */
void HELPER(lxdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
{
CPU_QuadU res;
float128 ret = float64_to_float128(f2, &env->fpu_status);
handle_exceptions(env, GETPC());
return RET128(ret);
}
res.q = float64_to_float128(env->fregs[f2].d, &env->fpu_status);
env->fregs[f1].ll = res.ll.upper;
env->fregs[f1 + 2].ll = res.ll.lower;
/* convert 32-bit float to 128-bit float */
uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
{
float128 ret = float32_to_float128(f2, &env->fpu_status);
handle_exceptions(env, GETPC());
return RET128(ret);
}
/* convert 64-bit float to 32-bit float */
void HELPER(ledbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
{
float64 d2 = env->fregs[f2].d;
env->fregs[f1].l.upper = float64_to_float32(d2, &env->fpu_status);
float32 ret = float64_to_float32(f2, &env->fpu_status);
handle_exceptions(env, GETPC());
return ret;
}
/* convert 128-bit float to 32-bit float */
void HELPER(lexbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
{
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);
float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
handle_exceptions(env, GETPC());
return ret;
}
/* absolute value of 32-bit float */
@ -328,32 +366,6 @@ uint32_t HELPER(lpxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
return set_cc_nz_f128(v1.q);
}
/* load and test 64-bit float */
uint32_t HELPER(ltdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
{
env->fregs[f1].d = env->fregs[f2].d;
return set_cc_nz_f64(env->fregs[f1].d);
}
/* load and test 32-bit float */
uint32_t HELPER(ltebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
{
env->fregs[f1].l.upper = env->fregs[f2].l.upper;
return set_cc_nz_f32(env->fregs[f1].l.upper);
}
/* load and test 128-bit float */
uint32_t HELPER(ltxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
{
CPU_QuadU x;
x.ll.upper = env->fregs[f2].ll;
x.ll.lower = env->fregs[f2 + 2].ll;
env->fregs[f1].ll = x.ll.upper;
env->fregs[f1 + 2].ll = x.ll.lower;
return set_cc_nz_f128(x.q);
}
/* load complement of 32-bit float */
uint32_t HELPER(lcebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
{
@ -383,18 +395,6 @@ uint32_t HELPER(lcxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
return set_cc_nz_f128(x1.q);
}
/* 32-bit FP addition RM */
void HELPER(aeb)(CPUS390XState *env, uint32_t f1, uint32_t val)
{
float32 v1 = env->fregs[f1].l.upper;
CPU_FloatU v2;
v2.l = val;
HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __func__,
v1, f1, v2.f);
env->fregs[f1].l.upper = float32_add(v1, v2.f, &env->fpu_status);
}
/* 32-bit FP division RM */
void HELPER(deb)(CPUS390XState *env, uint32_t f1, uint32_t val)
{
@ -419,66 +419,31 @@ void HELPER(meeb)(CPUS390XState *env, uint32_t f1, uint32_t val)
env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status);
}
/* 32-bit FP compare RR */
uint32_t HELPER(cebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
/* 32-bit FP compare */
uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_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);
int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
handle_exceptions(env, GETPC());
return float_comp_to_cc(env, cmp);
}
/* 64-bit FP compare RR */
uint32_t HELPER(cdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
/* 64-bit FP compare */
uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_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);
int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
handle_exceptions(env, GETPC());
return float_comp_to_cc(env, cmp);
}
/* 128-bit FP compare RR */
uint32_t HELPER(cxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
/* 128-bit FP compare */
uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
uint64_t bh, uint64_t bl)
{
CPU_QuadU v1;
CPU_QuadU v2;
v1.ll.upper = env->fregs[f1].ll;
v1.ll.lower = env->fregs[f1 + 2].ll;
v2.ll.upper = env->fregs[f2].ll;
v2.ll.lower = env->fregs[f2 + 2].ll;
return float_comp_to_cc(env, float128_compare_quiet(v1.q, v2.q,
&env->fpu_status));
}
/* 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);
}
/* 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);
int cmp = float128_compare_quiet(make_float128(ah, al),
make_float128(bh, bl),
&env->fpu_status);
handle_exceptions(env, GETPC());
return float_comp_to_cc(env, cmp);
}
/* 32-bit FP subtraction RM */
@ -672,23 +637,6 @@ uint32_t HELPER(sxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
return set_cc_nz_f128(res.q);
}
/* 128-bit FP addition RR */
uint32_t HELPER(axbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
{
CPU_QuadU v1;
CPU_QuadU v2;
CPU_QuadU res;
v1.ll.upper = env->fregs[f1].ll;
v1.ll.lower = env->fregs[f1 + 2].ll;
v2.ll.upper = env->fregs[f2].ll;
v2.ll.lower = env->fregs[f2 + 2].ll;
res.q = float128_add(v1.q, v2.q, &env->fpu_status);
env->fregs[f1].ll = res.ll.upper;
env->fregs[f1 + 2].ll = res.ll.lower;
return set_cc_nz_f128(res.q);
}
/* 32-bit FP multiplication RR */
void HELPER(meebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
{
@ -747,28 +695,6 @@ void HELPER(maebr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
&env->fpu_status);
}
/* convert 32-bit float to 64-bit float */
void HELPER(ldeb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
{
uint32_t v2;
v2 = cpu_ldl_data(env, a2);
env->fregs[f1].d = float32_to_float64(v2,
&env->fpu_status);
}
/* 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;
}
/* test data class 32-bit */
uint32_t HELPER(tceb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
{

View File

@ -36,40 +36,36 @@ DEF_HELPER_3(cxfbr, void, env, i32, s32)
DEF_HELPER_3(cegbr, void, env, i32, s64)
DEF_HELPER_3(cdgbr, void, env, i32, s64)
DEF_HELPER_3(cxgbr, void, env, i32, s64)
DEF_HELPER_3(adbr, i32, env, i32, i32)
DEF_HELPER_3(aebr, i32, env, i32, i32)
DEF_HELPER_3(aeb, i64, env, i64, i64)
DEF_HELPER_3(adb, i64, env, i64, i64)
DEF_HELPER_5(axb, i64, env, i64, i64, i64, i64)
DEF_HELPER_3(sebr, i32, env, i32, i32)
DEF_HELPER_3(sdbr, i32, env, i32, i32)
DEF_HELPER_3(debr, void, env, i32, i32)
DEF_HELPER_3(dxbr, void, env, i32, i32)
DEF_HELPER_3(mdbr, void, env, i32, i32)
DEF_HELPER_3(mxbr, void, env, i32, i32)
DEF_HELPER_3(ldebr, void, env, i32, i32)
DEF_HELPER_3(ldxbr, void, env, i32, i32)
DEF_HELPER_3(lxdbr, void, env, i32, i32)
DEF_HELPER_3(ledbr, void, env, i32, i32)
DEF_HELPER_3(lexbr, void, env, i32, i32)
DEF_HELPER_2(ldeb, i64, env, i64)
DEF_HELPER_3(ldxb, i64, env, i64, i64)
DEF_HELPER_2(lxdb, i64, env, i64)
DEF_HELPER_2(lxeb, i64, env, i64)
DEF_HELPER_2(ledb, i64, env, i64)
DEF_HELPER_3(lexb, i64, env, i64, i64)
DEF_HELPER_3(lpebr, i32, env, i32, i32)
DEF_HELPER_3(lpdbr, i32, env, i32, i32)
DEF_HELPER_3(lpxbr, i32, env, i32, i32)
DEF_HELPER_3(ltebr, i32, env, i32, i32)
DEF_HELPER_3(ltdbr, i32, env, i32, i32)
DEF_HELPER_3(ltxbr, i32, env, i32, i32)
DEF_HELPER_3(lcebr, i32, env, i32, i32)
DEF_HELPER_3(lcdbr, i32, env, i32, i32)
DEF_HELPER_3(lcxbr, i32, env, i32, i32)
DEF_HELPER_3(aeb, void, env, i32, i32)
DEF_HELPER_3(deb, void, env, i32, i32)
DEF_HELPER_3(meeb, void, env, i32, i32)
DEF_HELPER_3(cdb, i32, env, i32, i64)
DEF_HELPER_3(adb, i32, env, i32, i64)
DEF_HELPER_3(seb, void, env, i32, i32)
DEF_HELPER_3(sdb, i32, env, i32, i64)
DEF_HELPER_3(mdb, void, env, i32, i64)
DEF_HELPER_3(ddb, void, env, i32, i64)
DEF_HELPER_FLAGS_3(cebr, TCG_CALL_NO_SE, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(cdbr, TCG_CALL_NO_SE, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(cxbr, TCG_CALL_NO_SE, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(ceb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
DEF_HELPER_FLAGS_3(cdb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
DEF_HELPER_FLAGS_5(cxb, TCG_CALL_NO_WG_SE, i32, env, i64, i64, i64, i64)
DEF_HELPER_4(cgebr, i32, env, i32, i32, i32)
DEF_HELPER_4(cgdbr, i32, env, i32, i32, i32)
DEF_HELPER_4(cgxbr, i32, env, i32, i32, i32)
@ -79,7 +75,6 @@ DEF_HELPER_2(lzxr, void, env, i32)
DEF_HELPER_4(cfebr, i32, env, i32, i32, i32)
DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32)
DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32)
DEF_HELPER_3(axbr, i32, env, i32, i32)
DEF_HELPER_3(sxbr, i32, env, i32, i32)
DEF_HELPER_3(meebr, void, env, i32, i32)
DEF_HELPER_3(ddbr, void, env, i32, i32)
@ -87,11 +82,9 @@ DEF_HELPER_4(madb, void, env, i32, i64, i32)
DEF_HELPER_4(maebr, void, env, i32, i32, i32)
DEF_HELPER_4(madbr, void, env, i32, i32, i32)
DEF_HELPER_4(msdbr, void, env, i32, i32, i32)
DEF_HELPER_3(ldeb, void, env, i32, i64)
DEF_HELPER_3(lxdb, void, env, i32, i64)
DEF_HELPER_FLAGS_3(tceb, TCG_CALL_NO_SE, i32, env, i32, i64)
DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_NO_SE, i32, env, i32, i64)
DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_NO_SE, i32, env, i32, i64)
DEF_HELPER_FLAGS_3(tceb, TCG_CALL_NO_WG_SE, i32, env, i32, i64)
DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_NO_WG_SE, i32, env, i32, i64)
DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_NO_WG_SE, i32, env, i32, i64)
DEF_HELPER_3(flogr, i32, env, i32, i64)
DEF_HELPER_3(sqdbr, void, env, i32, i32)
DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32)

View File

@ -8,6 +8,11 @@
C(0xb9e8, AGRK, RRF_a, DO, r2, r3, r1, 0, add, adds64)
C(0xe308, AG, RXY_a, Z, r1, m2_64, r1, 0, add, adds64)
C(0xe318, AGF, RXY_a, Z, r1, m2_32s, r1, 0, add, adds64)
C(0xb30a, AEBR, RRE, Z, e1, e2, new, e1, aeb, f32)
C(0xb31a, ADBR, RRE, Z, f1_o, f2_o, f1, 0, adb, f64)
C(0xb34a, AXBR, RRE, Z, 0, x2_o, x1, 0, axb, f128)
C(0xed0a, AEB, RXE, Z, e1, m2_32u, new, e1, aeb, f32)
C(0xed1a, ADB, RXE, Z, f1_o, m2_64, f1, 0, adb, f64)
/* ADD IMMEDIATE */
C(0xc209, AFI, RIL_a, EI, r1, i2, new, r1_32, add, adds32)
C(0xeb6a, ASI, SIY, GIE, m1_32s, i2, new, m1_32, add, adds32)
@ -94,6 +99,11 @@
C(0xb930, CGFR, RRE, Z, r1_o, r2_32s, 0, 0, 0, cmps64)
C(0xe320, CG, RXY_a, Z, r1_o, m2_64, 0, 0, 0, cmps64)
C(0xe330, CGF, RXY_a, Z, r1_o, m2_32s, 0, 0, 0, cmps64)
C(0xb309, CEBR, RRE, Z, e1, e2, 0, 0, ceb, 0)
C(0xb319, CDBR, RRE, Z, f1_o, f2_o, 0, 0, cdb, 0)
C(0xb349, CXBR, RRE, Z, x1_o, x2_o, 0, 0, cxb, 0)
C(0xed09, CEB, RXE, Z, e1, m2_32u, 0, 0, ceb, 0)
C(0xed19, CDB, RXE, Z, f1_o, m2_64, 0, 0, cdb, 0)
/* COMPARE IMMEDIATE */
C(0xc20d, CFI, RIL_a, EI, r1, i2, 0, 0, 0, cmps32)
C(0xc20c, CGFI, RIL_a, EI, r1, i2, 0, 0, 0, cmps64)
@ -239,6 +249,9 @@
C(0xe312, LT, RXY_a, EI, 0, a2, new, r1_32, ld32s, s64)
C(0xe302, LTG, RXY_a, EI, 0, a2, r1, 0, ld64, s64)
C(0xe332, LTGF, RXY_a, GIE, 0, a2, r1, 0, ld32s, s64)
C(0xb302, LTEBR, RRE, Z, 0, e2, 0, cond_e1e2, mov2, f32)
C(0xb312, LTDBR, RRE, Z, 0, f2_o, 0, f1, mov2, f64)
C(0xb342, LTXBR, RRE, Z, 0, x2_o, 0, x1, movx, f128)
/* LOAD BYTE */
C(0xb926, LBR, RRE, EI, 0, r2_8s, 0, r1_32, mov2, 0)
C(0xb906, LGBR, RRE, EI, 0, r2_8s, 0, r1, mov2, 0)
@ -303,6 +316,18 @@
C(0xe31e, LRV, RXY_a, Z, 0, m2_32u, new, r1_32, rev32, 0)
C(0xe30f, LRVG, RXY_a, Z, 0, m2_64, r1, 0, rev64, 0)
/* LOAD LENGTHENED */
C(0xb304, LDEBR, RRE, Z, 0, e2, f1, 0, ldeb, 0)
C(0xb305, LXDBR, RRE, Z, 0, f2_o, x1, 0, lxdb, 0)
C(0xb306, LXEBR, RRE, Z, 0, e2, x1, 0, lxeb, 0)
C(0xed04, LDEB, RXE, Z, 0, m2_32u, f1, 0, ldeb, 0)
C(0xed05, LXDB, RXE, Z, 0, m2_64, x1, 0, lxdb, 0)
C(0xed06, LXEB, RXE, Z, 0, m2_32u, x1, 0, lxeb, 0)
/* LOAD ROUNDED */
C(0xb344, LEDBR, RRE, Z, 0, f2_o, new, e1, ledb, 0)
C(0xb345, LDXBR, RRE, Z, 0, x2_o, f1, 0, ldxb, 0)
C(0xb346, LEXBR, RRE, Z, 0, x2_o, new, e1, lexb, 0)
/* LOAD MULTIPLE */
C(0x9800, LM, RS_a, Z, 0, a2, 0, 0, lm32, 0)
C(0xeb98, LMY, RSY_a, LD, 0, a2, 0, 0, lm32, 0)

View File

@ -556,14 +556,6 @@ static inline void set_cc_s64(DisasContext *s, TCGv_i64 val)
gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
}
static void set_cc_cmp_f32_i64(DisasContext *s, TCGv_i32 v1, TCGv_i64 v2)
{
tcg_gen_extu_i32_i64(cc_src, v1);
tcg_gen_mov_i64(cc_dst, v2);
tcg_gen_discard_i64(cc_vr);
s->cc_op = CC_OP_LTGT_F32;
}
static void gen_set_cc_nz_f32(DisasContext *s, TCGv_i32 v1)
{
gen_op_update1_cc_i32(s, CC_OP_NZ_F32, v1);
@ -628,10 +620,9 @@ static void gen_op_calc_cc(DisasContext *s)
case CC_OP_LTUGTU_64:
case CC_OP_TM_32:
case CC_OP_TM_64:
case CC_OP_LTGT_F32:
case CC_OP_LTGT_F64:
case CC_OP_SLA_32:
case CC_OP_SLA_64:
case CC_OP_NZ_F128:
/* 2 arguments */
gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy);
break;
@ -1009,35 +1000,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
addr = get_address(s, x2, b2, d2);
tmp_r1 = tcg_const_i32(r1);
switch (op) {
case 0x4: /* LDEB R1,D2(X2,B2) [RXE] */
potential_page_fault(s);
gen_helper_ldeb(cpu_env, tmp_r1, addr);
break;
case 0x5: /* LXDB R1,D2(X2,B2) [RXE] */
potential_page_fault(s);
gen_helper_lxdb(cpu_env, tmp_r1, addr);
break;
case 0x9: /* CEB R1,D2(X2,B2) [RXE] */
tmp = tcg_temp_new_i64();
tmp32 = load_freg32(r1);
tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
set_cc_cmp_f32_i64(s, tmp32, tmp);
tcg_temp_free_i64(tmp);
tcg_temp_free_i32(tmp32);
break;
case 0xa: /* AEB R1,D2(X2,B2) [RXE] */
tmp = tcg_temp_new_i64();
tmp32 = tcg_temp_new_i32();
tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
tcg_gen_trunc_i64_i32(tmp32, tmp);
gen_helper_aeb(cpu_env, tmp_r1, tmp32);
tcg_temp_free_i64(tmp);
tcg_temp_free_i32(tmp32);
tmp32 = load_freg32(r1);
gen_set_cc_nz_f32(s, tmp32);
tcg_temp_free_i32(tmp32);
break;
case 0xb: /* SEB R1,D2(X2,B2) [RXE] */
tmp = tcg_temp_new_i64();
tmp32 = tcg_temp_new_i32();
@ -1084,16 +1046,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
tcg_temp_free_i64(tmp);
tcg_temp_free_i32(tmp32);
break;
case 0x19: /* CDB R1,D2(X2,B2) [RXE] */
potential_page_fault(s);
gen_helper_cdb(cc_op, cpu_env, tmp_r1, addr);
set_cc_static(s);
break;
case 0x1a: /* ADB R1,D2(X2,B2) [RXE] */
potential_page_fault(s);
gen_helper_adb(cc_op, cpu_env, tmp_r1, addr);
set_cc_static(s);
break;
case 0x1b: /* SDB R1,D2(X2,B2) [RXE] */
potential_page_fault(s);
gen_helper_sdb(cc_op, cpu_env, tmp_r1, addr);
@ -1524,24 +1476,9 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
case 0x0: /* LPEBR R1,R2 [RRE] */
FP_HELPER_CC(lpebr);
break;
case 0x2: /* LTEBR R1,R2 [RRE] */
FP_HELPER_CC(ltebr);
break;
case 0x3: /* LCEBR R1,R2 [RRE] */
FP_HELPER_CC(lcebr);
break;
case 0x4: /* LDEBR R1,R2 [RRE] */
FP_HELPER(ldebr);
break;
case 0x5: /* LXDBR R1,R2 [RRE] */
FP_HELPER(lxdbr);
break;
case 0x9: /* CEBR R1,R2 [RRE] */
FP_HELPER_CC(cebr);
break;
case 0xa: /* AEBR R1,R2 [RRE] */
FP_HELPER_CC(aebr);
break;
case 0xb: /* SEBR R1,R2 [RRE] */
FP_HELPER_CC(sebr);
break;
@ -1551,9 +1488,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
case 0x10: /* LPDBR R1,R2 [RRE] */
FP_HELPER_CC(lpdbr);
break;
case 0x12: /* LTDBR R1,R2 [RRE] */
FP_HELPER_CC(ltdbr);
break;
case 0x13: /* LCDBR R1,R2 [RRE] */
FP_HELPER_CC(lcdbr);
break;
@ -1563,12 +1497,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
case 0x17: /* MEEBR R1,R2 [RRE] */
FP_HELPER(meebr);
break;
case 0x19: /* CDBR R1,R2 [RRE] */
FP_HELPER_CC(cdbr);
break;
case 0x1a: /* ADBR R1,R2 [RRE] */
FP_HELPER_CC(adbr);
break;
case 0x1b: /* SDBR R1,R2 [RRE] */
FP_HELPER_CC(sdbr);
break;
@ -1605,27 +1533,9 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
case 0x40: /* LPXBR R1,R2 [RRE] */
FP_HELPER_CC(lpxbr);
break;
case 0x42: /* LTXBR R1,R2 [RRE] */
FP_HELPER_CC(ltxbr);
break;
case 0x43: /* LCXBR R1,R2 [RRE] */
FP_HELPER_CC(lcxbr);
break;
case 0x44: /* LEDBR R1,R2 [RRE] */
FP_HELPER(ledbr);
break;
case 0x45: /* LDXBR R1,R2 [RRE] */
FP_HELPER(ldxbr);
break;
case 0x46: /* LEXBR R1,R2 [RRE] */
FP_HELPER(lexbr);
break;
case 0x49: /* CXBR R1,R2 [RRE] */
FP_HELPER_CC(cxbr);
break;
case 0x4a: /* AXBR R1,R2 [RRE] */
FP_HELPER_CC(axbr);
break;
case 0x4b: /* SXBR R1,R2 [RRE] */
FP_HELPER_CC(sxbr);
break;
@ -2260,6 +2170,25 @@ static ExitStatus op_addc(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
static ExitStatus op_aeb(DisasContext *s, DisasOps *o)
{
gen_helper_aeb(o->out, cpu_env, o->in1, o->in2);
return NO_EXIT;
}
static ExitStatus op_adb(DisasContext *s, DisasOps *o)
{
gen_helper_adb(o->out, cpu_env, o->in1, o->in2);
return NO_EXIT;
}
static ExitStatus op_axb(DisasContext *s, DisasOps *o)
{
gen_helper_axb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
return_low128(o->out2);
return NO_EXIT;
}
static ExitStatus op_and(DisasContext *s, DisasOps *o)
{
tcg_gen_and_i64(o->out, o->in1, o->in2);
@ -2354,6 +2283,27 @@ static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
return help_branch(s, &c, is_imm, imm, o->in2);
}
static ExitStatus op_ceb(DisasContext *s, DisasOps *o)
{
gen_helper_ceb(cc_op, cpu_env, o->in1, o->in2);
set_cc_static(s);
return NO_EXIT;
}
static ExitStatus op_cdb(DisasContext *s, DisasOps *o)
{
gen_helper_cdb(cc_op, cpu_env, o->in1, o->in2);
set_cc_static(s);
return NO_EXIT;
}
static ExitStatus op_cxb(DisasContext *s, DisasOps *o)
{
gen_helper_cxb(cc_op, cpu_env, o->out, o->out2, o->in1, o->in2);
set_cc_static(s);
return NO_EXIT;
}
static ExitStatus op_clc(DisasContext *s, DisasOps *o)
{
int l = get_field(s->fields, l1);
@ -2610,6 +2560,44 @@ static ExitStatus op_insi(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
static ExitStatus op_ldeb(DisasContext *s, DisasOps *o)
{
gen_helper_ldeb(o->out, cpu_env, o->in2);
return NO_EXIT;
}
static ExitStatus op_ledb(DisasContext *s, DisasOps *o)
{
gen_helper_ledb(o->out, cpu_env, o->in2);
return NO_EXIT;
}
static ExitStatus op_ldxb(DisasContext *s, DisasOps *o)
{
gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2);
return NO_EXIT;
}
static ExitStatus op_lexb(DisasContext *s, DisasOps *o)
{
gen_helper_lexb(o->out, cpu_env, o->in1, o->in2);
return NO_EXIT;
}
static ExitStatus op_lxdb(DisasContext *s, DisasOps *o)
{
gen_helper_lxdb(o->out, cpu_env, o->in2);
return_low128(o->out2);
return NO_EXIT;
}
static ExitStatus op_lxeb(DisasContext *s, DisasOps *o)
{
gen_helper_lxeb(o->out, cpu_env, o->in2);
return_low128(o->out2);
return NO_EXIT;
}
static ExitStatus op_llgt(DisasContext *s, DisasOps *o)
{
tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff);
@ -3369,6 +3357,21 @@ static void cout_cmpu64(DisasContext *s, DisasOps *o)
gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, o->in1, o->in2);
}
static void cout_f32(DisasContext *s, DisasOps *o)
{
gen_op_update1_cc_i64(s, CC_OP_NZ_F32, o->out);
}
static void cout_f64(DisasContext *s, DisasOps *o)
{
gen_op_update1_cc_i64(s, CC_OP_NZ_F64, o->out);
}
static void cout_f128(DisasContext *s, DisasOps *o)
{
gen_op_update2_cc_i64(s, CC_OP_NZ_F128, o->out, o->out2);
}
static void cout_nabs32(DisasContext *s, DisasOps *o)
{
gen_op_update1_cc_i64(s, CC_OP_NABS_32, o->out);
@ -3482,6 +3485,21 @@ static void prep_r1_P(DisasContext *s, DisasFields *f, DisasOps *o)
o->g_out = o->g_out2 = true;
}
static void prep_f1(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->out = fregs[get_field(f, r1)];
o->g_out = true;
}
static void prep_x1(DisasContext *s, DisasFields *f, DisasOps *o)
{
/* ??? Specification exception: r1 must be < 14. */
int r1 = get_field(f, r1);
o->out = fregs[r1];
o->out2 = fregs[(r1 + 2) & 15];
o->g_out = o->g_out2 = true;
}
/* ====================================================================== */
/* The "Write OUTput" generators. These generally perform some non-trivial
copy of data to TCG globals, or to main memory. The trivial cases are
@ -3539,6 +3557,7 @@ static void wout_f1(DisasContext *s, DisasFields *f, DisasOps *o)
static void wout_x1(DisasContext *s, DisasFields *f, DisasOps *o)
{
/* ??? Specification exception: r1 must be < 14. */
int f1 = get_field(s->fields, r1);
store_freg(f1, o->out);
store_freg((f1 + 2) & 15, o->out2);
@ -3685,6 +3704,15 @@ static void in1_f1_o(DisasContext *s, DisasFields *f, DisasOps *o)
o->g_in1 = true;
}
static void in1_x1_o(DisasContext *s, DisasFields *f, DisasOps *o)
{
/* ??? Specification exception: r1 must be < 14. */
int r1 = get_field(f, r1);
o->out = fregs[r1];
o->out2 = fregs[(r1 + 2) & 15];
o->g_out = o->g_out2 = true;
}
static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
{
o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
@ -3832,9 +3860,10 @@ static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o)
static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
{
int f2 = get_field(f, r2);
o->in1 = fregs[f2];
o->in2 = fregs[(f2 + 2) & 15];
/* ??? Specification exception: r1 must be < 14. */
int r2 = get_field(f, r2);
o->in1 = fregs[r2];
o->in2 = fregs[(r2 + 2) & 15];
o->g_in1 = o->g_in2 = true;
}