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