libdragon
Loading...
Searching...
No Matches
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_DMA_SPADDR ((volatile uint32_t*)0xA4040000)
178#define SP_DMA_RAMADDR ((volatile uint32_t*)0xA4040004)
180#define SP_DMA_RDLEN ((volatile uint32_t*)0xA4040008)
182#define SP_DMA_WRLEN ((volatile uint32_t*)0xA404000C)
183
185#define SP_STATUS ((volatile uint32_t*)0xA4040010)
186
188#define SP_DMA_FULL ((volatile uint32_t*)0xA4040014)
189
191#define SP_DMA_BUSY ((volatile uint32_t*)0xA4040018)
192
194#define SP_SEMAPHORE ((volatile uint32_t*)0xA404001C)
195
197#define SP_STATUS_HALTED (1 << 0)
199#define SP_STATUS_BROKE (1 << 1)
201#define SP_STATUS_DMA_BUSY (1 << 2)
203#define SP_STATUS_DMA_FULL (1 << 3)
205#define SP_STATUS_IO_BUSY (1 << 4)
207#define SP_STATUS_SSTEP (1 << 5)
209#define SP_STATUS_INTERRUPT_ON_BREAK (1 << 6)
211#define SP_STATUS_SIG0 (1 << 7)
213#define SP_STATUS_SIG1 (1 << 8)
215#define SP_STATUS_SIG2 (1 << 9)
217#define SP_STATUS_SIG3 (1 << 10)
219#define SP_STATUS_SIG4 (1 << 11)
221#define SP_STATUS_SIG5 (1 << 12)
223#define SP_STATUS_SIG6 (1 << 13)
225#define SP_STATUS_SIG7 (1 << 14)
226
227#define SP_WSTATUS_CLEAR_HALT 0x00001
228#define SP_WSTATUS_SET_HALT 0x00002
229#define SP_WSTATUS_CLEAR_BROKE 0x00004
230#define SP_WSTATUS_CLEAR_INTR 0x00008
231#define SP_WSTATUS_SET_INTR 0x00010
232#define SP_WSTATUS_CLEAR_SSTEP 0x00020
233#define SP_WSTATUS_SET_SSTEP 0x00040
234#define SP_WSTATUS_CLEAR_INTR_BREAK 0x00080
235#define SP_WSTATUS_SET_INTR_BREAK 0x00100
236#define SP_WSTATUS_CLEAR_SIG0 0x00200
237#define SP_WSTATUS_SET_SIG0 0x00400
238#define SP_WSTATUS_CLEAR_SIG1 0x00800
239#define SP_WSTATUS_SET_SIG1 0x01000
240#define SP_WSTATUS_CLEAR_SIG2 0x02000
241#define SP_WSTATUS_SET_SIG2 0x04000
242#define SP_WSTATUS_CLEAR_SIG3 0x08000
243#define SP_WSTATUS_SET_SIG3 0x10000
244#define SP_WSTATUS_CLEAR_SIG4 0x20000
245#define SP_WSTATUS_SET_SIG4 0x40000
246#define SP_WSTATUS_CLEAR_SIG5 0x80000
247#define SP_WSTATUS_SET_SIG5 0x100000
248#define SP_WSTATUS_CLEAR_SIG6 0x200000
249#define SP_WSTATUS_SET_SIG6 0x400000
250#define SP_WSTATUS_CLEAR_SIG7 0x800000
251#define SP_WSTATUS_SET_SIG7 0x1000000
252
258typedef struct {
259 uint32_t gpr[32];
260 uint16_t vpr[32][8];
261 uint16_t vaccum[3][8];
262 uint32_t cop0[16];
263 uint32_t cop2[3];
264 uint32_t pc;
265 uint8_t dmem[4096] __attribute__((aligned(8)));
266 uint8_t imem[4096] __attribute__((aligned(8)));
268
279typedef struct {
280 uint8_t *code;
281 void *code_end;
282 uint8_t *data;
283 void *data_end;
284
285 const char *name;
286 uint32_t start_pc;
287
300 void (*crash_handler)(rsp_snapshot_t *state);
301
320 void (*assert_handler)(rsp_snapshot_t *state, uint16_t assert_code);
322
344#define DEFINE_RSP_UCODE(ucode_name, ...) \
345 extern uint8_t ucode_name ## _text_start[]; \
346 extern uint8_t ucode_name ## _data_start[]; \
347 extern uint8_t ucode_name ## _text_end[0]; \
348 extern uint8_t ucode_name ## _data_end[0]; \
349 rsp_ucode_t ucode_name = (rsp_ucode_t){ \
350 .code = ucode_name ## _text_start, \
351 .data = ucode_name ## _data_start, \
352 .code_end = ucode_name ## _text_end, \
353 .data_end = ucode_name ## _data_end, \
354 .name = #ucode_name, .start_pc = 0, \
355 .crash_handler = 0, .assert_handler = 0, \
356 __VA_ARGS__ \
357 }
358
360void rsp_init(void);
361
375void rsp_load(rsp_ucode_t *ucode);
376
381void rsp_run(void);
382
388inline void rsp_run_async(void)
389{
390 extern void __rsp_run_async(uint32_t status_flags);
392}
393
400void rsp_wait(void);
401
416void rsp_load_code(void* code, unsigned long size, unsigned int imem_offset);
417
429void rsp_load_data(void* data, unsigned long size, unsigned int dmem_offset);
430
431
443void rsp_read_code(void* code, unsigned long size, unsigned int imem_offset);
444
456void rsp_read_data(void* data, unsigned long size, unsigned int dmem_offset);
457
481#ifndef NDEBUG
482#define rsp_crash() ({ \
483 __rsp_crash(__FILE__, __LINE__, __func__, NULL); \
484})
485#else
486#define rsp_crash() abort()
487#endif
488
504#ifndef NDEBUG
505#define rsp_crashf(msg, ...) ({ \
506 __rsp_crash(__FILE__, __LINE__, __func__, msg, ##__VA_ARGS__); \
507})
508#else
509#define rsp_crashf(msg, ...) abort()
510#endif
511
537#define RSP_WAIT_LOOP(timeout_ms) \
538 for (uint32_t __t = TICKS_READ() + TICKS_FROM_MS(timeout_ms); \
539 TICKS_BEFORE(TICKS_READ(), __t) || (rsp_crashf("wait loop timed out (%d ms)", timeout_ms), false); \
540 __rsp_check_assert(__FILE__, __LINE__, __func__))
541
542static inline __attribute__((deprecated("use rsp_load_code instead")))
543void load_ucode(void * start, unsigned long size) {
544 rsp_load_code(start, size, 0);
545}
546
547static inline __attribute__((deprecated("use rsp_read_code instead")))
548void read_ucode(void * start, unsigned long size) {
549 rsp_read_code(start, size, 0);
550}
551
552static inline __attribute__((deprecated("use rsp_load_data instead")))
553void load_data(void * start, unsigned long size) {
554 rsp_load_data(start, size, 0);
555}
556
557static inline __attribute__((deprecated("use rsp_read_data instead")))
558void read_data(void * start, unsigned long size) {
559 rsp_read_data(start, size, 0);
560}
561
562static inline __attribute__((deprecated("use rsp_run_async instead")))
563void run_ucode(void) {
565}
566
567// Internal function used by rsp_crash and rsp_crashf. These are not part
568// of the public API of rsp.h. Do not call them directly.
570#ifndef NDEBUG
571void __rsp_crash(const char *file, int line, const char *func, const char *msg, ...)
572 __attribute__((noreturn, format(printf, 4, 5)));
573void __rsp_check_assert(const char *file, int line, const char *func);
574#else
575static inline void __rsp_check_assert(const char *file, int line, const char *func) {}
576#endif
578
579#ifdef __cplusplus
580}
581#endif
582
583#endif
void __rsp_run_async(uint32_t status_flags)
Internal implementation of rsp_run_async.
Definition rsp.c:150
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:66
uint32_t pc
Program counter.
Definition rsp.h:264
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:108
void rsp_wait(void)
Wait until RSP has finished processing.
Definition rsp.c:158
void rsp_run_async(void)
Run RSP async.
Definition rsp.h:388
void rsp_run(void)
Run RSP ucode.
Definition rsp.c:169
void rsp_load(rsp_ucode_t *ucode)
Load a RSP ucode.
Definition rsp.c:58
void rsp_init(void)
Initialize the RSP subsytem.
Definition rsp.c:49
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:89
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:129
#define SP_WSTATUS_SET_INTR_BREAK
SP_STATUS write mask: set SSTEP bit.
Definition rsp.h:235
Snapshot of the register status of the RSP.
Definition rsp.h:258
RSP ucode definition.
Definition rsp.h:279
void * code_end
Pointer past the end of the code segment.
Definition rsp.h:281
uint8_t * code
Pointer to the code segment.
Definition rsp.h:280
const char * name
Name of the ucode.
Definition rsp.h:285
void * data_end
Pointer past the end of the data segment.
Definition rsp.h:283
uint32_t start_pc
Initial RSP PC.
Definition rsp.h:286
uint8_t * data
Pointer to the data segment.
Definition rsp.h:282