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 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
... ... @@ -131,6 +131,9 @@ void do_rfi (void);
131 131 #if defined(TARGET_PPC64)
132 132 void do_rfid (void);
133 133 #endif
  134 +#if defined(TARGET_PPC64H)
  135 +void do_hrfid (void);
  136 +#endif
134 137 void do_tlbia (void);
135 138 void do_tlbie (void);
136 139 #if defined(TARGET_PPC64)
... ...
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;
... ...