| 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; |