Rearranging code a bit to keep things cleaner.
This commit is contained in:
parent
b91d550ef1
commit
95a8be078b
|
@ -7,34 +7,31 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_CPU_PPC_INSTR_CONTEXT_H_
|
||||
#define XENIA_CPU_PPC_INSTR_CONTEXT_H_
|
||||
#ifndef XENIA_CPU_CODEGEN_FUNCTION_GENERATOR_H_
|
||||
#define XENIA_CPU_CODEGEN_FUNCTION_GENERATOR_H_
|
||||
|
||||
#include <xenia/cpu/ppc/instr.h>
|
||||
#include <llvm/IR/Attributes.h>
|
||||
#include <llvm/IR/DataLayout.h>
|
||||
#include <llvm/IR/DerivedTypes.h>
|
||||
#include <llvm/IR/IRBuilder.h>
|
||||
#include <llvm/IR/LLVMContext.h>
|
||||
#include <llvm/IR/Module.h>
|
||||
|
||||
#include <xenia/cpu/sdb.h>
|
||||
|
||||
|
||||
namespace llvm {
|
||||
class LLVMContext;
|
||||
class Module;
|
||||
class Function;
|
||||
class BasicBlock;
|
||||
class Value;
|
||||
}
|
||||
#include <xenia/cpu/ppc/instr.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace ppc {
|
||||
namespace codegen {
|
||||
|
||||
|
||||
class InstrContext {
|
||||
class FunctionGenerator {
|
||||
public:
|
||||
InstrContext(xe_memory_ref memory, sdb::FunctionSymbol* fn,
|
||||
llvm::LLVMContext* context, llvm::Module* gen_module,
|
||||
llvm::Function* gen_fn);
|
||||
~InstrContext();
|
||||
FunctionGenerator(xe_memory_ref memory, sdb::FunctionSymbol* fn,
|
||||
llvm::LLVMContext* context, llvm::Module* gen_module,
|
||||
llvm::Function* gen_fn);
|
||||
~FunctionGenerator();
|
||||
|
||||
sdb::FunctionSymbol* fn();
|
||||
llvm::LLVMContext* context();
|
||||
|
@ -47,13 +44,18 @@ public:
|
|||
llvm::Function* GetFunction(uint32_t addr);
|
||||
|
||||
llvm::Value* cia_value();
|
||||
llvm::Value* nia_value();
|
||||
void update_nia_value(llvm::Value* value);
|
||||
llvm::Value* spr_value(uint32_t n);
|
||||
void update_spr_value(uint32_t n, llvm::Value* value);
|
||||
|
||||
llvm::Value* cr_value();
|
||||
void update_cr_value(llvm::Value* value);
|
||||
void FlushRegisters();
|
||||
|
||||
llvm::Value* xer_value();
|
||||
void update_xer_value(llvm::Value* value);
|
||||
llvm::Value* lr_value();
|
||||
void update_lr_value(llvm::Value* value);
|
||||
llvm::Value* ctr_value();
|
||||
void update_ctr_value(llvm::Value* value);
|
||||
|
||||
llvm::Value* cr_value(uint32_t n);
|
||||
void update_cr_value(uint32_t n, llvm::Value* value);
|
||||
|
||||
llvm::Value* gpr_value(uint32_t n);
|
||||
void update_gpr_value(uint32_t n, llvm::Value* value);
|
||||
|
@ -70,18 +72,28 @@ private:
|
|||
llvm::LLVMContext* context_;
|
||||
llvm::Module* gen_module_;
|
||||
llvm::Function* gen_fn_;
|
||||
// TODO(benvanik): IRBuilder/etc
|
||||
llvm::IRBuilder<>* builder_;
|
||||
|
||||
std::map<uint32_t, llvm::BasicBlock*> bbs_;
|
||||
|
||||
// Address of the instruction being generated.
|
||||
uint32_t cia_;
|
||||
|
||||
struct {
|
||||
llvm::Value* xer;
|
||||
llvm::Value* lr;
|
||||
llvm::Value* ctr;
|
||||
|
||||
llvm::Value* cr[4];
|
||||
|
||||
llvm::Value* gpr[32];
|
||||
} values_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace ppc
|
||||
} // namespace codegen
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_CPU_PPC_INSTR_CONTEXT_H_
|
||||
#endif // XENIA_CPU_CODEGEN_FUNCTION_GENERATOR_H_
|
|
@ -7,8 +7,8 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_CPU_CODEGEN_H_
|
||||
#define XENIA_CPU_CODEGEN_H_
|
||||
#ifndef XENIA_CPU_CODEGEN_MODULE_GENERATOR_H_
|
||||
#define XENIA_CPU_CODEGEN_MODULE_GENERATOR_H_
|
||||
|
||||
#include <xenia/cpu/sdb.h>
|
||||
#include <xenia/core/memory.h>
|
||||
|
@ -31,25 +31,24 @@ namespace cpu {
|
|||
namespace codegen {
|
||||
|
||||
|
||||
class CodegenFunction {
|
||||
class ModuleGenerator {
|
||||
public:
|
||||
sdb::FunctionSymbol* symbol;
|
||||
llvm::FunctionType* function_type;
|
||||
llvm::Function* function;
|
||||
};
|
||||
|
||||
|
||||
class CodegenContext {
|
||||
public:
|
||||
CodegenContext(
|
||||
ModuleGenerator(
|
||||
xe_memory_ref memory, kernel::ExportResolver* export_resolver,
|
||||
kernel::UserModule* module, sdb::SymbolDatabase* sdb,
|
||||
llvm::LLVMContext* context, llvm::Module* gen_module);
|
||||
~CodegenContext();
|
||||
~ModuleGenerator();
|
||||
|
||||
int GenerateModule();
|
||||
int Generate();
|
||||
|
||||
private:
|
||||
class CodegenFunction {
|
||||
public:
|
||||
sdb::FunctionSymbol* symbol;
|
||||
llvm::FunctionType* function_type;
|
||||
llvm::Function* function;
|
||||
};
|
||||
|
||||
CodegenFunction* GetCodegenFunction(uint32_t address);
|
||||
|
||||
void AddImports();
|
||||
|
@ -78,4 +77,4 @@ private:
|
|||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_CPU_CODEGEN_H_
|
||||
#endif // XENIA_CPU_CODEGEN_MODULE_GENERATOR_H_
|
|
@ -27,7 +27,7 @@ namespace llvm {
|
|||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace codegen {
|
||||
class CodegenContext;
|
||||
class ModuleGenerator;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,14 +53,14 @@ private:
|
|||
int Init();
|
||||
int Uninit();
|
||||
|
||||
xe_memory_ref memory_;
|
||||
shared_ptr<kernel::ExportResolver> export_resolver_;
|
||||
kernel::UserModule* module_;
|
||||
shared_ptr<llvm::ExecutionEngine> engine_;
|
||||
shared_ptr<sdb::SymbolDatabase> sdb_;
|
||||
shared_ptr<llvm::LLVMContext> context_;
|
||||
shared_ptr<llvm::Module> gen_module_;
|
||||
auto_ptr<codegen::CodegenContext> codegen_;
|
||||
xe_memory_ref memory_;
|
||||
shared_ptr<kernel::ExportResolver> export_resolver_;
|
||||
kernel::UserModule* module_;
|
||||
shared_ptr<llvm::ExecutionEngine> engine_;
|
||||
shared_ptr<sdb::SymbolDatabase> sdb_;
|
||||
shared_ptr<llvm::LLVMContext> context_;
|
||||
shared_ptr<llvm::Module> gen_module_;
|
||||
auto_ptr<codegen::ModuleGenerator> codegen_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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/codegen/function_generator.h>
|
||||
|
||||
|
||||
using namespace llvm;
|
||||
using namespace xe::cpu::codegen;
|
||||
using namespace xe::cpu::ppc;
|
||||
using namespace xe::cpu::sdb;
|
||||
|
||||
|
||||
/**
|
||||
* This generates function code.
|
||||
* One context is created for each function to generate. Each basic block in
|
||||
* the function is created and stashed in one pass, then filled in the next.
|
||||
*
|
||||
* This context object is a stateful representation of the current machine state
|
||||
* and all accessors to registers should occur through it. By doing so it's
|
||||
* possible to exploit the SSA nature of LLVM to reuse register values within
|
||||
* a function without needing to flush to memory.
|
||||
*
|
||||
* Function calls (any branch outside of the function) will result in an
|
||||
* expensive flush of registers.
|
||||
*
|
||||
* TODO(benvanik): track arguments by looking for register reads without writes
|
||||
* TODO(benvanik): avoid flushing registers for leaf nodes
|
||||
* TODO(benvnaik): pass return value in LLVM return, not by memory
|
||||
*/
|
||||
|
||||
|
||||
FunctionGenerator::FunctionGenerator(xe_memory_ref memory, FunctionSymbol* fn,
|
||||
LLVMContext* context, Module* gen_module,
|
||||
Function* gen_fn) {
|
||||
memory_ = memory;
|
||||
fn_ = fn;
|
||||
context_ = context;
|
||||
gen_module_ = gen_module;
|
||||
gen_fn_ = gen_fn;
|
||||
builder_ = new IRBuilder<>(*context_);
|
||||
}
|
||||
|
||||
FunctionGenerator::~FunctionGenerator() {
|
||||
delete builder_;
|
||||
}
|
||||
|
||||
FunctionSymbol* FunctionGenerator::fn() {
|
||||
return fn_;
|
||||
}
|
||||
|
||||
llvm::LLVMContext* FunctionGenerator::context() {
|
||||
return context_;
|
||||
}
|
||||
|
||||
llvm::Module* FunctionGenerator::gen_module() {
|
||||
return gen_module_;
|
||||
}
|
||||
|
||||
llvm::Function* FunctionGenerator::gen_fn() {
|
||||
return gen_fn_;
|
||||
}
|
||||
|
||||
void FunctionGenerator::GenerateBasicBlocks() {
|
||||
// Pass 1 creates all of the blocks - this way we can branch to them.
|
||||
for (std::map<uint32_t, FunctionBlock*>::iterator it = fn_->blocks.begin();
|
||||
it != fn_->blocks.end(); ++it) {
|
||||
FunctionBlock* block = it->second;
|
||||
|
||||
char name[32];
|
||||
xesnprintfa(name, XECOUNT(name), "loc_%.8X", block->start_address);
|
||||
BasicBlock* bb = BasicBlock::Create(*context_, name, gen_fn_);
|
||||
bbs_.insert(std::pair<uint32_t, BasicBlock*>(block->start_address, bb));
|
||||
}
|
||||
|
||||
for (std::map<uint32_t, FunctionBlock*>::iterator it = fn_->blocks.begin();
|
||||
it != fn_->blocks.end(); ++it) {
|
||||
FunctionBlock* block = it->second;
|
||||
GenerateBasicBlock(block, GetBasicBlock(block->start_address));
|
||||
}
|
||||
}
|
||||
|
||||
void FunctionGenerator::GenerateBasicBlock(FunctionBlock* block,
|
||||
BasicBlock* bb) {
|
||||
printf(" bb %.8X-%.8X:\n", block->start_address, block->end_address);
|
||||
|
||||
// Move the builder to this block and setup.
|
||||
builder_->SetInsertPoint(bb);
|
||||
//i->setMetadata("some.name", MDNode::get(context, MDString::get(context, pname)));
|
||||
|
||||
// Walk instructions in block.
|
||||
uint8_t* p = xe_memory_addr(memory_, 0);
|
||||
for (uint32_t ia = block->start_address; ia <= block->end_address; ia += 4) {
|
||||
InstrData i;
|
||||
i.address = ia;
|
||||
i.code = XEGETUINT32BE(p + ia);
|
||||
i.type = ppc::GetInstrType(i.code);
|
||||
if (!i.type) {
|
||||
XELOGCPU("Invalid instruction at %.8X: %.8X\n", ia, i.code);
|
||||
continue;
|
||||
}
|
||||
printf(" %.8X: %.8X %s\n", ia, i.code, i.type->name);
|
||||
|
||||
// TODO(benvanik): debugging information? source/etc?
|
||||
// builder_>SetCurrentDebugLocation(DebugLoc::get(
|
||||
// ia >> 8, ia & 0xFF, ctx->cu));
|
||||
|
||||
//emit(this, i, builder);
|
||||
}
|
||||
|
||||
//Value* tmp = builder_->getInt32(0);
|
||||
builder_->CreateRetVoid();
|
||||
|
||||
// TODO(benvanik): finish up BB
|
||||
}
|
||||
|
||||
BasicBlock* FunctionGenerator::GetBasicBlock(uint32_t address) {
|
||||
std::map<uint32_t, BasicBlock*>::iterator it = bbs_.find(address);
|
||||
if (it != bbs_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Function* FunctionGenerator::GetFunction(uint32_t addr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Value* FunctionGenerator::cia_value() {
|
||||
return builder_->getInt32(cia_);
|
||||
}
|
||||
|
||||
void FunctionGenerator::FlushRegisters() {
|
||||
|
||||
}
|
||||
|
||||
Value* FunctionGenerator::xer_value() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FunctionGenerator::update_xer_value(Value* value) {
|
||||
|
||||
}
|
||||
|
||||
Value* FunctionGenerator::lr_value() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FunctionGenerator::update_lr_value(Value* value) {
|
||||
|
||||
}
|
||||
|
||||
Value* FunctionGenerator::ctr_value() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FunctionGenerator::update_ctr_value(Value* value) {
|
||||
|
||||
}
|
||||
|
||||
Value* FunctionGenerator::cr_value(uint32_t n) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FunctionGenerator::update_cr_value(uint32_t n, Value* value) {
|
||||
//
|
||||
}
|
||||
|
||||
Value* FunctionGenerator::gpr_value(uint32_t n) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FunctionGenerator::update_gpr_value(uint32_t n, Value* value) {
|
||||
//
|
||||
}
|
||||
|
||||
Value* FunctionGenerator::memory_addr(uint32_t addr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Value* FunctionGenerator::read_memory(Value* addr, uint32_t size, bool extend) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FunctionGenerator::write_memory(Value* addr, uint32_t size, Value* value) {
|
||||
//
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <xenia/cpu/codegen.h>
|
||||
#include <xenia/cpu/codegen/module_generator.h>
|
||||
|
||||
#include <llvm/DIBuilder.h>
|
||||
#include <llvm/Linker.h>
|
||||
|
@ -24,18 +24,18 @@
|
|||
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
|
||||
|
||||
#include <xenia/cpu/ppc.h>
|
||||
#include "cpu/ppc/instr_context.h"
|
||||
#include <xenia/cpu/codegen/function_generator.h>
|
||||
|
||||
|
||||
using namespace llvm;
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::codegen;
|
||||
using namespace xe::cpu::ppc;
|
||||
using namespace xe::cpu::sdb;
|
||||
using namespace xe::kernel;
|
||||
|
||||
|
||||
CodegenContext::CodegenContext(
|
||||
ModuleGenerator::ModuleGenerator(
|
||||
xe_memory_ref memory, ExportResolver* export_resolver,
|
||||
UserModule* module, SymbolDatabase* sdb,
|
||||
LLVMContext* context, Module* gen_module) {
|
||||
|
@ -47,11 +47,11 @@ CodegenContext::CodegenContext(
|
|||
gen_module_ = gen_module;
|
||||
}
|
||||
|
||||
CodegenContext::~CodegenContext() {
|
||||
ModuleGenerator::~ModuleGenerator() {
|
||||
xe_memory_release(memory_);
|
||||
}
|
||||
|
||||
int CodegenContext::GenerateModule() {
|
||||
int ModuleGenerator::Generate() {
|
||||
std::string error_message;
|
||||
|
||||
// Setup a debug info builder.
|
||||
|
@ -111,7 +111,8 @@ int CodegenContext::GenerateModule() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
CodegenFunction* CodegenContext::GetCodegenFunction(uint32_t address) {
|
||||
ModuleGenerator::CodegenFunction* ModuleGenerator::GetCodegenFunction(
|
||||
uint32_t address) {
|
||||
std::map<uint32_t, CodegenFunction*>::iterator it = functions_.find(address);
|
||||
if (it != functions_.end()) {
|
||||
return it->second;
|
||||
|
@ -119,7 +120,7 @@ CodegenFunction* CodegenContext::GetCodegenFunction(uint32_t address) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void CodegenContext::AddMissingImport(FunctionSymbol* fn) {
|
||||
void ModuleGenerator::AddMissingImport(FunctionSymbol* fn) {
|
||||
Module* m = gen_module_;
|
||||
LLVMContext& context = m->getContext();
|
||||
|
||||
|
@ -158,14 +159,14 @@ void CodegenContext::AddMissingImport(FunctionSymbol* fn) {
|
|||
// implemented ? " " : "!!", name);
|
||||
}
|
||||
|
||||
void CodegenContext::AddPresentImport(FunctionSymbol* fn) {
|
||||
void ModuleGenerator::AddPresentImport(FunctionSymbol* fn) {
|
||||
// Module *m = gen_module_;
|
||||
// LLVMContext& context = m->getContext();
|
||||
|
||||
// TODO(benvanik): add import thunk code.
|
||||
}
|
||||
|
||||
void CodegenContext::PrepareFunction(FunctionSymbol* fn) {
|
||||
void ModuleGenerator::PrepareFunction(FunctionSymbol* fn) {
|
||||
Module* m = gen_module_;
|
||||
LLVMContext& context = m->getContext();
|
||||
|
||||
|
@ -177,7 +178,7 @@ void CodegenContext::PrepareFunction(FunctionSymbol* fn) {
|
|||
AttributeSet attrs = AttributeSet::get(context, awi);
|
||||
|
||||
std::vector<Type*> args;
|
||||
Type* return_type = Type::getInt32Ty(context);
|
||||
Type* return_type = Type::getVoidTy(context);
|
||||
|
||||
char name[64];
|
||||
char* pname = name;
|
||||
|
@ -202,16 +203,16 @@ void CodegenContext::PrepareFunction(FunctionSymbol* fn) {
|
|||
fn->start_address, cgf));
|
||||
}
|
||||
|
||||
void CodegenContext::BuildFunction(CodegenFunction* cgf) {
|
||||
void ModuleGenerator::BuildFunction(CodegenFunction* cgf) {
|
||||
FunctionSymbol* fn = cgf->symbol;
|
||||
|
||||
printf("%s:\n", fn->name);
|
||||
|
||||
// Setup the generation context.
|
||||
InstrContext ic(memory_, fn, context_, gen_module_, cgf->function);
|
||||
FunctionGenerator fgen(memory_, fn, context_, gen_module_, cgf->function);
|
||||
|
||||
// Run through and generate each basic block.
|
||||
ic.GenerateBasicBlocks();
|
||||
fgen.GenerateBasicBlocks();
|
||||
|
||||
// Run the optimizer on the function.
|
||||
// Doing this here keeps the size of the IR small and speeds up the later
|
||||
|
@ -219,7 +220,7 @@ void CodegenContext::BuildFunction(CodegenFunction* cgf) {
|
|||
OptimizeFunction(gen_module_, cgf->function);
|
||||
}
|
||||
|
||||
void CodegenContext::OptimizeFunction(Module* m, Function* fn) {
|
||||
void ModuleGenerator::OptimizeFunction(Module* m, Function* fn) {
|
||||
FunctionPassManager pm(m);
|
||||
PassManagerBuilder pmb;
|
||||
pmb.OptLevel = 3;
|
|
@ -0,0 +1,7 @@
|
|||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'function_generator.cc',
|
||||
'module_generator.cc',
|
||||
],
|
||||
}
|
|
@ -27,7 +27,7 @@
|
|||
#include <llvm/Transforms/IPO.h>
|
||||
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
|
||||
|
||||
#include <xenia/cpu/codegen.h>
|
||||
#include <xenia/cpu/codegen/module_generator.h>
|
||||
#include <xenia/cpu/sdb.h>
|
||||
|
||||
#include "cpu/xethunk/xethunk.h"
|
||||
|
@ -115,10 +115,10 @@ int ExecModule::Prepare() {
|
|||
&error_message);
|
||||
|
||||
// Build the module from the source code.
|
||||
codegen_ = auto_ptr<CodegenContext>(new CodegenContext(
|
||||
codegen_ = auto_ptr<ModuleGenerator>(new ModuleGenerator(
|
||||
memory_, export_resolver_.get(), module_, sdb_.get(),
|
||||
context_.get(), gen_module_.get()));
|
||||
XEEXPECTZERO(codegen_->GenerateModule());
|
||||
XEEXPECTZERO(codegen_->Generate());
|
||||
|
||||
// Write to cache.
|
||||
outs = auto_ptr<raw_ostream>(new raw_fd_ostream(
|
||||
|
|
|
@ -1,162 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 "cpu/ppc/instr_context.h"
|
||||
|
||||
#include <llvm/IR/Attributes.h>
|
||||
#include <llvm/IR/DataLayout.h>
|
||||
#include <llvm/IR/DerivedTypes.h>
|
||||
#include <llvm/IR/IRBuilder.h>
|
||||
#include <llvm/IR/LLVMContext.h>
|
||||
#include <llvm/IR/Module.h>
|
||||
|
||||
|
||||
using namespace llvm;
|
||||
using namespace xe::cpu::ppc;
|
||||
using namespace xe::cpu::sdb;
|
||||
|
||||
|
||||
InstrContext::InstrContext(xe_memory_ref memory, FunctionSymbol* fn,
|
||||
LLVMContext* context, Module* gen_module,
|
||||
Function* gen_fn) {
|
||||
memory_ = memory;
|
||||
fn_ = fn;
|
||||
context_ = context;
|
||||
gen_module_ = gen_module;
|
||||
gen_fn_ = gen_fn;
|
||||
}
|
||||
|
||||
InstrContext::~InstrContext() {
|
||||
}
|
||||
|
||||
FunctionSymbol* InstrContext::fn() {
|
||||
return fn_;
|
||||
}
|
||||
|
||||
llvm::LLVMContext* InstrContext::context() {
|
||||
return context_;
|
||||
}
|
||||
|
||||
llvm::Module* InstrContext::gen_module() {
|
||||
return gen_module_;
|
||||
}
|
||||
|
||||
llvm::Function* InstrContext::gen_fn() {
|
||||
return gen_fn_;
|
||||
}
|
||||
|
||||
void InstrContext::GenerateBasicBlocks() {
|
||||
// Pass 1 creates all of the blocks - this way we can branch to them.
|
||||
for (std::map<uint32_t, FunctionBlock*>::iterator it = fn_->blocks.begin();
|
||||
it != fn_->blocks.end(); ++it) {
|
||||
FunctionBlock* block = it->second;
|
||||
|
||||
char name[32];
|
||||
xesnprintfa(name, XECOUNT(name), "loc_%.8X", block->start_address);
|
||||
BasicBlock* bb = BasicBlock::Create(*context_, name, gen_fn_);
|
||||
bbs_.insert(std::pair<uint32_t, BasicBlock*>(block->start_address, bb));
|
||||
}
|
||||
|
||||
for (std::map<uint32_t, FunctionBlock*>::iterator it = fn_->blocks.begin();
|
||||
it != fn_->blocks.end(); ++it) {
|
||||
FunctionBlock* block = it->second;
|
||||
GenerateBasicBlock(block, GetBasicBlock(block->start_address));
|
||||
}
|
||||
}
|
||||
|
||||
void InstrContext::GenerateBasicBlock(FunctionBlock* block, BasicBlock* bb) {
|
||||
printf(" bb %.8X-%.8X:\n", block->start_address, block->end_address);
|
||||
|
||||
//builder.SetCurrentDebugLocation(DebugLoc::get(fn->start_address >> 8, fn->start_address & 0xFF, ctx->cu));
|
||||
//i->setMetadata("some.name", MDNode::get(context, MDString::get(context, pname)));
|
||||
|
||||
IRBuilder<> builder(bb);
|
||||
|
||||
// Walk instructions in block.
|
||||
uint8_t* p = xe_memory_addr(memory_, 0);
|
||||
for (uint32_t ia = block->start_address; ia <= block->end_address; ia += 4) {
|
||||
InstrData i;
|
||||
i.address = ia;
|
||||
i.code = XEGETUINT32BE(p + ia);
|
||||
i.type = ppc::GetInstrType(i.code);
|
||||
if (!i.type) {
|
||||
XELOGCPU("Invalid instruction at %.8X: %.8X\n", ia, i.code);
|
||||
continue;
|
||||
}
|
||||
printf(" %.8X: %.8X %s\n", ia, i.code, i.type->name);
|
||||
// stash current bb?
|
||||
// stash builder
|
||||
//emit(this, i);
|
||||
}
|
||||
|
||||
Value* tmp = builder.getInt32(0);
|
||||
builder.CreateRet(tmp);
|
||||
|
||||
// TODO(benvanik): finish up BB
|
||||
}
|
||||
|
||||
BasicBlock* InstrContext::GetBasicBlock(uint32_t address) {
|
||||
std::map<uint32_t, BasicBlock*>::iterator it = bbs_.find(address);
|
||||
if (it != bbs_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Function* InstrContext::GetFunction(uint32_t addr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Value* InstrContext::cia_value() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Value* InstrContext::nia_value() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void InstrContext::update_nia_value(Value* value) {
|
||||
//
|
||||
}
|
||||
|
||||
Value* InstrContext::spr_value(uint32_t n) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void InstrContext::update_spr_value(uint32_t n, Value* value) {
|
||||
//
|
||||
}
|
||||
|
||||
Value* InstrContext::cr_value() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void InstrContext::update_cr_value(Value* value) {
|
||||
//
|
||||
}
|
||||
|
||||
Value* InstrContext::gpr_value(uint32_t n) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void InstrContext::update_gpr_value(uint32_t n, Value* value) {
|
||||
//
|
||||
}
|
||||
|
||||
Value* InstrContext::memory_addr(uint32_t addr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Value* InstrContext::read_memory(Value* addr, uint32_t size, bool extend) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void InstrContext::write_memory(Value* addr, uint32_t size, Value* value) {
|
||||
//
|
||||
}
|
|
@ -2,6 +2,5 @@
|
|||
{
|
||||
'sources': [
|
||||
'instr.cc',
|
||||
'instr_context.cc',
|
||||
],
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'codegen.cc',
|
||||
'exec_module.cc',
|
||||
'processor.cc',
|
||||
'sdb.cc',
|
||||
],
|
||||
|
||||
'includes': [
|
||||
'codegen/sources.gypi',
|
||||
'ppc/sources.gypi',
|
||||
],
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue