Commit 6e473128b61901441fa2889dfa2079881895a9f9

Authored by ths
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
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 */