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,
};
/*****************************************************************************/
} 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
}
}
/* 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);
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)
/*** 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);
}
#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); \
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); \
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); \
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); \
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); \
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); \
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); \
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); \
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)
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
#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
}
* 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);
}
/* 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
*/
/* 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 ***/
}
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
}
}
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
}
}
/* 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 */
}