[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 23/26] target-hppa: Implement shifts and deposits
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [PATCH 23/26] target-hppa: Implement shifts and deposits |
Date: |
Fri, 16 Dec 2016 11:14:02 -0800 |
Signed-off-by: Richard Henderson <address@hidden>
---
target-hppa/translate.c | 309 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 309 insertions(+)
diff --git a/target-hppa/translate.c b/target-hppa/translate.c
index 14fe4bb..093a65e 100644
--- a/target-hppa/translate.c
+++ b/target-hppa/translate.c
@@ -1719,6 +1719,311 @@ static ExitStatus trans_movb(DisasContext *ctx,
uint32_t insn, bool is_imm)
return do_cbranch(ctx, disp, n, &cond);
}
+static ExitStatus trans_shrpw_sar(DisasContext *ctx, uint32_t insn,
+ const DisasInsn *di)
+{
+ unsigned rt = extract32(insn, 0, 5);
+ unsigned c = extract32(insn, 13, 3);
+ unsigned r1 = extract32(insn, 16, 5);
+ unsigned r2 = extract32(insn, 21, 5);
+ TCGv dest;
+
+ if (c) {
+ nullify_over(ctx);
+ }
+
+ dest = dest_gpr(ctx, rt);
+ if (r1 == 0) {
+ tcg_gen_ext32u_tl(dest, load_gpr(ctx, r2));
+ tcg_gen_shr_tl(dest, dest, cpu_sar);
+ } else if (r1 == r2) {
+ TCGv_i32 t32 = tcg_temp_new_i32();
+ tcg_gen_trunc_tl_i32(t32, load_gpr(ctx, r2));
+ tcg_gen_rotr_i32(t32, t32, cpu_sar);
+ tcg_gen_extu_i32_tl(dest, t32);
+ tcg_temp_free_i32(t32);
+ } else {
+ TCGv_i64 t = tcg_temp_new_i64();
+ TCGv_i64 s = tcg_temp_new_i64();
+
+ tcg_gen_concat_tl_i64(t, load_gpr(ctx, r2), load_gpr(ctx, r1));
+ tcg_gen_extu_tl_i64(s, cpu_sar);
+ tcg_gen_shr_i64(t, t, s);
+ tcg_gen_trunc_i64_tl(dest, t);
+
+ tcg_temp_free_i64(t);
+ tcg_temp_free_i64(s);
+ }
+ save_gpr(ctx, rt, dest);
+
+ /* Install the new nullification. */
+ cond_free(&ctx->null_cond);
+ if (c) {
+ ctx->null_cond = do_sed_cond(c, dest);
+ }
+ return nullify_end(ctx, NO_EXIT);
+}
+
+static ExitStatus trans_shrpw_imm(DisasContext *ctx, uint32_t insn,
+ const DisasInsn *di)
+{
+ unsigned rt = extract32(insn, 0, 5);
+ unsigned cpos = extract32(insn, 5, 5);
+ unsigned c = extract32(insn, 13, 3);
+ unsigned r1 = extract32(insn, 16, 5);
+ unsigned r2 = extract32(insn, 21, 5);
+ unsigned sa = 31 - cpos;
+ TCGv dest, t2;
+
+ if (c) {
+ nullify_over(ctx);
+ }
+
+ dest = dest_gpr(ctx, rt);
+ t2 = load_gpr(ctx, r2);
+ if (r1 == r2) {
+ TCGv_i32 t32 = tcg_temp_new_i32();
+ tcg_gen_trunc_tl_i32(t32, t2);
+ tcg_gen_rotri_i32(t32, t32, sa);
+ tcg_gen_extu_i32_tl(dest, t32);
+ tcg_temp_free_i32(t32);
+ } else if (r1 == 0) {
+ tcg_gen_extract_tl(dest, t2, sa, 32 - sa);
+ } else {
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_extract_tl(t0, t2, sa, 32 - sa);
+ tcg_gen_deposit_tl(dest, t0, cpu_gr[r1], 32 - sa, sa);
+ tcg_temp_free(t0);
+ }
+ save_gpr(ctx, rt, dest);
+
+ /* Install the new nullification. */
+ cond_free(&ctx->null_cond);
+ if (c) {
+ ctx->null_cond = do_sed_cond(c, dest);
+ }
+ return nullify_end(ctx, NO_EXIT);
+}
+
+static ExitStatus trans_extrw_sar(DisasContext *ctx, uint32_t insn,
+ const DisasInsn *di)
+{
+ unsigned clen = extract32(insn, 0, 5);
+ unsigned is_se = extract32(insn, 10, 1);
+ unsigned c = extract32(insn, 13, 3);
+ unsigned rt = extract32(insn, 16, 5);
+ unsigned rr = extract32(insn, 21, 5);
+ unsigned len = 32 - clen;
+ TCGv dest, src, tmp;
+
+ if (c) {
+ nullify_over(ctx);
+ }
+
+ dest = dest_gpr(ctx, rt);
+ src = load_gpr(ctx, rr);
+ tmp = tcg_temp_new();
+
+ /* Recall that SAR is using big-endian bit numbering. */
+ tcg_gen_xori_tl(tmp, cpu_sar, TARGET_LONG_BITS - 1);
+ if (is_se) {
+ tcg_gen_sar_tl(dest, src, tmp);
+ tcg_gen_sextract_tl(dest, dest, 0, len);
+ } else {
+ tcg_gen_shr_tl(dest, src, tmp);
+ tcg_gen_extract_tl(dest, dest, 0, len);
+ }
+ tcg_temp_free(tmp);
+ save_gpr(ctx, rt, dest);
+
+ /* Install the new nullification. */
+ cond_free(&ctx->null_cond);
+ if (c) {
+ ctx->null_cond = do_sed_cond(c, dest);
+ }
+ return nullify_end(ctx, NO_EXIT);
+}
+
+static ExitStatus trans_extrw_imm(DisasContext *ctx, uint32_t insn,
+ const DisasInsn *di)
+{
+ unsigned clen = extract32(insn, 0, 5);
+ unsigned pos = extract32(insn, 5, 5);
+ unsigned is_se = extract32(insn, 10, 1);
+ unsigned c = extract32(insn, 13, 3);
+ unsigned rt = extract32(insn, 16, 5);
+ unsigned rr = extract32(insn, 21, 5);
+ unsigned len = 32 - clen;
+ unsigned cpos = 31 - pos;
+ TCGv dest, src;
+
+ if (c) {
+ nullify_over(ctx);
+ }
+
+ dest = dest_gpr(ctx, rt);
+ src = load_gpr(ctx, rr);
+ if (is_se) {
+ tcg_gen_sextract_tl(dest, src, cpos, len);
+ } else {
+ tcg_gen_extract_tl(dest, src, cpos, len);
+ }
+ save_gpr(ctx, rt, dest);
+
+ /* Install the new nullification. */
+ cond_free(&ctx->null_cond);
+ if (c) {
+ ctx->null_cond = do_sed_cond(c, dest);
+ }
+ return nullify_end(ctx, NO_EXIT);
+}
+
+static const DisasInsn table_sh_ex[] = {
+ { 0xd0000000u, 0xfc001fe0u, trans_shrpw_sar },
+ { 0xd0000800u, 0xfc001c00u, trans_shrpw_imm },
+ { 0xd0001000u, 0xfc001be0u, trans_extrw_sar },
+ { 0xd0001800u, 0xfc001800u, trans_extrw_imm },
+};
+
+static ExitStatus trans_depw_imm_c(DisasContext *ctx, uint32_t insn,
+ const DisasInsn *di)
+{
+ unsigned clen = extract32(insn, 0, 5);
+ unsigned cpos = extract32(insn, 5, 5);
+ unsigned nz = extract32(insn, 10, 1);
+ unsigned c = extract32(insn, 13, 3);
+ target_long val = low_sextract(insn, 16, 5);
+ unsigned rt = extract32(insn, 21, 5);
+ unsigned len = 32 - clen;
+ target_long mask0, mask1;
+ TCGv dest;
+
+ if (c) {
+ nullify_over(ctx);
+ }
+ if (cpos + len > 32) {
+ len = 32 - cpos;
+ }
+
+ dest = dest_gpr(ctx, rt);
+ mask0 = deposit64(0, cpos, len, val);
+ mask1 = deposit64(-1, cpos, len, val);
+
+ if (nz) {
+ TCGv src = load_gpr(ctx, rt);
+ if (mask1 != -1) {
+ tcg_gen_andi_tl(dest, src, mask1);
+ src = dest;
+ }
+ tcg_gen_ori_tl(dest, src, mask0);
+ } else {
+ tcg_gen_movi_tl(dest, mask0);
+ }
+ save_gpr(ctx, rt, dest);
+
+ /* Install the new nullification. */
+ cond_free(&ctx->null_cond);
+ if (c) {
+ ctx->null_cond = do_sed_cond(c, dest);
+ }
+ return nullify_end(ctx, NO_EXIT);
+}
+
+static ExitStatus trans_depw_imm(DisasContext *ctx, uint32_t insn,
+ const DisasInsn *di)
+{
+ unsigned clen = extract32(insn, 0, 5);
+ unsigned cpos = extract32(insn, 5, 5);
+ unsigned nz = extract32(insn, 10, 1);
+ unsigned c = extract32(insn, 13, 3);
+ unsigned rr = extract32(insn, 16, 5);
+ unsigned rt = extract32(insn, 21, 5);
+ unsigned rs = nz ? rt : 0;
+ unsigned len = 32 - clen;
+ TCGv dest, val;
+
+ if (c) {
+ nullify_over(ctx);
+ }
+ if (cpos + len > 32) {
+ len = 32 - cpos;
+ }
+
+ dest = dest_gpr(ctx, rt);
+ val = load_gpr(ctx, rr);
+ if (rs == 0) {
+ tcg_gen_deposit_z_tl(dest, val, cpos, len);
+ } else {
+ tcg_gen_deposit_tl(dest, cpu_gr[rs], val, cpos, len);
+ }
+ save_gpr(ctx, rt, dest);
+
+ /* Install the new nullification. */
+ cond_free(&ctx->null_cond);
+ if (c) {
+ ctx->null_cond = do_sed_cond(c, dest);
+ }
+ return nullify_end(ctx, NO_EXIT);
+}
+
+static ExitStatus trans_depw_sar(DisasContext *ctx, uint32_t insn,
+ const DisasInsn *di)
+{
+ unsigned clen = extract32(insn, 0, 5);
+ unsigned nz = extract32(insn, 10, 1);
+ unsigned i = extract32(insn, 12, 1);
+ unsigned c = extract32(insn, 13, 3);
+ unsigned rt = extract32(insn, 21, 5);
+ unsigned rs = nz ? rt : 0;
+ unsigned len = 32 - clen;
+ TCGv val, mask, tmp, shift, dest;
+ unsigned msb = 1U << (len - 1);
+
+ if (c) {
+ nullify_over(ctx);
+ }
+
+ if (i) {
+ val = load_const(ctx, low_sextract(insn, 16, 5));
+ } else {
+ val = load_gpr(ctx, extract32(insn, 16, 5));
+ }
+ dest = dest_gpr(ctx, rt);
+ shift = tcg_temp_new();
+ tmp = tcg_temp_new();
+
+ /* Convert big-endian bit numbering in SAR to left-shift. */
+ tcg_gen_xori_tl(shift, cpu_sar, TARGET_LONG_BITS - 1);
+
+ mask = tcg_const_tl(msb + (msb - 1));
+ tcg_gen_and_tl(tmp, val, mask);
+ if (rs) {
+ tcg_gen_shl_tl(mask, mask, shift);
+ tcg_gen_shl_tl(tmp, tmp, shift);
+ tcg_gen_andc_tl(dest, cpu_gr[rs], mask);
+ tcg_gen_or_tl(dest, dest, tmp);
+ } else {
+ tcg_gen_shl_tl(dest, tmp, shift);
+ }
+ tcg_temp_free(shift);
+ tcg_temp_free(mask);
+ tcg_temp_free(tmp);
+ save_gpr(ctx, rt, dest);
+
+ /* Install the new nullification. */
+ cond_free(&ctx->null_cond);
+ if (c) {
+ ctx->null_cond = do_sed_cond(c, dest);
+ }
+ return nullify_end(ctx, NO_EXIT);
+}
+
+static const DisasInsn table_depw[] = {
+ { 0xd4000000u, 0xfc000be0u, trans_depw_sar },
+ { 0xd4000800u, 0xfc001800u, trans_depw_imm },
+ { 0xd4001800u, 0xfc001800u, trans_depw_imm_c },
+};
+
static ExitStatus trans_be(DisasContext *ctx, uint32_t insn, bool is_l)
{
unsigned n = extract32(insn, 1, 1);
@@ -1874,6 +2179,10 @@ static ExitStatus translate_one(DisasContext *ctx,
uint32_t insn)
return trans_movb(ctx, insn, false);
case 0x33:
return trans_movb(ctx, insn, true);
+ case 0x34:
+ return translate_table(ctx, insn, table_sh_ex);
+ case 0x35:
+ return translate_table(ctx, insn, table_depw);
case 0x38:
return trans_be(ctx, insn, false);
case 0x39:
--
2.9.3
- [Qemu-devel] [PATCH 03/26] linux-user: Handle TIOCSTART and TIOCSTOP, (continued)
- [Qemu-devel] [PATCH 03/26] linux-user: Handle TIOCSTART and TIOCSTOP, Richard Henderson, 2016/12/16
- [Qemu-devel] [PATCH 14/26] linux-user: Add HPPA target_signal.h and target_cpu.h, Richard Henderson, 2016/12/16
- [Qemu-devel] [PATCH 15/26] linux-user: Add HPPA signal handling, Richard Henderson, 2016/12/16
- [Qemu-devel] [PATCH 11/26] linux-user: Add HPPA target_syscall.h, Richard Henderson, 2016/12/16
- [Qemu-devel] [PATCH 12/26] linux-user: Add HPPA definitions to syscall_defs.h, Richard Henderson, 2016/12/16
- [Qemu-devel] [PATCH 13/26] linux-user: Add HPPA target_structs.h, Richard Henderson, 2016/12/16
- [Qemu-devel] [PATCH 10/26] linux-user: Add HPPA termbits.h, Richard Henderson, 2016/12/16
- [Qemu-devel] [PATCH 16/26] linux-user: Add HPPA startup and main loop, Richard Henderson, 2016/12/16
- [Qemu-devel] [PATCH 19/26] target-hppa: Add nullification framework, Richard Henderson, 2016/12/16
- [Qemu-devel] [PATCH 22/26] target-hppa: Implement linux-user gateway page, Richard Henderson, 2016/12/16
- [Qemu-devel] [PATCH 23/26] target-hppa: Implement shifts and deposits,
Richard Henderson <=
- [Qemu-devel] [PATCH 17/26] target-hppa: Add softfloat specializations, Richard Henderson, 2016/12/16
- [Qemu-devel] [PATCH 21/26] target-hppa: Implement branches, Richard Henderson, 2016/12/16
- [Qemu-devel] [PATCH 18/26] target-hppa: Add framework and enable compilation, Richard Henderson, 2016/12/16
- [Qemu-devel] [PATCH 25/26] target-hppa: Implement system and memory-management insns, Richard Henderson, 2016/12/16
- [Qemu-devel] [PATCH 20/26] target-hppa: Implement basic arithmetic, Richard Henderson, 2016/12/16
- [Qemu-devel] [PATCH 24/26] target-hppa: Implement loads and stores, Richard Henderson, 2016/12/16
- [Qemu-devel] [PATCH 01/26] Revert "Remove remainders of HPPA backend", Richard Henderson, 2016/12/16
- [Qemu-devel] [PATCH 26/26] target-hppa: Implement floating-point insns, Richard Henderson, 2016/12/16