diff --git a/libctru/include/3ds/svc.h b/libctru/include/3ds/svc.h index 08a25ab..b39edf7 100644 --- a/libctru/include/3ds/svc.h +++ b/libctru/include/3ds/svc.h @@ -188,51 +188,366 @@ static inline u32* getThreadCommandBuffer(void) return (u32*)((u8*)getThreadLocalStorage() + 0x80); } +static inline void __attribute__((noreturn)) svcExitProcess() +{ + asm volatile("svc 0x03" + ::: "lr"); + __builtin_unreachable(); +} + +static inline void __attribute__((noreturn)) svcExitThread() +{ + asm volatile("svc 0x09" + ::: "lr"); + __builtin_unreachable(); +} + +static inline void svcSleepThread(s64 ns) +{ + register s64 r0 asm("r0") = ns; + + asm volatile("svc 0x0A" + :: "r"(r0) + : "lr"); +} + +static inline s32 svcSetThreadPriority(Handle thread, s32 prio) +{ + register Handle r0 asm("r0") = thread; + register s32 r1 asm("r1") = prio; + register s32 res asm("r0"); + + asm volatile("svc 0x0C" + : "=r"(res) + : "r"(r0), "r"(r1) + : "lr"); + + return res; +} + +static inline s32 svcReleaseMutex(Handle handle) +{ + register Handle r0 asm("r0") = handle; + register s32 res asm("r0"); + + asm volatile("svc 0x14" + : "=r"(res) + : "r"(r0) + : "lr"); + + return res; +} + +static inline s32 svcSignalEvent(Handle handle) +{ + register Handle r0 asm("r0") = handle; + register s32 res asm("r0"); + + asm volatile("svc 0x18" + : "=r"(res) + : "r"(r0) + : "lr"); + + return res; +} + +static inline s32 svcClearEvent(Handle handle) +{ + register Handle r0 asm("r0") = handle; + register s32 res asm("r0"); + + asm volatile("svc 0x19" + : "=r"(res) + : "r"(r0) + : "lr"); + + return res; +} + +static inline s32 svcSetTimer(Handle timer, s64 initial, s64 interval) +{ + register Handle r0 asm("r0") = timer; + register s64 r1 asm("r1") = initial; + register s64 r2 asm("r2") = interval; + register s32 res asm("r0"); + + asm volatile("svc 0x1B" + : "=r"(res) + : "r"(r0), "r"(r1), "r"(r2) + : "lr"); + + return res; +} + +static inline s32 svcCancelTimer(Handle timer) +{ + register Handle r0 asm("r0") = timer; + register s32 res asm("r0"); + + asm volatile("svc 0x1C" + : "=r"(res) + : "r"(r0) + : "lr"); + + return res; +} + +static inline s32 svcClearTimer(Handle timer) +{ + register Handle r0 asm("r0") = timer; + register s32 res asm("r0"); + + asm volatile("svc 0x1D" + : "=r"(res) + : "r"(r0) + : "lr"); + + return res; +} + +static inline s32 svcMapMemoryBlock( + Handle memblock, u32 addr, MemPerm my_perm, MemPerm other_perm) +{ + register Handle r0 asm("r0") = memblock; + register u32 r1 asm("r1") = addr; + register MemPerm r2 asm("r2") = my_perm; + register MemPerm r3 asm("r3") = other_perm; + register s32 res asm("r0"); + + asm volatile("svc 0x1F" + : "=r"(res) + : "r"(r0), "r"(r1), "r"(r2), "r"(r3) + : "lr"); + + return res; +} + +static inline s32 svcUnmapMemoryBlock(Handle memblock, u32 addr) +{ + register Handle r0 asm("r0") = memblock; + register u32 r1 asm("r1") = addr; + register s32 res asm("r0"); + + asm volatile("svc 0x20" + : "=r"(res) + : "r"(r0), "r"(r1) + : "lr"); + + return res; +} + +static inline s32 svcCreateAddressArbiter(Handle *arbiter) +{ + register Handle *r0 asm("r0") = arbiter; + register s32 res asm("r0"); + + asm volatile("svc 0x21" + : "=r"(res) + : "r"(r0) + : "lr"); + + return res; +} + +static inline s32 svcCloseHandle(Handle handle) +{ + register Handle r0 asm("r0") = handle; + register s32 res asm("r0"); + + asm volatile("svc 0x23" + : "=r"(res) + : "r"(r0) + : "lr"); + + return res; +} + +static inline s32 svcWaitSynchronization(Handle handle, s64 nanoseconds) +{ + register Handle r0 asm("r0") = handle; + register s32 r1 asm("r1") = nanoseconds & 0xFFFFFFFF; + register s32 r2 asm("r2") = (nanoseconds >> 32) & 0xFFFFFFFF; + register s32 res asm("r0"); + + asm volatile("svc 0x24" + : "=r"(res) + : "r"(r0), "r"(r1), "r"(r2) + : "lr"); + + return res; +} + +static inline u64 svcGetSystemTick() +{ + register u32 r0 asm("r0"); + register u32 r1 asm("r1"); + + asm volatile("svc 0x28" + : "=r"(r0), "=r"(r1) + :: "lr"); + + return r0 | ((u64)r1 << 32); +} + +static inline s32 svcSendSyncRequest(Handle session) +{ + register Handle r0 asm("r0") = session; + register s32 res asm("r0"); + + asm volatile("svc 0x32" + : "=r"(res) + : "r"(r0) + : "lr"); + + return res; +} + +static inline s32 svcOutputDebugString(const char* str, int length) +{ + register const char *r0 asm("r0") = str; + register int r1 asm("r1") = length; + register s32 res asm("r0"); + + asm volatile("svc 0x3D" + : "=r"(res) + : "r"(r0), "r"(r1) + : "lr"); + + return res; +} + +static inline Result svcBreakDebugProcess(Handle debug) +{ + register Handle r0 asm("r0") = debug; + register s32 res asm("r0"); + + asm volatile("svc 0x61" + : "=r"(res) + : "r"(r0) + : "lr"); + + return res; +} + +static inline Result svcTerminateDebugProcess(Handle debug) +{ + register Handle r0 asm("r0") = debug; + register s32 res asm("r0"); + + asm volatile("svc 0x62" + : "=r"(res) + : "r"(r0) + : "lr"); + + return res; +} + +static inline Result svcGetProcessDebugEvent(DebugEventInfo *info, Handle debug) +{ + register DebugEventInfo *r0 asm("r0") = info; + register Handle r1 asm("r1") = debug; + register Result res asm("r0"); + + asm volatile("svc 0x63" + : "=r"(res) + : "r"(r0), "r"(r1) + : "lr"); + + return res; +} + +static inline Result svcContinueDebugEvent(Handle debug, u32 flags) +{ + register Handle r0 asm("r0") = debug; + register u32 r1 asm("r1") = flags; + register Result res asm("r0"); + + asm volatile("svc 0x64" + : "=r"(res) + : "r"(r0), "r"(r1) + : "lr"); + + return res; +} + +static inline Result svcReadProcessMemory(void* buffer, Handle debug, u32 addr, u32 size) +{ + register void* r0 asm("r0") = buffer; + register Handle r1 asm("r1") = debug; + register u32 r2 asm("r2") = addr; + register u32 r3 asm("r3") = size; + register Result res asm("r0"); + + asm volatile("svc 0x6A" + : "=r"(res) + : "r"(r0), "r"(r1), "r"(r2), "r"(r3) + : "lr"); + + return res; +} + +static inline Result svcMapProcessMemory(Handle process, u32 startAddr, u32 endAddr) +{ + register Handle r0 asm("r0") = process; + register u32 r1 asm("r1") = startAddr; + register u32 r2 asm("r2") = endAddr; + register Result res asm("r0"); + + asm volatile("svc 0x71" + : "=r"(res) + : "r"(r0), "r"(r1), "r"(r2) + : "lr"); + + return res; +} + +static inline Result svcUnmapProcessMemory(Handle process, u32 startAddr, u32 endAddr) +{ + register Handle r0 asm("r0") = process; + register u32 r1 asm("r1") = startAddr; + register u32 r2 asm("r2") = endAddr; + register Result res asm("r0"); + + asm volatile("svc 0x72" + : "=r"(res) + : "r"(r0), "r"(r1), "r"(r2) + : "lr"); + + return res; +} + +static inline s32 svcGetProcessorID() +{ + register s32 res asm("r0"); + + asm volatile("svc 0x11" + : "=r"(res) + :: "lr"); + + return res; +} + s32 svcControlMemory(u32* addr_out, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm); s32 svcQueryMemory(MemInfo* info, PageInfo* out, u32 addr); -void __attribute__((noreturn)) svcExitProcess(); s32 svcCreateThread(Handle* thread, ThreadFunc entrypoint, u32 arg, u32* stack_top, s32 thread_priority, s32 processor_id); -void __attribute__((noreturn)) svcExitThread(); -void svcSleepThread(s64 ns); s32 svcSetThreadPriority(Handle thread, s32 prio); s32 svcCreateMutex(Handle* mutex, bool initially_locked); -s32 svcReleaseMutex(Handle handle); s32 svcCreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count); s32 svcReleaseSemaphore(s32* count, Handle semaphore, s32 release_count); s32 svcCreateEvent(Handle* event, u8 reset_type); -s32 svcSignalEvent(Handle handle); -s32 svcClearEvent(Handle handle); s32 svcCreateTimer(Handle* timer, u8 reset_type); -s32 svcSetTimer(Handle timer, s64 initial, s64 interval); -s32 svcCancelTimer(Handle timer); -s32 svcClearTimer(Handle timer); s32 svcCreateMemoryBlock(Handle* memblock, u32 addr, u32 size, MemPerm my_perm, MemPerm other_perm); -s32 svcMapMemoryBlock(Handle memblock, u32 addr, MemPerm my_perm, MemPerm other_perm); -s32 svcUnmapMemoryBlock(Handle memblock, u32 addr); -s32 svcCreateAddressArbiter(Handle *arbiter); s32 svcArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds); -s32 svcWaitSynchronization(Handle handle, s64 nanoseconds); s32 svcWaitSynchronizationN(s32* out, Handle* handles, s32 handles_num, bool wait_all, s64 nanoseconds); -s32 svcCloseHandle(Handle handle); s32 svcDuplicateHandle(Handle* out, Handle original); -u64 svcGetSystemTick(); s32 svcGetSystemInfo(s64* out, u32 type, s32 param); s32 svcGetProcessInfo(s64* out, Handle process, u32 type); s32 svcConnectToPort(volatile Handle* out, const char* portName); -s32 svcSendSyncRequest(Handle session); Result svcOpenProcess(Handle* process, u32 processId); s32 svcGetProcessId(u32 *out, Handle handle); s32 svcGetThreadId(u32 *out, Handle handle); -s32 svcOutputDebugString(const char* str, int length); Result svcCreatePort(Handle* portServer, Handle* portClient, const char* name, s32 maxSessions); Result svcDebugActiveProcess(Handle* debug, u32 processId); -Result svcBreakDebugProcess(Handle debug); -Result svcTerminateDebugProcess(Handle debug); -Result svcGetProcessDebugEvent(DebugEventInfo *info, Handle debug); -Result svcContinueDebugEvent(Handle debug, u32 flags); + Result svcGetProcessList(s32* processCount, u32* processIds, s32 processIdMaxCount); -Result svcReadProcessMemory(void* buffer, Handle debug, u32 addr, u32 size); -Result svcMapProcessMemory(Handle process, u32 startAddr, u32 endAddr); -Result svcUnmapProcessMemory(Handle process, u32 startAddr, u32 endAddr); Result svcQueryProcessMemory(MemInfo* info, PageInfo* out, Handle process, u32 addr); -s32 svcGetProcessorID(); diff --git a/libctru/source/svc.s b/libctru/source/svc.s index 534a944..5c4c575 100644 --- a/libctru/source/svc.s +++ b/libctru/source/svc.s @@ -29,12 +29,6 @@ svcQueryMemory: pop {r4-r6} bx lr -.global svcExitProcess -.type svcExitProcess, %function -svcExitProcess: - svc 0x03 - bx lr - .global svcCreateThread .type svcCreateThread, %function svcCreateThread: @@ -47,24 +41,6 @@ svcCreateThread: ldr r4, [sp], #4 bx lr -.global svcExitThread -.type svcExitThread, %function -svcExitThread: - svc 0x09 - bx lr - -.global svcSleepThread -.type svcSleepThread, %function -svcSleepThread: - svc 0x0A - bx lr - -.global svcSetThreadPriority -.type svcSetThreadPriority, %function -svcSetThreadPriority: - svc 0x0C - bx lr - .global svcCreateMutex .type svcCreateMutex, %function svcCreateMutex: @@ -74,12 +50,6 @@ svcCreateMutex: str r1, [r3] bx lr -.global svcReleaseMutex -.type svcReleaseMutex, %function -svcReleaseMutex: - svc 0x14 - bx lr - .global svcCreateEvent .type svcCreateEvent, %function svcCreateEvent: @@ -89,18 +59,6 @@ svcCreateEvent: str r1, [r2] bx lr -.global svcSignalEvent -.type svcSignalEvent, %function -svcSignalEvent: - svc 0x18 - bx lr - -.global svcClearEvent -.type svcClearEvent, %function -svcClearEvent: - svc 0x19 - bx lr - .global svcCreateTimer .type svcCreateTimer, %function svcCreateTimer: @@ -110,24 +68,6 @@ svcCreateTimer: str r1, [r2] bx lr -.global svcSetTimer -.type svcSetTimer, %function -svcSetTimer: - svc 0x1B - bx lr - -.global svcCancelTimer -.type svcCancelTimer, %function -svcCancelTimer: - svc 0x1C - bx lr - -.global svcClearTimer -.type svcClearTimer, %function -svcClearTimer: - svc 0x1D - bx lr - .global svcCreateMemoryBlock .type svcCreateMemoryBlock, %function svcCreateMemoryBlock: @@ -138,24 +78,6 @@ svcCreateMemoryBlock: str r1, [r2] bx lr -.global svcMapMemoryBlock -.type svcMapMemoryBlock, %function -svcMapMemoryBlock: - svc 0x1F - bx lr - -.global svcUnmapMemoryBlock -.type svcUnmapMemoryBlock, %function -svcUnmapMemoryBlock: - svc 0x20 - bx lr - -.global svcCreateAddressArbiter -.type svcCreateAddressArbiter, %function -svcCreateAddressArbiter: - svc 0x21 - bx lr - .global svcArbitrateAddress .type svcArbitrateAddress, %function svcArbitrateAddress: @@ -168,18 +90,6 @@ svcArbitrateAddress: pop {r4, r5} bx lr -.global svcCloseHandle -.type svcCloseHandle, %function -svcCloseHandle: - svc 0x23 - bx lr - -.global svcWaitSynchronization -.type svcWaitSynchronization, %function -svcWaitSynchronization: - svc 0x24 - bx lr - .global svcWaitSynchronizationN .type svcWaitSynchronizationN, %function svcWaitSynchronizationN: @@ -203,12 +113,6 @@ svcDuplicateHandle: str r1, [r3] bx lr -.global svcGetSystemTick -.type svcGetSystemTick, %function -svcGetSystemTick: - svc 0x28 - bx lr - .global svcGetSystemInfo .type svcGetSystemInfo, %function svcGetSystemInfo: @@ -241,12 +145,6 @@ svcConnectToPort: str r1, [r3] bx lr -.global svcSendSyncRequest -.type svcSendSyncRequest, %function -svcSendSyncRequest: - svc 0x32 - bx lr - .global svcOpenProcess .type svcOpenProcess, %function svcOpenProcess: @@ -265,12 +163,6 @@ svcGetProcessId: str r1, [r3] bx lr -.global svcOutputDebugString -.type svcOutputDebugString, %function -svcOutputDebugString: - svc 0x3D - bx lr - .global svcCreateSemaphore .type svcCreateSemaphore, %function svcCreateSemaphore: @@ -319,30 +211,6 @@ svcDebugActiveProcess: str r1, [r2] bx lr -.global svcBreakDebugProcess -.type svcBreakDebugProcess, %function -svcBreakDebugProcess: - svc 0x61 - bx lr - -.global svcTerminateDebugProcess -.type svcTerminateDebugProcess, %function -svcTerminateDebugProcess: - svc 0x62 - bx lr - -.global svcGetProcessDebugEvent -.type svcGetProcessDebugEvent, %function -svcGetProcessDebugEvent: - svc 0x63 - bx lr - -.global svcContinueDebugEvent -.type svcContinueDebugEvent, %function -svcContinueDebugEvent: - svc 0x64 - bx lr - .global svcGetProcessList .type svcGetProcessList, %function svcGetProcessList: @@ -355,24 +223,6 @@ svcGetProcessList: add sp, sp, #8 bx lr -.global svcReadProcessMemory -.type svcReadProcessMemory, %function -svcReadProcessMemory: - svc 0x6A - bx lr - -.global svcMapProcessMemory -.type svcMapProcessMemory, %function -svcMapProcessMemory: - svc 0x71 - bx lr - -.global svcUnmapProcessMemory -.type svcUnmapProcessMemory, %function -svcUnmapProcessMemory: - svc 0x72 - bx lr - .global svcQueryProcessMemory .type svcQueryProcessMemory, %function svcQueryProcessMemory: @@ -385,9 +235,3 @@ svcQueryProcessMemory: add sp, sp, #8 pop {r4-r6} bx lr - -.global svcGetProcessorID -.type svcGetProcessorID, %function -svcGetProcessorID: - svc 0x11 - bx lr