libdragon
rsp.h
Go to the documentation of this file.
1
155#ifndef __LIBDRAGON_RSP_H
156#define __LIBDRAGON_RSP_H
157
158#include <stdbool.h>
159#include <stdint.h>
160#include <stdlib.h>
161
162#ifdef __cplusplus
163extern "C" {
164#endif
165
167#define SP_DMEM ((volatile uint32_t*)0xA4000000)
168
170#define SP_IMEM ((volatile uint32_t*)0xA4001000)
171
173#define SP_PC ((volatile uint32_t*)0xA4080000)
174
176#define SP_STATUS ((volatile uint32_t*)0xA4040010)
177
179#define SP_DMA_FULL ((volatile uint32_t*)0xA4040014)
180
182#define SP_DMA_BUSY ((volatile uint32_t*)0xA4040018)
183
185#define SP_SEMAPHORE ((volatile uint32_t*)0xA404001C)
186
188#define SP_STATUS_HALTED (1 << 0)
190#define SP_STATUS_BROKE (1 << 1)
192#define SP_STATUS_DMA_BUSY (1 << 2)
194#define SP_STATUS_DMA_FULL (1 << 3)
196#define SP_STATUS_IO_BUSY (1 << 4)
198#define SP_STATUS_SSTEP (1 << 5)
200#define SP_STATUS_INTERRUPT_ON_BREAK (1 << 6)
202#define SP_STATUS_SIG0 (1 << 7)
204#define SP_STATUS_SIG1 (1 << 8)
206#define SP_STATUS_SIG2 (1 << 9)
208#define SP_STATUS_SIG3 (1 << 10)
210#define SP_STATUS_SIG4 (1 << 11)
212#define SP_STATUS_SIG5 (1 << 12)
214#define SP_STATUS_SIG6 (1 << 13)
216#define SP_STATUS_SIG7 (1 << 14)
217
218#define SP_WSTATUS_CLEAR_HALT 0x00001
219#define SP_WSTATUS_SET_HALT 0x00002
220#define SP_WSTATUS_CLEAR_BROKE 0x00004
221#define SP_WSTATUS_CLEAR_INTR 0x00008
222#define SP_WSTATUS_SET_INTR 0x00010
223#define SP_WSTATUS_CLEAR_SSTEP 0x00020
224#define SP_WSTATUS_SET_SSTEP 0x00040
225#define SP_WSTATUS_CLEAR_INTR_BREAK 0x00080
226#define SP_WSTATUS_SET_INTR_BREAK 0x00100
227#define SP_WSTATUS_CLEAR_SIG0 0x00200
228#define SP_WSTATUS_SET_SIG0 0x00400
229#define SP_WSTATUS_CLEAR_SIG1 0x00800
230#define SP_WSTATUS_SET_SIG1 0x01000
231#define SP_WSTATUS_CLEAR_SIG2 0x02000
232#define SP_WSTATUS_SET_SIG2 0x04000
233#define SP_WSTATUS_CLEAR_SIG3 0x08000
234#define SP_WSTATUS_SET_SIG3 0x10000
235#define SP_WSTATUS_CLEAR_SIG4 0x20000
236#define SP_WSTATUS_SET_SIG4 0x40000
237#define SP_WSTATUS_CLEAR_SIG5 0x80000
238#define SP_WSTATUS_SET_SIG5 0x100000
239#define SP_WSTATUS_CLEAR_SIG6 0x200000
240#define SP_WSTATUS_SET_SIG6 0x400000
241#define SP_WSTATUS_CLEAR_SIG7 0x800000
242#define SP_WSTATUS_SET_SIG7 0x1000000
243
249typedef struct {
250 uint32_t gpr[32];
251 uint16_t vpr[32][8];
252 uint16_t vaccum[3][8];
253 uint32_t cop0[16];
254 uint32_t cop2[3];
255 uint32_t pc;
256 uint8_t dmem[4096] __attribute__((aligned(8)));
257 uint8_t imem[4096] __attribute__((aligned(8)));
259
270typedef struct {
271 uint8_t *code;
272 void *code_end;
273 uint8_t *data;
274 void *data_end;
275
276 const char *name;
277 uint32_t start_pc;
278
291 void (*crash_handler)(rsp_snapshot_t *state);
292
311 void (*assert_handler)(rsp_snapshot_t *state, uint16_t assert_code);
313
335#define DEFINE_RSP_UCODE(ucode_name, ...) \
336 extern uint8_t ucode_name ## _text_start[]; \
337 extern uint8_t ucode_name ## _data_start[]; \
338 extern uint8_t ucode_name ## _text_end[0]; \
339 extern uint8_t ucode_name ## _data_end[0]; \
340 rsp_ucode_t ucode_name = (rsp_ucode_t){ \
341 .code = ucode_name ## _text_start, \
342 .data = ucode_name ## _data_start, \
343 .code_end = ucode_name ## _text_end, \
344 .data_end = ucode_name ## _data_end, \
345 .name = #ucode_name, .start_pc = 0, \
346 .crash_handler = 0, .assert_handler = 0, \
347 __VA_ARGS__ \
348 }
349
351void rsp_init(void);
352
366void rsp_load(rsp_ucode_t *ucode);
367
372void rsp_run(void);
373
379inline void rsp_run_async(void)
380{
381 extern void __rsp_run_async(uint32_t status_flags);
383}
384
391void rsp_wait(void);
392
407void rsp_load_code(void* code, unsigned long size, unsigned int imem_offset);
408
420void rsp_load_data(void* data, unsigned long size, unsigned int dmem_offset);
421
422
434void rsp_read_code(void* code, unsigned long size, unsigned int imem_offset);
435
447void rsp_read_data(void* data, unsigned long size, unsigned int dmem_offset);
448
472#ifndef NDEBUG
473#define rsp_crash() ({ \
474 __rsp_crash(__FILE__, __LINE__, __func__, NULL); \
475})
476#else
477#define rsp_crash() abort()
478#endif
479
495#ifndef NDEBUG
496#define rsp_crashf(msg, ...) ({ \
497 __rsp_crash(__FILE__, __LINE__, __func__, msg, ##__VA_ARGS__); \
498})
499#else
500#define rsp_crashf(msg, ...) abort()
501#endif
502
528#define RSP_WAIT_LOOP(timeout_ms) \
529 for (uint32_t __t = TICKS_READ() + TICKS_FROM_MS(timeout_ms); \
530 TICKS_BEFORE(TICKS_READ(), __t) || (rsp_crashf("wait loop timed out (%d ms)", timeout_ms), false); \
531 __rsp_check_assert(__FILE__, __LINE__, __func__))
532
533static inline __attribute__((deprecated("use rsp_load_code instead")))
534void load_ucode(void * start, unsigned long size) {
535 rsp_load_code(start, size, 0);
536}
537
538static inline __attribute__((deprecated("use rsp_read_code instead")))
539void read_ucode(void * start, unsigned long size) {
540 rsp_read_code(start, size, 0);
541}
542
543static inline __attribute__((deprecated("use rsp_load_data instead")))
544void load_data(void * start, unsigned long size) {
545 rsp_load_data(start, size, 0);
546}
547
548static inline __attribute__((deprecated("use rsp_read_data instead")))
549void read_data(void * start, unsigned long size) {
550 rsp_read_data(start, size, 0);
551}
552
553static inline __attribute__((deprecated("use rsp_run_async instead")))
554void run_ucode(void) {
556}
557
558// Internal function used by rsp_crash and rsp_crashf. These are not part
559// of the public API of rsp.h. Do not call them directly.
561#ifndef NDEBUG
562void __rsp_crash(const char *file, int line, const char *func, const char *msg, ...)
563 __attribute__((noreturn, format(printf, 4, 5)));
564void __rsp_check_assert(const char *file, int line, const char *func);
565#else
566static inline void __rsp_check_assert(const char *file, int line, const char *func) {}
567#endif
569
570#ifdef __cplusplus
571}
572#endif
573
574#endif
void __rsp_run_async(uint32_t status_flags)
Internal implementation of rsp_run_async.
Definition: rsp.c:148
void rsp_load_code(void *code, unsigned long size, unsigned int imem_offset)
Do a DMA transfer to load a piece of code into RSP IMEM.
Definition: rsp.c:64
uint32_t pc
Program counter.
Definition: rsp.h:255
void rsp_read_code(void *code, unsigned long size, unsigned int imem_offset)
Do a DMA transfer to load a piece of code from RSP IMEM to RDRAM.
Definition: rsp.c:106
void rsp_wait(void)
Wait until RSP has finished processing.
Definition: rsp.c:156
void rsp_run_async(void)
Run RSP async.
Definition: rsp.h:379
void rsp_run(void)
Run RSP ucode.
Definition: rsp.c:167
void rsp_load(rsp_ucode_t *ucode)
Load a RSP ucode.
Definition: rsp.c:56
void rsp_init(void)
Initialize the RSP subsytem.
Definition: rsp.c:47
void rsp_load_data(void *data, unsigned long size, unsigned int dmem_offset)
Do a DMA transfer to load a piece of data into RSP DMEM.
Definition: rsp.c:87
void rsp_read_data(void *data, unsigned long size, unsigned int dmem_offset)
Do a DMA transfer to load a piece of data from RSP DMEM to RDRAM.
Definition: rsp.c:127
#define SP_WSTATUS_SET_INTR_BREAK
SP_STATUS write mask: set SSTEP bit.
Definition: rsp.h:226
Snapshot of the register status of the RSP.
Definition: rsp.h:249
RSP ucode definition.
Definition: rsp.h:270
void * code_end
Pointer past the end of the code segment.
Definition: rsp.h:272
uint8_t * code
Pointer to the code segment.
Definition: rsp.h:271
const char * name
Name of the ucode.
Definition: rsp.h:276
void * data_end
Pointer past the end of the data segment.
Definition: rsp.h:274
uint32_t start_pc
Initial RSP PC.
Definition: rsp.h:277
uint8_t * data
Pointer to the data segment.
Definition: rsp.h:273