Commit a42bd6ccdfefbadfc34d381c42d64a78f532df63

Authored by j_mayer
1 parent 363be49c

Fix rfi instruction: do not depend on current execution mode

but on the execution mode that will be effective after the return.
Add rfci, rfdi and rfmci for BookE PowerPC.
Extend mfdcr / mtdcr and implement mfdrcx / mtdcrx.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2544 c046a42c-6fe2-441c-8c8c-71466251a162
target-ppc/op.c
... ... @@ -1821,23 +1821,11 @@ void OPPROTO op_rfi (void)
1821 1821 }
1822 1822  
1823 1823 #if defined(TARGET_PPC64)
1824   -void OPPROTO op_rfi_32 (void)
1825   -{
1826   - do_rfi_32();
1827   - RETURN();
1828   -}
1829   -
1830 1824 void OPPROTO op_rfid (void)
1831 1825 {
1832 1826 do_rfid();
1833 1827 RETURN();
1834 1828 }
1835   -
1836   -void OPPROTO op_rfid_32 (void)
1837   -{
1838   - do_rfid_32();
1839   - RETURN();
1840   -}
1841 1829 #endif
1842 1830 #endif
1843 1831  
... ... @@ -2309,28 +2297,46 @@ void OPPROTO op_405_check_satu (void)
2309 2297 }
2310 2298  
2311 2299 #if !defined(CONFIG_USER_ONLY)
2312   -void OPPROTO op_4xx_load_dcr (void)
  2300 +void OPPROTO op_load_dcr (void)
2313 2301 {
2314   - do_4xx_load_dcr(PARAM1);
  2302 + do_load_dcr();
2315 2303 RETURN();
2316 2304 }
2317 2305  
2318   -void OPPROTO op_4xx_store_dcr (void)
  2306 +void OPPROTO op_store_dcr (void)
2319 2307 {
2320   - do_4xx_store_dcr(PARAM1);
  2308 + do_store_dcr();
2321 2309 RETURN();
2322 2310 }
2323 2311  
2324 2312 /* Return from critical interrupt :
2325 2313 * same as rfi, except nip & MSR are loaded from SRR2/3 instead of SRR0/1
2326 2314 */
2327   -void OPPROTO op_4xx_rfci (void)
  2315 +void OPPROTO op_40x_rfci (void)
  2316 +{
  2317 + do_40x_rfci();
  2318 + RETURN();
  2319 +}
  2320 +
  2321 +void OPPROTO op_rfci (void)
  2322 +{
  2323 + do_rfci();
  2324 + RETURN();
  2325 +}
  2326 +
  2327 +void OPPROTO op_rfdi (void)
  2328 +{
  2329 + do_rfdi();
  2330 + RETURN();
  2331 +}
  2332 +
  2333 +void OPPROTO op_rfmci (void)
2328 2334 {
2329   - do_4xx_rfci();
  2335 + do_rfmci();
2330 2336 RETURN();
2331 2337 }
2332 2338  
2333   -void OPPROTO op_4xx_wrte (void)
  2339 +void OPPROTO op_wrte (void)
2334 2340 {
2335 2341 msr_ee = T0 >> 16;
2336 2342 RETURN();
... ...
target-ppc/op_helper.c
... ... @@ -881,12 +881,17 @@ void do_fcmpo (void)
881 881 #if !defined (CONFIG_USER_ONLY)
882 882 void do_rfi (void)
883 883 {
884   - env->nip = (target_ulong)(env->spr[SPR_SRR0] & ~0x00000003);
885   - T0 = (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL);
886 884 #if defined(TARGET_PPC64)
887   - ppc_store_msr_32(env, T0);
  885 + if (env->spr[SPR_SRR1] & (1ULL << MSR_SF)) {
  886 + env->nip = (uint64_t)(env->spr[SPR_SRR0] & ~0x00000003);
  887 + do_store_msr(env, (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
  888 + } else {
  889 + env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
  890 + ppc_store_msr_32(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
  891 + }
888 892 #else
889   - do_store_msr(env, T0);
  893 + env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
  894 + do_store_msr(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
890 895 #endif
891 896 #if defined (DEBUG_OP)
892 897 dump_rfi();
... ... @@ -895,33 +900,15 @@ void do_rfi (void)
895 900 }
896 901  
897 902 #if defined(TARGET_PPC64)
898   -void do_rfi_32 (void)
899   -{
900   - env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
901   - T0 = (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL);
902   - ppc_store_msr_32(env, T0);
903   -#if defined (DEBUG_OP)
904   - dump_rfi();
905   -#endif
906   - env->interrupt_request |= CPU_INTERRUPT_EXITTB;
907   -}
908   -
909 903 void do_rfid (void)
910 904 {
911   - env->nip = (target_ulong)(env->spr[SPR_SRR0] & ~0x00000003);
912   - T0 = (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL);
913   - do_store_msr(env, T0);
914   -#if defined (DEBUG_OP)
915   - dump_rfi();
916   -#endif
917   - env->interrupt_request |= CPU_INTERRUPT_EXITTB;
918   -}
919   -
920   -void do_rfid_32 (void)
921   -{
922   - env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
923   - T0 = (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL);
924   - do_store_msr(env, T0);
  905 + if (env->spr[SPR_SRR1] & (1ULL << MSR_SF)) {
  906 + env->nip = (uint64_t)(env->spr[SPR_SRR0] & ~0x00000003);
  907 + do_store_msr(env, (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
  908 + } else {
  909 + env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
  910 + do_store_msr(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
  911 + }
925 912 #if defined (DEBUG_OP)
926 913 dump_rfi();
927 914 #endif
... ... @@ -936,8 +923,9 @@ void do_tw (int flags)
936 923 ((int32_t)T0 > (int32_t)T1 && (flags & 0x08)) ||
937 924 ((int32_t)T0 == (int32_t)T1 && (flags & 0x04)) ||
938 925 ((uint32_t)T0 < (uint32_t)T1 && (flags & 0x02)) ||
939   - ((uint32_t)T0 > (uint32_t)T1 && (flags & 0x01)))))
  926 + ((uint32_t)T0 > (uint32_t)T1 && (flags & 0x01))))) {
940 927 do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
  928 + }
941 929 }
942 930  
943 931 #if defined(TARGET_PPC64)
... ... @@ -1196,34 +1184,84 @@ void do_405_check_sat (void)
1196 1184 }
1197 1185  
1198 1186 #if !defined(CONFIG_USER_ONLY)
1199   -void do_4xx_rfci (void)
  1187 +void do_40x_rfci (void)
1200 1188 {
1201 1189 env->nip = env->spr[SPR_40x_SRR2];
1202   - T0 = env->spr[SPR_40x_SRR3] & ~0xFFFF0000;
1203   - do_store_msr(env, T0);
  1190 + do_store_msr(env, env->spr[SPR_40x_SRR3] & ~0xFFFF0000);
  1191 +#if defined (DEBUG_OP)
  1192 + dump_rfi();
  1193 +#endif
  1194 + env->interrupt_request = CPU_INTERRUPT_EXITTB;
  1195 +}
  1196 +
  1197 +void do_rfci (void)
  1198 +{
  1199 +#if defined(TARGET_PPC64)
  1200 + if (env->spr[SPR_BOOKE_CSRR1] & (1 << MSR_CM)) {
  1201 + env->nip = (uint64_t)env->spr[SPR_BOOKE_CSRR0];
  1202 + } else
  1203 +#endif
  1204 + {
  1205 + env->nip = (uint32_t)env->spr[SPR_BOOKE_CSRR0];
  1206 + }
  1207 + do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_CSRR1] & ~0x3FFF0000);
  1208 +#if defined (DEBUG_OP)
  1209 + dump_rfi();
  1210 +#endif
  1211 + env->interrupt_request = CPU_INTERRUPT_EXITTB;
  1212 +}
  1213 +
  1214 +void do_rfdi (void)
  1215 +{
  1216 +#if defined(TARGET_PPC64)
  1217 + if (env->spr[SPR_BOOKE_DSRR1] & (1 << MSR_CM)) {
  1218 + env->nip = (uint64_t)env->spr[SPR_BOOKE_DSRR0];
  1219 + } else
  1220 +#endif
  1221 + {
  1222 + env->nip = (uint32_t)env->spr[SPR_BOOKE_DSRR0];
  1223 + }
  1224 + do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_DSRR1] & ~0x3FFF0000);
  1225 +#if defined (DEBUG_OP)
  1226 + dump_rfi();
  1227 +#endif
  1228 + env->interrupt_request = CPU_INTERRUPT_EXITTB;
  1229 +}
  1230 +
  1231 +void do_rfmci (void)
  1232 +{
  1233 +#if defined(TARGET_PPC64)
  1234 + if (env->spr[SPR_BOOKE_MCSRR1] & (1 << MSR_CM)) {
  1235 + env->nip = (uint64_t)env->spr[SPR_BOOKE_MCSRR0];
  1236 + } else
  1237 +#endif
  1238 + {
  1239 + env->nip = (uint32_t)env->spr[SPR_BOOKE_MCSRR0];
  1240 + }
  1241 + do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_MCSRR1] & ~0x3FFF0000);
1204 1242 #if defined (DEBUG_OP)
1205 1243 dump_rfi();
1206 1244 #endif
1207 1245 env->interrupt_request = CPU_INTERRUPT_EXITTB;
1208 1246 }
1209 1247  
1210   -void do_4xx_load_dcr (int dcrn)
  1248 +void do_load_dcr (void)
1211 1249 {
1212 1250 target_ulong val;
1213 1251  
1214 1252 if (unlikely(env->dcr_read == NULL))
1215 1253 do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
1216   - else if (unlikely((*env->dcr_read)(env->dcr_env, dcrn, &val) != 0))
  1254 + else if (unlikely((*env->dcr_read)(env->dcr_env, T0, &val) != 0))
1217 1255 do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG);
1218 1256 else
1219 1257 T0 = val;
1220 1258 }
1221 1259  
1222   -void do_4xx_store_dcr (int dcrn)
  1260 +void do_store_dcr (void)
1223 1261 {
1224 1262 if (unlikely(env->dcr_write == NULL))
1225 1263 do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
1226   - else if (unlikely((*env->dcr_write)(env->dcr_env, dcrn, T0) != 0))
  1264 + else if (unlikely((*env->dcr_write)(env->dcr_env, T0, T1) != 0))
1227 1265 do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG);
1228 1266 }
1229 1267  
... ...
target-ppc/op_helper.h
... ... @@ -117,9 +117,7 @@ void do_td (int flags);
117 117 #if !defined(CONFIG_USER_ONLY)
118 118 void do_rfi (void);
119 119 #if defined(TARGET_PPC64)
120   -void do_rfi_32 (void);
121 120 void do_rfid (void);
122   -void do_rfid_32 (void);
123 121 #endif
124 122 void do_tlbia (void);
125 123 void do_tlbie (void);
... ... @@ -158,9 +156,12 @@ void do_op_602_mfrom (void);
158 156 void do_405_check_ov (void);
159 157 void do_405_check_sat (void);
160 158 #if !defined(CONFIG_USER_ONLY)
161   -void do_4xx_load_dcr (int dcrn);
162   -void do_4xx_store_dcr (int dcrn);
163   -void do_4xx_rfci (void);
  159 +void do_load_dcr (void);
  160 +void do_store_dcr (void);
  161 +void do_40x_rfci (void);
  162 +void do_rfci (void);
  163 +void do_rfdi (void);
  164 +void do_rfmci (void);
164 165 void do_4xx_tlbre_lo (void);
165 166 void do_4xx_tlbre_hi (void);
166 167 void do_4xx_tlbsx (void);
... ...
target-ppc/translate.c
... ... @@ -2861,12 +2861,7 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
2861 2861 RET_PRIVOPC(ctx);
2862 2862 return;
2863 2863 }
2864   -#if defined(TARGET_PPC64)
2865   - if (!ctx->sf_mode)
2866   - gen_op_rfi_32();
2867   - else
2868   -#endif
2869   - gen_op_rfi();
  2864 + gen_op_rfi();
2870 2865 RET_CHG_FLOW(ctx);
2871 2866 #endif
2872 2867 }
... ... @@ -2882,10 +2877,7 @@ GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_FLOW)
2882 2877 RET_PRIVOPC(ctx);
2883 2878 return;
2884 2879 }
2885   - if (!ctx->sf_mode)
2886   - gen_op_rfid_32();
2887   - else
2888   - gen_op_rfid();
  2880 + gen_op_rfid();
2889 2881 RET_CHG_FLOW(ctx);
2890 2882 #endif
2891 2883 }
... ... @@ -4423,7 +4415,8 @@ GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_EMB_COMMON)
4423 4415 RET_PRIVREG(ctx);
4424 4416 return;
4425 4417 }
4426   - gen_op_4xx_load_dcr(dcrn);
  4418 + gen_op_set_T0(dcrn);
  4419 + gen_op_load_dcr();
4427 4420 gen_op_store_T0_gpr(rD(ctx->opcode));
4428 4421 #endif
4429 4422 }
... ... @@ -4440,8 +4433,41 @@ GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_EMB_COMMON)
4440 4433 RET_PRIVREG(ctx);
4441 4434 return;
4442 4435 }
4443   - gen_op_load_gpr_T0(rS(ctx->opcode));
4444   - gen_op_4xx_store_dcr(dcrn);
  4436 + gen_op_set_T0(dcrn);
  4437 + gen_op_load_gpr_T1(rS(ctx->opcode));
  4438 + gen_op_store_dcr();
  4439 +#endif
  4440 +}
  4441 +
  4442 +/* mfdcrx */
  4443 +GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000001, PPC_BOOKE)
  4444 +{
  4445 +#if defined(CONFIG_USER_ONLY)
  4446 + RET_PRIVREG(ctx);
  4447 +#else
  4448 + if (unlikely(!ctx->supervisor)) {
  4449 + RET_PRIVREG(ctx);
  4450 + return;
  4451 + }
  4452 + gen_op_load_gpr_T0(rA(ctx->opcode));
  4453 + gen_op_load_dcr();
  4454 + gen_op_store_T0_gpr(rD(ctx->opcode));
  4455 +#endif
  4456 +}
  4457 +
  4458 +/* mtdcrx */
  4459 +GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000001, PPC_BOOKE)
  4460 +{
  4461 +#if defined(CONFIG_USER_ONLY)
  4462 + RET_PRIVREG(ctx);
  4463 +#else
  4464 + if (unlikely(!ctx->supervisor)) {
  4465 + RET_PRIVREG(ctx);
  4466 + return;
  4467 + }
  4468 + gen_op_load_gpr_T0(rA(ctx->opcode));
  4469 + gen_op_load_gpr_T1(rS(ctx->opcode));
  4470 + gen_op_store_dcr();
4445 4471 #endif
4446 4472 }
4447 4473  
... ... @@ -4513,7 +4539,38 @@ GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
4513 4539 }
4514 4540  
4515 4541 /* rfci (supervisor only) */
4516   -GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_EMB_COMMON)
  4542 +GEN_HANDLER(rfci_40x, 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
  4543 +{
  4544 +#if defined(CONFIG_USER_ONLY)
  4545 + RET_PRIVOPC(ctx);
  4546 +#else
  4547 + if (unlikely(!ctx->supervisor)) {
  4548 + RET_PRIVOPC(ctx);
  4549 + return;
  4550 + }
  4551 + /* Restore CPU state */
  4552 + gen_op_40x_rfci();
  4553 + RET_CHG_FLOW(ctx);
  4554 +#endif
  4555 +}
  4556 +
  4557 +GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
  4558 +{
  4559 +#if defined(CONFIG_USER_ONLY)
  4560 + RET_PRIVOPC(ctx);
  4561 +#else
  4562 + if (unlikely(!ctx->supervisor)) {
  4563 + RET_PRIVOPC(ctx);
  4564 + return;
  4565 + }
  4566 + /* Restore CPU state */
  4567 + gen_op_rfci();
  4568 + RET_CHG_FLOW(ctx);
  4569 +#endif
  4570 +}
  4571 +
  4572 +/* BookE specific */
  4573 +GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_BOOKE)
4517 4574 {
4518 4575 #if defined(CONFIG_USER_ONLY)
4519 4576 RET_PRIVOPC(ctx);
... ... @@ -4523,14 +4580,28 @@ GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_EMB_COMMON)
4523 4580 return;
4524 4581 }
4525 4582 /* Restore CPU state */
4526   - gen_op_4xx_rfci();
  4583 + gen_op_rfdi();
4527 4584 RET_CHG_FLOW(ctx);
4528 4585 #endif
4529 4586 }
4530 4587  
  4588 +GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_BOOKE)
  4589 +{
  4590 +#if defined(CONFIG_USER_ONLY)
  4591 + RET_PRIVOPC(ctx);
  4592 +#else
  4593 + if (unlikely(!ctx->supervisor)) {
  4594 + RET_PRIVOPC(ctx);
  4595 + return;
  4596 + }
  4597 + /* Restore CPU state */
  4598 + gen_op_rfmci();
  4599 + RET_CHG_FLOW(ctx);
  4600 +#endif
  4601 +}
4531 4602 /* TLB management - PowerPC 405 implementation */
4532 4603 /* tlbre */
4533   -GEN_HANDLER(tlbre, 0x1F, 0x12, 0x1D, 0x00000001, PPC_EMB_COMMON)
  4604 +GEN_HANDLER(tlbre, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_SPEC)
4534 4605 {
4535 4606 #if defined(CONFIG_USER_ONLY)
4536 4607 RET_PRIVOPC(ctx);
... ... @@ -4558,7 +4629,7 @@ GEN_HANDLER(tlbre, 0x1F, 0x12, 0x1D, 0x00000001, PPC_EMB_COMMON)
4558 4629 }
4559 4630  
4560 4631 /* tlbsx - tlbsx. */
4561   -GEN_HANDLER(tlbsx, 0x1F, 0x12, 0x1C, 0x00000000, PPC_EMB_COMMON)
  4632 +GEN_HANDLER(tlbsx, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_SPEC)
4562 4633 {
4563 4634 #if defined(CONFIG_USER_ONLY)
4564 4635 RET_PRIVOPC(ctx);
... ... @@ -4615,7 +4686,7 @@ GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_EMB_COMMON)
4615 4686 return;
4616 4687 }
4617 4688 gen_op_load_gpr_T0(rD(ctx->opcode));
4618   - gen_op_4xx_wrte();
  4689 + gen_op_wrte();
4619 4690 RET_EXCP(ctx, EXCP_MTMSR, 0);
4620 4691 #endif
4621 4692 }
... ... @@ -4631,7 +4702,7 @@ GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_EMB_COMMON)
4631 4702 return;
4632 4703 }
4633 4704 gen_op_set_T0(ctx->opcode & 0x00010000);
4634   - gen_op_4xx_wrte();
  4705 + gen_op_wrte();
4635 4706 RET_EXCP(ctx, EXCP_MTMSR, 0);
4636 4707 #endif
4637 4708 }
... ...