mirror of
https://github.com/open-goal/jak-project
synced 2026-06-17 23:21:41 -04:00
move GOAL stack to GOAL memory (#114)
* move GOAL code stack to GOAL memory * fix win arg reg and check rsp in debugger * fix windows maybe and fix some incorrect logging formatters
This commit is contained in:
@@ -133,6 +133,47 @@ _call_goal_asm_linux:
|
||||
pop r13
|
||||
ret
|
||||
|
||||
global _call_goal_on_stack_asm_linux
|
||||
|
||||
_call_goal_on_stack_asm_linux:
|
||||
;; RDI - stack pointer
|
||||
;; RSI - unused
|
||||
;; RDX - unused
|
||||
;; RCX - function pointer (goes in r13)
|
||||
;; R8 - st (goes in r14)
|
||||
;; R9 - off (goes in r15)
|
||||
|
||||
;; x86 saved registers we need to modify for GOAL should be saved
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
|
||||
;; stash current stack pointer in rsi
|
||||
mov rsi, rsp
|
||||
;; switch to new stack
|
||||
mov rsp, rdi
|
||||
;; back up old stack pointer
|
||||
push rsi
|
||||
|
||||
;; set GOAL function pointer
|
||||
mov r13, rcx
|
||||
;; offset
|
||||
mov r14, r8
|
||||
;; symbol table
|
||||
mov r15, r9
|
||||
;; call GOAL by function pointer
|
||||
call r13
|
||||
|
||||
;; get old stack pointer
|
||||
pop rsi
|
||||
mov rsp, rsi
|
||||
|
||||
;; retore x86 registers.
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
ret
|
||||
|
||||
|
||||
;; The _call_goal_asm function is used to call a GOAL function from C.
|
||||
;; It supports up to 3 arguments and a return value.
|
||||
@@ -184,4 +225,56 @@ _call_goal_asm_win32:
|
||||
pop rbx
|
||||
pop rdx
|
||||
|
||||
ret
|
||||
|
||||
global _call_goal_on_stack_asm_win32
|
||||
|
||||
_call_goal_on_stack_asm_win32:
|
||||
;; arg0 (rcx) stack
|
||||
;; arg1 (rdx) fp
|
||||
;; arg2 (r8) st
|
||||
;; arg3 (r9) off
|
||||
push rdx ; 8
|
||||
push rbx ; 16
|
||||
push rbp ; 24
|
||||
push rsi ; 32
|
||||
push rdi ; 40
|
||||
push r8 ; 48
|
||||
push r9 ; 56
|
||||
push r10 ; 64
|
||||
push r11 ; 72
|
||||
push r12 ; 80
|
||||
push r13 ; 88
|
||||
push r14 ; 96
|
||||
push r15 ; 104
|
||||
|
||||
;; stack swap
|
||||
mov rsi, rsp
|
||||
mov rsp, rcx
|
||||
push rsi
|
||||
|
||||
mov r13, rdx ;; fp
|
||||
mov r14, r8 ;; st
|
||||
mov r15, r9 ;; offset
|
||||
|
||||
call r13
|
||||
|
||||
;; restore stack
|
||||
pop rsi
|
||||
mov rsp, rsi
|
||||
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rbp
|
||||
pop rbx
|
||||
pop rdx
|
||||
|
||||
ret
|
||||
+8
-11
@@ -136,6 +136,8 @@ s32 goal_main(int argc, const char* const* argv) {
|
||||
* Main loop to dispatch the GOAL kernel.
|
||||
*/
|
||||
void KernelCheckAndDispatch() {
|
||||
u64 goal_stack = u64(g_ee_main_mem) + EE_MAIN_MEM_SIZE - 8;
|
||||
|
||||
while (!MasterExit) {
|
||||
// try to get a message from the listener, and process it if needed
|
||||
Ptr<char> new_message = WaitForMessageAndAck();
|
||||
@@ -148,20 +150,15 @@ void KernelCheckAndDispatch() {
|
||||
// dispatch the kernel
|
||||
//(**kernel_dispatcher)();
|
||||
|
||||
// todo remove. this is added while KERNEL.CGO is broken.
|
||||
if (MasterUseKernel) {
|
||||
call_goal(Ptr<Function>(kernel_dispatcher->value), 0, 0, 0, s7.offset, g_ee_main_mem);
|
||||
// use the GOAL kernel.
|
||||
call_goal_on_stack(Ptr<Function>(kernel_dispatcher->value), goal_stack, s7.offset,
|
||||
g_ee_main_mem);
|
||||
} else {
|
||||
// use a hack to just run the listener function if there's no GOAL kernel.
|
||||
if (ListenerFunction->value != s7.offset) {
|
||||
// fprintf(stderr, "Running Listener Function:\n");
|
||||
// auto cptr = Ptr<u8>(ListenerFunction->value).c();
|
||||
// for (int i = 0; i < 40; i++) {
|
||||
// fprintf(stderr, "%x ", cptr[i]);
|
||||
// }
|
||||
// fprintf(stderr, "\n");
|
||||
auto result =
|
||||
call_goal(Ptr<Function>(ListenerFunction->value), 0, 0, 0, s7.offset, g_ee_main_mem);
|
||||
// fprintf(stderr, "result of listener function: %lld\n", result);
|
||||
auto result = call_goal_on_stack(Ptr<Function>(ListenerFunction->value), goal_stack,
|
||||
s7.offset, g_ee_main_mem);
|
||||
#ifdef __linux__
|
||||
cprintf("%ld\n", result);
|
||||
#else
|
||||
|
||||
@@ -176,7 +176,7 @@ void BeginLoadingDGO(const char* name, Ptr<u8> buffer1, Ptr<u8> buffer2, Ptr<u8>
|
||||
|
||||
// file name
|
||||
strcpy(sMsg[msgID].name, name);
|
||||
spdlog::debug("[Begin Loading DGO RPC] {}, 0x{}, 0x{}, 0x{}", name, buffer1.offset,
|
||||
spdlog::debug("[Begin Loading DGO RPC] {}, 0x{:x}, 0x{:x}, 0x{:x}", name, buffer1.offset,
|
||||
buffer2.offset, currentHeap.offset);
|
||||
// this RPC will return once we have loaded the first object file.
|
||||
// but we call async, so we don't block here.
|
||||
|
||||
@@ -302,8 +302,8 @@ int InitMachine() {
|
||||
// initialize the global heap
|
||||
u32 global_heap_size = GLOBAL_HEAP_END - HEAP_START;
|
||||
float size_mb = ((float)global_heap_size) / (float)(1 << 20);
|
||||
spdlog::info("gkernel: global heap 0x{} to 0x{} (size {} MB)", HEAP_START, GLOBAL_HEAP_END,
|
||||
size_mb);
|
||||
spdlog::info("gkernel: global heap 0x{:08x} to 0x{:08x} (size {:.3f} MB)", HEAP_START,
|
||||
GLOBAL_HEAP_END, size_mb);
|
||||
kinitheap(kglobalheap, Ptr<u8>(HEAP_START), global_heap_size);
|
||||
|
||||
// initialize the debug heap, if appropriate
|
||||
@@ -312,8 +312,8 @@ int InitMachine() {
|
||||
kinitheap(kdebugheap, Ptr<u8>(DEBUG_HEAP_START), debug_heap_size);
|
||||
float debug_size_mb = ((float)debug_heap_size) / (float)(1 << 20);
|
||||
float gap_size_mb = ((float)DEBUG_HEAP_START - GLOBAL_HEAP_END) / (float)(1 << 20);
|
||||
spdlog::info("gkernel: global heap 0x{} to 0x{} (size {} MB, gap {} MB)", DEBUG_HEAP_START,
|
||||
debug_heap_end, debug_size_mb, gap_size_mb);
|
||||
spdlog::info("gkernel: debug heap 0x{:08x} to 0x{:08x} (size {:.3f} MB, gap {:.3f} MB)",
|
||||
DEBUG_HEAP_START, debug_heap_end, debug_size_mb, gap_size_mb);
|
||||
} else {
|
||||
// if no debug, we make the kheapinfo structure NULL so GOAL knows not to use it.
|
||||
kdebugheap.offset = 0;
|
||||
|
||||
@@ -997,13 +997,21 @@ extern "C" {
|
||||
// defined in asm_funcs.asm
|
||||
#ifdef __linux__
|
||||
uint64_t _call_goal_asm_linux(u64 a0, u64 a1, u64 a2, void* fptr, void* st_ptr, void* offset);
|
||||
uint64_t _call_goal_on_stack_asm_linux(u64 rsp,
|
||||
u64 u0,
|
||||
u64 u1,
|
||||
void* fptr,
|
||||
void* st_ptr,
|
||||
void* offset);
|
||||
#elif _WIN32
|
||||
uint64_t _call_goal_asm_win32(u64 a0, u64 a1, u64 a2, void* fptr, void* st_ptr, void* offset);
|
||||
uint64_t _call_goal_on_stack_asm_win32(u64 rsp, void* fptr, void* st_ptr, void* offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* Wrapper around _call_goal_asm for calling a GOAL function from C.
|
||||
* Calls from the parent stack.
|
||||
*/
|
||||
u64 call_goal(Ptr<Function> f, u64 a, u64 b, u64 c, u64 st, void* offset) {
|
||||
// auto st_ptr = (void*)((uint8_t*)(offset) + st); updated for the new compiler!
|
||||
@@ -1017,6 +1025,20 @@ u64 call_goal(Ptr<Function> f, u64 a, u64 b, u64 c, u64 st, void* offset) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* Wrapper around _call_goal_asm_on_stack for switching stacks and calling a GOAL function there.
|
||||
*/
|
||||
u64 call_goal_on_stack(Ptr<Function> f, u64 rsp, u64 st, void* offset) {
|
||||
void* st_ptr = (void*)st;
|
||||
|
||||
void* fptr = f.c();
|
||||
#ifdef __linux__
|
||||
return _call_goal_on_stack_asm_linux(rsp, 0, 0, fptr, st_ptr, offset);
|
||||
#elif _WIN32
|
||||
return _call_goal_on_stack_asm_win32(rsp, fptr, st_ptr, offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* Call a GOAL method of a given type.
|
||||
*/
|
||||
|
||||
@@ -89,6 +89,7 @@ u64 inspect_pair(u32 obj);
|
||||
u64 inspect_binteger(u64 obj);
|
||||
s32 InitHeapAndSymbol();
|
||||
u64 call_goal(Ptr<Function> f, u64 a, u64 b, u64 c, u64 st, void* offset);
|
||||
u64 call_goal_on_stack(Ptr<Function> f, u64 rsp, u64 st, void* offset);
|
||||
void print_symbol_table();
|
||||
u64 make_string_from_c(const char* c_str);
|
||||
Ptr<Symbol> find_symbol_from_c(const char* name);
|
||||
|
||||
@@ -385,7 +385,7 @@ void LoadDiscID() {
|
||||
for (uint32_t i = 0; i < SECTOR_SIZE / 4; i++) {
|
||||
CD_ID_SectorSum += CD_ID_Sector[i];
|
||||
}
|
||||
spdlog::info("[OVERLORD] DISK_ID.DIZ OK 0x{}\n", CD_ID_SectorSum);
|
||||
spdlog::info("[OVERLORD] DISK_ID.DIZ OK 0x{:x}\n", CD_ID_SectorSum);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
+1
-1
@@ -120,7 +120,7 @@ void ee_runner(SystemThreadInterface& iface) {
|
||||
}
|
||||
|
||||
spdlog::debug("Main memory mapped at 0x{:016x}", (u64)(g_ee_main_mem));
|
||||
spdlog::debug("Main memory size 0x{} bytes ({} MB)", EE_MAIN_MEM_SIZE,
|
||||
spdlog::debug("Main memory size 0x{:x} bytes ({:.3f} MB)", EE_MAIN_MEM_SIZE,
|
||||
(double)EE_MAIN_MEM_SIZE / (1 << 20));
|
||||
|
||||
spdlog::debug("[EE] Initialization complete!");
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ s32 sceDeci2Open(u16 protocol, void* opt, void (*handler)(s32 event, s32 param,
|
||||
drv.active = true;
|
||||
protocols[protocol_count++] = drv;
|
||||
// printf("[DECI2] Add new protocol driver %d for 0x%x\n", drv.id, drv.protocol);
|
||||
spdlog::info("[DECI2] Add new protocol driver {} for 0x{}", drv.id, drv.protocol);
|
||||
spdlog::info("[DECI2] Add new protocol driver {} for 0x{:x}", drv.id, drv.protocol);
|
||||
server->unlock();
|
||||
|
||||
if (protocol_count == 1) {
|
||||
|
||||
@@ -170,6 +170,11 @@ TEST(Debugger, SimpleBreakpoint) {
|
||||
// instructions can be at most 15 bytes long.
|
||||
EXPECT_TRUE(rip > expected_instr_before_rip && rip < expected_instr_before_rip + 15);
|
||||
|
||||
// check rsp in goal code to make sure the GOAL stack is in the right space.
|
||||
auto rsp = compiler.get_debugger().get_regs().gprs[emitter::RSP];
|
||||
EXPECT_TRUE(rsp < compiler.get_debugger().get_x86_base_addr() + EE_MAIN_MEM_SIZE);
|
||||
EXPECT_TRUE(rsp > compiler.get_debugger().get_x86_base_addr() + EE_MAIN_MEM_SIZE - (16 * 1024));
|
||||
|
||||
EXPECT_TRUE(compiler.get_debugger().is_halted());
|
||||
compiler.get_debugger().remove_addr_breakpoint(func_addr);
|
||||
compiler.get_debugger().do_continue();
|
||||
|
||||
Reference in New Issue
Block a user