Commit be147d08790d4d80bfcf2c209031eede52b7dd62

Authored by j_mayer
1 parent b0566f4f

* Update OEA environment, following the PowerPC 2.04 specification:

- New mtmsr/mtmsrd form that just update RI and EE bits
- New hrfid, lq and stq instructions
- Add support for supervisor and hypervisor modes process priority update
- Code provision for hypervisor SPR accesses
* Actually implement the wait instruction
* Bugfixes (missing RETURN in micro-op / missing #ifdef)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3289 c046a42c-6fe2-441c-8c8c-71466251a162
target-ppc/cpu.h
@@ -287,6 +287,7 @@ enum { @@ -287,6 +287,7 @@ enum {
287 287
288 #define PPC_INPUT(env) (env->bus_model) 288 #define PPC_INPUT(env) (env->bus_model)
289 289
  290 +/*****************************************************************************/
290 typedef struct ppc_def_t ppc_def_t; 291 typedef struct ppc_def_t ppc_def_t;
291 typedef struct opc_handler_t opc_handler_t; 292 typedef struct opc_handler_t opc_handler_t;
292 293
@@ -306,6 +307,10 @@ struct ppc_spr_t { @@ -306,6 +307,10 @@ struct ppc_spr_t {
306 #if !defined(CONFIG_USER_ONLY) 307 #if !defined(CONFIG_USER_ONLY)
307 void (*oea_read)(void *opaque, int spr_num); 308 void (*oea_read)(void *opaque, int spr_num);
308 void (*oea_write)(void *opaque, int spr_num); 309 void (*oea_write)(void *opaque, int spr_num);
  310 +#if defined(TARGET_PPC64H)
  311 + void (*hea_read)(void *opaque, int spr_num);
  312 + void (*hea_write)(void *opaque, int spr_num);
  313 +#endif
309 #endif 314 #endif
310 const unsigned char *name; 315 const unsigned char *name;
311 }; 316 };
@@ -607,7 +612,9 @@ target_ulong ppc_load_xer (CPUPPCState *env); @@ -607,7 +612,9 @@ target_ulong ppc_load_xer (CPUPPCState *env);
607 void ppc_store_xer (CPUPPCState *env, target_ulong value); 612 void ppc_store_xer (CPUPPCState *env, target_ulong value);
608 target_ulong do_load_msr (CPUPPCState *env); 613 target_ulong do_load_msr (CPUPPCState *env);
609 void do_store_msr (CPUPPCState *env, target_ulong value); 614 void do_store_msr (CPUPPCState *env, target_ulong value);
  615 +#if defined(TARGET_PPC64)
610 void ppc_store_msr_32 (CPUPPCState *env, uint32_t value); 616 void ppc_store_msr_32 (CPUPPCState *env, uint32_t value);
  617 +#endif
611 618
612 void do_compute_hflags (CPUPPCState *env); 619 void do_compute_hflags (CPUPPCState *env);
613 void cpu_ppc_reset (void *opaque); 620 void cpu_ppc_reset (void *opaque);
target-ppc/op.c
@@ -355,6 +355,13 @@ void OPPROTO op_store_msr (void) @@ -355,6 +355,13 @@ void OPPROTO op_store_msr (void)
355 RETURN(); 355 RETURN();
356 } 356 }
357 357
  358 +void OPPROTO op_update_riee (void)
  359 +{
  360 + msr_ri = (T0 >> MSR_RI) & 1;
  361 + msr_ee = (T0 >> MSR_EE) & 1;
  362 + RETURN();
  363 +}
  364 +
358 #if defined (TARGET_PPC64) 365 #if defined (TARGET_PPC64)
359 void OPPROTO op_store_msr_32 (void) 366 void OPPROTO op_store_msr_32 (void)
360 { 367 {
@@ -1913,6 +1920,12 @@ void OPPROTO op_check_reservation_64 (void) @@ -1913,6 +1920,12 @@ void OPPROTO op_check_reservation_64 (void)
1913 } 1920 }
1914 #endif 1921 #endif
1915 1922
  1923 +void OPPROTO op_wait (void)
  1924 +{
  1925 + env->halted = 1;
  1926 + RETURN();
  1927 +}
  1928 +
1916 /* Return from interrupt */ 1929 /* Return from interrupt */
1917 #if !defined(CONFIG_USER_ONLY) 1930 #if !defined(CONFIG_USER_ONLY)
1918 void OPPROTO op_rfi (void) 1931 void OPPROTO op_rfi (void)
@@ -1928,6 +1941,14 @@ void OPPROTO op_rfid (void) @@ -1928,6 +1941,14 @@ void OPPROTO op_rfid (void)
1928 RETURN(); 1941 RETURN();
1929 } 1942 }
1930 #endif 1943 #endif
  1944 +
  1945 +#if defined(TARGET_PPC64H)
  1946 +void OPPROTO op_hrfid (void)
  1947 +{
  1948 + do_hrfid();
  1949 + RETURN();
  1950 +}
  1951 +#endif
1931 #endif 1952 #endif
1932 1953
1933 /* Trap word */ 1954 /* Trap word */
@@ -2557,6 +2578,7 @@ void OPPROTO op_store_40x_pit (void) @@ -2557,6 +2578,7 @@ void OPPROTO op_store_40x_pit (void)
2557 void OPPROTO op_store_40x_dbcr0 (void) 2578 void OPPROTO op_store_40x_dbcr0 (void)
2558 { 2579 {
2559 store_40x_dbcr0(env, T0); 2580 store_40x_dbcr0(env, T0);
  2581 + RETURN();
2560 } 2582 }
2561 2583
2562 void OPPROTO op_store_40x_sler (void) 2584 void OPPROTO op_store_40x_sler (void)
@@ -2576,7 +2598,6 @@ void OPPROTO op_store_booke_tsr (void) @@ -2576,7 +2598,6 @@ void OPPROTO op_store_booke_tsr (void)
2576 store_booke_tsr(env, T0); 2598 store_booke_tsr(env, T0);
2577 RETURN(); 2599 RETURN();
2578 } 2600 }
2579 -  
2580 #endif /* !defined(CONFIG_USER_ONLY) */ 2601 #endif /* !defined(CONFIG_USER_ONLY) */
2581 2602
2582 #if defined(TARGET_PPCEMB) 2603 #if defined(TARGET_PPCEMB)
target-ppc/op_helper.c
@@ -1002,6 +1002,22 @@ void do_rfid (void) @@ -1002,6 +1002,22 @@ void do_rfid (void)
1002 env->interrupt_request |= CPU_INTERRUPT_EXITTB; 1002 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1003 } 1003 }
1004 #endif 1004 #endif
  1005 +#if defined(TARGET_PPC64H)
  1006 +void do_hrfid (void)
  1007 +{
  1008 + if (env->spr[SPR_HSRR1] & (1ULL << MSR_SF)) {
  1009 + env->nip = (uint64_t)(env->spr[SPR_HSRR0] & ~0x00000003);
  1010 + do_store_msr(env, (uint64_t)(env->spr[SPR_HSRR1] & ~0xFFFF0000UL));
  1011 + } else {
  1012 + env->nip = (uint32_t)(env->spr[SPR_HSRR0] & ~0x00000003);
  1013 + do_store_msr(env, (uint32_t)(env->spr[SPR_HSRR1] & ~0xFFFF0000UL));
  1014 + }
  1015 +#if defined (DEBUG_OP)
  1016 + cpu_dump_rfi(env->nip, do_load_msr(env));
  1017 +#endif
  1018 + env->interrupt_request |= CPU_INTERRUPT_EXITTB;
  1019 +}
  1020 +#endif
1005 #endif 1021 #endif
1006 1022
1007 void do_tw (int flags) 1023 void do_tw (int flags)
target-ppc/op_helper.h
@@ -131,6 +131,9 @@ void do_rfi (void); @@ -131,6 +131,9 @@ void do_rfi (void);
131 #if defined(TARGET_PPC64) 131 #if defined(TARGET_PPC64)
132 void do_rfid (void); 132 void do_rfid (void);
133 #endif 133 #endif
  134 +#if defined(TARGET_PPC64H)
  135 +void do_hrfid (void);
  136 +#endif
134 void do_tlbia (void); 137 void do_tlbia (void);
135 void do_tlbie (void); 138 void do_tlbie (void);
136 #if defined(TARGET_PPC64) 139 #if defined(TARGET_PPC64)
target-ppc/translate.c
@@ -480,6 +480,8 @@ enum { @@ -480,6 +480,8 @@ enum {
480 PPC_FLOAT_EXT = 0x0000080000000000ULL, 480 PPC_FLOAT_EXT = 0x0000080000000000ULL,
481 /* New wait instruction (PowerPC 2.0x) */ 481 /* New wait instruction (PowerPC 2.0x) */
482 PPC_WAIT = 0x0000100000000000ULL, 482 PPC_WAIT = 0x0000100000000000ULL,
  483 + /* New 64 bits extensions (PowerPC 2.0x) */
  484 + PPC_64BX = 0x0000200000000000ULL,
483 }; 485 };
484 486
485 /*****************************************************************************/ 487 /*****************************************************************************/
@@ -1141,6 +1143,34 @@ GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER) @@ -1141,6 +1143,34 @@ GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
1141 /* Set process priority to normal */ 1143 /* Set process priority to normal */
1142 gen_op_store_pri(4); 1144 gen_op_store_pri(4);
1143 break; 1145 break;
  1146 +#if !defined(CONFIG_USER_ONLY)
  1147 + case 31:
  1148 + if (ctx->supervisor > 0) {
  1149 + /* Set process priority to very low */
  1150 + gen_op_store_pri(1);
  1151 + }
  1152 + break;
  1153 + case 5:
  1154 + if (ctx->supervisor > 0) {
  1155 + /* Set process priority to medium-hight */
  1156 + gen_op_store_pri(5);
  1157 + }
  1158 + break;
  1159 + case 3:
  1160 + if (ctx->supervisor > 0) {
  1161 + /* Set process priority to high */
  1162 + gen_op_store_pri(6);
  1163 + }
  1164 + break;
  1165 +#if defined(TARGET_PPC64H)
  1166 + case 7:
  1167 + if (ctx->supervisor > 1) {
  1168 + /* Set process priority to very high */
  1169 + gen_op_store_pri(7);
  1170 + }
  1171 + break;
  1172 +#endif
  1173 +#endif
1144 default: 1174 default:
1145 /* nop */ 1175 /* nop */
1146 break; 1176 break;
@@ -1902,12 +1932,11 @@ GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT) @@ -1902,12 +1932,11 @@ GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
1902 1932
1903 /*** Addressing modes ***/ 1933 /*** Addressing modes ***/
1904 /* Register indirect with immediate index : EA = (rA|0) + SIMM */ 1934 /* Register indirect with immediate index : EA = (rA|0) + SIMM */
1905 -static inline void gen_addr_imm_index (DisasContext *ctx, int maskl) 1935 +static inline void gen_addr_imm_index (DisasContext *ctx, target_long maskl)
1906 { 1936 {
1907 target_long simm = SIMM(ctx->opcode); 1937 target_long simm = SIMM(ctx->opcode);
1908 1938
1909 - if (maskl)  
1910 - simm &= ~0x03; 1939 + simm &= ~maskl;
1911 if (rA(ctx->opcode) == 0) { 1940 if (rA(ctx->opcode) == 0) {
1912 gen_set_T0(simm); 1941 gen_set_T0(simm);
1913 } else { 1942 } else {
@@ -2051,7 +2080,7 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \ @@ -2051,7 +2080,7 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
2051 return; \ 2080 return; \
2052 } \ 2081 } \
2053 if (type == PPC_64B) \ 2082 if (type == PPC_64B) \
2054 - gen_addr_imm_index(ctx, 1); \ 2083 + gen_addr_imm_index(ctx, 0x03); \
2055 else \ 2084 else \
2056 gen_addr_imm_index(ctx, 0); \ 2085 gen_addr_imm_index(ctx, 0); \
2057 op_ldst(l##width); \ 2086 op_ldst(l##width); \
@@ -2116,7 +2145,7 @@ GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B) @@ -2116,7 +2145,7 @@ GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B)
2116 return; 2145 return;
2117 } 2146 }
2118 } 2147 }
2119 - gen_addr_imm_index(ctx, 1); 2148 + gen_addr_imm_index(ctx, 0x03);
2120 if (ctx->opcode & 0x02) { 2149 if (ctx->opcode & 0x02) {
2121 /* lwa (lwau is undefined) */ 2150 /* lwa (lwau is undefined) */
2122 op_ldst(lwa); 2151 op_ldst(lwa);
@@ -2128,6 +2157,38 @@ GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B) @@ -2128,6 +2157,38 @@ GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B)
2128 if (Rc(ctx->opcode)) 2157 if (Rc(ctx->opcode))
2129 gen_op_store_T0_gpr(rA(ctx->opcode)); 2158 gen_op_store_T0_gpr(rA(ctx->opcode));
2130 } 2159 }
  2160 +/* lq */
  2161 +GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX)
  2162 +{
  2163 +#if defined(CONFIG_USER_ONLY)
  2164 + GEN_EXCP_PRIVOPC(ctx);
  2165 +#else
  2166 + int ra, rd;
  2167 +
  2168 + /* Restore CPU state */
  2169 + if (unlikely(ctx->supervisor == 0)) {
  2170 + GEN_EXCP_PRIVOPC(ctx);
  2171 + return;
  2172 + }
  2173 + ra = rA(ctx->opcode);
  2174 + rd = rD(ctx->opcode);
  2175 + if (unlikely((rd & 1) || rd == ra)) {
  2176 + GEN_EXCP_INVAL(ctx);
  2177 + return;
  2178 + }
  2179 + if (unlikely(ctx->mem_idx & 1)) {
  2180 + /* Little-endian mode is not handled */
  2181 + GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
  2182 + return;
  2183 + }
  2184 + gen_addr_imm_index(ctx, 0x0F);
  2185 + op_ldst(ld);
  2186 + gen_op_store_T1_gpr(rd);
  2187 + gen_op_addi(8);
  2188 + op_ldst(ld);
  2189 + gen_op_store_T1_gpr(rd + 1);
  2190 +#endif
  2191 +}
2131 #endif 2192 #endif
2132 2193
2133 /*** Integer store ***/ 2194 /*** Integer store ***/
@@ -2147,7 +2208,7 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \ @@ -2147,7 +2208,7 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
2147 return; \ 2208 return; \
2148 } \ 2209 } \
2149 if (type == PPC_64B) \ 2210 if (type == PPC_64B) \
2150 - gen_addr_imm_index(ctx, 1); \ 2211 + gen_addr_imm_index(ctx, 0x03); \
2151 else \ 2212 else \
2152 gen_addr_imm_index(ctx, 0); \ 2213 gen_addr_imm_index(ctx, 0); \
2153 gen_op_load_gpr_T1(rS(ctx->opcode)); \ 2214 gen_op_load_gpr_T1(rS(ctx->opcode)); \
@@ -2193,19 +2254,50 @@ GEN_STS(w, 0x04, PPC_INTEGER); @@ -2193,19 +2254,50 @@ GEN_STS(w, 0x04, PPC_INTEGER);
2193 OP_ST_TABLE(d); 2254 OP_ST_TABLE(d);
2194 GEN_STUX(d, 0x15, 0x05, PPC_64B); 2255 GEN_STUX(d, 0x15, 0x05, PPC_64B);
2195 GEN_STX(d, 0x15, 0x04, PPC_64B); 2256 GEN_STX(d, 0x15, 0x04, PPC_64B);
2196 -GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000002, PPC_64B) 2257 +GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B)
2197 { 2258 {
2198 - if (Rc(ctx->opcode)) {  
2199 - if (unlikely(rA(ctx->opcode) == 0)) { 2259 + int rs;
  2260 +
  2261 + rs = rS(ctx->opcode);
  2262 + if ((ctx->opcode & 0x3) == 0x2) {
  2263 +#if defined(CONFIG_USER_ONLY)
  2264 + GEN_EXCP_PRIVOPC(ctx);
  2265 +#else
  2266 + /* stq */
  2267 + if (unlikely(ctx->supervisor == 0)) {
  2268 + GEN_EXCP_PRIVOPC(ctx);
  2269 + return;
  2270 + }
  2271 + if (unlikely(rs & 1)) {
2200 GEN_EXCP_INVAL(ctx); 2272 GEN_EXCP_INVAL(ctx);
2201 return; 2273 return;
2202 } 2274 }
  2275 + if (unlikely(ctx->mem_idx & 1)) {
  2276 + /* Little-endian mode is not handled */
  2277 + GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
  2278 + return;
  2279 + }
  2280 + gen_addr_imm_index(ctx, 0x03);
  2281 + gen_op_load_gpr_T1(rs);
  2282 + op_ldst(std);
  2283 + gen_op_addi(8);
  2284 + gen_op_load_gpr_T1(rs + 1);
  2285 + op_ldst(std);
  2286 +#endif
  2287 + } else {
  2288 + /* std / stdu */
  2289 + if (Rc(ctx->opcode)) {
  2290 + if (unlikely(rA(ctx->opcode) == 0)) {
  2291 + GEN_EXCP_INVAL(ctx);
  2292 + return;
  2293 + }
  2294 + }
  2295 + gen_addr_imm_index(ctx, 0x03);
  2296 + gen_op_load_gpr_T1(rs);
  2297 + op_ldst(std);
  2298 + if (Rc(ctx->opcode))
  2299 + gen_op_store_T0_gpr(rA(ctx->opcode));
2203 } 2300 }
2204 - gen_addr_imm_index(ctx, 1);  
2205 - gen_op_load_gpr_T1(rS(ctx->opcode));  
2206 - op_ldst(std);  
2207 - if (Rc(ctx->opcode))  
2208 - gen_op_store_T0_gpr(rA(ctx->opcode));  
2209 } 2301 }
2210 #endif 2302 #endif
2211 /*** Integer load and store with byte reverse ***/ 2303 /*** Integer load and store with byte reverse ***/
@@ -2620,8 +2712,8 @@ GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03BFF801, PPC_MEM_SYNC) @@ -2620,8 +2712,8 @@ GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03BFF801, PPC_MEM_SYNC)
2620 GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT) 2712 GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT)
2621 { 2713 {
2622 /* Stop translation, as the CPU is supposed to sleep from now */ 2714 /* Stop translation, as the CPU is supposed to sleep from now */
2623 - /* XXX: TODO: handle this idle CPU case */  
2624 - GEN_STOP(ctx); 2715 + gen_op_wait();
  2716 + GEN_EXCP(ctx, EXCP_HLT, 1);
2625 } 2717 }
2626 2718
2627 /*** Floating-point load ***/ 2719 /*** Floating-point load ***/
@@ -3077,6 +3169,23 @@ GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B) @@ -3077,6 +3169,23 @@ GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
3077 } 3169 }
3078 #endif 3170 #endif
3079 3171
  3172 +#if defined(TARGET_PPC64H)
  3173 +GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64B)
  3174 +{
  3175 +#if defined(CONFIG_USER_ONLY)
  3176 + GEN_EXCP_PRIVOPC(ctx);
  3177 +#else
  3178 + /* Restore CPU state */
  3179 + if (unlikely(ctx->supervisor <= 1)) {
  3180 + GEN_EXCP_PRIVOPC(ctx);
  3181 + return;
  3182 + }
  3183 + gen_op_hrfid();
  3184 + GEN_SYNC(ctx);
  3185 +#endif
  3186 +}
  3187 +#endif
  3188 +
3080 /* sc */ 3189 /* sc */
3081 GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW) 3190 GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW)
3082 { 3191 {
@@ -3193,6 +3302,11 @@ static inline void gen_op_mfspr (DisasContext *ctx) @@ -3193,6 +3302,11 @@ static inline void gen_op_mfspr (DisasContext *ctx)
3193 uint32_t sprn = SPR(ctx->opcode); 3302 uint32_t sprn = SPR(ctx->opcode);
3194 3303
3195 #if !defined(CONFIG_USER_ONLY) 3304 #if !defined(CONFIG_USER_ONLY)
  3305 +#if defined(TARGET_PPC64H)
  3306 + if (ctx->supervisor == 2)
  3307 + read_cb = ctx->spr_cb[sprn].hea_read;
  3308 + else
  3309 +#endif
3196 if (ctx->supervisor) 3310 if (ctx->supervisor)
3197 read_cb = ctx->spr_cb[sprn].oea_read; 3311 read_cb = ctx->spr_cb[sprn].oea_read;
3198 else 3312 else
@@ -3253,7 +3367,7 @@ GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC) @@ -3253,7 +3367,7 @@ GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
3253 3367
3254 /* mtmsr */ 3368 /* mtmsr */
3255 #if defined(TARGET_PPC64) 3369 #if defined(TARGET_PPC64)
3256 -GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001FF801, PPC_64B) 3370 +GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
3257 { 3371 {
3258 #if defined(CONFIG_USER_ONLY) 3372 #if defined(CONFIG_USER_ONLY)
3259 GEN_EXCP_PRIVREG(ctx); 3373 GEN_EXCP_PRIVREG(ctx);
@@ -3262,12 +3376,17 @@ GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001FF801, PPC_64B) @@ -3262,12 +3376,17 @@ GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001FF801, PPC_64B)
3262 GEN_EXCP_PRIVREG(ctx); 3376 GEN_EXCP_PRIVREG(ctx);
3263 return; 3377 return;
3264 } 3378 }
3265 - gen_update_nip(ctx, ctx->nip);  
3266 gen_op_load_gpr_T0(rS(ctx->opcode)); 3379 gen_op_load_gpr_T0(rS(ctx->opcode));
3267 - gen_op_store_msr();  
3268 - /* Must stop the translation as machine state (may have) changed */  
3269 - /* Note that mtmsr is not always defined as context-synchronizing */  
3270 - GEN_STOP(ctx); 3380 + if (ctx->opcode & 0x00010000) {
  3381 + /* Special form that does not need any synchronisation */
  3382 + gen_op_update_riee();
  3383 + } else {
  3384 + gen_update_nip(ctx, ctx->nip);
  3385 + gen_op_store_msr();
  3386 + /* Must stop the translation as machine state (may have) changed */
  3387 + /* Note that mtmsr is not always defined as context-synchronizing */
  3388 + GEN_STOP(ctx);
  3389 + }
3271 #endif 3390 #endif
3272 } 3391 }
3273 #endif 3392 #endif
@@ -3281,17 +3400,22 @@ GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC) @@ -3281,17 +3400,22 @@ GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
3281 GEN_EXCP_PRIVREG(ctx); 3400 GEN_EXCP_PRIVREG(ctx);
3282 return; 3401 return;
3283 } 3402 }
3284 - gen_update_nip(ctx, ctx->nip);  
3285 gen_op_load_gpr_T0(rS(ctx->opcode)); 3403 gen_op_load_gpr_T0(rS(ctx->opcode));
  3404 + if (ctx->opcode & 0x00010000) {
  3405 + /* Special form that does not need any synchronisation */
  3406 + gen_op_update_riee();
  3407 + } else {
  3408 + gen_update_nip(ctx, ctx->nip);
3286 #if defined(TARGET_PPC64) 3409 #if defined(TARGET_PPC64)
3287 - if (!ctx->sf_mode)  
3288 - gen_op_store_msr_32();  
3289 - else 3410 + if (!ctx->sf_mode)
  3411 + gen_op_store_msr_32();
  3412 + else
3290 #endif 3413 #endif
3291 - gen_op_store_msr();  
3292 - /* Must stop the translation as machine state (may have) changed */  
3293 - /* Note that mtmsrd is not always defined as context-synchronizing */  
3294 - GEN_STOP(ctx); 3414 + gen_op_store_msr();
  3415 + /* Must stop the translation as machine state (may have) changed */
  3416 + /* Note that mtmsrd is not always defined as context-synchronizing */
  3417 + GEN_STOP(ctx);
  3418 + }
3295 #endif 3419 #endif
3296 } 3420 }
3297 3421
@@ -3302,6 +3426,11 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC) @@ -3302,6 +3426,11 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
3302 uint32_t sprn = SPR(ctx->opcode); 3426 uint32_t sprn = SPR(ctx->opcode);
3303 3427
3304 #if !defined(CONFIG_USER_ONLY) 3428 #if !defined(CONFIG_USER_ONLY)
  3429 +#if defined(TARGET_PPC64H)
  3430 + if (ctx->supervisor == 2)
  3431 + write_cb = ctx->spr_cb[sprn].hea_write;
  3432 + else
  3433 +#endif
3305 if (ctx->supervisor) 3434 if (ctx->supervisor)
3306 write_cb = ctx->spr_cb[sprn].oea_write; 3435 write_cb = ctx->spr_cb[sprn].oea_write;
3307 else 3436 else
@@ -6011,7 +6140,12 @@ static inline int gen_intermediate_code_internal (CPUState *env, @@ -6011,7 +6140,12 @@ static inline int gen_intermediate_code_internal (CPUState *env,
6011 ctx.mem_idx |= msr_sf << 1; 6140 ctx.mem_idx |= msr_sf << 1;
6012 #endif 6141 #endif
6013 #else 6142 #else
6014 - ctx.supervisor = 1 - msr_pr; 6143 +#if defined(TARGET_PPC64H)
  6144 + if (msr_pr == 0 && msr_hv == 1)
  6145 + ctx.supervisor = 2;
  6146 + else
  6147 +#endif
  6148 + ctx.supervisor = 1 - msr_pr;
6015 ctx.mem_idx = ((1 - msr_pr) << 1) | msr_le; 6149 ctx.mem_idx = ((1 - msr_pr) << 1) | msr_le;
6016 #if defined(TARGET_PPC64) 6150 #if defined(TARGET_PPC64)
6017 ctx.mem_idx |= msr_sf << 2; 6151 ctx.mem_idx |= msr_sf << 2;