aboutsummaryrefslogtreecommitdiff
path: root/target-tilegx
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2015-08-22 10:37:38 -0700
committerRichard Henderson <rth@twiddle.net>2015-09-15 07:45:33 -0700
commit4ff49775ecc5e975ca5e4c1b6be25fb611ab38fa (patch)
tree0c315b229acd27b582c947e5e0b3d3d12858e0b2 /target-tilegx
parentf090f9f7ce6bc112710a693e176341b5031eafd8 (diff)
target-tilegx: Handle scalar multiply instructions
Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'target-tilegx')
-rw-r--r--target-tilegx/translate.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c
index 31b6a6cc06..673b4418da 100644
--- a/target-tilegx/translate.c
+++ b/target-tilegx/translate.c
@@ -213,6 +213,38 @@ static void gen_dblaligni(TCGv tdest, TCGv tsrca, TCGv tsrcb, int shr)
tcg_temp_free(t0);
}
+typedef enum {
+ LU, LS, HU, HS
+} MulHalf;
+
+static void gen_ext_half(TCGv d, TCGv s, MulHalf h)
+{
+ switch (h) {
+ case LU:
+ tcg_gen_ext32u_tl(d, s);
+ break;
+ case LS:
+ tcg_gen_ext32s_tl(d, s);
+ break;
+ case HU:
+ tcg_gen_shri_tl(d, s, 32);
+ break;
+ case HS:
+ tcg_gen_sari_tl(d, s, 32);
+ break;
+ }
+}
+
+static void gen_mul_half(TCGv tdest, TCGv tsrca, TCGv tsrcb,
+ MulHalf ha, MulHalf hb)
+{
+ TCGv t = tcg_temp_new();
+ gen_ext_half(t, tsrca, ha);
+ gen_ext_half(tdest, tsrcb, hb);
+ tcg_gen_mul_tl(tdest, tdest, t);
+ tcg_temp_free(t);
+}
+
static TileExcp gen_st_opcode(DisasContext *dc, unsigned dest, unsigned srca,
unsigned srcb, TCGMemOp memop, const char *name)
{
@@ -615,38 +647,118 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext,
case OE_RRR(MNZ, 0, X1):
case OE_RRR(MNZ, 4, Y0):
case OE_RRR(MNZ, 4, Y1):
+ return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
case OE_RRR(MULAX, 0, X0):
case OE_RRR(MULAX, 3, Y0):
+ tcg_gen_mul_tl(tdest, tsrca, tsrcb);
+ tcg_gen_add_tl(tdest, tdest, load_gr(dc, dest));
+ tcg_gen_ext32s_tl(tdest, tdest);
+ mnemonic = "mulax";
+ break;
case OE_RRR(MULA_HS_HS, 0, X0):
case OE_RRR(MULA_HS_HS, 9, Y0):
+ gen_mul_half(tdest, tsrca, tsrcb, HS, HS);
+ tcg_gen_add_tl(tdest, tdest, load_gr(dc, dest));
+ mnemonic = "mula_hs_hs";
+ break;
case OE_RRR(MULA_HS_HU, 0, X0):
+ gen_mul_half(tdest, tsrca, tsrcb, HS, HU);
+ tcg_gen_add_tl(tdest, tdest, load_gr(dc, dest));
+ mnemonic = "mula_hs_hu";
+ break;
case OE_RRR(MULA_HS_LS, 0, X0):
+ gen_mul_half(tdest, tsrca, tsrcb, HS, LS);
+ tcg_gen_add_tl(tdest, tdest, load_gr(dc, dest));
+ mnemonic = "mula_hs_ls";
+ break;
case OE_RRR(MULA_HS_LU, 0, X0):
+ gen_mul_half(tdest, tsrca, tsrcb, HS, LU);
+ tcg_gen_add_tl(tdest, tdest, load_gr(dc, dest));
+ mnemonic = "mula_hs_lu";
+ break;
case OE_RRR(MULA_HU_HU, 0, X0):
case OE_RRR(MULA_HU_HU, 9, Y0):
+ gen_mul_half(tdest, tsrca, tsrcb, HU, HU);
+ tcg_gen_add_tl(tdest, tdest, load_gr(dc, dest));
+ mnemonic = "mula_hu_hu";
+ break;
case OE_RRR(MULA_HU_LS, 0, X0):
+ gen_mul_half(tdest, tsrca, tsrcb, HU, LS);
+ tcg_gen_add_tl(tdest, tdest, load_gr(dc, dest));
+ mnemonic = "mula_hu_ls";
+ break;
case OE_RRR(MULA_HU_LU, 0, X0):
+ gen_mul_half(tdest, tsrca, tsrcb, HU, LU);
+ tcg_gen_add_tl(tdest, tdest, load_gr(dc, dest));
+ mnemonic = "mula_hu_lu";
+ break;
case OE_RRR(MULA_LS_LS, 0, X0):
case OE_RRR(MULA_LS_LS, 9, Y0):
+ gen_mul_half(tdest, tsrca, tsrcb, LS, LS);
+ tcg_gen_add_tl(tdest, tdest, load_gr(dc, dest));
+ mnemonic = "mula_ls_ls";
+ break;
case OE_RRR(MULA_LS_LU, 0, X0):
+ gen_mul_half(tdest, tsrca, tsrcb, LS, LU);
+ tcg_gen_add_tl(tdest, tdest, load_gr(dc, dest));
+ mnemonic = "mula_ls_lu";
+ break;
case OE_RRR(MULA_LU_LU, 0, X0):
case OE_RRR(MULA_LU_LU, 9, Y0):
+ gen_mul_half(tdest, tsrca, tsrcb, LU, LU);
+ tcg_gen_add_tl(tdest, tdest, load_gr(dc, dest));
+ mnemonic = "mula_lu_lu";
+ break;
case OE_RRR(MULX, 0, X0):
case OE_RRR(MULX, 3, Y0):
+ tcg_gen_mul_tl(tdest, tsrca, tsrcb);
+ tcg_gen_ext32s_tl(tdest, tdest);
+ mnemonic = "mulx";
+ break;
case OE_RRR(MUL_HS_HS, 0, X0):
case OE_RRR(MUL_HS_HS, 8, Y0):
+ gen_mul_half(tdest, tsrca, tsrcb, HS, HS);
+ mnemonic = "mul_hs_hs";
+ break;
case OE_RRR(MUL_HS_HU, 0, X0):
+ gen_mul_half(tdest, tsrca, tsrcb, HS, HU);
+ mnemonic = "mul_hs_hu";
+ break;
case OE_RRR(MUL_HS_LS, 0, X0):
+ gen_mul_half(tdest, tsrca, tsrcb, HS, LS);
+ mnemonic = "mul_hs_ls";
+ break;
case OE_RRR(MUL_HS_LU, 0, X0):
+ gen_mul_half(tdest, tsrca, tsrcb, HS, LU);
+ mnemonic = "mul_hs_lu";
+ break;
case OE_RRR(MUL_HU_HU, 0, X0):
case OE_RRR(MUL_HU_HU, 8, Y0):
+ gen_mul_half(tdest, tsrca, tsrcb, HU, HU);
+ mnemonic = "mul_hu_hu";
+ break;
case OE_RRR(MUL_HU_LS, 0, X0):
+ gen_mul_half(tdest, tsrca, tsrcb, HU, LS);
+ mnemonic = "mul_hu_ls";
+ break;
case OE_RRR(MUL_HU_LU, 0, X0):
+ gen_mul_half(tdest, tsrca, tsrcb, HU, LU);
+ mnemonic = "mul_hu_lu";
+ break;
case OE_RRR(MUL_LS_LS, 0, X0):
case OE_RRR(MUL_LS_LS, 8, Y0):
+ gen_mul_half(tdest, tsrca, tsrcb, LS, LS);
+ mnemonic = "mul_ls_ls";
+ break;
case OE_RRR(MUL_LS_LU, 0, X0):
+ gen_mul_half(tdest, tsrca, tsrcb, LS, LU);
+ mnemonic = "mul_ls_lu";
+ break;
case OE_RRR(MUL_LU_LU, 0, X0):
case OE_RRR(MUL_LU_LU, 8, Y0):
+ gen_mul_half(tdest, tsrca, tsrcb, LU, LU);
+ mnemonic = "mul_lu_lu";
+ break;
case OE_RRR(MZ, 0, X0):
case OE_RRR(MZ, 0, X1):
case OE_RRR(MZ, 4, Y0):