mirror of
https://github.com/qemu/qemu.git
synced 2024-11-24 19:33:39 +08:00
target-s390: Convert COMPARE AND SWAP
Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
504488b827
commit
f3de39c485
@ -18,9 +18,9 @@ DEF_HELPER_4(srst, i32, env, i32, i32, i32)
|
||||
DEF_HELPER_4(clst, i32, env, i32, i32, i32)
|
||||
DEF_HELPER_4(mvpg, void, env, i64, i64, i64)
|
||||
DEF_HELPER_4(mvst, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(csg, i32, env, i32, i64, i32)
|
||||
DEF_HELPER_4(csg, i64, env, i64, i64, i64)
|
||||
DEF_HELPER_4(cdsg, i32, env, i32, i64, i32)
|
||||
DEF_HELPER_4(cs, i32, env, i32, i64, i32)
|
||||
DEF_HELPER_4(cs, i64, env, i64, i64, i64)
|
||||
DEF_HELPER_5(ex, i32, env, i32, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_1(abs_i32, TCG_CALL_NO_RWG_SE, i32, s32)
|
||||
DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_NO_RWG_SE, s32, s32)
|
||||
|
@ -137,6 +137,15 @@
|
||||
/* COMPARE LOGICAL LONG EXTENDED */
|
||||
C(0xa900, CLCLE, RS_a, Z, 0, a2, 0, 0, clcle, 0)
|
||||
|
||||
/* COMPARE AND SWAP */
|
||||
C(0xba00, CS, RS_a, Z, r1_o, a2, new, r1_32, cs, 0)
|
||||
C(0xeb14, CSY, RSY_a, LD, r1_o, a2, new, r1_32, cs, 0)
|
||||
C(0xeb30, CSG, RSY_a, Z, r1_o, a2, r1, 0, csg, 0)
|
||||
/* COMPARE DOUBLE AND SWAP */
|
||||
C(0xbb00, CDS, RS_a, Z, r1_D32, a2, new, r1_D32, cds, 0)
|
||||
C(0xeb31, CDSY, RSY_a, LD, r1_D32, a2, new, r1_D32, cds, 0)
|
||||
C(0xeb3e, CDSG, RSY_a, Z, 0, a2, 0, 0, cdsg, 0)
|
||||
|
||||
/* CONVERT TO DECIMAL */
|
||||
C(0x4e00, CVD, RX_a, Z, r1_o, a2, 0, 0, cvd, 0)
|
||||
C(0xe326, CVDY, RXY_a, LD, r1_o, a2, 0, 0, cvd, 0)
|
||||
|
@ -457,20 +457,18 @@ void HELPER(mvst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
|
||||
}
|
||||
|
||||
/* compare and swap 64-bit */
|
||||
uint32_t HELPER(csg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
|
||||
uint64_t HELPER(csg)(CPUS390XState *env, uint64_t r1, uint64_t a2, uint64_t r3)
|
||||
{
|
||||
/* FIXME: locking? */
|
||||
uint32_t cc;
|
||||
uint64_t v2 = cpu_ldq_data(env, a2);
|
||||
|
||||
if (env->regs[r1] == v2) {
|
||||
cc = 0;
|
||||
cpu_stq_data(env, a2, env->regs[r3]);
|
||||
if (r1 == v2) {
|
||||
cpu_stq_data(env, a2, r3);
|
||||
env->cc_op = 0;
|
||||
return r1;
|
||||
} else {
|
||||
cc = 1;
|
||||
env->regs[r1] = v2;
|
||||
env->cc_op = 1;
|
||||
return v2;
|
||||
}
|
||||
return cc;
|
||||
}
|
||||
|
||||
/* compare double and swap 64-bit */
|
||||
@ -497,21 +495,18 @@ uint32_t HELPER(cdsg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
|
||||
}
|
||||
|
||||
/* compare and swap 32-bit */
|
||||
uint32_t HELPER(cs)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
|
||||
uint64_t HELPER(cs)(CPUS390XState *env, uint64_t r1, uint64_t a2, uint64_t r3)
|
||||
{
|
||||
/* FIXME: locking? */
|
||||
uint32_t cc;
|
||||
uint32_t v2 = cpu_ldl_data(env, a2);
|
||||
|
||||
HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __func__, r1, a2, r3);
|
||||
if (((uint32_t)env->regs[r1]) == v2) {
|
||||
cc = 0;
|
||||
cpu_stl_data(env, a2, (uint32_t)env->regs[r3]);
|
||||
if ((uint32_t)r1 == v2) {
|
||||
cpu_stl_data(env, a2, (uint32_t)r3);
|
||||
env->cc_op = 0;
|
||||
return r1;
|
||||
} else {
|
||||
cc = 1;
|
||||
env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | v2;
|
||||
env->cc_op = 1;
|
||||
return v2;
|
||||
}
|
||||
return cc;
|
||||
}
|
||||
|
||||
static uint32_t helper_icm(CPUS390XState *env, uint32_t r1, uint64_t address,
|
||||
|
@ -1146,30 +1146,6 @@ static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
|
||||
tcg_temp_free_i32(tmp32_2);
|
||||
break;
|
||||
#endif
|
||||
case 0x30: /* CSG R1,R3,D2(B2) [RSY] */
|
||||
tmp = get_address(s, 0, b2, d2);
|
||||
tmp32_1 = tcg_const_i32(r1);
|
||||
tmp32_2 = tcg_const_i32(r3);
|
||||
potential_page_fault(s);
|
||||
/* XXX rewrite in tcg */
|
||||
gen_helper_csg(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
|
||||
set_cc_static(s);
|
||||
tcg_temp_free_i64(tmp);
|
||||
tcg_temp_free_i32(tmp32_1);
|
||||
tcg_temp_free_i32(tmp32_2);
|
||||
break;
|
||||
case 0x3e: /* CDSG R1,R3,D2(B2) [RSY] */
|
||||
tmp = get_address(s, 0, b2, d2);
|
||||
tmp32_1 = tcg_const_i32(r1);
|
||||
tmp32_2 = tcg_const_i32(r3);
|
||||
potential_page_fault(s);
|
||||
/* XXX rewrite in tcg */
|
||||
gen_helper_cdsg(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
|
||||
set_cc_static(s);
|
||||
tcg_temp_free_i64(tmp);
|
||||
tcg_temp_free_i32(tmp32_1);
|
||||
tcg_temp_free_i32(tmp32_2);
|
||||
break;
|
||||
default:
|
||||
LOG_DISAS("illegal eb operation 0x%x\n", op);
|
||||
gen_illegal_opcode(s);
|
||||
@ -2021,19 +1997,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
|
||||
op = (insn >> 16) & 0xff;
|
||||
disas_b9(env, s, op, r1, r2);
|
||||
break;
|
||||
case 0xba: /* CS R1,R3,D2(B2) [RS] */
|
||||
insn = ld_code4(env, s->pc);
|
||||
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
||||
tmp = get_address(s, 0, b2, d2);
|
||||
tmp32_1 = tcg_const_i32(r1);
|
||||
tmp32_2 = tcg_const_i32(r3);
|
||||
potential_page_fault(s);
|
||||
gen_helper_cs(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
|
||||
set_cc_static(s);
|
||||
tcg_temp_free_i64(tmp);
|
||||
tcg_temp_free_i32(tmp32_1);
|
||||
tcg_temp_free_i32(tmp32_2);
|
||||
break;
|
||||
case 0xbd: /* CLM R1,M3,D2(B2) [RS] */
|
||||
insn = ld_code4(env, s->pc);
|
||||
decode_rs(s, insn, &r1, &r3, &b2, &d2);
|
||||
@ -2665,6 +2628,47 @@ static ExitStatus op_clcle(DisasContext *s, DisasOps *o)
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_cs(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int r3 = get_field(s->fields, r3);
|
||||
potential_page_fault(s);
|
||||
gen_helper_cs(o->out, cpu_env, o->in1, o->in2, regs[r3]);
|
||||
set_cc_static(s);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_csg(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int r3 = get_field(s->fields, r3);
|
||||
potential_page_fault(s);
|
||||
gen_helper_csg(o->out, cpu_env, o->in1, o->in2, regs[r3]);
|
||||
set_cc_static(s);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_cds(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int r3 = get_field(s->fields, r3);
|
||||
TCGv_i64 in3 = tcg_temp_new_i64();
|
||||
tcg_gen_deposit_i64(in3, regs[r3 + 1], regs[r3], 32, 32);
|
||||
potential_page_fault(s);
|
||||
gen_helper_csg(o->out, cpu_env, o->in1, o->in2, in3);
|
||||
tcg_temp_free_i64(in3);
|
||||
set_cc_static(s);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_cdsg(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
|
||||
TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
|
||||
potential_page_fault(s);
|
||||
/* XXX rewrite in tcg */
|
||||
gen_helper_cdsg(cc_op, cpu_env, r1, o->in2, r3);
|
||||
set_cc_static(s);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_cvd(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
|
Loading…
Reference in New Issue
Block a user