Converting everything to C++ cause I'm a masochist.
This commit is contained in:
71
include/xenia/cpu/codegen.h
Normal file
71
include/xenia/cpu/codegen.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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_CODEGEN_H_
|
||||
#define XENIA_CPU_CODEGEN_H_
|
||||
|
||||
#include <xenia/cpu/sdb.h>
|
||||
#include <xenia/core/memory.h>
|
||||
#include <xenia/kernel/export.h>
|
||||
#include <xenia/kernel/user_module.h>
|
||||
|
||||
|
||||
namespace llvm {
|
||||
class LLVMContext;
|
||||
class Module;
|
||||
class Function;
|
||||
class DIBuilder;
|
||||
class MDNode;
|
||||
}
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace codegen {
|
||||
|
||||
|
||||
class CodegenContext {
|
||||
public:
|
||||
CodegenContext(
|
||||
xe_memory_ref memory, kernel::ExportResolver* export_resolver,
|
||||
kernel::UserModule* module, sdb::SymbolDatabase* sdb,
|
||||
llvm::LLVMContext* context, llvm::Module* gen_module);
|
||||
~CodegenContext();
|
||||
|
||||
int GenerateModule();
|
||||
|
||||
private:
|
||||
void AddImports();
|
||||
void AddMissingImport(
|
||||
const xe_xex2_import_library_t *library,
|
||||
const xe_xex2_import_info_t* info, kernel::KernelExport* kernel_export);
|
||||
void AddPresentImport(
|
||||
const xe_xex2_import_library_t *library,
|
||||
const xe_xex2_import_info_t* info, kernel::KernelExport* kernel_export);
|
||||
void AddFunction(sdb::FunctionSymbol* fn);
|
||||
void OptimizeFunction(llvm::Module* m, llvm::Function* fn);
|
||||
|
||||
xe_memory_ref memory_;
|
||||
kernel::ExportResolver* export_resolver_;
|
||||
kernel::UserModule* module_;
|
||||
sdb::SymbolDatabase* sdb_;
|
||||
|
||||
llvm::LLVMContext* context_;
|
||||
llvm::Module* gen_module_;
|
||||
llvm::DIBuilder* di_builder_;
|
||||
llvm::MDNode* cu_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace codegen
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_CPU_CODEGEN_H_
|
||||
62
include/xenia/cpu/exec_module.h
Normal file
62
include/xenia/cpu/exec_module.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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_USERMODULE_H_
|
||||
#define XENIA_CPU_USERMODULE_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <xenia/cpu/sdb.h>
|
||||
#include <xenia/kernel/export.h>
|
||||
#include <xenia/kernel/user_module.h>
|
||||
|
||||
|
||||
namespace llvm {
|
||||
class LLVMContext;
|
||||
class Module;
|
||||
class ExecutionEngine;
|
||||
}
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
|
||||
|
||||
class ExecModule {
|
||||
public:
|
||||
ExecModule(
|
||||
xe_memory_ref memory, shared_ptr<kernel::ExportResolver> export_resolver,
|
||||
kernel::UserModule* user_module,
|
||||
shared_ptr<llvm::ExecutionEngine>& engine);
|
||||
~ExecModule();
|
||||
|
||||
int Prepare();
|
||||
|
||||
void Dump();
|
||||
|
||||
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_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_CPU_USERMODULE_H_
|
||||
@@ -13,6 +13,12 @@
|
||||
#include <xenia/common.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace ppc {
|
||||
|
||||
|
||||
// TODO(benvanik): rename these
|
||||
typedef enum {
|
||||
kXEPPCInstrFormatI = 0,
|
||||
kXEPPCInstrFormatB = 1,
|
||||
@@ -47,13 +53,12 @@ typedef enum {
|
||||
} xe_ppc_instr_flag_e;
|
||||
|
||||
|
||||
struct xe_ppc_instr_type;
|
||||
typedef struct xe_ppc_instr_type xe_ppc_instr_type_t;
|
||||
class InstrType;
|
||||
|
||||
|
||||
typedef struct {
|
||||
xe_ppc_instr_type_t *type;
|
||||
uint32_t address;
|
||||
InstrType* type;
|
||||
uint32_t address;
|
||||
|
||||
union {
|
||||
uint32_t code;
|
||||
@@ -110,28 +115,36 @@ typedef struct {
|
||||
// kXEPPCInstrFormatVX
|
||||
// kXEPPCInstrFormatVXR
|
||||
} data;
|
||||
} xe_ppc_instr_t;
|
||||
} InstrData;
|
||||
|
||||
typedef struct {
|
||||
xe_ppc_instr_t instr;
|
||||
class Instr {
|
||||
public:
|
||||
InstrData instr;
|
||||
|
||||
// TODO(benvanik): registers changed, special bits, etc
|
||||
} xe_ppc_dec_instr_t;
|
||||
|
||||
typedef int (*xe_ppc_emit_fn)(/* emit context */ xe_ppc_instr_t *instr);
|
||||
|
||||
struct xe_ppc_instr_type {
|
||||
uint32_t opcode;
|
||||
uint32_t format; // xe_ppc_instr_format_e
|
||||
uint32_t type; // xe_ppc_instr_type_e
|
||||
uint32_t flags; // xe_ppc_instr_flag_e
|
||||
char name[16];
|
||||
|
||||
xe_ppc_emit_fn emit;
|
||||
};
|
||||
|
||||
xe_ppc_instr_type_t *xe_ppc_get_instr_type(uint32_t code);
|
||||
int xe_ppc_register_instr_emit(uint32_t code, xe_ppc_emit_fn emit);
|
||||
typedef int (*InstrEmitFn)(/* emit context */ Instr* instr);
|
||||
|
||||
class InstrType {
|
||||
public:
|
||||
uint32_t opcode;
|
||||
uint32_t format; // xe_ppc_instr_format_e
|
||||
uint32_t type; // xe_ppc_instr_type_e
|
||||
uint32_t flags; // xe_ppc_instr_flag_e
|
||||
char name[16];
|
||||
|
||||
InstrEmitFn emit;
|
||||
};
|
||||
|
||||
InstrType* GetInstrType(uint32_t code);
|
||||
int RegisterInstrEmit(uint32_t code, InstrEmitFn emit);
|
||||
|
||||
|
||||
} // namespace ppc
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_CPU_PPC_INSTR_H_
|
||||
|
||||
|
||||
@@ -13,13 +13,33 @@
|
||||
#include <xenia/common.h>
|
||||
|
||||
|
||||
namespace XE_PPC_SPR {
|
||||
enum XE_PPC_SPR_e {
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace ppc {
|
||||
|
||||
|
||||
namespace SPR {
|
||||
enum SPR_e {
|
||||
XER = 1,
|
||||
LR = 8,
|
||||
CTR = 9,
|
||||
};
|
||||
} // XE_PPC_SPR
|
||||
} // SPR
|
||||
|
||||
|
||||
namespace FPRF {
|
||||
enum FPRF_e {
|
||||
QUIET_NAN = 0x00088000,
|
||||
NEG_INFINITY = 0x00090000,
|
||||
NEG_NORMALIZED = 0x00010000,
|
||||
NEG_DENORMALIZED = 0x00018000,
|
||||
NEG_ZERO = 0x00048000,
|
||||
POS_ZERO = 0x00040000,
|
||||
POS_DENORMALIZED = 0x00028000,
|
||||
POS_NORMALIZED = 0x00020000,
|
||||
POS_INFINITY = 0x000A0000,
|
||||
};
|
||||
} // FPRF
|
||||
|
||||
|
||||
typedef struct XECACHEALIGN64 {
|
||||
@@ -88,33 +108,24 @@ typedef struct XECACHEALIGN64 {
|
||||
// 11 = toward -infinity
|
||||
} bits;
|
||||
} fpscr; // Floating-point status and control register
|
||||
} xe_ppc_registers_t;
|
||||
|
||||
uint32_t get_fprf() {
|
||||
return fpscr.value & 0x000F8000;
|
||||
}
|
||||
void set_fprf(const uint32_t v) {
|
||||
fpscr.value = (fpscr.value & ~0x000F8000) | v;
|
||||
}
|
||||
} PpcRegisters;
|
||||
|
||||
|
||||
typedef struct {
|
||||
xe_ppc_registers_t registers;
|
||||
} xe_ppc_state_t;
|
||||
PpcRegisters registers;
|
||||
} PpcState;
|
||||
|
||||
|
||||
namespace XE_PPC_FPRF {
|
||||
enum XE_PPC_FPRF_e {
|
||||
QUIET_NAN = 0x00088000,
|
||||
NEG_INFINITY = 0x00090000,
|
||||
NEG_NORMALIZED = 0x00010000,
|
||||
NEG_DENORMALIZED = 0x00018000,
|
||||
NEG_ZERO = 0x00048000,
|
||||
POS_ZERO = 0x00040000,
|
||||
POS_DENORMALIZED = 0x00028000,
|
||||
POS_NORMALIZED = 0x00020000,
|
||||
POS_INFINITY = 0x000A0000,
|
||||
};
|
||||
} // XE_PPC_FPRF
|
||||
uint32_t xe_ppc_get_fprf(const xe_ppc_registers_t *r) {
|
||||
return r->fpscr.value & 0x000F8000;
|
||||
}
|
||||
void xe_ppc_set_fprf(xe_ppc_registers_t *r, const uint32_t v) {
|
||||
r->fpscr.value = (r->fpscr.value & ~0x000F8000) | v;
|
||||
}
|
||||
} // namespace ppc
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_CPU_PPC_STATE_H_
|
||||
|
||||
60
include/xenia/cpu/processor.h
Normal file
60
include/xenia/cpu/processor.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* 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_PROCESSOR_H_
|
||||
#define XENIA_CPU_PROCESSOR_H_
|
||||
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <xenia/cpu/exec_module.h>
|
||||
#include <xenia/kernel/export.h>
|
||||
#include <xenia/kernel/user_module.h>
|
||||
|
||||
|
||||
namespace llvm {
|
||||
class ExecutionEngine;
|
||||
}
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
|
||||
|
||||
class Processor {
|
||||
public:
|
||||
Processor(xe_pal_ref pal, xe_memory_ref memory);
|
||||
~Processor();
|
||||
|
||||
xe_pal_ref pal();
|
||||
xe_memory_ref memory();
|
||||
|
||||
int Setup();
|
||||
|
||||
int PrepareModule(kernel::UserModule* user_module,
|
||||
shared_ptr<kernel::ExportResolver> export_resolver);
|
||||
|
||||
int Execute(uint32_t address);
|
||||
uint32_t CreateCallback(void (*callback)(void* data), void* data);
|
||||
|
||||
private:
|
||||
xe_pal_ref pal_;
|
||||
xe_memory_ref memory_;
|
||||
shared_ptr<llvm::ExecutionEngine> engine_;
|
||||
|
||||
std::vector<ExecModule*> modules_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_CPU_PROCESSOR_H_
|
||||
@@ -12,79 +12,123 @@
|
||||
|
||||
#include <xenia/core.h>
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <xenia/kernel/module.h>
|
||||
#include <xenia/kernel/user_module.h>
|
||||
|
||||
|
||||
struct xe_sdb_function;
|
||||
typedef struct xe_sdb_function xe_sdb_function_t;
|
||||
struct xe_sdb_variable;
|
||||
typedef struct xe_sdb_variable xe_sdb_variable_t;
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace sdb {
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t address;
|
||||
xe_sdb_function_t *source;
|
||||
xe_sdb_function_t *target;
|
||||
} xe_sdb_function_call_t;
|
||||
class FunctionSymbol;
|
||||
class VariableSymbol;
|
||||
|
||||
typedef struct {
|
||||
uint32_t address;
|
||||
xe_sdb_function_t *source;
|
||||
xe_sdb_variable_t *target;
|
||||
} xe_sdb_variable_access_t;
|
||||
|
||||
typedef enum {
|
||||
kXESDBFunctionUnknown = 0,
|
||||
kXESDBFunctionKernel = 1,
|
||||
kXESDBFunctionUser = 2,
|
||||
} xe_sdb_function_type;
|
||||
|
||||
struct xe_sdb_function {
|
||||
uint32_t start_address;
|
||||
uint32_t end_address;
|
||||
char *name;
|
||||
xe_sdb_function_type type;
|
||||
uint32_t flags;
|
||||
|
||||
std::vector<xe_sdb_function_call_t*> incoming_calls;
|
||||
std::vector<xe_sdb_function_call_t*> outgoing_calls;
|
||||
std::vector<xe_sdb_variable_access_t*> variable_accesses;
|
||||
class FunctionCall {
|
||||
public:
|
||||
uint32_t address;
|
||||
FunctionSymbol* source;
|
||||
FunctionSymbol* target;
|
||||
};
|
||||
|
||||
struct xe_sdb_variable {
|
||||
class VariableAccess {
|
||||
public:
|
||||
uint32_t address;
|
||||
FunctionSymbol* source;
|
||||
VariableSymbol* target;
|
||||
};
|
||||
|
||||
class Symbol {
|
||||
public:
|
||||
enum SymbolType {
|
||||
Function = 0,
|
||||
Variable = 1,
|
||||
};
|
||||
|
||||
virtual ~Symbol() {}
|
||||
|
||||
SymbolType symbol_type;
|
||||
|
||||
protected:
|
||||
Symbol(SymbolType type) : symbol_type(type) {}
|
||||
};
|
||||
|
||||
class FunctionSymbol : public Symbol {
|
||||
public:
|
||||
enum FunctionType {
|
||||
Unknown = 0,
|
||||
Kernel = 1,
|
||||
User = 2,
|
||||
};
|
||||
|
||||
FunctionSymbol() : Symbol(Function) {}
|
||||
virtual ~FunctionSymbol() {}
|
||||
|
||||
uint32_t start_address;
|
||||
uint32_t end_address;
|
||||
char *name;
|
||||
FunctionType type;
|
||||
uint32_t flags;
|
||||
|
||||
vector<FunctionCall*> incoming_calls;
|
||||
vector<FunctionCall*> outgoing_calls;
|
||||
vector<VariableAccess*> variable_accesses;
|
||||
};
|
||||
|
||||
class VariableSymbol : public Symbol {
|
||||
public:
|
||||
VariableSymbol() : Symbol(Variable) {}
|
||||
virtual ~VariableSymbol() {}
|
||||
|
||||
uint32_t address;
|
||||
char *name;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
union {
|
||||
xe_sdb_function_t* function;
|
||||
xe_sdb_variable_t* variable;
|
||||
};
|
||||
} xe_sdb_symbol_t;
|
||||
|
||||
class SymbolDatabase {
|
||||
public:
|
||||
SymbolDatabase(xe_memory_ref memory, kernel::UserModule* user_module);
|
||||
~SymbolDatabase();
|
||||
|
||||
int Analyze();
|
||||
|
||||
FunctionSymbol* GetOrInsertFunction(uint32_t address);
|
||||
VariableSymbol* GetOrInsertVariable(uint32_t address);
|
||||
FunctionSymbol* GetFunction(uint32_t address);
|
||||
VariableSymbol* GetVariable(uint32_t address);
|
||||
Symbol* GetSymbol(uint32_t address);
|
||||
|
||||
int GetAllFunctions(vector<FunctionSymbol*>& functions);
|
||||
|
||||
void Dump();
|
||||
|
||||
private:
|
||||
typedef std::map<uint32_t, Symbol*> SymbolMap;
|
||||
typedef std::list<FunctionSymbol*> FunctionList;
|
||||
|
||||
int FindGplr();
|
||||
int AddImports(const xe_xex2_import_library_t *library);
|
||||
int AddMethodHints();
|
||||
int AnalyzeFunction(FunctionSymbol* fn);
|
||||
int FillHoles();
|
||||
int FlushQueue();
|
||||
|
||||
xe_memory_ref memory_;
|
||||
kernel::UserModule* module_;
|
||||
size_t function_count_;
|
||||
size_t variable_count_;
|
||||
SymbolMap symbols_;
|
||||
FunctionList scan_queue_;
|
||||
};
|
||||
|
||||
|
||||
struct xe_sdb;
|
||||
typedef struct xe_sdb* xe_sdb_ref;
|
||||
|
||||
|
||||
xe_sdb_ref xe_sdb_create(xe_memory_ref memory, xe_module_ref module);
|
||||
xe_sdb_ref xe_sdb_retain(xe_sdb_ref sdb);
|
||||
void xe_sdb_release(xe_sdb_ref sdb);
|
||||
|
||||
xe_sdb_function_t* xe_sdb_insert_function(xe_sdb_ref sdb, uint32_t address);
|
||||
xe_sdb_variable_t* xe_sdb_insert_variable(xe_sdb_ref sdb, uint32_t address);
|
||||
|
||||
xe_sdb_function_t* xe_sdb_get_function(xe_sdb_ref sdb, uint32_t address);
|
||||
xe_sdb_variable_t* xe_sdb_get_variable(xe_sdb_ref sdb, uint32_t address);
|
||||
|
||||
int xe_sdb_get_functions(xe_sdb_ref sdb, xe_sdb_function_t ***out_functions,
|
||||
size_t *out_function_count);
|
||||
|
||||
void xe_sdb_dump(xe_sdb_ref sdb);
|
||||
} // namespace sdb
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_CPU_SDB_H_
|
||||
|
||||
Reference in New Issue
Block a user