diff options
author | Richard Henderson <rth@twiddle.net> | 2015-08-22 10:37:38 -0700 |
---|---|---|
committer | Richard Henderson <rth@twiddle.net> | 2015-09-15 07:45:33 -0700 |
commit | 4ff49775ecc5e975ca5e4c1b6be25fb611ab38fa (patch) | |
tree | 0c315b229acd27b582c947e5e0b3d3d12858e0b2 /target-tilegx/translate.c | |
parent | f090f9f7ce6bc112710a693e176341b5031eafd8 (diff) | |
download | qemu-4ff49775ecc5e975ca5e4c1b6be25fb611ab38fa.zip |
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/translate.c')
-rw-r--r-- | target-tilegx/translate.c | 112 |
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): |