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