aboutsummaryrefslogtreecommitdiff
path: root/target-tilegx
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2015-08-21 14:06:57 -0700
committerRichard Henderson <rth@twiddle.net>2015-09-15 07:45:33 -0700
commitc06b1817297b4486c372950b4f65d34417aa01d0 (patch)
treea1b20eb0ab6ddb97313fb3a82eb8b1cd5f71c2ac /target-tilegx
parentd5dbd6eb388a936bb4ea027c48f8f960ae3977c9 (diff)
target-tilegx: Handle bitfield 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.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c
index 168b4da3c6..ba56a2ebcc 100644
--- a/target-tilegx/translate.c
+++ b/target-tilegx/translate.c
@@ -1125,13 +1125,87 @@ static TileExcp gen_bf_opcode_x0(DisasContext *dc, unsigned ext,
unsigned dest, unsigned srca,
unsigned bfs, unsigned bfe)
{
+ TCGv tdest = dest_gr(dc, dest);
+ TCGv tsrca = load_gr(dc, srca);
+ TCGv tsrcd;
+ int len;
const char *mnemonic;
+ /* The bitfield is either between E and S inclusive,
+ or up from S and down from E inclusive. */
+ if (bfs <= bfe) {
+ len = bfe - bfs + 1;
+ } else {
+ len = (64 - bfs) + (bfe + 1);
+ }
+
switch (ext) {
case BFEXTU_BF_OPCODE_X0:
+ if (bfs == 0 && bfe == 7) {
+ tcg_gen_ext8u_tl(tdest, tsrca);
+ } else if (bfs == 0 && bfe == 15) {
+ tcg_gen_ext16u_tl(tdest, tsrca);
+ } else if (bfs == 0 && bfe == 31) {
+ tcg_gen_ext32u_tl(tdest, tsrca);
+ } else {
+ int rol = 63 - bfe;
+ if (bfs <= bfe) {
+ tcg_gen_shli_tl(tdest, tsrca, rol);
+ } else {
+ tcg_gen_rotli_tl(tdest, tsrca, rol);
+ }
+ tcg_gen_shri_tl(tdest, tdest, (bfs + rol) & 63);
+ }
+ mnemonic = "bfextu";
+ break;
+
case BFEXTS_BF_OPCODE_X0:
+ if (bfs == 0 && bfe == 7) {
+ tcg_gen_ext8s_tl(tdest, tsrca);
+ } else if (bfs == 0 && bfe == 15) {
+ tcg_gen_ext16s_tl(tdest, tsrca);
+ } else if (bfs == 0 && bfe == 31) {
+ tcg_gen_ext32s_tl(tdest, tsrca);
+ } else {
+ int rol = 63 - bfe;
+ if (bfs <= bfe) {
+ tcg_gen_shli_tl(tdest, tsrca, rol);
+ } else {
+ tcg_gen_rotli_tl(tdest, tsrca, rol);
+ }
+ tcg_gen_sari_tl(tdest, tdest, (bfs + rol) & 63);
+ }
+ mnemonic = "bfexts";
+ break;
+
case BFINS_BF_OPCODE_X0:
+ tsrcd = load_gr(dc, dest);
+ if (bfs <= bfe) {
+ tcg_gen_deposit_tl(tdest, tsrcd, tsrca, bfs, len);
+ } else {
+ tcg_gen_rotri_tl(tdest, tsrcd, bfs);
+ tcg_gen_deposit_tl(tdest, tdest, tsrca, 0, len);
+ tcg_gen_rotli_tl(tdest, tdest, bfs);
+ }
+ mnemonic = "bfins";
+ break;
+
case MM_BF_OPCODE_X0:
+ tsrcd = load_gr(dc, dest);
+ if (bfs == 0) {
+ tcg_gen_deposit_tl(tdest, tsrca, tsrcd, 0, len);
+ } else {
+ uint64_t mask = len == 64 ? -1 : rol64((1ULL << len) - 1, bfs);
+ TCGv tmp = tcg_const_tl(mask);
+
+ tcg_gen_and_tl(tdest, tsrcd, tmp);
+ tcg_gen_andc_tl(tmp, tsrca, tmp);
+ tcg_gen_or_tl(tdest, tdest, tmp);
+ tcg_temp_free(tmp);
+ }
+ mnemonic = "mm";
+ break;
+
default:
return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;
}