134 |
target_ulong nip; |
target_ulong nip; |
135 |
uint32_t opcode; |
uint32_t opcode; |
136 |
uint32_t exception; |
uint32_t exception; |
137 |
/* Execution mode */ |
/* Routine used to access memory */ |
138 |
|
int mem_idx; |
139 |
|
/* Translation flags */ |
140 |
#if !defined(CONFIG_USER_ONLY) |
#if !defined(CONFIG_USER_ONLY) |
141 |
int supervisor; |
int supervisor; |
142 |
#endif |
#endif |
143 |
/* Routine used to access memory */ |
int fpu_enabled; |
|
int mem_idx; |
|
144 |
} DisasContext; |
} DisasContext; |
145 |
|
|
146 |
typedef struct opc_handler_t { |
typedef struct opc_handler_t { |
331 |
RET_EXCP(ctx, EXCP_HLT, 0); |
RET_EXCP(ctx, EXCP_HLT, 0); |
332 |
} |
} |
333 |
|
|
|
/* Special opcode to call open-firmware */ |
|
|
GEN_HANDLER(of_enter, 0x06, 0x01, 0xFF, 0x03FFFFC1, PPC_COMMON) |
|
|
{ |
|
|
RET_EXCP(ctx, EXCP_OFCALL, 0); |
|
|
} |
|
|
|
|
|
/* Special opcode to call RTAS */ |
|
|
GEN_HANDLER(rtas_enter, 0x06, 0x02, 0xFF, 0x03FFFFC1, PPC_COMMON) |
|
|
{ |
|
|
printf("RTAS entry point !\n"); |
|
|
RET_EXCP(ctx, EXCP_RTASCALL, 0); |
|
|
} |
|
|
|
|
334 |
static opc_handler_t invalid_handler = { |
static opc_handler_t invalid_handler = { |
335 |
.inval = 0xFFFFFFFF, |
.inval = 0xFFFFFFFF, |
336 |
.type = PPC_NONE, |
.type = PPC_NONE, |
752 |
#define _GEN_FLOAT_ACB(name, op1, op2) \ |
#define _GEN_FLOAT_ACB(name, op1, op2) \ |
753 |
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT) \ |
GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT) \ |
754 |
{ \ |
{ \ |
755 |
|
if (!ctx->fpu_enabled) { \ |
756 |
|
RET_EXCP(ctx, EXCP_NO_FP, 0); \ |
757 |
|
return; \ |
758 |
|
} \ |
759 |
gen_op_reset_scrfx(); \ |
gen_op_reset_scrfx(); \ |
760 |
gen_op_load_fpr_FT0(rA(ctx->opcode)); \ |
gen_op_load_fpr_FT0(rA(ctx->opcode)); \ |
761 |
gen_op_load_fpr_FT1(rC(ctx->opcode)); \ |
gen_op_load_fpr_FT1(rC(ctx->opcode)); \ |
773 |
#define _GEN_FLOAT_AB(name, op1, op2, inval) \ |
#define _GEN_FLOAT_AB(name, op1, op2, inval) \ |
774 |
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ |
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ |
775 |
{ \ |
{ \ |
776 |
|
if (!ctx->fpu_enabled) { \ |
777 |
|
RET_EXCP(ctx, EXCP_NO_FP, 0); \ |
778 |
|
return; \ |
779 |
|
} \ |
780 |
gen_op_reset_scrfx(); \ |
gen_op_reset_scrfx(); \ |
781 |
gen_op_load_fpr_FT0(rA(ctx->opcode)); \ |
gen_op_load_fpr_FT0(rA(ctx->opcode)); \ |
782 |
gen_op_load_fpr_FT1(rB(ctx->opcode)); \ |
gen_op_load_fpr_FT1(rB(ctx->opcode)); \ |
792 |
#define _GEN_FLOAT_AC(name, op1, op2, inval) \ |
#define _GEN_FLOAT_AC(name, op1, op2, inval) \ |
793 |
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ |
GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ |
794 |
{ \ |
{ \ |
795 |
|
if (!ctx->fpu_enabled) { \ |
796 |
|
RET_EXCP(ctx, EXCP_NO_FP, 0); \ |
797 |
|
return; \ |
798 |
|
} \ |
799 |
gen_op_reset_scrfx(); \ |
gen_op_reset_scrfx(); \ |
800 |
gen_op_load_fpr_FT0(rA(ctx->opcode)); \ |
gen_op_load_fpr_FT0(rA(ctx->opcode)); \ |
801 |
gen_op_load_fpr_FT1(rC(ctx->opcode)); \ |
gen_op_load_fpr_FT1(rC(ctx->opcode)); \ |
811 |
#define GEN_FLOAT_B(name, op2, op3) \ |
#define GEN_FLOAT_B(name, op2, op3) \ |
812 |
GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT) \ |
GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT) \ |
813 |
{ \ |
{ \ |
814 |
|
if (!ctx->fpu_enabled) { \ |
815 |
|
RET_EXCP(ctx, EXCP_NO_FP, 0); \ |
816 |
|
return; \ |
817 |
|
} \ |
818 |
gen_op_reset_scrfx(); \ |
gen_op_reset_scrfx(); \ |
819 |
gen_op_load_fpr_FT0(rB(ctx->opcode)); \ |
gen_op_load_fpr_FT0(rB(ctx->opcode)); \ |
820 |
gen_op_f##name(); \ |
gen_op_f##name(); \ |
826 |
#define GEN_FLOAT_BS(name, op2) \ |
#define GEN_FLOAT_BS(name, op2) \ |
827 |
GEN_HANDLER(f##name, 0x3F, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \ |
GEN_HANDLER(f##name, 0x3F, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \ |
828 |
{ \ |
{ \ |
829 |
|
if (!ctx->fpu_enabled) { \ |
830 |
|
RET_EXCP(ctx, EXCP_NO_FP, 0); \ |
831 |
|
return; \ |
832 |
|
} \ |
833 |
gen_op_reset_scrfx(); \ |
gen_op_reset_scrfx(); \ |
834 |
gen_op_load_fpr_FT0(rB(ctx->opcode)); \ |
gen_op_load_fpr_FT0(rB(ctx->opcode)); \ |
835 |
gen_op_f##name(); \ |
gen_op_f##name(); \ |
861 |
|
|
862 |
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT) |
GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT) |
863 |
{ |
{ |
864 |
|
if (!ctx->fpu_enabled) { |
865 |
|
RET_EXCP(ctx, EXCP_NO_FP, 0); |
866 |
|
return; |
867 |
|
} |
868 |
gen_op_reset_scrfx(); |
gen_op_reset_scrfx(); |
869 |
gen_op_load_fpr_FT0(rB(ctx->opcode)); |
gen_op_load_fpr_FT0(rB(ctx->opcode)); |
870 |
gen_op_fsqrts(); |
gen_op_fsqrts(); |
895 |
/* fcmpo */ |
/* fcmpo */ |
896 |
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT) |
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT) |
897 |
{ |
{ |
898 |
|
if (!ctx->fpu_enabled) { |
899 |
|
RET_EXCP(ctx, EXCP_NO_FP, 0); |
900 |
|
return; |
901 |
|
} |
902 |
gen_op_reset_scrfx(); |
gen_op_reset_scrfx(); |
903 |
gen_op_load_fpr_FT0(rA(ctx->opcode)); |
gen_op_load_fpr_FT0(rA(ctx->opcode)); |
904 |
gen_op_load_fpr_FT1(rB(ctx->opcode)); |
gen_op_load_fpr_FT1(rB(ctx->opcode)); |
909 |
/* fcmpu */ |
/* fcmpu */ |
910 |
GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT) |
GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT) |
911 |
{ |
{ |
912 |
|
if (!ctx->fpu_enabled) { |
913 |
|
RET_EXCP(ctx, EXCP_NO_FP, 0); |
914 |
|
return; |
915 |
|
} |
916 |
gen_op_reset_scrfx(); |
gen_op_reset_scrfx(); |
917 |
gen_op_load_fpr_FT0(rA(ctx->opcode)); |
gen_op_load_fpr_FT0(rA(ctx->opcode)); |
918 |
gen_op_load_fpr_FT1(rB(ctx->opcode)); |
gen_op_load_fpr_FT1(rB(ctx->opcode)); |
927 |
/* fmr - fmr. */ |
/* fmr - fmr. */ |
928 |
GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT) |
GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT) |
929 |
{ |
{ |
930 |
|
if (!ctx->fpu_enabled) { |
931 |
|
RET_EXCP(ctx, EXCP_NO_FP, 0); |
932 |
|
return; |
933 |
|
} |
934 |
gen_op_reset_scrfx(); |
gen_op_reset_scrfx(); |
935 |
gen_op_load_fpr_FT0(rB(ctx->opcode)); |
gen_op_load_fpr_FT0(rB(ctx->opcode)); |
936 |
gen_op_store_FT0_fpr(rD(ctx->opcode)); |
gen_op_store_FT0_fpr(rD(ctx->opcode)); |
947 |
/* mcrfs */ |
/* mcrfs */ |
948 |
GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT) |
GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT) |
949 |
{ |
{ |
950 |
|
if (!ctx->fpu_enabled) { |
951 |
|
RET_EXCP(ctx, EXCP_NO_FP, 0); |
952 |
|
return; |
953 |
|
} |
954 |
gen_op_load_fpscr_T0(crfS(ctx->opcode)); |
gen_op_load_fpscr_T0(crfS(ctx->opcode)); |
955 |
gen_op_store_T0_crf(crfD(ctx->opcode)); |
gen_op_store_T0_crf(crfD(ctx->opcode)); |
956 |
gen_op_clear_fpscr(crfS(ctx->opcode)); |
gen_op_clear_fpscr(crfS(ctx->opcode)); |
959 |
/* mffs */ |
/* mffs */ |
960 |
GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT) |
GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT) |
961 |
{ |
{ |
962 |
|
if (!ctx->fpu_enabled) { |
963 |
|
RET_EXCP(ctx, EXCP_NO_FP, 0); |
964 |
|
return; |
965 |
|
} |
966 |
gen_op_load_fpscr(); |
gen_op_load_fpscr(); |
967 |
gen_op_store_FT0_fpr(rD(ctx->opcode)); |
gen_op_store_FT0_fpr(rD(ctx->opcode)); |
968 |
if (Rc(ctx->opcode)) |
if (Rc(ctx->opcode)) |
974 |
{ |
{ |
975 |
uint8_t crb; |
uint8_t crb; |
976 |
|
|
977 |
|
if (!ctx->fpu_enabled) { |
978 |
|
RET_EXCP(ctx, EXCP_NO_FP, 0); |
979 |
|
return; |
980 |
|
} |
981 |
crb = crbD(ctx->opcode) >> 2; |
crb = crbD(ctx->opcode) >> 2; |
982 |
gen_op_load_fpscr_T0(crb); |
gen_op_load_fpscr_T0(crb); |
983 |
gen_op_andi_(~(1 << (crbD(ctx->opcode) & 0x03))); |
gen_op_andi_(~(1 << (crbD(ctx->opcode) & 0x03))); |
991 |
{ |
{ |
992 |
uint8_t crb; |
uint8_t crb; |
993 |
|
|
994 |
|
if (!ctx->fpu_enabled) { |
995 |
|
RET_EXCP(ctx, EXCP_NO_FP, 0); |
996 |
|
return; |
997 |
|
} |
998 |
crb = crbD(ctx->opcode) >> 2; |
crb = crbD(ctx->opcode) >> 2; |
999 |
gen_op_load_fpscr_T0(crb); |
gen_op_load_fpscr_T0(crb); |
1000 |
gen_op_ori(1 << (crbD(ctx->opcode) & 0x03)); |
gen_op_ori(1 << (crbD(ctx->opcode) & 0x03)); |
1006 |
/* mtfsf */ |
/* mtfsf */ |
1007 |
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT) |
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT) |
1008 |
{ |
{ |
1009 |
|
if (!ctx->fpu_enabled) { |
1010 |
|
RET_EXCP(ctx, EXCP_NO_FP, 0); |
1011 |
|
return; |
1012 |
|
} |
1013 |
gen_op_load_fpr_FT0(rB(ctx->opcode)); |
gen_op_load_fpr_FT0(rB(ctx->opcode)); |
1014 |
gen_op_store_fpscr(FM(ctx->opcode)); |
gen_op_store_fpscr(FM(ctx->opcode)); |
1015 |
if (Rc(ctx->opcode)) |
if (Rc(ctx->opcode)) |
1019 |
/* mtfsfi */ |
/* mtfsfi */ |
1020 |
GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT) |
GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT) |
1021 |
{ |
{ |
1022 |
|
if (!ctx->fpu_enabled) { |
1023 |
|
RET_EXCP(ctx, EXCP_NO_FP, 0); |
1024 |
|
return; |
1025 |
|
} |
1026 |
gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode)); |
gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode)); |
1027 |
if (Rc(ctx->opcode)) |
if (Rc(ctx->opcode)) |
1028 |
gen_op_set_Rc1(); |
gen_op_set_Rc1(); |
1573 |
/* stfiwx */ |
/* stfiwx */ |
1574 |
GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT) |
GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT) |
1575 |
{ |
{ |
1576 |
|
if (!ctx->fpu_enabled) { |
1577 |
|
RET_EXCP(ctx, EXCP_NO_FP, 0); |
1578 |
|
return; |
1579 |
|
} |
1580 |
RET_INVAL(ctx); |
RET_INVAL(ctx); |
1581 |
} |
} |
1582 |
|
|
3030 |
cpu_fprintf(f, "reservation 0x%08x\n", env->reserve); |
cpu_fprintf(f, "reservation 0x%08x\n", env->reserve); |
3031 |
} |
} |
3032 |
|
|
|
#if !defined(CONFIG_USER_ONLY) && defined (USE_OPENFIRMWARE) |
|
|
int setup_machine (CPUPPCState *env, uint32_t mid); |
|
|
#endif |
|
|
|
|
3033 |
CPUPPCState *cpu_ppc_init(void) |
CPUPPCState *cpu_ppc_init(void) |
3034 |
{ |
{ |
3035 |
CPUPPCState *env; |
CPUPPCState *env; |
3039 |
env = qemu_mallocz(sizeof(CPUPPCState)); |
env = qemu_mallocz(sizeof(CPUPPCState)); |
3040 |
if (!env) |
if (!env) |
3041 |
return NULL; |
return NULL; |
|
#if !defined(CONFIG_USER_ONLY) && defined (USE_OPEN_FIRMWARE) |
|
|
setup_machine(env, 0); |
|
|
#else |
|
3042 |
// env->spr[PVR] = 0; /* Basic PPC */ |
// env->spr[PVR] = 0; /* Basic PPC */ |
3043 |
env->spr[PVR] = 0x00080100; /* G3 CPU */ |
env->spr[PVR] = 0x00080100; /* G3 CPU */ |
3044 |
// env->spr[PVR] = 0x00083100; /* MPC755 (G3 embedded) */ |
// env->spr[PVR] = 0x00083100; /* MPC755 (G3 embedded) */ |
3045 |
// env->spr[PVR] = 0x00070100; /* IBM 750FX */ |
// env->spr[PVR] = 0x00070100; /* IBM 750FX */ |
|
#endif |
|
3046 |
tlb_flush(env, 1); |
tlb_flush(env, 1); |
3047 |
#if defined (DO_SINGLE_STEP) |
#if defined (DO_SINGLE_STEP) |
3048 |
/* Single step trace mode */ |
/* Single step trace mode */ |
3097 |
ctx.mem_idx = 0; |
ctx.mem_idx = 0; |
3098 |
#else |
#else |
3099 |
ctx.supervisor = 1 - msr_pr; |
ctx.supervisor = 1 - msr_pr; |
3100 |
ctx.mem_idx = (1 - msr_pr); |
ctx.mem_idx = 1 - msr_pr; |
3101 |
#endif |
#endif |
3102 |
|
ctx.fpu_enabled = msr_fp; |
3103 |
#if defined (DO_SINGLE_STEP) |
#if defined (DO_SINGLE_STEP) |
3104 |
/* Single step trace mode */ |
/* Single step trace mode */ |
3105 |
msr_se = 1; |
msr_se = 1; |