[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 2/7] target/ppc: Add support for prefixed load/store instructions
From: |
Gustavo Romero |
Subject: |
[PATCH 2/7] target/ppc: Add support for prefixed load/store instructions |
Date: |
Mon, 5 Oct 2020 01:03:14 -0300 |
From: Michael Roth <mdroth@linux.vnet.ibm.com>
This commit adds support for the following prefixed load and store
instructions for GPRs:
plbz, plh{a,z}, plw{a,z}, pld, plq
pstb, psth, pstw, pstd, pstq
paddi
Signed-off-by: Michael Roth <mroth@lamentation.net>
[ gromero: - fix for gen_addr_imm34_index()
- removed redundant PREFIX_R bit helper
- changes in commit log ]
Signed-off-by: Gustavo Romero <gromero@linux.ibm.com>
---
target/ppc/internal.h | 6 +
target/ppc/translate.c | 259 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 265 insertions(+)
diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index d03d691a44..dc4aff863c 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -159,6 +159,12 @@ EXTRACT_HELPER(PREFIX_TYPE, 24, 2);
EXTRACT_HELPER(PREFIX_ST1, 23, 1);
/* 4-bit sub-type */
EXTRACT_HELPER(PREFIX_ST4, 20, 4);
+/* 18 bits signed immediate value */
+EXTRACT_SHELPER(SIMM18, 0, 18);
+/* 18 bits unsigned immediate value */
+EXTRACT_HELPER(UIMM18, 0, 18);
+/* relative to CIA (current instruction address) */
+EXTRACT_HELPER(R, 20, 1);
#ifndef CONFIG_USER_ONLY
EXTRACT_HELPER(SR, 16, 4);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 96c2997d3f..82376b50ff 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -2495,6 +2495,34 @@ static inline void gen_addr_add(DisasContext *ctx, TCGv
ret, TCGv arg1,
}
}
+/* returns false if exception was generated */
+static inline int gen_addr_imm34_index(DisasContext *ctx, TCGv EA)
+{
+ uint64_t offset;
+
+ if (R(ctx->prefix) == 1) {
+ if (unlikely(rA(ctx->opcode) != 0)) {
+ gen_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
+ return 1;
+ }
+ // To find out the address of a prefixed instruction
+ // it's necessary to rewind 8 bytes because they are
+ // twice the size of non-prefixed instructions.
+ tcg_gen_movi_tl(EA, ctx->base.pc_next - 8);
+ } else {
+ gen_addr_register(ctx, EA);
+ }
+
+ offset = (uint64_t)UIMM18(ctx->prefix) << 16;
+ offset |= UIMM(ctx->opcode);
+ /* sign-extend 34 bit offset to 64-bits... */
+ if (extract64(offset, 33, 1) == 1) {
+ offset |= -1UL << 34;
+ }
+ tcg_gen_addi_tl(EA, EA, offset);
+ return 0;
+}
+
static inline void gen_align_no_le(DisasContext *ctx)
{
gen_exception_err(ctx, POWERPC_EXCP_ALIGN,
@@ -2714,6 +2742,35 @@ static void gen_ld(DisasContext *ctx)
tcg_temp_free(EA);
}
+static void gen_pld(DisasContext *ctx)
+{
+ TCGv EA;
+
+ gen_set_access_type(ctx, ACCESS_INT);
+ EA = tcg_temp_new();
+ if (gen_addr_imm34_index(ctx, EA)) {
+ goto out;
+ }
+ gen_qemu_ld64_i64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
+out:
+ tcg_temp_free(EA);
+}
+
+/* paddi */
+static void gen_paddi(DisasContext *ctx)
+{
+ TCGv EA;
+
+ EA = tcg_temp_new();
+ if (gen_addr_imm34_index(ctx, EA)) {
+ goto out;
+ }
+ gen_qemu_ld64_i64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
+
+out:
+ tcg_temp_free(EA);
+}
+
/* lq */
static void gen_lq(DisasContext *ctx)
{
@@ -2776,6 +2833,195 @@ static void gen_lq(DisasContext *ctx)
}
tcg_temp_free(EA);
}
+
+static void gen_plq(DisasContext *ctx)
+{
+ int ra, rd;
+ TCGv EA, rd0, rd1;
+
+ ra = rA(ctx->opcode);
+ rd = rD(ctx->opcode);
+ if (unlikely((rd & 1) || rd == ra)) {
+ gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
+ return;
+ }
+
+ gen_set_access_type(ctx, ACCESS_INT);
+ EA = tcg_temp_new();
+ if (gen_addr_imm34_index(ctx, EA)) {
+ goto out;
+ }
+
+ rd0 = cpu_gpr[rd];
+ rd1 = cpu_gpr[rd + 1];
+
+ if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
+ /* Restart with exclusive lock. */
+ gen_helper_exit_atomic(cpu_env);
+ ctx->base.is_jmp = DISAS_NORETURN;
+ } else {
+ tcg_gen_qemu_ld_i64(rd0, EA, ctx->mem_idx,
+ ctx->le_mode ? MO_LEQ : MO_BEQ);
+ gen_addr_add(ctx, EA, EA, 8);
+ tcg_gen_qemu_ld_i64(rd1, EA, ctx->mem_idx,
+ ctx->le_mode ? MO_LEQ : MO_BEQ);
+ }
+out:
+ tcg_temp_free(EA);
+}
+
+static void gen_plbz(DisasContext *ctx)
+{
+ TCGv EA;
+ gen_set_access_type(ctx, ACCESS_INT);
+ EA = tcg_temp_new();
+ if (gen_addr_imm34_index(ctx, EA)) {
+ goto out;
+ }
+ gen_qemu_ld8u(ctx, cpu_gpr[rD(ctx->opcode)], EA);
+out:
+ tcg_temp_free(EA);
+}
+
+static void gen_plhz(DisasContext *ctx)
+{
+ TCGv EA;
+ gen_set_access_type(ctx, ACCESS_INT);
+ EA = tcg_temp_new();
+ if (gen_addr_imm34_index(ctx, EA)) {
+ goto out;
+ }
+ gen_qemu_ld16u(ctx, cpu_gpr[rD(ctx->opcode)], EA);
+out:
+ tcg_temp_free(EA);
+}
+
+static void gen_plha(DisasContext *ctx)
+{
+ TCGv EA;
+ gen_set_access_type(ctx, ACCESS_INT);
+ EA = tcg_temp_new();
+ if (gen_addr_imm34_index(ctx, EA)) {
+ goto out;
+ }
+ gen_qemu_ld16s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
+out:
+ tcg_temp_free(EA);
+}
+
+static void gen_plwz(DisasContext *ctx)
+{
+ TCGv EA;
+ gen_set_access_type(ctx, ACCESS_INT);
+ EA = tcg_temp_new();
+ if (gen_addr_imm34_index(ctx, EA)) {
+ goto out;
+ }
+ gen_qemu_ld32u(ctx, cpu_gpr[rD(ctx->opcode)], EA);
+out:
+ tcg_temp_free(EA);
+}
+
+static void gen_plwa(DisasContext *ctx)
+{
+ TCGv EA;
+ gen_set_access_type(ctx, ACCESS_INT);
+ EA = tcg_temp_new();
+ if (gen_addr_imm34_index(ctx, EA)) {
+ goto out;
+ }
+ gen_qemu_ld32s(ctx, cpu_gpr[rD(ctx->opcode)], EA);
+out:
+ tcg_temp_free(EA);
+}
+
+static void gen_pstb(DisasContext *ctx)
+{
+ TCGv EA;
+ gen_set_access_type(ctx, ACCESS_INT);
+ EA = tcg_temp_new();
+ if (gen_addr_imm34_index(ctx, EA)) {
+ goto out;
+ }
+ gen_qemu_st8(ctx, cpu_gpr[rS(ctx->opcode)], EA);
+out:
+ tcg_temp_free(EA);
+}
+
+static void gen_psth(DisasContext *ctx)
+{
+ TCGv EA;
+ gen_set_access_type(ctx, ACCESS_INT);
+ EA = tcg_temp_new();
+ if (gen_addr_imm34_index(ctx, EA)) {
+ goto out;
+ }
+ gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], EA);
+out:
+ tcg_temp_free(EA);
+}
+
+static void gen_pstw(DisasContext *ctx)
+{
+ TCGv EA;
+ gen_set_access_type(ctx, ACCESS_INT);
+ EA = tcg_temp_new();
+ if (gen_addr_imm34_index(ctx, EA)) {
+ goto out;
+ }
+ gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], EA);
+out:
+ tcg_temp_free(EA);
+}
+
+static void gen_pstd(DisasContext *ctx) {
+ TCGv EA;
+ gen_set_access_type(ctx, ACCESS_INT);
+ EA = tcg_temp_new();
+ if (gen_addr_imm34_index(ctx, EA)) {
+ goto out;
+ }
+ gen_qemu_st64_i64(ctx, cpu_gpr[rS(ctx->opcode)], EA);
+out:
+ tcg_temp_free(EA);
+}
+
+static void gen_pstq(DisasContext *ctx) {
+ int ra, rs;
+ TCGv EA, rs0, rs1;
+
+ ra = rA(ctx->opcode);
+ rs = rD(ctx->opcode);
+ if (unlikely((rs & 1) || rs == ra)) {
+ gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
+ return;
+ }
+
+ gen_set_access_type(ctx, ACCESS_INT);
+ EA = tcg_temp_new();
+ if (gen_addr_imm34_index(ctx, EA)) {
+ goto out;
+ }
+
+ rs0 = cpu_gpr[rs];
+ rs1 = cpu_gpr[rs + 1];
+
+ if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
+ /* Restart with exclusive lock. */
+ gen_helper_exit_atomic(cpu_env);
+ ctx->base.is_jmp = DISAS_NORETURN;
+ } else {
+ tcg_gen_qemu_st_i64(rs0, EA, ctx->mem_idx,
+ ctx->le_mode ? MO_LEQ : MO_BEQ);
+ gen_addr_add(ctx, EA, EA, 8);
+ tcg_gen_qemu_st_i64(rs1, EA, ctx->mem_idx,
+ ctx->le_mode ? MO_LEQ : MO_BEQ);
+ }
+out:
+ tcg_temp_free(EA);
+}
+
+
#endif
/*** Integer store ***/
@@ -7067,6 +7313,7 @@ GEN_HANDLER_E(cmpb, 0x1F, 0x1C, 0x0F, 0x00000001,
PPC_NONE, PPC2_ISA205),
GEN_HANDLER_E(cmprb, 0x1F, 0x00, 0x06, 0x00400001, PPC_NONE, PPC2_ISA300),
GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL),
GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
+GEN_HANDLER_E_PREFIXED_M(paddi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_64B,
PPC2_ISA310),
GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
@@ -7128,6 +7375,18 @@ GEN_HANDLER2_E(extswsli1, "extswsli", 0x1F, 0x1B, 0x1B,
0x00000000,
GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B),
GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX),
GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B),
+GEN_HANDLER_E_PREFIXED_M(plbz, 0x22, 0xFF, 0xFF, 0x00000000, PPC_64B,
PPC2_ISA310),
+GEN_HANDLER_E_PREFIXED_M(plhz, 0x28, 0xFF, 0xFF, 0x00000000, PPC_64B,
PPC2_ISA310),
+GEN_HANDLER_E_PREFIXED_M(plha, 0x2a, 0xFF, 0xFF, 0x00000000, PPC_64B,
PPC2_ISA310),
+GEN_HANDLER_E_PREFIXED_M(plwz, 0x20, 0xFF, 0xFF, 0x00000000, PPC_64B,
PPC2_ISA310),
+GEN_HANDLER_E_PREFIXED(plwa, 0x29, 0xFF, 0xFF, 0x00000000, PPC_64B,
PPC2_ISA310),
+GEN_HANDLER_E_PREFIXED(pld, 0x39, 0xFF, 0xFF, 0x00000000, PPC_64B,
PPC2_ISA310),
+GEN_HANDLER_E_PREFIXED(plq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64B,
PPC2_ISA310),
+GEN_HANDLER_E_PREFIXED_M(pstb, 0x26, 0xFF, 0xFF, 0x00000000, PPC_64B,
PPC2_ISA310),
+GEN_HANDLER_E_PREFIXED_M(psth, 0x2c, 0xFF, 0xFF, 0x00000000, PPC_64B,
PPC2_ISA310),
+GEN_HANDLER_E_PREFIXED_M(pstw, 0x24, 0xFF, 0xFF, 0x00000000, PPC_64B,
PPC2_ISA310),
+GEN_HANDLER_E_PREFIXED(pstd, 0x3d, 0xFF, 0xFF, 0x00000000, PPC_64B,
PPC2_ISA310),
+GEN_HANDLER_E_PREFIXED(pstq, 0x3c, 0xFF, 0xFF, 0x00000000, PPC_64B,
PPC2_ISA310),
#endif
/* handles lfdp, lxsd, lxssp */
GEN_HANDLER_E(dform39, 0x39, 0xFF, 0xFF, 0x00000000, PPC_NONE, PPC2_ISA205),
--
2.17.1
- [PATCH 1/7] target/ppc: Add infrastructure for prefixed instructions, Gustavo Romero, 2020/10/05
- [PATCH 2/7] target/ppc: Add support for prefixed load/store instructions,
Gustavo Romero <=
- [PATCH 3/7] tests/tcg: Add tests for prefixed load/store instructions, Gustavo Romero, 2020/10/05
- [PATCH 4/7] target/ppc: Add support for paired vector load/store instructions, Gustavo Romero, 2020/10/05
- [PATCH 5/7] tests/tcg: Add tests for paired vector load/store instructions, Gustavo Romero, 2020/10/05
- [PATCH 6/7] target/ppc: Add support for prefixed load/store FP instructions, Gustavo Romero, 2020/10/05
- [PATCH 7/7] tests/tcg: Add tests for prefixed load/store FP instructions, Gustavo Romero, 2020/10/05