libdragon
Loading...
Searching...
No Matches
rsp.h
Go to the documentation of this file.
1
158#ifndef __LIBDRAGON_RSP_H
159#define __LIBDRAGON_RSP_H
160
161#include <stdbool.h>
162#include <stdint.h>
163#include <stdlib.h>
164
165#ifdef __cplusplus
166extern "C" {
167#endif
168
170#define SP_DMEM ((volatile uint32_t*)0xA4000000)
171
173#define SP_IMEM ((volatile uint32_t*)0xA4001000)
174
176#define SP_PC ((volatile uint32_t*)0xA4080000)
177
179#define SP_DMA_SPADDR ((volatile uint32_t*)0xA4040000)
181#define SP_DMA_RAMADDR ((volatile uint32_t*)0xA4040004)
183#define SP_DMA_RDLEN ((volatile uint32_t*)0xA4040008)
185#define SP_DMA_WRLEN ((volatile uint32_t*)0xA404000C)
186
188#define SP_STATUS ((volatile uint32_t*)0xA4040010)
189
191#define SP_DMA_FULL ((volatile uint32_t*)0xA4040014)
192
194#define SP_DMA_BUSY ((volatile uint32_t*)0xA4040018)
195
197#define SP_SEMAPHORE ((volatile uint32_t*)0xA404001C)
198
200#define SP_STATUS_HALTED (1 << 0)
202#define SP_STATUS_BROKE (1 << 1)
204#define SP_STATUS_DMA_BUSY (1 << 2)
206#define SP_STATUS_DMA_FULL (1 << 3)
208#define SP_STATUS_IO_BUSY (1 << 4)
210#define SP_STATUS_SSTEP (1 << 5)
212#define SP_STATUS_INTERRUPT_ON_BREAK (1 << 6)
214#define SP_STATUS_SIG0 (1 << 7)
216#define SP_STATUS_SIG1 (1 << 8)
218#define SP_STATUS_SIG2 (1 << 9)
220#define SP_STATUS_SIG3 (1 << 10)
222#define SP_STATUS_SIG4 (1 << 11)
224#define SP_STATUS_SIG5 (1 << 12)
226#define SP_STATUS_SIG6 (1 << 13)
228#define SP_STATUS_SIG7 (1 << 14)
229
230#define SP_WSTATUS_CLEAR_HALT 0x00001
231#define SP_WSTATUS_SET_HALT 0x00002
232#define SP_WSTATUS_CLEAR_BROKE 0x00004
233#define SP_WSTATUS_CLEAR_INTR 0x00008
234#define SP_WSTATUS_SET_INTR 0x00010
235#define SP_WSTATUS_CLEAR_SSTEP 0x00020
236#define SP_WSTATUS_SET_SSTEP 0x00040
237#define SP_WSTATUS_CLEAR_INTR_BREAK 0x00080
238#define SP_WSTATUS_SET_INTR_BREAK 0x00100
239#define SP_WSTATUS_CLEAR_SIG0 0x00200
240#define SP_WSTATUS_SET_SIG0 0x00400
241#define SP_WSTATUS_CLEAR_SIG1 0x00800
242#define SP_WSTATUS_SET_SIG1 0x01000
243#define SP_WSTATUS_CLEAR_SIG2 0x02000
244#define SP_WSTATUS_SET_SIG2 0x04000
245#define SP_WSTATUS_CLEAR_SIG3 0x08000
246#define SP_WSTATUS_SET_SIG3 0x10000
247#define SP_WSTATUS_CLEAR_SIG4 0x20000
248#define SP_WSTATUS_SET_SIG4 0x40000
249#define SP_WSTATUS_CLEAR_SIG5 0x80000
250#define SP_WSTATUS_SET_SIG5 0x100000
251#define SP_WSTATUS_CLEAR_SIG6 0x200000
252#define SP_WSTATUS_SET_SIG6 0x400000
253#define SP_WSTATUS_CLEAR_SIG7 0x800000
254#define SP_WSTATUS_SET_SIG7 0x1000000
255
261typedef struct {
262 uint32_t gpr[32];
263 uint16_t vpr[32][8];
264 uint16_t vaccum[3][8];
265 uint32_t cop0[16];
266 uint32_t cop2[3];
267 uint32_t pc;
268 uint8_t dmem[4096] __attribute__((aligned(8)));
269 uint8_t imem[4096] __attribute__((aligned(8)));
271
282typedef struct {
283 uint8_t *code;
284 void *code_end;
285 uint8_t *data;
286 void *data_end;
287
288 const char *name;
289 uint32_t start_pc;
290
303 void (*crash_handler)(rsp_snapshot_t *state);
304
323 void (*assert_handler)(rsp_snapshot_t *state, uint16_t assert_code);
325
347#define DEFINE_RSP_UCODE(ucode_name, ...) \
348 extern uint8_t ucode_name ## _text_start[]; \
349 extern uint8_t ucode_name ## _data_start[]; \
350 extern uint8_t ucode_name ## _text_end[0]; \
351 extern uint8_t ucode_name ## _data_end[0]; \
352 rsp_ucode_t ucode_name = (rsp_ucode_t){ \
353 .code = ucode_name ## _text_start, \
354 .data = ucode_name ## _data_start, \
355 .code_end = ucode_name ## _text_end, \
356 .data_end = ucode_name ## _data_end, \
357 .name = #ucode_name, .start_pc = 0, \
358 .crash_handler = 0, .assert_handler = 0, \
359 __VA_ARGS__ \
360 }
361
363void rsp_init(void);
364
378void rsp_load(rsp_ucode_t *ucode);
379
384void rsp_run(void);
385
391inline void rsp_run_async(void)
392{
393 extern void __rsp_run_async(uint32_t status_flags);
395}
396
403void rsp_wait(void);
404
419void rsp_load_code(void* code, unsigned long size, unsigned int imem_offset);
420
432void rsp_load_data(void* data, unsigned long size, unsigned int dmem_offset);
433
434
446void rsp_read_code(void* code, unsigned long size, unsigned int imem_offset);
447
459void rsp_read_data(void* data, unsigned long size, unsigned int dmem_offset);
460
484#ifndef NDEBUG
485#define rsp_crash() ({ \
486 __rsp_crash(__FILE__, __LINE__, __func__, NULL); \
487})
488#else
489#define rsp_crash() abort()
490#endif
491
507#ifndef NDEBUG
508#define rsp_crashf(msg, ...) ({ \
509 __rsp_crash(__FILE__, __LINE__, __func__, msg, ##__VA_ARGS__); \
510})
511#else
512#define rsp_crashf(msg, ...) abort()
513#endif
514
540#define RSP_WAIT_LOOP(timeout_ms) \
541 for (uint32_t __t = TICKS_READ() + TICKS_FROM_MS(timeout_ms); \
542 TICKS_BEFORE(TICKS_READ(), __t) || (rsp_crashf("wait loop timed out (%d ms)", timeout_ms), false); \
543 __rsp_check_assert(__FILE__, __LINE__, __func__))
544
545static inline __attribute__((deprecated("use rsp_load_code instead")))
546void load_ucode(void * start, unsigned long size) {
547 rsp_load_code(start, size, 0);
548}
549
550static inline __attribute__((deprecated("use rsp_read_code instead")))
551void read_ucode(void * start, unsigned long size) {
552 rsp_read_code(start, size, 0);
553}
554
555static inline __attribute__((deprecated("use rsp_load_data instead")))
556void load_data(void * start, unsigned long size) {
557 rsp_load_data(start, size, 0);
558}
559
560static inline __attribute__((deprecated("use rsp_read_data instead")))
561void read_data(void * start, unsigned long size) {
562 rsp_read_data(start, size, 0);
563}
564
565static inline __attribute__((deprecated("use rsp_run_async instead")))
566void run_ucode(void) {
568}
569
570// Internal function used by rsp_crash and rsp_crashf. These are not part
571// of the public API of rsp.h. Do not call them directly.
573#ifndef NDEBUG
574void __rsp_crash(const char *file, int line, const char *func, const char *msg, ...)
575 __attribute__((noreturn, format(printf, 4, 5)));
576void __rsp_check_assert(const char *file, int line, const char *func);
577#else
578static inline void __rsp_check_assert(const char *file, int line, const char *func) {}
579#endif
581
582#ifdef __cplusplus
583}
584#endif
585
586#endif
void __rsp_run_async(uint32_t status_flags)
Internal implementation of rsp_run_async.
Definition rsp.c:152
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:68
uint32_t pc
Program counter.
Definition rsp.h:267
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:110
void rsp_wait(void)
Wait until RSP has finished processing.
Definition rsp.c:160
void rsp_run_async(void)
Run RSP async.
Definition rsp.h:391
void rsp_run(void)
Run RSP ucode.
Definition rsp.c:171
void rsp_load(rsp_ucode_t *ucode)
Load a RSP ucode.
Definition rsp.c:60
void rsp_init(void)
Initialize the RSP subsytem.
Definition rsp.c:51
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:91
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:131
#define SP_WSTATUS_SET_INTR_BREAK
SP_STATUS write mask: set SP_STATUS_INTERRUPT_ON_BREAK bit.
Definition rsp.h:238
Snapshot of the register status of the RSP.
Definition rsp.h:261
RSP ucode definition.
Definition rsp.h:282
void * code_end
Pointer past the end of the code segment.
Definition rsp.h:284
uint8_t * code
Pointer to the code segment.
Definition rsp.h:283
const char * name
Name of the ucode.
Definition rsp.h:288
void * data_end
Pointer past the end of the data segment.
Definition rsp.h:286
uint32_t start_pc
Initial RSP PC.
Definition rsp.h:289
uint8_t * data
Pointer to the data segment.
Definition rsp.h:285