Skip to content

Commit

Permalink
s390x/tcg: Implement MULTIPLY SINGLE (MSC, MSGC, MSGRKC, MSRKC)
Browse files Browse the repository at this point in the history
We need new CC handling, determining the CC based on the intermediate
result (64bit for MSC and MSRKC, 128bit for MSGC and MSGRKC).

We want to store out2 ("low") after muls128 to r1, so add
"wout_out2_r1".

Signed-off-by: David Hildenbrand <[email protected]>
Reviewed-by: Richard Henderson <[email protected]>
Message-Id: <[email protected]>
Signed-off-by: Cornelia Huck <[email protected]>
  • Loading branch information
davidhildenbrand authored and cohuck committed Oct 2, 2020
1 parent 9131bd0 commit b1feeb8
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 0 deletions.
32 changes: 32 additions & 0 deletions target/s390x/cc_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,32 @@ static uint32_t cc_calc_vc(uint64_t low, uint64_t high)
}
}

static uint32_t cc_calc_muls_32(int64_t res)
{
const int64_t tmp = res >> 31;

if (!res) {
return 0;
} else if (tmp && tmp != -1) {
return 3;
} else if (res < 0) {
return 1;
}
return 2;
}

static uint64_t cc_calc_muls_64(int64_t res_high, uint64_t res_low)
{
if (!res_high && !res_low) {
return 0;
} else if (res_high + (res_low >> 63) != 0) {
return 3;
} else if (res_high < 0) {
return 1;
}
return 2;
}

static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
uint64_t src, uint64_t dst, uint64_t vr)
{
Expand Down Expand Up @@ -484,6 +510,9 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
case CC_OP_COMP_64:
r = cc_calc_comp_64(dst);
break;
case CC_OP_MULS_64:
r = cc_calc_muls_64(src, dst);
break;

case CC_OP_ADD_32:
r = cc_calc_add_32(src, dst, vr);
Expand Down Expand Up @@ -512,6 +541,9 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
case CC_OP_COMP_32:
r = cc_calc_comp_32(dst);
break;
case CC_OP_MULS_32:
r = cc_calc_muls_32(dst);
break;

case CC_OP_ICM:
r = cc_calc_icm(src, dst);
Expand Down
2 changes: 2 additions & 0 deletions target/s390x/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,8 @@ const char *cc_name(enum cc_op cc_op)
[CC_OP_FLOGR] = "CC_OP_FLOGR",
[CC_OP_LCBB] = "CC_OP_LCBB",
[CC_OP_VC] = "CC_OP_VC",
[CC_OP_MULS_32] = "CC_OP_MULS_32",
[CC_OP_MULS_64] = "CC_OP_MULS_64",
};

return cc_names[cc_op];
Expand Down
4 changes: 4 additions & 0 deletions target/s390x/insn-data.def
Original file line number Diff line number Diff line change
Expand Up @@ -682,11 +682,15 @@
C(0xe386, MLG, RXY_a, Z, r1p1, m2_64, r1_P, 0, mul128, 0)
/* MULTIPLY SINGLE */
C(0xb252, MSR, RRE, Z, r1_o, r2_o, new, r1_32, mul, 0)
C(0xb9fd, MSRKC, RRF_a, MIE2,r3_32s, r2_32s, new, r1_32, mul, muls32)
C(0x7100, MS, RX_a, Z, r1_o, m2_32s, new, r1_32, mul, 0)
C(0xe351, MSY, RXY_a, LD, r1_o, m2_32s, new, r1_32, mul, 0)
C(0xe353, MSC, RXY_a, MIE2,r1_32s, m2_32s, new, r1_32, mul, muls32)
C(0xb90c, MSGR, RRE, Z, r1_o, r2_o, r1, 0, mul, 0)
C(0xb9ed, MSGRKC, RRF_a, MIE2,r3_o, r2_o, new_P, out2_r1, muls128, muls64)
C(0xb91c, MSGFR, RRE, Z, r1_o, r2_32s, r1, 0, mul, 0)
C(0xe30c, MSG, RXY_a, Z, r1_o, m2_64, r1, 0, mul, 0)
C(0xe383, MSGC, RXY_a, MIE2,r1_o, m2_64, new_P, out2_r1, muls128, muls64)
C(0xe31c, MSGF, RXY_a, Z, r1_o, m2_32s, r1, 0, mul, 0)
/* MULTIPLY SINGLE IMMEDIATE */
C(0xc201, MSFI, RIL_a, GIE, r1_o, i2, new, r1_32, mul, 0)
Expand Down
2 changes: 2 additions & 0 deletions target/s390x/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ enum cc_op {
CC_OP_SUBB_64, /* overflow on unsigned sub-borrow (64bit) */
CC_OP_ABS_64, /* sign eval on abs (64bit) */
CC_OP_NABS_64, /* sign eval on nabs (64bit) */
CC_OP_MULS_64, /* overflow on signed multiply (64bit) */

CC_OP_ADD_32, /* overflow on add (32bit) */
CC_OP_ADDU_32, /* overflow on unsigned add (32bit) */
Expand All @@ -184,6 +185,7 @@ enum cc_op {
CC_OP_SUBB_32, /* overflow on unsigned sub-borrow (32bit) */
CC_OP_ABS_32, /* sign eval on abs (64bit) */
CC_OP_NABS_32, /* sign eval on nabs (64bit) */
CC_OP_MULS_32, /* overflow on signed multiply (32bit) */

CC_OP_COMP_32, /* complement */
CC_OP_COMP_64, /* complement */
Expand Down
19 changes: 19 additions & 0 deletions target/s390x/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,7 @@ static void gen_op_calc_cc(DisasContext *s)
case CC_OP_NZ_F64:
case CC_OP_FLOGR:
case CC_OP_LCBB:
case CC_OP_MULS_32:
/* 1 argument */
gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy);
break;
Expand All @@ -660,6 +661,7 @@ static void gen_op_calc_cc(DisasContext *s)
case CC_OP_SLA_64:
case CC_OP_NZ_F128:
case CC_OP_VC:
case CC_OP_MULS_64:
/* 2 arguments */
gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy);
break;
Expand Down Expand Up @@ -5310,6 +5312,17 @@ static void cout_tm64(DisasContext *s, DisasOps *o)
gen_op_update2_cc_i64(s, CC_OP_TM_64, o->in1, o->in2);
}

static void cout_muls32(DisasContext *s, DisasOps *o)
{
gen_op_update1_cc_i64(s, CC_OP_MULS_32, o->out);
}

static void cout_muls64(DisasContext *s, DisasOps *o)
{
/* out contains "high" part, out2 contains "low" part of 128 bit result */
gen_op_update2_cc_i64(s, CC_OP_MULS_64, o->out, o->out2);
}

/* ====================================================================== */
/* The "PREParation" generators. These initialize the DisasOps.OUT fields
with the TCG register to which we will write. Used in combination with
Expand Down Expand Up @@ -5365,6 +5378,12 @@ static void wout_r1(DisasContext *s, DisasOps *o)
}
#define SPEC_wout_r1 0

static void wout_out2_r1(DisasContext *s, DisasOps *o)
{
store_reg(get_field(s, r1), o->out2);
}
#define SPEC_wout_out2_r1 0

static void wout_r1_8(DisasContext *s, DisasOps *o)
{
int r1 = get_field(s, r1);
Expand Down

0 comments on commit b1feeb8

Please sign in to comment.