mirror of https://github.com/zeldaret/mm.git
Handwritten asm: exceptasm, get/setintmask (#1819)
* Handwritten asm: exceptasm, get/setintmask * Fix maybe * Update warnings * Remove .global from jlabel * Move os_internal_rsp inclusion to os.h * Make HWINT_* defins consistent
This commit is contained in:
parent
a0c992ea35
commit
b1a50c2d1b
|
|
@ -10,6 +10,7 @@
|
|||
#include "os_host.h"
|
||||
#include "os_internal_error.h"
|
||||
#include "os_internal_reg.h"
|
||||
#include "os_internal_rsp.h"
|
||||
#include "os_internal_si.h"
|
||||
#include "os_internal.h"
|
||||
#include "os_libc.h"
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
#ifndef PR_OS_EXCEPTION_H
|
||||
#define PR_OS_EXCEPTION_H
|
||||
|
||||
#include "ultratypes.h"
|
||||
|
||||
|
||||
typedef u32 OSIntMask;
|
||||
typedef u32 OSHWIntr;
|
||||
|
||||
/* Flags for debugging purpose */
|
||||
|
||||
#define OS_FLAG_CPU_BREAK 1 /* Break exception has occurred */
|
||||
|
|
@ -34,6 +28,15 @@ typedef u32 OSHWIntr;
|
|||
#define RCP_IMASK 0x003F0000
|
||||
#define RCP_IMASKSHIFT 16
|
||||
|
||||
/* OSHWIntr values */
|
||||
#define OS_INTR_CART 1
|
||||
|
||||
#ifdef _LANGUAGE_C
|
||||
|
||||
#include "ultratypes.h"
|
||||
|
||||
typedef u32 OSIntMask;
|
||||
typedef u32 OSHWIntr;
|
||||
|
||||
OSIntMask osGetIntMask(void);
|
||||
OSIntMask osSetIntMask(OSIntMask im);
|
||||
|
|
@ -45,5 +48,6 @@ void __osGetHWIntrRoutine(OSHWIntr interrupt, s32 (**handler)(void), void** stac
|
|||
void __osSetGlobalIntMask(OSHWIntr mask);
|
||||
void __osResetGlobalIntMask(OSHWIntr mask);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,14 +1,24 @@
|
|||
#ifndef PR_OS_INTERNAL_H
|
||||
#define PR_OS_INTERNAL_H
|
||||
|
||||
#ifdef _LANGUAGE_C
|
||||
|
||||
#include "ultratypes.h"
|
||||
#include "os_message.h"
|
||||
#include "os_pi.h"
|
||||
#include "os_internal_rsp.h"
|
||||
|
||||
typedef struct __osHwInt {
|
||||
/* 0x0 */ s32 (*handler)(void);
|
||||
/* 0x4 */ void* stackEnd;
|
||||
} __osHwInt; // size = 0x8
|
||||
|
||||
#else
|
||||
|
||||
/* __osHwInt struct member offsets */
|
||||
#define HWINT_CALLBACK 0x0
|
||||
#define HWINT_SP 0x4
|
||||
|
||||
/* __osHwInt struct size */
|
||||
#define HWINT_SIZE 0x8
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,20 +1,6 @@
|
|||
#ifndef PR_OS_MESSAGE_H
|
||||
#define PR_OS_MESSAGE_H
|
||||
|
||||
#include "os_thread.h"
|
||||
|
||||
typedef void* OSMesg;
|
||||
typedef u32 OSEvent;
|
||||
|
||||
typedef struct OSMesgQueue {
|
||||
/* 0x00 */ OSThread* mtQueue;
|
||||
/* 0x04 */ OSThread* fullQueue;
|
||||
/* 0x08 */ s32 validCount;
|
||||
/* 0x0C */ s32 first;
|
||||
/* 0x10 */ s32 msgCount;
|
||||
/* 0x14 */ OSMesg* msg;
|
||||
} OSMesgQueue; // size = 0x18
|
||||
|
||||
#define OS_NUM_EVENTS 15
|
||||
|
||||
#define OS_EVENT_SW1 0 /* CPU SW1 interrupt */
|
||||
|
|
@ -45,6 +31,22 @@ typedef struct OSMesgQueue {
|
|||
#define OS_MESG_NOBLOCK 0
|
||||
#define OS_MESG_BLOCK 1
|
||||
|
||||
#ifdef _LANGUAGE_C
|
||||
|
||||
#include "os_thread.h"
|
||||
|
||||
typedef void* OSMesg;
|
||||
typedef u32 OSEvent;
|
||||
|
||||
typedef struct OSMesgQueue {
|
||||
/* 0x00 */ OSThread* mtQueue;
|
||||
/* 0x04 */ OSThread* fullQueue;
|
||||
/* 0x08 */ s32 validCount;
|
||||
/* 0x0C */ s32 first;
|
||||
/* 0x10 */ s32 msgCount;
|
||||
/* 0x14 */ OSMesg* msg;
|
||||
} OSMesgQueue; // size = 0x18
|
||||
|
||||
#define MQ_GET_COUNT(mq) ((mq)->validCount)
|
||||
|
||||
#define MQ_IS_EMPTY(mq) (MQ_GET_COUNT(mq) == 0)
|
||||
|
|
@ -57,5 +59,17 @@ s32 osRecvMesg(OSMesgQueue* mq, OSMesg* msg, s32 flags);
|
|||
|
||||
void osSetEventMesg(OSEvent e, OSMesgQueue* mq, OSMesg m);
|
||||
|
||||
#else
|
||||
|
||||
/* OSMesgQueue struct member offsets */
|
||||
|
||||
#define MQ_MTQUEUE 0x00
|
||||
#define MQ_FULLQUEUE 0x04
|
||||
#define MQ_VALIDCOUNT 0x08
|
||||
#define MQ_FIRST 0x0C
|
||||
#define MQ_MSGCOUNT 0x10
|
||||
#define MQ_MSG 0x14
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,11 +1,35 @@
|
|||
#ifndef PR_OS_THREAD_H
|
||||
#define PR_OS_THREAD_H
|
||||
|
||||
#include "ultratypes.h"
|
||||
#define OS_STATE_STOPPED (1 << 0)
|
||||
#define OS_STATE_RUNNABLE (1 << 1)
|
||||
#define OS_STATE_RUNNING (1 << 2)
|
||||
#define OS_STATE_WAITING (1 << 3)
|
||||
|
||||
#define OS_PRIORITY_IDLE 0
|
||||
#define OS_PRIORITY_MAIN 10
|
||||
#define OS_PRIORITY_GRAPH 11
|
||||
#define OS_PRIORITY_AUDIOMGR 12
|
||||
#define OS_PRIORITY_PADMGR 14
|
||||
#define OS_PRIORITY_SCHED 15
|
||||
#define OS_PRIORITY_DMAMGR 16
|
||||
#define OS_PRIORITY_IRQMGR 17
|
||||
#define OS_PRIORITY_PIMGR 150
|
||||
#define OS_PRIORITY_FAULTCLIENT 126
|
||||
#define OS_PRIORITY_FAULT 127
|
||||
#define OS_PRIORITY_APPMAX 127
|
||||
#define OS_PRIORITY_RMONSPIN 200
|
||||
#define OS_PRIORITY_RMON 250
|
||||
#define OS_PRIORITY_VIMGR 254
|
||||
#define OS_PRIORITY_MAX 255
|
||||
|
||||
#define OS_FLAG_CPU_BREAK 1
|
||||
#define OS_FLAG_FAULT 2
|
||||
|
||||
#ifdef _LANGUAGE_C
|
||||
|
||||
#include "ultratypes.h"
|
||||
|
||||
typedef s32 OSPri;
|
||||
typedef s32 OSId;
|
||||
|
||||
|
|
@ -47,29 +71,6 @@ typedef struct OSThread {
|
|||
/* 0x20 */ __OSThreadContext context;
|
||||
} OSThread; // size = 0x1B0
|
||||
|
||||
#define OS_STATE_STOPPED (1 << 0)
|
||||
#define OS_STATE_RUNNABLE (1 << 1)
|
||||
#define OS_STATE_RUNNING (1 << 2)
|
||||
#define OS_STATE_WAITING (1 << 3)
|
||||
|
||||
|
||||
#define OS_PRIORITY_IDLE 0
|
||||
#define OS_PRIORITY_MAIN 10
|
||||
#define OS_PRIORITY_GRAPH 11
|
||||
#define OS_PRIORITY_AUDIOMGR 12
|
||||
#define OS_PRIORITY_PADMGR 14
|
||||
#define OS_PRIORITY_SCHED 15
|
||||
#define OS_PRIORITY_DMAMGR 16
|
||||
#define OS_PRIORITY_IRQMGR 17
|
||||
#define OS_PRIORITY_PIMGR 150
|
||||
#define OS_PRIORITY_FAULTCLIENT 126
|
||||
#define OS_PRIORITY_FAULT 127
|
||||
#define OS_PRIORITY_APPMAX 127
|
||||
#define OS_PRIORITY_RMONSPIN 200
|
||||
#define OS_PRIORITY_RMON 250
|
||||
#define OS_PRIORITY_VIMGR 254
|
||||
#define OS_PRIORITY_MAX 255
|
||||
|
||||
void osCreateThread(OSThread* thread, OSId id, void* entry, void* arg, void* sp, OSPri p);
|
||||
void osDestroyThread(OSThread* t);
|
||||
void osYieldThread(void);
|
||||
|
|
@ -82,4 +83,74 @@ OSPri osGetThreadPri(OSThread* t);
|
|||
// internal
|
||||
OSThread* __osGetActiveQueue(void);
|
||||
|
||||
#else
|
||||
|
||||
/* OSThread struct member offsets */
|
||||
|
||||
#define THREAD_NEXT 0x00
|
||||
#define THREAD_PRI 0x04
|
||||
#define THREAD_QUEUE 0x08
|
||||
#define THREAD_TLNEXT 0x0C
|
||||
#define THREAD_STATE 0x10
|
||||
#define THREAD_FLAGS 0x12
|
||||
#define THREAD_ID 0x14
|
||||
#define THREAD_FP 0x18
|
||||
#define THREAD_PROFILE 0x1C
|
||||
#define THREAD_CONTEXT 0x20
|
||||
#define THREAD_AT (THREAD_CONTEXT + 0x000)
|
||||
#define THREAD_V0 (THREAD_CONTEXT + 0x008)
|
||||
#define THREAD_V1 (THREAD_CONTEXT + 0x010)
|
||||
#define THREAD_A0 (THREAD_CONTEXT + 0x018)
|
||||
#define THREAD_A1 (THREAD_CONTEXT + 0x020)
|
||||
#define THREAD_A2 (THREAD_CONTEXT + 0x028)
|
||||
#define THREAD_A3 (THREAD_CONTEXT + 0x030)
|
||||
#define THREAD_T0 (THREAD_CONTEXT + 0x038)
|
||||
#define THREAD_T1 (THREAD_CONTEXT + 0x040)
|
||||
#define THREAD_T2 (THREAD_CONTEXT + 0x048)
|
||||
#define THREAD_T3 (THREAD_CONTEXT + 0x050)
|
||||
#define THREAD_T4 (THREAD_CONTEXT + 0x058)
|
||||
#define THREAD_T5 (THREAD_CONTEXT + 0x060)
|
||||
#define THREAD_T6 (THREAD_CONTEXT + 0x068)
|
||||
#define THREAD_T7 (THREAD_CONTEXT + 0x070)
|
||||
#define THREAD_S0 (THREAD_CONTEXT + 0x078)
|
||||
#define THREAD_S1 (THREAD_CONTEXT + 0x080)
|
||||
#define THREAD_S2 (THREAD_CONTEXT + 0x088)
|
||||
#define THREAD_S3 (THREAD_CONTEXT + 0x090)
|
||||
#define THREAD_S4 (THREAD_CONTEXT + 0x098)
|
||||
#define THREAD_S5 (THREAD_CONTEXT + 0x0A0)
|
||||
#define THREAD_S6 (THREAD_CONTEXT + 0x0A8)
|
||||
#define THREAD_S7 (THREAD_CONTEXT + 0x0B0)
|
||||
#define THREAD_T8 (THREAD_CONTEXT + 0x0B8)
|
||||
#define THREAD_T9 (THREAD_CONTEXT + 0x0C0)
|
||||
#define THREAD_GP (THREAD_CONTEXT + 0x0C8)
|
||||
#define THREAD_SP (THREAD_CONTEXT + 0x0D0)
|
||||
#define THREAD_S8 (THREAD_CONTEXT + 0x0D8)
|
||||
#define THREAD_RA (THREAD_CONTEXT + 0x0E0)
|
||||
#define THREAD_LO (THREAD_CONTEXT + 0x0E8)
|
||||
#define THREAD_HI (THREAD_CONTEXT + 0x0F0)
|
||||
#define THREAD_SR (THREAD_CONTEXT + 0x0F8)
|
||||
#define THREAD_PC (THREAD_CONTEXT + 0x0FC)
|
||||
#define THREAD_CAUSE (THREAD_CONTEXT + 0x100)
|
||||
#define THREAD_BADVADDR (THREAD_CONTEXT + 0x104)
|
||||
#define THREAD_RCP (THREAD_CONTEXT + 0x108)
|
||||
#define THREAD_FPCSR (THREAD_CONTEXT + 0x10C)
|
||||
#define THREAD_FP0 (THREAD_CONTEXT + 0x110)
|
||||
#define THREAD_FP2 (THREAD_CONTEXT + 0x118)
|
||||
#define THREAD_FP4 (THREAD_CONTEXT + 0x120)
|
||||
#define THREAD_FP6 (THREAD_CONTEXT + 0x128)
|
||||
#define THREAD_FP8 (THREAD_CONTEXT + 0x130)
|
||||
#define THREAD_FP10 (THREAD_CONTEXT + 0x138)
|
||||
#define THREAD_FP12 (THREAD_CONTEXT + 0x140)
|
||||
#define THREAD_FP14 (THREAD_CONTEXT + 0x148)
|
||||
#define THREAD_FP16 (THREAD_CONTEXT + 0x150)
|
||||
#define THREAD_FP18 (THREAD_CONTEXT + 0x158)
|
||||
#define THREAD_FP20 (THREAD_CONTEXT + 0x160)
|
||||
#define THREAD_FP22 (THREAD_CONTEXT + 0x168)
|
||||
#define THREAD_FP24 (THREAD_CONTEXT + 0x170)
|
||||
#define THREAD_FP26 (THREAD_CONTEXT + 0x178)
|
||||
#define THREAD_FP28 (THREAD_CONTEXT + 0x180)
|
||||
#define THREAD_FP30 (THREAD_CONTEXT + 0x188)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
850
include/PR/rcp.h
850
include/PR/rcp.h
|
|
@ -1,10 +1,90 @@
|
|||
#ifndef PR_RCP_H
|
||||
#define PR_RCP_H
|
||||
|
||||
#include "R4300.h"
|
||||
#include "ultratypes.h"
|
||||
|
||||
/**
|
||||
* RCP memory map overview:
|
||||
*
|
||||
* 0x0000_0000 .. 0x03EF_FFFF RDRAM memory
|
||||
* 0x03F0_0000 .. 0x03FF_FFFF RDRAM registers
|
||||
*
|
||||
* 0x0400_0000 .. 0x0400_2000 SP memory
|
||||
* 0x0404_0000 .. 0x040F_FFFF SP registers
|
||||
* 0x0410_0000 .. 0x041F_FFFF DP command registers
|
||||
* 0x0420_0000 .. 0x042F_FFFF DP span registers
|
||||
* 0x0430_0000 .. 0x043F_FFFF MI registers
|
||||
* 0x0440_0000 .. 0x044F_FFFF VI registers
|
||||
* 0x0450_0000 .. 0x045F_FFFF AI registers
|
||||
* 0x0460_0000 .. 0x046F_FFFF PI registers
|
||||
* 0x0470_0000 .. 0x047F_FFFF RI registers
|
||||
* 0x0480_0000 .. 0x048F_FFFF SI registers
|
||||
* 0x0490_0000 .. 0x04FF_FFFF unused
|
||||
*
|
||||
* 0x0500_0000 .. 0x05FF_FFFF cartridge domain 2
|
||||
* 0x0600_0000 .. 0x07FF_FFFF cartridge domain 1
|
||||
* 0x0800_0000 .. 0x0FFF_FFFF cartridge domain 2
|
||||
* 0x1000_0000 .. 0x1FBF_FFFF cartridge domain 1
|
||||
*
|
||||
* 0x1FC0_0000 .. 0x1FC0_07BF PIF Boot Rom (1984 bytes)
|
||||
* 0x1FC0_07C0 .. 0x1FC0_07FF PIF (JoyChannel) RAM (64 bytes)
|
||||
* 0x1FC0_0800 .. 0x1FCF_FFFF Reserved
|
||||
* 0x1FD0_0000 .. 0x7FFF_FFFF cartridge domain 1
|
||||
* 0x8000_0000 .. 0xFFFF_FFFF external SysAD device
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* RDRAM memory
|
||||
*/
|
||||
|
||||
#define RDRAM_0_START 0x00000000
|
||||
#define RDRAM_0_END 0x001FFFFF
|
||||
#define RDRAM_1_START 0x00200000
|
||||
#define RDRAM_1_END 0x003FFFFF
|
||||
|
||||
#define RDRAM_START RDRAM_0_START
|
||||
#define RDRAM_END RDRAM_1_END
|
||||
|
||||
|
||||
/**
|
||||
* RDRAM registers
|
||||
*/
|
||||
#define RDRAM_BASE_REG 0x03F00000
|
||||
|
||||
#define RDRAM_CONFIG_REG (RDRAM_BASE_REG + 0x00)
|
||||
#define RDRAM_DEVICE_TYPE_REG (RDRAM_BASE_REG + 0x00)
|
||||
#define RDRAM_DEVICE_ID_REG (RDRAM_BASE_REG + 0x04)
|
||||
#define RDRAM_DELAY_REG (RDRAM_BASE_REG + 0x08)
|
||||
#define RDRAM_MODE_REG (RDRAM_BASE_REG + 0x0C)
|
||||
#define RDRAM_REF_INTERVAL_REG (RDRAM_BASE_REG + 0x10)
|
||||
#define RDRAM_REF_ROW_REG (RDRAM_BASE_REG + 0x14)
|
||||
#define RDRAM_RAS_INTERVAL_REG (RDRAM_BASE_REG + 0x18)
|
||||
#define RDRAM_MIN_INTERVAL_REG (RDRAM_BASE_REG + 0x1C)
|
||||
#define RDRAM_ADDR_SELECT_REG (RDRAM_BASE_REG + 0x20)
|
||||
#define RDRAM_DEVICE_MANUF_REG (RDRAM_BASE_REG + 0x24)
|
||||
|
||||
#define RDRAM_0_DEVICE_ID 0
|
||||
#define RDRAM_1_DEVICE_ID 1
|
||||
|
||||
#define RDRAM_RESET_MODE 0
|
||||
#define RDRAM_ACTIVE_MODE 1
|
||||
#define RDRAM_STANDBY_MODE 2
|
||||
|
||||
#define RDRAM_LENGTH (2 * 512 * 2048)
|
||||
#define RDRAM_0_BASE_ADDRESS (RDRAM_0_DEVICE_ID * RDRAM_LENGTH)
|
||||
#define RDRAM_1_BASE_ADDRESS (RDRAM_1_DEVICE_ID * RDRAM_LENGTH)
|
||||
|
||||
#define RDRAM_0_CONFIG 0x00000
|
||||
#define RDRAM_1_CONFIG 0x00400
|
||||
#define RDRAM_GLOBAL_CONFIG 0x80000
|
||||
|
||||
|
||||
/**
|
||||
* PIF Physical memory map (total size = 2 KB)
|
||||
*
|
||||
* Size Description Mode
|
||||
* Size Description Mode
|
||||
* 1FC007FF +-------+-----------------+-----+
|
||||
* | 64 B | JoyChannel RAM | R/W |
|
||||
* 1FC007C0 +-------+-----------------+-----+
|
||||
|
|
@ -16,84 +96,13 @@
|
|||
#define PIF_RAM_START 0x1FC007C0
|
||||
#define PIF_RAM_END 0x1FC007FF
|
||||
|
||||
/*
|
||||
* Patterns to interpret VI_CONTROL_REG
|
||||
*/
|
||||
#define VI_CTRL_TYPE_16 0x00002 /* [1:0] pixel size: 16 bit */
|
||||
#define VI_CTRL_TYPE_32 0x00003 /* [1:0] pixel size: 32 bit */
|
||||
#define VI_CTRL_GAMMA_DITHER_ON 0x00004 /* 2: default = on */
|
||||
#define VI_CTRL_GAMMA_ON 0x00008 /* 3: default = on */
|
||||
#define VI_CTRL_DIVOT_ON 0x00010 /* 4: default = on */
|
||||
#define VI_CTRL_SERRATE_ON 0x00040 /* 6: on if interlaced */
|
||||
#define VI_CTRL_ANTIALIAS_MASK 0x00300 /* [9:8] anti-alias mode */
|
||||
#define VI_CTRL_ANTIALIAS_MODE_1 0x00100 /* Bit [9:8] anti-alias mode */
|
||||
#define VI_CTRL_ANTIALIAS_MODE_2 0x00200 /* Bit [9:8] anti-alias mode */
|
||||
#define VI_CTRL_ANTIALIAS_MODE_3 0x00300 /* Bit [9:8] anti-alias mode */
|
||||
#define VI_CTRL_PIXEL_ADV_MASK 0x01000 /* [15:12] pixel advance mode? */
|
||||
#define VI_CTRL_PIXEL_ADV_1 0x01000 /* Bit [15:12] pixel advance mode? */
|
||||
#define VI_CTRL_PIXEL_ADV_2 0x02000 /* Bit [15:12] pixel advance mode? */
|
||||
#define VI_CTRL_PIXEL_ADV_3 0x03000 /* Bit [15:12] pixel advance mode? */
|
||||
#define VI_CTRL_DITHER_FILTER_ON 0x10000 /* 16: dither-filter mode */
|
||||
|
||||
|
||||
#define VI_NTSC_CLOCK 48681812 /* Hz = 48.681812 MHz */
|
||||
#define VI_PAL_CLOCK 49656530 /* Hz = 49.656530 MHz */
|
||||
#define VI_MPAL_CLOCK 48628316 /* Hz = 48.628316 MHz */
|
||||
|
||||
/**
|
||||
* Audio Interface (AI) Registers
|
||||
* Controller channel
|
||||
* Each game controller channel has 4 error bits that are defined in bit 6-7 of
|
||||
* the Rx and Tx data size area bytes. Programmers need to clear these bits
|
||||
* when setting the Tx/Rx size area values for a channel
|
||||
*/
|
||||
#define AI_BASE_REG 0x04500000
|
||||
|
||||
/* AI DRAM address (W): [23:0] starting RDRAM address (8B-aligned) */
|
||||
#define AI_DRAM_ADDR_REG (AI_BASE_REG + 0x00) /* R0: DRAM address */
|
||||
|
||||
/* AI length (R/W): [14:0] transfer length (v1.0) - Bottom 3 bits are ignored */
|
||||
/* [17:0] transfer length (v2.0) - Bottom 3 bits are ignored */
|
||||
#define AI_LEN_REG (AI_BASE_REG + 0x04) /* R1: Length */
|
||||
|
||||
/* AI control (W): [0] DMA enable - if LSB == 1, DMA is enabled */
|
||||
#define AI_CONTROL_REG (AI_BASE_REG + 0x08) /* R2: DMA Control */
|
||||
|
||||
/* Value for control register */
|
||||
#define AI_CONTROL_DMA_ON 1 /* LSB = 1: DMA enable*/
|
||||
#define AI_CONTROL_DMA_OFF 0 /* LSB = 1: DMA enable*/
|
||||
|
||||
/*
|
||||
* AI status (R): [31]/[0] ai_full (addr & len buffer full), [30] ai_busy
|
||||
* Note that a 1->0 transition in ai_full will set interrupt
|
||||
* (W): clear audio interrupt
|
||||
*/
|
||||
#define AI_STATUS_REG (AI_BASE_REG + 0x0C) /* R3: Status */
|
||||
|
||||
/* Value for status register */
|
||||
#define AI_STATUS_FIFO_FULL (1 << 31)
|
||||
#define AI_STATUS_DMA_BUSY (1 << 30)
|
||||
|
||||
/*
|
||||
* AI DAC sample period register (W): [13:0] dac rate
|
||||
* - vid_clock/(dperiod + 1) is the DAC sample rate
|
||||
* - (dperiod + 1) >= 66 * (aclockhp + 1) must be true
|
||||
*/
|
||||
#define AI_DACRATE_REG (AI_BASE_REG + 0x10) /* R4: DAC rate 14-lsb*/
|
||||
|
||||
/* DAC rate = video clock / audio frequency
|
||||
* - DAC rate >= (66 * Bit rate) must be true
|
||||
*/
|
||||
#define AI_MAX_DAC_RATE 16384 /* 14-bit+1 */
|
||||
#define AI_MIN_DAC_RATE 132
|
||||
|
||||
/*
|
||||
* AI bit rate (W): [3:0] bit rate (abus clock half period register - aclockhp)
|
||||
* - vid_clock/(2 * (aclockhp + 1)) is the DAC clock rate
|
||||
* - The abus clock stops if aclockhp is zero
|
||||
*/
|
||||
#define AI_BITRATE_REG (AI_BASE_REG + 0x14) /* R5: Bit rate 4-lsb */
|
||||
|
||||
/* Bit rate <= (DAC rate / 66) */
|
||||
#define AI_MAX_BIT_RATE 16 /* 4-bit+1 */
|
||||
#define AI_MIN_BIT_RATE 2
|
||||
|
||||
#define CHNL_ERR_NORESP 0x80 /* Bit 7 (Rx): No response error */
|
||||
#define CHNL_ERR_OVERRUN 0x40 /* Bit 6 (Rx): Overrun error */
|
||||
#define CHNL_ERR_FRAME 0x80 /* Bit 7 (Tx): Frame error */
|
||||
|
|
@ -101,11 +110,18 @@
|
|||
|
||||
#define CHNL_ERR_MASK 0xC0 /* Bit 6-7: channel errors */
|
||||
|
||||
|
||||
/**
|
||||
* External device info
|
||||
*/
|
||||
#define DEVICE_TYPE_CART 0 /* ROM cartridge */
|
||||
#define DEVICE_TYPE_BULK 1 /* ROM bulk */
|
||||
#define DEVICE_TYPE_64DD 2 /* 64 Disk Drive */
|
||||
#define DEVICE_TYPE_SRAM 3 /* SRAM */
|
||||
/* 4-6 are reserved */
|
||||
#define DEVICE_TYPE_INIT 7 /* initial value */
|
||||
/* 8-14 are reserved */
|
||||
|
||||
|
||||
/**
|
||||
* Signal Processor (SP) Memory
|
||||
|
|
@ -115,43 +131,74 @@
|
|||
#define SP_IMEM_START 0x04001000
|
||||
#define SP_IMEM_END 0x04001FFF
|
||||
|
||||
#define SP_MEM_ADDR_REG 0x04040000
|
||||
#define SP_DRAM_ADDR_REG 0x04040004
|
||||
#define SP_RD_LEN_REG 0x04040008
|
||||
#define SP_WR_LEN_REG 0x0404000C
|
||||
#define SP_STATUS_REG 0x04040010
|
||||
#define SP_DMA_FULL_REG 0x04040014
|
||||
#define SP_DMA_BUSY_REG 0x04040018
|
||||
#define SP_PC_REG 0x04080000
|
||||
|
||||
/**
|
||||
* Signal Processor (SP) CP0 Registers
|
||||
*/
|
||||
|
||||
#define SP_BASE_REG 0x04040000
|
||||
|
||||
/* SP memory address (R/W): [12] 0=DMEM,1=IMEM, [11:0] DMEM/IMEM address */
|
||||
#define SP_MEM_ADDR_REG (SP_BASE_REG + 0x00)
|
||||
|
||||
/* SP DRAM DMA address (R/W): [23:0] RDRAM address */
|
||||
#define SP_DRAM_ADDR_REG (SP_BASE_REG + 0x04)
|
||||
|
||||
/* SP read DMA length (R/W): [31:20] skip, [19:12] count, [11:0] length; RDRAM -> I/DMEM */
|
||||
#define SP_RD_LEN_REG (SP_BASE_REG + 0x08)
|
||||
|
||||
/* SP write DMA length (R/W): [31:20] skip, [19:12] count, [11:0] length; I/DMEM -> RDRAM */
|
||||
#define SP_WR_LEN_REG (SP_BASE_REG + 0x0C)
|
||||
|
||||
/* SP status (R/W): [14:0] valid bits; see below for write/read mode */
|
||||
#define SP_STATUS_REG (SP_BASE_REG + 0x10)
|
||||
|
||||
/* SP DMA full (R): [0] dma full */
|
||||
#define SP_DMA_FULL_REG (SP_BASE_REG + 0x14)
|
||||
|
||||
/* SP DMA busy (R): [0] dma busy */
|
||||
#define SP_DMA_BUSY_REG (SP_BASE_REG + 0x18)
|
||||
|
||||
/* SP semaphore (R/W): Read: [0] acquire semaphore; Write: [] release semaphore */
|
||||
#define SP_SEMAPHORE_REG (SP_BASE_REG + 0x1C)
|
||||
|
||||
/* SP PC (R/W): [11:0] program counter */
|
||||
#define SP_PC_REG 0x04080000
|
||||
|
||||
/*
|
||||
* SP_MEM_ADDR_REG: bit 12
|
||||
*/
|
||||
#define SP_DMA_DMEM (0 << 12)
|
||||
#define SP_DMA_IMEM (1 << 12)
|
||||
|
||||
/*
|
||||
* SP_STATUS_REG: write bits
|
||||
*/
|
||||
#define SP_CLR_HALT (1 << 0)
|
||||
#define SP_SET_HALT (1 << 1)
|
||||
#define SP_CLR_BROKE (1 << 2)
|
||||
#define SP_CLR_INTR (1 << 3)
|
||||
#define SP_SET_INTR (1 << 4)
|
||||
#define SP_CLR_SSTEP (1 << 5)
|
||||
#define SP_SET_SSTEP (1 << 6)
|
||||
#define SP_CLR_INTR_BREAK (1 << 7)
|
||||
#define SP_SET_INTR_BREAK (1 << 8)
|
||||
#define SP_CLR_SIG0 (1 << 9)
|
||||
#define SP_SET_SIG0 (1 << 10)
|
||||
#define SP_CLR_SIG1 (1 << 11)
|
||||
#define SP_SET_SIG1 (1 << 12)
|
||||
#define SP_CLR_SIG2 (1 << 13)
|
||||
#define SP_SET_SIG2 (1 << 14)
|
||||
#define SP_CLR_SIG3 (1 << 15)
|
||||
#define SP_SET_SIG3 (1 << 16)
|
||||
#define SP_CLR_SIG4 (1 << 17)
|
||||
#define SP_SET_SIG4 (1 << 18)
|
||||
#define SP_CLR_SIG5 (1 << 19)
|
||||
#define SP_SET_SIG5 (1 << 20)
|
||||
#define SP_CLR_SIG6 (1 << 21)
|
||||
#define SP_SET_SIG6 (1 << 22)
|
||||
#define SP_CLR_SIG7 (1 << 23)
|
||||
#define SP_SET_SIG7 (1 << 24)
|
||||
#define SP_CLR_HALT (1 << 0) /* clear halt */
|
||||
#define SP_SET_HALT (1 << 1) /* set halt */
|
||||
#define SP_CLR_BROKE (1 << 2) /* clear broke */
|
||||
#define SP_CLR_INTR (1 << 3) /* clear interrupt */
|
||||
#define SP_SET_INTR (1 << 4) /* set interrupt */
|
||||
#define SP_CLR_SSTEP (1 << 5) /* clear sstep */
|
||||
#define SP_SET_SSTEP (1 << 6) /* set sstep */
|
||||
#define SP_CLR_INTR_BREAK (1 << 7) /* clear interrupt on break */
|
||||
#define SP_SET_INTR_BREAK (1 << 8) /* set interrupt on break */
|
||||
#define SP_CLR_SIG0 (1 << 9) /* clear signal 0 */
|
||||
#define SP_SET_SIG0 (1 << 10) /* set signal 0 */
|
||||
#define SP_CLR_SIG1 (1 << 11) /* clear signal 1 */
|
||||
#define SP_SET_SIG1 (1 << 12) /* set signal 1 */
|
||||
#define SP_CLR_SIG2 (1 << 13) /* clear signal 2 */
|
||||
#define SP_SET_SIG2 (1 << 14) /* set signal 2 */
|
||||
#define SP_CLR_SIG3 (1 << 15) /* clear signal 3 */
|
||||
#define SP_SET_SIG3 (1 << 16) /* set signal 3 */
|
||||
#define SP_CLR_SIG4 (1 << 17) /* clear signal 4 */
|
||||
#define SP_SET_SIG4 (1 << 18) /* set signal 4 */
|
||||
#define SP_CLR_SIG5 (1 << 19) /* clear signal 5 */
|
||||
#define SP_SET_SIG5 (1 << 20) /* set signal 5 */
|
||||
#define SP_CLR_SIG6 (1 << 21) /* clear signal 6 */
|
||||
#define SP_SET_SIG6 (1 << 22) /* set signal 6 */
|
||||
#define SP_CLR_SIG7 (1 << 23) /* clear signal 7 */
|
||||
#define SP_SET_SIG7 (1 << 24) /* set signal 7 */
|
||||
|
||||
/*
|
||||
* SP_STATUS_REG: read bits
|
||||
|
|
@ -172,7 +219,7 @@
|
|||
#define SP_STATUS_SIG6 (1 << 13)
|
||||
#define SP_STATUS_SIG7 (1 << 14)
|
||||
|
||||
/**
|
||||
/*
|
||||
* SP_STATUS_REG: use of SIG bits
|
||||
*/
|
||||
#define SP_CLR_YIELD SP_CLR_SIG0
|
||||
|
|
@ -191,49 +238,465 @@
|
|||
#define SP_SET_CPUSIGNAL SP_SET_SIG4
|
||||
#define SP_STATUS_CPUSIGNAL SP_STATUS_SIG4
|
||||
|
||||
#define VI_STATUS_REG 0x04400000
|
||||
#define VI_CONTROL_REG 0x04400000
|
||||
#define VI_ORIGIN_REG 0x04400004
|
||||
#define VI_DRAM_ADDR_REG 0x04400004
|
||||
#define VI_WIDTH_REG 0x04400008
|
||||
#define VI_H_WIDTH_REG 0x04400008
|
||||
#define VI_INTR_REG 0x0440000C
|
||||
#define VI_V_INTER_REG 0x0440000C
|
||||
#define VI_CURRENT_REG 0x04400010
|
||||
#define VI_V_CURRENT_LINE_REG 0x04400010
|
||||
#define VI_BURST_REG 0x04400014
|
||||
#define VI_TIMING_REG 0x04400014
|
||||
#define VI_V_SYNC_REG 0x04400018 // VI vertical sync
|
||||
#define VI_H_SYNC_REG 0x0440001C // VI horizontal sync
|
||||
#define VI_LEAP_REG 0x04400020 // VI horizontal sync leap
|
||||
#define VI_H_SYNC_LEAP_REG 0x04400020
|
||||
#define VI_H_START_REG 0x04400024 // VI horizontal video
|
||||
#define VI_H_VIDEO_REG 0x04400024
|
||||
#define VI_V_START_REG 0x04400028 // VI vertical video
|
||||
#define VI_V_VIDEO_REG 0x04400028
|
||||
#define VI_V_BURST_REG 0x0440002C // VI vertical burst
|
||||
#define VI_X_SCALE_REG 0x04400030 // VI x-scale
|
||||
#define VI_Y_SCALE_REG 0x04400034 // VI y-scale
|
||||
/* SP IMEM BIST REG (R/W): [6:0] BIST status bits; see below for detail */
|
||||
#define SP_IBIST_REG 0x04080004
|
||||
|
||||
#define PI_DRAM_ADDR_REG 0x04600000 // PI DRAM address
|
||||
#define PI_CART_ADDR_REG 0x04600004 // PI pbus (cartridge) address
|
||||
#define PI_RD_LEN_REG 0x04600008 // PI read length
|
||||
#define PI_WR_LEN_REG 0x0460000C // PI write length
|
||||
#define PI_STATUS_REG 0x04600010 // PI status
|
||||
#define PI_BSD_DOM1_LAT_REG 0x04600014 // PI dom1 latency
|
||||
#define PI_DOMAIN1_REG 0x04600014
|
||||
#define PI_BSD_DOM1_PWD_REG 0x04600018 // PI dom1 pulse width
|
||||
#define PI_BSD_DOM1_PGS_REG 0x0460001C // PI dom1 page size
|
||||
#define PI_BSD_DOM1_RLS_REG 0x04600020 // PI dom1 release
|
||||
#define PI_BSD_DOM2_LAT_REG 0x04600024 // PI dom2 latency
|
||||
#define PI_DOMAIN2_REG 0x04600024
|
||||
#define PI_BSD_DOM2_PWD_REG 0x04600028 // PI dom2 pulse width
|
||||
#define PI_BSD_DOM2_PGS_REG 0x0460002C // PI dom2 page size
|
||||
#define PI_BSD_DOM2_RLS_REG 0x04600030 // PI dom2 release
|
||||
/*
|
||||
* SP_IBIST_REG: write bits
|
||||
*/
|
||||
#define SP_IBIST_CHECK (1 << 0) /* BIST check */
|
||||
#define SP_IBIST_GO (1 << 1) /* BIST go */
|
||||
#define SP_IBIST_CLEAR (1 << 2) /* BIST clear */
|
||||
|
||||
#define PI_STATUS_DMA_BUSY (1 << 0)
|
||||
#define PI_STATUS_IO_BUSY (1 << 1)
|
||||
#define PI_STATUS_ERROR (1 << 2)
|
||||
/*
|
||||
* SP_BIST_REG: read bits
|
||||
* First 2 bits are same as in write mode
|
||||
*/
|
||||
#define SP_IBIST_DONE (1 << 2)
|
||||
#define SP_IBIST_FAILED 0x78 /* bits [6:3], BIST fail */
|
||||
|
||||
|
||||
/**
|
||||
* Display Processor Command (DPC) Registers
|
||||
*/
|
||||
#define DPC_BASE_REG 0x04100000
|
||||
|
||||
/* DP CMD DMA start (R/W): [23:0] DMEM/RDRAM start address */
|
||||
#define DPC_START_REG (DPC_BASE_REG + 0x00)
|
||||
|
||||
/* DP CMD DMA end (R/W): [23:0] DMEM/RDRAM end address */
|
||||
#define DPC_END_REG (DPC_BASE_REG + 0x04)
|
||||
|
||||
/* DP CMD DMA end (R): [23:0] DMEM/RDRAM current address */
|
||||
#define DPC_CURRENT_REG (DPC_BASE_REG + 0x08)
|
||||
|
||||
/* DP CMD status (R/W): [9:0] valid bits - see below for definitions */
|
||||
#define DPC_STATUS_REG (DPC_BASE_REG + 0x0C)
|
||||
|
||||
/* DP clock counter (R): [23:0] clock counter */
|
||||
#define DPC_CLOCK_REG (DPC_BASE_REG + 0x10)
|
||||
|
||||
/* DP buffer busy counter (R): [23:0] clock counter */
|
||||
#define DPC_BUFBUSY_REG (DPC_BASE_REG + 0x14)
|
||||
|
||||
/* DP pipe busy counter (R): [23:0] clock counter */
|
||||
#define DPC_PIPEBUSY_REG (DPC_BASE_REG + 0x18)
|
||||
|
||||
/* DP TMEM load counter (R): [23:0] clock counter */
|
||||
#define DPC_TMEM_REG (DPC_BASE_REG + 0x1C)
|
||||
|
||||
/*
|
||||
* DPC_STATUS_REG: write bits
|
||||
*/
|
||||
#define DPC_CLR_XBUS_DMEM_DMA (1 << 0)
|
||||
#define DPC_SET_XBUS_DMEM_DMA (1 << 1)
|
||||
#define DPC_CLR_FREEZE (1 << 2)
|
||||
#define DPC_SET_FREEZE (1 << 3)
|
||||
#define DPC_CLR_FLUSH (1 << 4)
|
||||
#define DPC_SET_FLUSH (1 << 5)
|
||||
#define DPC_CLR_TMEM_CTR (1 << 6)
|
||||
#define DPC_CLR_PIPE_CTR (1 << 7)
|
||||
#define DPC_CLR_CMD_CTR (1 << 8)
|
||||
#define DPC_CLR_CLOCK_CTR (1 << 9)
|
||||
|
||||
/*
|
||||
* DPC_STATUS_REG: read bits
|
||||
*/
|
||||
#define DPC_STATUS_XBUS_DMEM_DMA (1 << 0)
|
||||
#define DPC_STATUS_FREEZE (1 << 1)
|
||||
#define DPC_STATUS_FLUSH (1 << 2)
|
||||
#define DPC_STATUS_START_GCLK (1 << 3)
|
||||
#define DPC_STATUS_TMEM_BUSY (1 << 4)
|
||||
#define DPC_STATUS_PIPE_BUSY (1 << 5)
|
||||
#define DPC_STATUS_CMD_BUSY (1 << 6)
|
||||
#define DPC_STATUS_CBUF_READY (1 << 7)
|
||||
#define DPC_STATUS_DMA_BUSY (1 << 8)
|
||||
#define DPC_STATUS_END_VALID (1 << 9)
|
||||
#define DPC_STATUS_START_VALID (1 << 10)
|
||||
|
||||
|
||||
/**
|
||||
* Display Processor Span (DPS) Registers
|
||||
*/
|
||||
#define DPS_BASE_REG 0x04200000
|
||||
|
||||
/* DP tmem built-in self-test (R/W): [10:0] BIST status bits */
|
||||
#define DPS_TBIST_REG (DPS_BASE_REG + 0x00)
|
||||
|
||||
/* DP span test mode (R/W): [0] Span buffer test access enable */
|
||||
#define DPS_TEST_MODE_REG (DPS_BASE_REG + 0x04)
|
||||
|
||||
/* DP span buffer test address (R/W): [6:0] bits */
|
||||
#define DPS_BUFTEST_ADDR_REG (DPS_BASE_REG + 0x08)
|
||||
|
||||
/* DP span buffer test data (R/W): [31:0] span buffer data */
|
||||
#define DPS_BUFTEST_DATA_REG (DPS_BASE_REG + 0x0C)
|
||||
|
||||
/*
|
||||
* DPS_TMEM_BIST_REG: write bits
|
||||
*/
|
||||
#define DPS_TBIST_CHECK (1 << 0)
|
||||
#define DPS_TBIST_GO (1 << 1)
|
||||
#define DPS_TBIST_CLEAR (1 << 2)
|
||||
|
||||
/*
|
||||
* DPS_TMEM_BIST_REG: read bits
|
||||
* First 2 bits are same as in write mode
|
||||
*/
|
||||
#define DPS_TBIST_DONE (1 << 2)
|
||||
#define DPS_TBIST_FAILED 0x7F8 /* bits [10:3], BIST fail */
|
||||
|
||||
|
||||
/**
|
||||
* MIPS Interface (MI) Registers
|
||||
*/
|
||||
#define MI_BASE_REG 0x04300000
|
||||
|
||||
/* MI init mode (W): [11] clear DP interrupt, [9/10] clear/set ebus test mode */
|
||||
/* [8] set init mode, [7] clear init mode, [6:0] init length */
|
||||
/* (R): [8] ebus test mode, [7] init mode, [6:0] init length */
|
||||
#define MI_INIT_MODE_REG (MI_BASE_REG + 0x00)
|
||||
#define MI_MODE_REG MI_INIT_MODE_REG
|
||||
|
||||
/*
|
||||
* MI_MODE_REG: write bits
|
||||
*/
|
||||
#define MI_CLR_INIT (1 << 7) /* clear init mode */
|
||||
#define MI_SET_INIT (1 << 8) /* set init mode */
|
||||
#define MI_CLR_EBUS (1 << 9) /* clear ebus test */
|
||||
#define MI_SET_EBUS (1 << 10) /* set ebus test mode */
|
||||
#define MI_CLR_DP_INTR (1 << 11) /* clear dp interrupt */
|
||||
#define MI_CLR_RDRAM (1 << 12) /* clear RDRAM reg */
|
||||
#define MI_SET_RDRAM (1 << 13) /* set RDRAM reg mode */
|
||||
|
||||
/*
|
||||
* MI_MODE_REG: read bits
|
||||
*/
|
||||
#define MI_MODE_INIT (1 << 7) /* init mode */
|
||||
#define MI_MODE_EBUS (1 << 8) /* ebus test mode */
|
||||
#define MI_MODE_RDRAM (1 << 9) /* RDRAM reg mode */
|
||||
|
||||
/* MI version (R): [31:24] rsp, [23:16] rdp, [15:8] rac, [7:0] io */
|
||||
#define MI_VERSION_REG (MI_BASE_REG + 0x04)
|
||||
#define MI_NOOP_REG MI_VERSION_REG
|
||||
|
||||
/* MI interrupt (R): [5:0] valid bits - see below for bit patterns */
|
||||
#define MI_INTR_REG (MI_BASE_REG + 0x08)
|
||||
|
||||
/* MI interrupt mask (R): [5:0] valid bits - see below for bit patterns */
|
||||
/* (W): [11:0] valid bits - see below for bit patterns */
|
||||
#define MI_INTR_MASK_REG (MI_BASE_REG + 0x0C)
|
||||
|
||||
/*
|
||||
* MI_INTR_REG: read bits
|
||||
*/
|
||||
#define MI_INTR_SP (1 << 0) /* SP intr */
|
||||
#define MI_INTR_SI (1 << 1) /* SI intr */
|
||||
#define MI_INTR_AI (1 << 2) /* AI intr */
|
||||
#define MI_INTR_VI (1 << 3) /* VI intr */
|
||||
#define MI_INTR_PI (1 << 4) /* PI intr */
|
||||
#define MI_INTR_DP (1 << 5) /* DP intr */
|
||||
|
||||
/*
|
||||
* MI_INTR_MASK_REG: write bits
|
||||
*/
|
||||
#define MI_INTR_MASK_CLR_SP (1 << 0) /* clear SP mask */
|
||||
#define MI_INTR_MASK_SET_SP (1 << 1) /* set SP mask */
|
||||
#define MI_INTR_MASK_CLR_SI (1 << 2) /* clear SI mask */
|
||||
#define MI_INTR_MASK_SET_SI (1 << 3) /* set SI mask */
|
||||
#define MI_INTR_MASK_CLR_AI (1 << 4) /* clear AI mask */
|
||||
#define MI_INTR_MASK_SET_AI (1 << 5) /* set AI mask */
|
||||
#define MI_INTR_MASK_CLR_VI (1 << 6) /* clear VI mask */
|
||||
#define MI_INTR_MASK_SET_VI (1 << 7) /* set VI mask */
|
||||
#define MI_INTR_MASK_CLR_PI (1 << 8) /* clear PI mask */
|
||||
#define MI_INTR_MASK_SET_PI (1 << 9) /* set PI mask */
|
||||
#define MI_INTR_MASK_CLR_DP (1 << 10) /* clear DP mask */
|
||||
#define MI_INTR_MASK_SET_DP (1 << 11) /* set DP mask */
|
||||
|
||||
/*
|
||||
* MI_INTR_MASK_REG: read bits
|
||||
*/
|
||||
#define MI_INTR_MASK_SP (1 << 0) /* SP intr mask */
|
||||
#define MI_INTR_MASK_SI (1 << 1) /* SI intr mask */
|
||||
#define MI_INTR_MASK_AI (1 << 2) /* AI intr mask */
|
||||
#define MI_INTR_MASK_VI (1 << 3) /* VI intr mask */
|
||||
#define MI_INTR_MASK_PI (1 << 4) /* PI intr mask */
|
||||
#define MI_INTR_MASK_DP (1 << 5) /* DP intr mask */
|
||||
|
||||
|
||||
/**
|
||||
* Video Interface (VI) Registers
|
||||
*/
|
||||
#define VI_BASE_REG 0x04400000
|
||||
|
||||
/*
|
||||
* VI status/control (R/W): [15-0] valid bits:
|
||||
* [1:0] = type[1:0] (pixel size)
|
||||
* 0: blank (no data, no sync)
|
||||
* 1: reserved
|
||||
* 2: 5/5/5/3 ("16" bit)
|
||||
* 3: 8/8/8/8 (32 bit)
|
||||
* [2] = gamma_dither_enable (normally on, unless "special effect")
|
||||
* [3] = gamma_enable (normally on, unless MPEG/JPEG)
|
||||
* [4] = divot_enable (normally on if antialiased, unless decal lines)
|
||||
* [5] = vbus_clock_enable - always off
|
||||
* [6] = serrate (always on if interlaced, off if not)
|
||||
* [7] = test_mode - diagnostics only
|
||||
* [9:8] = anti-alias (aa) mode[1:0]
|
||||
* 0: aa & resamp (always fetch extra lines)
|
||||
* 1: aa & resamp (fetch extra lines if needed)
|
||||
* 2: resamp only (treat as all fully covered)
|
||||
* 3: neither (replicate pixels, no interpolate)
|
||||
* [11] = kill_we - diagnostics only
|
||||
* [15:12] = pixel_advance
|
||||
* [16] = dither_filter_enable
|
||||
*/
|
||||
#define VI_CONTROL_REG (VI_BASE_REG + 0x00)
|
||||
#define VI_STATUS_REG VI_CONTROL_REG
|
||||
|
||||
/* VI origin (R/W): [23:0] frame buffer origin in bytes */
|
||||
#define VI_ORIGIN_REG (VI_BASE_REG + 0x04)
|
||||
#define VI_DRAM_ADDR_REG VI_ORIGIN_REG
|
||||
|
||||
/* VI width (R/W): [11:0] frame buffer line width in pixels */
|
||||
#define VI_WIDTH_REG (VI_BASE_REG + 0x08)
|
||||
#define VI_H_WIDTH_REG VI_WIDTH_REG
|
||||
|
||||
/* VI vertical intr (R/W): [9:0] interrupt when current half-line = V_INTR */
|
||||
#define VI_INTR_REG (VI_BASE_REG + 0x0C)
|
||||
#define VI_V_INTR_REG VI_INTR_REG
|
||||
|
||||
/* VI current vertical line (R/W): [9:0] current half line, sampled once per */
|
||||
/* line (the lsb of V_CURRENT is constant within a field, and in interlaced */
|
||||
/* modes gives the field number - which is constant for non-interlaced modes) */
|
||||
/* - Any write to this register will clear interrupt line */
|
||||
#define VI_CURRENT_REG (VI_BASE_REG + 0x10)
|
||||
#define VI_V_CURRENT_LINE_REG VI_CURRENT_REG
|
||||
|
||||
/* VI video timing (R/W): [29:20] start of color burst in pixels from h-sync */
|
||||
/* [19:16] vertical sync width in half lines, */
|
||||
/* [15: 8] color burst width in pixels, */
|
||||
/* [ 7: 0] horizontal sync width in pixels, */
|
||||
#define VI_BURST_REG (VI_BASE_REG + 0x14)
|
||||
#define VI_TIMING_REG VI_BURST_REG
|
||||
|
||||
/* VI vertical sync (R/W): [9:0] number of half-lines per field */
|
||||
#define VI_V_SYNC_REG (VI_BASE_REG + 0x18)
|
||||
|
||||
/* VI horizontal sync (R/W): [20:16] a 5-bit leap pattern used for PAL only (h_sync_period) */
|
||||
/* [11: 0] total duration of a line in 1/4 pixel */
|
||||
#define VI_H_SYNC_REG (VI_BASE_REG + 0x1C)
|
||||
|
||||
/* VI horizontal sync leap (R/W): [27:16] identical to h_sync_period */
|
||||
/* [11: 0] identical to h_sync_period */
|
||||
#define VI_LEAP_REG (VI_BASE_REG + 0x20)
|
||||
#define VI_H_SYNC_LEAP_REG VI_LEAP_REG
|
||||
|
||||
/* VI horizontal video (R/W): [25:16] start of active video in screen pixels */
|
||||
/* [ 9: 0] end of active video in screen pixels */
|
||||
#define VI_H_START_REG (VI_BASE_REG + 0x24)
|
||||
#define VI_H_VIDEO_REG VI_H_START_REG
|
||||
|
||||
/* VI vertical video (R/W): [25:16] start of active video in screen half-lines */
|
||||
/* [ 9: 0] end of active video in screen half-lines */
|
||||
#define VI_V_START_REG (VI_BASE_REG + 0x28)
|
||||
#define VI_V_VIDEO_REG VI_V_START_REG
|
||||
|
||||
/* VI vertical burst (R/W): [25:16] start of color burst enable in half-lines */
|
||||
/* [ 9: 0] end of color burst enable in half-lines */
|
||||
#define VI_V_BURST_REG (VI_BASE_REG + 0x2C)
|
||||
|
||||
/* VI x-scale (R/W): [27:16] horizontal subpixel offset (2.10 format) */
|
||||
/* [11: 0] 1/horizontal scale up factor (2.10 format) */
|
||||
#define VI_X_SCALE_REG (VI_BASE_REG + 0x30)
|
||||
|
||||
/* VI y-scale (R/W): [27:16] vertical subpixel offset (2.10 format) */
|
||||
/* [11: 0] 1/vertical scale up factor (2.10 format) */
|
||||
#define VI_Y_SCALE_REG (VI_BASE_REG + 0x34)
|
||||
|
||||
/*
|
||||
* VI_CONTROL_REG: read bits
|
||||
*/
|
||||
#define VI_CTRL_TYPE_16 0x00002 /* [1:0] pixel size: 16 bit */
|
||||
#define VI_CTRL_TYPE_32 0x00003 /* [1:0] pixel size: 32 bit */
|
||||
#define VI_CTRL_GAMMA_DITHER_ON 0x00004 /* 2: default = on */
|
||||
#define VI_CTRL_GAMMA_ON 0x00008 /* 3: default = on */
|
||||
#define VI_CTRL_DIVOT_ON 0x00010 /* 4: default = on */
|
||||
#define VI_CTRL_SERRATE_ON 0x00040 /* 6: on if interlaced */
|
||||
#define VI_CTRL_ANTIALIAS_MASK 0x00300 /* [9:8] anti-alias mode */
|
||||
#define VI_CTRL_ANTIALIAS_MODE_0 0x00000 /* Bit [9:8] anti-alias mode: AA enabled, resampling enabled, always fetch extra lines */
|
||||
#define VI_CTRL_ANTIALIAS_MODE_1 0x00100 /* Bit [9:8] anti-alias mode: AA enabled, resampling enabled, fetch extra lines as-needed */
|
||||
#define VI_CTRL_ANTIALIAS_MODE_2 0x00200 /* Bit [9:8] anti-alias mode: AA disabled, resampling enabled, operate as if everything is covered */
|
||||
#define VI_CTRL_ANTIALIAS_MODE_3 0x00300 /* Bit [9:8] anti-alias mode: AA disabled, resampling disabled, replicate pixels */
|
||||
#define VI_CTRL_PIXEL_ADV_MASK 0x0F000 /* [15:12] pixel advance mode */
|
||||
#define VI_CTRL_PIXEL_ADV(n) (((n) << 12) & VI_CTRL_PIXEL_ADV_MASK) /* Bit [15:12] pixel advance mode: Always 3 on N64 */
|
||||
#define VI_CTRL_DITHER_FILTER_ON 0x10000 /* 16: dither-filter mode */
|
||||
|
||||
#define VI_CTRL_PIXEL_ADV_3 VI_CTRL_PIXEL_ADV(3)
|
||||
|
||||
/*
|
||||
* Possible video clocks (NTSC or PAL)
|
||||
*/
|
||||
#define VI_NTSC_CLOCK 48681812 /* Hz = 48.681812 MHz */
|
||||
#define VI_PAL_CLOCK 49656530 /* Hz = 49.656530 MHz */
|
||||
#define VI_MPAL_CLOCK 48628316 /* Hz = 48.628316 MHz */
|
||||
|
||||
|
||||
/**
|
||||
* Audio Interface (AI) Registers
|
||||
*
|
||||
* The address and length registers are double buffered; that is, they
|
||||
* can be written twice before becoming full.
|
||||
* The address must be written before the length.
|
||||
*/
|
||||
#define AI_BASE_REG 0x04500000
|
||||
|
||||
/* AI DRAM address (W): [23:0] starting RDRAM address (8B-aligned) */
|
||||
#define AI_DRAM_ADDR_REG (AI_BASE_REG + 0x00)
|
||||
|
||||
/* AI length (R/W): [14:0] transfer length (v1.0) - Bottom 3 bits are ignored */
|
||||
/* [17:0] transfer length (v2.0) - Bottom 3 bits are ignored */
|
||||
#define AI_LEN_REG (AI_BASE_REG + 0x04)
|
||||
|
||||
/* AI control (W): [0] DMA enable - if LSB == 1, DMA is enabled */
|
||||
#define AI_CONTROL_REG (AI_BASE_REG + 0x08)
|
||||
|
||||
/*
|
||||
* AI_CONTROL_REG: write bits
|
||||
*/
|
||||
#define AI_CONTROL_DMA_ON 1 /* LSB = 1: DMA enable */
|
||||
#define AI_CONTROL_DMA_OFF 0 /* LSB = 1: DMA enable */
|
||||
|
||||
/* AI status (R): [31]/[0] ai_full (addr & len buffer full), [30] ai_busy */
|
||||
/* Note that a 1->0 transition in ai_full will set interrupt */
|
||||
/* (W): clear audio interrupt */
|
||||
#define AI_STATUS_REG (AI_BASE_REG + 0x0C)
|
||||
|
||||
/*
|
||||
* AI_STATUS_REG: read bits
|
||||
*/
|
||||
#define AI_STATUS_FIFO_FULL (1 << 31)
|
||||
#define AI_STATUS_DMA_BUSY (1 << 30)
|
||||
|
||||
/* AI DAC sample period register (W): [13:0] dac rate */
|
||||
/* - vid_clock/(dperiod + 1) is the DAC sample rate */
|
||||
/* - (dperiod + 1) >= 66 * (aclockhp + 1) must be true */
|
||||
#define AI_DACRATE_REG (AI_BASE_REG + 0x10)
|
||||
|
||||
/* DAC rate = video clock / audio frequency */
|
||||
/* - DAC rate >= (66 * Bit rate) must be true */
|
||||
#define AI_MAX_DAC_RATE 16384 /* 14-bit+1 */
|
||||
#define AI_MIN_DAC_RATE 132
|
||||
|
||||
/* AI bit rate (W): [3:0] bit rate (abus clock half period register - aclockhp) */
|
||||
/* - vid_clock/(2 * (aclockhp + 1)) is the DAC clock rate */
|
||||
/* - The abus clock stops if aclockhp is zero */
|
||||
#define AI_BITRATE_REG (AI_BASE_REG + 0x14)
|
||||
|
||||
/* Bit rate <= (DAC rate / 66) */
|
||||
#define AI_MAX_BIT_RATE 16 /* 4-bit+1 */
|
||||
#define AI_MIN_BIT_RATE 2
|
||||
|
||||
/*
|
||||
* Maximum and minimum values for audio frequency based on video clocks
|
||||
* max frequency = (video clock / min dac rate)
|
||||
* min frequency = (video clock / max dac rate)
|
||||
*/
|
||||
#define AI_NTSC_MAX_FREQ 368000 /* 368 KHz */
|
||||
#define AI_NTSC_MIN_FREQ 3000 /* 3 KHz ~ 2971 Hz */
|
||||
|
||||
#define AI_PAL_MAX_FREQ 376000 /* 376 KHz */
|
||||
#define AI_PAL_MIN_FREQ 3050 /* 3 KHz ~ 3031 Hz */
|
||||
|
||||
#define AI_MPAL_MAX_FREQ 368000 /* 368 KHz */
|
||||
#define AI_MPAL_MIN_FREQ 3000 /* 3 KHz ~ 2968 Hz */
|
||||
|
||||
|
||||
/**
|
||||
* Peripheral Interface (PI) Registers
|
||||
*/
|
||||
#define PI_BASE_REG 0x04600000
|
||||
|
||||
/* PI DRAM address (R/W): [23:0] starting RDRAM address */
|
||||
#define PI_DRAM_ADDR_REG (PI_BASE_REG + 0x00)
|
||||
|
||||
/* PI pbus (cartridge) address (R/W): [31:0] starting AD16 address */
|
||||
#define PI_CART_ADDR_REG (PI_BASE_REG + 0x04)
|
||||
|
||||
/* PI read length (R/W): [23:0] read data length */
|
||||
#define PI_RD_LEN_REG (PI_BASE_REG + 0x08)
|
||||
|
||||
/* PI write length (R/W): [23:0] write data length */
|
||||
#define PI_WR_LEN_REG (PI_BASE_REG + 0x0C)
|
||||
|
||||
/* PI status (R): [3] interrupt flag, [2] error, [1] IO busy, [0] DMA busy */
|
||||
/* (W): [1] clear intr, [0] reset controller (and abort current op) */
|
||||
#define PI_STATUS_REG (PI_BASE_REG + 0x10)
|
||||
|
||||
/* PI dom1 latency (R/W): [7:0] domain 1 device latency */
|
||||
#define PI_BSD_DOM1_LAT_REG (PI_BASE_REG + 0x14)
|
||||
|
||||
/* PI dom1 pulse width (R/W): [7:0] domain 1 device R/W strobe pulse width */
|
||||
#define PI_BSD_DOM1_PWD_REG (PI_BASE_REG + 0x18)
|
||||
|
||||
/* PI dom1 page size (R/W): [3:0] domain 1 device page size */
|
||||
#define PI_BSD_DOM1_PGS_REG (PI_BASE_REG + 0x1C)
|
||||
|
||||
/* PI dom1 release (R/W): [1:0] domain 1 device R/W release duration */
|
||||
#define PI_BSD_DOM1_RLS_REG (PI_BASE_REG + 0x20)
|
||||
|
||||
/* PI dom2 latency (R/W): [7:0] domain 2 device latency */
|
||||
#define PI_BSD_DOM2_LAT_REG (PI_BASE_REG + 0x24)
|
||||
|
||||
/* PI dom2 pulse width (R/W): [7:0] domain 2 device R/W strobe pulse width */
|
||||
#define PI_BSD_DOM2_PWD_REG (PI_BASE_REG + 0x28)
|
||||
|
||||
/* PI dom2 page size (R/W): [3:0] domain 2 device page size */
|
||||
#define PI_BSD_DOM2_PGS_REG (PI_BASE_REG + 0x2C)
|
||||
|
||||
/* PI dom2 release (R/W): [1:0] domain 2 device R/W release duration */
|
||||
#define PI_BSD_DOM2_RLS_REG (PI_BASE_REG + 0x30)
|
||||
|
||||
#define PI_DOMAIN1_REG PI_BSD_DOM1_LAT_REG
|
||||
#define PI_DOMAIN2_REG PI_BSD_DOM2_LAT_REG
|
||||
|
||||
#define PI_DOM_LAT_OFS 0x00
|
||||
#define PI_DOM_PWD_OFS 0x04
|
||||
#define PI_DOM_PGS_OFS 0x08
|
||||
#define PI_DOM_RLS_OFS 0x0C
|
||||
|
||||
/*
|
||||
* PI_STATUS_REG: read bits
|
||||
* Bit 0: DMA busy - set when DMA is in progress
|
||||
* Bit 1: IO busy - set when IO is in progress
|
||||
* Bit 2: Error - set when CPU issues IO request while DMA is busy
|
||||
*/
|
||||
#define PI_STATUS_DMA_BUSY (1 << 0)
|
||||
#define PI_STATUS_IO_BUSY (1 << 1)
|
||||
#define PI_STATUS_ERROR (1 << 2)
|
||||
|
||||
/*
|
||||
* PI status register has 2 bits active when written to:
|
||||
* Bit 0: When set, reset PIC
|
||||
* Bit 1: When set, clear interrupt flag
|
||||
* The values of the two bits can be ORed together to both reset PIC and
|
||||
* clear interrupt at the same time.
|
||||
*
|
||||
* Note:
|
||||
* - The PIC does generate an interrupt at the end of each DMA. CPU
|
||||
* needs to clear the interrupt flag explicitly (from an interrupt
|
||||
* handler) by writing into the STATUS register with bit 1 set.
|
||||
*
|
||||
* - When a DMA completes, the interrupt flag is set. CPU can issue
|
||||
* another request even while the interrupt flag is set (as long as
|
||||
* PIC is idle). However, it is the CPU's responsibility for
|
||||
* maintaining accurate correspondence between DMA completions and
|
||||
* interrupts.
|
||||
*
|
||||
* - When PIC is reset, if PIC happens to be busy, an interrupt will
|
||||
* be generated as PIC returns to idle. Otherwise, no interrupt will
|
||||
* be generated and PIC remains idle.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PI_STATUS_REG: write bits
|
||||
|
|
@ -252,22 +715,99 @@
|
|||
#define PI_DOM2_ADDR1 0x05000000 /* to 0x05FFFFFF */
|
||||
#define PI_DOM2_ADDR2 0x08000000 /* to 0x0FFFFFFF */
|
||||
|
||||
|
||||
/**
|
||||
* RDRAM Interface (RI) Registers
|
||||
*/
|
||||
#define RI_BASE_REG 0x04700000
|
||||
|
||||
/* RI mode (R/W): [3] stop R active, [2] stop T active, [1:0] operating mode */
|
||||
#define RI_MODE_REG (RI_BASE_REG + 0x00)
|
||||
|
||||
/* RI config (R/W): [6] current control enable, [5:0] current control input */
|
||||
#define RI_CONFIG_REG (RI_BASE_REG + 0x04)
|
||||
|
||||
/* RI current load (W): [] any write updates current control register */
|
||||
#define RI_CURRENT_LOAD_REG (RI_BASE_REG + 0x08)
|
||||
|
||||
/* RI select (R/W): [3:2] receive select, [1:0] transmit select */
|
||||
#define RI_SELECT_REG (RI_BASE_REG + 0x0C)
|
||||
|
||||
/* RI refresh (R/W): [16] refresh bank, [17] refresh enable, [18] refresh optimize */
|
||||
/* [7:0] clean refresh delay, [15:8] dirty refresh dela */
|
||||
#define RI_REFRESH_REG (RI_BASE_REG + 0x10)
|
||||
#define RI_COUNT_REG RI_REFRESH_REG
|
||||
|
||||
/* RI latency (R/W): [3:0] DMA latency/overlap */
|
||||
#define RI_LATENCY_REG (RI_BASE_REG + 0x14)
|
||||
|
||||
/* RI error (R): [1] ack error, [0] nack error */
|
||||
#define RI_RERROR_REG (RI_BASE_REG + 0x18)
|
||||
|
||||
/* RI error (W): [] any write clears all error bits */
|
||||
#define RI_WERROR_REG (RI_BASE_REG + 0x1C)
|
||||
|
||||
|
||||
/**
|
||||
* Serial Interface (SI) Registers
|
||||
*/
|
||||
#define SI_BASE_REG 0x04800000
|
||||
|
||||
/* SI DRAM address (R/W): [23:0] starting RDRAM address */
|
||||
#define SI_DRAM_ADDR_REG (SI_BASE_REG + 0x00)
|
||||
|
||||
/* SI address read 64B (W): [] write begins a 64B DMA write PIF RAM -> RDRAM */
|
||||
#define SI_PIF_ADDR_RD64B_REG (SI_BASE_REG + 0x04)
|
||||
|
||||
/* Address SI_BASE_REG + (0x08, 0x0C, 0x14) are reserved */
|
||||
|
||||
/* SI address write 64B (W): [] write begins a 64B DMA read RDRAM -> PIF RAM */
|
||||
#define SI_PIF_ADDR_WR64B_REG (SI_BASE_REG + 0x10)
|
||||
|
||||
/* SI status (R/W): [] any write clears interrupt */
|
||||
#define SI_STATUS_REG (SI_BASE_REG + 0x18)
|
||||
|
||||
#define SI_STATUS_DMA_BUSY (1 << 0)
|
||||
#define SI_STATUS_IO_READ_BUSY (1 << 1)
|
||||
#define SI_STATUS_DMA_ERROR (1 << 3)
|
||||
#define SI_STATUS_INTERRUPT (1 << 12)
|
||||
/*
|
||||
* SI_STATUS_REG: read bits
|
||||
*/
|
||||
#define SI_STATUS_DMA_BUSY (1 << 0) /* DMA in progress */
|
||||
#define SI_STATUS_RD_BUSY (1 << 1) /* IO access in progress */
|
||||
#define SI_STATUS_DMA_ERROR (1 << 3) /* Overlapping DMA requests */
|
||||
#define SI_STATUS_INTERRUPT (1 << 12) /* Interrupt is set */
|
||||
|
||||
|
||||
/**
|
||||
* Development Board GIO Control Registers
|
||||
*/
|
||||
|
||||
#define GIO_BASE_REG 0x18000000
|
||||
|
||||
/* Game to Host Interrupt */
|
||||
#define GIO_GIO_INTR_REG (GIO_BASE_REG+0x000)
|
||||
|
||||
/* Game to Host SYNC */
|
||||
#define GIO_GIO_SYNC_REG (GIO_BASE_REG+0x400)
|
||||
|
||||
/* Host to Game Interrupt */
|
||||
#define GIO_CART_INTR_REG (GIO_BASE_REG+0x800)
|
||||
|
||||
|
||||
/**
|
||||
* Common macros
|
||||
*/
|
||||
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
|
||||
|
||||
#define IO_READ(addr) (*(vu32*)PHYS_TO_K1(addr))
|
||||
#define IO_WRITE(addr,data) (*(vu32*)PHYS_TO_K1(addr)=(u32)(data))
|
||||
|
||||
#define RCP_STAT_PRINT \
|
||||
rmonPrintf("current=%x start=%x end=%x dpstat=%x spstat=%x\n", \
|
||||
IO_READ(DPC_CURRENT_REG), \
|
||||
IO_READ(DPC_START_REG), \
|
||||
IO_READ(DPC_END_REG), \
|
||||
IO_READ(DPC_STATUS_REG), \
|
||||
IO_READ(SP_STATUS_REG))
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,50 +1,7 @@
|
|||
#ifndef PR_RDP_H
|
||||
#define PR_RDP_H
|
||||
|
||||
/* DP Command Registers */
|
||||
#define DPC_START_REG 0x04100000
|
||||
#define DPC_END_REG 0x04100004
|
||||
#define DPC_CURRENT_REG 0x04100008
|
||||
#define DPC_STATUS_REG 0x0410000C
|
||||
#define DPC_CLOCK_REG 0x04100010
|
||||
#define DPC_BUFBUSY_REG 0x04100014
|
||||
#define DPC_PIPEBUSY_REG 0x04100018
|
||||
#define DPC_TMEM_REG 0x0410001C
|
||||
|
||||
/* DP Span Registers */
|
||||
#define DPS_TBIST_REG 0x04200000
|
||||
#define DPS_TEST_MODE_REG 0x04200004
|
||||
#define DPS_BUFTEST_ADDR_REG 0x04200008
|
||||
#define DPS_BUFTEST_DATA_REG 0x0420000C
|
||||
|
||||
/* DP Status Read Flags */
|
||||
#define DPC_STATUS_XBUS_DMEM_DMA (1 << 0)
|
||||
#define DPC_STATUS_FREEZE (1 << 1)
|
||||
#define DPC_STATUS_FLUSH (1 << 2)
|
||||
#define DPC_STATUS_START_GCLK (1 << 3)
|
||||
#define DPC_STATUS_TMEM_BUSY (1 << 4)
|
||||
#define DPC_STATUS_PIPE_BUSY (1 << 5)
|
||||
#define DPC_STATUS_CMD_BUSY (1 << 6)
|
||||
#define DPC_STATUS_CBUF_READY (1 << 7)
|
||||
#define DPC_STATUS_DMA_BUSY (1 << 8)
|
||||
#define DPC_STATUS_END_VALID (1 << 9)
|
||||
#define DPC_STATUS_START_VALID (1 << 10)
|
||||
|
||||
/* DP Status Write Flags */
|
||||
#define DPC_CLR_XBUS_DMEM_DMA (1 << 0)
|
||||
#define DPC_SET_XBUS_DMEM_DMA (1 << 1)
|
||||
#define DPC_CLR_FREEZE (1 << 2)
|
||||
#define DPC_SET_FREEZE (1 << 3)
|
||||
#define DPC_CLR_FLUSH (1 << 4)
|
||||
#define DPC_SET_FLUSH (1 << 5)
|
||||
#define DPC_CLR_TMEM_CTR (1 << 6)
|
||||
#define DPC_CLR_PIPE_CTR (1 << 7)
|
||||
#define DPC_CLR_CMD_CTR (1 << 8)
|
||||
#define DPC_CLR_CLOCK_CTR (1 << 9)
|
||||
|
||||
|
||||
u32 osDpGetStatus(void);
|
||||
void osDpSetStatus(u32 data);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef PR_ULTRATYPES_H
|
||||
#define PR_ULTRATYPES_H
|
||||
|
||||
#ifdef _LANGUAGE_C
|
||||
|
||||
typedef signed char s8;
|
||||
typedef unsigned char u8;
|
||||
typedef signed short int s16;
|
||||
|
|
@ -39,3 +41,5 @@ typedef unsigned int size_t;
|
|||
typedef void* TexturePtr;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef PR_VERSION_H
|
||||
#define PR_VERSION_H
|
||||
|
||||
#define LIBULTRA_VERSION_D 'D'
|
||||
#define LIBULTRA_VERSION_E 'E'
|
||||
#define LIBULTRA_VERSION_F 'F'
|
||||
#define LIBULTRA_VERSION_G 'G'
|
||||
#define LIBULTRA_VERSION_H 'H'
|
||||
#define LIBULTRA_VERSION_I 'I'
|
||||
#define LIBULTRA_VERSION_J 'J'
|
||||
#define LIBULTRA_VERSION_K 'K'
|
||||
#define LIBULTRA_VERSION_L 'L'
|
||||
|
||||
#endif
|
||||
|
|
@ -21,7 +21,6 @@
|
|||
.endm
|
||||
|
||||
.macro jlabel label
|
||||
.global \label
|
||||
\label:
|
||||
.endm
|
||||
|
||||
|
|
|
|||
|
|
@ -55,9 +55,8 @@ beginseg
|
|||
include "$(BUILD_DIR)/src/libultra/io/viextendvstart.o"
|
||||
include "$(BUILD_DIR)/src/libultra/os/stopthread.o"
|
||||
include "$(BUILD_DIR)/src/libultra/os/recvmesg.o"
|
||||
include "$(BUILD_DIR)/asm/boot/setintmask.text.o"
|
||||
include "$(BUILD_DIR)/data/boot/setintmask.rodata.o"
|
||||
include "$(BUILD_DIR)/asm/boot/getintmask.text.o"
|
||||
include "$(BUILD_DIR)/src/libultra/os/setintmask.o"
|
||||
include "$(BUILD_DIR)/src/libultra/os/getintmask.o"
|
||||
include "$(BUILD_DIR)/src/libultra/voice/voicesetword.o"
|
||||
include "$(BUILD_DIR)/src/libultra/vimodes/vimodentschpf1.o"
|
||||
include "$(BUILD_DIR)/src/libultra/vimodes/vimodepallan1.o"
|
||||
|
|
@ -66,9 +65,7 @@ beginseg
|
|||
include "$(BUILD_DIR)/src/libultra/gu/sins.o"
|
||||
include "$(BUILD_DIR)/src/libultra/io/sptask.o"
|
||||
include "$(BUILD_DIR)/src/libultra/libc/ll.o"
|
||||
include "$(BUILD_DIR)/asm/boot/exceptasm.text.o"
|
||||
include "$(BUILD_DIR)/data/boot/exceptasm.data.o"
|
||||
include "$(BUILD_DIR)/data/boot/exceptasm.rodata.o"
|
||||
include "$(BUILD_DIR)/src/libultra/os/exceptasm.o"
|
||||
include "$(BUILD_DIR)/src/libultra/os/thread.o"
|
||||
include "$(BUILD_DIR)/src/libultra/os/destroythread.o"
|
||||
include "$(BUILD_DIR)/src/libultra/voice/voicecheckresult.o"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
s32 __osSiDeviceBusy() {
|
||||
register u32 status = IO_READ(SI_STATUS_REG);
|
||||
|
||||
if (status & (SI_STATUS_DMA_BUSY | SI_STATUS_IO_READ_BUSY)) {
|
||||
if (status & (SI_STATUS_DMA_BUSY | SI_STATUS_RD_BUSY)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#include "alignment.h"
|
||||
|
||||
s32 __osSiRawStartDma(s32 direction, void* dramAddr) {
|
||||
if (IO_READ(SI_STATUS_REG) & (SI_STATUS_DMA_BUSY | SI_STATUS_IO_READ_BUSY)) {
|
||||
if (IO_READ(SI_STATUS_REG) & (SI_STATUS_DMA_BUSY | SI_STATUS_RD_BUSY)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,879 @@
|
|||
#ifdef __GNUC__
|
||||
.set gp=64
|
||||
#endif
|
||||
#include "PR/asm.h"
|
||||
#include "PR/regdef.h"
|
||||
#include "PR/R4300.h"
|
||||
#include "PR/rcp.h"
|
||||
#include "PR/os_message.h"
|
||||
#include "PR/os_thread.h"
|
||||
#include "PR/os_exception.h"
|
||||
#include "PR/os_internal.h"
|
||||
#include "PR/version.h"
|
||||
|
||||
#define MESG(x) ((x) << 3)
|
||||
|
||||
.data
|
||||
.align 2
|
||||
|
||||
DATA(__osHwIntTable)
|
||||
.word 0, 0
|
||||
.word 0, 0 /* cart */
|
||||
.word 0, 0
|
||||
.word 0, 0
|
||||
.word 0, 0
|
||||
ENDDATA(__osHwIntTable)
|
||||
|
||||
DATA(__osPiIntTable)
|
||||
.word 0, 0
|
||||
ENDDATA(__osPiIntTable)
|
||||
|
||||
.rdata
|
||||
.align 2
|
||||
|
||||
__osIntOffTable:
|
||||
.byte 0x00 /* redispatch */
|
||||
.byte 0x14 /* prenmi */
|
||||
.byte 0x18 /* IP6_Hdlr */
|
||||
.byte 0x18 /* IP6_Hdlr */
|
||||
.byte 0x1C /* IP7_Hdlr */
|
||||
.byte 0x1C /* IP7_Hdlr */
|
||||
.byte 0x1C /* IP7_Hdlr */
|
||||
.byte 0x1C /* IP7_Hdlr */
|
||||
.byte 0x20 /* counter */
|
||||
.byte 0x20 /* counter */
|
||||
.byte 0x20 /* counter */
|
||||
.byte 0x20 /* counter */
|
||||
.byte 0x20 /* counter */
|
||||
.byte 0x20 /* counter */
|
||||
.byte 0x20 /* counter */
|
||||
.byte 0x20 /* counter */
|
||||
.byte 0x00 /* redispatch */
|
||||
.byte 0x04 /* sw1 */
|
||||
.byte 0x08 /* sw2 */
|
||||
.byte 0x08 /* sw2 */
|
||||
.byte 0x0C /* rcp */
|
||||
.byte 0x0C /* rcp */
|
||||
.byte 0x0C /* rcp */
|
||||
.byte 0x0C /* rcp */
|
||||
.byte 0x10 /* cart */
|
||||
.byte 0x10 /* cart */
|
||||
.byte 0x10 /* cart */
|
||||
.byte 0x10 /* cart */
|
||||
.byte 0x10 /* cart */
|
||||
.byte 0x10 /* cart */
|
||||
.byte 0x10 /* cart */
|
||||
.byte 0x10 /* cart */
|
||||
|
||||
__osIntTable:
|
||||
.word redispatch
|
||||
.word sw1
|
||||
.word sw2
|
||||
.word rcp
|
||||
.word cart
|
||||
.word prenmi
|
||||
.word IP6_Hdlr
|
||||
.word IP7_Hdlr
|
||||
.word counter
|
||||
|
||||
.text
|
||||
|
||||
/**
|
||||
* The 16-byte exception preamble is copied to the exception vectors at
|
||||
* UT_VEC, XUT_VEC, ECC_VEC, E_VEC, to direct execution to __osException
|
||||
*/
|
||||
LEAF(__osExceptionPreamble)
|
||||
la k0, __osException
|
||||
jr k0
|
||||
END(__osExceptionPreamble)
|
||||
|
||||
LEAF(__osException)
|
||||
.set noat
|
||||
/* Load scratch space for thread saving */
|
||||
la k0, __osThreadSave
|
||||
/* Save at */
|
||||
sd AT, THREAD_AT(k0)
|
||||
.set at
|
||||
/* Save sr */
|
||||
MFC0( k1, C0_SR)
|
||||
sw k1, THREAD_SR(k0)
|
||||
/* Disable interrupts */
|
||||
and k1, k1, ~(SR_IE | SR_EXL)
|
||||
MTC0( k1, C0_SR)
|
||||
/* Save some temp registers for use in the following */
|
||||
sd t0, THREAD_T0(k0)
|
||||
sd t1, THREAD_T1(k0)
|
||||
sd t2, THREAD_T2(k0)
|
||||
/* Mark FPU as unused */
|
||||
sw zero, THREAD_FP(k0)
|
||||
/* Left over from misplaced ifdef, immediately overwritten on next instruction */
|
||||
MFC0( t0, C0_CAUSE)
|
||||
savecontext:
|
||||
.set noreorder
|
||||
/* Save the previously running thread's context to be restored when it resumes */
|
||||
move t0, k0
|
||||
lw k0, __osRunningThread
|
||||
ld t1, THREAD_AT(t0)
|
||||
sd t1, THREAD_AT(k0)
|
||||
ld t1, THREAD_SR(t0)
|
||||
sd t1, THREAD_SR(k0)
|
||||
ld t1, THREAD_T0(t0)
|
||||
sd t1, THREAD_T0(k0)
|
||||
ld t1, THREAD_T1(t0)
|
||||
sd t1, THREAD_T1(k0)
|
||||
ld t1, THREAD_T2(t0)
|
||||
sd t1, THREAD_T2(k0)
|
||||
.set reorder
|
||||
sd $2, THREAD_V0(k0)
|
||||
sd $3, THREAD_V1(k0)
|
||||
sd $4, THREAD_A0(k0)
|
||||
sd $5, THREAD_A1(k0)
|
||||
sd $6, THREAD_A2(k0)
|
||||
sd $7, THREAD_A3(k0)
|
||||
sd $11, THREAD_T3(k0)
|
||||
sd $12, THREAD_T4(k0)
|
||||
sd $13, THREAD_T5(k0)
|
||||
sd $14, THREAD_T6(k0)
|
||||
sd $15, THREAD_T7(k0)
|
||||
sd $16, THREAD_S0(k0)
|
||||
sd $17, THREAD_S1(k0)
|
||||
sd $18, THREAD_S2(k0)
|
||||
sd $19, THREAD_S3(k0)
|
||||
sd $20, THREAD_S4(k0)
|
||||
sd $21, THREAD_S5(k0)
|
||||
sd $22, THREAD_S6(k0)
|
||||
sd $23, THREAD_S7(k0)
|
||||
sd $24, THREAD_T8(k0)
|
||||
sd $25, THREAD_T9(k0)
|
||||
sd $28, THREAD_GP(k0)
|
||||
sd $29, THREAD_SP(k0)
|
||||
sd $30, THREAD_S8(k0)
|
||||
sd $31, THREAD_RA(k0)
|
||||
mflo t0
|
||||
sd t0, THREAD_LO(k0)
|
||||
mfhi t0
|
||||
sd t0, THREAD_HI(k0)
|
||||
lw k1, THREAD_SR(k0)
|
||||
andi t1, k1, SR_IMASK
|
||||
beqz t1, savercp
|
||||
/* If any CPU interrupts are enabled in the previous thread's SR, bitwise-OR in the */
|
||||
/* disabled CPU interrupts from the global interrupt mask. */
|
||||
/* This is an attempt at reverting the effect of masking the thread's SR with the */
|
||||
/* global interrupt mask. This is however broken, see comments for osSetIntMask. */
|
||||
la t0, __OSGlobalIntMask
|
||||
lw t0, (t0)
|
||||
xor t2, t0, 0xFFFFFFFF
|
||||
andi t2, t2, SR_IMASK
|
||||
or t4, t1, t2
|
||||
and t3, k1, ~SR_IMASK
|
||||
or t3, t3, t4
|
||||
sw t3, THREAD_SR(k0)
|
||||
andi t0, t0, SR_IMASK
|
||||
and t1, t1, t0
|
||||
and k1, k1, ~SR_IMASK
|
||||
or k1, k1, t1
|
||||
savercp:
|
||||
/* Save the currently masked RCP interrupts. */
|
||||
lw t1, PHYS_TO_K1(MI_INTR_MASK_REG)
|
||||
beqz t1, endrcp
|
||||
/* Similar to the above comment, but for RCP interrupt enable bits rather than CPU. */
|
||||
/* This suffers from the same problem as above. */
|
||||
la t0, __OSGlobalIntMask
|
||||
lw t0, (t0)
|
||||
srl t0, t0, RCP_IMASKSHIFT
|
||||
xor t0, t0, 0xFFFFFFFF
|
||||
andi t0, t0, (RCP_IMASK >> RCP_IMASKSHIFT)
|
||||
lw t4, THREAD_RCP(k0)
|
||||
and t0, t0, t4
|
||||
or t1, t1, t0
|
||||
endrcp:
|
||||
sw t1, THREAD_RCP(k0)
|
||||
MFC0( t0, C0_EPC)
|
||||
sw t0, THREAD_PC(k0)
|
||||
lw t0, THREAD_FP(k0)
|
||||
beqz t0, handle_interrupt
|
||||
/* Save FP Registers if FPU was used by the thread */
|
||||
.set noreorder
|
||||
cfc1 t0, C1_FPCSR
|
||||
nop
|
||||
sw t0, THREAD_FPCSR(k0)
|
||||
.set reorder
|
||||
sdc1 $f0, THREAD_FP0(k0)
|
||||
sdc1 $f2, THREAD_FP2(k0)
|
||||
sdc1 $f4, THREAD_FP4(k0)
|
||||
sdc1 $f6, THREAD_FP6(k0)
|
||||
sdc1 $f8, THREAD_FP8(k0)
|
||||
sdc1 $f10, THREAD_FP10(k0)
|
||||
sdc1 $f12, THREAD_FP12(k0)
|
||||
sdc1 $f14, THREAD_FP14(k0)
|
||||
sdc1 $f16, THREAD_FP16(k0)
|
||||
sdc1 $f18, THREAD_FP18(k0)
|
||||
sdc1 $f20, THREAD_FP20(k0)
|
||||
sdc1 $f22, THREAD_FP22(k0)
|
||||
sdc1 $f24, THREAD_FP24(k0)
|
||||
sdc1 $f26, THREAD_FP26(k0)
|
||||
sdc1 $f28, THREAD_FP28(k0)
|
||||
sdc1 $f30, THREAD_FP30(k0)
|
||||
|
||||
handle_interrupt:
|
||||
/* Determine the cause of the exception or interrupt and */
|
||||
/* enter appropriate handling routine */
|
||||
MFC0( t0, C0_CAUSE)
|
||||
sw t0, THREAD_CAUSE(k0)
|
||||
label:
|
||||
li t1, OS_STATE_RUNNABLE
|
||||
sh t1, THREAD_STATE(k0)
|
||||
andi t1, t0, CAUSE_EXCMASK
|
||||
/* Test for break exception */
|
||||
li t2, EXC_BREAK
|
||||
beq t1, t2, handle_break
|
||||
/* Test for CpU (coprocessor unusable) exception */
|
||||
li t2, EXC_CPU
|
||||
beq t1, t2, handle_CpU
|
||||
/* Test for interrupt, if it's not an interrupt, panic */
|
||||
li t2, EXC_INT
|
||||
bne t1, t2, panic
|
||||
|
||||
and s0, k1, t0
|
||||
|
||||
next_interrupt:
|
||||
/* Handle external interrupt causes, using a jump table */
|
||||
/* to enter into the appropriate handler */
|
||||
andi t1, s0, CAUSE_IPMASK
|
||||
srl t2, t1, CAUSE_IPSHIFT + 4
|
||||
bnez t2, 1f
|
||||
|
||||
srl t2, t1, CAUSE_IPSHIFT
|
||||
addi t2, t2, 0x10
|
||||
1:
|
||||
lbu t2, __osIntOffTable(t2)
|
||||
lw t2, __osIntTable(t2)
|
||||
jr t2
|
||||
|
||||
/**
|
||||
* IP6 Interrupt
|
||||
* Only signalled by development hardware
|
||||
*/
|
||||
IP6_Hdlr:
|
||||
/* Mask out interrupt and continue */
|
||||
and s0, s0, ~CAUSE_IP6
|
||||
b next_interrupt
|
||||
|
||||
/**
|
||||
* IP7 Interrupt
|
||||
* Only signalled by development hardware
|
||||
*/
|
||||
IP7_Hdlr:
|
||||
/* Mask out interrupt and continue */
|
||||
and s0, s0, ~CAUSE_IP7
|
||||
b next_interrupt
|
||||
|
||||
/**
|
||||
* IP8/Counter Interrupt
|
||||
* Once the cop0 count register reaches the value of the
|
||||
* cop0 compare register, this interrupt is triggered
|
||||
*/
|
||||
counter:
|
||||
MFC0( t1, C0_COMPARE)
|
||||
MTC0( t1, C0_COMPARE)
|
||||
/* Post counter message */
|
||||
li a0, MESG(OS_EVENT_COUNTER)
|
||||
jal send_mesg
|
||||
/* Mask out interrupt and continue */
|
||||
and s0, s0, ~CAUSE_IP8
|
||||
b next_interrupt
|
||||
|
||||
/**
|
||||
* IP4/Cartridge Interrupt
|
||||
* Signalled by the N64 Disk Drive
|
||||
*/
|
||||
cart:
|
||||
/* Mask out interrupt */
|
||||
and s0, s0, ~CAUSE_IP4
|
||||
/* Load cart callback set by __osSetHWIntrRoutine */
|
||||
la t1, __osHwIntTable
|
||||
addi t1, t1, (OS_INTR_CART * HWINT_SIZE)
|
||||
lw t2, HWINT_CALLBACK(t1)
|
||||
/* If the callback is NULL, handling is done */
|
||||
beqz t2, 1f
|
||||
/* Set up a stack and run the callback */
|
||||
lw sp, HWINT_SP(t1)
|
||||
jalr t2
|
||||
beqz v0, 1f
|
||||
/* Redispatch immediately if the callback returned nonzero */
|
||||
b redispatch
|
||||
1:
|
||||
/* Post a cart event message */
|
||||
li a0, MESG(OS_EVENT_CART)
|
||||
jal send_mesg
|
||||
/* Continue */
|
||||
b next_interrupt
|
||||
|
||||
/**
|
||||
* IP3/RCP Interrupt
|
||||
* Signalled by the RCP for various reasons, described below
|
||||
*/
|
||||
rcp:
|
||||
/* Load the MI interrupts and mask with the RCP bits in the global interrupt mask */
|
||||
/*! @bug this clobbers the t0 register which is expected to hold the value of the */
|
||||
/*! C0_CAUSE register in the sw1 and sw2 handlers. If the sw1 or sw2 handler runs */
|
||||
/*! after this, the interrupt will not be cleared properly. */
|
||||
lw s1, PHYS_TO_K1(MI_INTR_REG)
|
||||
la t0, __OSGlobalIntMask
|
||||
lw t0, (t0)
|
||||
srl t0, t0, RCP_IMASKSHIFT
|
||||
and s1, s1, t0
|
||||
|
||||
/**
|
||||
* Signal Processor (SP) Interrupt
|
||||
*/
|
||||
/* Test for sp interrupt */
|
||||
andi t1, s1, MI_INTR_SP
|
||||
beqz t1, vi
|
||||
/* Mask out SP interrupt */
|
||||
andi s1, s1, (MI_INTR_SI | MI_INTR_AI | MI_INTR_VI | MI_INTR_PI | MI_INTR_DP)
|
||||
lw t4, PHYS_TO_K1(SP_STATUS_REG)
|
||||
/* Clear interrupt and signal 3 */
|
||||
li t1, (SP_CLR_INTR | SP_CLR_SIG3)
|
||||
sw t1, PHYS_TO_K1(SP_STATUS_REG)
|
||||
/* Test for yielded or done signals in particular */
|
||||
andi t4, t4, (SP_STATUS_YIELDED | SP_STATUS_TASKDONE)
|
||||
beqz t4, sp_other_break
|
||||
/* Post an SP event message */
|
||||
li a0, MESG(OS_EVENT_SP)
|
||||
jal send_mesg
|
||||
beqz s1, NoMoreRcpInts
|
||||
/* Step over sp_other_break handler */
|
||||
b vi
|
||||
|
||||
sp_other_break:
|
||||
/* An sp signal that is not due to yielding or task completion, such as */
|
||||
/* an sp breakpoint. Post a different event message */
|
||||
li a0, MESG(OS_EVENT_SP_BREAK)
|
||||
jal send_mesg
|
||||
beqz s1, NoMoreRcpInts
|
||||
|
||||
/**
|
||||
* Video Interface (VI) Interrupt
|
||||
*/
|
||||
vi:
|
||||
/* Test for vi interrupt */
|
||||
andi t1, s1, MI_INTR_VI
|
||||
beqz t1, ai
|
||||
/* Mask out vi interrupt */
|
||||
andi s1, s1, (MI_INTR_SP | MI_INTR_SI | MI_INTR_AI | MI_INTR_PI | MI_INTR_DP)
|
||||
/* Clear interrupt */
|
||||
sw zero, PHYS_TO_K1(VI_CURRENT_REG)
|
||||
/* Post vi event message */
|
||||
li a0, MESG(OS_EVENT_VI)
|
||||
jal send_mesg
|
||||
beqz s1, NoMoreRcpInts
|
||||
|
||||
/**
|
||||
* Audio Interface (AI) Interrupt
|
||||
*/
|
||||
ai:
|
||||
/* Test for ai interrupt */
|
||||
andi t1, s1, MI_INTR_AI
|
||||
beqz t1, si
|
||||
|
||||
/* Mask out ai interrupt */
|
||||
andi s1, s1, (MI_INTR_SP | MI_INTR_SI | MI_INTR_VI | MI_INTR_PI | MI_INTR_DP)
|
||||
/* Clear interrupt */
|
||||
li t1, 1
|
||||
sw t1, PHYS_TO_K1(AI_STATUS_REG)
|
||||
/* Post ai event message */
|
||||
li a0, MESG(OS_EVENT_AI)
|
||||
jal send_mesg
|
||||
beqz s1, NoMoreRcpInts
|
||||
|
||||
/**
|
||||
* Serial Interface (SI) Interrupt
|
||||
*/
|
||||
si:
|
||||
/* Test for si interrupt */
|
||||
andi t1, s1, MI_INTR_SI
|
||||
beqz t1, pi
|
||||
|
||||
/* Mask out si interrupt */
|
||||
andi s1, s1, (MI_INTR_SP | MI_INTR_AI | MI_INTR_VI | MI_INTR_PI | MI_INTR_DP)
|
||||
/* Clear interrupt */
|
||||
sw zero, PHYS_TO_K1(SI_STATUS_REG)
|
||||
/* Post si event message */
|
||||
li a0, MESG(OS_EVENT_SI)
|
||||
jal send_mesg
|
||||
beqz s1, NoMoreRcpInts
|
||||
|
||||
/**
|
||||
* Parallel Interface (PI) Interrupt
|
||||
*/
|
||||
pi:
|
||||
/* Test for pi interrupt */
|
||||
andi t1, s1, MI_INTR_PI
|
||||
beqz t1, dp
|
||||
|
||||
/* Mask out pi interrupt */
|
||||
andi s1, s1, (MI_INTR_SP | MI_INTR_SI | MI_INTR_AI | MI_INTR_VI | MI_INTR_DP)
|
||||
/* Clear the interrupt */
|
||||
li t1, PI_STATUS_CLR_INTR
|
||||
sw t1, PHYS_TO_K1(PI_STATUS_REG)
|
||||
/* Load pi callback */
|
||||
la t1, __osPiIntTable
|
||||
lw t2, HWINT_CALLBACK(t1)
|
||||
/* Skip callback if NULL */
|
||||
beqz t2, no_pi_callback
|
||||
/* Set up a stack and run the callback */
|
||||
lw sp, HWINT_SP(t1)
|
||||
move a0, v0
|
||||
jalr t2
|
||||
/* If the callback returns non-zero, don't post a pi event message */
|
||||
bnez v0, skip_pi_mesg
|
||||
no_pi_callback:
|
||||
/* Post pi event message */
|
||||
li a0, MESG(OS_EVENT_PI)
|
||||
jal send_mesg
|
||||
skip_pi_mesg:
|
||||
beqz s1, NoMoreRcpInts
|
||||
|
||||
/**
|
||||
* Display Processor (DP) Interrupt
|
||||
*/
|
||||
dp:
|
||||
/* Test for dp interrupt */
|
||||
andi t1, s1, MI_INTR_DP
|
||||
beqz t1, NoMoreRcpInts
|
||||
|
||||
/* Mask out dp interrupt */
|
||||
andi s1, s1, (MI_INTR_SP | MI_INTR_SI | MI_INTR_AI | MI_INTR_VI | MI_INTR_PI)
|
||||
/* Clear dp interrupt */
|
||||
li t1, MI_CLR_DP_INTR
|
||||
sw t1, PHYS_TO_K1(MI_INIT_MODE_REG)
|
||||
/* Post dp event message */
|
||||
li a0, MESG(OS_EVENT_DP)
|
||||
jal send_mesg
|
||||
|
||||
NoMoreRcpInts:
|
||||
/* Mask out interrupt and continue */
|
||||
and s0, s0, ~CAUSE_IP3
|
||||
b next_interrupt
|
||||
|
||||
/**
|
||||
* IP5/PreNMI Interrupt
|
||||
* Reset button has been pressed
|
||||
*/
|
||||
prenmi:
|
||||
/* Disable IP5/PreNMI interrupt for the previously running thread */
|
||||
lw k1, THREAD_SR(k0)
|
||||
and k1, k1, ~SR_IBIT5
|
||||
sw k1, THREAD_SR(k0)
|
||||
/* Test __osShutdown for first PreNMI event */
|
||||
la t1, __osShutdown
|
||||
lw t2, (t1)
|
||||
beqz t2, firstnmi
|
||||
/* Mask out interrupt and redispatch immediately */
|
||||
and s0, s0, ~CAUSE_IP5
|
||||
b redispatch
|
||||
|
||||
firstnmi:
|
||||
/* Set __osShutdown */
|
||||
li t2, 1
|
||||
sw t2, (t1)
|
||||
/* Post a PreNMI event message */
|
||||
li a0, MESG(OS_EVENT_PRENMI)
|
||||
jal send_mesg
|
||||
/* Mask out and disable IP5/PreNMI interrupt for the highest priority thread */
|
||||
and s0, s0, ~SR_IBIT5
|
||||
lw t2, __osRunQueue
|
||||
lw k1, THREAD_SR(t2)
|
||||
and k1, k1, ~SR_IBIT5
|
||||
sw k1, THREAD_SR(t2)
|
||||
/* Redispatch immediately */
|
||||
b redispatch
|
||||
|
||||
sw2:
|
||||
/* Mask out interrupt */
|
||||
and t0, t0, ~CAUSE_SW2
|
||||
MTC0( t0, C0_CAUSE)
|
||||
/* Post sw2 event message */
|
||||
li a0, MESG(OS_EVENT_SW2)
|
||||
jal send_mesg
|
||||
/* Mask out interrupt and continue */
|
||||
and s0, s0, ~CAUSE_SW2
|
||||
b next_interrupt
|
||||
|
||||
sw1:
|
||||
/* Mask out interrupt */
|
||||
and t0, t0, ~CAUSE_SW1
|
||||
MTC0( t0, C0_CAUSE)
|
||||
/* Post sw1 event message */
|
||||
li a0, MESG(OS_EVENT_SW1)
|
||||
jal send_mesg
|
||||
/* Mask out interrupt and continue */
|
||||
and s0, s0, ~CAUSE_SW1
|
||||
b next_interrupt
|
||||
|
||||
handle_break:
|
||||
/* Set last thread as having hit a break exception */
|
||||
li t1, OS_FLAG_CPU_BREAK
|
||||
sh t1, THREAD_FLAGS(k0)
|
||||
/* Post a cpu break event message */
|
||||
li a0, MESG(OS_EVENT_CPU_BREAK)
|
||||
jal send_mesg
|
||||
/* Redispatch */
|
||||
b redispatch
|
||||
|
||||
redispatch:
|
||||
/* Get priority of previously running thread */
|
||||
lw t1, THREAD_PRI(k0)
|
||||
lw t2, __osRunQueue
|
||||
/* Get highest priority from waiting threads */
|
||||
lw t3, THREAD_PRI(t2)
|
||||
bge t1, t3, enqueueRunning
|
||||
/* The previously running thread is no longer the highest priority, */
|
||||
/* enqueue it to the run queue to wait its turn again */
|
||||
move a1, k0
|
||||
la a0, __osRunQueue
|
||||
jal __osEnqueueThread
|
||||
|
||||
j __osDispatchThread
|
||||
|
||||
/**
|
||||
* Resume the previously running thread by placing it at the top of
|
||||
* the run queue and dispatching it
|
||||
*/
|
||||
enqueueRunning:
|
||||
la t1, __osRunQueue
|
||||
lw t2, (t1)
|
||||
sw t2, THREAD_NEXT(k0)
|
||||
sw k0, (t1)
|
||||
j __osDispatchThread
|
||||
|
||||
/**
|
||||
* Unhandled exceptions & interrupts end up here,
|
||||
* trap to software by posting a fault message
|
||||
*/
|
||||
panic:
|
||||
/* Mark the thread as having faulted */
|
||||
sw k0, __osFaultedThread
|
||||
li t1, OS_STATE_STOPPED
|
||||
sh t1, THREAD_STATE(k0)
|
||||
li t1, OS_FLAG_FAULT
|
||||
sh t1, THREAD_FLAGS(k0)
|
||||
/* Save C0_BADVADDR */
|
||||
MFC0( t2, C0_BADVADDR)
|
||||
sw t2, THREAD_BADVADDR(k0)
|
||||
/* Post the fault message */
|
||||
li a0, MESG(OS_EVENT_FAULT)
|
||||
jal send_mesg
|
||||
/* Dispatch next thread */
|
||||
j __osDispatchThread
|
||||
|
||||
/**
|
||||
* Handles posting event messages to the listening message queue, if there is one
|
||||
*/
|
||||
send_mesg:
|
||||
/* Save return address */
|
||||
move s2, ra
|
||||
/* Load pointer to listening message queue */
|
||||
la t2, __osEventStateTab
|
||||
addu t2, t2, a0
|
||||
lw t1, (t2)
|
||||
/* If there is no listening message queue, done */
|
||||
beqz t1, send_done
|
||||
|
||||
/* Test if the message queue is full, if so don't post the message */
|
||||
lw t3, MQ_VALIDCOUNT(t1)
|
||||
lw t4, MQ_MSGCOUNT(t1)
|
||||
bge t3, t4, send_done
|
||||
|
||||
/* Add validcount to first and modulo with msgcount */
|
||||
lw t5, MQ_FIRST(t1)
|
||||
addu t5, t5, t3
|
||||
rem t5, t5, t4
|
||||
lw t4, MQ_MSG(t1)
|
||||
mul t5, t5, 4
|
||||
addu t4, t4, t5
|
||||
/* Post the message to the message queue */
|
||||
lw t5, 4(t2)
|
||||
sw t5, (t4)
|
||||
/* Increment the validCount */
|
||||
addiu t2, t3, 1
|
||||
sw t2, MQ_VALIDCOUNT(t1)
|
||||
/* If there was a thread blocked on this message queue, */
|
||||
/* wake it up */
|
||||
lw t2, MQ_MTQUEUE(t1)
|
||||
lw t3, (t2)
|
||||
beqz t3, send_done
|
||||
move a0, t1
|
||||
jal __osPopThread
|
||||
move t2, v0
|
||||
move a1, t2
|
||||
la a0, __osRunQueue
|
||||
jal __osEnqueueThread
|
||||
send_done:
|
||||
jr s2
|
||||
|
||||
/**
|
||||
* Handle coprocessor unusable exception
|
||||
*/
|
||||
handle_CpU:
|
||||
and t1, t0, CAUSE_CEMASK
|
||||
srl t1, t1, CAUSE_CESHIFT
|
||||
li t2, 1 /* if not coprocessor 1, panic */
|
||||
bne t1, t2, panic
|
||||
/* Mark cop1 as usable for previous thread */
|
||||
li t1, 1
|
||||
sw t1, THREAD_FP(k0)
|
||||
lw k1, THREAD_SR(k0)
|
||||
or k1, k1, SR_CU1
|
||||
sw k1, THREAD_SR(k0)
|
||||
b enqueueRunning
|
||||
END(__osException)
|
||||
|
||||
/**
|
||||
* void __osEnqueueAndYield(OSThread** threadQueue);
|
||||
*
|
||||
* Voluntary thread yielding.
|
||||
* Enqueues the currently running thread to the top of the
|
||||
* thread queue `threadQueue` and yields to the highest priority
|
||||
* unblocked runnable thread.
|
||||
*/
|
||||
LEAF(__osEnqueueAndYield)
|
||||
lw a1, __osRunningThread
|
||||
/* Save SR */
|
||||
MFC0( t0, C0_SR)
|
||||
ori t0, t0, SR_EXL
|
||||
sw t0, THREAD_SR(a1)
|
||||
/* Save callee-saved registers */
|
||||
sd s0, THREAD_S0(a1)
|
||||
sd s1, THREAD_S1(a1)
|
||||
sd s2, THREAD_S2(a1)
|
||||
sd s3, THREAD_S3(a1)
|
||||
sd s4, THREAD_S4(a1)
|
||||
sd s5, THREAD_S5(a1)
|
||||
sd s6, THREAD_S6(a1)
|
||||
sd s7, THREAD_S7(a1)
|
||||
sd gp, THREAD_GP(a1)
|
||||
sd sp, THREAD_SP(a1)
|
||||
sd fp, THREAD_S8(a1)
|
||||
sd ra, THREAD_RA(a1)
|
||||
sw ra, THREAD_PC(a1)
|
||||
/* Save FPU callee-saved registers if the current thread has used the FPU */
|
||||
lw k1, THREAD_FP(a1)
|
||||
beqz k1, 1f
|
||||
cfc1 k1, C1_FPCSR
|
||||
sw k1, THREAD_FPCSR(a1)
|
||||
sdc1 $f20, THREAD_FP20(a1)
|
||||
sdc1 $f22, THREAD_FP22(a1)
|
||||
sdc1 $f24, THREAD_FP24(a1)
|
||||
sdc1 $f26, THREAD_FP26(a1)
|
||||
sdc1 $f28, THREAD_FP28(a1)
|
||||
sdc1 $f30, THREAD_FP30(a1)
|
||||
1:
|
||||
lw k1, THREAD_SR(a1)
|
||||
andi t1, k1, SR_IMASK
|
||||
beqz t1, 2f
|
||||
/* This code does the same thing as the block just above the `savercp` label. */
|
||||
/* See the comment there for more about this. */
|
||||
la t0, __OSGlobalIntMask
|
||||
lw t0, (t0)
|
||||
xor t0, t0, 0xFFFFFFFF
|
||||
andi t0, t0, SR_IMASK
|
||||
or t1, t1, t0
|
||||
and k1, k1, ~SR_IMASK
|
||||
or k1, k1, t1
|
||||
sw k1, THREAD_SR(a1)
|
||||
2:
|
||||
lw k1, PHYS_TO_K1(MI_INTR_MASK_REG)
|
||||
beqz k1, 3f
|
||||
/* This code does the same thing as the block just below the `savercp` label. */
|
||||
/* See the comment there for more about this. */
|
||||
la k0, __OSGlobalIntMask
|
||||
lw k0, (k0)
|
||||
srl k0, k0, RCP_IMASKSHIFT
|
||||
xor k0, k0, 0xFFFFFFFF
|
||||
andi k0, k0, (RCP_IMASK >> RCP_IMASKSHIFT)
|
||||
lw t0, THREAD_RCP(a1)
|
||||
and k0, k0, t0
|
||||
or k1, k1, k0
|
||||
3:
|
||||
/* If the specified thread queue is null, skip */
|
||||
/* straight to dispatching */
|
||||
sw k1, THREAD_RCP(a1)
|
||||
beqz a0, no_enqueue
|
||||
jal __osEnqueueThread
|
||||
no_enqueue:
|
||||
j __osDispatchThread
|
||||
END(__osEnqueueAndYield)
|
||||
|
||||
/**
|
||||
* void __osEnqueueThread(OSThread** threadQueue, OSThread* thread);
|
||||
*
|
||||
* Enqueues `thread` to the thread queue `threadQueue`, inserted by priority
|
||||
*/
|
||||
LEAF(__osEnqueueThread)
|
||||
move t9, a0
|
||||
lw t8, (a0)
|
||||
lw t7, THREAD_PRI(a1)
|
||||
lw t6, THREAD_PRI(t8)
|
||||
/* If the current highest priority thread is a lower priority than */
|
||||
/* the new thread, skip searching the queue */
|
||||
blt t6, t7, 2f
|
||||
1:
|
||||
/* Search the queue for the position to insert the thread to maintain */
|
||||
/* ordering by priority */
|
||||
move t9, t8
|
||||
lw t8, THREAD_NEXT(t8)
|
||||
lw t6, THREAD_PRI(t8)
|
||||
bge t6, t7, 1b
|
||||
2:
|
||||
/* Insert the thread into the queue */
|
||||
lw t8, (t9)
|
||||
sw t8, THREAD_NEXT(a1)
|
||||
sw a1, (t9)
|
||||
sw a0, THREAD_QUEUE(a1)
|
||||
jr ra
|
||||
END(__osEnqueueThread)
|
||||
|
||||
/**
|
||||
* OSThread* __osPopThread(OSThread** threadQueue);
|
||||
*
|
||||
* Pops the highest priority thread from the top of the
|
||||
* thread queue `threadQueue` and returns it
|
||||
*/
|
||||
LEAF(__osPopThread)
|
||||
lw v0, (a0)
|
||||
lw t9, THREAD_NEXT(v0)
|
||||
sw t9, (a0)
|
||||
jr ra
|
||||
END(__osPopThread)
|
||||
|
||||
LEAF(__osNop)
|
||||
jr ra
|
||||
END(__osNop)
|
||||
|
||||
/**
|
||||
* void __osDispatchThread(void);
|
||||
*
|
||||
* Dispatches the next thread to run after restoring the context
|
||||
*/
|
||||
LEAF(__osDispatchThread)
|
||||
/* Obtain highest priority thread from the active run queue */
|
||||
la a0, __osRunQueue
|
||||
jal __osPopThread
|
||||
/* Set thread as running */
|
||||
sw v0, __osRunningThread
|
||||
li t0, OS_STATE_RUNNING
|
||||
sh t0, THREAD_STATE(v0)
|
||||
/* Restore SR, masking out any interrupts that are not also */
|
||||
/* enabled in the global interrupt mask */
|
||||
move k0, v0
|
||||
lw k1, THREAD_SR(k0)
|
||||
la t0, __OSGlobalIntMask
|
||||
lw t0, (t0)
|
||||
andi t0, t0, SR_IMASK
|
||||
andi t1, k1, SR_IMASK
|
||||
and t1, t1, t0
|
||||
and k1, k1, ~SR_IMASK
|
||||
or k1, k1, t1
|
||||
MTC0( k1, C0_SR)
|
||||
/* Restore GPRs */
|
||||
.set noat
|
||||
ld AT, THREAD_AT(k0)
|
||||
ld v0, THREAD_V0(k0)
|
||||
ld v1, THREAD_V1(k0)
|
||||
ld a0, THREAD_A0(k0)
|
||||
ld a1, THREAD_A1(k0)
|
||||
ld a2, THREAD_A2(k0)
|
||||
ld a3, THREAD_A3(k0)
|
||||
ld t0, THREAD_T0(k0)
|
||||
ld t1, THREAD_T1(k0)
|
||||
ld t2, THREAD_T2(k0)
|
||||
ld t3, THREAD_T3(k0)
|
||||
ld t4, THREAD_T4(k0)
|
||||
ld t5, THREAD_T5(k0)
|
||||
ld t6, THREAD_T6(k0)
|
||||
ld t7, THREAD_T7(k0)
|
||||
ld s0, THREAD_S0(k0)
|
||||
ld s1, THREAD_S1(k0)
|
||||
ld s2, THREAD_S2(k0)
|
||||
ld s3, THREAD_S3(k0)
|
||||
ld s4, THREAD_S4(k0)
|
||||
ld s5, THREAD_S5(k0)
|
||||
ld s6, THREAD_S6(k0)
|
||||
ld s7, THREAD_S7(k0)
|
||||
ld t8, THREAD_T8(k0)
|
||||
ld t9, THREAD_T9(k0)
|
||||
ld gp, THREAD_GP(k0)
|
||||
ld sp, THREAD_SP(k0)
|
||||
ld fp, THREAD_S8(k0)
|
||||
ld ra, THREAD_RA(k0)
|
||||
ld k1, THREAD_LO(k0)
|
||||
mtlo k1
|
||||
ld k1, THREAD_HI(k0)
|
||||
mthi k1
|
||||
/* Move thread pc to EPC so that eret will return execution to where the thread left off */
|
||||
lw k1, THREAD_PC(k0)
|
||||
MTC0( k1, C0_EPC)
|
||||
/* Check if the FPU was used by this thread and if so also restore the FPU registers */
|
||||
lw k1, THREAD_FP(k0)
|
||||
beqz k1, 1f
|
||||
|
||||
.set noreorder
|
||||
lw k1, THREAD_FPCSR(k0)
|
||||
ctc1 k1, C1_FPCSR
|
||||
.set reorder
|
||||
ldc1 $f0, THREAD_FP0(k0)
|
||||
ldc1 $f2, THREAD_FP2(k0)
|
||||
ldc1 $f4, THREAD_FP4(k0)
|
||||
ldc1 $f6, THREAD_FP6(k0)
|
||||
ldc1 $f8, THREAD_FP8(k0)
|
||||
ldc1 $f10, THREAD_FP10(k0)
|
||||
ldc1 $f12, THREAD_FP12(k0)
|
||||
ldc1 $f14, THREAD_FP14(k0)
|
||||
ldc1 $f16, THREAD_FP16(k0)
|
||||
ldc1 $f18, THREAD_FP18(k0)
|
||||
ldc1 $f20, THREAD_FP20(k0)
|
||||
ldc1 $f22, THREAD_FP22(k0)
|
||||
ldc1 $f24, THREAD_FP24(k0)
|
||||
ldc1 $f26, THREAD_FP26(k0)
|
||||
ldc1 $f28, THREAD_FP28(k0)
|
||||
ldc1 $f30, THREAD_FP30(k0)
|
||||
1:
|
||||
/* Restore RCP interrupt mask, masking out any RCP interrupts that */
|
||||
/* are not also enabled in the global interrupt mask */
|
||||
.set noreorder
|
||||
lw k1, THREAD_RCP(k0)
|
||||
la k0, __OSGlobalIntMask
|
||||
lw k0, (k0)
|
||||
srl k0, k0, RCP_IMASKSHIFT
|
||||
and k1, k1, k0
|
||||
sll k1, k1, 1
|
||||
la k0, __osRcpImTable
|
||||
addu k1, k1, k0
|
||||
lhu k1, (k1)
|
||||
la k0, PHYS_TO_K1(MI_INTR_MASK_REG)
|
||||
sw k1, (k0)
|
||||
/* Empty pipeline */
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
/* Resume thread execution */
|
||||
eret
|
||||
.set reorder
|
||||
.set at
|
||||
END(__osDispatchThread)
|
||||
|
||||
/**
|
||||
* void __osCleanupThread(void);
|
||||
*
|
||||
* When a thread entrypoint function returns, it returns to this function.
|
||||
* This function is responsible for cleaning up the thread, signalling for the
|
||||
* current thread to be destroyed.
|
||||
*/
|
||||
LEAF(__osCleanupThread)
|
||||
move a0, zero
|
||||
jal osDestroyThread
|
||||
/* Despite being a jal, this function does not return as the thread will have been destroyed */
|
||||
END(__osCleanupThread)
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
#include "PR/asm.h"
|
||||
#include "PR/regdef.h"
|
||||
#include "PR/R4300.h"
|
||||
#include "PR/rcp.h"
|
||||
#include "PR/os_exception.h"
|
||||
|
||||
.text
|
||||
|
||||
/**
|
||||
* OSIntMask osGetIntMask(void);
|
||||
*
|
||||
* Gets the interrupt enable mask for the current thread.
|
||||
* Interrupts that are not enabled in the global interrupt mask __OSGlobalIntMask
|
||||
* are not returned here. The global interrupt mask is OS-internal and is not
|
||||
* expected to change during runtime.
|
||||
*
|
||||
* @bug Some usage of the global interrupt mask is broken both in the
|
||||
* get/set interrupt mask routines and in the exception handler routines.
|
||||
* See the comment for osSetIntMask for more details.
|
||||
*/
|
||||
LEAF(osGetIntMask)
|
||||
.set noreorder
|
||||
/* Extract interrupt enable bits from current SR */
|
||||
mfc0 v0, C0_SR
|
||||
andi v0, v0, (SR_IMASK | SR_IE)
|
||||
/* Get value of __OSGlobalIntMask */
|
||||
la t0, __OSGlobalIntMask
|
||||
lw t1, (t0)
|
||||
/* Bitwise-OR in the disabled CPU bits of __OSGlobalIntMask */
|
||||
xor t0, t1, ~0
|
||||
andi t0, t0, SR_IMASK
|
||||
or v0, v0, t0
|
||||
/* Fetch MI_INTR_MASK_REG */
|
||||
lw t1, PHYS_TO_K1(MI_INTR_MASK_REG)
|
||||
/* If there are RCP interrupts masked */
|
||||
beqz t1, 1f
|
||||
/* Get value of __OSGlobalIntMask */
|
||||
la t0, __OSGlobalIntMask /* Note: macro expansion in delay slot */
|
||||
lw t0, (t0)
|
||||
/* Bitwise-OR in the disabled RCP bits of __OSGlobalIntMask */
|
||||
srl t0, t0, RCP_IMASKSHIFT
|
||||
xor t0, t0, ~0
|
||||
andi t0, t0, (RCP_IMASK >> RCP_IMASKSHIFT)
|
||||
or t1, t1, t0
|
||||
1:
|
||||
/* Shift the RCP bits to not conflict with the CPU bits */
|
||||
sll t2, t1, RCP_IMASKSHIFT
|
||||
/* OR the CPU and RCP bits together */
|
||||
or v0, v0, t2
|
||||
jr ra
|
||||
nop
|
||||
.set reorder
|
||||
END(osGetIntMask)
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
#include "PR/asm.h"
|
||||
#include "PR/regdef.h"
|
||||
#include "PR/R4300.h"
|
||||
#include "PR/rcp.h"
|
||||
#include "PR/os_exception.h"
|
||||
|
||||
.rdata
|
||||
.align 2
|
||||
|
||||
/**
|
||||
* LUT to convert between an interrupt mask value and a value for MI_INTR_MASK_REG.
|
||||
* The interrupt mask value is a single bit 0 = disabled, 1 = enabled, while writes to MI_INTR_MASK_REG has two distinct non-zero
|
||||
* values for set and clear, hence the need for a conversion step.
|
||||
*/
|
||||
DATA(__osRcpImTable)
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_CLR_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_CLR_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_CLR_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_CLR_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_CLR_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_CLR_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP
|
||||
.half MI_INTR_MASK_SET_SP | MI_INTR_MASK_SET_SI | MI_INTR_MASK_SET_AI | MI_INTR_MASK_SET_VI | MI_INTR_MASK_SET_PI | MI_INTR_MASK_SET_DP
|
||||
ENDDATA(__osRcpImTable)
|
||||
|
||||
.text
|
||||
|
||||
/**
|
||||
* OSIntMask osSetIntMask(OSIntMask);
|
||||
*
|
||||
* Sets the interrupt enable mask for the current thread. External interrupts
|
||||
* originating either in the CPU or the RCP may be "masked out" so that they
|
||||
* are not handled. This is sometimes important for critical code sections
|
||||
* that must not be interrupted.
|
||||
* Interrupts that are not enabled in the global interrupt mask __OSGlobalIntMask
|
||||
* cannot be set here. The global interrupt mask is OS-internal and is not
|
||||
* expected to change during runtime.
|
||||
* The returned value is the previous interrupt enable mask so that it can be
|
||||
* restored later.
|
||||
*
|
||||
* @bug Some usage of the global interrupt mask is broken both in the
|
||||
* get/set interrupt mask routines and in the exception handler routines.
|
||||
* While a thread is running, the C0_SR interrupt enable bits contain the
|
||||
* interrupt enable bits for the current thread masked by the global
|
||||
* interrupt mask. There is an attempt to recover only the original interrupt
|
||||
* enable bits belonging to the thread itself using the operation
|
||||
* (SR | ~__OSGlobalIntMask).
|
||||
* However, this does not work as intended and can cause interrupts to end
|
||||
* up enabled when not intended to be. The same issue is present for the
|
||||
* RCP interrupt enable bits in MI_INTR_MASK_REG.
|
||||
* This does not cause issues in practice as __OSGlobalIntMask is almost always
|
||||
* OS_IM_ALL, so the operation is usually simply (SR | 0).
|
||||
*/
|
||||
LEAF(osSetIntMask)
|
||||
/* Extract interrupt enable bits from current SR */
|
||||
MFC0( t4, C0_SR)
|
||||
.set noreorder
|
||||
and v0, t4, (SR_IMASK | SR_IE)
|
||||
/* Get value of __OSGlobalIntMask */
|
||||
la t0, __OSGlobalIntMask
|
||||
lw t3, (t0)
|
||||
/* Bitwise-OR in the disabled CPU bits of __OSGlobalIntMask */
|
||||
xor t0, t3, 0xFFFFFFFF
|
||||
and t0, t0, SR_IMASK
|
||||
or v0, v0, t0
|
||||
/* Fetch MI_INTR_MASK_REG */
|
||||
lw t2, PHYS_TO_K1(MI_INTR_MASK_REG)
|
||||
/* If there are RCP interrupts masked */
|
||||
beqz t2, 1f
|
||||
srl t1, t3, RCP_IMASKSHIFT
|
||||
/* Bitwise-OR in the disabled RCP bits of __OSGlobalIntMask */
|
||||
xor t1, t1, 0xFFFFFFFF
|
||||
and t1, t1, (RCP_IMASK >> RCP_IMASKSHIFT)
|
||||
or t2, t2, t1
|
||||
1:
|
||||
/* Shift the RCP bits to not conflict with the CPU bits */
|
||||
sll t2, t2, RCP_IMASKSHIFT
|
||||
/* OR the CPU and RCP bits together */
|
||||
or v0, v0, t2
|
||||
/* Extract RCP interrupt enable bits from requested mask and mask with __OSGlobalIntMask */
|
||||
and t0, a0, RCP_IMASK
|
||||
and t0, t0, t3
|
||||
/* Convert to a value for MI_INTR_MASK_REG and set it */
|
||||
srl t0, t0, (RCP_IMASKSHIFT-1)
|
||||
lhu t2, __osRcpImTable(t0)
|
||||
sw t2, PHYS_TO_K1(MI_INTR_MASK_REG)
|
||||
/* Extract CPU interrupt enable bits from requested mask and mask with __OSGlobalIntMask */
|
||||
and t0, a0, OS_IM_CPU
|
||||
and t1, t3, SR_IMASK
|
||||
and t0, t0, t1
|
||||
and t4, t4, ~SR_IMASK
|
||||
/* Bitwise OR in the remaining bits of SR and set new SR */
|
||||
or t4, t4, t0
|
||||
MTC0( t4, C0_SR)
|
||||
NOP
|
||||
NOP
|
||||
jr ra
|
||||
END(osSetIntMask)
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
[95mWarning: [97mInvalid pointer indirect: 0 for samplebank SampleBank_2[0m
|
||||
[95mWarning: [97mIn Soundfont Soundfont_40: Invalid pointer indirect 0 for samplebank SampleBank_2[0m
|
||||
cc: Warning: -mips3 should not be used for ucode 32-bit compiles
|
||||
as1: Warning: src/libultra/os/getintmask.s, line 38: Macro instruction used in branch delay slot
|
||||
cc: Warning: -mips3 should not be used for ucode 32-bit compiles
|
||||
cc: Warning: -mips3 should not be used for ucode 32-bit compiles
|
||||
|
|
|
|||
Loading…
Reference in New Issue