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,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; |