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