diff --git a/include/xenia/cpu.h b/include/xenia/cpu.h index 6d34e971b..6cbef37a8 100644 --- a/include/xenia/cpu.h +++ b/include/xenia/cpu.h @@ -13,6 +13,32 @@ #include #include -void do_cpu_stuff(); +#include + + +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_ diff --git a/include/xenia/kernel.h b/include/xenia/kernel.h index f71da9250..7dffae2c6 100644 --- a/include/xenia/kernel.h +++ b/include/xenia/kernel.h @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -27,13 +28,14 @@ struct xe_kernel; 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_ref xe_kernel_retain(xe_kernel_ref kernel); void xe_kernel_release(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_cpu_ref xe_kernel_get_cpu(xe_kernel_ref kernel); const xechar_t *xe_kernel_get_command_line(xe_kernel_ref kernel); diff --git a/src/cpu/cpu.cc b/src/cpu/cpu.cc index 87aa74e1b..ae081b7e9 100644 --- a/src/cpu/cpu.cc +++ b/src/cpu/cpu.cc @@ -17,19 +17,68 @@ 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")); LLVMContext &context = getGlobalContext(); //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", - /*ret type*/ IntegerType::get(context, 32), - /*args*/ IntegerType::get(context, 32), - IntegerType::get(context, 32), - IntegerType::get(context, 32), - /*varargs terminated with null*/ NULL); + Constant* c = m->getOrInsertFunction("mul_add", + /*ret type*/ IntegerType::get(context, 32), + /*args*/ IntegerType::get(context, 32), + IntegerType::get(context, 32), + IntegerType::get(context, 32), + /*varargs terminated with null*/ NULL); Function* mul_add = cast(c); mul_add->setCallingConv(CallingConv::C); @@ -54,6 +103,18 @@ void do_cpu_stuff() { XELOGD(XT("woo %d"), 123); - module->dump(); - delete module; + m->dump(); + 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; } diff --git a/src/kernel/kernel.cc b/src/kernel/kernel.cc index 5a17bc443..fd3784d61 100644 --- a/src/kernel/kernel.cc +++ b/src/kernel/kernel.cc @@ -19,6 +19,7 @@ typedef struct xe_kernel { xe_pal_ref pal; xe_memory_ref memory; + xe_cpu_ref cpu; xe_kernel_export_resolver_ref export_resolver; struct { @@ -29,7 +30,7 @@ typedef struct xe_kernel { } 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_ref kernel = (xe_kernel_ref)xe_calloc(sizeof(xe_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)); 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->modules.xam = - xe_xam_create(pal, memory, kernel->export_resolver); + xe_xam_create(kernel->pal, kernel->memory, kernel->export_resolver); kernel->modules.xbdm = - xe_xbdm_create(pal, memory, kernel->export_resolver); + xe_xbdm_create(kernel->pal, kernel->memory, kernel->export_resolver); kernel->modules.xboxkrnl = - xe_xboxkrnl_create(pal, memory, kernel->export_resolver); + xe_xboxkrnl_create(kernel->pal, kernel->memory, kernel->export_resolver); return kernel; } void xe_kernel_dealloc(xe_kernel_ref kernel) { 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_cpu_release(kernel->cpu); xe_memory_release(kernel->memory); 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); } +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) { return kernel->options.command_line; } @@ -112,13 +121,37 @@ xe_module_ref xe_kernel_load_module(xe_kernel_ref kernel, 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); + +XECLEANUP: + xe_module_release(module); + return NULL; } 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) { diff --git a/tools/xenia-info/xenia-info.cc b/tools/xenia-info/xenia-info.cc index c613987a8..1ead07e13 100644 --- a/tools/xenia-info/xenia-info.cc +++ b/tools/xenia-info/xenia-info.cc @@ -15,6 +15,7 @@ int xenia_info(int argc, xechar_t **argv) { xe_pal_ref pal = NULL; xe_memory_ref memory = NULL; + xe_cpu_ref cpu = NULL; xe_kernel_ref kernel = NULL; xe_module_ref module = NULL; @@ -26,16 +27,23 @@ int xenia_info(int argc, xechar_t **argv) { const xechar_t *path = argv[1]; xe_pal_options_t pal_options; + xe_zero_struct(&pal_options, sizeof(pal_options)); pal = xe_pal_create(pal_options); XEEXPECTNOTNULL(pal); xe_memory_options_t memory_options; + xe_zero_struct(&memory_options, sizeof(memory_options)); memory = xe_memory_create(pal, memory_options); 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_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); module = xe_kernel_load_module(kernel, path); @@ -47,6 +55,7 @@ int xenia_info(int argc, xechar_t **argv) { XECLEANUP: xe_module_release(module); xe_kernel_release(kernel); + xe_cpu_release(cpu); xe_memory_release(memory); xe_pal_release(pal); return result_code; diff --git a/tools/xenia-run/xenia-run.cc b/tools/xenia-run/xenia-run.cc index 248a3cad4..3bfcb14bd 100644 --- a/tools/xenia-run/xenia-run.cc +++ b/tools/xenia-run/xenia-run.cc @@ -10,9 +10,85 @@ #include -int xenia_run(int argc, xechar_t **argv) { - do_cpu_stuff(); - do_gpu_stuff(); +typedef struct { + xe_pal_ref pal; + 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; + +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);