s390x/tcg: Implement LOAD COUNT TO BLOCK BOUNDARY
Use a new CC helper to calculate the CC lazily if needed. While the PoP mentions that "A 32-bit unsigned binary integer" is placed into the first operand, there is no word telling that the other 32 bits (high part) are left untouched. Maybe the other 32-bit are unpredictable. So store 64 bit for now. Bit magic courtesy of Richard. Signed-off-by: David Hildenbrand <david@redhat.com> Message-Id: <20190225200318.16102-8-david@redhat.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
This commit is contained in:
parent
86b59624c4
commit
6d9303322e
@ -397,6 +397,11 @@ static uint32_t cc_calc_flogr(uint64_t dst)
|
||||
return dst ? 2 : 0;
|
||||
}
|
||||
|
||||
static uint32_t cc_calc_lcbb(uint64_t dst)
|
||||
{
|
||||
return dst == 16 ? 0 : 3;
|
||||
}
|
||||
|
||||
static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
|
||||
uint64_t src, uint64_t dst, uint64_t vr)
|
||||
{
|
||||
@ -506,6 +511,9 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
|
||||
case CC_OP_FLOGR:
|
||||
r = cc_calc_flogr(dst);
|
||||
break;
|
||||
case CC_OP_LCBB:
|
||||
r = cc_calc_lcbb(dst);
|
||||
break;
|
||||
|
||||
case CC_OP_NZ_F32:
|
||||
r = set_cc_nz_f32(dst);
|
||||
|
@ -417,6 +417,7 @@ const char *cc_name(enum cc_op cc_op)
|
||||
[CC_OP_SLA_32] = "CC_OP_SLA_32",
|
||||
[CC_OP_SLA_64] = "CC_OP_SLA_64",
|
||||
[CC_OP_FLOGR] = "CC_OP_FLOGR",
|
||||
[CC_OP_LCBB] = "CC_OP_LCBB",
|
||||
};
|
||||
|
||||
return cc_names[cc_op];
|
||||
|
@ -479,6 +479,8 @@
|
||||
F(0xb313, LCDBR, RRE, Z, 0, f2, new, f1, negf64, f64, IF_BFP)
|
||||
F(0xb343, LCXBR, RRE, Z, x2h, x2l, new_P, x1, negf128, f128, IF_BFP)
|
||||
F(0xb373, LCDFR, RRE, FPSSH, 0, f2, new, f1, negf64, 0, IF_AFP1 | IF_AFP2)
|
||||
/* LOAD COUNT TO BLOCK BOUNDARY */
|
||||
C(0xe727, LCBB, RXE, V, la2, 0, r1, 0, lcbb, 0)
|
||||
/* LOAD HALFWORD */
|
||||
C(0xb927, LHR, RRE, EI, 0, r2_16s, 0, r1_32, mov2, 0)
|
||||
C(0xb907, LGHR, RRE, EI, 0, r2_16s, 0, r1, mov2, 0)
|
||||
|
@ -236,6 +236,7 @@ enum cc_op {
|
||||
CC_OP_SLA_32, /* Calculate shift left signed (32bit) */
|
||||
CC_OP_SLA_64, /* Calculate shift left signed (64bit) */
|
||||
CC_OP_FLOGR, /* find leftmost one */
|
||||
CC_OP_LCBB, /* load count to block boundary */
|
||||
CC_OP_MAX
|
||||
};
|
||||
|
||||
|
@ -557,6 +557,7 @@ static void gen_op_calc_cc(DisasContext *s)
|
||||
case CC_OP_NZ_F32:
|
||||
case CC_OP_NZ_F64:
|
||||
case CC_OP_FLOGR:
|
||||
case CC_OP_LCBB:
|
||||
/* 1 argument */
|
||||
gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy);
|
||||
break;
|
||||
@ -3142,6 +3143,23 @@ static DisasJumpType op_lzrb(DisasContext *s, DisasOps *o)
|
||||
return DISAS_NEXT;
|
||||
}
|
||||
|
||||
static DisasJumpType op_lcbb(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
const int64_t block_size = (1ull << (get_field(s->fields, m3) + 6));
|
||||
|
||||
if (get_field(s->fields, m3) > 6) {
|
||||
gen_program_exception(s, PGM_SPECIFICATION);
|
||||
return DISAS_NORETURN;
|
||||
}
|
||||
|
||||
tcg_gen_ori_i64(o->addr1, o->addr1, -block_size);
|
||||
tcg_gen_neg_i64(o->addr1, o->addr1);
|
||||
tcg_gen_movi_i64(o->out, 16);
|
||||
tcg_gen_umin_i64(o->out, o->out, o->addr1);
|
||||
gen_op_update1_cc_i64(s, CC_OP_LCBB, o->out);
|
||||
return DISAS_NEXT;
|
||||
}
|
||||
|
||||
static DisasJumpType op_mov2(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
o->out = o->in2;
|
||||
@ -5931,6 +5949,7 @@ enum DisasInsnEnum {
|
||||
#define FAC_ECT S390_FEAT_EXTRACT_CPU_TIME
|
||||
#define FAC_PCI S390_FEAT_ZPCI /* z/PCI facility */
|
||||
#define FAC_AIS S390_FEAT_ADAPTER_INT_SUPPRESSION
|
||||
#define FAC_V S390_FEAT_VECTOR /* vector facility */
|
||||
|
||||
static const DisasInsn insn_info[] = {
|
||||
#include "insn-data.def"
|
||||
|
Loading…
Reference in New Issue
Block a user