here we go.
i'm posting my mestub.s which can handle exceptions and be polled by SC processor, which is proved to be useful when developping on ME processor :
- _me_print_exception() : dump ME registers saved when a ME exception occured.
- _me_exception_regs : array of registers where to copy when an exception raises so that you can dump them with
- _me_report_exception: boolean to indicate whether a ME exception occured.
I'm still longing for how to activate int31 in ME processor so SC processor can signal it. And how to install an interrupt handler for int31 on SC processor for ME processor to signal it.
Code: Select all
#define zr $0
#define at $1
#define v0 $2
#define v1 $3
#define a0 $4
#define a1 $5
#define a2 $6
#define a3 $7
#define a4 $8
#define a5 $9
#define a6 $10
#define a7 $11
#define t0 $8
#define t1 $9
#define t2 $10
#define t3 $11
#define t4 $12
#define t5 $13
#define t6 $14
#define t7 $15
#define t8 $24
#define t9 $25
#define s0 $16
#define s1 $17
#define s2 $18
#define s3 $19
#define s4 $20
#define s5 $21
#define s6 $22
#define s7 $23
#define s8 $30
#define k0 $26
#define k1 $27
#define gp $28
#define sp $29
#define fp $30
#define ra $31
.set noreorder
.set noat
.extern _me_exception_regs
.global me_stub
me_stub:
li k0, 0xbc100000
li t0, 7
sw t0, 80(k0)
mtc0 zr, $28
mtc0 zr, $29
li k1, 8192
0: addi k1, k1, -64
bne k1, zr, 0b
cache 0x01, 0(k1)
li k1, 8192
0: addi k1, k1, -64
bne k1, zr, 0b
cache 0x11, 0(k1)
mtc0 zr, $13
li k0, 0x20000000
mtc0 k0, $12
sync
li v1, 0x80000000
la v0, me_exception_vector_table
or v0, v1, v0
ctc0 v0, $8
la v0, me_ebase
or v0, v1, v0
li t0, 0xbfc00000
mtc0 v0, $25
li t0, 0xbfc00000
lw a0, 0x604(t0)
lw k0, 0x600(t0)
li sp, 0x80200000
jr k0
nop
.global me_stub_end
me_stub_end:
.global me_interrupt
me_interrupt:
sync
lui at, 0xbc10
addiu v0, zr, 0x0001
sw v0, 0x0044(at)
jr ra
sync
.global me_leave_critical_session
.global me_unlock_mutex
me_leave_critical_session:
me_unlock_mutex:
sync
lui at, 0xbc10
sw zr, 0x0048(at)
jr ra
sync
.global me_try_lock_mutex
me_try_lock_mutex:
mfc0 a0, $22
sync
addiu a0, a0, 1
lui at, 0xbc10
sw a0, 0x0048(at)
sync
lw v0, 0x0048(at)
jr ra
xor v0, a0, v0
.global me_enter_critical_session
me_enter_critical_session:
mfc0 a0, $22
sync
addiu a0, a0, 1
lui at, 0xbc10
andi a0, a0, 3
sw a0, 0x0048(at)
0: sync
lw v0, 0x0048(at)
sync
andi v0, v0, 3
bne v0, a0, 0b
sw a0, 0x0048(at)
jr ra
nop
me_exc_31_error_handler:
ctc0 v0, $4
ctc0 v1, $5
mfc0 v0, $30
mfc0 v1, $12
ctc0 v0, $1
mtc0 v1, $19
mfc0 v0, $13
ctc0 v0, $20
b me_exception_handler
ori v0, zr, (31<<2)
me_ebase:
ctc0 v0, $4
ctc0 v1, $5
lui v0, 0x1FF0
lui v1, 0xBC20
ori v0, 0x01FF
sw v0, (v1)
mfc0 v0, $13
mfc0 v1, $14
ctc0 v0, $3
ctc0 v1, $0
andi v0, 0x7C
me_exception_handler:
cfc0 v1, $8
addu v0, v1, v0
lw v0, (v0)
jr v0
nop
.p2align 6
me_exception_vector_table:
.long me_default_irq_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_sys_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.long me_default_exc_handler
.global _me_report_exception
_me_report_exception:
.long 0
#define ZR 4*6
#define AT ZR + 4
#define V0 AT + 4
#define V1 V0 + 4
#define A0 V1 + 4
#define A1 A0 + 4
#define A2 A1 + 4
#define A3 A2 + 4
#define T0 A3 + 4
#define T1 T0 + 4
#define T2 T1 + 4
#define T3 T2 + 4
#define T4 T3 + 4
#define T5 T4 + 4
#define T6 T5 + 4
#define T7 T6 + 4
#define S0 T7 + 4
#define S1 S0 + 4
#define S2 S1 + 4
#define S3 S2 + 4
#define S4 S3 + 4
#define S5 S4 + 4
#define S6 S5 + 4
#define S7 S6 + 4
#define T8 S7 + 4
#define T9 T8 + 4
#define K0 T9 + 4
#define K1 K0 + 4
#define GP K1 + 4
#define SP GP + 4
#define S8 SP + 4
#define RA S8 + 4
#define STATUS RA + 4
#define LO STATUS + 4
#define HI LO + 4
#define BADVADDR HI + 4
#define CAUSE BADVADDR + 4
#define EPC CAUSE + 4
#define F0 EPC + 4
#define F1 F0 + 4
#define F2 F1 + 4
#define F3 F2 + 4
#define F4 F3 + 4
#define F5 F4 + 4
#define F6 F5 + 4
#define F7 F6 + 4
#define F8 F7 + 4
#define F9 F8 + 4
#define F10 F9 + 4
#define F11 F10 + 4
#define F12 F11 + 4
#define F13 F12 + 4
#define F14 F13 + 4
#define F15 F14 + 4
#define F16 F15 + 4
#define F17 F16 + 4
#define F18 F17 + 4
#define F19 F18 + 4
#define F20 F19 + 4
#define F21 F20 + 4
#define F22 F21 + 4
#define F23 F22 + 4
#define F24 F23 + 4
#define F25 F24 + 4
#define F26 F25 + 4
#define F27 F26 + 4
#define F28 F27 + 4
#define F29 F28 + 4
#define F30 F29 + 4
#define F31 F30 + 4
#define FSR F31 + 4
#define FIR FSR + 4
#define FP FIR + 4
.p2align 6
me_default_irq_handler:
me_default_exc_handler:
me_default_sys_handler:
lui v1, 0xa000
la v0, _me_exception_regs
or v0, v1, v0
mfic v1, $0
mtic zr, $0
sw at, AT(v0)
cfc0 at, $4
sw at, V0(v0)
cfc0 at, $5
sw at, V1(v0)
sw a0, A0(v0)
sw a1, A1(v0)
sw a2, A2(v0)
sw a3, A3(v0)
sw t0, T0(v0)
sw t1, T1(v0)
sw t2, T2(v0)
sw t3, T3(v0)
sw t4, T4(v0)
sw t5, T5(v0)
sw t6, T6(v0)
sw t7, T7(v0)
sw s0, S0(v0)
sw s1, S1(v0)
sw s2, S2(v0)
sw s3, S3(v0)
sw s4, S4(v0)
sw s5, S5(v0)
sw s6, S6(v0)
sw s7, S7(v0)
sw t8, T8(v0)
sw t9, T9(v0)
sw k0, K0(v0)
sw k1, K1(v0)
sw gp, GP(v0)
sw sp, SP(v0)
sw s8, S8(v0)
sw ra, RA(v0)
mfhi a0
mflo a1
sw a0, HI(v0)
sw a1, LO(v0)
mfc0 a0, $8
mfc0 a1, $12
mfc0 a2, $13
mfc0 a3, $14
sw a0, BADVADDR(v0)
lui a0, 0x2000
sw a1, STATUS(v0)
and a0, a0, a1
sw a2, CAUSE(v0)
beq a0, zr, 0f
sw a3, EPC(v0)
swc1 $0, F0(v0)
swc1 $1, F1(v0)
swc1 $2, F2(v0)
swc1 $3, F3(v0)
swc1 $4, F4(v0)
swc1 $5, F5(v0)
swc1 $6, F6(v0)
swc1 $7, F7(v0)
swc1 $8, F8(v0)
swc1 $9, F9(v0)
swc1 $10, F10(v0)
swc1 $11, F11(v0)
swc1 $12, F12(v0)
swc1 $13, F13(v0)
swc1 $14, F14(v0)
swc1 $15, F15(v0)
swc1 $16, F16(v0)
swc1 $17, F17(v0)
swc1 $18, F18(v0)
swc1 $19, F19(v0)
swc1 $20, F20(v0)
swc1 $21, F21(v0)
swc1 $22, F22(v0)
swc1 $23, F23(v0)
swc1 $24, F24(v0)
swc1 $25, F25(v0)
swc1 $26, F26(v0)
swc1 $27, F27(v0)
swc1 $28, F28(v0)
swc1 $29, F29(v0)
swc1 $30, F30(v0)
swc1 $31, F31(v0)
cfc1 a0, $31
cfc1 a1, $0
sw a0, FSR(v0)
sw a1, FIR(v0)
ctc1 zr, $31
0: sw sp, FP(v0)
mtic v1, $0
sync
lui v0, 0xa000
lui at, %hi(_me_report_exception)
or at, at, v0
nor v0, zr, zr
sw v0, %lo(_me_report_exception)(at)
sync
0: b 0b
nop
Code: Select all
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspctrl.h>
#include <pspdisplay.h>
#include <stdlib.h>
#include <string.h>
PSP_MODULE_INFO("ME", 0x1000, 1, 1);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_VFPU);
#define printf pspDebugScreenPrintf
void me_stub(void);
void me_stub_end(void);
void me_interrupt();
void me_enter_critical_session();
void me_leave_critical_session();
static void me_startup(u32 func, u32 param)
{
memcpy((void *)0xbfc00040, me_stub, (int)(me_stub_end - me_stub));
_sw(func, 0xbfc00600);
_sw(param, 0xbfc00604);
sceKernelDcacheWritebackAll();
sceSysregMeResetEnable();
sceSysregMeBusClockEnable();
sceSysregMeResetDisable();
}
volatile unsigned int g_counter1 = 0;
volatile unsigned int g_counter2 = 0;
static __attribute__((aligned(64))) int g_data[0x200000/sizeof(int)];
void me_test_exception(int param)
{
volatile unsigned int *pctr1 = (volatile unsigned int *)(((int)&g_counter1)|0x40000000);
volatile unsigned int *pctr2 = (volatile unsigned int *)(((int)&g_counter2)|0x40000000);
volatile unsigned int *vptr1 = (volatile unsigned int *)((int)g_data|0x40000000);
volatile unsigned int *vptr2 = (volatile unsigned int *)(0x88000000);
while (1)
{
if (*pctr1)
_sw(1, 0); // <- exception
}
}
void me_test_memory(int param)
{
volatile unsigned int *pctr1 = (volatile unsigned int *)(((int)&g_counter1)|0x40000000);
volatile unsigned int *pctr2 = (volatile unsigned int *)(((int)&g_counter2)|0x40000000);
volatile unsigned int *vptr1 = (volatile unsigned int *)((int)g_data|0x40000000);
volatile unsigned int *vptr2 = (volatile unsigned int *)(0x88000000);
while (1)
{
if (*pctr1)
{
me_enter_critical_session();
while (1)
{
*pctr2 = vptr2;
*vptr1++ = *vptr2++;
if ((int)vptr2 >= (0x88200000))
{
*pctr1 = 0;
break;
}
}
me_leave_critical_session();
_sw(1, 0); // <- exception
}
}
}
#define mfc0(reg) ({ unsigned int res; asm volatile ("mfc0 %0, $%1" : "=r"(res) : "i"(reg)); res; })
#define cfc0(reg) ({ unsigned int res; asm volatile ("cfc0 %0, $%1" : "=r"(res) : "i"(reg)); res; })
void read_cop0_registers(int param)
{
volatile unsigned int *pctr1 = (volatile unsigned int *)(((int)&g_counter1)|0x40000000);
volatile unsigned int *vptr1 = (volatile unsigned int *)((int)g_data|0x40000000);
loop:
while (!(*pctr1));
me_enter_critical_session();
if (*pctr1)
{
*vptr1++ = mfc0(0);
*vptr1++ = mfc0(1);
*vptr1++ = mfc0(2);
*vptr1++ = mfc0(3);
*vptr1++ = mfc0(4);
*vptr1++ = mfc0(5);
*vptr1++ = mfc0(6);
*vptr1++ = mfc0(7);
*vptr1++ = mfc0(8);
*vptr1++ = mfc0(9);
*vptr1++ = mfc0(10);
*vptr1++ = mfc0(11);
*vptr1++ = mfc0(12);
*vptr1++ = mfc0(13);
*vptr1++ = mfc0(14);
*vptr1++ = mfc0(15);
*vptr1++ = mfc0(16);
*vptr1++ = mfc0(17);
*vptr1++ = mfc0(18);
*vptr1++ = mfc0(19);
*vptr1++ = mfc0(20);
*vptr1++ = mfc0(21);
*vptr1++ = mfc0(22);
*vptr1++ = mfc0(23);
*vptr1++ = mfc0(24);
*vptr1++ = mfc0(25);
*vptr1++ = mfc0(26);
*vptr1++ = mfc0(27);
*vptr1++ = mfc0(28);
*vptr1++ = mfc0(29);
*vptr1++ = mfc0(30);
*vptr1++ = mfc0(31);
*vptr1++ = cfc0(0);
*vptr1++ = cfc0(1);
*vptr1++ = cfc0(2);
*vptr1++ = cfc0(3);
*vptr1++ = cfc0(4);
*vptr1++ = cfc0(5);
*vptr1++ = cfc0(6);
*vptr1++ = cfc0(7);
*vptr1++ = cfc0(8);
*vptr1++ = cfc0(9);
*vptr1++ = cfc0(10);
*vptr1++ = cfc0(11);
*vptr1++ = cfc0(12);
*vptr1++ = cfc0(13);
*vptr1++ = cfc0(14);
*vptr1++ = cfc0(15);
*vptr1++ = cfc0(16);
*vptr1++ = cfc0(17);
*vptr1++ = cfc0(18);
*vptr1++ = cfc0(19);
*vptr1++ = cfc0(20);
*vptr1++ = cfc0(21);
*vptr1++ = cfc0(22);
*vptr1++ = cfc0(23);
*vptr1++ = cfc0(24);
*vptr1++ = cfc0(25);
*vptr1++ = cfc0(26);
*vptr1++ = cfc0(27);
*vptr1++ = cfc0(28);
*vptr1++ = cfc0(29);
*vptr1++ = cfc0(30);
*vptr1++ = cfc0(31);
*pctr1 = 0;
}
me_leave_critical_session();
goto loop;
}
void save_file(const char *data, unsigned int n, const char *name)
{
int fdout;
fdout = sceIoOpen(name, PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC, 0777);
sceIoWrite(fdout, data, n);
sceIoClose(fdout);
}
void load_file(const char *data, unsigned int n, const char *name)
{
int fdin;
fdin = sceIoOpen(name, PSP_O_RDONLY, 0777);
sceIoRead(fdin, data, n);
sceIoClose(fdin);
}
static void wait()
{
while (1)
{
SceCtrlData pad;
sceCtrlReadBufferNegative(&pad, 1);
if (pad.Buttons & PSP_CTRL_CROSS)
break;
}
while (1)
{
SceCtrlData pad;
sceCtrlReadBufferPositive(&pad, 1);
if (pad.Buttons & PSP_CTRL_CROSS)
break;
}
}
void sc_exception_handler(PspDebugRegBlock *regs)
{
pspDebugScreenInit();
pspDebugScreenSetBackColor(0x00FF0000);
pspDebugScreenSetTextColor(0xFFFFFFFF);
pspDebugScreenClear();
pspDebugScreenPrintf("\nSC - Exception Details:\n");
pspDebugDumpException(regs);
pspDebugScreenPrintf("\n\nPress 'cross' button to exit.");
wait();
sceKernelExitGame();
}
PspDebugRegBlock __attribute__((aligned(16))) _me_exception_regs;
extern int _me_report_exception;
static void _me_print_exception()
{
pspDebugScreenInit();
pspDebugScreenSetBackColor(0x00FF0000);
pspDebugScreenSetTextColor(0xFFFFFFFF);
pspDebugScreenClear();
pspDebugScreenPrintf("\nME - Exception Details:\n");
pspDebugDumpException((PspDebugRegBlock *)(((int)&_me_exception_regs)|0xa0000000));
pspDebugScreenPrintf("\n\nPress 'cross' button to exit.");
wait();
sceKernelExitGame();
}
int main(int argc, char *argv[])
{
SceCtrlData ctl;
pspDebugScreenInit();
sceCtrlSetSamplingCycle(0);
sceCtrlSetSamplingMode(PSP_CTRL_MODE_DIGITAL);
pspDebugInstallErrorHandler(sc_exception_handler);
me_startup((unsigned)me_test_exception, 0x10000);
while (1)
{
volatile unsigned int *pctr1 = (volatile unsigned int *)(((int)&g_counter1)|0x40000000); // uncached read pointer
volatile unsigned int *pctr2 = (volatile unsigned int *)(((int)&g_counter2)|0x40000000); // uncached read pointer
volatile unsigned int *pctr3 = (volatile unsigned int *)(((int)&_me_report_exception)|0x40000000);
me_enter_critical_session();
*pctr1 = 1;
me_leave_critical_session();
while (*pctr1)
{
if (*pctr3)
_me_print_exception();
}
me_enter_critical_session();
unsigned int val1 = *pctr1;
unsigned int val2 = *pctr2;
unsigned int val3 = *pctr3;
me_leave_critical_session();
pspDebugScreenSetXY(0, 0);
pspDebugScreenPrintf("ME test, press Home to exit\n");
pspDebugScreenPrintf("ME : %08x, %08x\n", val1, val2);
while(1)
{
sceCtrlReadBufferPositive(&ctl, 1);
if(ctl.Buttons & PSP_CTRL_HOME)
{
save_file(((int)g_data|0x40000000), 0x200000, "ms0:/me.bin");
sceKernelExitGame();
}
sceDisplayWaitVblankStart();
if (val3)
_me_print_exception();
}
}
return 0;
}
EDIT: it seems I mess up with critical session so i need to investigate why...