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 */ | ... | ... |