Initial libjit skeleton.

Not currently generating instructions, but most of the flow is right up to
that point. A lot of work required to refactor the emitter, but wanted to
get this checked in.
This commit is contained in:
Ben Vanik
2013-05-21 15:36:58 -07:00
parent 94e3e592dd
commit 85804f7415
44 changed files with 5272 additions and 274 deletions

View File

@@ -0,0 +1,61 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <xenia/cpu/libjit/libjit_backend.h>
#include <xenia/cpu/libjit/libjit_emit.h>
#include <xenia/cpu/libjit/libjit_jit.h>
#include <xenia/cpu/sdb/symbol_table.h>
using namespace xe;
using namespace xe::cpu;
using namespace xe::cpu::libjit;
using namespace xe::cpu::sdb;
namespace {
void InitializeIfNeeded();
void CleanupOnShutdown();
void InitializeIfNeeded() {
static bool has_initialized = false;
if (has_initialized) {
return;
}
has_initialized = true;
libjit::LibjitRegisterEmitCategoryALU();
libjit::LibjitRegisterEmitCategoryControl();
libjit::LibjitRegisterEmitCategoryFPU();
libjit::LibjitRegisterEmitCategoryMemory();
atexit(CleanupOnShutdown);
}
void CleanupOnShutdown() {
}
}
LibjitBackend::LibjitBackend() :
Backend() {
InitializeIfNeeded();
}
LibjitBackend::~LibjitBackend() {
}
LibraryLoader* LibjitBackend::CreateLibraryLoader() {
return NULL;
}
JIT* LibjitBackend::CreateJIT(xe_memory_ref memory, SymbolTable* sym_table) {
return new LibjitJIT(memory, sym_table);
}

View File

@@ -0,0 +1,41 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_CPU_LIBJIT_LIBJIT_BACKEND_H_
#define XENIA_CPU_LIBJIT_LIBJIT_BACKEND_H_
#include <xenia/common.h>
#include <xenia/cpu/backend.h>
namespace xe {
namespace cpu {
namespace libjit {
class LibjitBackend : public Backend {
public:
LibjitBackend();
virtual ~LibjitBackend();
virtual LibraryLoader* CreateLibraryLoader();
virtual JIT* CreateJIT(xe_memory_ref memory, sdb::SymbolTable* sym_table);
protected:
};
} // namespace libjit
} // namespace cpu
} // namespace xe
#endif // XENIA_CPU_LIBJIT_LIBJIT_BACKEND_H_

View File

@@ -0,0 +1,43 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_CPU_LIBJIT_LIBJIT_EMIT_H_
#define XENIA_CPU_LIBJIT_LIBJIT_EMIT_H_
#include <xenia/cpu/libjit/libjit_emitter.h>
#include <xenia/cpu/ppc/instr.h>
#include <xenia/cpu/ppc/state.h>
namespace xe {
namespace cpu {
namespace libjit {
void LibjitRegisterEmitCategoryALU();
void LibjitRegisterEmitCategoryControl();
void LibjitRegisterEmitCategoryFPU();
void LibjitRegisterEmitCategoryMemory();
#define XEEMITTER(name, opcode, format) int InstrEmit_##name
#define XEREGISTERINSTR(name, opcode) \
RegisterInstrEmit(opcode, (InstrEmitFn)InstrEmit_##name);
#define XEINSTRNOTIMPLEMENTED()
//#define XEINSTRNOTIMPLEMENTED XEASSERTALWAYS
} // namespace libjit
} // namespace cpu
} // namespace xe
#endif // XENIA_CPU_LIBJIT_LIBJIT_EMIT_H_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,709 @@
/*
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <xenia/cpu/libjit/libjit_emit.h>
using namespace xe::cpu;
using namespace xe::cpu::ppc;
using namespace xe::cpu::sdb;
namespace xe {
namespace cpu {
namespace libjit {
// int XeEmitIndirectBranchTo(
// LibjitEmitter& e, jit_function_t f, const char* src, uint32_t cia,
// bool lk, uint32_t reg) {
// // TODO(benvanik): run a DFA pass to see if we can detect whether this is
// // a normal function return that is pulling the LR from the stack that
// // it set in the prolog. If so, we can omit the dynamic check!
// // NOTE: we avoid spilling registers until we know that the target is not
// // a basic block within this function.
// Value* target;
// switch (reg) {
// case kXEPPCRegLR:
// target = e.lr_value();
// break;
// case kXEPPCRegCTR:
// target = e.ctr_value();
// break;
// default:
// XEASSERTALWAYS();
// return 1;
// }
// // Dynamic test when branching to LR, which is usually used for the return.
// // We only do this if LK=0 as returns wouldn't set LR.
// // Ideally it's a return and we can just do a simple ret and be done.
// // If it's not, we fall through to the full indirection logic.
// if (!lk && reg == kXEPPCRegLR) {
// BasicBlock* next_block = e.GetNextBasicBlock();
// BasicBlock* mismatch_bb = BasicBlock::Create(*e.context(), "lr_mismatch",
// e.gen_fn(), next_block);
// Value* lr_cmp = b.CreateICmpEQ(target, ++(e.gen_fn()->arg_begin()));
// // The return block will spill registers for us.
// b.CreateCondBr(lr_cmp, e.GetReturnBasicBlock(), mismatch_bb);
// b.SetInsertPoint(mismatch_bb);
// }
// // Defer to the generator, which will do fancy things.
// bool likely_local = !lk && reg == kXEPPCRegCTR;
// return e.GenerateIndirectionBranch(cia, target, lk, likely_local);
// }
// int XeEmitBranchTo(
// LibjitEmitter& e, jit_function_t f, const char* src, uint32_t cia,
// bool lk) {
// // Get the basic block and switch behavior based on outgoing type.
// FunctionBlock* fn_block = e.fn_block();
// switch (fn_block->outgoing_type) {
// case FunctionBlock::kTargetBlock:
// {
// BasicBlock* target_bb = e.GetBasicBlock(fn_block->outgoing_address);
// XEASSERTNOTNULL(target_bb);
// b.CreateBr(target_bb);
// break;
// }
// case FunctionBlock::kTargetFunction:
// {
// // Spill all registers to memory.
// // TODO(benvanik): only spill ones used by the target function? Use
// // calling convention flags on the function to not spill temp
// // registers?
// e.SpillRegisters();
// XEASSERTNOTNULL(fn_block->outgoing_function);
// Function* target_fn = e.GetFunction(fn_block->outgoing_function);
// Function::arg_iterator args = e.gen_fn()->arg_begin();
// Value* state_ptr = args;
// BasicBlock* next_bb = e.GetNextBasicBlock();
// if (!lk || !next_bb) {
// // Tail. No need to refill the local register values, just return.
// // We optimize this by passing in the LR from our parent instead of the
// // next instruction. This allows the return from our callee to pop
// // all the way up.
// b.CreateCall2(target_fn, state_ptr, ++args);
// b.CreateRetVoid();
// } else {
// // Will return here eventually.
// // Refill registers from state.
// b.CreateCall2(target_fn, state_ptr, b.getInt64(cia + 4));
// e.FillRegisters();
// b.CreateBr(next_bb);
// }
// break;
// }
// case FunctionBlock::kTargetLR:
// {
// // An indirect jump.
// printf("INDIRECT JUMP VIA LR: %.8X\n", cia);
// return XeEmitIndirectBranchTo(e, b, src, cia, lk, kXEPPCRegLR);
// }
// case FunctionBlock::kTargetCTR:
// {
// // An indirect jump.
// printf("INDIRECT JUMP VIA CTR: %.8X\n", cia);
// return XeEmitIndirectBranchTo(e, b, src, cia, lk, kXEPPCRegCTR);
// }
// default:
// case FunctionBlock::kTargetNone:
// XEASSERTALWAYS();
// return 1;
// }
// return 0;
// }
// XEEMITTER(bx, 0x48000000, I )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// // if AA then
// // NIA <- EXTS(LI || 0b00)
// // else
// // NIA <- CIA + EXTS(LI || 0b00)
// // if LK then
// // LR <- CIA + 4
// uint32_t nia;
// if (i.I.AA) {
// nia = XEEXTS26(i.I.LI << 2);
// } else {
// nia = i.address + XEEXTS26(i.I.LI << 2);
// }
// if (i.I.LK) {
// e.update_lr_value(b.getInt32(i.address + 4));
// }
// return XeEmitBranchTo(e, b, "bx", i.address, i.I.LK);
// }
// XEEMITTER(bcx, 0x40000000, B )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// // if ¬BO[2] then
// // CTR <- CTR - 1
// // ctr_ok <- BO[2] | ((CTR[0:63] != 0) XOR BO[3])
// // cond_ok <- BO[0] | (CR[BI+32] ≡ BO[1])
// // if ctr_ok & cond_ok then
// // if AA then
// // NIA <- EXTS(BD || 0b00)
// // else
// // NIA <- CIA + EXTS(BD || 0b00)
// // if LK then
// // LR <- CIA + 4
// // NOTE: the condition bits are reversed!
// // 01234 (docs)
// // 43210 (real)
// // TODO(benvanik): this may be wrong and overwrite LRs when not desired!
// // The docs say always, though...
// if (i.B.LK) {
// e.update_lr_value(b.getInt32(i.address + 4));
// }
// Value* ctr_ok = NULL;
// if (XESELECTBITS(i.B.BO, 2, 2)) {
// // Ignore ctr.
// } else {
// // Decrement counter.
// Value* ctr = e.ctr_value();
// ctr = b.CreateSub(ctr, b.getInt64(1));
// e.update_ctr_value(ctr);
// // Ctr check.
// if (XESELECTBITS(i.B.BO, 1, 1)) {
// ctr_ok = b.CreateICmpEQ(ctr, b.getInt64(0));
// } else {
// ctr_ok = b.CreateICmpNE(ctr, b.getInt64(0));
// }
// }
// Value* cond_ok = NULL;
// if (XESELECTBITS(i.B.BO, 4, 4)) {
// // Ignore cond.
// } else {
// Value* cr = e.cr_value(i.B.BI >> 2);
// cr = b.CreateAnd(cr, 1 << (i.B.BI & 3));
// if (XESELECTBITS(i.B.BO, 3, 3)) {
// cond_ok = b.CreateICmpNE(cr, b.getInt64(0));
// } else {
// cond_ok = b.CreateICmpEQ(cr, b.getInt64(0));
// }
// }
// // We do a bit of optimization here to make the llvm assembly easier to read.
// Value* ok = NULL;
// if (ctr_ok && cond_ok) {
// ok = b.CreateAnd(ctr_ok, cond_ok);
// } else if (ctr_ok) {
// ok = ctr_ok;
// } else if (cond_ok) {
// ok = cond_ok;
// }
// // Handle unconditional branches without extra fluff.
// BasicBlock* original_bb = b.GetInsertBlock();
// if (ok) {
// char name[32];
// xesnprintfa(name, XECOUNT(name), "loc_%.8X_bcx", i.address);
// BasicBlock* next_block = e.GetNextBasicBlock();
// BasicBlock* branch_bb = BasicBlock::Create(*e.context(), name, e.gen_fn(),
// next_block);
// b.CreateCondBr(ok, branch_bb, next_block);
// b.SetInsertPoint(branch_bb);
// }
// // Note that this occurs entirely within the branch true block.
// uint32_t nia;
// if (i.B.AA) {
// nia = XEEXTS26(i.B.BD << 2);
// } else {
// nia = i.address + XEEXTS26(i.B.BD << 2);
// }
// if (XeEmitBranchTo(e, b, "bcx", i.address, i.B.LK)) {
// return 1;
// }
// b.SetInsertPoint(original_bb);
// return 0;
// }
// XEEMITTER(bcctrx, 0x4C000420, XL )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// // cond_ok <- BO[0] | (CR[BI+32] ≡ BO[1])
// // if cond_ok then
// // NIA <- CTR[0:61] || 0b00
// // if LK then
// // LR <- CIA + 4
// // NOTE: the condition bits are reversed!
// // 01234 (docs)
// // 43210 (real)
// // TODO(benvanik): this may be wrong and overwrite LRs when not desired!
// // The docs say always, though...
// if (i.XL.LK) {
// e.update_lr_value(b.getInt32(i.address + 4));
// }
// Value* cond_ok = NULL;
// if (XESELECTBITS(i.XL.BO, 4, 4)) {
// // Ignore cond.
// } else {
// Value* cr = e.cr_value(i.XL.BI >> 2);
// cr = b.CreateAnd(cr, 1 << (i.XL.BI & 3));
// if (XESELECTBITS(i.XL.BO, 3, 3)) {
// cond_ok = b.CreateICmpNE(cr, b.getInt64(0));
// } else {
// cond_ok = b.CreateICmpEQ(cr, b.getInt64(0));
// }
// }
// // We do a bit of optimization here to make the llvm assembly easier to read.
// Value* ok = NULL;
// if (cond_ok) {
// ok = cond_ok;
// }
// // Handle unconditional branches without extra fluff.
// BasicBlock* original_bb = b.GetInsertBlock();
// if (ok) {
// char name[32];
// xesnprintfa(name, XECOUNT(name), "loc_%.8X_bcctrx", i.address);
// BasicBlock* next_block = e.GetNextBasicBlock();
// XEASSERTNOTNULL(next_block);
// BasicBlock* branch_bb = BasicBlock::Create(*e.context(), name, e.gen_fn(),
// next_block);
// b.CreateCondBr(ok, branch_bb, next_block);
// b.SetInsertPoint(branch_bb);
// }
// // Note that this occurs entirely within the branch true block.
// if (XeEmitBranchTo(e, b, "bcctrx", i.address, i.XL.LK)) {
// return 1;
// }
// b.SetInsertPoint(original_bb);
// return 0;
// }
// XEEMITTER(bclrx, 0x4C000020, XL )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// // if ¬BO[2] then
// // CTR <- CTR - 1
// // ctr_ok <- BO[2] | ((CTR[0:63] != 0) XOR BO[3]
// // cond_ok <- BO[0] | (CR[BI+32] ≡ BO[1])
// // if ctr_ok & cond_ok then
// // NIA <- LR[0:61] || 0b00
// // if LK then
// // LR <- CIA + 4
// // NOTE: the condition bits are reversed!
// // 01234 (docs)
// // 43210 (real)
// // TODO(benvanik): this may be wrong and overwrite LRs when not desired!
// // The docs say always, though...
// if (i.XL.LK) {
// e.update_lr_value(b.getInt32(i.address + 4));
// }
// Value* ctr_ok = NULL;
// if (XESELECTBITS(i.XL.BO, 2, 2)) {
// // Ignore ctr.
// } else {
// // Decrement counter.
// Value* ctr = e.ctr_value();
// ctr = b.CreateSub(ctr, b.getInt64(1));
// // Ctr check.
// if (XESELECTBITS(i.XL.BO, 1, 1)) {
// ctr_ok = b.CreateICmpEQ(ctr, b.getInt64(0));
// } else {
// ctr_ok = b.CreateICmpNE(ctr, b.getInt64(0));
// }
// }
// Value* cond_ok = NULL;
// if (XESELECTBITS(i.XL.BO, 4, 4)) {
// // Ignore cond.
// } else {
// Value* cr = e.cr_value(i.XL.BI >> 2);
// cr = b.CreateAnd(cr, 1 << (i.XL.BI & 3));
// if (XESELECTBITS(i.XL.BO, 3, 3)) {
// cond_ok = b.CreateICmpNE(cr, b.getInt64(0));
// } else {
// cond_ok = b.CreateICmpEQ(cr, b.getInt64(0));
// }
// }
// // We do a bit of optimization here to make the llvm assembly easier to read.
// Value* ok = NULL;
// if (ctr_ok && cond_ok) {
// ok = b.CreateAnd(ctr_ok, cond_ok);
// } else if (ctr_ok) {
// ok = ctr_ok;
// } else if (cond_ok) {
// ok = cond_ok;
// }
// // Handle unconditional branches without extra fluff.
// BasicBlock* original_bb = b.GetInsertBlock();
// if (ok) {
// char name[32];
// xesnprintfa(name, XECOUNT(name), "loc_%.8X_bclrx", i.address);
// BasicBlock* next_block = e.GetNextBasicBlock();
// XEASSERTNOTNULL(next_block);
// BasicBlock* branch_bb = BasicBlock::Create(*e.context(), name, e.gen_fn(),
// next_block);
// b.CreateCondBr(ok, branch_bb, next_block);
// b.SetInsertPoint(branch_bb);
// }
// // Note that this occurs entirely within the branch true block.
// if (XeEmitBranchTo(e, b, "bclrx", i.address, i.XL.LK)) {
// return 1;
// }
// b.SetInsertPoint(original_bb);
// return 0;
// }
// // Condition register logical (A-23)
// XEEMITTER(crand, 0x4C000202, XL )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// XEINSTRNOTIMPLEMENTED();
// return 1;
// }
// XEEMITTER(crandc, 0x4C000102, XL )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// XEINSTRNOTIMPLEMENTED();
// return 1;
// }
// XEEMITTER(creqv, 0x4C000242, XL )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// XEINSTRNOTIMPLEMENTED();
// return 1;
// }
// XEEMITTER(crnand, 0x4C0001C2, XL )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// XEINSTRNOTIMPLEMENTED();
// return 1;
// }
// XEEMITTER(crnor, 0x4C000042, XL )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// XEINSTRNOTIMPLEMENTED();
// return 1;
// }
// XEEMITTER(cror, 0x4C000382, XL )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// XEINSTRNOTIMPLEMENTED();
// return 1;
// }
// XEEMITTER(crorc, 0x4C000342, XL )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// XEINSTRNOTIMPLEMENTED();
// return 1;
// }
// XEEMITTER(crxor, 0x4C000182, XL )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// XEINSTRNOTIMPLEMENTED();
// return 1;
// }
// XEEMITTER(mcrf, 0x4C000000, XL )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// XEINSTRNOTIMPLEMENTED();
// return 1;
// }
// // System linkage (A-24)
// XEEMITTER(sc, 0x44000002, SC )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// XEINSTRNOTIMPLEMENTED();
// return 1;
// }
// // Trap (A-25)
// int XeEmitTrap(LibjitEmitter& e, jit_function_t f, InstrData& i,
// Value* va, Value* vb, uint32_t TO) {
// // if (a < b) & TO[0] then TRAP
// // if (a > b) & TO[1] then TRAP
// // if (a = b) & TO[2] then TRAP
// // if (a <u b) & TO[3] then TRAP
// // if (a >u b) & TO[4] then TRAP
// // Bits swapped:
// // 01234
// // 43210
// if (!TO) {
// return 0;
// }
// BasicBlock* after_bb = BasicBlock::Create(*e.context(), "", e.gen_fn(),
// e.GetNextBasicBlock());
// BasicBlock* trap_bb = BasicBlock::Create(*e.context(), "", e.gen_fn(),
// after_bb);
// // Create the basic blocks (so we can chain).
// std::vector<BasicBlock*> bbs;
// if (TO & (1 << 4)) {
// bbs.push_back(BasicBlock::Create(*e.context(), "", e.gen_fn(), trap_bb));
// }
// if (TO & (1 << 3)) {
// bbs.push_back(BasicBlock::Create(*e.context(), "", e.gen_fn(), trap_bb));
// }
// if (TO & (1 << 2)) {
// bbs.push_back(BasicBlock::Create(*e.context(), "", e.gen_fn(), trap_bb));
// }
// if (TO & (1 << 1)) {
// bbs.push_back(BasicBlock::Create(*e.context(), "", e.gen_fn(), trap_bb));
// }
// if (TO & (1 << 0)) {
// bbs.push_back(BasicBlock::Create(*e.context(), "", e.gen_fn(), trap_bb));
// }
// bbs.push_back(after_bb);
// // Jump to the first bb.
// b.CreateBr(bbs.front());
// // Setup each basic block.
// std::vector<BasicBlock*>::iterator it = bbs.begin();
// if (TO & (1 << 4)) {
// // a < b
// BasicBlock* bb = *(it++);
// b.SetInsertPoint(bb);
// Value* cmp = b.CreateICmpSLT(va, vb);
// b.CreateCondBr(cmp, trap_bb, *it);
// }
// if (TO & (1 << 3)) {
// // a > b
// BasicBlock* bb = *(it++);
// b.SetInsertPoint(bb);
// Value* cmp = b.CreateICmpSGT(va, vb);
// b.CreateCondBr(cmp, trap_bb, *it);
// }
// if (TO & (1 << 2)) {
// // a = b
// BasicBlock* bb = *(it++);
// b.SetInsertPoint(bb);
// Value* cmp = b.CreateICmpEQ(va, vb);
// b.CreateCondBr(cmp, trap_bb, *it);
// }
// if (TO & (1 << 1)) {
// // a <u b
// BasicBlock* bb = *(it++);
// b.SetInsertPoint(bb);
// Value* cmp = b.CreateICmpULT(va, vb);
// b.CreateCondBr(cmp, trap_bb, *it);
// }
// if (TO & (1 << 0)) {
// // a >u b
// BasicBlock* bb = *(it++);
// b.SetInsertPoint(bb);
// Value* cmp = b.CreateICmpUGT(va, vb);
// b.CreateCondBr(cmp, trap_bb, *it);
// }
// // Create trap BB.
// b.SetInsertPoint(trap_bb);
// e.SpillRegisters();
// // TODO(benvanik): use @llvm.debugtrap? could make debugging better
// b.CreateCall2(e.gen_module()->getFunction("XeTrap"),
// e.gen_fn()->arg_begin(),
// b.getInt32(i.address));
// b.CreateBr(after_bb);
// // Resume.
// b.SetInsertPoint(after_bb);
// return 0;
// }
// XEEMITTER(td, 0x7C000088, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// // a <- (RA)
// // b <- (RB)
// // if (a < b) & TO[0] then TRAP
// // if (a > b) & TO[1] then TRAP
// // if (a = b) & TO[2] then TRAP
// // if (a <u b) & TO[3] then TRAP
// // if (a >u b) & TO[4] then TRAP
// return XeEmitTrap(e, b, i,
// e.gpr_value(i.X.RA),
// e.gpr_value(i.X.RB),
// i.X.RT);
// }
// XEEMITTER(tdi, 0x08000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// // a <- (RA)
// // if (a < EXTS(SI)) & TO[0] then TRAP
// // if (a > EXTS(SI)) & TO[1] then TRAP
// // if (a = EXTS(SI)) & TO[2] then TRAP
// // if (a <u EXTS(SI)) & TO[3] then TRAP
// // if (a >u EXTS(SI)) & TO[4] then TRAP
// return XeEmitTrap(e, b, i,
// e.gpr_value(i.D.RA),
// b.getInt64(XEEXTS16(i.D.DS)),
// i.D.RT);
// }
// XEEMITTER(tw, 0x7C000008, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// // a <- EXTS((RA)[32:63])
// // b <- EXTS((RB)[32:63])
// // if (a < b) & TO[0] then TRAP
// // if (a > b) & TO[1] then TRAP
// // if (a = b) & TO[2] then TRAP
// // if (a <u b) & TO[3] then TRAP
// // if (a >u b) & TO[4] then TRAP
// return XeEmitTrap(e, b, i,
// b.CreateSExt(b.CreateTrunc(e.gpr_value(i.X.RA),
// b.getInt32Ty()),
// b.getInt64Ty()),
// b.CreateSExt(b.CreateTrunc(e.gpr_value(i.X.RB),
// b.getInt32Ty()),
// b.getInt64Ty()),
// i.X.RT);
// }
// XEEMITTER(twi, 0x0C000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// // a <- EXTS((RA)[32:63])
// // if (a < EXTS(SI)) & TO[0] then TRAP
// // if (a > EXTS(SI)) & TO[1] then TRAP
// // if (a = EXTS(SI)) & TO[2] then TRAP
// // if (a <u EXTS(SI)) & TO[3] then TRAP
// // if (a >u EXTS(SI)) & TO[4] then TRAP
// return XeEmitTrap(e, b, i,
// b.CreateSExt(b.CreateTrunc(e.gpr_value(i.D.RA),
// b.getInt32Ty()),
// b.getInt64Ty()),
// b.getInt64(XEEXTS16(i.D.DS)),
// i.D.RT);
// }
// // Processor control (A-26)
// XEEMITTER(mfcr, 0x7C000026, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// XEINSTRNOTIMPLEMENTED();
// return 1;
// }
// XEEMITTER(mfspr, 0x7C0002A6, XFX)(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// // n <- spr[5:9] || spr[0:4]
// // if length(SPR(n)) = 64 then
// // RT <- SPR(n)
// // else
// // RT <- i32.0 || SPR(n)
// const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
// Value* v = NULL;
// switch (n) {
// case 1:
// // XER
// v = e.xer_value();
// break;
// case 8:
// // LR
// v = e.lr_value();
// break;
// case 9:
// // CTR
// v = e.ctr_value();
// break;
// default:
// XEINSTRNOTIMPLEMENTED();
// return 1;
// }
// e.update_gpr_value(i.XFX.RT, v);
// return 0;
// }
// XEEMITTER(mftb, 0x7C0002E6, XFX)(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// XEINSTRNOTIMPLEMENTED();
// return 1;
// }
// XEEMITTER(mtcrf, 0x7C000120, XFX)(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// XEINSTRNOTIMPLEMENTED();
// return 1;
// }
// XEEMITTER(mtspr, 0x7C0003A6, XFX)(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// // n <- spr[5:9] || spr[0:4]
// // if length(SPR(n)) = 64 then
// // SPR(n) <- (RS)
// // else
// // SPR(n) <- (RS)[32:63]
// Value* v = e.gpr_value(i.XFX.RT);
// const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
// switch (n) {
// case 1:
// // XER
// e.update_xer_value(v);
// break;
// case 8:
// // LR
// e.update_lr_value(v);
// break;
// case 9:
// // CTR
// e.update_ctr_value(v);
// break;
// default:
// XEINSTRNOTIMPLEMENTED();
// return 1;
// }
// return 0;
// }
void LibjitRegisterEmitCategoryControl() {
// XEREGISTERINSTR(bx, 0x48000000);
// XEREGISTERINSTR(bcx, 0x40000000);
// XEREGISTERINSTR(bcctrx, 0x4C000420);
// XEREGISTERINSTR(bclrx, 0x4C000020);
// XEREGISTERINSTR(crand, 0x4C000202);
// XEREGISTERINSTR(crandc, 0x4C000102);
// XEREGISTERINSTR(creqv, 0x4C000242);
// XEREGISTERINSTR(crnand, 0x4C0001C2);
// XEREGISTERINSTR(crnor, 0x4C000042);
// XEREGISTERINSTR(cror, 0x4C000382);
// XEREGISTERINSTR(crorc, 0x4C000342);
// XEREGISTERINSTR(crxor, 0x4C000182);
// XEREGISTERINSTR(mcrf, 0x4C000000);
// XEREGISTERINSTR(sc, 0x44000002);
// XEREGISTERINSTR(td, 0x7C000088);
// XEREGISTERINSTR(tdi, 0x08000000);
// XEREGISTERINSTR(tw, 0x7C000008);
// XEREGISTERINSTR(twi, 0x0C000000);
// XEREGISTERINSTR(mfcr, 0x7C000026);
// XEREGISTERINSTR(mfspr, 0x7C0002A6);
// XEREGISTERINSTR(mftb, 0x7C0002E6);
// XEREGISTERINSTR(mtcrf, 0x7C000120);
// XEREGISTERINSTR(mtspr, 0x7C0003A6);
}
} // namespace libjit
} // namespace cpu
} // namespace xe

View File

@@ -0,0 +1,293 @@
/*
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <xenia/cpu/libjit/libjit_emit.h>
using namespace xe::cpu;
using namespace xe::cpu::ppc;
namespace xe {
namespace cpu {
namespace libjit {
// Floating-point arithmetic (A-8)
XEEMITTER(faddx, 0xFC00002A, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(faddsx, 0xEC00002A, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fdivx, 0xFC000024, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fdivsx, 0xEC000024, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fmulx, 0xFC000032, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fmulsx, 0xEC000032, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fresx, 0xEC000030, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(frsqrtex, 0xFC000034, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fsubx, 0xFC000028, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fsubsx, 0xEC000028, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fselx, 0xFC00002E, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fsqrtx, 0xFC00002C, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fsqrtsx, 0xEC00002C, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
// Floating-point multiply-add (A-9)
XEEMITTER(fmaddx, 0xFC00003A, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fmaddsx, 0xEC00003A, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fmsubx, 0xFC000038, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fmsubsx, 0xEC000038, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fnmaddx, 0xFC00003E, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fnmaddsx, 0xEC00003E, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fnmsubx, 0xFC00003C, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fnmsubsx, 0xEC00003C, A )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
// Floating-point rounding and conversion (A-10)
XEEMITTER(fcfidx, 0xFC00069C, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fctidx, 0xFC00065C, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fctidzx, 0xFC00065E, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fctiwx, 0xFC00001C, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fctiwzx, 0xFC00001E, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(frspx, 0xFC000018, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
// Floating-point compare (A-11)
XEEMITTER(fcmpo, 0xFC000040, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fcmpu, 0xFC000000, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
// if (FRA) is a NaN or (FRB) is a NaN then
// c <- 0b0001
// else if (FRA) < (FRB) then
// c <- 0b1000
// else if (FRA) > (FRB) then
// c <- 0b0100
// else {
// c <- 0b0010
// }
// FPCC <- c
// CR[4*BF:4*BF+3] <- c
// if (FRA) is an SNaN or (FRB) is an SNaN then
// VXSNAN <- 1
XEINSTRNOTIMPLEMENTED();
return 1;
}
// Floating-point status and control register (A
XEEMITTER(mcrfs, 0xFC000080, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(mffsx, 0xFC00048E, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(mtfsb0x, 0xFC00008C, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(mtfsb1x, 0xFC00004C, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(mtfsfx, 0xFC00058E, XFL)(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(mtfsfix, 0xFC00010C, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
// Floating-point move (A-21)
XEEMITTER(fabsx, 0xFC000210, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fmrx, 0xFC000090, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fnabsx, 0xFC000110, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEEMITTER(fnegx, 0xFC000050, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
void LibjitRegisterEmitCategoryFPU() {
XEREGISTERINSTR(faddx, 0xFC00002A);
XEREGISTERINSTR(faddsx, 0xEC00002A);
XEREGISTERINSTR(fdivx, 0xFC000024);
XEREGISTERINSTR(fdivsx, 0xEC000024);
XEREGISTERINSTR(fmulx, 0xFC000032);
XEREGISTERINSTR(fmulsx, 0xEC000032);
XEREGISTERINSTR(fresx, 0xEC000030);
XEREGISTERINSTR(frsqrtex, 0xFC000034);
XEREGISTERINSTR(fsubx, 0xFC000028);
XEREGISTERINSTR(fsubsx, 0xEC000028);
XEREGISTERINSTR(fselx, 0xFC00002E);
XEREGISTERINSTR(fsqrtx, 0xFC00002C);
XEREGISTERINSTR(fsqrtsx, 0xEC00002C);
XEREGISTERINSTR(fmaddx, 0xFC00003A);
XEREGISTERINSTR(fmaddsx, 0xEC00003A);
XEREGISTERINSTR(fmsubx, 0xFC000038);
XEREGISTERINSTR(fmsubsx, 0xEC000038);
XEREGISTERINSTR(fnmaddx, 0xFC00003E);
XEREGISTERINSTR(fnmaddsx, 0xEC00003E);
XEREGISTERINSTR(fnmsubx, 0xFC00003C);
XEREGISTERINSTR(fnmsubsx, 0xEC00003C);
XEREGISTERINSTR(fcfidx, 0xFC00069C);
XEREGISTERINSTR(fctidx, 0xFC00065C);
XEREGISTERINSTR(fctidzx, 0xFC00065E);
XEREGISTERINSTR(fctiwx, 0xFC00001C);
XEREGISTERINSTR(fctiwzx, 0xFC00001E);
XEREGISTERINSTR(frspx, 0xFC000018);
XEREGISTERINSTR(fcmpo, 0xFC000040);
XEREGISTERINSTR(fcmpu, 0xFC000000);
XEREGISTERINSTR(mcrfs, 0xFC000080);
XEREGISTERINSTR(mffsx, 0xFC00048E);
XEREGISTERINSTR(mtfsb0x, 0xFC00008C);
XEREGISTERINSTR(mtfsb1x, 0xFC00004C);
XEREGISTERINSTR(mtfsfx, 0xFC00058E);
XEREGISTERINSTR(mtfsfix, 0xFC00010C);
XEREGISTERINSTR(fabsx, 0xFC000210);
XEREGISTERINSTR(fmrx, 0xFC000090);
XEREGISTERINSTR(fnabsx, 0xFC000110);
XEREGISTERINSTR(fnegx, 0xFC000050);
}
} // namespace libjit
} // namespace cpu
} // namespace xe

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,143 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_CPU_LIBJIT_LIBJIT_EMITTER_H_
#define XENIA_CPU_LIBJIT_LIBJIT_EMITTER_H_
#include <xenia/cpu/global_exports.h>
#include <xenia/cpu/sdb.h>
#include <xenia/cpu/ppc/instr.h>
#include <jit/jit.h>
namespace xe {
namespace cpu {
namespace libjit {
class LibjitEmitter {
public:
LibjitEmitter(xe_memory_ref memory, jit_context_t context);
~LibjitEmitter();
jit_context_t context();
jit_type_t fn_signature();
int PrepareFunction(sdb::FunctionSymbol* symbol);
int MakeFunction(sdb::FunctionSymbol* symbol, jit_function_t fn);
sdb::FunctionSymbol* fn();
jit_function_t gen_fn();
sdb::FunctionBlock* fn_block();
void PushInsertPoint();
void PopInsertPoint();
void GenerateBasicBlocks();
// llvm::BasicBlock* GetBasicBlock(uint32_t address);
// llvm::BasicBlock* GetNextBasicBlock();
// llvm::BasicBlock* GetReturnBasicBlock();
int GenerateIndirectionBranch(uint32_t cia, jit_value_t target,
bool lk, bool likely_local);
jit_value_t LoadStateValue(uint32_t offset, jit_type_t type,
const char* name = "");
void StoreStateValue(uint32_t offset, jit_type_t type, jit_value_t value);
jit_value_t cia_value();
jit_value_t SetupLocal(jit_type_t type, const char* name);
void FillRegisters();
void SpillRegisters();
jit_value_t xer_value();
void update_xer_value(jit_value_t value);
void update_xer_with_overflow(jit_value_t value);
void update_xer_with_carry(jit_value_t value);
void update_xer_with_overflow_and_carry(jit_value_t value);
jit_value_t lr_value();
void update_lr_value(jit_value_t value);
jit_value_t ctr_value();
void update_ctr_value(jit_value_t value);
jit_value_t cr_value(uint32_t n);
void update_cr_value(uint32_t n, jit_value_t value);
void update_cr_with_cond(uint32_t n, jit_value_t lhs, jit_value_t rhs,
bool is_signed);
jit_value_t gpr_value(uint32_t n);
void update_gpr_value(uint32_t n, jit_value_t value);
jit_value_t fpr_value(uint32_t n);
void update_fpr_value(uint32_t n, jit_value_t value);
jit_value_t GetMembase();
jit_value_t GetMemoryAddress(uint32_t cia, jit_value_t addr);
jit_value_t ReadMemory(
uint32_t cia, jit_value_t addr, uint32_t size, bool acquire = false);
void WriteMemory(
uint32_t cia, jit_value_t addr, uint32_t size, jit_value_t value,
bool release = false);
private:
int MakeUserFunction();
int MakePresentImportFunction();
int MakeMissingImportFunction();
void GenerateSharedBlocks();
int PrepareBasicBlock(sdb::FunctionBlock* block);
void GenerateBasicBlock(sdb::FunctionBlock* block);
void SetupLocals();
xe_memory_ref memory_;
jit_context_t context_;
GlobalExports global_exports_;
jit_type_t fn_signature_;
jit_type_t global_export_signature_;
sdb::FunctionSymbol* fn_;
jit_function_t gen_fn_;
sdb::FunctionBlock* fn_block_;
// llvm::BasicBlock* return_block_;
// llvm::BasicBlock* internal_indirection_block_;
// llvm::BasicBlock* external_indirection_block_;
// llvm::BasicBlock* bb_;
// std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock::iterator> >
// insert_points_;
//std::map<uint32_t, llvm::BasicBlock*> bbs_;
// Address of the instruction being generated.
uint32_t cia_;
ppc::InstrAccessBits access_bits_;
struct {
jit_value_t indirection_target;
jit_value_t indirection_cia;
jit_value_t xer;
jit_value_t lr;
jit_value_t ctr;
jit_value_t cr[8];
jit_value_t gpr[32];
jit_value_t fpr[32];
} locals_;
};
} // namespace libjit
} // namespace cpu
} // namespace xe
#endif // XENIA_CPU_LIBJIT_LIBJIT_EMITTER_H_

View File

@@ -0,0 +1,113 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <xenia/cpu/libjit/libjit_jit.h>
#include <xenia/cpu/cpu-private.h>
#include <xenia/cpu/exec_module.h>
#include <xenia/cpu/sdb.h>
using namespace xe;
using namespace xe::cpu;
using namespace xe::cpu::libjit;
using namespace xe::cpu::sdb;
LibjitJIT::LibjitJIT(xe_memory_ref memory, SymbolTable* sym_table) :
JIT(memory, sym_table),
context_(NULL), emitter_(NULL) {
}
LibjitJIT::~LibjitJIT() {
delete emitter_;
if (context_) {
jit_context_destroy(context_);
}
}
int LibjitJIT::Setup() {
int result_code = 1;
// Shared libjit context.
context_ = jit_context_create();
XEEXPECTNOTNULL(context_);
// Create the emitter used to generate functions.
emitter_ = new LibjitEmitter(memory_, context_);
// Inject global functions/variables/etc.
XEEXPECTZERO(InjectGlobals());
result_code = 0;
XECLEANUP:
return result_code;
}
int LibjitJIT::InjectGlobals() {
// LLVMContext& context = *context_;
// const DataLayout* dl = engine_->getDataLayout();
// Type* intPtrTy = dl->getIntPtrType(context);
// Type* int8PtrTy = PointerType::getUnqual(Type::getInt8Ty(context));
// GlobalVariable* gv;
// // xe_memory_base
// // This is the base void* pointer to the memory space.
// gv = new GlobalVariable(
// *module_,
// int8PtrTy,
// true,
// GlobalValue::ExternalLinkage,
// 0,
// "xe_memory_base");
// // Align to 64b - this makes SSE faster.
// gv->setAlignment(64);
// gv->setInitializer(ConstantExpr::getIntToPtr(
// ConstantInt::get(intPtrTy, (uintptr_t)xe_memory_addr(memory_, 0)),
// int8PtrTy));
return 0;
}
int LibjitJIT::InitModule(ExecModule* module) {
return 0;
}
int LibjitJIT::UninitModule(ExecModule* module) {
return 0;
}
int LibjitJIT::Execute(xe_ppc_state_t* ppc_state, FunctionSymbol* fn_symbol) {
XELOGCPU("Execute(%.8X): %s...", fn_symbol->start_address, fn_symbol->name());
// Check function.
jit_function_t jit_fn = (jit_function_t)fn_symbol->impl_value;
if (!jit_fn) {
// Function hasn't been prepped yet - prep it.
if (emitter_->PrepareFunction(fn_symbol)) {
XELOGCPU("Execute(%.8X): unable to make function %s",
fn_symbol->start_address, fn_symbol->name());
return 1;
}
jit_fn = (jit_function_t)fn_symbol->impl_value;
XEASSERTNOTNULL(jit_fn);
}
// TODO(benvanik): replace generic apply with special trampoline.
void* args[] = {&ppc_state, &ppc_state->lr};
uint64_t return_value;
int apply_result = jit_function_apply(jit_fn, (void**)&args, &return_value);
if (apply_result) {
XELOGCPU("Execute(%.8X): apply failed with %d",
fn_symbol->start_address, apply_result);
return 1;
}
return 0;
}

View File

@@ -0,0 +1,54 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_CPU_LIBJIT_LIBJIT_JIT_H_
#define XENIA_CPU_LIBJIT_LIBJIT_JIT_H_
#include <xenia/core.h>
#include <xenia/cpu/jit.h>
#include <xenia/cpu/ppc.h>
#include <xenia/cpu/sdb.h>
#include <xenia/cpu/libjit/libjit_emitter.h>
#include <jit/jit.h>
namespace xe {
namespace cpu {
namespace libjit {
class LibjitJIT : public JIT {
public:
LibjitJIT(xe_memory_ref memory, sdb::SymbolTable* sym_table);
virtual ~LibjitJIT();
virtual int Setup();
virtual int InitModule(ExecModule* module);
virtual int UninitModule(ExecModule* module);
virtual int Execute(xe_ppc_state_t* ppc_state,
sdb::FunctionSymbol* fn_symbol);
protected:
int InjectGlobals();
jit_context_t context_;
LibjitEmitter* emitter_;
};
} // namespace libjit
} // namespace cpu
} // namespace xe
#endif // XENIA_CPU_LIBJIT_LIBJIT_JIT_H_

View File

@@ -0,0 +1,24 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <xenia/cpu/libjit/libjit_library_loader.h>
using namespace xe;
using namespace xe::cpu;
using namespace xe::cpu::libjit;
LibjitLibraryLoader::LibjitLibraryLoader(
xe_memory_ref memory, kernel::ExportResolver* export_resolver) :
LibraryLoader(memory, export_resolver) {
}
LibjitLibraryLoader::~LibjitLibraryLoader() {
}

View File

@@ -0,0 +1,37 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_CPU_LIBJIT_LIBJIT_LIBRARY_LOADER_H_
#define XENIA_CPU_LIBJIT_LIBJIT_LIBRARY_LOADER_H_
#include <xenia/common.h>
#include <xenia/core.h>
#include <xenia/cpu/library_loader.h>
namespace xe {
namespace cpu {
namespace libjit {
class LibjitLibraryLoader : public LibraryLoader {
public:
LibjitLibraryLoader(xe_memory_ref memory,
kernel::ExportResolver* export_resolver);
virtual ~LibjitLibraryLoader();
};
} // namespace libjit
} // namespace cpu
} // namespace xe
#endif // XENIA_CPU_LIBJIT_LIBJIT_LIBRARY_LOADER_H_

View File

@@ -0,0 +1,18 @@
# Copyright 2013 Ben Vanik. All Rights Reserved.
{
'sources': [
'libjit_backend.cc',
'libjit_backend.h',
'libjit_emit.h',
'libjit_emit_alu.cc',
'libjit_emit_control.cc',
'libjit_emit_fpu.cc',
'libjit_emit_memory.cc',
'libjit_emitter.cc',
'libjit_emitter.h',
'libjit_jit.cc',
'libjit_jit.h',
'libjit_library_loader.cc',
'libjit_library_loader.h',
],
}