Implement FP madd/msub, wire up bc1any[24][ft].
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Fri, 11 May 2007 09:59:10 +0000 (09:59 +0000)
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Fri, 11 May 2007 09:59:10 +0000 (09:59 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2802 c046a42c-6fe2-441c-8c8c-71466251a162

target-mips/op.c
target-mips/translate.c

index 9b0cee0..15c541c 100644 (file)
@@ -2185,6 +2185,7 @@ FLOAT_OP(name, d)         \
     FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status);    \
     update_fcr31();       \
     DEBUG_FPU_STATE();    \
+    RETURN();             \
 }                         \
 FLOAT_OP(name, s)         \
 {                         \
@@ -2192,6 +2193,7 @@ FLOAT_OP(name, s)         \
     FST2 = float32_ ## name (FST0, FST1, &env->fp_status);    \
     update_fcr31();       \
     DEBUG_FPU_STATE();    \
+    RETURN();             \
 }                         \
 FLOAT_OP(name, ps)        \
 {                         \
@@ -2200,6 +2202,7 @@ FLOAT_OP(name, ps)        \
     FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \
     update_fcr31();       \
     DEBUG_FPU_STATE();    \
+    RETURN();             \
 }
 FLOAT_BINOP(add)
 FLOAT_BINOP(sub)
@@ -2207,6 +2210,16 @@ FLOAT_BINOP(mul)
 FLOAT_BINOP(div)
 #undef FLOAT_BINOP
 
+FLOAT_OP(addr, ps)
+{
+    set_float_exception_flags(0, &env->fp_status);
+    FST2 = float32_add (FST0, FSTH0, &env->fp_status);
+    FSTH2 = float32_add (FST1, FSTH1, &env->fp_status);
+    update_fcr31();
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+
 /* ternary operations */
 #define FLOAT_TERNOP(name1, name2) \
 FLOAT_OP(name1 ## name2, d)        \
@@ -2214,12 +2227,14 @@ FLOAT_OP(name1 ## name2, d)        \
     FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status);    \
     FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status);    \
     DEBUG_FPU_STATE();             \
+    RETURN();                      \
 }                                  \
 FLOAT_OP(name1 ## name2, s)        \
 {                                  \
     FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status);    \
     FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status);    \
     DEBUG_FPU_STATE();             \
+    RETURN();                      \
 }                                  \
 FLOAT_OP(name1 ## name2, ps)       \
 {                                  \
@@ -2228,28 +2243,65 @@ FLOAT_OP(name1 ## name2, ps)       \
     FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status);    \
     FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
     DEBUG_FPU_STATE();             \
+    RETURN();                      \
 }
 FLOAT_TERNOP(mul, add)
 FLOAT_TERNOP(mul, sub)
 #undef FLOAT_TERNOP
 
+/* negated ternary operations */
+#define FLOAT_NTERNOP(name1, name2) \
+FLOAT_OP(n ## name1 ## name2, d)    \
+{                                   \
+    FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status);    \
+    FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status);    \
+    FDT2 ^= 1ULL << 63;             \
+    DEBUG_FPU_STATE();              \
+    RETURN();                       \
+}                                   \
+FLOAT_OP(n ## name1 ## name2, s)    \
+{                                   \
+    FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status);    \
+    FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status);    \
+    FST2 ^= 1 << 31;                \
+    DEBUG_FPU_STATE();              \
+    RETURN();                       \
+}                                   \
+FLOAT_OP(n ## name1 ## name2, ps)   \
+{                                   \
+    FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status);    \
+    FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \
+    FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status);    \
+    FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
+    FST2 ^= 1 << 31;                \
+    FSTH2 ^= 1 << 31;               \
+    DEBUG_FPU_STATE();              \
+    RETURN();                       \
+}
+FLOAT_NTERNOP(mul, add)
+FLOAT_NTERNOP(mul, sub)
+#undef FLOAT_NTERNOP
+
 /* unary operations, modifying fp status  */
 #define FLOAT_UNOP(name)  \
 FLOAT_OP(name, d)         \
 {                         \
     FDT2 = float64_ ## name(FDT0, &env->fp_status);   \
     DEBUG_FPU_STATE();    \
+    RETURN();                      \
 }                         \
 FLOAT_OP(name, s)         \
 {                         \
     FST2 = float32_ ## name(FST0, &env->fp_status);   \
     DEBUG_FPU_STATE();    \
+    RETURN();                      \
 }                         \
 FLOAT_OP(name, ps)        \
 {                         \
     FST2 = float32_ ## name(FST0, &env->fp_status);   \
     FSTH2 = float32_ ## name(FSTH0, &env->fp_status); \
     DEBUG_FPU_STATE();    \
+    RETURN();                      \
 }
 FLOAT_UNOP(sqrt)
 #undef FLOAT_UNOP
@@ -2260,17 +2312,20 @@ FLOAT_OP(name, d)         \
 {                         \
     FDT2 = float64_ ## name(FDT0);   \
     DEBUG_FPU_STATE();    \
+    RETURN();             \
 }                         \
 FLOAT_OP(name, s)         \
 {                         \
     FST2 = float32_ ## name(FST0);   \
     DEBUG_FPU_STATE();    \
+    RETURN();             \
 }                         \
 FLOAT_OP(name, ps)        \
 {                         \
     FST2 = float32_ ## name(FST0);   \
     FSTH2 = float32_ ## name(FSTH0); \
     DEBUG_FPU_STATE();    \
+    RETURN();             \
 }
 FLOAT_UNOP(abs)
 FLOAT_UNOP(chs)
index dda44d0..8114178 100644 (file)
@@ -402,7 +402,7 @@ enum {
     OPC_MSUB_D  = 0x29 | OPC_CP3,
     OPC_MSUB_PS = 0x2E | OPC_CP3,
     OPC_NMADD_S = 0x30 | OPC_CP3,
-    OPC_NMADD_D = 0x32 | OPC_CP3,
+    OPC_NMADD_D = 0x31 | OPC_CP3,
     OPC_NMADD_PS= 0x36 | OPC_CP3,
     OPC_NMSUB_S = 0x38 | OPC_CP3,
     OPC_NMSUB_D = 0x39 | OPC_CP3,
@@ -4955,6 +4955,17 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
         GEN_STORE_FTN_FREG(fd, WTH2);
         opn = "movn.ps";
         break;
+    case FOP(24, 22):
+        CHECK_FR(ctx, fs | fd | ft);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WTH0, fs);
+        GEN_LOAD_FREG_FTN(WT1, ft);
+        GEN_LOAD_FREG_FTN(WTH1, ft);
+        gen_op_float_addr_ps();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        GEN_STORE_FTN_FREG(fd, WTH2);
+        opn = "addr.ps";
+        break;
     case FOP(32, 22):
         CHECK_FR(ctx, fs);
         GEN_LOAD_FREG_FTN(WTH0, fs);
@@ -5120,47 +5131,107 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, int fd,
         opn = "madd.s";
         break;
     case OPC_MADD_D:
-        generate_exception (ctx, EXCP_RI);
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        GEN_LOAD_FREG_FTN(DT1, ft);
+        GEN_LOAD_FREG_FTN(DT2, fr);
+        gen_op_float_muladd_d();
+        GEN_STORE_FTN_FREG(fd, DT2);
         opn = "madd.d";
         break;
     case OPC_MADD_PS:
-        generate_exception (ctx, EXCP_RI);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WTH0, fs);
+        GEN_LOAD_FREG_FTN(WT1, ft);
+        GEN_LOAD_FREG_FTN(WTH1, ft);
+        GEN_LOAD_FREG_FTN(WT2, fr);
+        GEN_LOAD_FREG_FTN(WTH2, fr);
+        gen_op_float_muladd_ps();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        GEN_STORE_FTN_FREG(fd, WTH2);
         opn = "madd.ps";
         break;
     case OPC_MSUB_S:
-        generate_exception (ctx, EXCP_RI);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WT1, ft);
+        GEN_LOAD_FREG_FTN(WT2, fr);
+        gen_op_float_mulsub_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
         opn = "msub.s";
         break;
     case OPC_MSUB_D:
-        generate_exception (ctx, EXCP_RI);
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        GEN_LOAD_FREG_FTN(DT1, ft);
+        GEN_LOAD_FREG_FTN(DT2, fr);
+        gen_op_float_mulsub_d();
+        GEN_STORE_FTN_FREG(fd, DT2);
         opn = "msub.d";
         break;
     case OPC_MSUB_PS:
-        generate_exception (ctx, EXCP_RI);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WTH0, fs);
+        GEN_LOAD_FREG_FTN(WT1, ft);
+        GEN_LOAD_FREG_FTN(WTH1, ft);
+        GEN_LOAD_FREG_FTN(WT2, fr);
+        GEN_LOAD_FREG_FTN(WTH2, fr);
+        gen_op_float_mulsub_ps();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        GEN_STORE_FTN_FREG(fd, WTH2);
         opn = "msub.ps";
         break;
     case OPC_NMADD_S:
-        generate_exception (ctx, EXCP_RI);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WT1, ft);
+        GEN_LOAD_FREG_FTN(WT2, fr);
+        gen_op_float_nmuladd_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
         opn = "nmadd.s";
         break;
     case OPC_NMADD_D:
-        generate_exception (ctx, EXCP_RI);
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        GEN_LOAD_FREG_FTN(DT1, ft);
+        GEN_LOAD_FREG_FTN(DT2, fr);
+        gen_op_float_nmuladd_d();
+        GEN_STORE_FTN_FREG(fd, DT2);
         opn = "nmadd.d";
         break;
     case OPC_NMADD_PS:
-        generate_exception (ctx, EXCP_RI);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WTH0, fs);
+        GEN_LOAD_FREG_FTN(WT1, ft);
+        GEN_LOAD_FREG_FTN(WTH1, ft);
+        GEN_LOAD_FREG_FTN(WT2, fr);
+        GEN_LOAD_FREG_FTN(WTH2, fr);
+        gen_op_float_nmuladd_ps();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        GEN_STORE_FTN_FREG(fd, WTH2);
         opn = "nmadd.ps";
         break;
     case OPC_NMSUB_S:
-        generate_exception (ctx, EXCP_RI);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WT1, ft);
+        GEN_LOAD_FREG_FTN(WT2, fr);
+        gen_op_float_nmulsub_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
         opn = "nmsub.s";
         break;
     case OPC_NMSUB_D:
-        generate_exception (ctx, EXCP_RI);
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        GEN_LOAD_FREG_FTN(DT1, ft);
+        GEN_LOAD_FREG_FTN(DT2, fr);
+        gen_op_float_nmulsub_d();
+        GEN_STORE_FTN_FREG(fd, DT2);
         opn = "nmsub.d";
         break;
     case OPC_NMSUB_PS:
-        generate_exception (ctx, EXCP_RI);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WTH0, fs);
+        GEN_LOAD_FREG_FTN(WT1, ft);
+        GEN_LOAD_FREG_FTN(WTH1, ft);
+        GEN_LOAD_FREG_FTN(WT2, fr);
+        GEN_LOAD_FREG_FTN(WTH2, fr);
+        gen_op_float_nmulsub_ps();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        GEN_STORE_FTN_FREG(fd, WTH2);
         opn = "nmsub.ps";
         break;
     default:
@@ -5562,6 +5633,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
                 gen_cp1(ctx, op1, rt, rd);
                 break;
             case OPC_BC1:
+            case OPC_BC1ANY2:
+            case OPC_BC1ANY4:
                 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
                                     (rt >> 2) & 0x7, imm << 2);
                 return;