qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] Add special MIPS multiply instructions


From: Dirk Behme
Subject: [Qemu-devel] [PATCH] Add special MIPS multiply instructions
Date: Sat, 22 Jul 2006 08:04:46 +0200
User-agent: Mozilla Thunderbird 1.0.7 (X11/20050923)


This is an update of MIPS NEC VR5400 special instruction
patch [1]. It is necessary because of MIPS instruction set
configuration patch. Therefore this patch has to be applied
on top of

http://lists.gnu.org/archive/html/qemu-devel/2006-07/msg00158.html

Best regards

Dirk

[1]
http://lists.gnu.org/archive/html/qemu-devel/2006-04/msg00375.html


--- ./target-mips/op_helper.c_orig      2006-07-22 07:32:51.000000000 +0200
+++ ./target-mips/op_helper.c   2006-07-22 08:01:16.000000000 +0200
@@ -128,6 +128,134 @@ void do_msubu (void)
     tmp = ((uint64_t)T0 * (uint64_t)T1);
     set_HILO(get_HILO() - tmp);
 }
+
+#ifdef MIPS_USES_NEC_VR5400
+void do_muls (void)
+{
+    int64_t tmp;
+
+    tmp = 0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF;
+}
+
+void do_mulsu (void)
+{
+    uint64_t tmp;
+
+    tmp = 0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF;
+}
+
+void do_macc (void)
+{
+    int64_t tmp;
+
+    tmp = ((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * 
(int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF;
+}
+
+void do_macchi (void)
+{
+    int64_t tmp;
+
+    tmp = ((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * 
(int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+}
+
+void do_maccu (void)
+{
+    uint64_t tmp;
+
+    tmp = ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * 
(uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF; 
+}
+
+void do_macchiu (void)
+{
+    uint64_t tmp;
+
+    tmp = ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * 
(uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+}
+
+void do_msac (void)
+{
+    int64_t tmp;
+
+    tmp = ((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * 
(int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF;
+}
+
+void do_msachi (void)
+{
+    int64_t tmp;
+
+    tmp = ((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * 
(int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+}
+
+void do_msacu (void)
+{
+    uint64_t tmp;
+
+    tmp = ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * 
(uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF;
+}
+
+void do_msachiu (void)
+{
+    uint64_t tmp;
+
+    tmp = ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * 
(uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+}
+
+void do_mulhi (void)
+{
+    int64_t tmp;
+
+    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+}
+
+void do_mulhiu (void)
+{
+    uint64_t tmp;
+
+    tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+}
+
+void do_mulshi (void)
+{
+    int64_t tmp;
+
+    tmp = 0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+}
+
+void do_mulshiu (void)
+{
+    uint64_t tmp;
+
+    tmp = 0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+}
+#endif /* MIPS_USES_NEC_VR5400 */
 #endif
 
 #if defined(CONFIG_USER_ONLY) 
@@ -159,6 +287,149 @@ void do_tlbr (void)
 {
     cpu_abort(env, "tlbr\n");
 }
+
+#ifdef MIPS_USES_NEC_VR5400
+void op_muls (void)
+{
+    int64_t tmp;
+
+    tmp = 0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF;
+    RETURN();
+}
+
+void op_mulsu (void)
+{
+    uint64_t tmp;
+
+    tmp = 0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF;
+    RETURN();
+}
+
+void op_macc (void)
+{
+    int64_t tmp;
+
+    tmp = ((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * 
(int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF;
+    RETURN();
+}
+
+void op_macchi (void)
+{
+    int64_t tmp;
+
+    tmp = ((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * 
(int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+    RETURN();
+}
+
+void op_maccu (void)
+{
+    uint64_t tmp;
+
+    tmp = ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * 
(uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF;
+    RETURN();
+}
+
+void op_macchiu (void)
+{
+    uint64_t tmp;
+
+    tmp = ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * 
(uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+    RETURN();
+}
+
+void op_msac (void)
+{
+    int64_t tmp;
+
+    tmp = ((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * 
(int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF;
+    RETURN();
+}
+
+void op_msachi (void)
+{
+    int64_t tmp;
+
+    tmp = ((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * 
(int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+    RETURN();
+}
+
+void op_msacu (void)
+{
+    uint64_t tmp;
+
+    tmp = ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * 
(uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF;
+    RETURN();
+}
+
+void op_msachiu (void)
+{
+    uint64_t tmp;
+
+    tmp = ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * 
(uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+    RETURN();
+}
+
+void op_mulhi (void)
+{
+    int64_t tmp;
+
+    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+    RETURN();
+}
+
+void op_mulhiu (void)
+{
+    uint64_t tmp;
+
+    tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+    RETURN();
+}
+
+void op_mulshi (void)
+{
+    int64_t tmp;
+
+    tmp = 0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+    RETURN();
+}
+
+void op_mulshiu (void)
+{
+    uint64_t tmp;
+
+    tmp = 0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+    RETURN();
+}
+#endif /* MIPS_USES_NEC_VR5400 */
+
 #else
 
 /* CP0 helpers */
--- ./target-mips/op.c_orig     2006-07-22 07:32:51.000000000 +0200
+++ ./target-mips/op.c  2006-07-22 08:00:37.000000000 +0200
@@ -549,6 +549,148 @@ void op_msubu (void)
     set_HILO(get_HILO() - tmp);
     RETURN();
 }
+
+#ifdef MIPS_USES_NEC_VR5400
+void op_muls (void)
+{
+    int64_t tmp;
+
+    tmp = 0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF;
+    RETURN();
+}
+
+void op_mulsu (void)
+{
+    uint64_t tmp;
+
+    tmp = 0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF;
+    RETURN();
+}
+
+void op_macc (void)
+{
+    int64_t tmp;
+
+    tmp = ((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * 
(int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF;
+    RETURN();
+}
+
+void op_macchi (void)
+{
+    int64_t tmp;
+
+    tmp = ((int64_t)get_HILO()) + ((int64_t)(int32_t)T0 * 
(int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+    RETURN();
+}
+
+void op_maccu (void)
+{
+    uint64_t tmp;
+
+    tmp = ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * 
(uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF;
+    RETURN();
+}
+
+void op_macchiu (void)
+{
+    uint64_t tmp;
+
+    tmp = ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)T0 * 
(uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+    RETURN();
+}
+
+void op_msac (void)
+{
+    int64_t tmp;
+
+    tmp = ((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * 
(int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF;
+    RETURN();
+}
+
+void op_msachi (void)
+{
+    int64_t tmp;
+
+    tmp = ((int64_t)get_HILO()) - ((int64_t)(int32_t)T0 * 
(int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+    RETURN();
+}
+
+void op_msacu (void)
+{
+    uint64_t tmp;
+
+    tmp = ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * 
(uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp & 0xFFFFFFFF;
+    RETURN();
+}
+
+void op_msachiu (void)
+{
+    uint64_t tmp;
+
+    tmp = ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)T0 * 
(uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+    RETURN();
+}
+
+void op_mulhi (void)
+{
+    int64_t tmp;
+
+    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+    RETURN();
+}
+
+void op_mulhiu (void)
+{
+    uint64_t tmp;
+
+    tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+    RETURN();
+}
+
+void op_mulshi (void)
+{
+    int64_t tmp;
+
+    tmp = 0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+    RETURN();
+}
+
+void op_mulshiu (void)
+{
+    uint64_t tmp;
+
+    tmp = 0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
+    set_HILO(tmp);
+    T0 = tmp >> 32;
+    RETURN();
+}
+#endif /* MIPS_USES_NEC_VR5400 */
 #else
 void op_mult (void)
 {
@@ -585,6 +727,91 @@ void op_msubu (void)
     CALL_FROM_TB0(do_msubu);
     RETURN();
 }
+
+#ifdef MIPS_USES_NEC_VR5400
+void op_muls (void)
+{
+    CALL_FROM_TB0(do_muls);
+    RETURN();
+}
+
+void op_mulsu (void)
+{
+    CALL_FROM_TB0(do_mulsu);
+    RETURN();
+}
+
+void op_macc (void)
+{
+    CALL_FROM_TB0(do_macc);
+    RETURN();
+}
+
+void op_macchi (void)
+{
+    CALL_FROM_TB0(do_macchi); 
+    RETURN();
+}
+
+void op_maccu (void)
+{
+    CALL_FROM_TB0(do_maccu); 
+    RETURN();
+}
+void op_macchiu (void)
+{
+    CALL_FROM_TB0(do_macchiu);
+    RETURN();
+}
+
+void op_msac (void)
+{
+    CALL_FROM_TB0(do_msac);
+    RETURN();
+}
+
+void op_msachi (void)
+{
+    CALL_FROM_TB0(do_msachi);
+    RETURN();
+}
+
+void op_msacu (void)
+{
+    CALL_FROM_TB0(do_msacu);
+    RETURN();
+}
+
+void op_msachiu (void)
+{
+    CALL_FROM_TB0(do_msachiu);
+    RETURN();
+}
+
+void op_mulhi (void)
+{
+    CALL_FROM_TB0(do_mulhi);
+    RETURN();
+}
+
+void op_mulhiu (void)
+{
+    CALL_FROM_TB0(do_mulhiu);
+    RETURN();
+}
+
+void op_mulshi (void)
+{
+    CALL_FROM_TB0(do_mulshi);
+    RETURN();
+}
+
+void op_mulshiu (void)
+{
+    CALL_FROM_TB0(do_mulshiu);
+    RETURN();
+}
+#endif /* MIPS_USES_NEC_VR5400 */
 #endif
 
 /* Conditional moves */
--- ./target-mips/translate.c_orig      2006-07-22 07:32:51.000000000 +0200
+++ ./target-mips/translate.c   2006-07-22 08:01:44.000000000 +0200
@@ -984,6 +984,81 @@ static void gen_muldiv (DisasContext *ct
     MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
 }
 
+#ifdef MIPS_USES_NEC_VR5400
+static void gen_muldiv_ext (DisasContext *ctx, uint16_t opc,
+                            int rd, int rs, int rt)
+{
+    const unsigned char *opn = "unk";
+
+    GEN_LOAD_REG_TN(T0, rs);
+    GEN_LOAD_REG_TN(T1, rt);
+    switch (opc) {
+    case 0x0d8:
+        gen_op_muls();
+        opn = "muls";
+       break;
+    case 0x0d9:
+        gen_op_mulsu();
+        opn = "mulsu";
+       break;
+    case 0x158:
+        gen_op_macc();
+        opn = "macc";
+       break;
+    case 0x159:
+        gen_op_maccu();
+        opn = "maccu";
+       break;
+    case 0x1d8:
+        gen_op_msac();
+        opn = "msac";
+       break;
+    case 0x1d9:
+        gen_op_msacu();
+        opn = "msacu";
+       break;
+    case 0x258:
+        gen_op_mulhi();
+        opn = "mulhi";
+       break;
+    case 0x259:
+        gen_op_mulhiu();
+        opn = "mulhiu";
+       break;
+    case 0x2d8:
+        gen_op_mulshi();
+        opn = "mulshi";
+       break;
+    case 0x2d9:
+        gen_op_mulshiu();
+        opn = "mulshiu";
+       break;
+    case 0x358:
+        gen_op_macchi();
+        opn = "macchi";
+       break;
+    case 0x359:
+        gen_op_macchiu();
+        opn = "macchiu";
+       break;
+    case 0x3d8:
+        gen_op_msachi();
+        opn = "msachi";
+       break;
+    case 0x3d9:
+        gen_op_msachiu();
+        opn = "msachiu";
+       break;
+    default:
+        MIPS_INVAL("mul/div ext");
+        generate_exception(ctx, EXCP_RI);
+        return;
+    }
+    GEN_STORE_TN_REG(rd, T0);
+    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
+}
+#endif /* MIPS_USES_NEC_VR5400 */
+
 static void gen_cl (DisasContext *ctx, uint16_t opc,
                     int rd, int rs)
 {
@@ -1932,7 +2007,7 @@ static void decode_opc (CPUState *env, D
            } else {
                if(mips_uses_nec_vr5400()) {
                    op1 = ctx->opcode & 0x7FF;
-                   /* tbd: call handler for special NEC instructions */
+                   gen_muldiv_ext(ctx, op1, rd, rs, rt);
                 } else {
                    MIPS_INVAL("NEC extension");
                     generate_exception(ctx, EXCP_RI);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]