Commit be147d08790d4d80bfcf2c209031eede52b7dd62
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
Showing
5 changed files
with
213 additions
and
32 deletions
target-ppc/cpu.h
| ... | ... | @@ -287,6 +287,7 @@ enum { |
| 287 | 287 | |
| 288 | 288 | #define PPC_INPUT(env) (env->bus_model) |
| 289 | 289 | |
| 290 | +/*****************************************************************************/ | |
| 290 | 291 | typedef struct ppc_def_t ppc_def_t; |
| 291 | 292 | typedef struct opc_handler_t opc_handler_t; |
| 292 | 293 | |
| ... | ... | @@ -306,6 +307,10 @@ struct ppc_spr_t { |
| 306 | 307 | #if !defined(CONFIG_USER_ONLY) |
| 307 | 308 | void (*oea_read)(void *opaque, int spr_num); |
| 308 | 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 | 314 | #endif |
| 310 | 315 | const unsigned char *name; |
| 311 | 316 | }; |
| ... | ... | @@ -607,7 +612,9 @@ target_ulong ppc_load_xer (CPUPPCState *env); |
| 607 | 612 | void ppc_store_xer (CPUPPCState *env, target_ulong value); |
| 608 | 613 | target_ulong do_load_msr (CPUPPCState *env); |
| 609 | 614 | void do_store_msr (CPUPPCState *env, target_ulong value); |
| 615 | +#if defined(TARGET_PPC64) | |
| 610 | 616 | void ppc_store_msr_32 (CPUPPCState *env, uint32_t value); |
| 617 | +#endif | |
| 611 | 618 | |
| 612 | 619 | void do_compute_hflags (CPUPPCState *env); |
| 613 | 620 | void cpu_ppc_reset (void *opaque); | ... | ... |
target-ppc/op.c
| ... | ... | @@ -355,6 +355,13 @@ void OPPROTO op_store_msr (void) |
| 355 | 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 | 365 | #if defined (TARGET_PPC64) |
| 359 | 366 | void OPPROTO op_store_msr_32 (void) |
| 360 | 367 | { |
| ... | ... | @@ -1913,6 +1920,12 @@ void OPPROTO op_check_reservation_64 (void) |
| 1913 | 1920 | } |
| 1914 | 1921 | #endif |
| 1915 | 1922 | |
| 1923 | +void OPPROTO op_wait (void) | |
| 1924 | +{ | |
| 1925 | + env->halted = 1; | |
| 1926 | + RETURN(); | |
| 1927 | +} | |
| 1928 | + | |
| 1916 | 1929 | /* Return from interrupt */ |
| 1917 | 1930 | #if !defined(CONFIG_USER_ONLY) |
| 1918 | 1931 | void OPPROTO op_rfi (void) |
| ... | ... | @@ -1928,6 +1941,14 @@ void OPPROTO op_rfid (void) |
| 1928 | 1941 | RETURN(); |
| 1929 | 1942 | } |
| 1930 | 1943 | #endif |
| 1944 | + | |
| 1945 | +#if defined(TARGET_PPC64H) | |
| 1946 | +void OPPROTO op_hrfid (void) | |
| 1947 | +{ | |
| 1948 | + do_hrfid(); | |
| 1949 | + RETURN(); | |
| 1950 | +} | |
| 1951 | +#endif | |
| 1931 | 1952 | #endif |
| 1932 | 1953 | |
| 1933 | 1954 | /* Trap word */ |
| ... | ... | @@ -2557,6 +2578,7 @@ void OPPROTO op_store_40x_pit (void) |
| 2557 | 2578 | void OPPROTO op_store_40x_dbcr0 (void) |
| 2558 | 2579 | { |
| 2559 | 2580 | store_40x_dbcr0(env, T0); |
| 2581 | + RETURN(); | |
| 2560 | 2582 | } |
| 2561 | 2583 | |
| 2562 | 2584 | void OPPROTO op_store_40x_sler (void) |
| ... | ... | @@ -2576,7 +2598,6 @@ void OPPROTO op_store_booke_tsr (void) |
| 2576 | 2598 | store_booke_tsr(env, T0); |
| 2577 | 2599 | RETURN(); |
| 2578 | 2600 | } |
| 2579 | - | |
| 2580 | 2601 | #endif /* !defined(CONFIG_USER_ONLY) */ |
| 2581 | 2602 | |
| 2582 | 2603 | #if defined(TARGET_PPCEMB) | ... | ... |
target-ppc/op_helper.c
| ... | ... | @@ -1002,6 +1002,22 @@ void do_rfid (void) |
| 1002 | 1002 | env->interrupt_request |= CPU_INTERRUPT_EXITTB; |
| 1003 | 1003 | } |
| 1004 | 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 | 1021 | #endif |
| 1006 | 1022 | |
| 1007 | 1023 | void do_tw (int flags) | ... | ... |
target-ppc/op_helper.h
target-ppc/translate.c
| ... | ... | @@ -480,6 +480,8 @@ enum { |
| 480 | 480 | PPC_FLOAT_EXT = 0x0000080000000000ULL, |
| 481 | 481 | /* New wait instruction (PowerPC 2.0x) */ |
| 482 | 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 | 1143 | /* Set process priority to normal */ |
| 1142 | 1144 | gen_op_store_pri(4); |
| 1143 | 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 | 1174 | default: |
| 1145 | 1175 | /* nop */ |
| 1146 | 1176 | break; |
| ... | ... | @@ -1902,12 +1932,11 @@ GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT) |
| 1902 | 1932 | |
| 1903 | 1933 | /*** Addressing modes ***/ |
| 1904 | 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 | 1937 | target_long simm = SIMM(ctx->opcode); |
| 1908 | 1938 | |
| 1909 | - if (maskl) | |
| 1910 | - simm &= ~0x03; | |
| 1939 | + simm &= ~maskl; | |
| 1911 | 1940 | if (rA(ctx->opcode) == 0) { |
| 1912 | 1941 | gen_set_T0(simm); |
| 1913 | 1942 | } else { |
| ... | ... | @@ -2051,7 +2080,7 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \ |
| 2051 | 2080 | return; \ |
| 2052 | 2081 | } \ |
| 2053 | 2082 | if (type == PPC_64B) \ |
| 2054 | - gen_addr_imm_index(ctx, 1); \ | |
| 2083 | + gen_addr_imm_index(ctx, 0x03); \ | |
| 2055 | 2084 | else \ |
| 2056 | 2085 | gen_addr_imm_index(ctx, 0); \ |
| 2057 | 2086 | op_ldst(l##width); \ |
| ... | ... | @@ -2116,7 +2145,7 @@ GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B) |
| 2116 | 2145 | return; |
| 2117 | 2146 | } |
| 2118 | 2147 | } |
| 2119 | - gen_addr_imm_index(ctx, 1); | |
| 2148 | + gen_addr_imm_index(ctx, 0x03); | |
| 2120 | 2149 | if (ctx->opcode & 0x02) { |
| 2121 | 2150 | /* lwa (lwau is undefined) */ |
| 2122 | 2151 | op_ldst(lwa); |
| ... | ... | @@ -2128,6 +2157,38 @@ GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B) |
| 2128 | 2157 | if (Rc(ctx->opcode)) |
| 2129 | 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 | 2192 | #endif |
| 2132 | 2193 | |
| 2133 | 2194 | /*** Integer store ***/ |
| ... | ... | @@ -2147,7 +2208,7 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \ |
| 2147 | 2208 | return; \ |
| 2148 | 2209 | } \ |
| 2149 | 2210 | if (type == PPC_64B) \ |
| 2150 | - gen_addr_imm_index(ctx, 1); \ | |
| 2211 | + gen_addr_imm_index(ctx, 0x03); \ | |
| 2151 | 2212 | else \ |
| 2152 | 2213 | gen_addr_imm_index(ctx, 0); \ |
| 2153 | 2214 | gen_op_load_gpr_T1(rS(ctx->opcode)); \ |
| ... | ... | @@ -2193,19 +2254,50 @@ GEN_STS(w, 0x04, PPC_INTEGER); |
| 2193 | 2254 | OP_ST_TABLE(d); |
| 2194 | 2255 | GEN_STUX(d, 0x15, 0x05, PPC_64B); |
| 2195 | 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 | 2272 | GEN_EXCP_INVAL(ctx); |
| 2201 | 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 | 2302 | #endif |
| 2211 | 2303 | /*** Integer load and store with byte reverse ***/ |
| ... | ... | @@ -2620,8 +2712,8 @@ GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03BFF801, PPC_MEM_SYNC) |
| 2620 | 2712 | GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT) |
| 2621 | 2713 | { |
| 2622 | 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 | 2719 | /*** Floating-point load ***/ |
| ... | ... | @@ -3077,6 +3169,23 @@ GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B) |
| 3077 | 3169 | } |
| 3078 | 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 | 3189 | /* sc */ |
| 3081 | 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 | 3302 | uint32_t sprn = SPR(ctx->opcode); |
| 3194 | 3303 | |
| 3195 | 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 | 3310 | if (ctx->supervisor) |
| 3197 | 3311 | read_cb = ctx->spr_cb[sprn].oea_read; |
| 3198 | 3312 | else |
| ... | ... | @@ -3253,7 +3367,7 @@ GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC) |
| 3253 | 3367 | |
| 3254 | 3368 | /* mtmsr */ |
| 3255 | 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 | 3372 | #if defined(CONFIG_USER_ONLY) |
| 3259 | 3373 | GEN_EXCP_PRIVREG(ctx); |
| ... | ... | @@ -3262,12 +3376,17 @@ GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001FF801, PPC_64B) |
| 3262 | 3376 | GEN_EXCP_PRIVREG(ctx); |
| 3263 | 3377 | return; |
| 3264 | 3378 | } |
| 3265 | - gen_update_nip(ctx, ctx->nip); | |
| 3266 | 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 | 3390 | #endif |
| 3272 | 3391 | } |
| 3273 | 3392 | #endif |
| ... | ... | @@ -3281,17 +3400,22 @@ GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC) |
| 3281 | 3400 | GEN_EXCP_PRIVREG(ctx); |
| 3282 | 3401 | return; |
| 3283 | 3402 | } |
| 3284 | - gen_update_nip(ctx, ctx->nip); | |
| 3285 | 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 | 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 | 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 | 3419 | #endif |
| 3296 | 3420 | } |
| 3297 | 3421 | |
| ... | ... | @@ -3302,6 +3426,11 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC) |
| 3302 | 3426 | uint32_t sprn = SPR(ctx->opcode); |
| 3303 | 3427 | |
| 3304 | 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 | 3434 | if (ctx->supervisor) |
| 3306 | 3435 | write_cb = ctx->spr_cb[sprn].oea_write; |
| 3307 | 3436 | else |
| ... | ... | @@ -6011,7 +6140,12 @@ static inline int gen_intermediate_code_internal (CPUState *env, |
| 6011 | 6140 | ctx.mem_idx |= msr_sf << 1; |
| 6012 | 6141 | #endif |
| 6013 | 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 | 6149 | ctx.mem_idx = ((1 - msr_pr) << 1) | msr_le; |
| 6016 | 6150 | #if defined(TARGET_PPC64) |
| 6017 | 6151 | ctx.mem_idx |= msr_sf << 2; | ... | ... |