mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-07-02 23:29:37 +00:00
Initial code for the NuInterpreter.
This commit is contained in:
parent
6124dfd897
commit
d659253f91
127
cpu/ppc/interpops.h
Normal file
127
cpu/ppc/interpops.h
Normal file
|
@ -0,0 +1,127 @@
|
|||
GEN_OP(addi, {
|
||||
ppc_state.gpr[code->d1] = ppc_state.gpr[code->d2] + code->simm;
|
||||
NEXT;
|
||||
})
|
||||
|
||||
GEN_OP(adde, {
|
||||
uint32_t xer_ca = !!(ppc_state.spr[SPR::XER] & 0x20000000);
|
||||
uint32_t val_a = ppc_state.gpr[code->d2];
|
||||
uint32_t val_b = ppc_state.gpr[code->d3];
|
||||
|
||||
uint32_t result = val_a + val_b + xer_ca;
|
||||
if ((result < val_a) || (xer_ca && (result == val_a))) {
|
||||
ppc_state.spr[SPR::XER] |= 0x20000000UL;
|
||||
} else {
|
||||
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
|
||||
}
|
||||
ppc_state.gpr[code->d1] = result;
|
||||
NEXT;
|
||||
})
|
||||
|
||||
GEN_OP(addze, {
|
||||
uint32_t val_a = ppc_state.gpr[code->d2];
|
||||
uint32_t xer_ca = !!(ppc_state.spr[SPR::XER] & 0x20000000);
|
||||
uint32_t result = val_a + xer_ca;
|
||||
if (result < val_a) {
|
||||
ppc_state.spr[SPR::XER] |= 0x20000000UL;
|
||||
} else {
|
||||
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
|
||||
}
|
||||
ppc_state.gpr[code->d1] = result;
|
||||
NEXT;
|
||||
})
|
||||
|
||||
GEN_OP(andidot, {
|
||||
uint32_t result = ppc_state.gpr[code->d1] & code->uimm;
|
||||
ppc_state.gpr[code->d2] = result;
|
||||
ppc_changecrf0(result);
|
||||
NEXT;
|
||||
})
|
||||
|
||||
GEN_OP(lwz, {
|
||||
ppc_state.gpr[code->d1] = (mem_grab_dword((
|
||||
(code->d2) ? ppc_state.gpr[code->d2] : 0) + code->simm));
|
||||
NEXT;
|
||||
})
|
||||
|
||||
GEN_OP(lwzu, {
|
||||
uint32_t ea = ppc_state.gpr[code->d2] + code->simm;
|
||||
ppc_state.gpr[code->d1] = mem_grab_dword(ea);
|
||||
ppc_state.gpr[code->d2] = ea;
|
||||
NEXT;
|
||||
})
|
||||
|
||||
GEN_OP(lbz, {
|
||||
ppc_state.gpr[code->d1] = (mem_grab_byte((
|
||||
(code->d2) ? ppc_state.gpr[code->d2] : 0) + code->simm));
|
||||
NEXT;
|
||||
})
|
||||
|
||||
GEN_OP(lhz, {
|
||||
ppc_state.gpr[code->d1] = (mem_grab_word((
|
||||
(code->d2) ? ppc_state.gpr[code->d2] : 0) + code->simm));
|
||||
NEXT;
|
||||
})
|
||||
|
||||
GEN_OP(rlwinm, {
|
||||
uint32_t val_s = ppc_state.gpr[code->d1];
|
||||
uint32_t r = ((val_s << code->d3) | (val_s >> (32 - code->d3)));
|
||||
uint32_t result = r & code->uimm;
|
||||
ppc_state.gpr[code->d2] = result;
|
||||
|
||||
if (code->d4) {
|
||||
ppc_changecrf0(result);
|
||||
}
|
||||
NEXT;
|
||||
})
|
||||
|
||||
GEN_OP(srawidot, {
|
||||
uint32_t val_s = ppc_state.gpr[code->d1];
|
||||
uint32_t result = (int32_t)val_s >> code->d2;
|
||||
if ((val_s & 0x80000000UL) && (val_s & code->uimm)) {
|
||||
ppc_state.spr[SPR::XER] |= 0x20000000UL;
|
||||
} else {
|
||||
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
|
||||
}
|
||||
ppc_state.gpr[code->d2] = result;
|
||||
ppc_changecrf0(result);
|
||||
NEXT;
|
||||
})
|
||||
|
||||
GEN_OP(bc, {
|
||||
if (ppc_state.cr & code->uimm) {
|
||||
interp_tpc += code->bt;
|
||||
} else {
|
||||
NEXT;
|
||||
}
|
||||
})
|
||||
|
||||
GEN_OP(mtspr, {
|
||||
ppc_state.spr[code->uimm] = ppc_state.gpr[code->d1];
|
||||
NEXT;
|
||||
})
|
||||
|
||||
GEN_OP(bdnz, {
|
||||
if (--ppc_state.spr[SPR::CTR]) {
|
||||
interp_tpc += code->bt;
|
||||
} else {
|
||||
NEXT;
|
||||
}
|
||||
})
|
||||
|
||||
GEN_OP(bdz, {
|
||||
if (!(--ppc_state.spr[SPR::CTR])) {
|
||||
interp_tpc += code->bt;
|
||||
} else {
|
||||
NEXT;
|
||||
}
|
||||
})
|
||||
|
||||
GEN_OP(bclr, {
|
||||
// PLACEHOLDER
|
||||
})
|
||||
|
||||
GEN_OP(bexit, {
|
||||
ppc_state.pc = code->uimm; // write source pc
|
||||
interp_running = false;
|
||||
})
|
185
cpu/ppc/jittables.cpp
Normal file
185
cpu/ppc/jittables.cpp
Normal file
|
@ -0,0 +1,185 @@
|
|||
#include <cinttypes>
|
||||
#include <map>
|
||||
#include "jittables.h"
|
||||
#include "ppcdefs.h"
|
||||
|
||||
uint16_t main_index_tab[64] = {
|
||||
PPCInstr::illegal, PPCInstr::illegal, PPCInstr::illegal,
|
||||
PPCInstr::twi, PPCInstr::illegal, PPCInstr::illegal,
|
||||
PPCInstr::illegal, PPCInstr::mulli, PPCInstr::subfic,
|
||||
PPCInstr::dozi, PPCInstr::cmpli, PPCInstr::cmpi,
|
||||
PPCInstr::addic, PPCInstr::addicdot, PPCInstr::addi,
|
||||
PPCInstr::addis, PPCInstr::illegal, PPCInstr::sc,
|
||||
PPCInstr::illegal, PPCInstr::illegal, PPCInstr::rlwimix,
|
||||
PPCInstr::rlwinmx, PPCInstr::rlmi, PPCInstr::rlwnmx,
|
||||
PPCInstr::ori, PPCInstr::oris, PPCInstr::xori,
|
||||
PPCInstr::xoris, PPCInstr::andidot, PPCInstr::andisdot,
|
||||
PPCInstr::illegal, PPCInstr::illegal, PPCInstr::lwz,
|
||||
PPCInstr::lwzu, PPCInstr::lbz, PPCInstr::lbzu,
|
||||
PPCInstr::stw, PPCInstr::stwu, PPCInstr::stb,
|
||||
PPCInstr::stbu, PPCInstr::lhz, PPCInstr::lhzu,
|
||||
PPCInstr::lha, PPCInstr::lhau, PPCInstr::sth,
|
||||
PPCInstr::sthu, PPCInstr::lmw, PPCInstr::stmw,
|
||||
PPCInstr::lfs, PPCInstr::lfsu, PPCInstr::lfd,
|
||||
PPCInstr::lfdu, PPCInstr::stfs, PPCInstr::stfsu,
|
||||
PPCInstr::stfd, PPCInstr::stfdu, PPCInstr::illegal,
|
||||
PPCInstr::illegal, PPCInstr::illegal, PPCInstr::illegal,
|
||||
PPCInstr::illegal, PPCInstr::illegal, PPCInstr::illegal,
|
||||
PPCInstr::illegal
|
||||
};
|
||||
|
||||
uint16_t subgrp16_index_tab[4] = {
|
||||
PPCInstr::bc, PPCInstr::bcl, PPCInstr::bca, PPCInstr::bcla
|
||||
};
|
||||
|
||||
uint16_t subgrp18_index_tab[4] = {
|
||||
PPCInstr::b, PPCInstr::bl, PPCInstr::ba, PPCInstr::bla
|
||||
};
|
||||
|
||||
uint16_t subgrp19_index_tab[2048] = { PPCInstr::illegal };
|
||||
|
||||
uint16_t subgrp31_index_tab[2048] = { PPCInstr::illegal };
|
||||
|
||||
uint16_t subgrp59_index_tab[64] = { PPCInstr::illegal };
|
||||
|
||||
uint16_t subgrp63_index_tab[2048] = { PPCInstr::illegal };
|
||||
|
||||
static std::map<uint16_t, PPCInstr> Subop19Init = {
|
||||
{ 32, PPCInstr::bclr },
|
||||
{ 33, PPCInstr::bclrl },
|
||||
{ 66, PPCInstr::crnor },
|
||||
{ 100, PPCInstr::rfi },
|
||||
{ 258, PPCInstr::crandc },
|
||||
{ 300, PPCInstr::isync },
|
||||
{ 386, PPCInstr::crxor },
|
||||
{ 450, PPCInstr::crnand },
|
||||
{ 514, PPCInstr::crand },
|
||||
{ 578, PPCInstr::creqv },
|
||||
{ 834, PPCInstr::crorc },
|
||||
{ 898, PPCInstr::cror },
|
||||
{ 1056, PPCInstr::bcctr },
|
||||
{ 1057, PPCInstr::bcctrl }
|
||||
};
|
||||
|
||||
static std::map<uint16_t, PPCInstr> Subop31Init = {
|
||||
{ 0, PPCInstr::cmp}, { 8, PPCInstr::tw},
|
||||
{ 16, PPCInstr::subfc}, { 17, PPCInstr::subfcdot},
|
||||
{ 20, PPCInstr::addc}, { 21, PPCInstr::addcdot},
|
||||
{ 22, PPCInstr::mulhwu}, { 23, PPCInstr::mulhwudot},
|
||||
{ 38, PPCInstr::mfcr}, { 40, PPCInstr::lwarx},
|
||||
{ 46, PPCInstr::lwzx}, { 48, PPCInstr::slw},
|
||||
{ 49, PPCInstr::slwdot}, { 52, PPCInstr::cntlzw},
|
||||
{ 53, PPCInstr::cntlzwdot}, { 56, PPCInstr::ppc_and},
|
||||
{ 57, PPCInstr::anddot}, { 58, PPCInstr::maskg},
|
||||
{ 59, PPCInstr::maskgdot}, { 64, PPCInstr::cmpl},
|
||||
{ 80, PPCInstr::subf}, { 81, PPCInstr::subfdot},
|
||||
{ 108, PPCInstr::dcbst}, { 110, PPCInstr::lwzux},
|
||||
{ 120, PPCInstr::andc}, { 121, PPCInstr::andcdot},
|
||||
{ 150, PPCInstr::mulhw}, { 151, PPCInstr::mulhwdot},
|
||||
{ 166, PPCInstr::mfmsr}, { 172, PPCInstr::dcbf},
|
||||
{ 174, PPCInstr::lbzx}, { 208, PPCInstr::neg},
|
||||
{ 209, PPCInstr::negdot}, { 214, PPCInstr::mul},
|
||||
{ 215, PPCInstr::muldot}, { 238, PPCInstr::lbzux},
|
||||
{ 248, PPCInstr::nor}, { 249, PPCInstr::nordot},
|
||||
{ 272, PPCInstr::subfe}, { 273, PPCInstr::subfedot},
|
||||
{ 276, PPCInstr::adde}, { 277, PPCInstr::addedot},
|
||||
{ 288, PPCInstr::mtcrf}, { 292, PPCInstr::mtmsr},
|
||||
{ 301, PPCInstr::stwcx}, { 302, PPCInstr::stwx},
|
||||
{ 304, PPCInstr::slq}, { 305, PPCInstr::slqdot},
|
||||
{ 306, PPCInstr::sle}, { 307, PPCInstr::sledot},
|
||||
{ 366, PPCInstr::stwux}, { 368, PPCInstr::sliq},
|
||||
{ 400, PPCInstr::subfze}, { 401, PPCInstr::subfzedot},
|
||||
{ 404, PPCInstr::addze}, { 405, PPCInstr::addzedot},
|
||||
{ 420, PPCInstr::mtsr}, { 430, PPCInstr::stbx},
|
||||
{ 432, PPCInstr::sllq}, { 433, PPCInstr::sllqdot},
|
||||
{ 434, PPCInstr::sleq}, { 436, PPCInstr::sleqdot},
|
||||
{ 464, PPCInstr::subfme}, { 465, PPCInstr::subfmedot},
|
||||
{ 468, PPCInstr::addme}, { 469, PPCInstr::addmedot},
|
||||
{ 470, PPCInstr::mullw}, { 471, PPCInstr::mullwdot},
|
||||
{ 484, PPCInstr::mtsrin}, { 492, PPCInstr::dcbtst},
|
||||
{ 494, PPCInstr::stbux}, { 496, PPCInstr::slliq},
|
||||
{ 497, PPCInstr::slliqdot}, { 528, PPCInstr::doz},
|
||||
{ 529, PPCInstr::dozdot}, { 532, PPCInstr::add},
|
||||
{ 533, PPCInstr::adddot}, { 554, PPCInstr::lscbx},
|
||||
{ 555, PPCInstr::lscbxdot}, { 556, PPCInstr::dcbt},
|
||||
{ 558, PPCInstr::lhzx}, { 568, PPCInstr::eqv},
|
||||
{ 569, PPCInstr::eqvdot}, { 612, PPCInstr::tlbie},
|
||||
{ 622, PPCInstr::lhzux}, { 632, PPCInstr::ppc_xor},
|
||||
{ 633, PPCInstr::xordot}, { 662, PPCInstr::div},
|
||||
{ 663, PPCInstr::divdot}, { 678, PPCInstr::mfspr},
|
||||
{ 686, PPCInstr::lhax}, { 720, PPCInstr::abs},
|
||||
{ 721, PPCInstr::absdot}, { 726, PPCInstr::divs},
|
||||
{ 727, PPCInstr::divsdot}, { 740, PPCInstr::tlbia},
|
||||
{ 742, PPCInstr::mftb}, { 750, PPCInstr::lhaux},
|
||||
{ 814, PPCInstr::sthx}, { 824, PPCInstr::orc},
|
||||
{ 825, PPCInstr::orcdot}, { 878, PPCInstr::sthux},
|
||||
{ 888, PPCInstr::ppc_or}, { 889, PPCInstr::ordot},
|
||||
{ 918, PPCInstr::divwu}, { 919, PPCInstr::divwudot},
|
||||
{ 934, PPCInstr::mtspr}, { 940, PPCInstr::dcbi},
|
||||
{ 952, PPCInstr::nand}, { 953, PPCInstr::nanddot},
|
||||
{ 976, PPCInstr::nabs}, { 977, PPCInstr::nabsdot},
|
||||
{ 982, PPCInstr::divw}, { 983, PPCInstr::divwdot},
|
||||
{ 1024, PPCInstr::mcrxr}, { 1040, PPCInstr::subfco},
|
||||
{ 1041, PPCInstr::subfcodot}, { 1044, PPCInstr::addco},
|
||||
{ 1045, PPCInstr::addcodot}, { 1062, PPCInstr::clcs},
|
||||
{ 1063, PPCInstr::clcsdot}, { 1066, PPCInstr::lswx},
|
||||
{ 1068, PPCInstr::lwbrx}, { 1070, PPCInstr::lfsx},
|
||||
{ 1072, PPCInstr::srw}, { 1073, PPCInstr::srwdot},
|
||||
{ 1074, PPCInstr::rrib}, { 1075, PPCInstr::rribdot},
|
||||
{ 1082, PPCInstr::maskir}, { 1083, PPCInstr::maskirdot},
|
||||
{ 1104, PPCInstr::subfo}, { 1105, PPCInstr::subfodot},
|
||||
{ 1132, PPCInstr::tlbsync}, { 1134, PPCInstr::lfsux},
|
||||
{ 1190, PPCInstr::mfsr}, { 1194, PPCInstr::lswi},
|
||||
{ 1196, PPCInstr::sync}, { 1198, PPCInstr::lfdx},
|
||||
{ 1232, PPCInstr::nego}, { 1233, PPCInstr::negodot},
|
||||
{ 1238, PPCInstr::mulo}, { 1239, PPCInstr::mulodot},
|
||||
{ 1262, PPCInstr::lfdux}, { 1296, PPCInstr::subfeo},
|
||||
{ 1297, PPCInstr::subfeodot}, { 1300, PPCInstr::addeo},
|
||||
{ 1301, PPCInstr::addeodot}, { 1318, PPCInstr::mfsrin},
|
||||
{ 1322, PPCInstr::stswx}, { 1324, PPCInstr::stwbrx},
|
||||
{ 1326, PPCInstr::stfsx}, { 1328, PPCInstr::srq},
|
||||
{ 1329, PPCInstr::srqdot}, { 1330, PPCInstr::sre},
|
||||
{ 1331, PPCInstr::sredot}, { 1390, PPCInstr::stfsux},
|
||||
{ 1392, PPCInstr::sriq}, { 1393, PPCInstr::sriqdot},
|
||||
{ 1424, PPCInstr::subfzeo}, { 1425, PPCInstr::subfzeodot},
|
||||
{ 1428, PPCInstr::addzeo}, { 1429, PPCInstr::addzeodot},
|
||||
{ 1450, PPCInstr::stswi}, { 1454, PPCInstr::stfdx},
|
||||
{ 1456, PPCInstr::srlq}, { 1457, PPCInstr::srlqdot},
|
||||
{ 1458, PPCInstr::sreq }, { 1459, PPCInstr::sreqdot},
|
||||
{ 1488, PPCInstr::subfmeo }, { 1489, PPCInstr::subfmeodot},
|
||||
{ 1492, PPCInstr::addmeo }, { 1493, PPCInstr::addmeodot},
|
||||
{ 1494, PPCInstr::mullwo }, { 1495, PPCInstr::mullwodot},
|
||||
{ 1518, PPCInstr::stfdux }, { 1520, PPCInstr::srliq},
|
||||
{ 1521, PPCInstr::srliqdot }, { 1552, PPCInstr::dozo},
|
||||
{ 1553, PPCInstr::dozodot }, { 1556, PPCInstr::addo},
|
||||
{ 1557, PPCInstr::addodot }, { 1580, PPCInstr::lhbrx},
|
||||
{ 1584, PPCInstr::sraw }, { 1585, PPCInstr::srawdot},
|
||||
{ 1648, PPCInstr::srawi }, { 1649, PPCInstr::srawidot},
|
||||
{ 1686, PPCInstr::divo }, { 1687, PPCInstr::divodot},
|
||||
{ 1708, PPCInstr::eieio }, { 1744, PPCInstr::abso},
|
||||
{ 1745, PPCInstr::absodot }, { 1750, PPCInstr::divso},
|
||||
{ 1751, PPCInstr::divsodot }, { 1836, PPCInstr::sthbrx},
|
||||
{ 1840, PPCInstr::sraq }, { 1841, PPCInstr::sraqdot},
|
||||
{ 1842, PPCInstr::srea }, { 1843, PPCInstr::sreadot},
|
||||
{ 1844, PPCInstr::extsh }, { 1845, PPCInstr::extshdot},
|
||||
{ 1904, PPCInstr::sraiq }, { 1905, PPCInstr::sraiqdot},
|
||||
{ 1908, PPCInstr::extsb }, { 1909, PPCInstr::extsbdot},
|
||||
{ 1942, PPCInstr::divwuo }, { 1943, PPCInstr::divwuodot},
|
||||
{ 1956, PPCInstr::tlbld }, { 1964, PPCInstr::icbi},
|
||||
{ 1966, PPCInstr::stfiwx }, { 2000, PPCInstr::nabso},
|
||||
{ 2001, PPCInstr::nabsodot }, { 2006, PPCInstr::divwo},
|
||||
{ 2007, PPCInstr::divwodot }, { 2020, PPCInstr::tlbli},
|
||||
{ 2028, PPCInstr::dcbz }
|
||||
};
|
||||
|
||||
void init_jit_tables() {
|
||||
std::map<uint16_t, PPCInstr>::iterator it;
|
||||
|
||||
for (it = Subop19Init.begin(); it != Subop19Init.end(); it++ ) {
|
||||
subgrp19_index_tab[it->first] = it->second;
|
||||
}
|
||||
|
||||
for (it = Subop31Init.begin(); it != Subop31Init.end(); it++ ) {
|
||||
subgrp31_index_tab[it->first] = it->second;
|
||||
}
|
||||
}
|
48
cpu/ppc/jittables.h
Normal file
48
cpu/ppc/jittables.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
#ifndef JIT_TABLES_H
|
||||
#define JIT_TABLES_H
|
||||
|
||||
#include <cinttypes>
|
||||
#include "ppcemu.h"
|
||||
|
||||
/** Instruction operands formats. */
|
||||
enum class InstrOps {
|
||||
opNone,
|
||||
opDA,
|
||||
opDAB,
|
||||
opDASimm,
|
||||
opSAUimm,
|
||||
opSASh,
|
||||
opRot,
|
||||
opSSpr,
|
||||
opBrRel,
|
||||
opBrLink,
|
||||
};
|
||||
|
||||
/* Control flow kind. */
|
||||
enum class CFlowType {
|
||||
CFL_NONE,
|
||||
CFL_COND_BRANCH,
|
||||
CFL_UNCOND_BRANCH,
|
||||
CFL_TRAP,
|
||||
};
|
||||
|
||||
struct InstrInfo {
|
||||
InstrOps ops_fmt; // describes operands format
|
||||
CFlowType cflow_type; // control flow type
|
||||
int num_cycles;
|
||||
|
||||
// Required by JIT
|
||||
//int flags; // flags updated by this instruction
|
||||
};
|
||||
|
||||
extern uint16_t main_index_tab[];
|
||||
extern uint16_t subgrp16_index_tab[];
|
||||
extern uint16_t subgrp18_index_tab[];
|
||||
extern uint16_t subgrp19_index_tab[];
|
||||
extern uint16_t subgrp31_index_tab[];
|
||||
extern uint16_t subgrp59_index_tab[];
|
||||
extern uint16_t subgrp63_index_tab[];
|
||||
|
||||
void init_jit_tables(void);
|
||||
|
||||
#endif /* JIT_TABLES_H */
|
238
cpu/ppc/nuinterpreter.cpp
Normal file
238
cpu/ppc/nuinterpreter.cpp
Normal file
|
@ -0,0 +1,238 @@
|
|||
#include <cinttypes>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include "ppcemu.h"
|
||||
#include "ppcmmu.h"
|
||||
#include "ppcdefs.h"
|
||||
#include "jittables.h"
|
||||
|
||||
struct CachedInstr; // forward declaration
|
||||
|
||||
typedef void (*ImplSubr)(const CachedInstr *);
|
||||
|
||||
struct CachedInstr {
|
||||
ImplSubr call_me;
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint8_t d1;
|
||||
uint8_t d2;
|
||||
uint8_t d3;
|
||||
uint8_t d4;
|
||||
};
|
||||
int32_t bt; // branch target
|
||||
};
|
||||
|
||||
union {
|
||||
int32_t simm;
|
||||
uint32_t uimm;
|
||||
};
|
||||
};
|
||||
|
||||
CachedInstr* interp_tpc;
|
||||
bool interp_running;
|
||||
|
||||
#define GEN_OP(name,body) void impl_##name(const CachedInstr* code) {body}
|
||||
#define NEXT interp_tpc++
|
||||
|
||||
#include "interpops.h"
|
||||
|
||||
struct InterpInstr {
|
||||
ImplSubr emu_fn; // pointer to the instruction emulation routine
|
||||
InstrInfo info;
|
||||
};
|
||||
|
||||
/* WARNING: entries in this table MUST be in the same order as constants in PPCInstr! */
|
||||
InterpInstr interp_tab[] = {
|
||||
{nullptr, {InstrOps::opNone, CFlowType::CFL_NONE, 0}},
|
||||
{impl_addi, {InstrOps::opDASimm, CFlowType::CFL_NONE, 1}},
|
||||
{impl_adde, {InstrOps::opDAB, CFlowType::CFL_NONE, 1}},
|
||||
{impl_addze, {InstrOps::opDA, CFlowType::CFL_NONE, 1}},
|
||||
{impl_andidot, {InstrOps::opSAUimm, CFlowType::CFL_NONE, 1}},
|
||||
{impl_lwz, {InstrOps::opDASimm, CFlowType::CFL_NONE, 1}},
|
||||
{impl_lwzu, {InstrOps::opDASimm, CFlowType::CFL_NONE, 1}},
|
||||
{impl_lbz, {InstrOps::opDASimm, CFlowType::CFL_NONE, 1}},
|
||||
{impl_lhz, {InstrOps::opDASimm, CFlowType::CFL_NONE, 1}},
|
||||
{impl_rlwinm, {InstrOps::opRot, CFlowType::CFL_NONE, 1}},
|
||||
{impl_srawidot, {InstrOps::opSASh, CFlowType::CFL_NONE, 1}},
|
||||
{impl_bc, {InstrOps::opBrRel, CFlowType::CFL_COND_BRANCH, 0}},
|
||||
{impl_bdnz, {InstrOps::opBrRel, CFlowType::CFL_COND_BRANCH, 0}},
|
||||
{impl_bdz, {InstrOps::opBrRel, CFlowType::CFL_COND_BRANCH, 0}},
|
||||
{impl_bclr, {InstrOps::opBrLink, CFlowType::CFL_COND_BRANCH, 0}},
|
||||
{impl_mtspr, {InstrOps::opSSpr, CFlowType::CFL_NONE, 2}},
|
||||
{impl_bexit, {InstrOps::opNone, CFlowType::CFL_UNCOND_BRANCH, 0}},
|
||||
};
|
||||
|
||||
CachedInstr code_block[256];
|
||||
|
||||
#define REG_D(opcode) ((opcode >> 21) & 0x1F)
|
||||
#define REG_A(opcode) ((opcode >> 16) & 0x1F)
|
||||
#define REG_B(opcode) ((opcode >> 11) & 0x1F)
|
||||
#define REG_S REG_D
|
||||
#define BR_BO REG_D
|
||||
#define BR_BI REG_A
|
||||
#define SIMM(opcode) ((int32_t)((int16_t)(opcode & 0xFFFF)))
|
||||
#define UIMM(opcode) ((uint32_t)((uint16_t)(opcode & 0xFFFF)))
|
||||
|
||||
/** mask generator for rotate and shift instructions (§ 4.2.1.4 PowerpC PEM) */
|
||||
static inline uint32_t rot_mask(unsigned rot_mb, unsigned rot_me) {
|
||||
uint32_t m1 = 0xFFFFFFFFUL >> rot_mb;
|
||||
uint32_t m2 = 0xFFFFFFFFUL << (31 - rot_me);
|
||||
return ((rot_mb <= rot_me) ? m2 & m1 : m1 | m2);
|
||||
}
|
||||
|
||||
|
||||
bool PreDecode(uint32_t next_pc, CachedInstr* c_instr)
|
||||
{
|
||||
uint32_t opcode, main_opcode;
|
||||
unsigned instr_index;
|
||||
uint8_t* pc_real;
|
||||
bool done;
|
||||
|
||||
pc_real = quickinstruction_translate(next_pc);
|
||||
|
||||
//CachedInstr* c_instr = &code[0];
|
||||
|
||||
done = false;
|
||||
|
||||
while (!done) {
|
||||
opcode = ppc_cur_instruction;
|
||||
main_opcode = opcode >> 26;
|
||||
|
||||
instr_index = main_index_tab[main_opcode];
|
||||
if (!instr_index) {
|
||||
switch (main_opcode) {
|
||||
case 16:
|
||||
instr_index = subgrp16_index_tab[opcode & 3];
|
||||
break;
|
||||
case 18:
|
||||
instr_index = subgrp18_index_tab[opcode & 3];
|
||||
break;
|
||||
case 19:
|
||||
instr_index = subgrp19_index_tab[opcode & 0x7FF];
|
||||
break;
|
||||
case 31:
|
||||
instr_index = subgrp31_index_tab[opcode & 0x7FF];
|
||||
break;
|
||||
case 59:
|
||||
instr_index = subgrp59_index_tab[opcode & 0x3F];
|
||||
break;
|
||||
case 63:
|
||||
instr_index = subgrp63_index_tab[opcode & 0x7FF];
|
||||
break;
|
||||
default:
|
||||
instr_index = 0;
|
||||
}
|
||||
|
||||
if (!instr_index) {
|
||||
LOG_F(ERROR, "Illegal opcode 0x%08X - Program exception!", opcode);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const InterpInstr* p_instr = &interp_tab[instr_index];
|
||||
|
||||
c_instr->call_me = p_instr->emu_fn;
|
||||
|
||||
if (p_instr->info.cflow_type == CFlowType::CFL_UNCOND_BRANCH) {
|
||||
// finish translation block when an uncoditional branch is encountered
|
||||
done = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* pre-decode operands, immediate values etc. */
|
||||
switch (p_instr->info.ops_fmt) {
|
||||
case InstrOps::opDA:
|
||||
c_instr->d1 = REG_D(opcode);
|
||||
c_instr->d2 = REG_A(opcode);
|
||||
break;
|
||||
case InstrOps::opDAB:
|
||||
c_instr->d1 = REG_D(opcode);
|
||||
c_instr->d2 = REG_A(opcode);
|
||||
c_instr->d3 = REG_B(opcode);
|
||||
break;
|
||||
case InstrOps::opDASimm:
|
||||
c_instr->d1 = REG_D(opcode);
|
||||
c_instr->d2 = REG_A(opcode);
|
||||
c_instr->simm = SIMM(opcode);
|
||||
break;
|
||||
case InstrOps::opSAUimm:
|
||||
c_instr->d1 = REG_S(opcode);
|
||||
c_instr->d2 = REG_A(opcode);
|
||||
c_instr->uimm = UIMM(opcode);
|
||||
break;
|
||||
case InstrOps::opSASh:
|
||||
c_instr->d1 = REG_S(opcode);
|
||||
c_instr->d2 = REG_A(opcode);
|
||||
c_instr->d3 = (opcode >> 11) & 0x1F; // shift
|
||||
c_instr->uimm = (1 << c_instr->d3) - 1; // mask
|
||||
break;
|
||||
case InstrOps::opRot:
|
||||
c_instr->d1 = REG_S(opcode);
|
||||
c_instr->d2 = REG_A(opcode);
|
||||
c_instr->d3 = (opcode >> 11) & 0x1F; // shift
|
||||
c_instr->d4 = opcode & 1; // Rc bit
|
||||
c_instr->uimm = rot_mask((opcode >> 6) & 31, (opcode >> 1) & 31); //mask
|
||||
break;
|
||||
case InstrOps::opSSpr:
|
||||
c_instr->d1 = REG_S(opcode);
|
||||
c_instr->uimm = (REG_B(opcode) << 5) | REG_A(opcode);
|
||||
break;
|
||||
case InstrOps::opBrRel:
|
||||
c_instr->bt = SIMM(opcode) >> 2;
|
||||
switch (BR_BO(opcode) & 0x1E) {
|
||||
case 12:
|
||||
case 14:
|
||||
c_instr->call_me = interp_tab[PPCInstr::bc].emu_fn;
|
||||
c_instr->uimm = 0x80000000UL >> BR_BI(opcode);
|
||||
break;
|
||||
case 16:
|
||||
c_instr->call_me = interp_tab[PPCInstr::bdnz].emu_fn;
|
||||
break;
|
||||
case 18:
|
||||
c_instr->call_me = interp_tab[PPCInstr::bdz].emu_fn;
|
||||
break;
|
||||
default:
|
||||
LOG_F(ERROR, "Unsupported opcode 0x%08X - Program exception!", opcode);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case InstrOps::opBrLink:
|
||||
switch (BR_BO(opcode) & 0x1E) {
|
||||
case 20: // blr
|
||||
c_instr->call_me = interp_tab[PPCInstr::bexit].emu_fn;
|
||||
c_instr->uimm = next_pc;
|
||||
done = true;
|
||||
continue;
|
||||
default:
|
||||
LOG_F(ERROR, "Unsupported opcode 0x%08X - Program exception!", opcode);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_F(ERROR, "Unknown opcode format %d!", p_instr->info.ops_fmt);
|
||||
return false;
|
||||
}
|
||||
|
||||
c_instr++;
|
||||
|
||||
next_pc += 4;
|
||||
pc_real += 4;
|
||||
ppc_set_cur_instruction(pc_real);
|
||||
} // while
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NuInterpExec(uint32_t start_addr) {
|
||||
interp_tpc = &code_block[0];
|
||||
|
||||
if (!PreDecode(start_addr, interp_tpc)) {
|
||||
return;
|
||||
}
|
||||
|
||||
interp_running = true;
|
||||
|
||||
while(interp_running) {
|
||||
interp_tpc->call_me(interp_tpc);
|
||||
}
|
||||
}
|
2
cpu/ppc/nuinterpreter.h
Normal file
2
cpu/ppc/nuinterpreter.h
Normal file
|
@ -0,0 +1,2 @@
|
|||
//void PreDecode(uint32_t next_pc);
|
||||
void NuInterpExec(uint32_t start_addr);
|
297
cpu/ppc/ppcdefs.h
Normal file
297
cpu/ppc/ppcdefs.h
Normal file
|
@ -0,0 +1,297 @@
|
|||
#ifndef PPC_DEFS_H
|
||||
#define PPC_DEFS_H
|
||||
|
||||
/* Enumerate all supported PowerPC instructions. */
|
||||
enum PPCInstr : int {
|
||||
illegal = 0,
|
||||
addi,
|
||||
adde,
|
||||
addze,
|
||||
andidot,
|
||||
lwz,
|
||||
lwzu,
|
||||
lbz,
|
||||
lhz,
|
||||
rlwinmx,
|
||||
srawidot,
|
||||
bc,
|
||||
bdnz,
|
||||
bdz,
|
||||
bclr,
|
||||
mtspr,
|
||||
bexit, // arificial block exit opcode
|
||||
|
||||
twi,
|
||||
mulli,
|
||||
subfic,
|
||||
cmpli,
|
||||
cmpi,
|
||||
addic,
|
||||
addicdot,
|
||||
addis,
|
||||
sc,
|
||||
rlwimix,
|
||||
rlwnmx,
|
||||
ori,
|
||||
oris,
|
||||
xori,
|
||||
xoris,
|
||||
andisdot,
|
||||
lbzu,
|
||||
stw,
|
||||
stwu,
|
||||
stb,
|
||||
stbu,
|
||||
lhzu,
|
||||
lha,
|
||||
lhau,
|
||||
sth,
|
||||
sthu,
|
||||
lmw,
|
||||
stmw,
|
||||
lfs,
|
||||
lfsu,
|
||||
lfd,
|
||||
lfdu,
|
||||
stfs,
|
||||
stfsu,
|
||||
stfd,
|
||||
stfdu,
|
||||
bcl,
|
||||
bca,
|
||||
bcla,
|
||||
b,
|
||||
bl,
|
||||
ba,
|
||||
bla,
|
||||
bclrl,
|
||||
crnor,
|
||||
rfi,
|
||||
crandc,
|
||||
isync,
|
||||
crxor,
|
||||
crnand,
|
||||
crand,
|
||||
creqv,
|
||||
crorc,
|
||||
cror,
|
||||
bcctr,
|
||||
bcctrl,
|
||||
cmp,
|
||||
tw,
|
||||
subfc,
|
||||
subfcdot,
|
||||
addc,
|
||||
addcdot,
|
||||
mulhwu,
|
||||
mulhwudot,
|
||||
mfcr,
|
||||
lwarx,
|
||||
lwzx,
|
||||
slw,
|
||||
slwdot,
|
||||
cntlzw,
|
||||
cntlzwdot,
|
||||
ppc_and,
|
||||
anddot,
|
||||
cmpl,
|
||||
subf,
|
||||
subfdot,
|
||||
dcbst,
|
||||
lwzux,
|
||||
andc,
|
||||
andcdot,
|
||||
mulhw,
|
||||
mulhwdot,
|
||||
mfmsr,
|
||||
dcbf,
|
||||
lbzx,
|
||||
neg,
|
||||
negdot,
|
||||
mul,
|
||||
muldot,
|
||||
lbzux,
|
||||
nor,
|
||||
nordot,
|
||||
subfe,
|
||||
subfedot,
|
||||
addedot,
|
||||
mtcrf,
|
||||
mtmsr,
|
||||
stwcx,
|
||||
stwx,
|
||||
stwux,
|
||||
subfze,
|
||||
subfzedot,
|
||||
addzedot,
|
||||
mtsr,
|
||||
stbx,
|
||||
subfme,
|
||||
subfmedot,
|
||||
addme,
|
||||
addmedot,
|
||||
mullw,
|
||||
mullwdot,
|
||||
mtsrin,
|
||||
dcbtst,
|
||||
stbux,
|
||||
add,
|
||||
adddot,
|
||||
lscbx,
|
||||
lscbxdot,
|
||||
dcbt,
|
||||
lhzx,
|
||||
eqv,
|
||||
eqvdot,
|
||||
tlbie,
|
||||
lhzux,
|
||||
ppc_xor,
|
||||
xordot,
|
||||
div,
|
||||
divdot,
|
||||
mfspr,
|
||||
lhax,
|
||||
abs,
|
||||
absdot,
|
||||
divs,
|
||||
divsdot,
|
||||
tlbia,
|
||||
mftb,
|
||||
lhaux,
|
||||
sthx,
|
||||
orc,
|
||||
orcdot,
|
||||
sthux,
|
||||
ppc_or,
|
||||
ordot,
|
||||
divwu,
|
||||
divwudot,
|
||||
dcbi,
|
||||
nand,
|
||||
nanddot,
|
||||
divw,
|
||||
divwdot,
|
||||
mcrxr,
|
||||
subfco,
|
||||
subfcodot,
|
||||
addco,
|
||||
addcodot,
|
||||
lswx,
|
||||
lwbrx,
|
||||
lfsx,
|
||||
srw,
|
||||
srwdot,
|
||||
subfo,
|
||||
subfodot,
|
||||
tlbsync,
|
||||
lfsux,
|
||||
mfsr,
|
||||
lswi,
|
||||
sync,
|
||||
lfdx,
|
||||
nego,
|
||||
negodot,
|
||||
mulo,
|
||||
mulodot,
|
||||
lfdux,
|
||||
subfeo,
|
||||
subfeodot,
|
||||
addeo,
|
||||
addeodot,
|
||||
mfsrin,
|
||||
stswx,
|
||||
stwbrx,
|
||||
stfsx,
|
||||
stfsux,
|
||||
subfzeo,
|
||||
subfzeodot,
|
||||
addzeo,
|
||||
addzeodot,
|
||||
stswi,
|
||||
stfdx,
|
||||
subfmeo,
|
||||
subfmeodot,
|
||||
addmeo,
|
||||
addmeodot,
|
||||
mullwo,
|
||||
mullwodot,
|
||||
stfdux,
|
||||
addo,
|
||||
addodot,
|
||||
lhbrx,
|
||||
sraw,
|
||||
srawdot,
|
||||
srawi,
|
||||
eieio,
|
||||
sthbrx,
|
||||
extsh,
|
||||
extshdot,
|
||||
extsb,
|
||||
extsbdot,
|
||||
divwuo,
|
||||
divwuodot,
|
||||
tlbld,
|
||||
icbi,
|
||||
stfiwx,
|
||||
divwo,
|
||||
divwodot,
|
||||
tlbli,
|
||||
dcbz,
|
||||
|
||||
// POWER-specific
|
||||
dozi,
|
||||
rlmi,
|
||||
maskg,
|
||||
maskgdot,
|
||||
slq,
|
||||
slqdot,
|
||||
sle,
|
||||
sledot,
|
||||
sliq,
|
||||
sllq,
|
||||
sllqdot,
|
||||
sleq,
|
||||
sleqdot,
|
||||
slliq,
|
||||
slliqdot,
|
||||
doz,
|
||||
dozdot,
|
||||
nabs,
|
||||
nabsdot,
|
||||
clcs,
|
||||
clcsdot,
|
||||
rrib,
|
||||
rribdot,
|
||||
maskir,
|
||||
maskirdot,
|
||||
srq,
|
||||
srqdot,
|
||||
sre,
|
||||
sredot,
|
||||
sriq,
|
||||
sriqdot,
|
||||
srlq,
|
||||
srlqdot,
|
||||
sreq,
|
||||
sreqdot,
|
||||
srliq,
|
||||
srliqdot,
|
||||
dozo,
|
||||
dozodot,
|
||||
divo,
|
||||
divodot,
|
||||
abso,
|
||||
absodot,
|
||||
divso,
|
||||
divsodot,
|
||||
sraq,
|
||||
sraqdot,
|
||||
srea,
|
||||
sreadot,
|
||||
sraiq,
|
||||
sraiqdot,
|
||||
nabso,
|
||||
nabsodot,
|
||||
};
|
||||
|
||||
#endif /* PPC_DEFS_H */
|
Loading…
Reference in New Issue
Block a user