aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target/microblaze/insns.decode6
-rw-r--r--target/microblaze/translate.c77
2 files changed, 37 insertions, 46 deletions
diff --git a/target/microblaze/insns.decode b/target/microblaze/insns.decode
index 93bd51c78b..1a2e22e44a 100644
--- a/target/microblaze/insns.decode
+++ b/target/microblaze/insns.decode
@@ -50,6 +50,12 @@ andni 101011 ..... ..... ................ @typeb
cmp 000101 ..... ..... ..... 000 0000 0001 @typea
cmpu 000101 ..... ..... ..... 000 0000 0011 @typea
+mul 010000 ..... ..... ..... 000 0000 0000 @typea
+mulh 010000 ..... ..... ..... 000 0000 0001 @typea
+mulhu 010000 ..... ..... ..... 000 0000 0011 @typea
+mulhsu 010000 ..... ..... ..... 000 0000 0010 @typea
+muli 011000 ..... ..... ................ @typeb
+
or 100000 ..... ..... ..... 000 0000 0000 @typea
ori 101000 ..... ..... ................ @typeb
diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
index a143f17e9d..617e208583 100644
--- a/target/microblaze/translate.c
+++ b/target/microblaze/translate.c
@@ -287,6 +287,10 @@ static bool do_typeb_val(DisasContext *dc, arg_typeb *arg, bool side_effects,
static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \
{ return do_typeb_imm(dc, a, SE, FNI); }
+#define DO_TYPEBI_CFG(NAME, CFG, SE, FNI) \
+ static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \
+ { return dc->cpu->cfg.CFG && do_typeb_imm(dc, a, SE, FNI); }
+
#define DO_TYPEBV(NAME, SE, FN) \
static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \
{ return do_typeb_val(dc, a, SE, FN); }
@@ -364,6 +368,33 @@ static void gen_cmpu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
DO_TYPEA(cmp, false, gen_cmp)
DO_TYPEA(cmpu, false, gen_cmpu)
+static void gen_mulh(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
+{
+ TCGv_i32 tmp = tcg_temp_new_i32();
+ tcg_gen_muls2_i32(tmp, out, ina, inb);
+ tcg_temp_free_i32(tmp);
+}
+
+static void gen_mulhu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
+{
+ TCGv_i32 tmp = tcg_temp_new_i32();
+ tcg_gen_mulu2_i32(tmp, out, ina, inb);
+ tcg_temp_free_i32(tmp);
+}
+
+static void gen_mulhsu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
+{
+ TCGv_i32 tmp = tcg_temp_new_i32();
+ tcg_gen_mulsu2_i32(tmp, out, ina, inb);
+ tcg_temp_free_i32(tmp);
+}
+
+DO_TYPEA_CFG(mul, use_hw_mul, false, tcg_gen_mul_i32)
+DO_TYPEA_CFG(mulh, use_hw_mul >= 2, false, gen_mulh)
+DO_TYPEA_CFG(mulhu, use_hw_mul >= 2, false, gen_mulhu)
+DO_TYPEA_CFG(mulhsu, use_hw_mul >= 2, false, gen_mulhsu)
+DO_TYPEBI_CFG(muli, use_hw_mul, false, tcg_gen_muli_i32)
+
DO_TYPEA(or, false, tcg_gen_or_i32)
DO_TYPEBI(ori, false, tcg_gen_ori_i32)
@@ -652,51 +683,6 @@ static void dec_msr(DisasContext *dc)
}
}
-/* Multiplier unit. */
-static void dec_mul(DisasContext *dc)
-{
- TCGv_i32 tmp;
- unsigned int subcode;
-
- if (trap_illegal(dc, !dc->cpu->cfg.use_hw_mul)) {
- return;
- }
-
- subcode = dc->imm & 3;
-
- if (dc->type_b) {
- tcg_gen_mul_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
- return;
- }
-
- /* mulh, mulhsu and mulhu are not available if C_USE_HW_MUL is < 2. */
- if (subcode >= 1 && subcode <= 3 && dc->cpu->cfg.use_hw_mul < 2) {
- /* nop??? */
- }
-
- tmp = tcg_temp_new_i32();
- switch (subcode) {
- case 0:
- tcg_gen_mul_i32(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
- break;
- case 1:
- tcg_gen_muls2_i32(tmp, cpu_R[dc->rd],
- cpu_R[dc->ra], cpu_R[dc->rb]);
- break;
- case 2:
- tcg_gen_mulsu2_i32(tmp, cpu_R[dc->rd],
- cpu_R[dc->ra], cpu_R[dc->rb]);
- break;
- case 3:
- tcg_gen_mulu2_i32(tmp, cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
- break;
- default:
- cpu_abort(CPU(dc->cpu), "unknown MUL insn %x\n", subcode);
- break;
- }
- tcg_temp_free_i32(tmp);
-}
-
/* Div unit. */
static void dec_div(DisasContext *dc)
{
@@ -1579,7 +1565,6 @@ static struct decoder_info {
{DEC_BCC, dec_bcc},
{DEC_RTS, dec_rts},
{DEC_FPU, dec_fpu},
- {DEC_MUL, dec_mul},
{DEC_DIV, dec_div},
{DEC_MSR, dec_msr},
{DEC_STREAM, dec_stream},