All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/4] Add TriCore RCPW, RCRR, RCRW, RLC and RCR instructions
@ 2014-11-13 17:12 Bastian Koppelmann
  2014-11-13 17:12 ` [Qemu-devel] [PATCH v2 1/4] target-tricore: Make TRICORE_FEATURES implying others Bastian Koppelmann
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Bastian Koppelmann @ 2014-11-13 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, rth

Hi,

this patch depends on the previous TriCore patches (https://patchwork.ozlabs.org/patch/405459/) and will hopefully end up in 2.3 QEMU.
Other than adding the RCPW, RCRR, RCRW, RLC and RCR instructions, it cleans up how ISA versions in the feature bitmask are handled,
to simplify the checks, when instructions are available.

Thanks,
Bastian

v1 -> v2:
    - Fixed obvious style errors, given by checkpatch.

Bastian Koppelmann (4):
  target-tricore: Make TRICORE_FEATURES implying others.
  target-tricore: Add instructions of RCPW, RCRR and RCRW opcode format
  target-tricore: Add instructions of RLC opcode format
  target-tricore: Add instructions of RCR opcode format

 target-tricore/cpu.c             |   9 +
 target-tricore/csfr.def          | 124 +++++++
 target-tricore/helper.h          |  11 +
 target-tricore/op_helper.c       | 203 +++++++++++
 target-tricore/translate.c       | 744 ++++++++++++++++++++++++++++++++++++++-
 target-tricore/tricore-opcodes.h |   4 +-
 6 files changed, 1088 insertions(+), 7 deletions(-)
 create mode 100644 target-tricore/csfr.def

--
2.1.3

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH v2 1/4] target-tricore: Make TRICORE_FEATURES implying others.
  2014-11-13 17:12 [Qemu-devel] [PATCH v2 0/4] Add TriCore RCPW, RCRR, RCRW, RLC and RCR instructions Bastian Koppelmann
@ 2014-11-13 17:12 ` Bastian Koppelmann
  2014-11-13 17:12 ` [Qemu-devel] [PATCH v2 2/4] target-tricore: Add instructions of RCPW, RCRR and RCRW opcode format Bastian Koppelmann
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Bastian Koppelmann @ 2014-11-13 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, rth

Since all the TriCore instructionsets are subsets of each other (1.3 C 1.3.1 C 1.6),
make the features implying each other, e.g 1.6 also has 1.3.1 and 1.3. This way
we only need to check our features for the instructionset, where a instruction was first introduced.

Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
---
 target-tricore/cpu.c       | 9 +++++++++
 target-tricore/translate.c | 6 +++---
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/target-tricore/cpu.c b/target-tricore/cpu.c
index 7bf041a..abe16fa 100644
--- a/target-tricore/cpu.c
+++ b/target-tricore/cpu.c
@@ -63,8 +63,17 @@ static bool tricore_cpu_has_work(CPUState *cs)
 static void tricore_cpu_realizefn(DeviceState *dev, Error **errp)
 {
     CPUState *cs = CPU(dev);
+    TriCoreCPU *cpu = TRICORE_CPU(dev);
     TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(dev);
+    CPUTriCoreState *env = &cpu->env;
 
+    /* Some features automatically imply others */
+    if (tricore_feature(env, TRICORE_FEATURE_16)) {
+        set_feature(env, TRICORE_FEATURE_131);
+    }
+    if (tricore_feature(env, TRICORE_FEATURE_131)) {
+        set_feature(env, TRICORE_FEATURE_13);
+    }
     cpu_reset(cs);
     qemu_init_vcpu(cs);
 
diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index 1daf26d..3775374 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -2206,17 +2206,17 @@ static void decode_bo_addrmode_post_pre_base(CPUTriCoreState *env,
     case OPC2_32_BO_CACHEI_WI_SHORTOFF:
     case OPC2_32_BO_CACHEI_W_SHORTOFF:
         /* TODO: Raise illegal opcode trap,
-                 if tricore_feature(TRICORE_FEATURE_13) */
+                 if !tricore_feature(TRICORE_FEATURE_131) */
         break;
     case OPC2_32_BO_CACHEI_W_POSTINC:
     case OPC2_32_BO_CACHEI_WI_POSTINC:
-        if (!tricore_feature(env, TRICORE_FEATURE_13)) {
+        if (tricore_feature(env, TRICORE_FEATURE_131)) {
             tcg_gen_addi_tl(cpu_gpr_d[r2], cpu_gpr_d[r2], off10);
         } /* TODO: else raise illegal opcode trap */
         break;
     case OPC2_32_BO_CACHEI_W_PREINC:
     case OPC2_32_BO_CACHEI_WI_PREINC:
-        if (!tricore_feature(env, TRICORE_FEATURE_13)) {
+        if (tricore_feature(env, TRICORE_FEATURE_131)) {
             tcg_gen_addi_tl(cpu_gpr_d[r2], cpu_gpr_d[r2], off10);
         } /* TODO: else raise illegal opcode trap */
         break;
-- 
2.1.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH v2 2/4] target-tricore: Add instructions of RCPW, RCRR and RCRW opcode format
  2014-11-13 17:12 [Qemu-devel] [PATCH v2 0/4] Add TriCore RCPW, RCRR, RCRW, RLC and RCR instructions Bastian Koppelmann
  2014-11-13 17:12 ` [Qemu-devel] [PATCH v2 1/4] target-tricore: Make TRICORE_FEATURES implying others Bastian Koppelmann
@ 2014-11-13 17:12 ` Bastian Koppelmann
  2014-11-13 17:12 ` [Qemu-devel] [PATCH v2 3/4] target-tricore: Add instructions of RLC " Bastian Koppelmann
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Bastian Koppelmann @ 2014-11-13 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, rth

Add instructions of RCPW, RCRR and RCRW opcode format.
Add microcode generator function gen_insert.

Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
---
 target-tricore/translate.c | 132 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 129 insertions(+), 3 deletions(-)

diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index 3775374..689596f 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -869,7 +869,28 @@ static inline void gen_eqany_hi(TCGv ret, TCGv r1, int32_t con)
     tcg_temp_free(h0);
     tcg_temp_free(h1);
 }
+/* mask = ((1 << width) -1) << pos;
+   ret = (r1 & ~mask) | (r2 << pos) & mask); */
+static inline void gen_insert(TCGv ret, TCGv r1, TCGv r2, TCGv width, TCGv pos)
+{
+    TCGv mask = tcg_temp_new();
+    TCGv temp = tcg_temp_new();
+    TCGv temp2 = tcg_temp_new();
 
+    tcg_gen_movi_tl(mask, 1);
+    tcg_gen_shl_tl(mask, mask, width);
+    tcg_gen_subi_tl(mask, mask, 1);
+    tcg_gen_shl_tl(mask, mask, pos);
+
+    tcg_gen_shl_tl(temp, r2, pos);
+    tcg_gen_and_tl(temp, temp, mask);
+    tcg_gen_andc_tl(temp2, r1, mask);
+    tcg_gen_or_tl(ret, temp, temp2);
+
+    tcg_temp_free(mask);
+    tcg_temp_free(temp);
+    tcg_temp_free(temp2);
+}
 
 /* helpers for generating program flow micro-ops */
 
@@ -3128,14 +3149,92 @@ static void decode_rc_mul(CPUTriCoreState *env, DisasContext *ctx)
     }
 }
 
+/* RCPW format */
+static void decode_rcpw_insert(CPUTriCoreState *env, DisasContext *ctx)
+{
+    uint32_t op2;
+    int r1, r2;
+    int32_t pos, width, const4;
+
+    TCGv temp;
+
+    op2    = MASK_OP_RCPW_OP2(ctx->opcode);
+    r1     = MASK_OP_RCPW_S1(ctx->opcode);
+    r2     = MASK_OP_RCPW_D(ctx->opcode);
+    const4 = MASK_OP_RCPW_CONST4(ctx->opcode);
+    width  = MASK_OP_RCPW_WIDTH(ctx->opcode);
+    pos    = MASK_OP_RCPW_POS(ctx->opcode);
+
+    switch (op2) {
+    case OPC2_32_RCPW_IMASK:
+        /* if pos + width > 31 undefined result */
+        if (pos + width <= 31) {
+            tcg_gen_movi_tl(cpu_gpr_d[r2+1], ((1u << width) - 1) << pos);
+            tcg_gen_movi_tl(cpu_gpr_d[r2], (const4 << pos));
+        }
+        break;
+    case OPC2_32_RCPW_INSERT:
+        /* if pos + width > 32 undefined result */
+        if (pos + width <= 32) {
+            temp = tcg_const_i32(const4);
+            tcg_gen_deposit_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], temp, pos, width);
+            tcg_temp_free(temp);
+        }
+        break;
+    }
+}
+
+/* RCRW format */
+
+static void decode_rcrw_insert(CPUTriCoreState *env, DisasContext *ctx)
+{
+    uint32_t op2;
+    int r1, r3, r4;
+    int32_t width, const4;
+
+    TCGv temp, temp2, temp3;
+
+    op2    = MASK_OP_RCRW_OP2(ctx->opcode);
+    r1     = MASK_OP_RCRW_S1(ctx->opcode);
+    r3     = MASK_OP_RCRW_S3(ctx->opcode);
+    r4     = MASK_OP_RCRW_D(ctx->opcode);
+    width  = MASK_OP_RCRW_WIDTH(ctx->opcode);
+    const4 = MASK_OP_RCRW_CONST4(ctx->opcode);
+
+    temp = tcg_temp_new();
+    temp2 = tcg_temp_new();
+
+    switch (op2) {
+    case OPC2_32_RCRW_IMASK:
+        tcg_gen_andi_tl(temp, cpu_gpr_d[r4], 0x1f);
+        tcg_gen_movi_tl(temp2, (1 << width) - 1);
+        tcg_gen_shl_tl(cpu_gpr_d[r3 + 1], temp2, temp);
+        tcg_gen_movi_tl(temp2, const4);
+        tcg_gen_shl_tl(cpu_gpr_d[r3], temp2, temp);
+        break;
+    case OPC2_32_RCRW_INSERT:
+        temp3 = tcg_temp_new();
+
+        tcg_gen_movi_tl(temp, width);
+        tcg_gen_movi_tl(temp2, const4);
+        tcg_gen_andi_tl(temp3, cpu_gpr_d[r4], 0x1f);
+        gen_insert(cpu_gpr_d[r3], cpu_gpr_d[r1], temp2, temp, temp3);
+
+        tcg_temp_free(temp3);
+        break;
+    }
+    tcg_temp_free(temp);
+    tcg_temp_free(temp2);
+}
+
 static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
 {
     int op1;
-    int32_t r1, r2;
-    int32_t address;
+    int32_t r1, r2, r3;
+    int32_t address, const16;
     int8_t b, const4;
     int32_t bpos;
-    TCGv temp, temp2;
+    TCGv temp, temp2, temp3;
 
     op1 = MASK_OP_MAJOR(ctx->opcode);
 
@@ -3309,6 +3408,33 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
     case OPCM_32_RC_MUL:
         decode_rc_mul(env, ctx);
         break;
+/* RCPW Format */
+    case OPCM_32_RCPW_MASK_INSERT:
+        decode_rcpw_insert(env, ctx);
+        break;
+/* RCRR Format */
+    case OPC1_32_RCRR_INSERT:
+        r1 = MASK_OP_RCRR_S1(ctx->opcode);
+        r2 = MASK_OP_RCRR_S3(ctx->opcode);
+        r3 = MASK_OP_RCRR_D(ctx->opcode);
+        const16 = MASK_OP_RCRR_CONST4(ctx->opcode);
+        temp = tcg_const_i32(const16);
+        temp2 = tcg_temp_new(); /* width*/
+        temp3 = tcg_temp_new(); /* pos */
+
+        tcg_gen_andi_tl(temp2, cpu_gpr_d[r3+1], 0x1f);
+        tcg_gen_andi_tl(temp3, cpu_gpr_d[r3], 0x1f);
+
+        gen_insert(cpu_gpr_d[r2], cpu_gpr_d[r1], temp, temp2, temp3);
+
+        tcg_temp_free(temp);
+        tcg_temp_free(temp2);
+        tcg_temp_free(temp3);
+        break;
+/* RCRW Format */
+    case OPCM_32_RCRW_MASK_INSERT:
+        decode_rcrw_insert(env, ctx);
+        break;
     }
 }
 
-- 
2.1.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH v2 3/4] target-tricore: Add instructions of RLC opcode format
  2014-11-13 17:12 [Qemu-devel] [PATCH v2 0/4] Add TriCore RCPW, RCRR, RCRW, RLC and RCR instructions Bastian Koppelmann
  2014-11-13 17:12 ` [Qemu-devel] [PATCH v2 1/4] target-tricore: Make TRICORE_FEATURES implying others Bastian Koppelmann
  2014-11-13 17:12 ` [Qemu-devel] [PATCH v2 2/4] target-tricore: Add instructions of RCPW, RCRR and RCRW opcode format Bastian Koppelmann
@ 2014-11-13 17:12 ` Bastian Koppelmann
  2014-11-13 17:12 ` [Qemu-devel] [PATCH v2 4/4] target-tricore: Add instructions of RCR " Bastian Koppelmann
  2014-11-14 13:41 ` [Qemu-devel] [PATCH v2 0/4] Add TriCore RCPW, RCRR, RCRW, RLC and RCR instructions Richard Henderson
  4 siblings, 0 replies; 8+ messages in thread
From: Bastian Koppelmann @ 2014-11-13 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, rth

Add instructions of RLC opcode format.
Add helper psw_write/read.
Add microcode generator gen_mtcr/mfcr, which loads/stores a value to a core special function register, which are defined in csfr.def

Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
---
 target-tricore/csfr.def          | 124 +++++++++++++++++++++++++++++++++++++++
 target-tricore/helper.h          |   3 +
 target-tricore/op_helper.c       |  11 ++++
 target-tricore/translate.c       | 113 +++++++++++++++++++++++++++++++++++
 target-tricore/tricore-opcodes.h |   1 +
 5 files changed, 252 insertions(+)
 create mode 100644 target-tricore/csfr.def

diff --git a/target-tricore/csfr.def b/target-tricore/csfr.def
new file mode 100644
index 0000000..5b219b4
--- /dev/null
+++ b/target-tricore/csfr.def
@@ -0,0 +1,124 @@
+/* A(ll) access permited
+   R(ead only) access
+   E(nd init protected) access
+
+   A|R|E(offset, register, feature introducing reg)
+
+   NOTE: PSW is handled as a special case in gen_mtcr/mfcr */
+
+A(0xfe00, PCXI, TRICORE_FEATURE_13)
+A(0xfe08, PC, TRICORE_FEATURE_13)
+A(0xfe14, SYSCON, TRICORE_FEATURE_13)
+R(0xfe18, CPU_ID, TRICORE_FEATURE_13)
+E(0xfe20, BIV, TRICORE_FEATURE_13)
+E(0xfe24, BTV, TRICORE_FEATURE_13)
+E(0xfe28, ISP, TRICORE_FEATURE_13)
+A(0xfe2c, ICR, TRICORE_FEATURE_13)
+A(0xfe38, FCX, TRICORE_FEATURE_13)
+A(0xfe3c, LCX, TRICORE_FEATURE_13)
+E(0x9400, COMPAT, TRICORE_FEATURE_131)
+/* memory protection register */
+A(0xC000, DPR0_0L, TRICORE_FEATURE_13)
+A(0xC004, DPR0_0U, TRICORE_FEATURE_13)
+A(0xC008, DPR0_1L, TRICORE_FEATURE_13)
+A(0xC00C, DPR0_1U, TRICORE_FEATURE_13)
+A(0xC010, DPR0_2L, TRICORE_FEATURE_13)
+A(0xC014, DPR0_2U, TRICORE_FEATURE_13)
+A(0xC018, DPR0_3L, TRICORE_FEATURE_13)
+A(0xC01C, DPR0_3U, TRICORE_FEATURE_13)
+A(0xC400, DPR1_0L, TRICORE_FEATURE_13)
+A(0xC404, DPR1_0U, TRICORE_FEATURE_13)
+A(0xC408, DPR1_1L, TRICORE_FEATURE_13)
+A(0xC40C, DPR1_1U, TRICORE_FEATURE_13)
+A(0xC410, DPR1_2L, TRICORE_FEATURE_13)
+A(0xC414, DPR1_2U, TRICORE_FEATURE_13)
+A(0xC418, DPR1_3L, TRICORE_FEATURE_13)
+A(0xC41C, DPR1_3U, TRICORE_FEATURE_13)
+A(0xC800, DPR2_0L, TRICORE_FEATURE_13)
+A(0xC804, DPR2_0U, TRICORE_FEATURE_13)
+A(0xC808, DPR2_1L, TRICORE_FEATURE_13)
+A(0xC80C, DPR2_1U, TRICORE_FEATURE_13)
+A(0xC810, DPR2_2L, TRICORE_FEATURE_13)
+A(0xC814, DPR2_2U, TRICORE_FEATURE_13)
+A(0xC818, DPR2_3L, TRICORE_FEATURE_13)
+A(0xC81C, DPR2_3U, TRICORE_FEATURE_13)
+A(0xCC00, DPR3_0L, TRICORE_FEATURE_13)
+A(0xCC04, DPR3_0U, TRICORE_FEATURE_13)
+A(0xCC08, DPR3_1L, TRICORE_FEATURE_13)
+A(0xCC0C, DPR3_1U, TRICORE_FEATURE_13)
+A(0xCC10, DPR3_2L, TRICORE_FEATURE_13)
+A(0xCC14, DPR3_2U, TRICORE_FEATURE_13)
+A(0xCC18, DPR3_3L, TRICORE_FEATURE_13)
+A(0xCC1C, DPR3_3U, TRICORE_FEATURE_13)
+A(0xD000, CPR0_0L, TRICORE_FEATURE_13)
+A(0xD004, CPR0_0U, TRICORE_FEATURE_13)
+A(0xD008, CPR0_1L, TRICORE_FEATURE_13)
+A(0xD00C, CPR0_1U, TRICORE_FEATURE_13)
+A(0xD010, CPR0_2L, TRICORE_FEATURE_13)
+A(0xD014, CPR0_2U, TRICORE_FEATURE_13)
+A(0xD018, CPR0_3L, TRICORE_FEATURE_13)
+A(0xD01C, CPR0_3U, TRICORE_FEATURE_13)
+A(0xD400, CPR1_0L, TRICORE_FEATURE_13)
+A(0xD404, CPR1_0U, TRICORE_FEATURE_13)
+A(0xD408, CPR1_1L, TRICORE_FEATURE_13)
+A(0xD40C, CPR1_1U, TRICORE_FEATURE_13)
+A(0xD410, CPR1_2L, TRICORE_FEATURE_13)
+A(0xD414, CPR1_2U, TRICORE_FEATURE_13)
+A(0xD418, CPR1_3L, TRICORE_FEATURE_13)
+A(0xD41C, CPR1_3U, TRICORE_FEATURE_13)
+A(0xD800, CPR2_0L, TRICORE_FEATURE_13)
+A(0xD804, CPR2_0U, TRICORE_FEATURE_13)
+A(0xD808, CPR2_1L, TRICORE_FEATURE_13)
+A(0xD80C, CPR2_1U, TRICORE_FEATURE_13)
+A(0xD810, CPR2_2L, TRICORE_FEATURE_13)
+A(0xD814, CPR2_2U, TRICORE_FEATURE_13)
+A(0xD818, CPR2_3L, TRICORE_FEATURE_13)
+A(0xD81C, CPR2_3U, TRICORE_FEATURE_13)
+A(0xDC00, CPR3_0L, TRICORE_FEATURE_13)
+A(0xDC04, CPR3_0U, TRICORE_FEATURE_13)
+A(0xDC08, CPR3_1L, TRICORE_FEATURE_13)
+A(0xDC0C, CPR3_1U, TRICORE_FEATURE_13)
+A(0xDC10, CPR3_2L, TRICORE_FEATURE_13)
+A(0xDC14, CPR3_2U, TRICORE_FEATURE_13)
+A(0xDC18, CPR3_3L, TRICORE_FEATURE_13)
+A(0xDC1C, CPR3_3U, TRICORE_FEATURE_13)
+A(0xE000, DPM0, TRICORE_FEATURE_13)
+A(0xE080, DPM1, TRICORE_FEATURE_13)
+A(0xE100, DPM2, TRICORE_FEATURE_13)
+A(0xE180, DPM3, TRICORE_FEATURE_13)
+A(0xE200, CPM0, TRICORE_FEATURE_13)
+A(0xE280, CPM1, TRICORE_FEATURE_13)
+A(0xE300, CPM2, TRICORE_FEATURE_13)
+A(0xE380, CPM3, TRICORE_FEATURE_13)
+/* memory Managment Registers */
+A(0x8000, MMU_CON, TRICORE_FEATURE_13)
+A(0x8004, MMU_ASI, TRICORE_FEATURE_13)
+A(0x800C, MMU_TVA, TRICORE_FEATURE_13)
+A(0x8010, MMU_TPA, TRICORE_FEATURE_13)
+A(0x8014, MMU_TPX, TRICORE_FEATURE_13)
+A(0x8018, MMU_TFA, TRICORE_FEATURE_13)
+E(0x9004, BMACON, TRICORE_FEATURE_131)
+E(0x900C, SMACON, TRICORE_FEATURE_131)
+A(0x9020, DIEAR, TRICORE_FEATURE_131)
+A(0x9024, DIETR, TRICORE_FEATURE_131)
+A(0x9028, CCDIER, TRICORE_FEATURE_131)
+E(0x9044, MIECON, TRICORE_FEATURE_131)
+A(0x9210, PIEAR, TRICORE_FEATURE_131)
+A(0x9214, PIETR, TRICORE_FEATURE_131)
+A(0x9218, CCPIER, TRICORE_FEATURE_131)
+/* debug registers */
+A(0xFD00, DBGSR, TRICORE_FEATURE_13)
+A(0xFD08, EXEVT, TRICORE_FEATURE_13)
+A(0xFD0C, CREVT, TRICORE_FEATURE_13)
+A(0xFD10, SWEVT, TRICORE_FEATURE_13)
+A(0xFD20, TR0EVT, TRICORE_FEATURE_13)
+A(0xFD24, TR1EVT, TRICORE_FEATURE_13)
+A(0xFD40, DMS, TRICORE_FEATURE_13)
+A(0xFD44, DCX, TRICORE_FEATURE_13)
+A(0xFD48, DBGTCR, TRICORE_FEATURE_131)
+A(0xFC00, CCTRL, TRICORE_FEATURE_131)
+A(0xFC04, CCNT, TRICORE_FEATURE_131)
+A(0xFC08, ICNT, TRICORE_FEATURE_131)
+A(0xFC0C, M1CNT, TRICORE_FEATURE_131)
+A(0xFC10, M2CNT, TRICORE_FEATURE_131)
+A(0xFC14, M3CNT, TRICORE_FEATURE_131)
diff --git a/target-tricore/helper.h b/target-tricore/helper.h
index 4893060..2eb33ea 100644
--- a/target-tricore/helper.h
+++ b/target-tricore/helper.h
@@ -36,3 +36,6 @@ DEF_HELPER_2(stucx, void, env, i32)
 /* Address mode helper */
 DEF_HELPER_1(br_update, i32, i32)
 DEF_HELPER_2(circ_update, i32, i32, i32)
+/* PSW cache helper */
+DEF_HELPER_2(psw_write, void, env, i32)
+DEF_HELPER_1(psw_read, i32, env)
diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c
index d8d57b0..0b6b471 100644
--- a/target-tricore/op_helper.c
+++ b/target-tricore/op_helper.c
@@ -536,6 +536,17 @@ void helper_stucx(CPUTriCoreState *env, uint32_t ea)
     save_context_upper(env, ea);
 }
 
+void helper_psw_write(CPUTriCoreState *env, uint32_t arg)
+{
+    psw_write(env, arg);
+}
+
+uint32_t helper_psw_read(CPUTriCoreState *env)
+{
+    return psw_read(env);
+}
+
+
 static inline void QEMU_NORETURN do_raise_exception_err(CPUTriCoreState *env,
                                                         uint32_t exception,
                                                         int error_code,
diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index 689596f..fdc9ade 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -233,6 +233,63 @@ static void gen_swap(DisasContext *ctx, int reg, TCGv ea)
     tcg_temp_free(temp);
 }
 
+/* We generate loads and store to core special function register (csfr) through
+   the function gen_mfcr and gen_mtcr. To handle access permissions, we use 3
+   makros R, A and E, which allow read-only, all and endinit protected access.
+   These makros also specify in which ISA version the csfr was introduced. */
+#define R(ADDRESS, REG, FEATURE)                                         \
+    case ADDRESS:                                                        \
+        if (tricore_feature(env, FEATURE)) {                             \
+            tcg_gen_ld_tl(ret, cpu_env, offsetof(CPUTriCoreState, REG)); \
+        }                                                                \
+        break;
+#define A(ADDRESS, REG, FEATURE) R(ADDRESS, REG, FEATURE)
+#define E(ADDRESS, REG, FEATURE) R(ADDRESS, REG, FEATURE)
+static inline void gen_mfcr(CPUTriCoreState *env, TCGv ret, int32_t offset)
+{
+    /* since we're caching PSW make this a special case */
+    if (offset == 0xfe04) {
+        gen_helper_psw_read(ret, cpu_env);
+    } else {
+        switch (offset) {
+#include "csfr.def"
+        }
+    }
+}
+#undef R
+#undef A
+#undef E
+
+#define R(ADDRESS, REG, FEATURE) /* don't gen writes to read-only reg,
+                                    since no execption occurs */
+#define A(ADDRESS, REG, FEATURE) R(ADDRESS, REG, FEATURE)                \
+    case ADDRESS:                                                        \
+        if (tricore_feature(env, FEATURE)) {                             \
+            tcg_gen_st_tl(r1, cpu_env, offsetof(CPUTriCoreState, REG));  \
+        }                                                                \
+        break;
+/* Endinit protected registers
+   TODO: Since the endinit bit is in a register of a not yet implemented
+         watchdog device, we handle endinit protected registers like
+         all-access registers for now. */
+#define E(ADDRESS, REG, FEATURE) A(ADDRESS, REG, FEATURE)
+static inline void gen_mtcr(CPUTriCoreState *env, DisasContext *ctx, TCGv r1,
+                            int32_t offset)
+{
+    if (ctx->hflags & TRICORE_HFLAG_SM) {
+        /* since we're caching PSW make this a special case */
+        if (offset == 0xfe04) {
+            gen_helper_psw_write(cpu_env, r1);
+        } else {
+            switch (offset) {
+#include "csfr.def"
+            }
+        }
+    } else {
+        /* generate privilege trap */
+    }
+}
+
 /* Functions for arithmetic instructions  */
 
 static inline void gen_add_d(TCGv ret, TCGv r1, TCGv r2)
@@ -3227,6 +3284,50 @@ static void decode_rcrw_insert(CPUTriCoreState *env, DisasContext *ctx)
     tcg_temp_free(temp2);
 }
 
+/* RLC format */
+
+static void decode_rlc_opc(CPUTriCoreState *env, DisasContext *ctx,
+                           uint32_t op1)
+{
+    int32_t const16;
+    int r1, r2;
+
+    const16 = MASK_OP_RLC_CONST16_SEXT(ctx->opcode);
+    r1      = MASK_OP_RLC_S1(ctx->opcode);
+    r2      = MASK_OP_RLC_D(ctx->opcode);
+
+    switch (op1) {
+    case OPC1_32_RLC_ADDI:
+        gen_addi_CC(cpu_gpr_d[r2], cpu_gpr_d[r1], const16);
+        break;
+    case OPC1_32_RLC_ADDIH:
+        gen_addi_CC(cpu_gpr_d[r2], cpu_gpr_d[r1], const16 << 16);
+        break;
+    case OPC1_32_RLC_ADDIH_A:
+        tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r1], const16 << 16);
+        break;
+    case OPC1_32_RLC_MFCR:
+        gen_mfcr(env, cpu_gpr_d[r2], const16);
+        break;
+    case OPC1_32_RLC_MOV:
+        tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
+        break;
+    case OPC1_32_RLC_MOV_U:
+        const16 = MASK_OP_RLC_CONST16(ctx->opcode);
+        tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
+        break;
+    case OPC1_32_RLC_MOV_H:
+        tcg_gen_movi_tl(cpu_gpr_d[r2], const16 << 16);
+        break;
+    case OPC1_32_RLC_MOVH_A:
+        tcg_gen_movi_tl(cpu_gpr_a[r2], const16 << 16);
+        break;
+    case OPC1_32_RLC_MTCR:
+        gen_mtcr(env, ctx, cpu_gpr_d[r2], const16);
+        break;
+    }
+}
+
 static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
 {
     int op1;
@@ -3435,6 +3536,18 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
     case OPCM_32_RCRW_MASK_INSERT:
         decode_rcrw_insert(env, ctx);
         break;
+/* RLC Format */
+    case OPC1_32_RLC_ADDI:
+    case OPC1_32_RLC_ADDIH:
+    case OPC1_32_RLC_ADDIH_A:
+    case OPC1_32_RLC_MFCR:
+    case OPC1_32_RLC_MOV:
+    case OPC1_32_RLC_MOV_U:
+    case OPC1_32_RLC_MOV_H:
+    case OPC1_32_RLC_MOVH_A:
+    case OPC1_32_RLC_MTCR:
+        decode_rlc_opc(env, ctx, op1);
+        break;
     }
 }
 
diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h
index 9b042e4..bafc8fb 100644
--- a/target-tricore/tricore-opcodes.h
+++ b/target-tricore/tricore-opcodes.h
@@ -192,6 +192,7 @@
 
 #define MASK_OP_RLC_D(op)       MASK_OP_META_D(op)
 #define MASK_OP_RLC_CONST16(op) MASK_BITS_SHIFT(op, 12, 27)
+#define MASK_OP_RLC_CONST16_SEXT(op) MASK_BITS_SHIFT_SEXT(op, 12, 27)
 #define MASK_OP_RLC_S1(op)      MASK_OP_META_S1(op)
 
 /* RR  Format */
-- 
2.1.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH v2 4/4] target-tricore: Add instructions of RCR opcode format
  2014-11-13 17:12 [Qemu-devel] [PATCH v2 0/4] Add TriCore RCPW, RCRR, RCRW, RLC and RCR instructions Bastian Koppelmann
                   ` (2 preceding siblings ...)
  2014-11-13 17:12 ` [Qemu-devel] [PATCH v2 3/4] target-tricore: Add instructions of RLC " Bastian Koppelmann
@ 2014-11-13 17:12 ` Bastian Koppelmann
  2014-11-14 13:39   ` Richard Henderson
  2014-11-14 13:41 ` [Qemu-devel] [PATCH v2 0/4] Add TriCore RCPW, RCRR, RCRW, RLC and RCR instructions Richard Henderson
  4 siblings, 1 reply; 8+ messages in thread
From: Bastian Koppelmann @ 2014-11-13 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, rth

Add instructions of RCR opcode format.
Add helper for madd32/64_ssov and madd32/64_suov.
Add helper for msub32/64_ssov and msub32/64_suov.
Add microcode generator function madd/msub for 32bit and 64bit, which calculate a mul and a add/sub.
OPC2_32_RCR_MSUB_U_32 -> OPC2_32_RCR_MSUB_U_32.

Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
---
 target-tricore/helper.h          |   8 +
 target-tricore/op_helper.c       | 192 +++++++++++++++
 target-tricore/translate.c       | 493 +++++++++++++++++++++++++++++++++++++++
 target-tricore/tricore-opcodes.h |   3 +-
 4 files changed, 695 insertions(+), 1 deletion(-)

diff --git a/target-tricore/helper.h b/target-tricore/helper.h
index 2eb33ea..6c07bd7 100644
--- a/target-tricore/helper.h
+++ b/target-tricore/helper.h
@@ -24,6 +24,14 @@ DEF_HELPER_3(mul_ssov, i32, env, i32, i32)
 DEF_HELPER_3(mul_suov, i32, env, i32, i32)
 DEF_HELPER_3(sha_ssov, i32, env, i32, i32)
 DEF_HELPER_3(absdif_ssov, i32, env, i32, i32)
+DEF_HELPER_4(madd32_ssov, i32, env, i32, i32, i32)
+DEF_HELPER_4(madd32_suov, i32, env, i32, i32, i32)
+DEF_HELPER_4(madd64_ssov, i64, env, i32, i64, i32)
+DEF_HELPER_4(madd64_suov, i64, env, i32, i64, i32)
+DEF_HELPER_4(msub32_ssov, i32, env, i32, i32, i32)
+DEF_HELPER_4(msub32_suov, i32, env, i32, i32, i32)
+DEF_HELPER_4(msub64_ssov, i64, env, i32, i64, i32)
+DEF_HELPER_4(msub64_suov, i64, env, i32, i64, i32)
 /* CSA */
 DEF_HELPER_2(call, void, env, i32)
 DEF_HELPER_1(ret, void, env)
diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c
index 0b6b471..22fa452 100644
--- a/target-tricore/op_helper.c
+++ b/target-tricore/op_helper.c
@@ -56,6 +56,16 @@ uint32_t helper_circ_update(uint32_t reg, uint32_t off)
     return reg - index + new_index;
 }

+static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
+{
+    *plow += a;
+    /* carry test */
+    if (*plow < a) {
+        (*phigh)++;
+    }
+    *phigh += b;
+}
+
 #define SSOV(env, ret, arg, len) do {               \
     int64_t max_pos = INT##len ##_MAX;              \
     int64_t max_neg = INT##len ##_MIN;              \
@@ -198,6 +208,188 @@ target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1,
     SSOV(env, ret, result, 32);
     return ret;
 }
+
+target_ulong helper_madd32_ssov(CPUTriCoreState *env, target_ulong r1,
+                                target_ulong r2, target_ulong r3)
+{
+    target_ulong ret;
+    int64_t t1 = sextract64(r1, 0, 32);
+    int64_t t2 = sextract64(r2, 0, 32);
+    int64_t t3 = sextract64(r3, 0, 32);
+    int64_t result;
+
+    result = t2 + (t1 * t3);
+    SSOV(env, ret, result, 32);
+    return ret;
+}
+
+target_ulong helper_madd32_suov(CPUTriCoreState *env, target_ulong r1,
+                                target_ulong r2, target_ulong r3)
+{
+    target_ulong ret;
+    uint64_t t1 = extract64(r1, 0, 32);
+    uint64_t t2 = extract64(r2, 0, 32);
+    uint64_t t3 = extract64(r3, 0, 32);
+    int64_t result;
+
+    result = t2 + (t1 * t3);
+    SUOV(env, ret, result, 32);
+    return ret;
+}
+
+uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1,
+                            uint64_t r2, target_ulong r3)
+{
+    uint64_t ret_low, ret_high;
+    uint64_t r2_high;
+    int64_t t1 = sextract64(r1, 0, 32);
+    int64_t t3 = sextract64(r3, 0, 32);
+
+    muls64(&ret_low, &ret_high, t1, t3);
+    r2_high = ((int64_t)r2 >> 63);
+    add128(&ret_low, &ret_high, r2, r2_high);
+
+    /* check for saturate */
+    t1 = (int64_t)ret_low >> 63;
+    if (t1 != ret_high) {
+        env->PSW_USB_V = (1 << 31);
+        env->PSW_USB_SV = (1 << 31);
+        if (t1 == 0x0) {
+            ret_low = INT64_MIN;
+        } else {
+            ret_low = INT64_MAX;
+        }
+    } else {
+        env->PSW_USB_V = 0;
+    }
+    t1 = ret_low >> 32;
+    env->PSW_USB_AV = t1 ^ t1 * 2u;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+    return ret_low;
+}
+
+uint64_t helper_madd64_suov(CPUTriCoreState *env, target_ulong r1,
+                            uint64_t r2, target_ulong r3)
+{
+    uint64_t ret_low, ret_high;
+    uint64_t t1 = extract64(r1, 0, 32);
+    uint64_t t3 = extract64(r3, 0, 32);
+
+    mulu64(&ret_low, &ret_high, t1, t3);
+    add128(&ret_low, &ret_high, r2, 0);
+
+    if (ret_high != 0) {
+        env->PSW_USB_V = (1 << 31);
+        env->PSW_USB_SV = (1 << 31);
+        ret_low = UINT64_MAX;
+    } else if ((ret_high & (1LL << 63)) != 0) {
+        ret_low = 0;
+        env->PSW_USB_V = (1 << 31);
+        env->PSW_USB_SV = (1 << 31);
+    } else {
+        env->PSW_USB_V = 0;
+    }
+    t1 = ret_low >> 32;
+    env->PSW_USB_AV = t1 ^ t1 * 2u;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+    return ret_low;
+}
+
+target_ulong helper_msub32_ssov(CPUTriCoreState *env, target_ulong r1,
+                                target_ulong r2, target_ulong r3)
+{
+    target_ulong ret;
+    int64_t t1 = sextract64(r1, 0, 32);
+    int64_t t2 = sextract64(r2, 0, 32);
+    int64_t t3 = sextract64(r3, 0, 32);
+    int64_t result;
+
+    result = t2 - (t1 * t3);
+    SSOV(env, ret, result, 32);
+    return ret;
+}
+
+target_ulong helper_msub32_suov(CPUTriCoreState *env, target_ulong r1,
+                                target_ulong r2, target_ulong r3)
+{
+    target_ulong ret;
+    int64_t t1 = extract64(r1, 0, 32);
+    int64_t t2 = extract64(r2, 0, 32);
+    int64_t t3 = extract64(r3, 0, 32);
+    int64_t result;
+
+    result = t2 - (t1 * t3);
+    SUOV(env, ret, result, 32);
+    return ret;
+}
+
+uint64_t helper_msub64_ssov(CPUTriCoreState *env, target_ulong r1,
+                            uint64_t r2, target_ulong r3)
+{
+    uint64_t ret_low, ret_high;
+    int64_t t1 = sextract64(r1, 0, 32);
+    int64_t t3 = sextract64(r3, 0, 32);
+    uint64_t r2_high;
+
+    r2_high = (int64_t)r2 >> 63;
+    muls64(&ret_low, &ret_high, t1, t3);
+    ret_low = ~ret_low;
+    ret_high = ~ret_high;
+    add128(&ret_low, &ret_high, 1, 0);
+    add128(&ret_low, &ret_high, r2, r2_high);
+
+    /* check for saturate */
+    t1 = (int64_t)ret_low >> 63;
+    if (t1 != ret_high) {
+        env->PSW_USB_V = (1 << 31);
+        env->PSW_USB_SV = (1 << 31);
+        if (t1 == 0x0) {
+            ret_low = INT64_MIN;
+        } else {
+            ret_low = INT64_MAX;
+        }
+    } else {
+        env->PSW_USB_V = 0;
+    }
+    t1 = ret_low >> 32;
+    env->PSW_USB_AV = t1 ^ t1 * 2u;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+    return ret_low;
+}
+
+uint64_t helper_msub64_suov(CPUTriCoreState *env, target_ulong r1,
+                            uint64_t r2, target_ulong r3)
+{
+    uint64_t ret_low, ret_high;
+    uint64_t t1 = extract64(r1, 0, 32);
+    uint64_t t3 = extract64(r3, 0, 32);
+
+    mulu64(&ret_low, &ret_high, t1, t3);
+    ret_low = ~ret_low;
+    ret_high = ~ret_high;
+    add128(&ret_low, &ret_high, 1, 0);
+    add128(&ret_low, &ret_high, r2, 0);
+
+    if (ret_high != 0) {
+        if ((ret_high & (1LL << 63)) == 0) {
+            env->PSW_USB_V = (1 << 31);
+            env->PSW_USB_SV = (1 << 31);
+            ret_low = UINT64_MAX;
+        } else if ((ret_high & (1LL << 63)) != 0) {
+            ret_low = 0;
+            env->PSW_USB_V = (1 << 31);
+            env->PSW_USB_SV = (1 << 31);
+        }
+    } else {
+        env->PSW_USB_V = 0;
+    }
+    t1 = ret_low >> 32;
+    env->PSW_USB_AV = t1 ^ t1 * 2u;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+    return ret_low;
+}
+
 /* context save area (CSA) related helpers */

 static int cdc_increment(target_ulong *psw)
diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index fdc9ade..02279f4 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -316,6 +316,275 @@ static inline void gen_add_d(TCGv ret, TCGv r1, TCGv r2)
     tcg_temp_free(t0);
 }

+/* ret = r2 + (r1 * r3); */
+static inline void gen_madd32_d(TCGv ret, TCGv r1, TCGv r2, TCGv r3)
+{
+    TCGv_i64 t1 = tcg_temp_new_i64();
+    TCGv_i64 t2 = tcg_temp_new_i64();
+    TCGv_i64 t3 = tcg_temp_new_i64();
+
+    tcg_gen_ext_i32_i64(t1, r1);
+    tcg_gen_ext_i32_i64(t2, r2);
+    tcg_gen_ext_i32_i64(t3, r3);
+
+    tcg_gen_mul_i64(t1, t1, t3);
+    tcg_gen_add_i64(t1, t2, t1);
+
+    tcg_gen_trunc_i64_i32(ret, t1);
+    /* calc V
+       t1 > 0x7fffffff */
+    tcg_gen_setcondi_i64(TCG_COND_GT, t3, t1, 0x7fffffffLL);
+    /* t1 < -0x80000000 */
+    tcg_gen_setcondi_i64(TCG_COND_LT, t2, t1, -0x80000000LL);
+    tcg_gen_or_i64(t2, t2, t3);
+    tcg_gen_trunc_i64_i32(cpu_PSW_V, t2);
+    tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+    /* Calc SV bit */
+    tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+    /* Calc AV/SAV bits */
+    tcg_gen_add_tl(cpu_PSW_AV, ret, ret);
+    tcg_gen_xor_tl(cpu_PSW_AV, ret, cpu_PSW_AV);
+    /* calc SAV */
+    tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+
+    tcg_temp_free_i64(t1);
+    tcg_temp_free_i64(t2);
+    tcg_temp_free_i64(t3);
+}
+
+static inline void gen_maddi32_d(TCGv ret, TCGv r1, TCGv r2, int32_t con)
+{
+    TCGv temp = tcg_const_i32(con);
+    gen_madd32_d(ret, r1, r2, temp);
+    tcg_temp_free(temp);
+}
+
+static inline void
+gen_madd64_d(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high,
+             TCGv r3)
+{
+    TCGv_i64 t1 = tcg_temp_new_i64();
+    TCGv_i64 t2 = tcg_temp_new_i64();
+    TCGv_i64 t3 = tcg_temp_new_i64();
+    TCGv_i64 t4 = tcg_temp_new_i64();
+
+    tcg_gen_ext_i32_i64(t3, r3);
+    tcg_gen_concat_i32_i64(t2, r2_low, r2_high);
+    /* extend the sign for r2 to high 64 bits */
+    tcg_gen_sari_i64(t4, t2, 63);
+    tcg_gen_ext_i32_i64(t1, r1);
+
+    tcg_gen_muls2_i64(t1, t3, t1, t3);
+    tcg_gen_add2_i64(t1, t3, t2, t4, t1, t3);
+
+    tcg_gen_extr_i64_i32(ret_low, ret_high, t1);
+    /* calc V */
+    tcg_gen_sari_i64(t1, t1, 63);
+    tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, t3);
+    tcg_gen_trunc_i64_i32(cpu_PSW_V, t1);
+    tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+    /* Calc SV bit */
+    tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+    /* Calc AV/SAV bits */
+    tcg_gen_add_tl(cpu_PSW_AV, ret_high, ret_high);
+    tcg_gen_xor_tl(cpu_PSW_AV, ret_high, cpu_PSW_AV);
+    /* calc SAV */
+    tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+
+    tcg_temp_free_i64(t1);
+    tcg_temp_free_i64(t2);
+    tcg_temp_free_i64(t3);
+    tcg_temp_free_i64(t4);
+}
+
+static inline void
+gen_maddu64_d(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high,
+              TCGv r3)
+{
+    TCGv_i64 t1 = tcg_temp_new_i64();
+    TCGv_i64 t2 = tcg_temp_new_i64();
+    TCGv_i64 t3 = tcg_temp_new_i64();
+    TCGv_i64 t4 = tcg_const_i64(0);
+
+    tcg_gen_concat_i32_i64(t2, r2_low, r2_high);
+    tcg_gen_extu_i32_i64(t1, r1);
+    tcg_gen_extu_i32_i64(t3, r3);
+
+    tcg_gen_mulu2_i64(t1, t3, t1, t3);
+    tcg_gen_add2_i64(t1, t3, t2, t4, t1, t3);
+
+    tcg_gen_extr_i64_i32(ret_low, ret_high, t1);
+    /* calc V */
+    tcg_gen_setcond_i64(TCG_COND_NE, t1, t3, t4);
+    tcg_gen_trunc_i64_i32(cpu_PSW_V, t1);
+    tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+    /* Calc SV bit */
+    tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+    /* Calc AV/SAV bits */
+    tcg_gen_add_tl(cpu_PSW_AV, ret_high, ret_high);
+    tcg_gen_xor_tl(cpu_PSW_AV, ret_high, cpu_PSW_AV);
+    /* calc SAV */
+    tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+
+    tcg_temp_free_i64(t1);
+    tcg_temp_free_i64(t2);
+    tcg_temp_free_i64(t3);
+    tcg_temp_free_i64(t4);
+}
+
+static inline void
+gen_maddi64_d(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high,
+              int32_t con)
+{
+    TCGv temp = tcg_const_i32(con);
+    gen_madd64_d(ret_low, ret_high, r1, r2_low, r2_high, temp);
+    tcg_temp_free(temp);
+}
+
+static inline void
+gen_maddui64_d(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high,
+               int32_t con)
+{
+    TCGv temp = tcg_const_i32(con);
+    gen_maddu64_d(ret_low, ret_high, r1, r2_low, r2_high, temp);
+    tcg_temp_free(temp);
+}
+
+/* ret = r2 - (r1 * r3); */
+static inline void gen_msub32_d(TCGv ret, TCGv r1, TCGv r2, TCGv r3)
+{
+    TCGv_i64 t1 = tcg_temp_new_i64();
+    TCGv_i64 t2 = tcg_temp_new_i64();
+    TCGv_i64 t3 = tcg_temp_new_i64();
+
+    tcg_gen_ext_i32_i64(t1, r1);
+    tcg_gen_ext_i32_i64(t2, r2);
+    tcg_gen_ext_i32_i64(t3, r3);
+
+    tcg_gen_mul_i64(t1, t1, t3);
+    tcg_gen_sub_i64(t1, t2, t1);
+
+    tcg_gen_trunc_i64_i32(ret, t1);
+    /* calc V
+       t2 > 0x7fffffff */
+    tcg_gen_setcondi_i64(TCG_COND_GT, t3, t1, 0x7fffffffLL);
+    /* result < -0x80000000 */
+    tcg_gen_setcondi_i64(TCG_COND_LT, t2, t1, -0x80000000LL);
+    tcg_gen_or_i64(t2, t2, t3);
+    tcg_gen_trunc_i64_i32(cpu_PSW_V, t2);
+    tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+
+    /* Calc SV bit */
+    tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+    /* Calc AV/SAV bits */
+    tcg_gen_add_tl(cpu_PSW_AV, ret, ret);
+    tcg_gen_xor_tl(cpu_PSW_AV, ret, cpu_PSW_AV);
+    /* calc SAV */
+    tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+
+    tcg_temp_free_i64(t1);
+    tcg_temp_free_i64(t2);
+    tcg_temp_free_i64(t3);
+}
+
+static inline void gen_msubi32_d(TCGv ret, TCGv r1, TCGv r2, int32_t con)
+{
+    TCGv temp = tcg_const_i32(con);
+    gen_msub32_d(ret, r1, r2, temp);
+    tcg_temp_free(temp);
+}
+
+static inline void
+gen_msub64_d(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high,
+             TCGv r3)
+{
+    TCGv_i64 t1 = tcg_temp_new_i64();
+    TCGv_i64 t2 = tcg_temp_new_i64();
+    TCGv_i64 t3 = tcg_temp_new_i64();
+    TCGv_i64 t4 = tcg_temp_new_i64();
+
+    tcg_gen_concat_i32_i64(t2, r2_low, r2_high);
+    /* extend the sign for r2 to high 64 bits */
+    tcg_gen_sari_i64(t4, t2, 63);
+    tcg_gen_ext_i32_i64(t1, r1);
+    tcg_gen_ext_i32_i64(t3, r3);
+
+    tcg_gen_muls2_i64(t1, t3, t1, t3);
+    tcg_gen_sub2_i64(t1, t3, t2, t4, t1, t3);
+
+    tcg_gen_extr_i64_i32(ret_low, ret_high, t1);
+    /* calc V */
+    tcg_gen_sari_i64(t1, t1, 63);
+    tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, t3);
+    tcg_gen_trunc_i64_i32(cpu_PSW_V, t1);
+    tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+    /* Calc SV bit */
+    tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+    /* Calc AV/SAV bits */
+    tcg_gen_add_tl(cpu_PSW_AV, ret_high, ret_high);
+    tcg_gen_xor_tl(cpu_PSW_AV, ret_high, cpu_PSW_AV);
+    /* calc SAV */
+    tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+
+    tcg_temp_free_i64(t1);
+    tcg_temp_free_i64(t2);
+    tcg_temp_free_i64(t3);
+    tcg_temp_free_i64(t4);
+}
+
+static inline void
+gen_msubi64_d(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high,
+              int32_t con)
+{
+    TCGv temp = tcg_const_i32(con);
+    gen_msub64_d(ret_low, ret_high, r1, r2_low, r2_high, temp);
+    tcg_temp_free(temp);
+}
+
+static inline void
+gen_msubu64_d(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high,
+              TCGv r3)
+{
+    TCGv_i64 t1 = tcg_temp_new_i64();
+    TCGv_i64 t2 = tcg_temp_new_i64();
+    TCGv_i64 t3 = tcg_temp_new_i64();
+    TCGv_i64 t4 = tcg_const_i64(0);
+
+    tcg_gen_concat_i32_i64(t2, r2_low, r2_high);
+    tcg_gen_extu_i32_i64(t1, r1);
+    tcg_gen_extu_i32_i64(t3, r3);
+
+    tcg_gen_mulu2_i64(t1, t3, t1, t3);
+    tcg_gen_sub2_i64(t1, t3, t2, t4, t1, t3);
+
+    tcg_gen_extr_i64_i32(ret_low, ret_high, t1);
+    /* calc V */
+    tcg_gen_setcond_i64(TCG_COND_NE, t1, t3, t4);
+    tcg_gen_trunc_i64_i32(cpu_PSW_V, t1);
+    tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+    /* Calc SV bit */
+    tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+    /* Calc AV/SAV bits */
+    tcg_gen_add_tl(cpu_PSW_AV, ret_high, ret_high);
+    tcg_gen_xor_tl(cpu_PSW_AV, ret_high, cpu_PSW_AV);
+    /* calc SAV */
+    tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+
+    tcg_temp_free_i64(t1);
+    tcg_temp_free_i64(t2);
+    tcg_temp_free_i64(t3);
+    tcg_temp_free_i64(t4);
+}
+
+static inline void
+gen_msubui64_d(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high,
+               int32_t con)
+{
+    TCGv temp = tcg_const_i32(con);
+    gen_msubu64_d(ret_low, ret_high, r1, r2_low, r2_high, temp);
+    tcg_temp_free(temp);
+}
+
 static inline void gen_addi_d(TCGv ret, TCGv r1, target_ulong r2)
 {
     TCGv temp = tcg_const_i32(r2);
@@ -594,6 +863,86 @@ static inline void gen_mulsui_i32(TCGv ret, TCGv r1, int32_t con)
     gen_helper_mul_suov(ret, cpu_env, r1, temp);
     tcg_temp_free(temp);
 }
+/* gen_maddsi_32(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r3], const9); */
+static inline void gen_maddsi_32(TCGv ret, TCGv r1, TCGv r2, int32_t con)
+{
+    TCGv temp = tcg_const_i32(con);
+    gen_helper_madd32_ssov(ret, cpu_env, r1, r2, temp);
+    tcg_temp_free(temp);
+}
+
+static inline void gen_maddsui_32(TCGv ret, TCGv r1, TCGv r2, int32_t con)
+{
+    TCGv temp = tcg_const_i32(con);
+    gen_helper_madd32_suov(ret, cpu_env, r1, r2, temp);
+    tcg_temp_free(temp);
+}
+
+static inline void
+gen_maddsi_64(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high,
+              int32_t con)
+{
+    TCGv temp = tcg_const_i32(con);
+    TCGv_i64 temp64 = tcg_temp_new_i64();
+    tcg_gen_concat_i32_i64(temp64, r2_low, r2_high);
+    gen_helper_madd64_ssov(temp64, cpu_env, r1, temp64, temp);
+    tcg_gen_extr_i64_i32(ret_low, ret_high, temp64);
+    tcg_temp_free(temp);
+    tcg_temp_free_i64(temp64);
+}
+
+static inline void
+gen_maddsui_64(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high,
+               int32_t con)
+{
+    TCGv temp = tcg_const_i32(con);
+    TCGv_i64 temp64 = tcg_temp_new_i64();
+    tcg_gen_concat_i32_i64(temp64, r2_low, r2_high);
+    gen_helper_madd64_suov(temp64, cpu_env, r1, temp64, temp);
+    tcg_gen_extr_i64_i32(ret_low, ret_high, temp64);
+    tcg_temp_free(temp);
+    tcg_temp_free_i64(temp64);
+}
+
+static inline void gen_msubsi_32(TCGv ret, TCGv r1, TCGv r2, int32_t con)
+{
+    TCGv temp = tcg_const_i32(con);
+    gen_helper_msub32_ssov(ret, cpu_env, r1, r2, temp);
+    tcg_temp_free(temp);
+}
+
+static inline void gen_msubsui_32(TCGv ret, TCGv r1, TCGv r2, int32_t con)
+{
+    TCGv temp = tcg_const_i32(con);
+    gen_helper_msub32_suov(ret, cpu_env, r1, r2, temp);
+    tcg_temp_free(temp);
+}
+
+static inline void
+gen_msubsi_64(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high,
+              int32_t con)
+{
+    TCGv temp = tcg_const_i32(con);
+    TCGv_i64 temp64 = tcg_temp_new_i64();
+    tcg_gen_concat_i32_i64(temp64, r2_low, r2_high);
+    gen_helper_msub64_ssov(temp64, cpu_env, r1, temp64, temp);
+    tcg_gen_extr_i64_i32(ret_low, ret_high, temp64);
+    tcg_temp_free(temp);
+    tcg_temp_free_i64(temp64);
+}
+
+static inline void
+gen_msubsui_64(TCGv ret_low, TCGv ret_high, TCGv r1, TCGv r2_low, TCGv r2_high,
+               int32_t con)
+{
+    TCGv temp = tcg_const_i32(con);
+    TCGv_i64 temp64 = tcg_temp_new_i64();
+    tcg_gen_concat_i32_i64(temp64, r2_low, r2_high);
+    gen_helper_msub64_suov(temp64, cpu_env, r1, temp64, temp);
+    tcg_gen_extr_i64_i32(ret_low, ret_high, temp64);
+    tcg_temp_free(temp);
+    tcg_temp_free_i64(temp64);
+}

 static void gen_saturate(TCGv ret, TCGv arg, int32_t up, int32_t low)
 {
@@ -3284,6 +3633,140 @@ static void decode_rcrw_insert(CPUTriCoreState *env, DisasContext *ctx)
     tcg_temp_free(temp2);
 }

+/* RCR format */
+
+static void decode_rcr_cond_select(CPUTriCoreState *env, DisasContext *ctx)
+{
+    uint32_t op2;
+    int r1, r3, r4;
+    int32_t const9;
+
+    TCGv temp, temp2;
+
+    op2 = MASK_OP_RCR_OP2(ctx->opcode);
+    r1 = MASK_OP_RCR_S1(ctx->opcode);
+    const9 = MASK_OP_RCR_CONST9_SEXT(ctx->opcode);
+    r3 = MASK_OP_RCR_S3(ctx->opcode);
+    r4 = MASK_OP_RCR_D(ctx->opcode);
+
+    switch (op2) {
+    case OPC2_32_RCR_CADD:
+        gen_condi_add(TCG_COND_NE, cpu_gpr_d[r1], const9, cpu_gpr_d[r3],
+                      cpu_gpr_d[r4]);
+        break;
+    case OPC2_32_RCR_CADDN:
+        gen_condi_add(TCG_COND_EQ, cpu_gpr_d[r1], const9, cpu_gpr_d[r3],
+                      cpu_gpr_d[r4]);
+        break;
+    case OPC2_32_RCR_SEL:
+        temp = tcg_const_i32(0);
+        temp2 = tcg_const_i32(const9);
+        tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r4], temp,
+                           cpu_gpr_d[r1], temp2);
+        tcg_temp_free(temp);
+        tcg_temp_free(temp2);
+        break;
+    case OPC2_32_RCR_SELN:
+        temp = tcg_const_i32(0);
+        temp2 = tcg_const_i32(const9);
+        tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r4], temp,
+                           cpu_gpr_d[r1], temp2);
+        tcg_temp_free(temp);
+        tcg_temp_free(temp2);
+        break;
+    }
+}
+
+static void decode_rcr_madd(CPUTriCoreState *env, DisasContext *ctx)
+{
+    uint32_t op2;
+    int r1, r3, r4;
+    int32_t const9;
+
+
+    op2 = MASK_OP_RCR_OP2(ctx->opcode);
+    r1 = MASK_OP_RCR_S1(ctx->opcode);
+    const9 = MASK_OP_RCR_CONST9_SEXT(ctx->opcode);
+    r3 = MASK_OP_RCR_S3(ctx->opcode);
+    r4 = MASK_OP_RCR_D(ctx->opcode);
+
+    switch (op2) {
+    case OPC2_32_RCR_MADD_32:
+        gen_maddi32_d(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r3], const9);
+        break;
+    case OPC2_32_RCR_MADD_64:
+        gen_maddi64_d(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r1],
+                      cpu_gpr_d[r3], cpu_gpr_d[r3+1], const9);
+        break;
+    case OPC2_32_RCR_MADDS_32:
+        gen_maddsi_32(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r3], const9);
+        break;
+    case OPC2_32_RCR_MADDS_64:
+        gen_maddsi_64(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r1],
+                      cpu_gpr_d[r3], cpu_gpr_d[r3+1], const9);
+        break;
+    case OPC2_32_RCR_MADD_U_64:
+        const9 = MASK_OP_RCR_CONST9(ctx->opcode);
+        gen_maddui64_d(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r1],
+                       cpu_gpr_d[r3], cpu_gpr_d[r3+1], const9);
+        break;
+    case OPC2_32_RCR_MADDS_U_32:
+        const9 = MASK_OP_RCR_CONST9(ctx->opcode);
+        gen_maddsui_32(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r3], const9);
+        break;
+    case OPC2_32_RCR_MADDS_U_64:
+        const9 = MASK_OP_RCR_CONST9(ctx->opcode);
+        gen_maddsui_64(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r1],
+                       cpu_gpr_d[r3], cpu_gpr_d[r3+1], const9);
+        break;
+    }
+}
+
+static void decode_rcr_msub(CPUTriCoreState *env, DisasContext *ctx)
+{
+    uint32_t op2;
+    int r1, r3, r4;
+    int32_t const9;
+
+
+    op2 = MASK_OP_RCR_OP2(ctx->opcode);
+    r1 = MASK_OP_RCR_S1(ctx->opcode);
+    const9 = MASK_OP_RCR_CONST9_SEXT(ctx->opcode);
+    r3 = MASK_OP_RCR_S3(ctx->opcode);
+    r4 = MASK_OP_RCR_D(ctx->opcode);
+
+    switch (op2) {
+    case OPC2_32_RCR_MSUB_32:
+        gen_msubi32_d(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r3], const9);
+        break;
+    case OPC2_32_RCR_MSUB_64:
+        gen_msubi64_d(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r1],
+                      cpu_gpr_d[r3], cpu_gpr_d[r3+1], const9);
+        break;
+    case OPC2_32_RCR_MSUBS_32:
+        gen_msubsi_32(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r3], const9);
+        break;
+    case OPC2_32_RCR_MSUBS_64:
+        gen_msubsi_64(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r1],
+                      cpu_gpr_d[r3], cpu_gpr_d[r3+1], const9);
+        break;
+    case OPC2_32_RCR_MSUB_U_64:
+        const9 = MASK_OP_RCR_CONST9(ctx->opcode);
+        gen_msubui64_d(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r1],
+                       cpu_gpr_d[r3], cpu_gpr_d[r3+1], const9);
+        break;
+    case OPC2_32_RCR_MSUBS_U_32:
+        const9 = MASK_OP_RCR_CONST9(ctx->opcode);
+        gen_msubsui_32(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r3], const9);
+        break;
+    case OPC2_32_RCR_MSUBS_U_64:
+        const9 = MASK_OP_RCR_CONST9(ctx->opcode);
+        gen_msubsui_64(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r1],
+                       cpu_gpr_d[r3], cpu_gpr_d[r3+1], const9);
+        break;
+    }
+}
+
 /* RLC format */

 static void decode_rlc_opc(CPUTriCoreState *env, DisasContext *ctx,
@@ -3536,6 +4019,16 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
     case OPCM_32_RCRW_MASK_INSERT:
         decode_rcrw_insert(env, ctx);
         break;
+/* RCR Format */
+    case OPCM_32_RCR_COND_SELECT:
+        decode_rcr_cond_select(env, ctx);
+        break;
+    case OPCM_32_RCR_MADD:
+        decode_rcr_madd(env, ctx);
+        break;
+    case OPCM_32_RCR_MSUB:
+        decode_rcr_msub(env, ctx);
+        break;
 /* RLC Format */
     case OPC1_32_RLC_ADDI:
     case OPC1_32_RLC_ADDIH:
diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h
index bafc8fb..0a9122c 100644
--- a/target-tricore/tricore-opcodes.h
+++ b/target-tricore/tricore-opcodes.h
@@ -169,6 +169,7 @@
 #define MASK_OP_RCR_S3(op)     MASK_BITS_SHIFT(op, 24, 27)
 #define MASK_OP_RCR_OP2(op)    MASK_BITS_SHIFT(op, 21, 23)
 #define MASK_OP_RCR_CONST9(op) MASK_BITS_SHIFT(op, 12, 20)
+#define MASK_OP_RCR_CONST9_SEXT(op) MASK_BITS_SHIFT_SEXT(op, 12, 20)
 #define MASK_OP_RCR_S1(op)     MASK_OP_META_S1(op)

 /* RCRR Format */
@@ -945,7 +946,7 @@ enum {
     OPC2_32_RCR_MSUB_64                          = 0x03,
     OPC2_32_RCR_MSUBS_32                         = 0x05,
     OPC2_32_RCR_MSUBS_64                         = 0x07,
-    OPC2_32_RCR_MSUB_U_32                        = 0x02,
+    OPC2_32_RCR_MSUB_U_64                        = 0x02,
     OPC2_32_RCR_MSUBS_U_32                       = 0x04,
     OPC2_32_RCR_MSUBS_U_64                       = 0x06,
 };
--
2.1.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH v2 4/4] target-tricore: Add instructions of RCR opcode format
  2014-11-13 17:12 ` [Qemu-devel] [PATCH v2 4/4] target-tricore: Add instructions of RCR " Bastian Koppelmann
@ 2014-11-14 13:39   ` Richard Henderson
  2014-11-19 13:35     ` Bastian Koppelmann
  0 siblings, 1 reply; 8+ messages in thread
From: Richard Henderson @ 2014-11-14 13:39 UTC (permalink / raw)
  To: Bastian Koppelmann, qemu-devel; +Cc: peter.maydell

On 11/13/2014 06:12 PM, Bastian Koppelmann wrote:
> +    tcg_gen_ext_i32_i64(t3, r3);
> +    tcg_gen_concat_i32_i64(t2, r2_low, r2_high);
> +    /* extend the sign for r2 to high 64 bits */
> +    tcg_gen_sari_i64(t4, t2, 63);
> +    tcg_gen_ext_i32_i64(t1, r1);
> +
> +    tcg_gen_muls2_i64(t1, t3, t1, t3);
> +    tcg_gen_add2_i64(t1, t3, t2, t4, t1, t3);
> +

I don't believe that you need 128 bit arithemetic for multiply-accumulate,
either here or elsewhere (e.g. msub).

Looking at unsigned, the maximum result of the multiply is 2*(2^n-1), or 2^(2n)
- 2^(n+1).  Which means that the accumulate with a 2^n-1 value cannot overflow
a double-word intermediate result.


r~

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH v2 0/4] Add TriCore RCPW, RCRR, RCRW, RLC and RCR instructions
  2014-11-13 17:12 [Qemu-devel] [PATCH v2 0/4] Add TriCore RCPW, RCRR, RCRW, RLC and RCR instructions Bastian Koppelmann
                   ` (3 preceding siblings ...)
  2014-11-13 17:12 ` [Qemu-devel] [PATCH v2 4/4] target-tricore: Add instructions of RCR " Bastian Koppelmann
@ 2014-11-14 13:41 ` Richard Henderson
  4 siblings, 0 replies; 8+ messages in thread
From: Richard Henderson @ 2014-11-14 13:41 UTC (permalink / raw)
  To: Bastian Koppelmann, qemu-devel; +Cc: peter.maydell

On 11/13/2014 06:12 PM, Bastian Koppelmann wrote:
> Hi,
> 
> this patch depends on the previous TriCore patches (https://patchwork.ozlabs.org/patch/405459/) and will hopefully end up in 2.3 QEMU.
> Other than adding the RCPW, RCRR, RCRW, RLC and RCR instructions, it cleans up how ISA versions in the feature bitmask are handled,
> to simplify the checks, when instructions are available.
> 
> Thanks,
> Bastian
> 
> v1 -> v2:
>     - Fixed obvious style errors, given by checkpatch.
> 
> Bastian Koppelmann (4):
>   target-tricore: Make TRICORE_FEATURES implying others.
>   target-tricore: Add instructions of RCPW, RCRR and RCRW opcode format
>   target-tricore: Add instructions of RLC opcode format
>   target-tricore: Add instructions of RCR opcode format

Patches 1-3 get

Reviewed-by: Richard Henderson <rth@twiddle.net>

Patch 4 looks correct, but appears to work too hard.


r~

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH v2 4/4] target-tricore: Add instructions of RCR opcode format
  2014-11-14 13:39   ` Richard Henderson
@ 2014-11-19 13:35     ` Bastian Koppelmann
  0 siblings, 0 replies; 8+ messages in thread
From: Bastian Koppelmann @ 2014-11-19 13:35 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: peter.maydell


On 11/14/2014 01:39 PM, Richard Henderson wrote:
> On 11/13/2014 06:12 PM, Bastian Koppelmann wrote:
>> +    tcg_gen_ext_i32_i64(t3, r3);
>> +    tcg_gen_concat_i32_i64(t2, r2_low, r2_high);
>> +    /* extend the sign for r2 to high 64 bits */
>> +    tcg_gen_sari_i64(t4, t2, 63);
>> +    tcg_gen_ext_i32_i64(t1, r1);
>> +
>> +    tcg_gen_muls2_i64(t1, t3, t1, t3);
>> +    tcg_gen_add2_i64(t1, t3, t2, t4, t1, t3);
>> +
> I don't believe that you need 128 bit arithemetic for multiply-accumulate,
> either here or elsewhere (e.g. msub).
>
> Looking at unsigned, the maximum result of the multiply is 2*(2^n-1), or 2^(2n)
> - 2^(n+1).  Which means that the accumulate with a 2^n-1 value cannot overflow
> a double-word intermediate result.
Madd.u has the following signature 64 + (32 * 32) --> 64, as far as I 
read the documentation, and would result as you described in a max 
result of 2^(2n) - 2^(n+1) for the multiplication, but it would 
accumulate with 2^(2n) -1, which can definitly overflow, with n = 32.

However for signed multiply accumulate I don't need 128 bit arithmetic, 
because only the add/sub operation of those two can overflow. Thanks for 
the tip!

Cheers,
Bastian

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2014-11-19 12:35 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-13 17:12 [Qemu-devel] [PATCH v2 0/4] Add TriCore RCPW, RCRR, RCRW, RLC and RCR instructions Bastian Koppelmann
2014-11-13 17:12 ` [Qemu-devel] [PATCH v2 1/4] target-tricore: Make TRICORE_FEATURES implying others Bastian Koppelmann
2014-11-13 17:12 ` [Qemu-devel] [PATCH v2 2/4] target-tricore: Add instructions of RCPW, RCRR and RCRW opcode format Bastian Koppelmann
2014-11-13 17:12 ` [Qemu-devel] [PATCH v2 3/4] target-tricore: Add instructions of RLC " Bastian Koppelmann
2014-11-13 17:12 ` [Qemu-devel] [PATCH v2 4/4] target-tricore: Add instructions of RCR " Bastian Koppelmann
2014-11-14 13:39   ` Richard Henderson
2014-11-19 13:35     ` Bastian Koppelmann
2014-11-14 13:41 ` [Qemu-devel] [PATCH v2 0/4] Add TriCore RCPW, RCRR, RCRW, RLC and RCR instructions Richard Henderson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.