CPU skeleton.
This commit is contained in:
parent
bcd575f9b0
commit
2f4bc598e5
|
@ -13,6 +13,32 @@
|
||||||
#include <xenia/common.h>
|
#include <xenia/common.h>
|
||||||
#include <xenia/core.h>
|
#include <xenia/core.h>
|
||||||
|
|
||||||
void do_cpu_stuff();
|
#include <xenia/kernel/module.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int reserved;
|
||||||
|
} xe_cpu_options_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct xe_cpu;
|
||||||
|
typedef struct xe_cpu* xe_cpu_ref;
|
||||||
|
|
||||||
|
|
||||||
|
xe_cpu_ref xe_cpu_create(xe_pal_ref pal, xe_memory_ref memory,
|
||||||
|
xe_cpu_options_t options);
|
||||||
|
xe_cpu_ref xe_cpu_retain(xe_cpu_ref cpu);
|
||||||
|
void xe_cpu_release(xe_cpu_ref cpu);
|
||||||
|
|
||||||
|
xe_pal_ref xe_cpu_get_pal(xe_cpu_ref cpu);
|
||||||
|
xe_memory_ref xe_cpu_get_memory(xe_cpu_ref cpu);
|
||||||
|
|
||||||
|
int xe_cpu_prepare_module(xe_cpu_ref cpu, xe_module_ref module);
|
||||||
|
|
||||||
|
int xe_cpu_execute(xe_cpu_ref cpu, uint32_t address);
|
||||||
|
|
||||||
|
uint32_t xe_cpu_create_callback(xe_cpu_ref cpu,
|
||||||
|
void (*callback)(void*), void *data);
|
||||||
|
|
||||||
|
|
||||||
#endif // XENIA_CPU_H_
|
#endif // XENIA_CPU_H_
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include <xenia/common.h>
|
#include <xenia/common.h>
|
||||||
#include <xenia/core.h>
|
#include <xenia/core.h>
|
||||||
|
#include <xenia/cpu.h>
|
||||||
|
|
||||||
#include <xenia/kernel/export.h>
|
#include <xenia/kernel/export.h>
|
||||||
#include <xenia/kernel/module.h>
|
#include <xenia/kernel/module.h>
|
||||||
|
@ -27,13 +28,14 @@ struct xe_kernel;
|
||||||
typedef struct xe_kernel* xe_kernel_ref;
|
typedef struct xe_kernel* xe_kernel_ref;
|
||||||
|
|
||||||
|
|
||||||
xe_kernel_ref xe_kernel_create(xe_pal_ref pal, xe_memory_ref memory,
|
xe_kernel_ref xe_kernel_create(xe_pal_ref pal, xe_cpu_ref cpu,
|
||||||
xe_kernel_options_t options);
|
xe_kernel_options_t options);
|
||||||
xe_kernel_ref xe_kernel_retain(xe_kernel_ref kernel);
|
xe_kernel_ref xe_kernel_retain(xe_kernel_ref kernel);
|
||||||
void xe_kernel_release(xe_kernel_ref kernel);
|
void xe_kernel_release(xe_kernel_ref kernel);
|
||||||
|
|
||||||
xe_pal_ref xe_kernel_get_pal(xe_kernel_ref kernel);
|
xe_pal_ref xe_kernel_get_pal(xe_kernel_ref kernel);
|
||||||
xe_memory_ref xe_kernel_get_memory(xe_kernel_ref kernel);
|
xe_memory_ref xe_kernel_get_memory(xe_kernel_ref kernel);
|
||||||
|
xe_cpu_ref xe_kernel_get_cpu(xe_kernel_ref kernel);
|
||||||
|
|
||||||
const xechar_t *xe_kernel_get_command_line(xe_kernel_ref kernel);
|
const xechar_t *xe_kernel_get_command_line(xe_kernel_ref kernel);
|
||||||
|
|
||||||
|
|
|
@ -17,19 +17,68 @@
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
|
||||||
void do_cpu_stuff() {
|
typedef struct xe_cpu {
|
||||||
|
xe_ref_t ref;
|
||||||
|
|
||||||
|
xe_cpu_options_t options;
|
||||||
|
|
||||||
|
xe_pal_ref pal;
|
||||||
|
xe_memory_ref memory;
|
||||||
|
} xe_cpu_t;
|
||||||
|
|
||||||
|
|
||||||
|
xe_cpu_ref xe_cpu_create(xe_pal_ref pal, xe_memory_ref memory,
|
||||||
|
xe_cpu_options_t options) {
|
||||||
|
xe_cpu_ref cpu = (xe_cpu_ref)xe_calloc(sizeof(xe_cpu));
|
||||||
|
xe_ref_init((xe_ref)cpu);
|
||||||
|
|
||||||
|
xe_copy_struct(&cpu->options, &options, sizeof(xe_cpu_options_t));
|
||||||
|
|
||||||
|
cpu->pal = xe_pal_retain(pal);
|
||||||
|
cpu->memory = xe_memory_retain(memory);
|
||||||
|
|
||||||
|
return cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void xe_cpu_dealloc(xe_cpu_ref cpu) {
|
||||||
|
xe_memory_release(cpu->memory);
|
||||||
|
xe_pal_release(cpu->pal);
|
||||||
|
}
|
||||||
|
|
||||||
|
xe_cpu_ref xe_cpu_retain(xe_cpu_ref cpu) {
|
||||||
|
xe_ref_retain((xe_ref)cpu);
|
||||||
|
return cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void xe_cpu_release(xe_cpu_ref cpu) {
|
||||||
|
xe_ref_release((xe_ref)cpu, (xe_ref_dealloc_t)xe_cpu_dealloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
xe_pal_ref xe_cpu_get_pal(xe_cpu_ref cpu) {
|
||||||
|
return xe_pal_retain(cpu->pal);
|
||||||
|
}
|
||||||
|
|
||||||
|
xe_memory_ref xe_cpu_get_memory(xe_cpu_ref cpu) {
|
||||||
|
return xe_memory_retain(cpu->memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xe_cpu_prepare_module(xe_cpu_ref cpu, xe_module_ref module) {
|
||||||
|
// TODO(benvanik): lookup the module in the cache.
|
||||||
|
|
||||||
|
// TODO(benvanik): implement prepare module.
|
||||||
|
|
||||||
XELOGCPU(XT("cpu"));
|
XELOGCPU(XT("cpu"));
|
||||||
|
|
||||||
LLVMContext &context = getGlobalContext();
|
LLVMContext &context = getGlobalContext();
|
||||||
//IRBuilder<> builder(context);
|
//IRBuilder<> builder(context);
|
||||||
Module *module = new Module("my cool jit", context);
|
Module *m = new Module("my cool jit", context);
|
||||||
|
|
||||||
Constant* c = module->getOrInsertFunction("mul_add",
|
Constant* c = m->getOrInsertFunction("mul_add",
|
||||||
/*ret type*/ IntegerType::get(context, 32),
|
/*ret type*/ IntegerType::get(context, 32),
|
||||||
/*args*/ IntegerType::get(context, 32),
|
/*args*/ IntegerType::get(context, 32),
|
||||||
IntegerType::get(context, 32),
|
IntegerType::get(context, 32),
|
||||||
IntegerType::get(context, 32),
|
IntegerType::get(context, 32),
|
||||||
/*varargs terminated with null*/ NULL);
|
/*varargs terminated with null*/ NULL);
|
||||||
|
|
||||||
Function* mul_add = cast<Function>(c);
|
Function* mul_add = cast<Function>(c);
|
||||||
mul_add->setCallingConv(CallingConv::C);
|
mul_add->setCallingConv(CallingConv::C);
|
||||||
|
@ -54,6 +103,18 @@ void do_cpu_stuff() {
|
||||||
|
|
||||||
XELOGD(XT("woo %d"), 123);
|
XELOGD(XT("woo %d"), 123);
|
||||||
|
|
||||||
module->dump();
|
m->dump();
|
||||||
delete module;
|
delete m;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xe_cpu_execute(xe_cpu_ref cpu, uint32_t address) {
|
||||||
|
// TODO(benvanik): implement execute.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t xe_cpu_create_callback(xe_cpu_ref cpu,
|
||||||
|
void (*callback)(void*), void *data) {
|
||||||
|
// TODO(benvanik): implement callback creation.
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ typedef struct xe_kernel {
|
||||||
|
|
||||||
xe_pal_ref pal;
|
xe_pal_ref pal;
|
||||||
xe_memory_ref memory;
|
xe_memory_ref memory;
|
||||||
|
xe_cpu_ref cpu;
|
||||||
xe_kernel_export_resolver_ref export_resolver;
|
xe_kernel_export_resolver_ref export_resolver;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -29,7 +30,7 @@ typedef struct xe_kernel {
|
||||||
} xe_kernel_t;
|
} xe_kernel_t;
|
||||||
|
|
||||||
|
|
||||||
xe_kernel_ref xe_kernel_create(xe_pal_ref pal, xe_memory_ref memory,
|
xe_kernel_ref xe_kernel_create(xe_pal_ref pal, xe_cpu_ref cpu,
|
||||||
xe_kernel_options_t options) {
|
xe_kernel_options_t options) {
|
||||||
xe_kernel_ref kernel = (xe_kernel_ref)xe_calloc(sizeof(xe_kernel));
|
xe_kernel_ref kernel = (xe_kernel_ref)xe_calloc(sizeof(xe_kernel));
|
||||||
xe_ref_init((xe_ref)kernel);
|
xe_ref_init((xe_ref)kernel);
|
||||||
|
@ -37,23 +38,27 @@ xe_kernel_ref xe_kernel_create(xe_pal_ref pal, xe_memory_ref memory,
|
||||||
xe_copy_struct(&kernel->options, &options, sizeof(xe_kernel_options_t));
|
xe_copy_struct(&kernel->options, &options, sizeof(xe_kernel_options_t));
|
||||||
|
|
||||||
kernel->pal = xe_pal_retain(pal);
|
kernel->pal = xe_pal_retain(pal);
|
||||||
kernel->memory = xe_memory_retain(memory);
|
kernel->memory = xe_cpu_get_memory(cpu);
|
||||||
|
kernel->cpu = xe_cpu_retain(cpu);
|
||||||
kernel->export_resolver = xe_kernel_export_resolver_create();
|
kernel->export_resolver = xe_kernel_export_resolver_create();
|
||||||
|
|
||||||
kernel->modules.xam =
|
kernel->modules.xam =
|
||||||
xe_xam_create(pal, memory, kernel->export_resolver);
|
xe_xam_create(kernel->pal, kernel->memory, kernel->export_resolver);
|
||||||
kernel->modules.xbdm =
|
kernel->modules.xbdm =
|
||||||
xe_xbdm_create(pal, memory, kernel->export_resolver);
|
xe_xbdm_create(kernel->pal, kernel->memory, kernel->export_resolver);
|
||||||
kernel->modules.xboxkrnl =
|
kernel->modules.xboxkrnl =
|
||||||
xe_xboxkrnl_create(pal, memory, kernel->export_resolver);
|
xe_xboxkrnl_create(kernel->pal, kernel->memory, kernel->export_resolver);
|
||||||
|
|
||||||
return kernel;
|
return kernel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xe_kernel_dealloc(xe_kernel_ref kernel) {
|
void xe_kernel_dealloc(xe_kernel_ref kernel) {
|
||||||
xe_xboxkrnl_release(kernel->modules.xboxkrnl);
|
xe_xboxkrnl_release(kernel->modules.xboxkrnl);
|
||||||
|
xe_xbdm_release(kernel->modules.xbdm);
|
||||||
|
xe_xam_release(kernel->modules.xam);
|
||||||
|
|
||||||
xe_kernel_export_resolver_release(kernel->export_resolver);
|
xe_kernel_export_resolver_release(kernel->export_resolver);
|
||||||
|
xe_cpu_release(kernel->cpu);
|
||||||
xe_memory_release(kernel->memory);
|
xe_memory_release(kernel->memory);
|
||||||
xe_pal_release(kernel->pal);
|
xe_pal_release(kernel->pal);
|
||||||
}
|
}
|
||||||
|
@ -75,6 +80,10 @@ xe_memory_ref xe_kernel_get_memory(xe_kernel_ref kernel) {
|
||||||
return xe_memory_retain(kernel->memory);
|
return xe_memory_retain(kernel->memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xe_cpu_ref xe_kernel_get_cpu(xe_kernel_ref kernel) {
|
||||||
|
return xe_cpu_retain(kernel->cpu);
|
||||||
|
}
|
||||||
|
|
||||||
const xechar_t *xe_kernel_get_command_line(xe_kernel_ref kernel) {
|
const xechar_t *xe_kernel_get_command_line(xe_kernel_ref kernel) {
|
||||||
return kernel->options.command_line;
|
return kernel->options.command_line;
|
||||||
}
|
}
|
||||||
|
@ -112,13 +121,37 @@ xe_module_ref xe_kernel_load_module(xe_kernel_ref kernel,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// stash in modules list
|
// Prepare the module.
|
||||||
|
XEEXPECTZERO(xe_cpu_prepare_module(kernel->cpu, module));
|
||||||
|
|
||||||
|
// Stash in modules list (takes reference).
|
||||||
|
// TODO(benvanik): stash in list.
|
||||||
return xe_module_retain(module);
|
return xe_module_retain(module);
|
||||||
|
|
||||||
|
XECLEANUP:
|
||||||
|
xe_module_release(module);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xe_kernel_launch_module(xe_kernel_ref kernel, xe_module_ref module) {
|
void xe_kernel_launch_module(xe_kernel_ref kernel, xe_module_ref module) {
|
||||||
//
|
//const xe_xex2_header_t *xex_header = xe_module_get_xex_header(module);
|
||||||
|
|
||||||
|
// TODO(benvanik): set as main module/etc
|
||||||
|
// xekXexExecutableModuleHandle = xe_module_get_handle(module);
|
||||||
|
|
||||||
|
// XEEXPECTTRUE(XECPUPrepareModule(XEGetCPU(), module->xex, module->pe, module->address_space, module->address_space_size));
|
||||||
|
|
||||||
|
// Setup the heap (and TLS?).
|
||||||
|
// xex_header->exe_heap_size;
|
||||||
|
|
||||||
|
// Launch thread.
|
||||||
|
// XHANDLE thread_handle;
|
||||||
|
// XDWORD thread_id;
|
||||||
|
// XBOOL result = xekExCreateThread(&thread_handle, xex_header->exe_stack_size, &thread_id, NULL, (void*)xex_header->exe_entry_point, NULL, 0);
|
||||||
|
|
||||||
|
// Wait until thread completes.
|
||||||
|
// XLARGE_INTEGER timeout = XINFINITE;
|
||||||
|
// xekNtWaitForSingleObjectEx(thread_handle, TRUE, &timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
xe_module_ref xe_kernel_get_module(xe_kernel_ref kernel, const xechar_t *path) {
|
xe_module_ref xe_kernel_get_module(xe_kernel_ref kernel, const xechar_t *path) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ int xenia_info(int argc, xechar_t **argv) {
|
||||||
|
|
||||||
xe_pal_ref pal = NULL;
|
xe_pal_ref pal = NULL;
|
||||||
xe_memory_ref memory = NULL;
|
xe_memory_ref memory = NULL;
|
||||||
|
xe_cpu_ref cpu = NULL;
|
||||||
xe_kernel_ref kernel = NULL;
|
xe_kernel_ref kernel = NULL;
|
||||||
xe_module_ref module = NULL;
|
xe_module_ref module = NULL;
|
||||||
|
|
||||||
|
@ -26,16 +27,23 @@ int xenia_info(int argc, xechar_t **argv) {
|
||||||
const xechar_t *path = argv[1];
|
const xechar_t *path = argv[1];
|
||||||
|
|
||||||
xe_pal_options_t pal_options;
|
xe_pal_options_t pal_options;
|
||||||
|
xe_zero_struct(&pal_options, sizeof(pal_options));
|
||||||
pal = xe_pal_create(pal_options);
|
pal = xe_pal_create(pal_options);
|
||||||
XEEXPECTNOTNULL(pal);
|
XEEXPECTNOTNULL(pal);
|
||||||
|
|
||||||
xe_memory_options_t memory_options;
|
xe_memory_options_t memory_options;
|
||||||
|
xe_zero_struct(&memory_options, sizeof(memory_options));
|
||||||
memory = xe_memory_create(pal, memory_options);
|
memory = xe_memory_create(pal, memory_options);
|
||||||
XEEXPECTNOTNULL(memory);
|
XEEXPECTNOTNULL(memory);
|
||||||
|
|
||||||
|
xe_cpu_options_t cpu_options;
|
||||||
|
xe_zero_struct(&cpu_options, sizeof(cpu_options));
|
||||||
|
cpu = xe_cpu_create(pal, memory, cpu_options);
|
||||||
|
XEEXPECTNOTNULL(cpu);
|
||||||
|
|
||||||
xe_kernel_options_t kernel_options;
|
xe_kernel_options_t kernel_options;
|
||||||
xe_zero_struct(&kernel_options, sizeof(kernel_options));
|
xe_zero_struct(&kernel_options, sizeof(kernel_options));
|
||||||
kernel = xe_kernel_create(pal, memory, kernel_options);
|
kernel = xe_kernel_create(pal, cpu, kernel_options);
|
||||||
XEEXPECTNOTNULL(kernel);
|
XEEXPECTNOTNULL(kernel);
|
||||||
|
|
||||||
module = xe_kernel_load_module(kernel, path);
|
module = xe_kernel_load_module(kernel, path);
|
||||||
|
@ -47,6 +55,7 @@ int xenia_info(int argc, xechar_t **argv) {
|
||||||
XECLEANUP:
|
XECLEANUP:
|
||||||
xe_module_release(module);
|
xe_module_release(module);
|
||||||
xe_kernel_release(kernel);
|
xe_kernel_release(kernel);
|
||||||
|
xe_cpu_release(cpu);
|
||||||
xe_memory_release(memory);
|
xe_memory_release(memory);
|
||||||
xe_pal_release(pal);
|
xe_pal_release(pal);
|
||||||
return result_code;
|
return result_code;
|
||||||
|
|
|
@ -10,9 +10,85 @@
|
||||||
#include <xenia/xenia.h>
|
#include <xenia/xenia.h>
|
||||||
|
|
||||||
|
|
||||||
int xenia_run(int argc, xechar_t **argv) {
|
typedef struct {
|
||||||
do_cpu_stuff();
|
xe_pal_ref pal;
|
||||||
do_gpu_stuff();
|
xe_memory_ref memory;
|
||||||
|
xe_cpu_ref cpu;
|
||||||
|
xe_kernel_ref kernel;
|
||||||
|
xe_module_ref module;
|
||||||
|
} xenia_run_t;
|
||||||
|
|
||||||
|
|
||||||
|
int setup_run(xenia_run_t *run, const xechar_t *path) {
|
||||||
|
xe_pal_options_t pal_options;
|
||||||
|
xe_zero_struct(&pal_options, sizeof(pal_options));
|
||||||
|
run->pal = xe_pal_create(pal_options);
|
||||||
|
XEEXPECTNOTNULL(run->pal);
|
||||||
|
|
||||||
|
xe_memory_options_t memory_options;
|
||||||
|
xe_zero_struct(&memory_options, sizeof(memory_options));
|
||||||
|
run->memory = xe_memory_create(run->pal, memory_options);
|
||||||
|
XEEXPECTNOTNULL(run->memory);
|
||||||
|
|
||||||
|
xe_cpu_options_t cpu_options;
|
||||||
|
xe_zero_struct(&cpu_options, sizeof(cpu_options));
|
||||||
|
run->cpu = xe_cpu_create(run->pal, run->memory, cpu_options);
|
||||||
|
XEEXPECTNOTNULL(run->cpu);
|
||||||
|
|
||||||
|
xe_kernel_options_t kernel_options;
|
||||||
|
xe_zero_struct(&kernel_options, sizeof(kernel_options));
|
||||||
|
run->kernel = xe_kernel_create(run->pal, run->cpu, kernel_options);
|
||||||
|
XEEXPECTNOTNULL(run->kernel);
|
||||||
|
|
||||||
|
run->module = xe_kernel_load_module(run->kernel, path);
|
||||||
|
XEEXPECTNOTNULL(run->module);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
XECLEANUP:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy_run(xenia_run_t *run) {
|
||||||
|
xe_module_release(run->module);
|
||||||
|
xe_kernel_release(run->kernel);
|
||||||
|
xe_cpu_release(run->cpu);
|
||||||
|
xe_memory_release(run->memory);
|
||||||
|
xe_pal_release(run->pal);
|
||||||
|
xe_free(run);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xenia_run(int argc, xechar_t **argv) {
|
||||||
|
// Dummy call to keep the GPU code linking in to ensure it's working.
|
||||||
|
do_gpu_stuff();
|
||||||
|
|
||||||
|
int result_code = 1;
|
||||||
|
|
||||||
|
// TODO(benvanik): real command line parsing.
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("usage: xenia-run some.xex\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
const xechar_t *path = argv[1];
|
||||||
|
|
||||||
|
xenia_run_t *run = (xenia_run_t*)xe_calloc(sizeof(xenia_run_t));
|
||||||
|
XEEXPECTNOTNULL(run);
|
||||||
|
|
||||||
|
result_code = setup_run(run, path);
|
||||||
|
XEEXPECTZERO(result_code);
|
||||||
|
|
||||||
|
xe_module_dump(run->module);
|
||||||
|
|
||||||
|
xe_kernel_launch_module(run->kernel, run->module);
|
||||||
|
|
||||||
|
// TODO(benvanik): wait until the module thread exits
|
||||||
|
destroy_run(run);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
XECLEANUP:
|
||||||
|
if (run) {
|
||||||
|
destroy_run(run);
|
||||||
|
}
|
||||||
|
return result_code;
|
||||||
}
|
}
|
||||||
XE_MAIN_THUNK(xenia_run);
|
XE_MAIN_THUNK(xenia_run);
|
||||||
|
|
Loading…
Reference in New Issue