diff mbox series

[v4,5/9] target/mips: Add MXU instruction S8LDD

Message ID 20180830193019.20104-6-jancraig@amazon.com
State New
Headers show
Series Add limited MXU instruction support | expand

Commit Message

Cameron Esfahani via Aug. 30, 2018, 7:30 p.m. UTC
Adds support for emulating the S8LDD MXU instruction.

Signed-off-by: Craig Janeczek <jancraig@amazon.com>
---
 v1
    - initial patch
 v2
    - changed bitfield usage to extract32
    - used deposit_tl instructions instead of shift and bitmask
 v3
    - Split gen_mxu function into command specific gen_mxu_<ins> functions
 v4
    -Add and use MXU_OPTN3_PTN #defines
    -Add check for MXUEN

 target/mips/translate.c | 98 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 98 insertions(+)

Comments

Aleksandar Markovic Aug. 31, 2018, 1:39 p.m. UTC | #1
Hi, Craig,

> From: Craig Janeczek <jancraig@amazon.com>
> Sent: Thursday, August 30, 2018 9:30 PM
> 
> Subject: [PATCH v4 5/9] target/mips: Add MXU instruction S8LDD

> Adds support for emulating the S8LDD MXU instruction.

> Signed-off-by: Craig Janeczek <jancraig@amazon.com>
> ---
>  v1
>     - initial patch
>  v2
>     - changed bitfield usage to extract32
>     - used deposit_tl instructions instead of shift and bitmask
>  v3
>     - Split gen_mxu function into command specific gen_mxu_<ins> functions
>  v4
>     -Add and use MXU_OPTN3_PTN #defines
>     -Add check for MXUEN

>  target/mips/translate.c | 98 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 98 insertions(+)

> diff --git a/target/mips/translate.c b/target/mips/translate.c

> +    TCGv t0, t1;
> +    TCGLabel *l0;
> +    uint32_t xra, s8, optn3, rb;
> +
> +    t0 = tcg_temp_new();
> +    t1 = tcg_temp_new();
> +
> +    l0 = gen_new_label();
> +
> +    xra = extract32(ctx->opcode, 6, 4);
> +    s8 = extract32(ctx->opcode, 10, 8);
> +    optn3 = extract32(ctx->opcode, 18, 3);
> +    rb = extract32(ctx->opcode, 21, 5);
> +
> +    gen_load_mxu_cr(t0);
> +    tcg_gen_andi_tl(t0, t0, MXUEN);
> +    tcg_gen_brcondi_tl(TCG_COND_NE, t0, MXUEN, l0);
> +
> +    gen_load_gpr(t0, rb);
> +    tcg_gen_addi_tl(t0, t0, (int8_t)s8);

I am not sure if this works as desired, with respect to branching. In order to survive branching, tcg variables must be initialized with tcg_temp_local_new(), rather than with tcg_tem_new(). Please retest, and amend if needed.

Thanks,
Aleksandar
Richard Henderson Sept. 12, 2018, 8:19 p.m. UTC | #2
On 08/30/2018 12:30 PM, Craig Janeczek via Qemu-devel wrote:
> +    gen_load_mxu_cr(t0);
> +    tcg_gen_andi_tl(t0, t0, MXUEN);
> +    tcg_gen_brcondi_tl(TCG_COND_NE, t0, MXUEN, l0);

Probably MXUEN should be included in env->hflags, and therefore
tested via ctx->hflags.  (Which also means ending a TB after a
write to MCR, which can change this value).

The documentation says that if MXUEN is unset the result is
"unpredictable".  What does real hardware do?  Does it really
treat the instruction as a nop?  Does it raise an exception?

Otherwise another possibility for "unpredictable" is to simply
execute the instruction.  Which would certainly be the easiest
implementation...


r~
Richard Henderson Sept. 12, 2018, 8:20 p.m. UTC | #3
On 08/31/2018 06:39 AM, Aleksandar Markovic wrote:
>> +    gen_load_mxu_cr(t0);
>> +    tcg_gen_andi_tl(t0, t0, MXUEN);
>> +    tcg_gen_brcondi_tl(TCG_COND_NE, t0, MXUEN, l0);
>> +
>> +    gen_load_gpr(t0, rb);
>> +    tcg_gen_addi_tl(t0, t0, (int8_t)s8);
> 
> I am not sure if this works as desired, with respect to branching. In order to survive branching, tcg variables must be initialized with tcg_temp_local_new(), rather than with tcg_tem_new(). Please retest, and amend if needed.

There is no value live across the branch here.

T0 is used before the branch, yes, but it is also reset
immediately via the gen_load_gpr after the branch.

This is fine.


r~
diff mbox series

Patch

diff --git a/target/mips/translate.c b/target/mips/translate.c
index 41081ee066..cfd25c3abe 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -1462,6 +1462,8 @@  static TCGv_i64 msa_wr_d[64];
 static TCGv mxu_gpr[15];
 static TCGv mxu_CR;
 
+#define MXUEN 0x01
+
 #include "exec/gen-icount.h"
 
 #define gen_helper_0e0i(name, arg) do {                           \
@@ -3837,6 +3839,16 @@  static void gen_cl (DisasContext *ctx, uint32_t opc,
 
 /* MXU Instructions */
 
+/* MXU operand getting patterns OPTN3 */
+#define MXU_OPTN3_PTN0  0
+#define MXU_OPTN3_PTN1  1
+#define MXU_OPTN3_PTN2  2
+#define MXU_OPTN3_PTN3  3
+#define MXU_OPTN3_PTN4  4
+#define MXU_OPTN3_PTN5  5
+#define MXU_OPTN3_PTN6  6
+#define MXU_OPTN3_PTN7  7
+
 /* S32I2M XRa, rb - Register move from GRF to XRF */
 static void gen_mxu_s32i2m(DisasContext *ctx, uint32_t opc)
 {
@@ -3880,6 +3892,88 @@  static void gen_mxu_s32m2i(DisasContext *ctx, uint32_t opc)
     tcg_temp_free(t0);
 }
 
+/* S8LDD XRa, rb, S8, OPTN3 - Load a byte from memory to XRF */
+static void gen_mxu_s8ldd(DisasContext *ctx, uint32_t opc)
+{
+    TCGv t0, t1;
+    TCGLabel *l0;
+    uint32_t xra, s8, optn3, rb;
+
+    t0 = tcg_temp_new();
+    t1 = tcg_temp_new();
+
+    l0 = gen_new_label();
+
+    xra = extract32(ctx->opcode, 6, 4);
+    s8 = extract32(ctx->opcode, 10, 8);
+    optn3 = extract32(ctx->opcode, 18, 3);
+    rb = extract32(ctx->opcode, 21, 5);
+
+    gen_load_mxu_cr(t0);
+    tcg_gen_andi_tl(t0, t0, MXUEN);
+    tcg_gen_brcondi_tl(TCG_COND_NE, t0, MXUEN, l0);
+
+    gen_load_gpr(t0, rb);
+    tcg_gen_addi_tl(t0, t0, (int8_t)s8);
+    switch (optn3) {
+    /*XRa[7:0] = tmp8 */
+    case MXU_OPTN3_PTN0:
+        tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+        gen_load_mxu_gpr(t0, xra);
+        tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
+        break;
+    /* XRa[15:8] = tmp8 */
+    case MXU_OPTN3_PTN1:
+        tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+        gen_load_mxu_gpr(t0, xra);
+        tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
+        break;
+    /* XRa[23:16] = tmp8 */
+    case MXU_OPTN3_PTN2:
+        tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+        gen_load_mxu_gpr(t0, xra);
+        tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
+        break;
+    /* XRa[31:24] = tmp8 */
+    case MXU_OPTN3_PTN3:
+        tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+        gen_load_mxu_gpr(t0, xra);
+        tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
+        break;
+    /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
+    case MXU_OPTN3_PTN4:
+        tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+        tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
+        break;
+    /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
+    case MXU_OPTN3_PTN5:
+        tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+        tcg_gen_shli_tl(t1, t1, 8);
+        tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
+        break;
+    /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
+    case MXU_OPTN3_PTN6:
+        tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
+        tcg_gen_mov_tl(t0, t1);
+        tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
+        tcg_gen_shli_tl(t1, t1, 16);
+        tcg_gen_or_tl(t0, t0, t1);
+        break;
+    /* XRa = {tmp8, tmp8, tmp8, tmp8} */
+    case MXU_OPTN3_PTN7:
+        tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+        tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
+        tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
+        break;
+    }
+    gen_store_mxu_gpr(t0, xra);
+
+    gen_set_label(l0);
+
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+}
+
 /* Godson integer instructions */
 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
                                  int rd, int rs, int rt)
@@ -17952,6 +18046,10 @@  static void decode_opc_special2_mxu(CPUMIPSState *env, DisasContext *ctx)
         gen_mxu_s32m2i(ctx, op1);
         break;
 
+    case OPC_MXU_S8LDD:
+        gen_mxu_s8ldd(ctx, op1);
+        break;
+
     default:            /* Invalid */
         MIPS_INVAL("special2_mxu");
         generate_exception_end(ctx, EXCP_RI);