Synchronize with latest PowerPC ISA VEA:
[qemu] / target-ppc / translate.c
index dc4e758..612b0ad 100644 (file)
@@ -476,6 +476,10 @@ enum {
     PPC_RFMCI         = 0x0000020000000000ULL,
     /* user-mode DCR access, implemented in PowerPC 460 */
     PPC_DCRUX         = 0x0000040000000000ULL,
+    /* New floating-point extensions (PowerPC 2.0x)     */
+    PPC_FLOAT_EXT     = 0x0000080000000000ULL,
+    /* New wait instruction (PowerPC 2.0x)              */
+    PPC_WAIT          = 0x0000100000000000ULL,
 };
 
 /*****************************************************************************/
@@ -1122,6 +1126,26 @@ GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
     } else if (unlikely(Rc(ctx->opcode) != 0)) {
         gen_op_load_gpr_T0(rs);
         gen_set_Rc0(ctx);
+#if defined(TARGET_PPC64)
+    } else {
+        switch (rs) {
+        case 1:
+            /* Set process priority to low */
+            gen_op_store_pri(2);
+            break;
+        case 6:
+            /* Set process priority to medium-low */
+            gen_op_store_pri(3);
+            break;
+        case 2:
+            /* Set process priority to normal */
+            gen_op_store_pri(4);
+            break;
+        default:
+            /* nop */
+            break;
+        }
+#endif
     }
 }
 
@@ -1660,6 +1684,9 @@ GEN_FLOAT_AB(div, 0x12, 0x000007C0);
 /* fmul - fmuls */
 GEN_FLOAT_AC(mul, 0x19, 0x0000F800);
 
+/* fre */
+GEN_FLOAT_BS(re, 0x3F, 0x18, PPC_FLOAT_EXT);
+
 /* fres */
 GEN_FLOAT_BS(res, 0x3B, 0x18, PPC_FLOAT_FRES);
 
@@ -1727,6 +1754,15 @@ GEN_FLOAT_B(ctid, 0x0E, 0x19, PPC_64B);
 GEN_FLOAT_B(ctidz, 0x0F, 0x19, PPC_64B);
 #endif
 
+/* frin */
+GEN_FLOAT_B(rin, 0x08, 0x0C, PPC_FLOAT_EXT);
+/* friz */
+GEN_FLOAT_B(riz, 0x08, 0x0D, PPC_FLOAT_EXT);
+/* frip */
+GEN_FLOAT_B(rip, 0x08, 0x0E, PPC_FLOAT_EXT);
+/* frim */
+GEN_FLOAT_B(rim, 0x08, 0x0F, PPC_FLOAT_EXT);
+
 /***                         Floating-Point compare                        ***/
 /* fcmpo */
 GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
@@ -2429,12 +2465,12 @@ GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_INTEGER)
 
 /***                        Memory synchronisation                         ***/
 /* eieio */
-GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM_EIEIO)
+GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO)
 {
 }
 
 /* isync */
-GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FF0801, PPC_MEM)
+GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM)
 {
     GEN_STOP(ctx);
 }
@@ -2576,13 +2612,21 @@ GEN_HANDLER(stdcx_, 0x1F, 0x16, 0x06, 0x00000000, PPC_64B)
 #endif /* defined(TARGET_PPC64) */
 
 /* sync */
-GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03CF0801, PPC_MEM_SYNC)
+GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03BFF801, PPC_MEM_SYNC)
+{
+}
+
+/* wait */
+GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT)
 {
+    /* Stop translation, as the CPU is supposed to sleep from now */
+    /* XXX: TODO: handle this idle CPU case */
+    GEN_STOP(ctx);
 }
 
 /***                         Floating-point load                           ***/
-#define GEN_LDF(width, opc)                                                   \
-GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)                 \
+#define GEN_LDF(width, opc, type)                                             \
+GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type)                      \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
         GEN_EXCP_NO_FP(ctx);                                                  \
@@ -2593,8 +2637,8 @@ GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)                 \
     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
 }
 
-#define GEN_LDUF(width, opc)                                                  \
-GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)              \
+#define GEN_LDUF(width, opc, type)                                            \
+GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                   \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
         GEN_EXCP_NO_FP(ctx);                                                  \
@@ -2610,8 +2654,8 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)              \
     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
 }
 
-#define GEN_LDUXF(width, opc)                                                 \
-GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)             \
+#define GEN_LDUXF(width, opc, type)                                           \
+GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, type)                  \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
         GEN_EXCP_NO_FP(ctx);                                                  \
@@ -2627,8 +2671,8 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)             \
     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
 }
 
-#define GEN_LDXF(width, opc2, opc3)                                           \
-GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT)             \
+#define GEN_LDXF(width, opc2, opc3, type)                                     \
+GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type)                  \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
         GEN_EXCP_NO_FP(ctx);                                                  \
@@ -2639,21 +2683,21 @@ GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT)             \
     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
 }
 
-#define GEN_LDFS(width, op)                                                   \
+#define GEN_LDFS(width, op, type)                                             \
 OP_LD_TABLE(width);                                                           \
-GEN_LDF(width, op | 0x20);                                                    \
-GEN_LDUF(width, op | 0x21);                                                   \
-GEN_LDUXF(width, op | 0x01);                                                  \
-GEN_LDXF(width, 0x17, op | 0x00)
+GEN_LDF(width, op | 0x20, type);                                              \
+GEN_LDUF(width, op | 0x21, type);                                             \
+GEN_LDUXF(width, op | 0x01, type);                                            \
+GEN_LDXF(width, 0x17, op | 0x00, type)
 
 /* lfd lfdu lfdux lfdx */
-GEN_LDFS(fd, 0x12);
+GEN_LDFS(fd, 0x12, PPC_FLOAT);
 /* lfs lfsu lfsux lfsx */
-GEN_LDFS(fs, 0x10);
+GEN_LDFS(fs, 0x10, PPC_FLOAT);
 
 /***                         Floating-point store                          ***/
-#define GEN_STF(width, opc)                                                   \
-GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)                \
+#define GEN_STF(width, opc, type)                                             \
+GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type)                     \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
         GEN_EXCP_NO_FP(ctx);                                                  \
@@ -2664,8 +2708,8 @@ GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)                \
     op_ldst(st##width);                                                       \
 }
 
-#define GEN_STUF(width, opc)                                                  \
-GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)             \
+#define GEN_STUF(width, opc, type)                                            \
+GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                  \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
         GEN_EXCP_NO_FP(ctx);                                                  \
@@ -2681,8 +2725,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)             \
     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
 }
 
-#define GEN_STUXF(width, opc)                                                 \
-GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)            \
+#define GEN_STUXF(width, opc, type)                                           \
+GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, type)                 \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
         GEN_EXCP_NO_FP(ctx);                                                  \
@@ -2698,8 +2742,8 @@ GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)            \
     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
 }
 
-#define GEN_STXF(width, opc2, opc3)                                           \
-GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT)            \
+#define GEN_STXF(width, opc2, opc3, type)                                     \
+GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type)                 \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
         GEN_EXCP_NO_FP(ctx);                                                  \
@@ -2710,30 +2754,22 @@ GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT)            \
     op_ldst(st##width);                                                       \
 }
 
-#define GEN_STFS(width, op)                                                   \
+#define GEN_STFS(width, op, type)                                             \
 OP_ST_TABLE(width);                                                           \
-GEN_STF(width, op | 0x20);                                                    \
-GEN_STUF(width, op | 0x21);                                                   \
-GEN_STUXF(width, op | 0x01);                                                  \
-GEN_STXF(width, 0x17, op | 0x00)
+GEN_STF(width, op | 0x20, type);                                              \
+GEN_STUF(width, op | 0x21, type);                                             \
+GEN_STUXF(width, op | 0x01, type);                                            \
+GEN_STXF(width, 0x17, op | 0x00, type)
 
 /* stfd stfdu stfdux stfdx */
-GEN_STFS(fd, 0x16);
+GEN_STFS(fd, 0x16, PPC_FLOAT);
 /* stfs stfsu stfsux stfsx */
-GEN_STFS(fs, 0x14);
+GEN_STFS(fs, 0x14, PPC_FLOAT);
 
 /* Optional: */
 /* stfiwx */
-GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT_STFIWX)
-{
-    if (unlikely(!ctx->fpu_enabled)) {
-        GEN_EXCP_NO_FP(ctx);
-        return;
-    }
-    gen_addr_reg_index(ctx);
-    /* XXX: TODO: memcpy low order 32 bits of FRP(rs) into memory */
-    GEN_EXCP_INVAL(ctx);
-}
+OP_ST_TABLE(fiwx);
+GEN_STXF(fiwx, 0x17, 0x1E, PPC_FLOAT_STFIWX);
 
 /***                                Branch                                 ***/
 static inline void gen_goto_tb (DisasContext *ctx, int n, target_ulong dest)
@@ -3230,7 +3266,8 @@ GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001FF801, PPC_64B)
     gen_op_load_gpr_T0(rS(ctx->opcode));
     gen_op_store_msr();
     /* Must stop the translation as machine state (may have) changed */
-    GEN_SYNC(ctx);
+    /* Note that mtmsr is not always defined as context-synchronizing */
+    GEN_STOP(ctx);
 #endif
 }
 #endif
@@ -3253,7 +3290,8 @@ GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
 #endif
         gen_op_store_msr();
     /* Must stop the translation as machine state (may have) changed */
-    GEN_SYNC(ctx);
+    /* Note that mtmsrd is not always defined as context-synchronizing */
+    GEN_STOP(ctx);
 #endif
 }
 
@@ -3300,7 +3338,7 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
  * We just have to flush tb while invalidating instruction cache lines...
  */
 /* dcbf */
-GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE)
+GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE)
 {
     gen_addr_reg_index(ctx);
     op_ldst(lbz);
@@ -3332,16 +3370,18 @@ GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
 }
 
 /* dcbt */
-GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x03E00001, PPC_CACHE)
+GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE)
 {
+    /* interpreted as no-op */
     /* XXX: specification say this is treated as a load by the MMU
      *      but does not generate any exception
      */
 }
 
 /* dcbtst */
-GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE)
+GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE)
 {
+    /* interpreted as no-op */
     /* XXX: specification say this is treated as a load by the MMU
      *      but does not generate any exception
      */
@@ -3440,6 +3480,10 @@ GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE)
 /* dcba */
 GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
 {
+    /* interpreted as no-op */
+    /* XXX: specification say this is treated as a store by the MMU
+     *      but does not generate any exception
+     */
 }
 
 /***                    Segment register manipulation                      ***/
@@ -4936,6 +4980,9 @@ GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_EMB_COMMON)
     }
     gen_op_load_gpr_T0(rD(ctx->opcode));
     gen_op_wrte();
+    /* Stop translation to have a chance to raise an exception
+     * if we just set msr_ee to 1
+     */
     GEN_STOP(ctx);
 #endif
 }
@@ -4952,6 +4999,9 @@ GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_EMB_COMMON)
     }
     gen_op_set_T0(ctx->opcode & 0x00010000);
     gen_op_wrte();
+    /* Stop translation to have a chance to raise an exception
+     * if we just set msr_ee to 1
+     */
     GEN_STOP(ctx);
 #endif
 }
@@ -4978,7 +5028,7 @@ GEN_HANDLER(mbar, 0x1F, 0x16, 0x13, 0x001FF801, PPC_BOOKE)
 }
 
 /* msync replaces sync on 440 */
-GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_BOOKE)
+GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
 {
     /* interpreted as no-op */
 }