141 lines
3.8 KiB
C++
141 lines
3.8 KiB
C++
#pragma once
|
|
#include <ircolib/types.hpp>
|
|
#include <capstone/capstone.h>
|
|
#include <xbyak/xbyak.h>
|
|
#include <array>
|
|
|
|
namespace weee::core {
|
|
struct mem;
|
|
struct broadway {
|
|
broadway();
|
|
void set_pc(ircolib::u32);
|
|
void run(mem &);
|
|
|
|
private:
|
|
ircolib::u32 fetch(mem &);
|
|
void print_disasm(ircolib::u32);
|
|
void execute(ircolib::u32, mem &);
|
|
|
|
bool disasm_available = true;
|
|
ircolib::u32 pc = 0, lr = 0, ctr = 0, cr = 0, srr0 = 0, fpscr = 0, msr = 0, tbl = 0, tbu = 0;
|
|
union {
|
|
struct {
|
|
unsigned bytecount : 7;
|
|
unsigned : 22;
|
|
unsigned ca : 1;
|
|
unsigned ov : 1;
|
|
unsigned so : 1;
|
|
};
|
|
|
|
ircolib::u32 raw;
|
|
} xer;
|
|
|
|
void set_cr(ircolib::u8 value, ircolib::u8 index) {
|
|
cr &= ~(0xffff << index * 4);
|
|
cr |= (value << index * 4);
|
|
}
|
|
|
|
bool get_cr_bit(ircolib::u8 index, ircolib::u8 bit) { return (cr >> index * 4) & (1 << (4 - bit)); }
|
|
|
|
// bat registers indexes
|
|
static constexpr ircolib::u32 BAT_LOWER_OFFSET = 0;
|
|
static constexpr ircolib::u32 BAT_UPPER_OFFSET = 8;
|
|
|
|
std::array<ircolib::u32, 16> ibat, dbat;
|
|
std::array<ircolib::u32, 32> gpr{};
|
|
|
|
struct Fgr {
|
|
ircolib::u64 ps0, ps1;
|
|
};
|
|
|
|
std::array<Fgr, 32> fgrs{};
|
|
|
|
// ircolib::u32 const_gpr_lookup{};
|
|
csh capstone;
|
|
// Xbyak::CodeGenerator code;
|
|
|
|
// instructions
|
|
void decode_special1(ircolib::u32, mem &);
|
|
void decode_special2(ircolib::u32, mem &);
|
|
void decode_special3(ircolib::u32, mem &);
|
|
|
|
void branch(bool, bool, ircolib::u32);
|
|
bool test_cond_and_ctr(ircolib::u32);
|
|
|
|
void andi(ircolib::u32);
|
|
void andis(ircolib::u32);
|
|
void and(ircolib::u32);
|
|
void add(ircolib::u32);
|
|
void addc(ircolib::u32);
|
|
void adde(ircolib::u32);
|
|
void addze(ircolib::u32);
|
|
void addis(ircolib::u32);
|
|
void addi(ircolib::u32);
|
|
void addic(ircolib::u32);
|
|
void addicr(ircolib::u32);
|
|
void ori(ircolib::u32);
|
|
void oris(ircolib::u32);
|
|
void bx(ircolib::u32);
|
|
void bcx(ircolib::u32);
|
|
void mftspr(bool, ircolib::u32);
|
|
void mtcrf(ircolib::u32);
|
|
void stw(ircolib::u32, mem &);
|
|
void stb(ircolib::u32, mem &);
|
|
void stwu(ircolib::u32, mem &);
|
|
void sthu(ircolib::u32, mem &);
|
|
void stwx(ircolib::u32, mem &);
|
|
void stbu(ircolib::u32, mem &);
|
|
void sth(ircolib::u32, mem &);
|
|
void lbz(ircolib::u32, mem &);
|
|
void lwz(ircolib::u32, mem &);
|
|
void lwzx(ircolib::u32, mem &);
|
|
void lhz(ircolib::u32, mem &);
|
|
void lhzx(ircolib::u32, mem &);
|
|
void lfd(ircolib::u32, mem &);
|
|
void bclrx(ircolib::u32);
|
|
void cmpi(ircolib::u32);
|
|
void cmpli(ircolib::u32);
|
|
void cmp(ircolib::u32);
|
|
void cmpl(ircolib::u32);
|
|
void rlwinm(ircolib::u32);
|
|
void rlwimi(ircolib::u32);
|
|
void lwzu(ircolib::u32, mem &);
|
|
void rfi(ircolib::u32);
|
|
void mfcr(ircolib::u32);
|
|
void mtfsf(ircolib::u32);
|
|
void mtfsb1(ircolib::u32);
|
|
void mtfsb0(ircolib::u32);
|
|
void mfmsr(ircolib::u32);
|
|
void mtmsr(ircolib::u32);
|
|
void mullw(ircolib::u32);
|
|
void mulli(ircolib::u32);
|
|
void nand(ircolib::u32);
|
|
void subf(ircolib::u32);
|
|
void subfc(ircolib::u32);
|
|
void subfic(ircolib::u32);
|
|
void subfe(ircolib::u32);
|
|
void or (ircolib::u32);
|
|
void xori(ircolib::u32);
|
|
void divwu(ircolib::u32);
|
|
void mftb(ircolib::u32);
|
|
void sraw(ircolib::u32);
|
|
|
|
inline void cr0_update(bool condition, ircolib::s32 result) {
|
|
if (condition) {
|
|
const bool b0 = result < 0;
|
|
const bool b1 = result >= 0;
|
|
const bool b2 = result == 0;
|
|
const bool b3 = xer.so;
|
|
set_cr((b0 << 3) | (b1 << 2) | (b2 << 1) | (b3 << 0), 0);
|
|
}
|
|
}
|
|
|
|
inline void cr1_update(bool condition) {
|
|
if (condition) {
|
|
const ircolib::u8 field = (fpscr >> 28) & 0xf;
|
|
set_cr(field, 1);
|
|
}
|
|
}
|
|
};
|
|
} // namespace weee::core
|