Nugget
Bare-metal libraries and examples for the original PlayStation
Loading...
Searching...
No Matches
kernel.hh
Go to the documentation of this file.
1/*
2
3MIT License
4
5Copyright (c) 2022 PCSX-Redux authors
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26
27#pragma once
28
29#include <EASTL/functional.h>
30#include <stdint.h>
31
32#include <source_location>
33
34namespace psyqo {
35
36namespace DMA {
37
42
43}
44
45class Application;
46
56namespace Kernel {
57
58#ifdef PSYQO_RELEASE
59static constexpr bool debugMode = false;
60#else
61static constexpr bool debugMode = true;
62#endif
63
64namespace Internal {
65static inline uint32_t getCop0Status() {
66#ifndef PS1_PC_PORT
67 uint32_t r;
68 asm("mfc0 %0, $12 ; nop" : "=r"(r));
69 return r;
70#else
71 return 0;
72#endif
73}
74
75static inline void setCop0Status(uint32_t r) {
76#ifndef PS1_PC_PORT
77 asm("mtc0 %0, $12 ; nop" : : "r"(r));
78#endif
79}
80
81[[noreturn]] void abort(const char* msg, std::source_location location = std::source_location::current());
82[[noreturn]] void abort();
83
84} // namespace Internal
85
92static inline void fastEnterCriticalSection() {
93#ifndef PS1_PC_PORT
94 asm volatile("mtc0 %0, $12 ; nop ; nop" : : "r"(0x40000000));
95#endif
96}
97
103static inline void fastLeaveCriticalSection() {
104#ifndef PS1_PC_PORT
105 asm volatile("mtc0 %0, $12" : : "r"(0x40000401));
106#endif
107}
108
117template <typename T>
118static void waitForStatus(T mask, T expected, const volatile T* value) {
119 while ((*value & mask) != expected);
120}
121
122enum class DMA : unsigned {
123 MDECin,
124 MDECout,
125 GPU,
126 CDRom,
127 SPU,
128 EXP1,
129 OTC,
130 Max,
131};
132
133enum class IRQ : unsigned {
134 VBlank,
135 GPU,
136 CDRom,
137 DMA,
138 Timer0,
139 Timer1,
140 Timer2,
142 SIO,
143 SPU,
144 PIO,
145 Max,
146};
147
151[[noreturn]] static inline void abort(const char* msg,
152 std::source_location location = std::source_location::current()) {
153 if constexpr (debugMode) {
154 Internal::abort(msg, location);
155 } else if constexpr (!debugMode) {
156 (void)msg;
157 (void)location;
159 }
160}
161
193void takeOverKernel();
194
198bool isKernelTakenOver();
199
217
235void queueIRQHandler(IRQ irq, eastl::function<void()>&& lambda);
236
246uint32_t openEvent(uint32_t classId, uint32_t spec, uint32_t mode, eastl::function<void()>&& lambda);
247
261unsigned registerDmaEvent(DMA channel, eastl::function<void()>&& lambda);
262
270
277void enableDma(DMA channel, unsigned priority = 7);
278
284void disableDma(DMA channel);
285
291void unregisterDmaEvent(unsigned slot);
292
303void queueCallback(eastl::function<void()>&& lambda);
304
314void queueCallbackFromISR(eastl::function<void()>&& lambda);
315
336void setBreakHandler(unsigned category, eastl::function<bool(uint32_t)>&& handler);
337
343void queuePsyqoBreakHandler(eastl::function<bool(uint32_t)>&& handler);
344
345namespace Internal {
346void pumpCallbacks();
347void prepare(Application&);
348void addInitializer(eastl::function<void(Application&)>&& lambda);
349void addOnFrame(eastl::function<void()>&& lambda);
350void beginFrame();
351[[noreturn]] void crashHandler(uint32_t exceptionCode, uint32_t* kernelRegisters);
352} // namespace Internal
353
357inline void assert(bool condition, const char* message,
358 std::source_location location = std::source_location::current()) {
359 if constexpr (debugMode) {
360 if (!condition) {
361 Internal::abort(message, location);
363 }
364 } else if constexpr (!debugMode) {
365 (void)message;
366 (void)location;
367 if (!condition) {
370 }
371 }
372}
373
374} // namespace Kernel
375
376} // namespace psyqo
The application class.
Definition application.hh:49
uint32_t r
Definition cpu.c:222
IRQ
Definition irq.h:31
DmaCallback
Definition kernel.hh:38
@ FROM_MAIN_LOOP
Definition kernel.hh:40
@ FROM_ISR
Definition kernel.hh:39
void pumpCallbacks()
Definition kernel.cpp:407
void prepare(Application &)
Definition kernel.cpp:319
void crashHandler(uint32_t exceptionCode, uint32_t *kernelRegisters)
Definition crash-handler.cpp:145
void addOnFrame(eastl::function< void()> &&lambda)
Definition kernel.cpp:427
void beginFrame()
Definition kernel.cpp:431
void addInitializer(eastl::function< void(Application &)> &&lambda)
Definition kernel.cpp:285
void abort()
Definition kernel.cpp:202
uint32_t openEvent(uint32_t classId, uint32_t spec, uint32_t mode, eastl::function< void()> &&lambda)
A C++ wrapper around the openEvent syscall.
Definition kernel.cpp:209
void queueCallbackFromISR(eastl::function< void()> &&lambda)
Queues a callback to be called from the main thead.
Definition kernel.cpp:401
void assert(bool condition, const char *message, std::source_location location=std::source_location::current())
A simple assert macro.
Definition kernel.hh:357
unsigned registerDmaEvent(DMA channel, eastl::function< void()> &&lambda)
Sets an ISR callback for a given DMA channel.
Definition kernel.cpp:218
DMA
Definition kernel.hh:122
void queuePsyqoBreakHandler(eastl::function< bool(uint32_t)> &&handler)
Queues a break handler for psyqo's reserved category.
Definition kernel.cpp:111
void disableDma(DMA channel)
Disables the given DMA channel.
Definition kernel.cpp:254
void installCrashHandler()
Installs a crash handler for the application.
Definition kernel.cpp:173
void setBreakHandler(unsigned category, eastl::function< bool(uint32_t)> &&handler)
Sets a break handler for a given category.
Definition kernel.cpp:105
void flushCache()
Flushes the i-cache.
IRQ
Definition kernel.hh:133
void queueCallback(eastl::function< void()> &&lambda)
Queues a callback to be called from the main thead.
Definition kernel.cpp:394
void unregisterDmaEvent(unsigned slot)
Frees the given DMA callback slot.
Definition kernel.cpp:267
bool isKernelTakenOver()
Returns whether the kernel has been taken over.
Definition kernel.cpp:115
void enableDma(DMA channel, unsigned priority=7)
Enables the given DMA channel.
Definition kernel.cpp:236
void queueIRQHandler(IRQ irq, eastl::function< void()> &&lambda)
Queues an IRQ handler to be called from the exception handler.
Definition kernel.cpp:185
void takeOverKernel()
Takes over the kernel. Can only be called once inside the main function.
Definition kernel.cpp:140
Definition lua.hh:38
static int value
Definition syscalls.h:535
__builtin_unreachable()
static uint32_t spec
Definition syscalls.h:364
static uint32_t uint32_t void(* handler)())
Definition syscalls.h:371
void void(ptr, size)
static void uint32_t mode
Definition syscalls.h:231
void uint32_t(classId, spec)