mirror of https://github.com/PCSX2/pcsx2.git
3620 lines
96 KiB
C
3620 lines
96 KiB
C
//[module] KERNEL
|
|
//[processor] EE
|
|
//[type] RAW
|
|
//[size] 80880(0x13BF0)
|
|
//[bios] 10000(0xB3200-0xC6DF0)
|
|
//[iopboot] NA
|
|
//[loaded @] 80000000
|
|
//[name] NA
|
|
//[version] NA
|
|
//[memory map] [too many, see mem.txt]
|
|
//[handlers]
|
|
//[entry point] ENTRYPOINT @ 0x80001000
|
|
//[made by] [RO]man, zerofrog & others
|
|
#include <tamtypes.h>
|
|
#include <stdio.h>
|
|
|
|
#include "eekernel.h"
|
|
#include "eeinit.h"
|
|
#include "eedebug.h"
|
|
#include "romdir.h"
|
|
|
|
#define PS2_LOADADDR 0x82000
|
|
|
|
// internal functions
|
|
int InitPgifHandler();
|
|
int InitPgifHandler2();
|
|
|
|
struct ll* LL_unlink(struct ll *l);
|
|
struct ll* LL_rotate(struct ll *l);
|
|
struct ll *LL_unlinkthis(struct ll *l);
|
|
void LL_add(struct ll *l, struct ll *new);
|
|
|
|
extern int (*table_GetCop0[32])(int reg); // 124E8-12564
|
|
extern int (*table_SetCop0[32])(int reg, int val); // 12568-125E4
|
|
|
|
void DefaultCPUTimerHandler();
|
|
void _excepRet(u32 eretpc, u32 v1, u32 a, u32 a1, u32 a2);
|
|
int __ExitThread();
|
|
int __ExitDeleteThread();
|
|
int __SleepThread();
|
|
int _iWaitSema(int sid);
|
|
|
|
void saveContext();
|
|
void restoreContext();
|
|
|
|
int _SemasInit();
|
|
|
|
void _ThreadHandler(u32 epc, u32 stack);
|
|
void _ChangeThread(u32 entry, u32 stack_res, int waitSema);
|
|
|
|
int __DeleteThread(int tid);
|
|
int __StartThread(int tid, void *arg);
|
|
int __load_module(char *name, void (*entry)(void*), void *stack_res, int prio);
|
|
void* __ExecPS2(void * entry, void * gp, int argc, char ** argv);
|
|
|
|
void releaseTCB(int tid);
|
|
void unsetTCB(int tid);
|
|
void thread_2_ready(int tid);
|
|
|
|
void FlushInstructionCache();
|
|
void FlushDataCache();
|
|
void FlushSecondaryCache();
|
|
|
|
void SifDmaInit();
|
|
|
|
u32 excepRetPc=0;//124E4
|
|
int threadId=0; // 125EC
|
|
int threadPrio=0; // 125F0
|
|
int threadStatus=0; // 125F4
|
|
|
|
char threadArgStrBuffer[256]; // 12608
|
|
u64 hvParam;
|
|
|
|
u32 machineType;
|
|
u64 gsIMR;
|
|
u32 memorySize;
|
|
|
|
u8 g_kernelstack[0x2000] __attribute((aligned(128)));
|
|
u32 g_kernelstackend; // hopefully this is right after g_kernelstack
|
|
|
|
int _HandlersCount;
|
|
|
|
int VSyncFlag0;
|
|
int VSyncFlag1;
|
|
|
|
struct ll handler_ll_free, *ihandlers_last=NULL, *ihandlers_first=NULL;
|
|
struct HCinfo intcs_array[14];
|
|
struct ll *dhandlers_last=NULL, *dhandlers_first=NULL;
|
|
struct HCinfo dmacs_array[15];
|
|
struct IDhandl pgifhandlers_array[161];
|
|
void (*sbus_handlers[32])(int ca);
|
|
void (*CPUTimerHandler)() = DefaultCPUTimerHandler; //12480
|
|
|
|
u64 _alarm_unk = 0;
|
|
u64 rcnt3Valid=0;//16A68
|
|
int rcnt3Count = 0; //16A70
|
|
u32 dword_80016A78, dword_80016A7C, dword_80016A84, dword_80016A88;
|
|
//u32 rcnt3gp; //16A80
|
|
//u32 rcnt3Mode; //16A84
|
|
int rcnt3TargetTable[0x142]={0};//16A80
|
|
u8 rcnt3TargetNum[0x40];//16F78
|
|
int threads_count=0;
|
|
|
|
u32 excepRA=0;//16FC0
|
|
u32 excepSP=0;//16FD0
|
|
|
|
struct ll thread_ll_free;
|
|
struct ll thread_ll_priorities[128];
|
|
int semas_count=0;
|
|
struct kSema* semas_last=0;
|
|
|
|
struct TCB threads_array[256];
|
|
struct kSema semas_array[256];
|
|
|
|
char tagindex=0;//1E104
|
|
short transferscount=0;//1E106
|
|
struct TAG tadrptr[31] __attribute((aligned(16)));//1E140
|
|
int extrastorage[(16/4) * 8][31] __attribute((aligned(16)));//1E340
|
|
|
|
int osdConfigParam;//1F340
|
|
|
|
u32 sifEEbuff[32] __attribute((aligned(16)));
|
|
u32 sifRegs[32] __attribute((aligned(16)));
|
|
u32 sifIOPbuff;
|
|
u32 sif1tagdata;
|
|
|
|
void _eret()
|
|
{
|
|
__asm__("mfc0 $26, $12\n"
|
|
"ori $26, 0x13\n"
|
|
"mtc0 $26, $12\n"
|
|
"sync\n"
|
|
"eret\n"
|
|
"nop\n");
|
|
}
|
|
|
|
#define eret() __asm__("j _eret\nnop\n");
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800006C0 SYSCALL 116 RFU116_SetSYSCALL
|
|
////////////////////////////////////////////////////////////////////
|
|
void _SetSYSCALL(int num, int address)
|
|
{
|
|
table_SYSCALL[num] = (void (*)())address;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000740 SYSCALL 114 SetPgifHandler
|
|
////////////////////////////////////////////////////////////////////
|
|
void _SetPgifHandler(void (*handler)(int))
|
|
{
|
|
INTCTable[15] = handler;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800007C0 SYSCALL 108 SetCPUTimerHandler
|
|
////////////////////////////////////////////////////////////////////
|
|
void _SetCPUTimerHandler(void (*handler)())
|
|
{
|
|
CPUTimerHandler = handler;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000800 SYSCALL 109 SetCPUTimer
|
|
////////////////////////////////////////////////////////////////////
|
|
void _SetCPUTimer(int compval)
|
|
{
|
|
if( compval < 0 ) {
|
|
u32 status;
|
|
__asm__("mfc0 %0, $12\n" : "=r"(status) : );
|
|
__asm__("mtc0 %0, $12\n"
|
|
"mtc0 $0, $9\n" : : "r"(status|0x18001));
|
|
}
|
|
else if( compval == 0 ) {
|
|
u32 compare, status;
|
|
__asm__("mfc0 %0, $12\n"
|
|
"mfc0 %1, $11\n"
|
|
: "=r"(status), "=r"(compare) : );
|
|
__asm__("mtc0 %0, $12\n"
|
|
"mtc0 $0, $9\n"
|
|
"mtc0 %1, $11\n"
|
|
: : "r"(status&~0x8000), "r"(compare) );
|
|
}
|
|
else {
|
|
__asm__("mtc0 $0, $9\n" // count
|
|
"mtc0 %0, $11\n" // compare
|
|
: : "r"(compval));
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800008C0 SYSCALL 020 EnableIntc
|
|
////////////////////////////////////////////////////////////////////
|
|
int __EnableIntc(int ch)
|
|
{
|
|
int intbit;
|
|
|
|
intbit = 0x1 << ch;
|
|
if ((INTC_MASK & intbit) != 0) return 0;
|
|
|
|
INTC_MASK = intbit;
|
|
|
|
return 1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000900 SYSCALL 021 DisableIntc
|
|
////////////////////////////////////////////////////////////////////
|
|
int __DisableIntc(int ch)
|
|
{
|
|
int intbit;
|
|
|
|
intbit = 0x1 << ch;
|
|
if ((INTC_MASK & intbit) == 0) return 0;
|
|
|
|
INTC_MASK = intbit;
|
|
|
|
return 1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000940 SYSCALL 022 EnableDmac
|
|
////////////////////////////////////////////////////////////////////
|
|
int __EnableDmac(int ch)
|
|
{
|
|
int dmabit;
|
|
|
|
dmabit = 0x10000 << ch;
|
|
if ((DMAC_STAT & dmabit) != 0) return 0;
|
|
|
|
DMAC_STAT = dmabit;
|
|
|
|
return 1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000980 SYSCALL 023 DisableDmac
|
|
////////////////////////////////////////////////////////////////////
|
|
int __DisableDmac(int ch)
|
|
{
|
|
int dmabit;
|
|
|
|
dmabit = 0x10000 << ch;
|
|
if ((DMAC_STAT & dmabit) == 0) return 0;
|
|
|
|
DMAC_STAT = dmabit;
|
|
|
|
return 1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800009C0 SYSCALL 013 SetVTLBRefillHandler
|
|
////////////////////////////////////////////////////////////////////
|
|
void* _SetVTLBRefillHandler(int cause, void (*handler)())
|
|
{
|
|
if ((cause-1) >= 3) return 0;
|
|
|
|
VCRTable[cause] = handler;
|
|
|
|
return handler;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000A00 SYSCALL 014 SetVCommonHandler
|
|
////////////////////////////////////////////////////////////////////
|
|
void* _SetVCommonHandler(int cause, void (*handler)())
|
|
{
|
|
if ((cause-4) >= 10) return 0;
|
|
|
|
VCRTable[cause] = handler;
|
|
|
|
return handler;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000A40 SYSCALL 015 SetVInterruptHandler
|
|
////////////////////////////////////////////////////////////////////
|
|
void* _SetVInterruptHandler(int cause, void (*handler)())
|
|
{
|
|
if (cause >= 8) return 0;
|
|
|
|
VIntTable[cause] = handler;
|
|
// no return value...
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000A80 SYSCALL 102,106 CpuConfig
|
|
////////////////////////////////////////////////////////////////////
|
|
u32 _CpuConfig(u32 op)
|
|
{
|
|
u32 cfg;
|
|
__asm__("mfc0 %0, $16\n" : "=r"(cfg) : );
|
|
return table_CpuConfig[op](cfg);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000AB8
|
|
////////////////////////////////////////////////////////////////////
|
|
u32 _CpuConfig_0(u32 cfg)
|
|
{
|
|
cfg |= 0x40000;
|
|
__asm__("mtc0 %0, $16\n"
|
|
"sync\n": : "r"(cfg));
|
|
return cfg;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000AD0
|
|
////////////////////////////////////////////////////////////////////
|
|
u32 _CpuConfig_1(u32 cfg)
|
|
{
|
|
cfg |= 0x2000;
|
|
__asm__("mtc0 %0, $16\n"
|
|
"sync\n": : "r"(cfg));
|
|
return cfg;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000AEC
|
|
////////////////////////////////////////////////////////////////////
|
|
u32 _CpuConfig_2(u32 cfg)
|
|
{
|
|
cfg |= 0x1000;
|
|
__asm__("mtc0 %0, $16\n"
|
|
"sync\n": : "r"(cfg));
|
|
return cfg;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000B04
|
|
////////////////////////////////////////////////////////////////////
|
|
u32 _CpuConfig_3(u32 cfg)
|
|
{
|
|
cfg &= ~0x40000;
|
|
__asm__("mtc0 %0, $16\n"
|
|
"sync\n": : "r"(cfg));
|
|
return cfg;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000B20
|
|
////////////////////////////////////////////////////////////////////
|
|
u32 _CpuConfig_4(u32 cfg)
|
|
{
|
|
cfg &= ~0x2000;
|
|
__asm__("mtc0 %0, $16\n"
|
|
"sync\n": : "r"(cfg));
|
|
return cfg;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000B40
|
|
////////////////////////////////////////////////////////////////////
|
|
u32 _CpuConfig_5(u32 cfg)
|
|
{
|
|
cfg &= ~0x1000;
|
|
__asm__("mtc0 %0, $16\n"
|
|
"sync\n": : "r"(cfg));
|
|
return cfg;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000B80 SYSCALL 125 PSMode
|
|
////////////////////////////////////////////////////////////////////
|
|
void _PSMode()
|
|
{
|
|
machineType|= 0x8000;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000BC0 SYSCALL 126 MachineType
|
|
////////////////////////////////////////////////////////////////////
|
|
u32 _MachineType()
|
|
{
|
|
return machineType;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000C00
|
|
////////////////////////////////////////////////////////////////////
|
|
u32 _SetMemorySize(u32 size)
|
|
{
|
|
memorySize = size;
|
|
return size;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000C40 SYSCALL 127 GetMemorySize
|
|
////////////////////////////////////////////////////////////////////
|
|
u32 _GetMemorySize()
|
|
{
|
|
return memorySize;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000D00 SYSCALL 112 GsGetIMR
|
|
////////////////////////////////////////////////////////////////////
|
|
u64 _GsGetIMR()
|
|
{
|
|
return gsIMR;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000D40 SYSCALL 113 GsPutIMR
|
|
////////////////////////////////////////////////////////////////////
|
|
u64 _GsPutIMR(u64 val)
|
|
{
|
|
GS_IMR = val;
|
|
gsIMR = val;
|
|
return val;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80000D80 SYSCALL 002 Exit
|
|
////////////////////////////////////////////////////////////////////
|
|
int _Exit()
|
|
{
|
|
return _RFU004_Exit();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001000 ENTRYPOINT
|
|
////////////////////////////////////////////////////////////////////
|
|
void __attribute__((noreturn)) _start()
|
|
{
|
|
__asm__("lui $sp, %hi(g_kernelstackend)\n"
|
|
"addiu $sp, %lo(g_kernelstackend)\n");
|
|
|
|
__puts("EEKERNEL start\n");
|
|
|
|
memorySize = 32*1024*1024;
|
|
machineType = 0;
|
|
//memorySize = *(int*)0x70003FF0;
|
|
//machineType = machine_type;
|
|
|
|
__printf("TlbInit\n");
|
|
TlbInit();
|
|
__printf("InitPgifHandler\n");
|
|
InitPgifHandler();
|
|
__printf("Initialize\n");
|
|
Initialize();
|
|
// __load_module_EENULL();
|
|
|
|
__asm__ (
|
|
"li $26, %0\n"
|
|
"lw $26, 0($26)\n"
|
|
"mtc0 $26, $12\n"
|
|
"li $26, %1\n"
|
|
"lw $26, 0($26)\n"
|
|
"mtc0 $26, $16\n"
|
|
: : "i"(SRInitVal), "i"(ConfigInitVal)
|
|
);
|
|
|
|
// ee_deci2_manager_init();
|
|
SifDmaInit();
|
|
// __init_unk(0x81FE0);
|
|
SetVSyncFlag(0, 0);
|
|
|
|
// call directly instread of loading module, might need to
|
|
// set thread0 as used since soem code assumes thread 0 is always
|
|
// main thread
|
|
//eeload_start();
|
|
//launch_thread(__load_module("EELOAD", 0x82000, 0x81000, 0));
|
|
|
|
for (;;);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001300
|
|
////////////////////////////////////////////////////////////////////
|
|
void saveContext2() {
|
|
__asm__ (
|
|
".set noat\n"
|
|
"lui $26, %hi(SavedRegs)\n"
|
|
"sq $2, %lo(SavedRegs+0x000)($26)\n"
|
|
"sq $3, %lo(SavedRegs+0x010)($26)\n"
|
|
"sq $4, %lo(SavedRegs+0x020)($26)\n"
|
|
"sq $5, %lo(SavedRegs+0x030)($26)\n"
|
|
"sq $6, %lo(SavedRegs+0x040)($26)\n"
|
|
"sq $7, %lo(SavedRegs+0x050)($26)\n"
|
|
"sq $8, %lo(SavedRegs+0x060)($26)\n"
|
|
"sq $9, %lo(SavedRegs+0x070)($26)\n"
|
|
"sq $10, %lo(SavedRegs+0x080)($26)\n"
|
|
"sq $11, %lo(SavedRegs+0x090)($26)\n"
|
|
"sq $12, %lo(SavedRegs+0x0A0)($26)\n"
|
|
"sq $13, %lo(SavedRegs+0x0B0)($26)\n"
|
|
"sq $14, %lo(SavedRegs+0x0C0)($26)\n"
|
|
"sq $15, %lo(SavedRegs+0x0D0)($26)\n"
|
|
"sq $16, %lo(SavedRegs+0x0E0)($26)\n"
|
|
"sq $17, %lo(SavedRegs+0x0F0)($26)\n"
|
|
"sq $18, %lo(SavedRegs+0x100)($26)\n"
|
|
"sq $19, %lo(SavedRegs+0x110)($26)\n"
|
|
"sq $20, %lo(SavedRegs+0x120)($26)\n"
|
|
"sq $21, %lo(SavedRegs+0x130)($26)\n"
|
|
"sq $22, %lo(SavedRegs+0x140)($26)\n"
|
|
"sq $23, %lo(SavedRegs+0x150)($26)\n"
|
|
"sq $24, %lo(SavedRegs+0x160)($26)\n"
|
|
"sq $25, %lo(SavedRegs+0x170)($26)\n"
|
|
"sq $gp, %lo(SavedRegs+0x180)($26)\n"
|
|
"sq $fp, %lo(SavedRegs+0x190)($26)\n"
|
|
|
|
"mfhi $2\n"
|
|
"sd $2, %lo(SavedRegs+0x1A0)($26)\n"
|
|
"mfhi1 $2\n"
|
|
"sd $2, %lo(SavedRegs+0x1A8)($26)\n"
|
|
|
|
"mflo $2\n"
|
|
"sd $2, %lo(SavedRegs+0x1B0)($26)\n"
|
|
"mflo1 $2\n"
|
|
"sd $2, %lo(SavedRegs+0x1B8)($26)\n"
|
|
|
|
"mfsa $2\n"
|
|
"sd $2, %lo(SavedRegs+0x1C0)($26)\n"
|
|
"jr $31\n"
|
|
"nop\n"
|
|
".set at\n"
|
|
);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800013C0
|
|
////////////////////////////////////////////////////////////////////
|
|
void restoreContext2() {
|
|
__asm__ (
|
|
".set noat\n"
|
|
"lui $26, %hi(SavedRegs)\n"
|
|
"lq $2, %lo(SavedRegs+0x000)($26)\n"
|
|
"lq $3, %lo(SavedRegs+0x010)($26)\n"
|
|
"lq $4, %lo(SavedRegs+0x020)($26)\n"
|
|
"lq $5, %lo(SavedRegs+0x030)($26)\n"
|
|
"lq $6, %lo(SavedRegs+0x040)($26)\n"
|
|
"lq $7, %lo(SavedRegs+0x050)($26)\n"
|
|
"lq $8, %lo(SavedRegs+0x060)($26)\n"
|
|
"lq $9, %lo(SavedRegs+0x070)($26)\n"
|
|
"lq $10, %lo(SavedRegs+0x080)($26)\n"
|
|
"lq $11, %lo(SavedRegs+0x090)($26)\n"
|
|
"lq $12, %lo(SavedRegs+0x0A0)($26)\n"
|
|
"lq $13, %lo(SavedRegs+0x0B0)($26)\n"
|
|
"lq $14, %lo(SavedRegs+0x0C0)($26)\n"
|
|
"lq $15, %lo(SavedRegs+0x0D0)($26)\n"
|
|
"lq $16, %lo(SavedRegs+0x0E0)($26)\n"
|
|
"lq $17, %lo(SavedRegs+0x0F0)($26)\n"
|
|
"lq $18, %lo(SavedRegs+0x100)($26)\n"
|
|
"lq $19, %lo(SavedRegs+0x110)($26)\n"
|
|
"lq $20, %lo(SavedRegs+0x120)($26)\n"
|
|
"lq $21, %lo(SavedRegs+0x130)($26)\n"
|
|
"lq $22, %lo(SavedRegs+0x140)($26)\n"
|
|
"lq $23, %lo(SavedRegs+0x150)($26)\n"
|
|
"lq $24, %lo(SavedRegs+0x160)($26)\n"
|
|
"lq $25, %lo(SavedRegs+0x170)($26)\n"
|
|
"lq $gp, %lo(SavedRegs+0x180)($26)\n"
|
|
"lq $fp, %lo(SavedRegs+0x190)($26)\n"
|
|
|
|
"ld $1, %lo(SavedRegs+0x1A0)($26)\n"
|
|
"mthi $1\n"
|
|
"ld $1, %lo(SavedRegs+0x1A8)($26)\n"
|
|
"mthi1 $1\n"
|
|
|
|
"ld $1, %lo(SavedRegs+0x1B0)($26)\n"
|
|
"mtlo $1\n"
|
|
"ld $1, %lo(SavedRegs+0x1B8)($26)\n"
|
|
"mtlo1 $1\n"
|
|
|
|
"ld $1, %lo(SavedRegs+0x1C0)($26)\n"
|
|
"mtsa $1\n"
|
|
|
|
"jr $31\n"
|
|
"nop\n"
|
|
".set at\n"
|
|
);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001460
|
|
////////////////////////////////////////////////////////////////////
|
|
void erase_cpu_regs()
|
|
{
|
|
__asm__(
|
|
".set noat\n"
|
|
"padduw $1, $0, $0\n"
|
|
"padduw $2, $0, $0\n"
|
|
"padduw $3, $0, $0\n"
|
|
"padduw $4, $0, $0\n"
|
|
"padduw $5, $0, $0\n"
|
|
"padduw $6, $0, $0\n"
|
|
"padduw $7, $0, $0\n"
|
|
"padduw $8, $0, $0\n"
|
|
"padduw $9, $0, $0\n"
|
|
"padduw $10, $0, $0\n"
|
|
"padduw $11, $0, $0\n"
|
|
"padduw $12, $0, $0\n"
|
|
"padduw $13, $0, $0\n"
|
|
"padduw $14, $0, $0\n"
|
|
"padduw $15, $0, $0\n"
|
|
"padduw $16, $0, $0\n"
|
|
"padduw $17, $0, $0\n"
|
|
"padduw $18, $0, $0\n"
|
|
"padduw $19, $0, $0\n"
|
|
"padduw $20, $0, $0\n"
|
|
"padduw $21, $0, $0\n"
|
|
"padduw $22, $0, $0\n"
|
|
"padduw $23, $0, $0\n"
|
|
"padduw $24, $0, $0\n"
|
|
"padduw $25, $0, $0\n"
|
|
"padduw $gp, $0, $0\n"
|
|
"jr $31\n"
|
|
"padduw $fp, $0, $0\n"
|
|
".set at\n"
|
|
);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800014D8 dummy intc handler
|
|
////////////////////////////////////////////////////////////////////
|
|
void _DummyINTCHandler(int n)
|
|
{
|
|
__printf("# INT: INTC (%d)\n", n);
|
|
while(1) { __asm__ ("nop\nnop\nnop\nnop\n"); }
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001508 dummy dmac handler
|
|
////////////////////////////////////////////////////////////////////
|
|
void _DummyDMACHandler(int n)
|
|
{
|
|
__printf("# INT: DMAC (%d)\n", n);
|
|
while(1) { __asm__ ("nop\nnop\nnop\nnop\n"); }
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001508
|
|
////////////////////////////////////////////////////////////////////
|
|
void DefaultCPUTimerHandler()
|
|
{
|
|
__printf("# INT: CPU Timer\n");
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001564 SYSCALL 000 RFU000_FullReset
|
|
//80001564 SYSCALL 003 RFU003 (also)
|
|
//80001564 SYSCALL 008 RFU008 (too)
|
|
////////////////////////////////////////////////////////////////////
|
|
void _RFU___()
|
|
{
|
|
register int syscnum __asm__("$3");
|
|
__printf("# Syscall: undefined (%d)\n", syscnum>>2);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001588
|
|
////////////////////////////////////////////////////////////////////
|
|
void _SetVSyncFlag(int flag0, int flag1)
|
|
{
|
|
VSyncFlag0 = flag0;
|
|
VSyncFlag1 = flag1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800015A0
|
|
////////////////////////////////////////////////////////////////////
|
|
struct ll* _AddHandler()
|
|
{
|
|
struct ll *l;
|
|
|
|
l = LL_unlink(&handler_ll_free);
|
|
if (l == NULL) return NULL;
|
|
|
|
_HandlersCount++;
|
|
return l;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800015E8
|
|
////////////////////////////////////////////////////////////////////
|
|
void _RemoveHandler(int n)
|
|
{
|
|
LL_add(&handler_ll_free, (struct ll*)&pgifhandlers_array[n]);
|
|
_HandlersCount--;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001630
|
|
////////////////////////////////////////////////////////////////////
|
|
void DefaultINTCHandler(int n)
|
|
{
|
|
//TODO
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001798
|
|
////////////////////////////////////////////////////////////////////
|
|
void DefaultDMACHandler(int n)
|
|
{
|
|
//TODO
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800018B0
|
|
////////////////////////////////////////////////////////////////////
|
|
int __AddIntcHandler(int cause, int (*handler)(int), int next, void *arg, int flag)
|
|
{
|
|
struct IDhandl *idh;
|
|
|
|
if ((flag != 0) && (cause == INTC_SBUS)) return -1;
|
|
if (cause >= 15) return -1;
|
|
|
|
idh = (struct IDhandl *)_AddHandler();
|
|
if (idh == 0) return -1;
|
|
|
|
idh->handler = handler;
|
|
__asm__ ("sw $gp, %0\n" : "=m"(idh->gp) : );
|
|
idh->arg = arg;
|
|
idh->flag = flag;
|
|
|
|
if (next==-1) //register_last
|
|
LL_add(&ihandlers_last[cause*12], (struct ll*)idh);
|
|
else if (next==0) //register_first
|
|
LL_add(&ihandlers_first[cause*12], (struct ll*)idh);
|
|
else{
|
|
if (next>128) return -1;
|
|
if (pgifhandlers_array[next].flag==3) return -1;
|
|
LL_add((struct ll*)&pgifhandlers_array[next], (struct ll*)idh);
|
|
}
|
|
|
|
intcs_array[cause].count++;
|
|
return (((u32)idh-(u32)&pgifhandlers_array) * 0xAAAAAAAB) / 8;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001A30 SYSCALL 016 AddIntcHandler
|
|
////////////////////////////////////////////////////////////////////
|
|
int _AddIntcHandler(int cause, int (*handler)(int), int next, void *arg)
|
|
{
|
|
__AddIntcHandler(cause, handler, next, arg, 2);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001A50
|
|
////////////////////////////////////////////////////////////////////
|
|
int _AddIntcHandler2(int cause, int (*handler)(int), int next, void *arg)
|
|
{
|
|
__AddIntcHandler(cause, handler, next, arg, 0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001AC8 SYSCALL 017 RemoveIntcHandler
|
|
////////////////////////////////////////////////////////////////////
|
|
int _RemoveIntcHandler(int cause, int hid)
|
|
{
|
|
if (hid >= 128) return -1;
|
|
|
|
if (pgifhandlers_array[hid].flag == 3) return -1;
|
|
pgifhandlers_array[hid].flag = 3;
|
|
pgifhandlers_array[hid].handler = 0;
|
|
|
|
LL_unlinkthis((struct ll*)&pgifhandlers_array[hid]);
|
|
_RemoveHandler(hid);
|
|
|
|
intcs_array[cause].count--;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001B10
|
|
////////////////////////////////////////////////////////////////////
|
|
int __AddDmacHandler(int cause, int (*handler)(int), int next, void *arg, int flag)
|
|
{
|
|
struct IDhandl *idh;
|
|
register int temp;
|
|
|
|
if (cause >= 16) return -1;
|
|
|
|
idh = (struct IDhandl *)_AddHandler();
|
|
if (idh == 0) return -1;
|
|
|
|
idh->handler = handler;
|
|
__asm__ ("sw $gp, %0\n" : "=m"(idh->gp) : );
|
|
idh->arg = arg;
|
|
idh->flag = flag;
|
|
|
|
if (next==-1) //register_last
|
|
LL_add(&dhandlers_last[cause*12], (struct ll*)idh);
|
|
else if (next==0) //register_first
|
|
LL_add(&dhandlers_first[cause*12], (struct ll*)idh);
|
|
else{
|
|
if (next>128) return -1;
|
|
if (pgifhandlers_array[next].flag==3) return -1;
|
|
LL_add((struct ll*)&pgifhandlers_array[next], (struct ll*)idh);
|
|
}
|
|
|
|
dmacs_array[cause].count++;
|
|
return (((u32)idh-(u32)&pgifhandlers_array) * 0xAAAAAAAB) / 8;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001C78 SYSCALL 018 AddDmacHandler
|
|
////////////////////////////////////////////////////////////////////
|
|
int _AddDmacHandler(int cause, int (*handler)(int), int next, void *arg)
|
|
{
|
|
__AddDmacHandler(cause, handler, next, arg, 2);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001C98
|
|
////////////////////////////////////////////////////////////////////
|
|
int _AddDmacHandler2(int cause, int (*handler)(int), int next, void *arg)
|
|
{
|
|
__AddDmacHandler(cause, handler, next, arg, 0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001CB8 SYSCALL 019 RemoveDmacHandler
|
|
////////////////////////////////////////////////////////////////////
|
|
int _RemoveDmacHandler(int cause, int hid)
|
|
{
|
|
if (hid >= 128) return -1;
|
|
|
|
if (pgifhandlers_array[hid].flag == 3) return -1;
|
|
pgifhandlers_array[hid].flag = 3;
|
|
pgifhandlers_array[hid].handler = 0;
|
|
|
|
LL_unlinkthis((struct ll*)&pgifhandlers_array[hid]);
|
|
_RemoveHandler(hid);
|
|
|
|
dmacs_array[cause].count--;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001D58
|
|
////////////////////////////////////////////////////////////////////
|
|
void sbusHandler()
|
|
{
|
|
//TODO
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001E38
|
|
////////////////////////////////////////////////////////////////////
|
|
int __AddSbusIntcHandler(int cause, void (*handler)(int ca))
|
|
{
|
|
if (cause >= 32) return -1;
|
|
|
|
if (sbus_handlers[cause] != 0) return -1;
|
|
|
|
sbus_handlers[cause] = handler;
|
|
return cause;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001E78 SYSCALL 010 AddSbusIntcHandler
|
|
////////////////////////////////////////////////////////////////////
|
|
int _AddSbusIntcHandler(int cause, void (*handler)(int ca))
|
|
{
|
|
if (cause < 16) return __AddSbusIntcHandler(cause, handler);
|
|
|
|
return -1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001EA8
|
|
////////////////////////////////////////////////////////////////////
|
|
int __RemoveSbusIntcHandler(int cause)
|
|
{
|
|
if (cause >= 32) return -1;
|
|
|
|
sbus_handlers[cause] = 0;
|
|
return cause;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001ED0 SYSCALL 011 RemoveSbusIntcHandler
|
|
////////////////////////////////////////////////////////////////////
|
|
int _RemoveSbusIntcHandler(int cause)
|
|
{
|
|
if (cause < 16) return __RemoveSbusIntcHandler(cause);
|
|
|
|
return -1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001F00
|
|
////////////////////////////////////////////////////////////////////
|
|
int __Interrupt2Iop(int cause)
|
|
{
|
|
if (cause >= 32) {
|
|
return -1;
|
|
}
|
|
|
|
SBUS_MSFLG = 1 << cause;
|
|
|
|
SBUS_F240 = 0x100;
|
|
SBUS_F240 = 0x100;
|
|
SBUS_F240 = 0x100;
|
|
SBUS_F240 = 0x100;
|
|
SBUS_F240 = 0x100;
|
|
SBUS_F240 = 0x100;
|
|
SBUS_F240 = 0x100;
|
|
SBUS_F240 = 0x100; // eight times
|
|
|
|
SBUS_F240 = 0x40100;
|
|
|
|
return cause;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001F70 SYSCALL 012 Interrupt2Iop
|
|
////////////////////////////////////////////////////////////////////
|
|
int _Interrupt2Iop(int cause)
|
|
{
|
|
if (cause < 16) {
|
|
return _Interrupt2Iop(cause);
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001FA0 SYSCALL 092 EnableIntcHandler
|
|
////////////////////////////////////////////////////////////////////
|
|
void _EnableIntcHandler(u32 id)
|
|
{
|
|
pgifhandlers_array[id].flag = 2;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001FA0 SYSCALL 093 DisableIntcHandler
|
|
////////////////////////////////////////////////////////////////////
|
|
void _DisableIntcHandler(u32 id)
|
|
{
|
|
pgifhandlers_array[id].flag = 1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001FA0 SYSCALL 094 EnableDmacHandler
|
|
////////////////////////////////////////////////////////////////////
|
|
void _EnableDmacHandler(u32 id)
|
|
{
|
|
pgifhandlers_array[id].flag = 2;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80001FA0 SYSCALL 095 DisableDmacHandler
|
|
////////////////////////////////////////////////////////////////////
|
|
void _DisableDmacHandler(u32 id)
|
|
{
|
|
pgifhandlers_array[id].flag = 1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80002040 SYSCALL 083 iSetEventFlag
|
|
////////////////////////////////////////////////////////////////////
|
|
int _iSetEventFlag(int ef, u32 bits)
|
|
{
|
|
return _HandlersCount; //?
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800022D8 SYSCALL 24,30
|
|
////////////////////////////////////////////////////////////////////
|
|
int _SetAlarm(short a0, int a1, int a2)
|
|
{
|
|
int mode = _alarm_unk & 0x1;
|
|
int i;
|
|
|
|
i = 0;
|
|
while (mode) {
|
|
mode = (_alarm_unk >> i++) & 0x1;
|
|
if (i >= 64) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
_alarm_unk|= mode << i;
|
|
|
|
__asm__("move %0, $gp\n" : "=r"(rcnt3TargetTable[0]) : );
|
|
dword_80016A78 = a1;
|
|
dword_80016A7C = a2;
|
|
rcnt3TargetTable[1] = RCNT3_MODE;
|
|
i = RCNT3_MODE + a0;
|
|
if (i < -1)
|
|
i&= 0xffff;
|
|
dword_80016A88 = i;
|
|
|
|
if (RCNT3_MODE < i) {
|
|
if (rcnt3Count <= 0) {
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80002570 SYSCALL 25,31 ReleaseAlarm
|
|
////////////////////////////////////////////////////////////////////
|
|
void _ReleaseAlarm()
|
|
{
|
|
//TODO
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80002650
|
|
////////////////////////////////////////////////////////////////////
|
|
void rcnt3Handler()
|
|
{
|
|
unsigned int i;
|
|
u32* ptr;
|
|
u32 storegp;
|
|
u32 addr;
|
|
|
|
if (rcnt3Count < 2) {
|
|
RCNT3_MODE = 0x483;
|
|
} else {
|
|
RCNT3_MODE = 0x583;
|
|
RCNT3_TARGET = rcnt3TargetTable[2+rcnt3TargetNum[1] * 5];
|
|
}
|
|
|
|
for (;;) {
|
|
u32 id = (u32)rcnt3TargetNum[0];
|
|
if (--rcnt3Count >= 0) {
|
|
// shift one down
|
|
for (i=0; i<rcnt3Count; i++) {
|
|
rcnt3TargetNum[i] = rcnt3TargetNum[i+1];
|
|
}
|
|
}
|
|
|
|
rcnt3Valid &= ~(1 << id);
|
|
ptr = &rcnt3TargetTable[id * 5];
|
|
addr = (u32)*(u16*)(ptr+2);
|
|
__asm__("move %0, $gp\n" : "=r"(storegp) : );
|
|
__asm__("move $gp, %0\n" : : "r"(ptr[0]) );
|
|
|
|
_excepRet(excepRetPc, ptr[-2], id, addr, ptr[-1]);
|
|
|
|
__asm__("move $gp, %0\n" : : "r"(storegp) );
|
|
|
|
if (rcnt3Count >= 0) {
|
|
if (addr != rcnt3TargetTable[rcnt3TargetNum[0] * 5 + 2]) {
|
|
break;
|
|
}
|
|
} else break;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800027F8 SYSCALL 082 SetEventFlag
|
|
////////////////////////////////////////////////////////////////////
|
|
int _SetEventFlag(int ef, u32 bits)
|
|
{
|
|
return rcnt3Count; //?
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800027F8
|
|
////////////////////////////////////////////////////////////////////
|
|
void _InitRCNT3()
|
|
{
|
|
int i;
|
|
|
|
rcnt3Count = 0;
|
|
rcnt3Valid = 0;
|
|
_alarm_unk = 0;
|
|
for (i=0; i<0x40; i++) rcnt3TargetNum[i] = 0;
|
|
|
|
__EnableIntc(INTC_TIM3);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80002840
|
|
////////////////////////////////////////////////////////////////////
|
|
void _excepRet(u32 eretpc, u32 v1, u32 a, u32 a1, u32 a2)
|
|
{
|
|
__asm__("sw $31, %0\n"
|
|
"sw $sp, %1\n"
|
|
: "=m"(excepRA), "=m"(excepSP) : );
|
|
__asm__("mtc0 $4, $14\n"
|
|
"sync\n"
|
|
"daddu $3, $5, $0\n"
|
|
"daddu $4, $6, $0\n"
|
|
"daddu $5, $7, $0\n"
|
|
"daddu $6, $8, $0\n"
|
|
"mfc0 $26, $12\n"
|
|
"ori $26, 0x12\n"
|
|
"mtc0 $26, $12\n"
|
|
"sync\n"
|
|
"eret\n"
|
|
"nop\n");
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80002880 SYSCALL 005 RFU005
|
|
////////////////////////////////////////////////////////////////////
|
|
void _RFU005()
|
|
{
|
|
__asm__ (
|
|
".set noat\n"
|
|
|
|
"mfc0 $26, $12\n"
|
|
"ori $1, $0, 0xFFE4\n"
|
|
"and $26, $1\n"
|
|
"mtc0 $26, $12\n"
|
|
"sync\n"
|
|
|
|
"lw $ra, excepRA\n"
|
|
"lw $sp, excepSP\n"
|
|
"jr $ra\n"
|
|
"nop\n"
|
|
|
|
".set at\n");
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//A00028C0 SYSCALL 097 EnableCache
|
|
////////////////////////////////////////////////////////////////////
|
|
int _EnableCache(int cache)
|
|
{
|
|
u32 cfg;
|
|
__asm__("mfc0 %0, $16\n" : "=r"(cfg) : );
|
|
cfg |= ((cache&3)<<16);
|
|
__asm__("mtc0 %0, $16\n"
|
|
"sync\n" : : "r"(cfg) );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//A0002980 SYSCALL 098 DisableCache
|
|
////////////////////////////////////////////////////////////////////
|
|
int _DisableCache(int cache)
|
|
{
|
|
u32 cfg;
|
|
__asm__("mfc0 %0, $16\n" : "=r"(cfg) : );
|
|
cfg &= ~((cache&3)<<16);
|
|
__asm__("mtc0 %0, $16\n"
|
|
"sync\n" : : "r"(cfg) );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//A0002A40 SYSCALL 100 FlushCache
|
|
////////////////////////////////////////////////////////////////////
|
|
void _FlushCache(int op)
|
|
{
|
|
if( op == 0 ) FlushInstructionCache();
|
|
else if ( op == 1 ) FlushSecondaryCache();
|
|
else if( op == 2 ) FlushDataCache();
|
|
else {
|
|
FlushSecondaryCache();
|
|
FlushDataCache();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80002AC0
|
|
////////////////////////////////////////////////////////////////////
|
|
void FlushInstructionCache()
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80002A80
|
|
////////////////////////////////////////////////////////////////////
|
|
void FlushDataCache()
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80002B00
|
|
////////////////////////////////////////////////////////////////////
|
|
void FlushSecondaryCache()
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//A0002B40 SYSCALL 101,105 _105
|
|
////////////////////////////////////////////////////////////////////
|
|
void _105(int op1, int op2)
|
|
{
|
|
// flushing caches again
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//A0002C00 SYSCALL 096 KSeg0
|
|
////////////////////////////////////////////////////////////////////
|
|
void _KSeg0(u32 arg)
|
|
{
|
|
u32 cfg;
|
|
__asm__("mfc0 %0, $16\n" : "=r"(cfg) : );
|
|
cfg = (arg&3)&((cfg>>3)<<3); // yes it is 0, don't ask
|
|
__asm__("mtc0 %0, $16\n"
|
|
"sync\n" : : "r"(cfg) );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80002C40 SYSCALL 099 GetCop0
|
|
////////////////////////////////////////////////////////////////////
|
|
int _GetCop0(int reg)
|
|
{
|
|
return table_GetCop0[reg](reg);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80002C58-80002D50 calls for table_GetCop0
|
|
////////////////////////////////////////////////////////////////////
|
|
int GetCop0_Index(int reg) { __asm__(" mfc0 $2, $0\n"); }
|
|
int GetCop0_Random(int reg) { __asm__(" mfc0 $2, $1\n"); }
|
|
int GetCop0_EntryLo0(int reg) { __asm__(" mfc0 $2, $2\n"); }
|
|
int GetCop0_EntryLo1(int reg) { __asm__(" mfc0 $2, $3\n"); }
|
|
|
|
int GetCop0_Context(int reg) { __asm__(" mfc0 $2, $4\n"); }
|
|
int GetCop0_PageMask(int reg) { __asm__(" mfc0 $2, $5\n"); }
|
|
int GetCop0_Wired(int reg) { __asm__(" mfc0 $2, $6\n"); }
|
|
int GetCop0_Reg7(int reg) { return; }
|
|
|
|
int GetCop0_BadVAddr(int reg) { __asm__(" mfc0 $2, $8\n"); }
|
|
int GetCop0_Count(int reg) { __asm__(" mfc0 $2, $9\n"); }
|
|
int GetCop0_EntryHi(int reg) { __asm__(" mfc0 $2, $10\n"); }
|
|
int GetCop0_Compare(int reg) { __asm__(" mfc0 $2, $11\n"); }
|
|
|
|
int GetCop0_Status(int reg) { __asm__(" mfc0 $2, $12\n"); }
|
|
int GetCop0_Cause(int reg) { __asm__(" mfc0 $2, $13\n"); }
|
|
int GetCop0_ExceptPC(int reg) { __asm__(" mfc0 $2, $14\n"); }
|
|
int GetCop0_PRevID(int reg) { __asm__(" mfc0 $2, $15\n"); }
|
|
|
|
int GetCop0_Config(int reg) { __asm__(" mfc0 $2, $16\n"); }
|
|
int GetCop0_Reg17(int reg) { return; }
|
|
int GetCop0_Reg18(int reg) { return; }
|
|
int GetCop0_Reg19(int reg) { return; }
|
|
|
|
int GetCop0_Reg20(int reg) { return; }
|
|
int GetCop0_Reg21(int reg) { return; }
|
|
int GetCop0_Reg22(int reg) { return; }
|
|
int GetCop0_Reg23(int reg) { __asm__(" mfc0 $2, $23\n"); }
|
|
|
|
int GetCop0_DebugReg24(int reg) { __asm__(" mfc0 $2, $24\n"); }
|
|
int GetCop0_Perf(int reg) { __asm__(" mfc0 $2, $25\n"); }
|
|
int GetCop0_Reg26(int reg) { return; }
|
|
int GetCop0_Reg27(int reg) { return; }
|
|
|
|
int GetCop0_TagLo(int reg) { __asm__(" mfc0 $2, $28\n"); }
|
|
int GetCop0_TagHi(int reg) { __asm__(" mfc0 $2, $29\n"); }
|
|
int GetCop0_ErrorPC(int reg) { __asm__(" mfc0 $2, $30\n"); }
|
|
int GetCop0_Reg31(int reg) { return; }
|
|
|
|
int (*table_GetCop0[32])(int reg) = { // 800124E8
|
|
GetCop0_Index, GetCop0_Random, GetCop0_EntryLo0, GetCop0_EntryLo1,
|
|
GetCop0_Context, GetCop0_PageMask, GetCop0_Wired, GetCop0_Reg7,
|
|
GetCop0_BadVAddr, GetCop0_Count, GetCop0_EntryHi, GetCop0_Compare,
|
|
GetCop0_Status, GetCop0_Cause, GetCop0_ExceptPC, GetCop0_PRevID,
|
|
GetCop0_Config, GetCop0_Reg17, GetCop0_Reg18, GetCop0_Reg19,
|
|
GetCop0_Reg20, GetCop0_Reg21, GetCop0_Reg22, GetCop0_Reg23,
|
|
GetCop0_DebugReg24, GetCop0_Perf, GetCop0_Reg26, GetCop0_Reg27,
|
|
GetCop0_TagLo, GetCop0_TagHi, GetCop0_ErrorPC, GetCop0_Reg31
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80002D80
|
|
////////////////////////////////////////////////////////////////////
|
|
int SetCop0(int reg, int val)
|
|
{
|
|
return table_SetCop0[reg](reg, val);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80002D98-80002F74 calls for table_SetCop0
|
|
////////////////////////////////////////////////////////////////////
|
|
int SetCop0_Index(int reg, int val) { __asm__(" mfc0 $2, $0\nmtc0 %0, $0\nsync\n" : : "r"(val)); }
|
|
int SetCop0_Random(int reg, int val) { return -1; }
|
|
int SetCop0_EntryLo0(int reg, int val) { __asm__(" mfc0 $2, $2\nmtc0 %0, $2\nsync\n" : : "r"(val)); }
|
|
int SetCop0_EntryLo1(int reg, int val) { __asm__(" mfc0 $2, $3\nmtc0 %0, $3\nsync\n" : : "r"(val)); }
|
|
|
|
int SetCop0_Context(int reg, int val) { __asm__(" mfc0 $2, $4\nmtc0 %0, $4\nsync\n" : : "r"(val)); }
|
|
int SetCop0_PageMask(int reg, int val) { __asm__(" mfc0 $2, $5\nmtc0 %0, $5\nsync\n" : : "r"(val)); }
|
|
int SetCop0_Wired(int reg, int val) { __asm__(" mfc0 $2, $6\nmtc0 %0, $6\nsync\n" : : "r"(val)); }
|
|
int SetCop0_Reg7(int reg, int val) { return -1; }
|
|
|
|
int SetCop0_BadVAddr(int reg, int val) { return -1; }
|
|
int SetCop0_Count(int reg, int val) { __asm__(" mfc0 $2, $9\nmtc0 %0, $9\nsync\n" : : "r"(val)); }
|
|
int SetCop0_EntryHi(int reg, int val) { __asm__(" mfc0 $2, $10\nmtc0 %0, $10\nsync\n" : : "r"(val)); }
|
|
int SetCop0_Compare(int reg, int val) { __asm__(" mfc0 $2, $11\nmtc0 %0, $11\nsync\n" : : "r"(val)); }
|
|
|
|
int SetCop0_Status(int reg, int val) { __asm__(" mfc0 $2, $12\nmtc0 %0, $12\nsync\n" : : "r"(val)); }
|
|
int SetCop0_Cause(int reg, int val) { return -1; }
|
|
int SetCop0_ExceptPC(int reg, int val) { __asm__(" mfc0 $2, $14\nmtc0 %0, $14\nsync\n" : : "r"(val)); }
|
|
int SetCop0_PRevID(int reg, int val) { return -1; }
|
|
|
|
int SetCop0_Config(int reg, int val) { __asm__(" mfc0 $2, $16\nmtc0 %0, $16\nsync\n" : : "r"(val)); }
|
|
int SetCop0_Reg17(int reg, int val) { return -1; }
|
|
int SetCop0_Reg18(int reg, int val) { return -1; }
|
|
int SetCop0_Reg19(int reg, int val) { return -1; }
|
|
|
|
int SetCop0_Reg20(int reg, int val) { return -1; }
|
|
int SetCop0_Reg21(int reg, int val) { return -1; }
|
|
int SetCop0_Reg22(int reg, int val) { return -1; }
|
|
int SetCop0_Reg23(int reg, int val) { __asm__(" mfc0 $2, $23\nmtc0 %0, $23\nsync\n" : : "r"(val)); }
|
|
|
|
int SetCop0_DebugReg24(int reg, int val){ __asm__(" mfc0 $2, $24\nmtc0 %0, $24\nsync\n" : : "r"(val)); }
|
|
int SetCop0_Perf(int reg, int val) { __asm__(" mfc0 $2, $25\nmtc0 %0, $25\nsync\n" : : "r"(val)); }
|
|
int SetCop0_Reg26(int reg, int val) { return -1; }
|
|
int SetCop0_Reg27(int reg, int val) { return -1; }
|
|
|
|
int SetCop0_TagLo(int reg, int val) { __asm__(" mfc0 $2, $28\nmtc0 %0, $28\nsync\n" : : "r"(val)); }
|
|
int SetCop0_TagHi(int reg, int val) { __asm__(" mfc0 $2, $29\nmtc0 %0, $29\nsync\n" : : "r"(val)); }
|
|
int SetCop0_ErrorPC(int reg, int val) { __asm__(" mfc0 $2, $30\nmtc0 %0, $30\nsync\n" : : "r"(val)); }
|
|
int SetCop0_Reg31(int reg, int val) { return -1; }
|
|
|
|
int (*table_SetCop0[32])(int reg, int val) = { // 80012568
|
|
SetCop0_Index, SetCop0_Random, SetCop0_EntryLo0, SetCop0_EntryLo1,
|
|
SetCop0_Context, SetCop0_PageMask, SetCop0_Wired, SetCop0_Reg7,
|
|
SetCop0_BadVAddr, SetCop0_Count, SetCop0_EntryHi, SetCop0_Compare,
|
|
SetCop0_Status, SetCop0_Cause, SetCop0_ExceptPC, SetCop0_PRevID,
|
|
SetCop0_Config, SetCop0_Reg17, SetCop0_Reg18, SetCop0_Reg19,
|
|
SetCop0_Reg20, SetCop0_Reg21, SetCop0_Reg22, SetCop0_Reg23,
|
|
SetCop0_DebugReg24, SetCop0_Perf, SetCop0_Reg26, SetCop0_Reg27,
|
|
SetCop0_TagLo, SetCop0_TagHi, SetCop0_ErrorPC, SetCop0_Reg31
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80002F80 SYSCALL 007 ExecPS2
|
|
////////////////////////////////////////////////////////////////////
|
|
int _ExecPS2(void * entry, void * gp, int argc, char ** argv)
|
|
{
|
|
saveContext();
|
|
__ExecPS2(entry, gp, argc, argv);
|
|
__asm__("mtc0 $2, $14\n"
|
|
"move $sp, %0\n"
|
|
"sd $2, 0x20($sp)\n"
|
|
: : "r"(SavedSP));
|
|
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80002FC0 SYSCALL 033 DeleteThread
|
|
////////////////////////////////////////////////////////////////////
|
|
int _DeleteThread(int tid)
|
|
{
|
|
register int ret __asm__("$2");
|
|
register u32 curepc __asm__("$4");
|
|
|
|
saveContext();
|
|
|
|
ret = __DeleteThread(tid);
|
|
if (ret < 0) {
|
|
__asm__("lw $sp, %0\n" : : "m"(SavedSP));
|
|
// make sure the return value is also stored
|
|
__asm__("sd $2, 0x20($sp)\n");
|
|
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
|
|
__asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); // EPC
|
|
_ThreadHandler(curepc, SavedSP); // returns entry in $3, stack in $4
|
|
|
|
__asm__("mtc0 $2, $14\n"
|
|
"move $sp, $3\n");
|
|
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80003040 SYSCALL 034 StartThread
|
|
////////////////////////////////////////////////////////////////////
|
|
int _StartThread(int tid, void *arg)
|
|
{
|
|
register int ret __asm__("$2");
|
|
register u32 curepc __asm__("$4");
|
|
|
|
saveContext();
|
|
|
|
ret = __StartThread(tid, arg);
|
|
|
|
if (ret < 0) {
|
|
__asm__("lw $sp, %0\n" : : "m"(SavedSP));
|
|
// make sure the return value is also stored
|
|
__asm__("sd $2, 0x20($sp)\n");
|
|
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
|
|
__asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); // EPC
|
|
_ThreadHandler(curepc, SavedSP); // returns entry in $3, stack in $4
|
|
|
|
__asm__("mtc0 $2, $14\n"
|
|
"move $sp, $3\n");
|
|
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800030C0 SYSCALL 035 ExitThread
|
|
////////////////////////////////////////////////////////////////////
|
|
int _ExitThread()
|
|
{
|
|
saveContext();
|
|
|
|
__ExitThread();
|
|
__asm__("mtc0 $2, $14\n"
|
|
"sync\n"
|
|
"move $sp, $3\n");
|
|
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80003100 SYSCALL 036 ExitDeleteThread
|
|
////////////////////////////////////////////////////////////////////
|
|
int _ExitDeleteThread()
|
|
{
|
|
saveContext();
|
|
|
|
__ExitDeleteThread();
|
|
__asm__("mtc0 $2, $14\n"
|
|
"sync\n"
|
|
"move $sp, $3\n");
|
|
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80003140 SYSCALL 037 TerminateThread
|
|
////////////////////////////////////////////////////////////////////
|
|
int _TerminateThread(int tid)
|
|
{
|
|
register int ret __asm__("$2");
|
|
register u32 curepc __asm__("$4");
|
|
|
|
saveContext();
|
|
|
|
ret = _iTerminateThread(tid);
|
|
|
|
if( ret < 0 ) {
|
|
__asm__("lw $sp, %0\n" : : "m"(SavedSP));
|
|
// make sure the return value is also stored
|
|
__asm__("sd $2, 0x20($sp)\n");
|
|
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
__asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); // EPC
|
|
_ThreadHandler(curepc, SavedSP); // returns entry in $3, stack in $4
|
|
|
|
__asm__("mtc0 $2, $14\n"
|
|
"move $sp, $3\n");
|
|
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800031C0 SYSCALL 043 RotateThreadReadyQueue
|
|
////////////////////////////////////////////////////////////////////
|
|
void _RotateThreadReadyQueue(int pri)
|
|
{
|
|
register int ret __asm__("$2");
|
|
register u32 curepc __asm__("$4");
|
|
|
|
ret = pri;
|
|
saveContext();
|
|
|
|
ret = _iRotateThreadReadyQueue(pri);
|
|
|
|
if( ret < 0 ) {
|
|
__asm__("lw $sp, %0\n" : : "m"(SavedSP));
|
|
// make sure the return value is also stored
|
|
__asm__("sd $2, 0x20($sp)\n");
|
|
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
__asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); // EPC
|
|
_ThreadHandler(curepc, SavedSP); // returns entry in $3, stack in $4
|
|
|
|
__asm__("mtc0 $2, $14\n"
|
|
"move $sp, $3\n");
|
|
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80003240 SYSCALL 045 ReleaseWaitThread
|
|
////////////////////////////////////////////////////////////////////
|
|
void _ReleaseWaitThread(int tid)
|
|
{
|
|
register int ret __asm__("$2");
|
|
register u32 curepc __asm__("$4");
|
|
|
|
ret = tid;
|
|
saveContext();
|
|
|
|
ret = _iReleaseWaitThread(tid);
|
|
|
|
if( ret < 0 ) {
|
|
__asm__("lw $sp, %0\n" : : "m"(SavedSP));
|
|
// make sure the return value is also stored
|
|
__asm__("sd $2, 0x20($sp)\n");
|
|
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
__asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); // EPC
|
|
_ThreadHandler(curepc, SavedSP); // returns entry in $3, stack in $4
|
|
|
|
__asm__("mtc0 $2, $14\n"
|
|
"move $sp, $3\n");
|
|
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800032C0 SYSCALL 052 SleepThread
|
|
////////////////////////////////////////////////////////////////////
|
|
int _SleepThread()
|
|
{
|
|
register int ret __asm__("$2");
|
|
|
|
ret = threadId;
|
|
saveContext();
|
|
|
|
ret = __SleepThread();
|
|
if (ret < 0) {
|
|
register int curepc __asm__("$4");
|
|
__asm__("mfc0 %0, $14\n" : "=r"(curepc) : );
|
|
_ChangeThread(curepc, SavedSP, 1);
|
|
|
|
__asm__("mtc0 $2, $14\n"
|
|
"sync\n"
|
|
"move $sp, $3\n");
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
__asm__("lw $sp, %0\n"
|
|
"sd %1, 0x20($sp)\n" : : "m"(SavedSP), "r"(ret) );
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80003340 SYSCALL 051 WakeupThread
|
|
////////////////////////////////////////////////////////////////////
|
|
int _WakeupThread(int tid)
|
|
{
|
|
register int ret __asm__("$2");
|
|
|
|
ret = tid;
|
|
saveContext();
|
|
|
|
ret = iWakeupThread(tid);
|
|
if( ret >= 0 ) {
|
|
register int curepc __asm__("$4");
|
|
__asm__("mfc0 %0, $14\n" : "=r"(curepc) : );
|
|
_ThreadHandler(curepc, SavedSP);
|
|
|
|
__asm__("mtc0 $2, $14\n"
|
|
"sync\n"
|
|
"move $sp, $3\n");
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
__asm__("lw $sp, %0\n"
|
|
"sd %1, 0x20($sp)\n" : : "m"(SavedSP), "r"(ret) );
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800033C0 SYSCALL 057 ResumeThread
|
|
////////////////////////////////////////////////////////////////////
|
|
int _ResumeThread(int tid)
|
|
{
|
|
register int ret __asm__("$2");
|
|
|
|
ret = tid;
|
|
saveContext();
|
|
|
|
ret = _iResumeThread(tid);
|
|
if( ret >= 0 ) {
|
|
register int curepc __asm__("$4");
|
|
__asm__("mfc0 %0, $14\n" : "=r"(curepc) : );
|
|
_ThreadHandler(curepc, SavedSP);
|
|
|
|
__asm__("mtc0 $2, $14\n"
|
|
"sync\n"
|
|
"move $sp, $3\n");
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
__asm__("lw $sp, %0\n"
|
|
"sd %1, 0x20($sp)\n" : : "m"(SavedSP), "r"(ret) );
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80003440 SYSCALL 068 WaitSema
|
|
////////////////////////////////////////////////////////////////////
|
|
int _WaitSema(int sid)
|
|
{
|
|
register int ret __asm__("$2");
|
|
|
|
ret = sid;
|
|
saveContext();
|
|
|
|
ret = _iWaitSema(sid);
|
|
if( ret == 0xFFFFFFFE ) {
|
|
register int curepc __asm__("$4");
|
|
__asm__("mfc0 %0, $14\n" : "=r"(curepc) : );
|
|
_ChangeThread(curepc, SavedSP, 2);
|
|
|
|
__asm__("mtc0 $2, $14\n"
|
|
"sync\n"
|
|
"move $sp, $3\n");
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
__asm__("lw $sp, %0\n" : : "m"(SavedSP));
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800034C0 SYSCALL 066 SignalSema
|
|
////////////////////////////////////////////////////////////////////
|
|
void _SignalSema(int sid)
|
|
{
|
|
register int ret __asm__("$2");
|
|
|
|
ret = sid;
|
|
saveContext();
|
|
|
|
ret = _iSignalSema(sid);
|
|
if( ret >= 0 ) {
|
|
register int curepc __asm__("$4");
|
|
__asm__("mfc0 %0, $14\n" : "=r"(curepc) : );
|
|
_ThreadHandler(curepc, SavedSP);
|
|
|
|
__asm__("mtc0 $2, $14\n"
|
|
"sync\n"
|
|
"move $sp, $3\n");
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
__asm__("lw $sp, %0\n"
|
|
"sd %1, 0x20($sp)\n" : : "m"(SavedSP), "r"(ret) );
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80003540 SYSCALL 065 DeleteSema
|
|
////////////////////////////////////////////////////////////////////
|
|
int _DeleteSema(int sid)
|
|
{
|
|
register int ret __asm__("$2");
|
|
|
|
ret = sid;
|
|
saveContext();
|
|
|
|
ret = _iDeleteSema(sid);
|
|
if( ret >= 0 ) {
|
|
register int curepc __asm__("$4");
|
|
__asm__("mfc0 %0, $14\n" : "=r"(curepc) : );
|
|
_ThreadHandler(curepc, SavedSP);
|
|
|
|
__asm__("mtc0 $2, $14\n"
|
|
"sync\n"
|
|
"move $sp, $3\n");
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
__asm__("lw $sp, %0\n"
|
|
"sd %1, 0x20($sp)\n" : : "m"(SavedSP), "r"(ret) );
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800035C0 SYSCALL 041 ChangeThreadPriority
|
|
//return has to be void (even though it fills in v0)
|
|
////////////////////////////////////////////////////////////////////
|
|
void _ChangeThreadPriority(int tid, int prio)
|
|
{
|
|
register int ret __asm__("$2");
|
|
|
|
saveContext();
|
|
ret = _iChangeThreadPriority(tid, prio);
|
|
|
|
__asm__("lw $26, %0\n"
|
|
"sd %1, 0x20($26)\n" : : "m"(SavedSP), "r"(ret) );
|
|
|
|
if (ret>=0){
|
|
register int curepc __asm__("$4");
|
|
__asm__("mfc0 %0, $14\n" : "=r"(curepc) : );
|
|
_ThreadHandler(curepc, SavedSP);
|
|
|
|
__asm__("mtc0 $2, $14\n"
|
|
"sync\n"
|
|
"move $sp, $3\n");
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
// why twice?
|
|
__asm__("lw $sp, %0\n"
|
|
"sd %1, 0x20($sp)\n" : : "m"(SavedSP), "r"(ret) );
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//8000363C
|
|
////////////////////////////////////////////////////////////////////
|
|
void __ThreadHandler()
|
|
{
|
|
register int curepc __asm__("$4");
|
|
|
|
saveContext();
|
|
|
|
__asm__("mfc0 %0, $14\n" : "=r"(curepc) : );
|
|
_ThreadHandler(curepc, SavedSP);
|
|
__asm__("mtc0 $2, $14\n"
|
|
"sync\n"
|
|
"move $sp, $3\n");
|
|
restoreContext();
|
|
eret();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80003680
|
|
////////////////////////////////////////////////////////////////////
|
|
void saveContext()
|
|
{
|
|
__asm__ (
|
|
"lui $26, %hi(SavedSP)\n"
|
|
"lq $26, %lo(SavedSP)($26)\n"
|
|
);
|
|
__asm__ (
|
|
"addiu $26, %0\n"
|
|
: : "i"(-sizeof(struct threadCtx))
|
|
);
|
|
__asm__ (
|
|
".set noat\n"
|
|
"lui $1, %hi(SavedAT)\n"
|
|
"lq $1, %lo(SavedAT)($1)\n"
|
|
"sq $1, 0x000($26)\n"
|
|
"sq $2, 0x010($26)\n"
|
|
"sq $3, 0x020($26)\n"
|
|
"sq $4, 0x030($26)\n"
|
|
"sq $5, 0x040($26)\n"
|
|
"sq $6, 0x050($26)\n"
|
|
"sq $7, 0x060($26)\n"
|
|
"sq $8, 0x070($26)\n"
|
|
"sq $9, 0x080($26)\n"
|
|
"sq $10, 0x090($26)\n"
|
|
"sq $11, 0x0A0($26)\n"
|
|
"sq $12, 0x0B0($26)\n"
|
|
"sq $13, 0x0C0($26)\n"
|
|
"sq $14, 0x0D0($26)\n"
|
|
"sq $15, 0x0E0($26)\n"
|
|
"sq $16, 0x0F0($26)\n"
|
|
"sq $17, 0x100($26)\n"
|
|
"sq $18, 0x110($26)\n"
|
|
"sq $19, 0x120($26)\n"
|
|
"sq $20, 0x130($26)\n"
|
|
"sq $21, 0x140($26)\n"
|
|
"sq $22, 0x150($26)\n"
|
|
"sq $23, 0x160($26)\n"
|
|
"sq $24, 0x170($26)\n"
|
|
"sq $25, 0x180($26)\n"
|
|
"sq $gp, 0x190($26)\n"
|
|
"lui $1, %hi(SavedSP)\n"
|
|
"lq $sp, %lo(SavedSP)($1)\n"
|
|
"sq $sp, 0x1A0($26)\n"
|
|
"sq $fp, 0x1B0($26)\n"
|
|
"lui $1, %hi(SavedRA)\n"
|
|
"lq $1, %lo(SavedRA)($1)\n"
|
|
"sq $1, 0x1C0($26)\n"
|
|
|
|
"swc1 $0, 0x200($26)\n"
|
|
"swc1 $1, 0x204($26)\n"
|
|
"swc1 $2, 0x208($26)\n"
|
|
"swc1 $3, 0x20C($26)\n"
|
|
"swc1 $4, 0x210($26)\n"
|
|
"swc1 $5, 0x214($26)\n"
|
|
"swc1 $6, 0x218($26)\n"
|
|
"swc1 $7, 0x21C($26)\n"
|
|
"swc1 $8, 0x220($26)\n"
|
|
"swc1 $9, 0x224($26)\n"
|
|
"swc1 $10, 0x228($26)\n"
|
|
"swc1 $11, 0x22C($26)\n"
|
|
"swc1 $12, 0x230($26)\n"
|
|
"swc1 $13, 0x234($26)\n"
|
|
"swc1 $14, 0x238($26)\n"
|
|
"swc1 $15, 0x23C($26)\n"
|
|
"swc1 $16, 0x240($26)\n"
|
|
"swc1 $17, 0x244($26)\n"
|
|
"swc1 $18, 0x248($26)\n"
|
|
"swc1 $19, 0x24C($26)\n"
|
|
"swc1 $20, 0x250($26)\n"
|
|
"swc1 $21, 0x254($26)\n"
|
|
"swc1 $22, 0x258($26)\n"
|
|
"swc1 $23, 0x25C($26)\n"
|
|
"swc1 $24, 0x260($26)\n"
|
|
"swc1 $25, 0x264($26)\n"
|
|
"swc1 $26, 0x268($26)\n"
|
|
"swc1 $27, 0x26C($26)\n"
|
|
"swc1 $28, 0x270($26)\n"
|
|
"swc1 $29, 0x274($26)\n"
|
|
"swc1 $30, 0x278($26)\n"
|
|
"swc1 $31, 0x27C($26)\n"
|
|
|
|
"mfsa $1\n"
|
|
"sw $1, 0x1F0($26)\n"
|
|
|
|
"cfc1 $1, $31\n"
|
|
"sw $1, 0x1F4($26)\n"
|
|
|
|
"lui $1, 0x8000\n"
|
|
"mtc1 $1, $1\n"
|
|
"mtc1 $1, $0\n"
|
|
"madd.s $f0, $f0, $f1\n"
|
|
"swc1 $0, 0x1F8($26)\n"
|
|
|
|
"mfhi $1\n"
|
|
"sd $1, 0x1D0($26)\n"
|
|
"mfhi1 $1\n"
|
|
"sd $1, 0x1D8($26)\n"
|
|
|
|
"mflo $1\n"
|
|
"sd $1, 0x1E0($26)\n"
|
|
"mflo1 $1\n"
|
|
"sd $1, 0x1E8($26)\n"
|
|
|
|
"lui $1, %hi(SavedSP)\n"
|
|
"sw $26, %lo(SavedSP)($1)\n"
|
|
|
|
"jr $31\n"
|
|
"lui $1, 0x8000\n"
|
|
".set at\n"
|
|
);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80003800
|
|
////////////////////////////////////////////////////////////////////
|
|
void restoreContext()
|
|
{
|
|
__asm__ (
|
|
".set noat\n"
|
|
|
|
"lui $26, 0x8000\n"
|
|
"mtc1 $26, $1\n"
|
|
"lwc1 $0, 0x1F8($sp)\n"
|
|
"adda.s $f0, $f1\n"
|
|
|
|
"lw $26, 0x1F0($sp)\n"
|
|
"mtsa $26\n"
|
|
|
|
"lw $26, 0x1F4($sp)\n"
|
|
"ctc1 $26, $31\n"
|
|
|
|
"ld $26, 0x1D0($sp)\n"
|
|
"mthi $26\n"
|
|
"ld $26, 0x1D8($sp)\n"
|
|
"mthi1 $26\n"
|
|
|
|
"ld $26, 0x1E0($sp)\n"
|
|
"mtlo $26\n"
|
|
"ld $26, 0x1E8($sp)\n"
|
|
"mtlo1 $26\n"
|
|
|
|
"lq $1, 0x000($sp)\n"
|
|
"lq $2, 0x010($sp)\n"
|
|
"lq $3, 0x020($sp)\n"
|
|
"lq $4, 0x030($sp)\n"
|
|
"lq $5, 0x040($sp)\n"
|
|
"lq $6, 0x050($sp)\n"
|
|
"lq $7, 0x060($sp)\n"
|
|
"lq $8, 0x070($sp)\n"
|
|
"lq $9, 0x080($sp)\n"
|
|
"lq $10, 0x090($sp)\n"
|
|
"lq $11, 0x0A0($sp)\n"
|
|
"lq $12, 0x0B0($sp)\n"
|
|
"lq $13, 0x0C0($sp)\n"
|
|
"lq $14, 0x0D0($sp)\n"
|
|
"lq $15, 0x0E0($sp)\n"
|
|
"lq $16, 0x0F0($sp)\n"
|
|
"lq $17, 0x100($sp)\n"
|
|
"lq $18, 0x110($sp)\n"
|
|
"lq $19, 0x120($sp)\n"
|
|
"lq $20, 0x130($sp)\n"
|
|
"lq $21, 0x140($sp)\n"
|
|
"lq $22, 0x150($sp)\n"
|
|
"lq $23, 0x160($sp)\n"
|
|
"lq $24, 0x170($sp)\n"
|
|
"lq $25, 0x180($sp)\n"
|
|
"lq $gp, 0x190($sp)\n"
|
|
"lq $fp, 0x1B0($sp)\n"
|
|
|
|
"lwc1 $0, 0x200($sp)\n"
|
|
"lwc1 $1, 0x204($sp)\n"
|
|
"lwc1 $2, 0x208($sp)\n"
|
|
"lwc1 $3, 0x20C($sp)\n"
|
|
"lwc1 $4, 0x210($sp)\n"
|
|
"lwc1 $5, 0x214($sp)\n"
|
|
"lwc1 $6, 0x218($sp)\n"
|
|
"lwc1 $7, 0x21C($sp)\n"
|
|
"lwc1 $8, 0x220($sp)\n"
|
|
"lwc1 $9, 0x224($sp)\n"
|
|
"lwc1 $10, 0x228($sp)\n"
|
|
"lwc1 $11, 0x22C($sp)\n"
|
|
"lwc1 $12, 0x230($sp)\n"
|
|
"lwc1 $13, 0x234($sp)\n"
|
|
"lwc1 $14, 0x238($sp)\n"
|
|
"lwc1 $15, 0x23C($sp)\n"
|
|
"lwc1 $16, 0x240($sp)\n"
|
|
"lwc1 $17, 0x244($sp)\n"
|
|
"lwc1 $18, 0x248($sp)\n"
|
|
"lwc1 $19, 0x24C($sp)\n"
|
|
"lwc1 $20, 0x250($sp)\n"
|
|
"lwc1 $21, 0x254($sp)\n"
|
|
"lwc1 $22, 0x258($sp)\n"
|
|
"lwc1 $23, 0x25C($sp)\n"
|
|
"lwc1 $24, 0x260($sp)\n"
|
|
"lwc1 $25, 0x264($sp)\n"
|
|
"lwc1 $26, 0x268($sp)\n"
|
|
"lwc1 $27, 0x26C($sp)\n"
|
|
"lwc1 $28, 0x270($sp)\n"
|
|
"lwc1 $29, 0x274($sp)\n"
|
|
"lwc1 $30, 0x278($sp)\n"
|
|
"lwc1 $31, 0x27C($sp)\n"
|
|
"daddu $26, $31, $0\n"
|
|
"lq $31, 0x1C0($sp)\n"
|
|
"jr $26\n"
|
|
"lq $sp, 0x1A0($sp)\n"
|
|
".set at\n"
|
|
);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80003940
|
|
////////////////////////////////////////////////////////////////////
|
|
void _ThreadHandler(u32 epc, u32 stack)
|
|
{
|
|
register int tid;
|
|
|
|
threads_array[threadId].entry =(void*)epc;
|
|
threads_array[threadId].status =THS_READY;
|
|
threads_array[threadId].stack_res =(void*)stack;
|
|
|
|
for ( ; threadPrio < 129; threadPrio++)
|
|
if ((thread_ll_priorities[threadPrio].next !=
|
|
&thread_ll_priorities[threadPrio]) ||
|
|
(thread_ll_priorities[threadPrio].prev !=
|
|
&thread_ll_priorities[threadPrio])){
|
|
tid=threadId=(( (u32)thread_ll_priorities[threadPrio].prev -
|
|
(u32)threads_array)*0x286BCA1B)>>2;
|
|
break;
|
|
}
|
|
|
|
if (threadPrio>=129){
|
|
__printf("# <Thread> No active threads\n");
|
|
Exit(1);
|
|
tid=0;
|
|
}
|
|
|
|
threads_array[tid].status=THS_RUN;
|
|
|
|
if (threads_array[tid].waitSema){
|
|
threads_array[tid].waitSema=0;
|
|
*(u32*)((u32)threads_array[tid].stack_res + 0x20) = -1;
|
|
}
|
|
|
|
__asm__("move $2, %0\n"
|
|
"move $3, %1\n"
|
|
: : "r"(threads_array[tid].entry), "r"(threads_array[tid].stack_res) );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80003A78
|
|
////////////////////////////////////////////////////////////////////
|
|
void _ChangeThread(u32 entry, u32 stack_res, int waitSema)
|
|
{
|
|
struct TCB *th;
|
|
struct ll *l, *p;
|
|
int prio;
|
|
|
|
th = &threads_array[threadId];
|
|
th->status = THS_WAIT;
|
|
th->waitSema = waitSema;
|
|
th->entry = (void (*)(void*))entry;
|
|
th->stack_res = (void*)stack_res;
|
|
|
|
prio = threadPrio;
|
|
for (l = &thread_ll_priorities[prio]; ; l++, prio++) {
|
|
if (prio >= 129) {
|
|
__printf("# <Thread> No active threads\n");
|
|
Exit(1); l = 0; break;
|
|
}
|
|
|
|
if (l->next != l) { p = l->next; break; }
|
|
if (l->prev == l) continue;
|
|
p = l->prev; break;
|
|
}
|
|
|
|
if (l) {
|
|
threadPrio = prio;
|
|
threadId = (((u32)p - (u32)threads_array) * 0x286BCA1B) / 4;
|
|
}
|
|
|
|
th = &threads_array[threadId];
|
|
th->status = THS_RUN;
|
|
if (th->waitSema) {
|
|
th->waitSema = 0;
|
|
*(s64*)((u32)th->stack_res+0x20) = -1;
|
|
}
|
|
|
|
__asm__("move $2, %0\n"
|
|
"move $3, %1\n"
|
|
: : "r"(th->entry), "r"(th->stack_res) );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80003C50 SYSCALL 032 CreateThread
|
|
////////////////////////////////////////////////////////////////////
|
|
int _CreateThread(struct ThreadParam *param)
|
|
{
|
|
struct TCB *th;
|
|
struct threadCtx *thctx;
|
|
int index;
|
|
int *ptr;
|
|
|
|
th = (struct TCB *)LL_unlink((struct ll*)&thread_ll_free);
|
|
if (th == NULL) {
|
|
__printf("%s: failed to get free thread\n", __FUNCTION__);
|
|
return -1;
|
|
}
|
|
|
|
threads_count++;
|
|
index=(((u32)th-(u32)threads_array) * 0x286BCA1B)/4;
|
|
|
|
th->entry = param->entry;
|
|
th->stack_res = param->stack + param->stackSize - STACK_RES;
|
|
th->status = THS_DORMANT;
|
|
th->gpReg = param->gpReg;
|
|
th->initPriority = param->initPriority;
|
|
th->argstring = 0;
|
|
th->wakeupCount = 0;
|
|
th->semaId = 0;
|
|
th->stack = param->stack;
|
|
th->argc = 0;
|
|
th->entry_ = param->entry;
|
|
th->heap_base = threads_array[threadId].heap_base;
|
|
th->stackSize = param->stackSize;
|
|
th->currentPriority = param->initPriority;
|
|
th->waitSema = 0;
|
|
th->root = threads_array[threadId].root;
|
|
|
|
thctx = th->stack_res;
|
|
thctx->gp = (u32)param->gpReg;
|
|
thctx->sp = (u32)&thctx[1];
|
|
thctx->fp = (u32)&thctx[1];
|
|
thctx->ra = (u32)threads_array[threadId].root;
|
|
|
|
return index;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80003E00 SYSCALL 37 iTerminateThread
|
|
////////////////////////////////////////////////////////////////////
|
|
int _iTerminateThread(int tid)
|
|
{
|
|
//TODO
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80003F00
|
|
////////////////////////////////////////////////////////////////////
|
|
int __DeleteThread(int tid)
|
|
{
|
|
if ((tid>=256) || (tid==threadId) || (threads_array[tid].status!=THS_DORMANT))
|
|
return -1;
|
|
|
|
releaseTCB(tid);
|
|
return tid;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80003F70
|
|
////////////////////////////////////////////////////////////////////
|
|
int __StartThread(int tid, void *arg)
|
|
{
|
|
if ((tid>=256) || (tid==threadId) || (threads_array[tid].status!=THS_DORMANT))
|
|
return -1;
|
|
|
|
threads_array[tid].argstring = arg;
|
|
((void**)threads_array[tid].stack_res)[0x10] = arg; //a0
|
|
thread_2_ready(tid);
|
|
return tid;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80003FF8
|
|
////////////////////////////////////////////////////////////////////
|
|
int __ExitThread()
|
|
{
|
|
//TODO
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004110
|
|
////////////////////////////////////////////////////////////////////
|
|
int __ExitDeleteThread()
|
|
{
|
|
//TODO
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004228 SYSCALL 39 DisableDispatchThread
|
|
////////////////////////////////////////////////////////////////////
|
|
int _DisableDispatchThread()
|
|
{
|
|
__printf("# DisableDispatchThread is not supported in this version\n");
|
|
return threadId;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004258 SYSCALL 40 EnableDispatchThread
|
|
////////////////////////////////////////////////////////////////////
|
|
int _EnableDispatchThread()
|
|
{
|
|
__printf("# EnableDispatchThread is not supported in this version\n");
|
|
return threadId;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004288 SYSCALL 042 iChangeThreadPriority
|
|
////////////////////////////////////////////////////////////////////
|
|
int _iChangeThreadPriority(int tid, int prio)
|
|
{
|
|
short oldPrio;
|
|
|
|
if ((tid >= 256) || (prio < 0) || (prio >= 128)) return -1;
|
|
|
|
if (tid == 0) tid = threadId;
|
|
if (threads_array[tid].status == 0) return -1;
|
|
if ((0 < (threads_array[tid].status ^ 0x10)) == 0) return -1;
|
|
|
|
oldPrio = threads_array[tid].currentPriority;
|
|
if ((tid != threadId) && (threads_array[tid].status != THS_READY)) {
|
|
threads_array[tid].currentPriority = prio;
|
|
return oldPrio;
|
|
}
|
|
|
|
if (threadPrio < prio) threadStatus = 1;
|
|
|
|
unsetTCB(tid);
|
|
threads_array[tid].currentPriority = prio;
|
|
thread_2_ready(tid);
|
|
|
|
return oldPrio;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004388 SYSCALL 044 iRotateThreadReadyQueue
|
|
////////////////////////////////////////////////////////////////////
|
|
int _iRotateThreadReadyQueue(int prio)
|
|
{
|
|
if (prio >= 128) return -1;
|
|
|
|
LL_rotate(&thread_ll_priorities[prio]);
|
|
return prio;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800043D0 SYSCALL 046 iReleaseWaitThread
|
|
////////////////////////////////////////////////////////////////////
|
|
int _iReleaseWaitThread(int tid)
|
|
{
|
|
if( (u32)(tid-1) >= 255 )
|
|
return -1;
|
|
|
|
if( (u32)threads_array[tid].status >= 17 )
|
|
return tid;
|
|
|
|
switch(threads_array[tid].status) {
|
|
case 0:
|
|
return -1;
|
|
case THS_WAIT: {
|
|
//443C
|
|
if( threads_array[tid].waitSema == 2 ) {
|
|
LL_unlinkthis((struct ll*)&threads_array[tid]);
|
|
semas_array[threads_array[tid].semaId].wait_threads--;
|
|
}
|
|
|
|
int threadPrioOld = threadPrio;
|
|
threads_array[tid].status = THS_READY;
|
|
thread_2_ready(tid);
|
|
|
|
if( threadPrio < threadPrioOld ) {
|
|
threadStatus = 1;
|
|
}
|
|
break;
|
|
}
|
|
case (THS_WAIT|THS_SUSPEND):
|
|
threads_array[tid].status = THS_SUSPEND;
|
|
if( threads_array[tid].waitSema != 2 )
|
|
return tid;
|
|
|
|
LL_unlinkthis((struct ll*)&threads_array[tid]);
|
|
semas_array[threads_array[tid].semaId].wait_threads--;
|
|
break;
|
|
}
|
|
|
|
return tid;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004548 SYSCALL 047 GetThreadId
|
|
////////////////////////////////////////////////////////////////////
|
|
int _GetThreadId()
|
|
{
|
|
return threadId;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004558 SYSCALL 048 ReferThreadStatus
|
|
////////////////////////////////////////////////////////////////////
|
|
int _ReferThreadStatus(int tid, struct ThreadParam *info)
|
|
{
|
|
if (tid >= 256) return -1;
|
|
if (tid == 0) tid = threadId;
|
|
|
|
if (info != NULL) {
|
|
info->entry = threads_array[tid].entry;
|
|
info->status = threads_array[tid].status;
|
|
info->stack = threads_array[tid].stack;
|
|
info->stackSize = threads_array[tid].stackSize;
|
|
info->gpReg = threads_array[tid].gpReg;
|
|
info->initPriority = threads_array[tid].initPriority;
|
|
info->currentPriority = threads_array[tid].currentPriority;
|
|
info->attr = threads_array[tid].attr;
|
|
info->waitSema = threads_array[tid].waitSema;
|
|
info->option = threads_array[tid].option;
|
|
info->waitId = threads_array[tid].semaId;
|
|
info->wakeupCount = threads_array[tid].wakeupCount;
|
|
}
|
|
|
|
return threads_array[tid].status;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004658
|
|
////////////////////////////////////////////////////////////////////
|
|
int __SleepThread()
|
|
{
|
|
if (threads_array[threadId].wakeupCount <= 0) {
|
|
unsetTCB(threadId);
|
|
return -1;
|
|
}
|
|
|
|
threads_array[threadId].wakeupCount--;
|
|
return threadId;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800046B0 SYSCALL 052 iWakeupThread
|
|
////////////////////////////////////////////////////////////////////
|
|
int _iWakeupThread(int tid)
|
|
{
|
|
register int prio;
|
|
|
|
if (tid>=256) return -1;
|
|
|
|
if (tid==0) tid = threadId;
|
|
|
|
switch (threads_array[tid].status){
|
|
case THS_WAIT:
|
|
if (threads_array[tid].waitSema=1){
|
|
prio=threadPrio;
|
|
thread_2_ready(tid);
|
|
if (threadPrio<prio)
|
|
threadStatus=THS_RUN;
|
|
threads_array[tid].waitSema=0;
|
|
}else
|
|
threads_array[tid].wakeupCount++;
|
|
break;
|
|
case THS_READY:
|
|
case THS_SUSPEND:
|
|
threads_array[tid].wakeupCount++;
|
|
break;
|
|
case (THS_WAIT|THS_SUSPEND):
|
|
if (threads_array[tid].waitSema==1){
|
|
threads_array[tid].status=THS_SUSPEND;
|
|
threads_array[tid].waitSema=0;
|
|
}else
|
|
threads_array[tid].wakeupCount++;
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
return tid;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004808 SYSCALL 055 SuspendThread
|
|
//80004808 SYSCALL 056 iSuspendThread
|
|
////////////////////////////////////////////////////////////////////
|
|
int _SuspendThread(int thid)
|
|
{
|
|
if (thid<256){
|
|
if ((threads_array[thid].status==THS_READY) ||
|
|
(threads_array[thid].status==THS_RUN)){
|
|
unsetTCB(thid);
|
|
threads_array[thid].status=THS_SUSPEND;
|
|
return thid;
|
|
}
|
|
if (threads_array[thid].status==THS_WAIT){
|
|
threads_array[thid].status=(THS_WAIT|THS_SUSPEND);
|
|
return thid;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800048C0 SYSCALL 058 iResumeThread
|
|
////////////////////////////////////////////////////////////////////
|
|
int _iResumeThread(int tid)
|
|
{
|
|
int tmp;
|
|
if ((tid<256) && (threadId!=tid)) {
|
|
if (threads_array[tid].status==THS_SUSPEND){
|
|
tmp=threadPrio;
|
|
thread_2_ready(tid);
|
|
if (threadPrio < tmp)
|
|
threadStatus=THS_RUN;
|
|
}
|
|
else if (threads_array[tid].status==(THS_WAIT|THS_SUSPEND))
|
|
threads_array[tid].status=THS_WAIT;
|
|
return tid;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004970 SYSCALL 053 CancelWakeupThread
|
|
//80004970 SYSCALL 054 iCancelWakeupThread
|
|
////////////////////////////////////////////////////////////////////
|
|
int _CancelWakeupThread(int tid)
|
|
{
|
|
register int ret;
|
|
|
|
if (tid>=256) return -1;
|
|
tid = tid ? tid : threadId;
|
|
ret=threads_array[tid].wakeupCount;
|
|
threads_array[tid].wakeupCount=0;
|
|
return ret;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800049B0 SYSCALL 080 RFU080_CreateEventFlag
|
|
////////////////////////////////////////////////////////////////////
|
|
int _CreateEventFlag()
|
|
{
|
|
return threads_count; // CreateEventFlag, why!?!
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800049C0 SYSCALL 064 CreateSema
|
|
////////////////////////////////////////////////////////////////////
|
|
int _CreateSema(struct SemaParam *sema)
|
|
{
|
|
register struct kSema *crt=semas_last;
|
|
|
|
if ((crt==NULL) || (sema->init_count<0)) return -1;
|
|
|
|
crt->wait_prev = (struct TCB*)&crt->wait_next;
|
|
semas_count++;
|
|
crt->count =sema->init_count;
|
|
crt->wait_next =(struct TCB*)&crt->wait_next;
|
|
semas_last = crt->free;
|
|
crt->max_count =sema->max_count;
|
|
crt->free =NULL;
|
|
crt->attr =sema->attr;
|
|
crt->wait_threads=0;
|
|
crt->option =sema->option;
|
|
|
|
return (crt-semas_array); //sizeof(kSema)==32
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004A48 SYSCALL 073 iDeleteSema
|
|
////////////////////////////////////////////////////////////////////
|
|
int _iDeleteSema(int sid)
|
|
{
|
|
register thid, thprio;
|
|
if ((sid>=MAX_SEMAS) || (semas_array[sid].count<0)) return -1;
|
|
|
|
semas_count--;
|
|
while (semas_array[sid].wait_threads>0){
|
|
thid=(((u32)LL_unlink((struct ll*)&semas_array[sid].wait_next)-(u32)threads_array) * 0x286BCA1B)/4;
|
|
LL_unlinkthis((struct ll*)&threads_array[thid]);
|
|
semas_array[sid].wait_threads--;
|
|
if (threads_array[thid].status==THS_WAIT){
|
|
thprio=threadPrio;
|
|
thread_2_ready(thid);
|
|
if (threadPrio<thprio)
|
|
threadStatus=THS_RUN;
|
|
}
|
|
else if (threads_array[thid].status!=(THS_WAIT|THS_SUSPEND))
|
|
threads_array[thid].status=THS_SUSPEND;
|
|
}
|
|
semas_array[sid].count =-1;
|
|
semas_array[sid].free =semas_last;
|
|
semas_last =&semas_array[sid];
|
|
return sid;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004BC8 SYSCALL 067 iSignalSema
|
|
////////////////////////////////////////////////////////////////////
|
|
int _iSignalSema(int sid)
|
|
{
|
|
register int prio, thid;
|
|
if ((sid>=MAX_SEMAS) || (semas_array[sid].count<0)) return -1;
|
|
|
|
if (semas_array[sid].wait_threads>0){
|
|
thid=(((u32)LL_unlink((struct ll*)&semas_array[sid].wait_next)-(u32)threads_array)*0x286BCA1B)/4;
|
|
|
|
LL_unlinkthis((struct ll*)&threads_array[thid]);
|
|
|
|
semas_array[sid].wait_threads--;
|
|
|
|
if (threads_array[thid].status==THS_WAIT){
|
|
prio=threadPrio;
|
|
thread_2_ready(thid);
|
|
if (threadPrio < prio)
|
|
threadStatus=THS_RUN;
|
|
threads_array[thid].waitSema=0; //just a guess:P
|
|
}
|
|
else if (threads_array[thid].status==(THS_WAIT|THS_SUSPEND)){
|
|
threads_array[thid].status =THS_SUSPEND;
|
|
threads_array[thid].waitSema=0;
|
|
}
|
|
}else
|
|
semas_array[sid].count++;
|
|
return sid;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004CF8
|
|
////////////////////////////////////////////////////////////////////
|
|
int _iWaitSema(int sid)
|
|
{
|
|
if ((sid>=MAX_SEMAS) || (semas_array[sid].count<0)) return -1;
|
|
|
|
if (semas_array[sid].count>0){
|
|
semas_array[sid].count--;
|
|
return sid;
|
|
}
|
|
|
|
semas_array[sid].wait_threads++;
|
|
|
|
unsetTCB(threadId);
|
|
LL_add((struct ll*)&semas_array[sid].wait_next, (struct ll*)&threads_array[threadId]);
|
|
threads_array[threadId].semaId=sid;
|
|
|
|
return -2;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004DC8 SYSCALL 069 PollSema, 070 iPollSema
|
|
////////////////////////////////////////////////////////////////////
|
|
int _PollSema(int sid)
|
|
{
|
|
if ((sid>=MAX_SEMAS) || (semas_array[sid].count<=0)) return -1;
|
|
|
|
semas_array[sid].count--;
|
|
|
|
return sid;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004E00 SYSCALL 071 ReferSemaStatus, 072 iReferSemaStatus
|
|
////////////////////////////////////////////////////////////////////
|
|
int _ReferSemaStatus(int sid, struct SemaParam *sema)
|
|
{
|
|
if ((sid>=MAX_SEMAS) || (semas_array[sid].count<0)) return -1;
|
|
|
|
sema->count =semas_array[sid].count;
|
|
sema->max_count =semas_array[sid].max_count;
|
|
sema->wait_threads =semas_array[sid].wait_threads;
|
|
sema->attr =semas_array[sid].attr;
|
|
sema->option =semas_array[sid].option;
|
|
|
|
return sid;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004E58 SYSCALL 081 RFU081_DeleteEventFlag
|
|
////////////////////////////////////////////////////////////////////
|
|
int _DeleteEventFlag()
|
|
{
|
|
return semas_count; // DeleteEventFlag, why!?!
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004E68
|
|
////////////////////////////////////////////////////////////////////
|
|
int _SemasInit()
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<256; i++) {
|
|
semas_array[i].free = &semas_array[i+1];
|
|
semas_array[i].count = -1;
|
|
semas_array[i].wait_threads = 0;
|
|
semas_array[i].wait_next = (struct TCB*)&semas_array[i].wait_next;
|
|
semas_array[i].wait_prev = (struct TCB*)&semas_array[i].wait_next;
|
|
}
|
|
semas_array[255].free = 0;
|
|
|
|
semas_last = semas_array;
|
|
semas_count = 0;
|
|
|
|
return 256;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004EC8
|
|
////////////////////////////////////////////////////////////////////
|
|
void __load_module_EENULL()
|
|
{
|
|
int i;
|
|
|
|
thread_ll_free.prev = &thread_ll_free;
|
|
thread_ll_free.next = &thread_ll_free;
|
|
|
|
for (i=0; i<128; i++) {
|
|
thread_ll_priorities[i].prev = &thread_ll_priorities[i];
|
|
thread_ll_priorities[i].next = &thread_ll_priorities[i];
|
|
}
|
|
|
|
threads_count = 0;
|
|
threadId = 0;
|
|
threadPrio = 0;
|
|
|
|
for (i=0; i<256; i++) {
|
|
threads_array[i].status = 0;
|
|
LL_add(&thread_ll_free, (struct ll*)&threads_array[i]);
|
|
}
|
|
|
|
_SemasInit();
|
|
|
|
threadStatus = 0;
|
|
__load_module("EENULL", (void (*)(void*))0x81FC0, (void*)0x81000, 0x80);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80004FB0
|
|
// makes the args from argc & argstring; args is in bss of program
|
|
////////////////////////////////////////////////////////////////////
|
|
void _InitArgs(char *argstring, ARGS *args, int argc)
|
|
{
|
|
int i;
|
|
char *p = args->args;
|
|
|
|
args->argc = argc;
|
|
for (i=0; i<argc; i++) {
|
|
args->argv[i] = p; //copy string pointer
|
|
while (*argstring) //copy the string itself
|
|
*p++ = *argstring++;
|
|
*p++ = *argstring++; //copy the '\0'
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80005198 SYSCALL 060 _InitializeMainThread
|
|
////////////////////////////////////////////////////////////////////
|
|
void *_InitializeMainThread(u32 gp, void *stack, int stack_size, char *args, int root)
|
|
{
|
|
struct TCB *th;
|
|
struct threadCtx *ctx;
|
|
|
|
if ((int)stack == -1)
|
|
stack = (void*)((_GetMemorySize() - 4*1024) - stack_size);
|
|
|
|
ctx = (struct threadCtx*)((u32)stack + stack_size - STACK_RES/4);
|
|
ctx->gp = gp; //+1C0
|
|
ctx->ra = root; //+1F0
|
|
ctx->fp = (u32)ctx+0x280; //+1E0 <- &280
|
|
ctx->sp = (u32)ctx+0x280; //+1D0 <- &280
|
|
|
|
th = &threads_array[threadId];
|
|
th->gpReg = (void*)gp;
|
|
th->stackSize = stack_size;
|
|
th->stack_res = ctx;
|
|
th->stack = stack;
|
|
th->root = (void*)root;
|
|
_InitArgs(th->argstring, (ARGS*)args, th->argc);
|
|
th->argstring = args;
|
|
|
|
return ctx;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800052A0 SYSCALL 061 RFU061_InitializeHeapArea
|
|
////////////////////////////////////////////////////////////////////
|
|
void* _InitializeHeapArea(void *heap_base, int heap_size)
|
|
{
|
|
void *ret;
|
|
|
|
if (heap_size < 0) {
|
|
ret = threads_array[threadId].stack;
|
|
} else {
|
|
ret = heap_base + heap_size;
|
|
}
|
|
|
|
threads_array[threadId].heap_base = ret;
|
|
return ret;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800052D8 SYSCALL 062 RFU062_EndOfHeap
|
|
////////////////////////////////////////////////////////////////////
|
|
void* _EndOfHeap()
|
|
{
|
|
return threads_array[threadId].heap_base;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80005390
|
|
////////////////////////////////////////////////////////////////////
|
|
int __load_module(char *name, void (*entry)(void*), void *stack_res, int prio)
|
|
{
|
|
struct TCB *th;
|
|
int index;
|
|
int *ptr;
|
|
struct rominfo ri;
|
|
|
|
th = (struct TCB*)LL_unlink(&thread_ll_free);
|
|
if (th) {
|
|
threads_count++;
|
|
index = (((u32)th-(u32)threads_array) * 0x286BCA1B)/4;
|
|
} else {
|
|
index = -1;
|
|
}
|
|
|
|
threadId = index;
|
|
th->wakeupCount = 0;
|
|
th->semaId = 0;
|
|
th->attr = 0;
|
|
th->stack_res = stack_res;
|
|
th->option = 0;
|
|
th->entry = entry;
|
|
th->gpReg = 0;
|
|
th->currentPriority = prio;
|
|
th->status = THS_DORMANT;
|
|
th->waitSema = 0;
|
|
th->entry_ = entry;
|
|
th->argc = 0;
|
|
th->argstring = 0;
|
|
th->initPriority = prio;
|
|
|
|
thread_2_ready(index);
|
|
|
|
if (romdirGetFile(name, &ri) == NULL) {
|
|
__printf("# panic ! '%s' not found\n", name);
|
|
_Exit(1);
|
|
}
|
|
|
|
if (ri.fileSize > 0) {
|
|
int i;
|
|
int *src = (int*)(0xbfc00000+ri.fileOffset);
|
|
int *dst = (int*)entry;
|
|
|
|
for (i=0; i<ri.fileSize; i+=4) {
|
|
*dst++ = *src++;
|
|
}
|
|
}
|
|
|
|
FlushInstructionCache();
|
|
FlushDataCache();
|
|
|
|
return index;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80005560 eestrcpy
|
|
////////////////////////////////////////////////////////////////////
|
|
char* eestrcpy(char* dst, const char* src)
|
|
{
|
|
while( *src )
|
|
*dst++ = *src++;
|
|
|
|
*dst = 0;
|
|
return dst+1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800055A0 SYSCALL 6 LoadPS2Exe
|
|
////////////////////////////////////////////////////////////////////
|
|
int _LoadPS2Exe(char *filename, int argc, char **argv)
|
|
{
|
|
char* pbuf;
|
|
struct rominfo ri;
|
|
struct TCB* curtcb;
|
|
int curthreadid;
|
|
|
|
pbuf = eestrcpy(threadArgStrBuffer, "EELOAD");
|
|
pbuf = eestrcpy(pbuf, filename);
|
|
|
|
if( argc > 0 ) {
|
|
int i;
|
|
for(i = 0; i < argc; ++i)
|
|
pbuf = strcpy(pbuf, argv[i]);
|
|
}
|
|
|
|
threads_array[threadId].argc = argc+2;
|
|
threads_array[threadId].argstring = threadArgStrBuffer;
|
|
_CancelWakeupThread(threadId);
|
|
_iChangeThreadPriority(threadId, 0);
|
|
|
|
// search for RESET
|
|
// search for filename romdir entry
|
|
if( romdirGetFile(filename, &ri) == NULL ) {
|
|
__printf("# panic ! '%s' not found\n", filename);
|
|
_Exit();
|
|
}
|
|
|
|
// terminate threads
|
|
curthreadid = 1; // skip main thread?
|
|
curtcb = &threads_array[curthreadid];
|
|
|
|
while(curthreadid < 256) {
|
|
if( curtcb->status && threadId != curthreadid ) {
|
|
if( curtcb->status == THS_DORMANT ) {
|
|
_DeleteThread(curthreadid);
|
|
}
|
|
else {
|
|
iTerminateThread(curthreadid);
|
|
_DeleteThread(curthreadid);
|
|
}
|
|
}
|
|
++curthreadid;
|
|
++curtcb;
|
|
}
|
|
|
|
_SemasInit();
|
|
threadStatus = 0;
|
|
InitPgifHandler2();
|
|
|
|
Restart();
|
|
|
|
if( ri.fileSize > 0 ) {
|
|
// copy to PS2_LOADADDR
|
|
int i;
|
|
u32* psrc = (u32*)(0xbfc00000+ri.fileOffset);
|
|
u32* pdst = (u32*)PS2_LOADADDR;
|
|
for(i = 0; i < ri.fileSize; i += 4)
|
|
*pdst++ = *psrc++;
|
|
}
|
|
|
|
FlushInstructionCache();
|
|
FlushDataCache();
|
|
|
|
__asm__("mtc0 %0, $14\n"
|
|
"sync\n" : : "r"(PS2_LOADADDR));
|
|
erase_cpu_regs();
|
|
__asm__("di\n"
|
|
"eret\n");
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800057E8
|
|
////////////////////////////////////////////////////////////////////
|
|
void* __ExecPS2(void * entry, void * gp, int argc, char ** argv)
|
|
{
|
|
char* pbuf = threadArgStrBuffer;
|
|
int i;
|
|
|
|
if( argc > 0 ) {
|
|
for(i = 0; i < argc; ++i)
|
|
pbuf = eestrcpy(pbuf, argv[i]);
|
|
}
|
|
|
|
threads_array[threadId].entry = entry; //0C
|
|
threads_array[threadId].wakeupCount = 0; //24
|
|
threads_array[threadId].gpReg = gp; //14
|
|
threads_array[threadId].semaId = 0; //20
|
|
threads_array[threadId].argstring = threadArgStrBuffer; //38
|
|
threads_array[threadId].argc = argc; //34
|
|
threads_array[threadId].entry_ = entry; //30
|
|
threads_array[threadId].currentPriority = 0; //18
|
|
threads_array[threadId].waitSema = 0; //1C
|
|
threads_array[threadId].initPriority = 0;
|
|
FlushInstructionCache();
|
|
FlushDataCache();
|
|
|
|
return entry;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800058E8
|
|
////////////////////////////////////////////////////////////////////
|
|
int _ExecOSD(int argc, char **argv)
|
|
{
|
|
return _LoadPS2Exe("rom0:OSDSYS", argc, argv);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80005900
|
|
////////////////////////////////////////////////////////////////////
|
|
int _RFU004_Exit()
|
|
{
|
|
char *bb = "BootBrowser";
|
|
return _LoadPS2Exe("rom0:OSDSYS", 1, &bb);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80005938
|
|
////////////////////////////////////////////////////////////////////
|
|
void releaseTCB(int tid)
|
|
{
|
|
threads_count--;
|
|
threads_array[tid].status=0;
|
|
LL_add(&thread_ll_free, (struct ll*)&threads_array[tid]);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80005978
|
|
////////////////////////////////////////////////////////////////////
|
|
void unsetTCB(int tid)
|
|
{
|
|
if ((threads_array[tid].status) <= THS_READY)
|
|
LL_unlinkthis((struct ll*)&threads_array[tid]);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800059B8
|
|
////////////////////////////////////////////////////////////////////
|
|
void thread_2_ready(int tid)
|
|
{
|
|
threads_array[tid].status=THS_READY;
|
|
if (threads_array[tid].initPriority < threadPrio)
|
|
threadPrio=(short)threads_array[tid].initPriority;
|
|
LL_add( &thread_ll_priorities[threads_array[tid].initPriority], (struct ll*)&threads_array[tid] );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80005A58
|
|
////////////////////////////////////////////////////////////////////
|
|
struct ll* LL_unlink(struct ll *l)
|
|
{
|
|
struct ll *p;
|
|
|
|
if ((l==l->next) && (l==l->prev))
|
|
return 0;
|
|
p=l->prev;
|
|
p->prev->next=p->next;
|
|
p->next->prev=p->prev;
|
|
return p;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80005A98
|
|
////////////////////////////////////////////////////////////////////
|
|
struct ll* LL_rotate(struct ll *l)
|
|
{
|
|
struct ll *p;
|
|
|
|
if (p=LL_unlink(l)){
|
|
p->prev=l;
|
|
p->next=l->next;
|
|
l->next->prev=p;
|
|
l->next=p;
|
|
return l->prev;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80005AE8
|
|
////////////////////////////////////////////////////////////////////
|
|
struct ll *LL_unlinkthis(struct ll *l)
|
|
{
|
|
l->prev->next=l->next;
|
|
l->next->prev=l->prev;
|
|
return l->next;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80005B08
|
|
////////////////////////////////////////////////////////////////////
|
|
void LL_add(struct ll *l, struct ll *new)
|
|
{
|
|
new->prev=l;
|
|
new->next=l->next;
|
|
l->next->prev=new;
|
|
l->next=new;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80005B28 SYSCALL 9 (0x09) TlbWriteRandom
|
|
////////////////////////////////////////////////////////////////////
|
|
int _TlbWriteRandom(u32 PageMask, u32 EntryHi, u32 EntryLo0, u32 EntryLo1) {
|
|
if ((EntryHi >> 24) != 4) return -1;
|
|
__asm__ (
|
|
"mfc0 $2, $1\n"
|
|
"mtc0 $2, $0\n"
|
|
"mtc0 $4, $5\n"
|
|
"mtc0 $5, $10\n"
|
|
"mtc0 $6, $2\n"
|
|
"mtc0 $7, $3\n"
|
|
"sync\n"
|
|
"tlbwi\n"
|
|
"sync\n"
|
|
);
|
|
}
|
|
|
|
int _sifGetMSFLG() {
|
|
u32 msflg;
|
|
for (;;) {
|
|
msflg = SBUS_MSFLG;
|
|
__asm__ ("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n");
|
|
__asm__ ("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n");
|
|
__asm__ ("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n");
|
|
|
|
if (msflg == SBUS_MSFLG) return msflg;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80005E58
|
|
////////////////////////////////////////////////////////////////////
|
|
int _sifGetSMFLG() {
|
|
u32 smflg;
|
|
for (;;) {
|
|
smflg = SBUS_SMFLG;
|
|
__asm__ ("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n");
|
|
__asm__ ("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n");
|
|
__asm__ ("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n");
|
|
|
|
if (smflg == SBUS_SMFLG) return smflg;
|
|
}
|
|
}
|
|
|
|
int _ResetSif1()
|
|
{
|
|
sif1tagdata = 0xFFFF001E;
|
|
//*(int*)0xa0001e330 = 0x20000000;
|
|
//*(int*)0xa0001e334 = (u32)ptag&0x0fffffff;
|
|
D6_QWC = 0;
|
|
D6_TAG = (u32)&sif1tagdata&0x0fffffff;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80006198
|
|
////////////////////////////////////////////////////////////////////
|
|
void SifDmaInit()
|
|
{
|
|
int msflg;
|
|
memset(sifEEbuff, 0, sizeof(sifEEbuff));
|
|
memset(sifRegs, 0, sizeof(sifRegs));
|
|
|
|
*(u32*)0xB000F260 = 0xFF;
|
|
D5_CHCR = 0;
|
|
D6_CHCR = 0;
|
|
|
|
_SifSetDChain();
|
|
*(u32*)0xB000F200 = (u32)sifEEbuff;
|
|
__printf("MSFLG = 0x10000\n");
|
|
SBUS_MSFLG = 0x10000;
|
|
msflg = SBUS_MSFLG;
|
|
_ResetSif1();
|
|
_SifSetReg(1, 0);
|
|
|
|
while (!(_SifGetReg(4) & 0x10000)) { __asm__ ("nop\nnop\nnop\nnop\n"); }
|
|
|
|
sifIOPbuff = *(u32*)0xB000F210;
|
|
|
|
SBUS_MSFLG = 0x20000;
|
|
SBUS_MSFLG;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800062A0 SYSCALL 120 (0x78) SifSetDChain
|
|
////////////////////////////////////////////////////////////////////
|
|
void _SifSetDChain(){
|
|
int var_10;
|
|
|
|
D5_CHCR = 0;
|
|
D5_QWC = 0;
|
|
D5_CHCR = 0x184; // 0001 1000 0100
|
|
var_10 = D5_CHCR; // read?
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800062D8 SYSCALL 107 (0x6B) SifStopDma
|
|
////////////////////////////////////////////////////////////////////
|
|
void _SifStopDma(){
|
|
int var_10;
|
|
|
|
D5_CHCR = 0;
|
|
D5_QWC = 0;
|
|
var_10 = D5_CHCR; // read?
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80006370
|
|
////////////////////////////////////////////////////////////////////
|
|
void _SifDmaSend(void *src, void *dest, int size, int attr, int id)
|
|
{
|
|
int qwc;
|
|
struct TAG* t1;
|
|
int *t3;
|
|
int tocopy;
|
|
|
|
if (((++tagindex) & 0xFF) == 31){
|
|
tagindex=0;
|
|
transferscount++;
|
|
}
|
|
|
|
qwc=(size+15)/16; //rount up
|
|
|
|
t1=(struct TAG*)KSEG1_ADDR(&tadrptr[tagindex]);
|
|
if (attr & SIF_DMA_TAG) {
|
|
t1->id_qwc = (id << 16) | qwc |
|
|
((attr & SIF_DMA_INT_I) ? 0x80000000 : 0); //IRQ
|
|
t1->addr=(u32)src & 0x1FFFFFFF;
|
|
t3=(int*)KSEG1_ADDR(src);
|
|
qwc--;
|
|
}
|
|
else {
|
|
if (qwc >= 8){ //two transfers
|
|
tocopy=7;
|
|
t1->id_qwc=0x30000008; //(id)REF | (qwc)8;
|
|
t1->addr=(u32)&extrastorage[tagindex] | 0x1FFFFFFF;
|
|
t3=(int*)KSEG1_ADDR(&extrastorage[tagindex]);
|
|
|
|
if (((++tagindex) & 0xff) == 31){
|
|
tagindex=0;
|
|
transferscount++;
|
|
}
|
|
|
|
t1=(struct TAG*)KSEG1_ADDR(&tadrptr[tagindex]);
|
|
t1->id_qwc=(id << 16) | (qwc - 7) |
|
|
((attr & SIF_DMA_INT_I) ? 0x80000000 : 0);//IRQ
|
|
t1->addr=(u32)(src+112) | 0x1FFFFFFF;
|
|
}
|
|
else {
|
|
tocopy=qwc;
|
|
t1->id_qwc=(id << 16) | (qwc+1) |
|
|
((attr & SIF_DMA_INT_I) ? 0x80000000 : 0);//IRQ
|
|
t1->addr=(u32)&extrastorage[tagindex] & 0x1FFFFFFF;
|
|
t3=(int*)KSEG1_ADDR(&extrastorage[tagindex]);
|
|
}
|
|
memcpy((char*)t3+16, (void*)KSEG1_ADDR(src), tocopy*16);//inline with qwords
|
|
}
|
|
t3[1]=qwc * 4;
|
|
t3[0]=(u32)((u32)dest & 0x00FFFFFF) |
|
|
((((u32)(attr & SIF_DMA_INT_O)) ? 0x40000000 : 0) |
|
|
(((u32)(attr & SIF_DMA_ERT)) ? 0x80000000 : 0));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800065C8
|
|
////////////////////////////////////////////////////////////////////
|
|
int _SifDmaCount()
|
|
{
|
|
register int count;
|
|
|
|
count=((D6_TAG-(u32)tadrptr) & 0x1FFFFFFF) >> 4;
|
|
|
|
count=count>0? count-1:30;
|
|
|
|
if (count == tagindex)
|
|
return (D6_QWC ? 30 : 31);
|
|
|
|
if (count < tagindex)
|
|
return count + 30 - tagindex;
|
|
|
|
return count-tagindex-1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80006650
|
|
////////////////////////////////////////////////////////////////////
|
|
void _SifDmaPrepare(int count)
|
|
{
|
|
register struct TAG *t0;
|
|
|
|
if (count==31) return;
|
|
|
|
t0=(struct TAG*)KSEG1_ADDR(&tadrptr[tagindex]);
|
|
if (count == 30){
|
|
t0->id_qwc &= DMA_TAG_IRQ|DMA_TAG_PCE; //keep PCE|REFE|IRQ
|
|
t0->id_qwc |= DMA_TAG_REF<<28;
|
|
t0->id_qwc |= D6_QWC;
|
|
t0->addr = D6_MADR;
|
|
D6_QWC = 0;
|
|
D6_TAG = KUSEG_ADDR(t0);
|
|
}else
|
|
t0->id_qwc |= DMA_TAG_REF<<28;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800066F8 SYSCALL 119 (0x77) SifSetDma
|
|
////////////////////////////////////////////////////////////////////
|
|
u32 _SifSetDma(SifDmaTransfer_t *sdd, int len)
|
|
{
|
|
int var_10;
|
|
int count, tmp;
|
|
int i, c, _len = len;
|
|
int nextindex;
|
|
|
|
DMAC_ENABLEW = DMAC_ENABLER | 0x10000; //suspend
|
|
|
|
D6_CHCR = 0; //kill any previous transfer?!?
|
|
var_10 = D6_CHCR; // read?
|
|
|
|
DMAC_ENABLEW = DMAC_ENABLER & ~0x10000; //enable
|
|
|
|
count = _SifDmaCount();
|
|
|
|
lenloop:
|
|
i=0; c=0;
|
|
while (_len > 0) {
|
|
if (!(sdd[i].attr & SIF_DMA_TAG)) {
|
|
if (sdd[i].size <= 112) c++;
|
|
else c+=2;
|
|
} else c++;
|
|
_len--; i++;
|
|
}
|
|
if (count < c) { count = 0; goto lenloop; }
|
|
|
|
nextindex = ((tagindex+1) % 31) & 0xff;
|
|
if (nextindex == 0)
|
|
tmp = (transferscount + 1) & 0xFFFF;
|
|
else
|
|
tmp = transferscount;
|
|
|
|
_SifDmaPrepare(count);
|
|
|
|
while (len > 0) {
|
|
_SifDmaSend(sdd->src, sdd->dest, sdd->size, sdd->attr, DMA_TAG_REF<<12);//REF >> 16
|
|
sdd++; len--;
|
|
}
|
|
|
|
_SifDmaSend(sdd->src, sdd->dest, sdd->size, sdd->attr, DMA_TAG_REFE<<12);//REFE >> 16
|
|
|
|
D6_CHCR|= 0x184;
|
|
var_10 = D6_CHCR; // read?
|
|
return (tmp<<16)|(nextindex<<8)|c;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800068B0 SYSCALL 118 (0x76) SifDmaStat
|
|
////////////////////////////////////////////////////////////////////
|
|
int _SifDmaStat(int id)
|
|
{
|
|
//TODO
|
|
return 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80006B60 SYSCALL 121 (0x79) SifSetDma
|
|
////////////////////////////////////////////////////////////////////
|
|
int _SifSetReg(int reg, u32 val)
|
|
{
|
|
__printf("%s: reg=%d; val=%x\n", __FUNCTION__, reg, val);
|
|
|
|
if (reg == 1) {
|
|
*(u32*)0xB000F200 = val;
|
|
return *(u32*)0xB000F200;
|
|
} else
|
|
if (reg == 3) {
|
|
SBUS_MSFLG = val;
|
|
return _sifGetMSFLG();
|
|
} else
|
|
if (reg == 4) {
|
|
SBUS_SMFLG = val;
|
|
return _sifGetSMFLG();
|
|
} else
|
|
if (reg >= 0) {
|
|
return 0;
|
|
}
|
|
|
|
reg&= 0x7FFFFFFF;
|
|
if (reg >= 32) return 0;
|
|
|
|
sifRegs[reg] = val;
|
|
return val;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80006C18 SYSCALL 122 (0x7A) SifSetDma
|
|
////////////////////////////////////////////////////////////////////
|
|
int _SifGetReg(int reg)
|
|
{
|
|
//__printf("%s: reg=%x\n", __FUNCTION__, reg);
|
|
|
|
if (reg == 1) {
|
|
return *(u32*)0xB000F200;
|
|
} else
|
|
if (reg == 2) {
|
|
return *(u32*)0xB000F210;
|
|
} else
|
|
if (reg == 3) {
|
|
return _sifGetMSFLG();
|
|
} else
|
|
if (reg == 4) {
|
|
return _sifGetSMFLG();
|
|
} else
|
|
if (reg >= 0) {
|
|
return 0;
|
|
}
|
|
|
|
reg&= 0x7FFFFFFF;
|
|
if (reg >= 32) return 0;
|
|
|
|
//__printf("ret=%x\n", sifRegs[reg]);
|
|
return sifRegs[reg];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80007428 SYSCALL 117 print
|
|
////////////////////////////////////////////////////////////////////
|
|
void _print()
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800074D8
|
|
////////////////////////////////////////////////////////////////////
|
|
void _SetGsCrt2()
|
|
{
|
|
u32 tmp;
|
|
|
|
tmp = *(int*)0x8001F344;
|
|
if (tmp == 0x40 || tmp == 0x60 || tmp == 0x61) {
|
|
*(char*)0xbf803218 = 0;
|
|
*(char*)0xbf803218 = 2;
|
|
return;
|
|
}
|
|
|
|
*(short*)0xbf801470 = 0;
|
|
*(short*)0xbf801472 = 0;
|
|
*(short*)0xbf801472 = 1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800076B0
|
|
////////////////////////////////////////////////////////////////////
|
|
void _iJoinThread(int param)
|
|
{
|
|
//TODO
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80008A60
|
|
////////////////////////////////////////////////////////////////////
|
|
void _SetGsCrt3(short arg0, short arg1, short arg2)
|
|
{
|
|
__printf("_SetGsCrt3 unimplemented\n");
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80009CE0
|
|
////////////////////////////////////////////////////////////////////
|
|
void _SetGsCrt4(short arg0, short arg1, short arg2)
|
|
{
|
|
__printf("_SetGsCrt4 unimplemented\n");
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//8000A060 SYSCALL 002 SetGsCrt
|
|
////////////////////////////////////////////////////////////////////
|
|
void _SetGsCrt(short arg0, short arg1, short arg2)
|
|
{
|
|
u64 val, val2;
|
|
u64 tmp;
|
|
int count;
|
|
|
|
if (arg1 == 0) {
|
|
tmp = (hvParam >> 3) & 0x7;
|
|
tmp^= 0x2;
|
|
if (tmp == 0) arg1 = 3;
|
|
else arg1 = 2;
|
|
}
|
|
|
|
for (count=0x270f; count >= 0; count--) {
|
|
__asm__ ("nop\nnop\nnop\nnop\nnop\nnop\n");
|
|
}
|
|
|
|
*(int*)0x8001F344 = 0;
|
|
|
|
if (arg1 == 2) {
|
|
if (arg0 != 0) {
|
|
val = 0x740834504LL;
|
|
val2 = 0x740814504LL;
|
|
|
|
tmp = (hvParam & 0x1) << 25;
|
|
val|= tmp;
|
|
val2|= tmp;
|
|
|
|
GS_SMODE1 = val;
|
|
GS_SYNCH1 = 0x7F5B61F06F040LL;
|
|
GS_SYNCH2 = 0x33A4D8;
|
|
GS_SYNCV = 0xC7800601A01801LL;
|
|
|
|
GS_SMODE2 = (arg2 << 1) | 1;
|
|
GS_SRFSH = 8;
|
|
GS_SMODE1 = val2;
|
|
} else {
|
|
val = 0x740834504LL;
|
|
val2 = 0x740814504LL;
|
|
|
|
tmp = (hvParam & 0x2) << 35;
|
|
val|= tmp;
|
|
val2|= tmp;
|
|
|
|
tmp = (hvParam & 0x1) << 25;
|
|
val|= tmp;
|
|
val2|= tmp;
|
|
|
|
GS_SMODE1 = val;
|
|
GS_SYNCH1 = 0x7F5B61F06F040LL;
|
|
GS_SYNCH2 = 0x33A4D8;
|
|
GS_SYNCV = 0xC7800601A01802LL;
|
|
GS_SMODE2 = 0;
|
|
GS_SRFSH = 8;
|
|
GS_SMODE1 = val2;
|
|
}
|
|
_SetGsCrt2();
|
|
return;
|
|
}
|
|
|
|
if (arg1 == 3) {
|
|
if (arg0 != 0) {
|
|
val = 0x740836504LL;
|
|
val2 = 0x740816504LL;
|
|
|
|
tmp = (hvParam & 0x1) << 25;
|
|
val|= tmp;
|
|
val2|= tmp;
|
|
|
|
GS_SMODE1 = val;
|
|
GS_SYNCH1 = 0x7F5C21FC83030LL;
|
|
GS_SYNCH2 = 0x3484BC;
|
|
GS_SYNCV = 0xA9000502101401LL;
|
|
|
|
GS_SMODE2 = (arg2 << 1) | 1;
|
|
GS_SRFSH = 8;
|
|
GS_SMODE1 = val2;
|
|
} else {
|
|
val = 0x740836504LL;
|
|
val2 = 0x740816504LL;
|
|
|
|
tmp = (hvParam & 0x2) << 35;
|
|
val|= tmp;
|
|
val2|= tmp;
|
|
|
|
tmp = (hvParam & 0x1) << 25;
|
|
val|= tmp;
|
|
val2|= tmp;
|
|
|
|
GS_SMODE1 = val;
|
|
GS_SYNCH1 = 0x7F5C21F683030LL;
|
|
GS_SYNCH2 = 0x3484BC;
|
|
GS_SYNCV = 0xA9000502101404LL;
|
|
GS_SMODE2 = 0;
|
|
GS_SRFSH = 8;
|
|
GS_SMODE1 = val2;
|
|
}
|
|
_SetGsCrt2();
|
|
return;
|
|
}
|
|
|
|
if (arg1 == 0x72) {
|
|
if (arg0 != 0) {
|
|
val = 0x740814504LL;
|
|
val|= (hvParam & 0x1) << 25;
|
|
|
|
GS_SYNCH1 = 0x7F5B61F06F040LL;
|
|
GS_SYNCH2 = 0x33A4D8;
|
|
GS_SYNCV = 0xC7800601A01801LL;
|
|
|
|
GS_SMODE2 = (arg2 << 1) | 1;
|
|
GS_SRFSH = 8;
|
|
GS_SMODE1 = val;
|
|
} else {
|
|
val = 0x740814504LL;
|
|
|
|
val|= (hvParam & 0x2) << 35;
|
|
val|= (hvParam & 0x1) << 25;
|
|
|
|
GS_SYNCH1 = 0x7F5B61F06F040LL;
|
|
GS_SYNCH2 = 0x33A4D8;
|
|
GS_SYNCV = 0xC7800601A01802LL;
|
|
GS_SMODE2 = 0;
|
|
GS_SRFSH = 8;
|
|
GS_SMODE1 = val;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (arg1 == 0x73) {
|
|
if (arg0 != 0) {
|
|
val = 0x740816504LL;
|
|
val|= (hvParam & 0x1) << 25;
|
|
|
|
GS_SYNCH1 = 0x7F5C21FC83030LL;
|
|
GS_SYNCH2 = 0x3484BC;
|
|
GS_SYNCV = 0xA9000502101401LL;
|
|
|
|
GS_SMODE2 = (arg2 << 1) | 1;
|
|
GS_SRFSH = 8;
|
|
GS_SMODE1 = val;
|
|
} else {
|
|
val = 0x740816504;
|
|
|
|
val|= (hvParam & 0x2) << 35;
|
|
val|= (hvParam & 0x1) << 25;
|
|
|
|
GS_SYNCH1 = 0x7F5C21FC83030LL;
|
|
GS_SYNCH2 = 0x3484BC;
|
|
GS_SYNCV = 0xA9000502101404LL;
|
|
GS_SMODE2 = 0;
|
|
GS_SRFSH = 8;
|
|
GS_SMODE1 = val;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if ((u32)(arg1 - 26) >= 0x38) {
|
|
_SetGsCrt3(arg0, arg1, arg2); return;
|
|
}
|
|
|
|
if (arg1 == 0x52) {
|
|
_SetGsCrt3(arg0, arg1, arg2); return;
|
|
}
|
|
|
|
_SetGsCrt4(arg0, arg1, arg2);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//8000A768 SYSCALL 076 GetGsHParam
|
|
////////////////////////////////////////////////////////////////////
|
|
void _GetGsHParam(int *p0, int *p1, int *p2, int *p3)
|
|
{
|
|
u32 _hvParam = (u32)hvParam;
|
|
|
|
*p0 = _hvParam >> 12;
|
|
*p1 = _hvParam >> 24;
|
|
*p2 = _hvParam >> 18;
|
|
*p3 = _hvParam >> 28;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//8000A7D0 SYSCALL 077 GetGsVParam
|
|
////////////////////////////////////////////////////////////////////
|
|
int _GetGsVParam()
|
|
{
|
|
return hvParam & 0x3;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//8000A800 SYSCALL 059 JoinThread
|
|
////////////////////////////////////////////////////////////////////
|
|
void _JoinThread()
|
|
{
|
|
_iJoinThread(0x87);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//8000A820 SYSCALL 078 SetGsHParam
|
|
////////////////////////////////////////////////////////////////////
|
|
void _SetGsHParam(int a0, int a1, int a2, int a3)
|
|
{
|
|
__printf("SetGsHParam(%x,%x,%x,%x)... probably will never be supported\n", a0, a1, a2, a3);
|
|
//write hvParam&1 to 12000010?
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//8000A8F8 SYSCALL 079 SetGsVParam
|
|
////////////////////////////////////////////////////////////////////
|
|
void _SetGsVParam(int VParam)
|
|
{
|
|
hvParam&= ~0x1;
|
|
hvParam|= VParam & 0x1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//8000A920 SYSCALL 075 GetOsdConfigParam
|
|
////////////////////////////////////////////////////////////////////
|
|
void _GetOsdConfigParam(int *result)
|
|
{
|
|
*result= (*result & 0xFFFFFFFE) | (osdConfigParam & 1);
|
|
*result= (*result & 0xFFFFFFF9) | (osdConfigParam & 6);
|
|
*result= (*result & 0xFFFFFFF7) | (osdConfigParam & 8);
|
|
*result= (*result & 0xFFFFFFEF) | (osdConfigParam & 0x10);
|
|
*result=((*result & 0xFFFFE01F) | (osdConfigParam & 0x1FE0)) & 0xFFFF1FFF;
|
|
((u16*)result)[1]=((u16*)&osdConfigParam)[1];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//8000A9C0 SYSCALL 074 SetOsdConfigParam
|
|
////////////////////////////////////////////////////////////////////
|
|
void _SetOsdConfigParam(int *param)
|
|
{
|
|
osdConfigParam= (osdConfigParam & 0xFFFFFFFE) | (*param & 1);
|
|
osdConfigParam= (osdConfigParam & 0xFFFFFFF9) | (*param & 6);
|
|
osdConfigParam= (osdConfigParam & 0xFFFFFFF7) | (*param & 8);
|
|
osdConfigParam= (osdConfigParam & 0xFFFFFFEF) | (*param & 0x10);
|
|
osdConfigParam=((osdConfigParam & 0xFFFFE01F) | (*param & 0x1FE0)) & 0xFFFF1FFF;
|
|
((u16*)&osdConfigParam)[1]=((u16*)param)[1];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//8000FCE8
|
|
////////////////////////////////////////////////////////////////////
|
|
void __exhandler(int a0)
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80010F34
|
|
////////////////////////////////////////////////////////////////////
|
|
void __disableInterrupts()
|
|
{
|
|
__asm__("mtc0 $0, $25\n"
|
|
"mtc0 $0, $24\n"
|
|
"li $3, 0xFFFFFFE0\n"
|
|
"mfc0 $2, $12\n"
|
|
"and $2, $3\n"
|
|
"mtc0 $2, $12\n"
|
|
"sync\n");
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80010F58
|
|
////////////////////////////////////////////////////////////////////
|
|
void kSaveContext()
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80011030
|
|
////////////////////////////////////////////////////////////////////
|
|
void kLoadContext()
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800110F4
|
|
////////////////////////////////////////////////////////////////////
|
|
void kLoadDebug()
|
|
{
|
|
kLoadContext();
|
|
// lq $31, 0x1F0($27)
|
|
// lq $27, 0x1B0($27)
|
|
// j 80005020 - probably load debug services or restore prev program state
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//80011108
|
|
////////////////////////////////////////////////////////////////////
|
|
int __exception()
|
|
{
|
|
register u32 curepc __asm__("$2");
|
|
int ret;
|
|
|
|
__asm__("mfc0 %0, $14\n" : "=r"(curepc) : );
|
|
|
|
// check if epc is currently in the except handlers:
|
|
// _Deci2Handler, __exception1, and __exception
|
|
if (curepc >= (u32)__exception && curepc < (u32)__exception+0x300) {
|
|
__asm__("mfc0 %0, $13\n" : "=r"(ret) : );
|
|
return (ret & 0x7C) >> 2;
|
|
}
|
|
|
|
kSaveContext();
|
|
|
|
__disableInterrupts();
|
|
__exhandler(1);
|
|
|
|
kLoadContext();
|
|
|
|
__asm__("eret\n");
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//800111F0
|
|
////////////////////////////////////////////////////////////////////
|
|
void __exception1()
|
|
{
|
|
kSaveContext();
|
|
__disableInterrupts();
|
|
//sub_8000CF68
|
|
kLoadContext();
|
|
__asm__("eret\n");
|
|
}
|