Commit 6e473128b61901441fa2889dfa2079881895a9f9
1 parent
85aa199a
Handle PX/UX status flags correctly, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2892 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
48 additions
and
7 deletions
target-mips/cpu.h
| ... | ... | @@ -260,6 +260,7 @@ struct CPUMIPSState { |
| 260 | 260 | #define MIPS_HFLAG_UM 0x0001 /* user mode */ |
| 261 | 261 | #define MIPS_HFLAG_DM 0x0008 /* Debug mode */ |
| 262 | 262 | #define MIPS_HFLAG_SM 0x0010 /* Supervisor mode */ |
| 263 | +#define MIPS_HFLAG_64 0x0020 /* 64-bit instructions enabled */ | |
| 263 | 264 | #define MIPS_HFLAG_RE 0x0040 /* Reversed endianness */ |
| 264 | 265 | /* If translation is interrupted between the branch instruction and |
| 265 | 266 | * the delay slot, record what type of branch it is so that we can | ... | ... |
target-mips/helper.c
| ... | ... | @@ -370,6 +370,7 @@ void do_interrupt (CPUState *env) |
| 370 | 370 | } |
| 371 | 371 | enter_debug_mode: |
| 372 | 372 | env->hflags |= MIPS_HFLAG_DM; |
| 373 | + env->hflags |= MIPS_HFLAG_64; | |
| 373 | 374 | env->hflags &= ~MIPS_HFLAG_UM; |
| 374 | 375 | /* EJTAG probe trap enable is not implemented... */ |
| 375 | 376 | if (!(env->CP0_Status & (1 << CP0St_EXL))) |
| ... | ... | @@ -395,6 +396,7 @@ void do_interrupt (CPUState *env) |
| 395 | 396 | env->CP0_ErrorEPC = env->PC; |
| 396 | 397 | } |
| 397 | 398 | env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); |
| 399 | + env->hflags |= MIPS_HFLAG_64; | |
| 398 | 400 | env->hflags &= ~MIPS_HFLAG_UM; |
| 399 | 401 | if (!(env->CP0_Status & (1 << CP0St_EXL))) |
| 400 | 402 | env->CP0_Cause &= ~(1 << CP0Ca_BD); |
| ... | ... | @@ -493,6 +495,7 @@ void do_interrupt (CPUState *env) |
| 493 | 495 | env->CP0_Cause &= ~(1 << CP0Ca_BD); |
| 494 | 496 | } |
| 495 | 497 | env->CP0_Status |= (1 << CP0St_EXL); |
| 498 | + env->hflags |= MIPS_HFLAG_64; | |
| 496 | 499 | env->hflags &= ~MIPS_HFLAG_UM; |
| 497 | 500 | } |
| 498 | 501 | env->hflags &= ~MIPS_HFLAG_BMASK; | ... | ... |
target-mips/op.c
| ... | ... | @@ -1358,6 +1358,12 @@ void op_mtc0_status (void) |
| 1358 | 1358 | !(env->hflags & MIPS_HFLAG_DM) && |
| 1359 | 1359 | (val & (1 << CP0St_UM))) |
| 1360 | 1360 | env->hflags |= MIPS_HFLAG_UM; |
| 1361 | +#ifdef TARGET_MIPS64 | |
| 1362 | + if ((env->hflags & MIPS_HFLAG_UM) && | |
| 1363 | + !(val & (1 << CP0St_PX)) && | |
| 1364 | + !(val & (1 << CP0St_UX))) | |
| 1365 | + env->hflags &= ~MIPS_HFLAG_64; | |
| 1366 | +#endif | |
| 1361 | 1367 | env->CP0_Status = (env->CP0_Status & ~mask) | val; |
| 1362 | 1368 | if (loglevel & CPU_LOG_EXEC) |
| 1363 | 1369 | CALL_FROM_TB2(do_mtc0_status_debug, old, val); |
| ... | ... | @@ -2338,6 +2344,12 @@ void op_eret (void) |
| 2338 | 2344 | !(env->hflags & MIPS_HFLAG_DM) && |
| 2339 | 2345 | (env->CP0_Status & (1 << CP0St_UM))) |
| 2340 | 2346 | env->hflags |= MIPS_HFLAG_UM; |
| 2347 | +#ifdef TARGET_MIPS64 | |
| 2348 | + if ((env->hflags & MIPS_HFLAG_UM) && | |
| 2349 | + !(env->CP0_Status & (1 << CP0St_PX)) && | |
| 2350 | + !(env->CP0_Status & (1 << CP0St_UX))) | |
| 2351 | + env->hflags &= ~MIPS_HFLAG_64; | |
| 2352 | +#endif | |
| 2341 | 2353 | if (loglevel & CPU_LOG_EXEC) |
| 2342 | 2354 | CALL_FROM_TB0(debug_post_eret); |
| 2343 | 2355 | env->CP0_LLAddr = 1; |
| ... | ... | @@ -2355,6 +2367,12 @@ void op_deret (void) |
| 2355 | 2367 | !(env->hflags & MIPS_HFLAG_DM) && |
| 2356 | 2368 | (env->CP0_Status & (1 << CP0St_UM))) |
| 2357 | 2369 | env->hflags |= MIPS_HFLAG_UM; |
| 2370 | +#ifdef TARGET_MIPS64 | |
| 2371 | + if ((env->hflags & MIPS_HFLAG_UM) && | |
| 2372 | + !(env->CP0_Status & (1 << CP0St_PX)) && | |
| 2373 | + !(env->CP0_Status & (1 << CP0St_UX))) | |
| 2374 | + env->hflags &= ~MIPS_HFLAG_64; | |
| 2375 | +#endif | |
| 2358 | 2376 | if (loglevel & CPU_LOG_EXEC) |
| 2359 | 2377 | CALL_FROM_TB0(debug_post_eret); |
| 2360 | 2378 | env->CP0_LLAddr = 1; | ... | ... |
target-mips/translate.c
| ... | ... | @@ -730,9 +730,9 @@ OP_ST_TABLE(dl); |
| 730 | 730 | OP_ST_TABLE(dr); |
| 731 | 731 | OP_LD_TABLE(ld); |
| 732 | 732 | OP_ST_TABLE(cd); |
| 733 | +OP_LD_TABLE(wu); | |
| 733 | 734 | #endif |
| 734 | 735 | OP_LD_TABLE(w); |
| 735 | -OP_LD_TABLE(wu); | |
| 736 | 736 | OP_LD_TABLE(wl); |
| 737 | 737 | OP_LD_TABLE(wr); |
| 738 | 738 | OP_ST_TABLE(w); |
| ... | ... | @@ -773,6 +773,11 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, |
| 773 | 773 | */ |
| 774 | 774 | switch (opc) { |
| 775 | 775 | #ifdef TARGET_MIPS64 |
| 776 | + case OPC_LWU: | |
| 777 | + op_ldst(lwu); | |
| 778 | + GEN_STORE_TN_REG(rt, T0); | |
| 779 | + opn = "lwu"; | |
| 780 | + break; | |
| 776 | 781 | case OPC_LD: |
| 777 | 782 | op_ldst(ld); |
| 778 | 783 | GEN_STORE_TN_REG(rt, T0); |
| ... | ... | @@ -823,11 +828,6 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, |
| 823 | 828 | GEN_STORE_TN_REG(rt, T0); |
| 824 | 829 | opn = "lw"; |
| 825 | 830 | break; |
| 826 | - case OPC_LWU: | |
| 827 | - op_ldst(lwu); | |
| 828 | - GEN_STORE_TN_REG(rt, T0); | |
| 829 | - opn = "lwu"; | |
| 830 | - break; | |
| 831 | 831 | case OPC_SW: |
| 832 | 832 | GEN_LOAD_REG_TN(T1, rt); |
| 833 | 833 | op_ldst(sw); |
| ... | ... | @@ -5377,14 +5377,20 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
| 5377 | 5377 | case OPC_DSRL ... OPC_DSRA: |
| 5378 | 5378 | case OPC_DSLL32: |
| 5379 | 5379 | case OPC_DSRL32 ... OPC_DSRA32: |
| 5380 | + if (!(ctx->hflags & MIPS_HFLAG_64)) | |
| 5381 | + generate_exception(ctx, EXCP_RI); | |
| 5380 | 5382 | gen_arith_imm(ctx, op1, rd, rt, sa); |
| 5381 | 5383 | break; |
| 5382 | 5384 | case OPC_DSLLV: |
| 5383 | 5385 | case OPC_DSRLV ... OPC_DSRAV: |
| 5384 | 5386 | case OPC_DADD ... OPC_DSUBU: |
| 5387 | + if (!(ctx->hflags & MIPS_HFLAG_64)) | |
| 5388 | + generate_exception(ctx, EXCP_RI); | |
| 5385 | 5389 | gen_arith(ctx, op1, rd, rs, rt); |
| 5386 | 5390 | break; |
| 5387 | 5391 | case OPC_DMULT ... OPC_DDIVU: |
| 5392 | + if (!(ctx->hflags & MIPS_HFLAG_64)) | |
| 5393 | + generate_exception(ctx, EXCP_RI); | |
| 5388 | 5394 | gen_muldiv(ctx, op1, rs, rt); |
| 5389 | 5395 | break; |
| 5390 | 5396 | #endif |
| ... | ... | @@ -5420,6 +5426,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
| 5420 | 5426 | break; |
| 5421 | 5427 | #ifdef TARGET_MIPS64 |
| 5422 | 5428 | case OPC_DCLZ ... OPC_DCLO: |
| 5429 | + if (!(ctx->hflags & MIPS_HFLAG_64)) | |
| 5430 | + generate_exception(ctx, EXCP_RI); | |
| 5423 | 5431 | gen_cl(ctx, op1, rd, rs); |
| 5424 | 5432 | break; |
| 5425 | 5433 | #endif |
| ... | ... | @@ -5491,9 +5499,13 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
| 5491 | 5499 | #ifdef TARGET_MIPS64 |
| 5492 | 5500 | case OPC_DEXTM ... OPC_DEXT: |
| 5493 | 5501 | case OPC_DINSM ... OPC_DINS: |
| 5502 | + if (!(ctx->hflags & MIPS_HFLAG_64)) | |
| 5503 | + generate_exception(ctx, EXCP_RI); | |
| 5494 | 5504 | gen_bitops(ctx, op1, rt, rs, sa, rd); |
| 5495 | 5505 | break; |
| 5496 | 5506 | case OPC_DBSHFL: |
| 5507 | + if (!(ctx->hflags & MIPS_HFLAG_64)) | |
| 5508 | + generate_exception(ctx, EXCP_RI); | |
| 5497 | 5509 | op2 = MASK_DBSHFL(ctx->opcode); |
| 5498 | 5510 | switch (op2) { |
| 5499 | 5511 | case OPC_DSBH: |
| ... | ... | @@ -5732,9 +5744,13 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
| 5732 | 5744 | case OPC_LD: |
| 5733 | 5745 | case OPC_SCD: |
| 5734 | 5746 | case OPC_SD: |
| 5747 | + if (!(ctx->hflags & MIPS_HFLAG_64)) | |
| 5748 | + generate_exception(ctx, EXCP_RI); | |
| 5735 | 5749 | gen_ldst(ctx, op, rt, rs, imm); |
| 5736 | 5750 | break; |
| 5737 | 5751 | case OPC_DADDI ... OPC_DADDIU: |
| 5752 | + if (!(ctx->hflags & MIPS_HFLAG_64)) | |
| 5753 | + generate_exception(ctx, EXCP_RI); | |
| 5738 | 5754 | gen_arith_imm(ctx, op, rt, rs, imm); |
| 5739 | 5755 | break; |
| 5740 | 5756 | #endif |
| ... | ... | @@ -6072,11 +6088,14 @@ void cpu_reset (CPUMIPSState *env) |
| 6072 | 6088 | /* If the exception was raised from a delay slot, |
| 6073 | 6089 | * come back to the jump. */ |
| 6074 | 6090 | env->CP0_ErrorEPC = env->PC - 4; |
| 6075 | - env->hflags &= ~MIPS_HFLAG_BMASK; | |
| 6076 | 6091 | } else { |
| 6077 | 6092 | env->CP0_ErrorEPC = env->PC; |
| 6078 | 6093 | } |
| 6094 | +#ifdef TARGET_MIPS64 | |
| 6095 | + env->hflags = MIPS_HFLAG_64; | |
| 6096 | +#else | |
| 6079 | 6097 | env->hflags = 0; |
| 6098 | +#endif | |
| 6080 | 6099 | env->PC = (int32_t)0xBFC00000; |
| 6081 | 6100 | env->CP0_Wired = 0; |
| 6082 | 6101 | /* SMP not implemented */ | ... | ... |