📄 translate.c
字号:
/* fnabs */GEN_FLOAT_B(nabs, 0x08, 0x04);/* fneg */GEN_FLOAT_B(neg, 0x08, 0x01);/*** Floating-Point status & ctrl register ***//* mcrfs */GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT){ if (!ctx->fpu_enabled) { RET_EXCP(ctx, EXCP_NO_FP, 0); return; } gen_op_load_fpscr_T0(crfS(ctx->opcode)); gen_op_store_T0_crf(crfD(ctx->opcode)); gen_op_clear_fpscr(crfS(ctx->opcode));}/* mffs */GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT){ if (!ctx->fpu_enabled) { RET_EXCP(ctx, EXCP_NO_FP, 0); return; } gen_op_load_fpscr(); gen_op_store_FT0_fpr(rD(ctx->opcode)); if (Rc(ctx->opcode)) gen_op_set_Rc1();}/* mtfsb0 */GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT){ uint8_t crb; if (!ctx->fpu_enabled) { RET_EXCP(ctx, EXCP_NO_FP, 0); return; } crb = crbD(ctx->opcode) >> 2; gen_op_load_fpscr_T0(crb); gen_op_andi_(~(1 << (crbD(ctx->opcode) & 0x03))); gen_op_store_T0_fpscr(crb); if (Rc(ctx->opcode)) gen_op_set_Rc1();}/* mtfsb1 */GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT){ uint8_t crb; if (!ctx->fpu_enabled) { RET_EXCP(ctx, EXCP_NO_FP, 0); return; } crb = crbD(ctx->opcode) >> 2; gen_op_load_fpscr_T0(crb); gen_op_ori(1 << (crbD(ctx->opcode) & 0x03)); gen_op_store_T0_fpscr(crb); if (Rc(ctx->opcode)) gen_op_set_Rc1();}/* mtfsf */GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT){ if (!ctx->fpu_enabled) { RET_EXCP(ctx, EXCP_NO_FP, 0); return; } gen_op_load_fpr_FT0(rB(ctx->opcode)); gen_op_store_fpscr(FM(ctx->opcode)); if (Rc(ctx->opcode)) gen_op_set_Rc1();}/* mtfsfi */GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT){ if (!ctx->fpu_enabled) { RET_EXCP(ctx, EXCP_NO_FP, 0); return; } gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode)); if (Rc(ctx->opcode)) gen_op_set_Rc1();}/*** Integer load ***/#define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()#if defined(CONFIG_USER_ONLY)#define OP_LD_TABLE(width) \static GenOpFunc *gen_op_l##width[] = { \ &gen_op_l##width##_raw, \ &gen_op_l##width##_le_raw, \};#define OP_ST_TABLE(width) \static GenOpFunc *gen_op_st##width[] = { \ &gen_op_st##width##_raw, \ &gen_op_st##width##_le_raw, \};/* Byte access routine are endian safe */#define gen_op_stb_le_raw gen_op_stb_raw#define gen_op_lbz_le_raw gen_op_lbz_raw#else#define OP_LD_TABLE(width) \static GenOpFunc *gen_op_l##width[] = { \ &gen_op_l##width##_user, \ &gen_op_l##width##_le_user, \ &gen_op_l##width##_kernel, \ &gen_op_l##width##_le_kernel, \};#define OP_ST_TABLE(width) \static GenOpFunc *gen_op_st##width[] = { \ &gen_op_st##width##_user, \ &gen_op_st##width##_le_user, \ &gen_op_st##width##_kernel, \ &gen_op_st##width##_le_kernel, \};/* Byte access routine are endian safe */#define gen_op_stb_le_user gen_op_stb_user#define gen_op_lbz_le_user gen_op_lbz_user#define gen_op_stb_le_kernel gen_op_stb_kernel#define gen_op_lbz_le_kernel gen_op_lbz_kernel#endif#define GEN_LD(width, opc) \GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \{ \ uint32_t simm = SIMM(ctx->opcode); \ if (rA(ctx->opcode) == 0) { \ gen_op_set_T0(simm); \ } else { \ gen_op_load_gpr_T0(rA(ctx->opcode)); \ if (simm != 0) \ gen_op_addi(simm); \ } \ op_ldst(l##width); \ gen_op_store_T1_gpr(rD(ctx->opcode)); \}#define GEN_LDU(width, opc) \GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \{ \ uint32_t simm = SIMM(ctx->opcode); \ if (rA(ctx->opcode) == 0 || \ rA(ctx->opcode) == rD(ctx->opcode)) { \ RET_INVAL(ctx); \ return; \ } \ gen_op_load_gpr_T0(rA(ctx->opcode)); \ if (simm != 0) \ gen_op_addi(simm); \ op_ldst(l##width); \ gen_op_store_T1_gpr(rD(ctx->opcode)); \ gen_op_store_T0_gpr(rA(ctx->opcode)); \}#define GEN_LDUX(width, opc) \GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \{ \ if (rA(ctx->opcode) == 0 || \ rA(ctx->opcode) == rD(ctx->opcode)) { \ RET_INVAL(ctx); \ return; \ } \ gen_op_load_gpr_T0(rA(ctx->opcode)); \ gen_op_load_gpr_T1(rB(ctx->opcode)); \ gen_op_add(); \ op_ldst(l##width); \ gen_op_store_T1_gpr(rD(ctx->opcode)); \ gen_op_store_T0_gpr(rA(ctx->opcode)); \}#define GEN_LDX(width, opc2, opc3) \GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \{ \ if (rA(ctx->opcode) == 0) { \ gen_op_load_gpr_T0(rB(ctx->opcode)); \ } else { \ gen_op_load_gpr_T0(rA(ctx->opcode)); \ gen_op_load_gpr_T1(rB(ctx->opcode)); \ gen_op_add(); \ } \ op_ldst(l##width); \ gen_op_store_T1_gpr(rD(ctx->opcode)); \}#define GEN_LDS(width, op) \OP_LD_TABLE(width); \GEN_LD(width, op | 0x20); \GEN_LDU(width, op | 0x21); \GEN_LDUX(width, op | 0x01); \GEN_LDX(width, 0x17, op | 0x00)/* lbz lbzu lbzux lbzx */GEN_LDS(bz, 0x02);/* lha lhau lhaux lhax */GEN_LDS(ha, 0x0A);/* lhz lhzu lhzux lhzx */GEN_LDS(hz, 0x08);/* lwz lwzu lwzux lwzx */GEN_LDS(wz, 0x00);/*** Integer store ***/#define GEN_ST(width, opc) \GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \{ \ uint32_t simm = SIMM(ctx->opcode); \ if (rA(ctx->opcode) == 0) { \ gen_op_set_T0(simm); \ } else { \ gen_op_load_gpr_T0(rA(ctx->opcode)); \ if (simm != 0) \ gen_op_addi(simm); \ } \ gen_op_load_gpr_T1(rS(ctx->opcode)); \ op_ldst(st##width); \}#define GEN_STU(width, opc) \GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \{ \ uint32_t simm = SIMM(ctx->opcode); \ if (rA(ctx->opcode) == 0) { \ RET_INVAL(ctx); \ return; \ } \ gen_op_load_gpr_T0(rA(ctx->opcode)); \ if (simm != 0) \ gen_op_addi(simm); \ gen_op_load_gpr_T1(rS(ctx->opcode)); \ op_ldst(st##width); \ gen_op_store_T0_gpr(rA(ctx->opcode)); \}#define GEN_STUX(width, opc) \GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \{ \ if (rA(ctx->opcode) == 0) { \ RET_INVAL(ctx); \ return; \ } \ gen_op_load_gpr_T0(rA(ctx->opcode)); \ gen_op_load_gpr_T1(rB(ctx->opcode)); \ gen_op_add(); \ gen_op_load_gpr_T1(rS(ctx->opcode)); \ op_ldst(st##width); \ gen_op_store_T0_gpr(rA(ctx->opcode)); \}#define GEN_STX(width, opc2, opc3) \GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \{ \ if (rA(ctx->opcode) == 0) { \ gen_op_load_gpr_T0(rB(ctx->opcode)); \ } else { \ gen_op_load_gpr_T0(rA(ctx->opcode)); \ gen_op_load_gpr_T1(rB(ctx->opcode)); \ gen_op_add(); \ } \ gen_op_load_gpr_T1(rS(ctx->opcode)); \ op_ldst(st##width); \}#define GEN_STS(width, op) \OP_ST_TABLE(width); \GEN_ST(width, op | 0x20); \GEN_STU(width, op | 0x21); \GEN_STUX(width, op | 0x01); \GEN_STX(width, 0x17, op | 0x00)/* stb stbu stbux stbx */GEN_STS(b, 0x06);/* sth sthu sthux sthx */GEN_STS(h, 0x0C);/* stw stwu stwux stwx */GEN_STS(w, 0x04);/*** Integer load and store with byte reverse ***//* lhbrx */OP_LD_TABLE(hbr);GEN_LDX(hbr, 0x16, 0x18);/* lwbrx */OP_LD_TABLE(wbr);GEN_LDX(wbr, 0x16, 0x10);/* sthbrx */OP_ST_TABLE(hbr);GEN_STX(hbr, 0x16, 0x1C);/* stwbrx */OP_ST_TABLE(wbr);GEN_STX(wbr, 0x16, 0x14);/*** Integer load and store multiple ***/#define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)#if defined(CONFIG_USER_ONLY)static GenOpFunc1 *gen_op_lmw[] = { &gen_op_lmw_raw, &gen_op_lmw_le_raw,};static GenOpFunc1 *gen_op_stmw[] = { &gen_op_stmw_raw, &gen_op_stmw_le_raw,};#elsestatic GenOpFunc1 *gen_op_lmw[] = { &gen_op_lmw_user, &gen_op_lmw_le_user, &gen_op_lmw_kernel, &gen_op_lmw_le_kernel,};static GenOpFunc1 *gen_op_stmw[] = { &gen_op_stmw_user, &gen_op_stmw_le_user, &gen_op_stmw_kernel, &gen_op_stmw_le_kernel,};#endif/* lmw */GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER){ int simm = SIMM(ctx->opcode); if (rA(ctx->opcode) == 0) { gen_op_set_T0(simm);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -