Code: Select all
li k0, 0xbc100000
li t0, 7
sw t0, 80(k0)
Thx
Code: Select all
li k0, 0xbc100000
li t0, 7
sw t0, 80(k0)
Access to system memory causes an exception unless that is done.Shazz wrote:Short question, what do we have in 0xbc100080 ?????? (And the value 7 for ?)
Shouldn't it be 0xbc100050 to enable the ME clock ?Code: Select all
li k0, 0xbc100000 li t0, 7 sw t0, 80(k0)
Thx
The me has no kernel. Any threading would have to be written from scratch.Hum, and an other little question, what's missing/the we should implement/... on the m.e side to have threads support ?
Code: Select all
struct me_struct
{
int start;
int end;
void (*func)(int);
int param;
};
volatile struct me_struct *nocache;
void me_stub(void);
void me_stub_end(void);
void me_startproc(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();
}
void me_function(int unused)
{
while (1)
{
while (nocache->start == 0);
nocache->start = 0;
nocache->func(nocache->param);
nocache->end = 1;
}
}
int me_struct_init()
{
nocache = malloc_64(sizeof(struct me_struct));
if (nocache == 0) return(0);
nocache = (volatile struct me_struct *) (((int) nocache) | 0x40000000);
sceKernelDcacheWritebackInvalidateAll();
nocache->start = 0;
nocache->end = 1;
nocache->func = 0;
nocache->param = 0;
me_startproc((u32) me_function, 0);
return(1);
}
void me_start(int func, int param)
{
nocache->end = 0;
nocache->func = (void (*)(int)) func;
nocache->param = param;
nocache->start = 1;
}
I'm not an expert, but there is an instruction "sync" which may help you. Here is what I found :Brunni wrote:Okay thx
I did some tries to get it to work and synchronize with the main CPU. But I'm having some serious problems. I was first invalidating the d-cache each time I finished to write informations to variables that should be used by the ME, but it slows down quite a lot.
So I replaced this method with writing to uncached addresses. Altrough I've found anywhere, I assumed that I could also add 0x40000000 to bypass cache with RAM variables (0x80000000). I did a simple synchronization:
...< cut >...
Code: Select all
# Conditions at entry:
# The value 0 has been stored in FLAG and that value is observable by B.
SW R1, DATA # change shared DATA value
LI R2, 1
SYNC # perform DATA store before performing FLAG store
SW R2, FLAG # say that the shared DATA value is valid
Code: Select all
LI R2, 1
1: LW R1, FLAG # get FLAG
BNE R2, R1, 1B # if it says that DATA is not valid, poll again
NOP
SYNC # FLAG value checked before doing DATA reads
LW R1, DATA # read (valid) shared DATA values
could it be the interface which allows ME processor to reprogram AVC decoder or VME DSP (I was heard it is kind of a FPGA) ?crazyc wrote:The local ram is at 0x80000000, in my library I use it for heap and stack, that seems to be what sony does too. What's at 0x04000000 is probably mmio, but all I know for sure is that it's not ram.
I don't know if this is the problem, but if you put this in you ME startup code, it will disable the kernel memory protection.jockyw2001 wrote:I wonder if the ME can access user space memory using some kind of trick. Can that be done?
Code: Select all
li $t0, 0xbc00002c
li $t1, 0xbc000000
li $t2, -1
c:
sw $t2, 0($t1)
bne $t1, $t0, c
Like this?crazyc wrote:I don't know if this is the problem, but if you put this in you ME startup code, it will disable the kernel memory protection.
Code: Select all
li $t0, 0xbc00002c li $t1, 0xbc000000 li $t2, -1 c: sw $t2, 0($t1) bne $t1, $t0, c
Code: Select all
#include <regdef.h>
#define STATUS $12
#define CAUSE $13
#define CONFIG $16
#define TAGLO $28
#define TAGHI $29
#define IXIST 0x01
#define DXIST 0x11
.global me_stub
.global me_stub_end
.set noreorder
.set noat
me_stub:
li k0, 0xbc100000
li t0, 7
sw t0, 80(k0)
mtc0 zero, TAGLO
mtc0 zero, TAGHI
li k1, 8192
a:
addi k1, k1, -64
bne k1, zero, a
cache IXIST, 0(k1)
li k1, 8192
b:
addi k1, k1, -64
bne k1, zero, b
cache DXIST, 0(k1)
mtc0 zero, CAUSE
li t0, 0xbc00002c
li t1, 0xbc000000
li t2, -1
c:
sw t2, 0(t1)
bne t1, t0, c
li k0, 0x20000000
mtc0 k0, STATUS
sync
li t0, 0xbfc00000
lw a0, 0x604(t0)
lw k0, 0x600(t0)
li sp, 0x80200000
jr k0
nop
me_stub_end:
shouldn't bejockyw2001 wrote:Code: Select all
... li t0, 0xbc00002c li t1, 0xbc000000 li t2, -1 c: sw t2, 0(t1) bne t1, t0, c li k0, 0x20000000 ...
Code: Select all
...
li t0, 0xbc00002c
li t1, 0xbc000000
li t2, -1
c:
sw t2, 0(t1)
bne t1, t0, c
addiu t1, t1, 4
li k0, 0x20000000
...
hlide wrote:shouldn't beYes, that looks better. But afaik this is just for enabling 64MB ?Code: Select all
... addiu t1, t1, 4 ...
No, doesn't workso far as I remember you can access data with a "user mode" address.
The whole idea is to port apps to 3.x firmwares and minimize the porting work. And the bulk of the routines I like to run on ME are in the parent user mode module. It's a bit of a pain to separate these routines out and put them in the ME kernel mode child module.But I never try to call such an address. What for ?
Yes, i see the problem. The caller function (me_function) runs in kernel mode and calls my function which is user mode.usually you don't call a function in user mode with ME processor because those functions are normally for ME processor and then can be executed in kernel mode. Any direct jump or call can be executed without any problem since they don't care about segments. For indirect jump or call, it is another story because you can change the segment this way (kseg and kuseg) if the register contains an address to another segment. I don't see why you cannot enter in user mode but it would be a problem to return kernel mode since a user mode function cannot call a function or jump into a kernel mode from a user mode for security reason. The only way to return kernel mode is through a syscall.
I tried or-ing the function address with 0x80000000 already. It didn't work, perhaps because some variables in the function are in user space?So if you need to use a user mode function through an indirect call, don't forget to or the register with 0x80000000 beforehand.
If it is indeed the recommended solution, how can I then make a syscall to my function? :Code: Select all
void me_function(int unused) { while (1) // this kernel mode function is running forever in ME { while (nocache->start == 0); nocache->start = 0; nocache->func(nocache->param); // our user mode function is called here. Can we change this into a syscall? If so, what's the syntax? nocache->end = 1; } }
Yeah, oops.hlide wrote: shouldn't be?Code: Select all
... li t0, 0xbc00002c li t1, 0xbc000000 li t2, -1 c: sw t2, 0(t1) bne t1, t0, c addiu t1, t1, 4 li k0, 0x20000000 ...
It disables the kernel memory memory protection. It's what prevents user mode code from accessing the lower memory where the kernel is located.jockyw2001 wrote:Excuse my ignorance, but what exactly is the additional code good for?crazyc wrote: Anyway, this probably won't fix your problem, unless you are switching the ME into user mode.
sorry to say but you can because there is no USEG but a KUSEG at 0x00000000-0x7fffffff, which means accessible in user or kernel mode. And meseems I already tried to read kuseg segment without problem.jockyw2001 wrote:No, doesn't workso far as I remember you can access data with a "user mode" address.
i have some functions that I can call with SC or ME processors (but I admit i use kernel mode in SC processor too). As I say, you can call those functions with SC processor but they run in kernel mode. But ONE important thing NO TO DO is to call some PRX functions relying on hardware - like IO or GU manipulations because they are specific to SC processor.jockyw2001 wrote: The whole idea is to port apps to 3.x firmwares and minimize the porting work. And the bulk of the routines I like to run on ME are in the parent user mode module. It's a bit of a pain to separate these routines out and put them in the ME kernel mode child module
use mode variables are in KUSEG !!!! that Kernel And User Segment, so there is no reason why a kernel code cannot access this segment. Anyway , kernel has all the rights.jockyw2001 wrote: Yes, i see the problem. The caller function (me_function) runs in kernel mode and calls my function which is user mode.
I tried or-ing the function address with 0x80000000 already. It didn't work, perhaps because some variables in the function are in user space?So if you need to use a user mode function through an indirect call, don't forget to or the register with 0x80000000 beforehand.
a syscall ? there is no syscall in ME processor, unless you are coding your own OS.jockyw2001 wrote: If it is indeed the recommended solution, how can I then make a syscall to my function?
so far as I know it doesn't seem to be possible. We know how to protect/unprotect the lower 64MB main memory and the 2MB VRAM (fast RAM of ME processor) but nothing for enabling access to VIDEO RAM (0x04000000-0x041FFFFF don't raise a bus address exception but it is mapped on nothing). I wouldn't expect too much for this possibility to exist.moonlight wrote:Does anyone know if the vram can be accesed with the me?
...and they cannot be user-kernel transition calls ("module"ForUser), because even if your app is running in kernel mode those are syscalls and would require a ME syscall hander (it would be possible to obtain the syscall table then write a handler, but it might not be worthwhile).hlide wrote:i have some functions that I can call with SC or ME processors (but I admit i use kernel mode in SC processor too). As I say, you can call those functions with SC processor but they run in kernel mode. But ONE important thing NO TO DO is to call some PRX functions relying on hardware - like IO or GU manipulations because they are specific to SC processor.jockyw2001 wrote: The whole idea is to port apps to 3.x firmwares and minimize the porting work. And the bulk of the routines I like to run on ME are in the parent user mode module. It's a bit of a pain to separate these routines out and put them in the ME kernel mode child module
Not necessarily. Although I haven't tested it, it may be that the code I posted earlier affects kernel mode too if the oxbc0000xx registers affect any access to KUSEG regardless of mode.hlide wrote:use mode variables are in KUSEG !!!! that Kernel And User Segment, so there is no reason why a kernel code cannot access this segment. Anyway , kernel has all the rights.jockyw2001 wrote: Yes, i see the problem. The caller function (me_function) runs in kernel mode and calls my function which is user mode.
I tried or-ing the function address with 0x80000000 already. It didn't work, perhaps because some variables in the function are in user space?So if you need to use a user mode function through an indirect call, don't forget to or the register with 0x80000000 beforehand.
That region isn't mapped to nothing. The ME OS uses it a lot, but it seems to load pointers to tables and structures around 0x04002000 and other places. There is definitely something interesting there, but not VRAM. That isn't to say it isn't possible to access the VRAM, just that the ME OS doesn't and it isn't mapped anywhere else by default.hlide wrote:so far as I know it doesn't seem to be possible. We know how to protect/unprotect the lower 64MB main memory and the 2MB VRAM (fast RAM of ME processor) but nothing for enabling access to VIDEO RAM (0x04000000-0x041FFFFF don't raise a bus address exception but it is mapped on nothing). I wouldn't expect too much for this possibility to exist.moonlight wrote:Does anyone know if the vram can be accesed with the me?
well i NEVER say it is ALWAYS mapped to nothing. By default it is mapped to nothing, meaning you always get the same fixed value whatever you try to put into. But yes maybe there is protected area on this range which has some meaning to be discovered.crazyc wrote:That region isn't mapped to nothing. The ME OS uses it a lot, but it seems to load pointers to tables and structures around 0x04002000 and other places. There is definitely something interesting there, but not VRAM. That isn't to say it isn't possible to access the VRAM, just that the ME OS doesn't and it isn't mapped anywhere else by default.hlide wrote:so far as I know it doesn't seem to be possible. We know how to protect/unprotect the lower 64MB main memory and the 2MB VRAM (fast RAM of ME processor) but nothing for enabling access to VIDEO RAM (0x04000000-0x041FFFFF don't raise a bus address exception but it is mapped on nothing). I wouldn't expect too much for this possibility to exist.moonlight wrote:Does anyone know if the vram can be accesed with the me?
i'm ASSUMING you already give user and kernel access rights to main memory through those 0xBC0000xx registers of course.crazyc wrote:Not necessarily. Although I haven't tested it, it may be that the code I posted earlier affects kernel mode too if the oxbc0000xx registers affect any access to KUSEG regardless of mode.hlide wrote: use mode variables are in KUSEG !!!! that Kernel And User Segment, so there is no reason why a kernel code cannot access this segment. Anyway , kernel has all the rights.
The ipl which is rumored to be started in the me uses also some of those funny addresses... 0x040f0000 and then 0x04000000...hlide wrote:well i NEVER say it is ALWAYS mapped to nothing. By default it is mapped to nothing, meaning you always get the same fixed value whatever you try to put into. But yes maybe there is protected area on this range which has some meaning to be discovered.crazyc wrote:That region isn't mapped to nothing. The ME OS uses it a lot, but it seems to load pointers to tables and structures around 0x04002000 and other places. There is definitely something interesting there, but not VRAM. That isn't to say it isn't possible to access the VRAM, just that the ME OS doesn't and it isn't mapped anywhere else by default.hlide wrote: so far as I know it doesn't seem to be possible. We know how to protect/unprotect the lower 64MB main memory and the 2MB VRAM (fast RAM of ME processor) but nothing for enabling access to VIDEO RAM (0x04000000-0x041FFFFF don't raise a bus address exception but it is mapped on nothing). I wouldn't expect too much for this possibility to exist.
Since you are saying that 0x04002000 is used to load pointers to table (?) could you say in which code ? is that relative with audio ? with video ? and so on. You may open some perspective here !!!
Here's an example that I found interesting.Since you are saying that 0x04002000 is used to load pointers to table (?) could you say in which code ? is that relative with audio ? with video ? and so on. You may open some perspective here !!!
Code: Select all
lui $t1, 0x4410
lui $a3, 0x4000
move $t0, $a3
ins $t0, $a0, 0, 0x1D
addiu $v0, $a2, 0xFFFF
addiu $a0, $t1, 0xF010
li $v1, 0x40 # '@'
sw $t0, 0x40FF010
sw $v0, 4($a0)
sw $a1, 8($a0)
jr $ra
sw $v1, -8($a0)
Code: Select all
.word 1048576,1048570,1048554,1048528,1048492,1048446 # 0
.word 1048391,1048326,1048250,1048165,1048070,1047965 # 6
.word 1047851,1047726,1047592,1047447,1047293,1047129 # 12
.word 1046955,1046772,1046578,1046375,1046161,1045938 # 18
hmm, then I wonder why I can't pass user mode function pointers to my main ME loop:hlide wrote: sorry to say but you can because there is no USEG but a KUSEG at 0x00000000-0x7fffffff, which means accessible in user or kernel mode. And meseems I already tried to read kuseg segment without problem.
Code: Select all
void me_function(int unused)
{
while (1) // this kernel mode function is running forever in ME
{
while (nocache->start == 0);
nocache->start = 0;
nocache->func(nocache->param); // our function is called here. kernel mode function pointers work, user mode pointers don't (psp freezes)
nocache->end = 1;
}
}
can you give us more details about nocache->func ?jockyw2001 wrote:hmm, then I wonder why I can't pass user mode function pointers to my main ME loop:hlide wrote: sorry to say but you can because there is no USEG but a KUSEG at 0x00000000-0x7fffffff, which means accessible in user or kernel mode. And meseems I already tried to read kuseg segment without problem.Any ideas guys?Code: Select all
void me_function(int unused) { while (1) // this kernel mode function is running forever in ME { while (nocache->start == 0); nocache->start = 0; nocache->func(nocache->param); // our function is called here. kernel mode function pointers work, user mode pointers don't (psp freezes) nocache->end = 1; } }
Sure, here is the major part of the sourcecode (me.c, mestub.S and Makefile). It's originally from jonny's PMP Mod player. PMP Mod is a kernel mode app. My app (PMP VLC) is a normal mode app which calls exported functions from the ME kernel mode prx (memodule.prx)hlide wrote:can you give us more details about nocache->func ?
Code: Select all
/*
PMP Mod
Copyright (C) 2006 jonny
Homepage: http://jonny.leffe.dnsalias.com
E-mail: [email protected]
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
simple lib to use the psp me
a lot of code is taken from here: http://forums.ps2dev.org/viewtopic.php?t=2652
thanks to crazyc, mrbrown, Brunni, xdeadbeef and anyone else involved
(major optimizations in libavcodec are done with the me)
*/
#include <pspsdk.h>
#include <pspkernel.h>
#include <string.h>
#include <stdio.h>
#include "me.h"
#include "mem64.h"
PSP_MODULE_INFO("MEPRX", 0x1000, 1, 1);
PSP_HEAP_SIZE_KB(1024);
struct me_struct
{
int start;
int end;
void (*func)(int); // function ptr func which takes argument nochache->param and returns void
int param; // function parameter func
int signaled;
unsigned int k1; // k1 register
};
volatile struct me_struct *nocache;
void me_stub(void);
void me_stub_end(void);
#define WELCOME_MESSAGE "Hello from the PRX\n"
int me_idct_start_row;
int main(int argc, char **argv)
{
int i;
printf(WELCOME_MESSAGE);
for(i = 0; i < argc; i++)
{
printf("Arg %d: %s\n", i, argv[i]);
}
sceKernelSleepThread();
return 0;
}
void me_startproc(u32 func, u32 param)
{
memcpy((void *) 0xbfc00040, me_stub, (int) (me_stub_end - me_stub));
_sw(func, 0xbfc00600); // k0
_sw(param, 0xbfc00604); // a0
sceKernelDcacheWritebackAll();
sceSysregMeResetEnable();
sceSysregMeBusClockEnable();
sceSysregMeResetDisable();
fprintf(stdout,"me.c: me_startproc()\n");
}
void me_function(int unused)
{
while (1) // ME runs this loop forever
{
while (nocache->start == 0); // me_start() clears this loop by setting start=1 and end=0
nocache->start = 0;
// nocache->k1 = pspSdkSetK1(0);
nocache->func(nocache->param); // run this function
// pspSdkSetK1(nocache->k1);
nocache->end = 1;
}
}
int me_struct_init()
{
nocache = malloc_64(sizeof(struct me_struct));
if (nocache == 0) return(0);
fprintf(stdout,"me.c: me_struct_init()\n");
nocache = (volatile struct me_struct *) (((int) nocache) | 0x40000000);
sceKernelDcacheWritebackInvalidateAll();
nocache->start = 0;
nocache->end = 1;
nocache->func = 0;
nocache->param = 0;
nocache->signaled = 0;
me_startproc((u32) me_function, 0);
return(1);
}
me_test(int i)
{
nocache->k1 = 777;
}
void me_start(int func, int param)
{
//#if 0
nocache->end = 0;
nocache->func = (void (*)(int)) func;
// nocache->func = (void (*)(int)) ((int)me_test | 0x80000000);
nocache->param = param;
nocache->start = 1;
//#endif
fprintf(stdout,"me.c: me_start() func = 0x%8X, k1=0x%8X\n", nocache->func, nocache->k1);
}
void me_wait()
{
while (nocache->end == 0);
}
int me_unused()
{
return(nocache->end);
}
void me_signal_reset()
{
nocache->signaled = 0;
}
void me_signal()
{
nocache->signaled = 1;
}
int me_signaled()
{
return(nocache->signaled);
}
void me_sceKernelDcacheWritebackInvalidateAll()
{
asm __volatile__
(
"cache 20, 0($0)\n"
"cache 20, 0($0)\n"
"cache 20, 64($0)\n"
"cache 20, 64($0)\n"
"cache 20, 128($0)\n"
"cache 20, 128($0)\n"
"cache 20, 192($0)\n"
"cache 20, 192($0)\n"
"cache 20, 256($0)\n"
"cache 20, 256($0)\n"
"cache 20, 320($0)\n"
"cache 20, 320($0)\n"
"cache 20, 384($0)\n"
"cache 20, 384($0)\n"
"cache 20, 448($0)\n"
"cache 20, 448($0)\n"
"cache 20, 512($0)\n"
"cache 20, 512($0)\n"
"cache 20, 576($0)\n"
"cache 20, 576($0)\n"
"cache 20, 640($0)\n"
"cache 20, 640($0)\n"
"cache 20, 704($0)\n"
"cache 20, 704($0)\n"
"cache 20, 768($0)\n"
"cache 20, 768($0)\n"
"cache 20, 832($0)\n"
"cache 20, 832($0)\n"
"cache 20, 896($0)\n"
"cache 20, 896($0)\n"
"cache 20, 960($0)\n"
"cache 20, 960($0)\n"
"cache 20, 1024($0)\n"
"cache 20, 1024($0)\n"
"cache 20, 1088($0)\n"
"cache 20, 1088($0)\n"
"cache 20, 1152($0)\n"
"cache 20, 1152($0)\n"
"cache 20, 1216($0)\n"
"cache 20, 1216($0)\n"
"cache 20, 1280($0)\n"
"cache 20, 1280($0)\n"
"cache 20, 1344($0)\n"
"cache 20, 1344($0)\n"
"cache 20, 1408($0)\n"
"cache 20, 1408($0)\n"
"cache 20, 1472($0)\n"
"cache 20, 1472($0)\n"
"cache 20, 1536($0)\n"
"cache 20, 1536($0)\n"
"cache 20, 1600($0)\n"
"cache 20, 1600($0)\n"
"cache 20, 1664($0)\n"
"cache 20, 1664($0)\n"
"cache 20, 1728($0)\n"
"cache 20, 1728($0)\n"
"cache 20, 1792($0)\n"
"cache 20, 1792($0)\n"
"cache 20, 1856($0)\n"
"cache 20, 1856($0)\n"
"cache 20, 1920($0)\n"
"cache 20, 1920($0)\n"
"cache 20, 1984($0)\n"
"cache 20, 1984($0)\n"
"cache 20, 2048($0)\n"
"cache 20, 2048($0)\n"
"cache 20, 2112($0)\n"
"cache 20, 2112($0)\n"
"cache 20, 2176($0)\n"
"cache 20, 2176($0)\n"
"cache 20, 2240($0)\n"
"cache 20, 2240($0)\n"
"cache 20, 2304($0)\n"
"cache 20, 2304($0)\n"
"cache 20, 2368($0)\n"
"cache 20, 2368($0)\n"
"cache 20, 2432($0)\n"
"cache 20, 2432($0)\n"
"cache 20, 2496($0)\n"
"cache 20, 2496($0)\n"
"cache 20, 2560($0)\n"
"cache 20, 2560($0)\n"
"cache 20, 2624($0)\n"
"cache 20, 2624($0)\n"
"cache 20, 2688($0)\n"
"cache 20, 2688($0)\n"
"cache 20, 2752($0)\n"
"cache 20, 2752($0)\n"
"cache 20, 2816($0)\n"
"cache 20, 2816($0)\n"
"cache 20, 2880($0)\n"
"cache 20, 2880($0)\n"
"cache 20, 2944($0)\n"
"cache 20, 2944($0)\n"
"cache 20, 3008($0)\n"
"cache 20, 3008($0)\n"
"cache 20, 3072($0)\n"
"cache 20, 3072($0)\n"
"cache 20, 3136($0)\n"
"cache 20, 3136($0)\n"
"cache 20, 3200($0)\n"
"cache 20, 3200($0)\n"
"cache 20, 3264($0)\n"
"cache 20, 3264($0)\n"
"cache 20, 3328($0)\n"
"cache 20, 3328($0)\n"
"cache 20, 3392($0)\n"
"cache 20, 3392($0)\n"
"cache 20, 3456($0)\n"
"cache 20, 3456($0)\n"
"cache 20, 3520($0)\n"
"cache 20, 3520($0)\n"
"cache 20, 3584($0)\n"
"cache 20, 3584($0)\n"
"cache 20, 3648($0)\n"
"cache 20, 3648($0)\n"
"cache 20, 3712($0)\n"
"cache 20, 3712($0)\n"
"cache 20, 3776($0)\n"
"cache 20, 3776($0)\n"
"cache 20, 3840($0)\n"
"cache 20, 3840($0)\n"
"cache 20, 3904($0)\n"
"cache 20, 3904($0)\n"
"cache 20, 3968($0)\n"
"cache 20, 3968($0)\n"
"cache 20, 4032($0)\n"
"cache 20, 4032($0)\n"
"cache 20, 4096($0)\n"
"cache 20, 4096($0)\n"
"cache 20, 4160($0)\n"
"cache 20, 4160($0)\n"
"cache 20, 4224($0)\n"
"cache 20, 4224($0)\n"
"cache 20, 4288($0)\n"
"cache 20, 4288($0)\n"
"cache 20, 4352($0)\n"
"cache 20, 4352($0)\n"
"cache 20, 4416($0)\n"
"cache 20, 4416($0)\n"
"cache 20, 4480($0)\n"
"cache 20, 4480($0)\n"
"cache 20, 4544($0)\n"
"cache 20, 4544($0)\n"
"cache 20, 4608($0)\n"
"cache 20, 4608($0)\n"
"cache 20, 4672($0)\n"
"cache 20, 4672($0)\n"
"cache 20, 4736($0)\n"
"cache 20, 4736($0)\n"
"cache 20, 4800($0)\n"
"cache 20, 4800($0)\n"
"cache 20, 4864($0)\n"
"cache 20, 4864($0)\n"
"cache 20, 4928($0)\n"
"cache 20, 4928($0)\n"
"cache 20, 4992($0)\n"
"cache 20, 4992($0)\n"
"cache 20, 5056($0)\n"
"cache 20, 5056($0)\n"
"cache 20, 5120($0)\n"
"cache 20, 5120($0)\n"
"cache 20, 5184($0)\n"
"cache 20, 5184($0)\n"
"cache 20, 5248($0)\n"
"cache 20, 5248($0)\n"
"cache 20, 5312($0)\n"
"cache 20, 5312($0)\n"
"cache 20, 5376($0)\n"
"cache 20, 5376($0)\n"
"cache 20, 5440($0)\n"
"cache 20, 5440($0)\n"
"cache 20, 5504($0)\n"
"cache 20, 5504($0)\n"
"cache 20, 5568($0)\n"
"cache 20, 5568($0)\n"
"cache 20, 5632($0)\n"
"cache 20, 5632($0)\n"
"cache 20, 5696($0)\n"
"cache 20, 5696($0)\n"
"cache 20, 5760($0)\n"
"cache 20, 5760($0)\n"
"cache 20, 5824($0)\n"
"cache 20, 5824($0)\n"
"cache 20, 5888($0)\n"
"cache 20, 5888($0)\n"
"cache 20, 5952($0)\n"
"cache 20, 5952($0)\n"
"cache 20, 6016($0)\n"
"cache 20, 6016($0)\n"
"cache 20, 6080($0)\n"
"cache 20, 6080($0)\n"
"cache 20, 6144($0)\n"
"cache 20, 6144($0)\n"
"cache 20, 6208($0)\n"
"cache 20, 6208($0)\n"
"cache 20, 6272($0)\n"
"cache 20, 6272($0)\n"
"cache 20, 6336($0)\n"
"cache 20, 6336($0)\n"
"cache 20, 6400($0)\n"
"cache 20, 6400($0)\n"
"cache 20, 6464($0)\n"
"cache 20, 6464($0)\n"
"cache 20, 6528($0)\n"
"cache 20, 6528($0)\n"
"cache 20, 6592($0)\n"
"cache 20, 6592($0)\n"
"cache 20, 6656($0)\n"
"cache 20, 6656($0)\n"
"cache 20, 6720($0)\n"
"cache 20, 6720($0)\n"
"cache 20, 6784($0)\n"
"cache 20, 6784($0)\n"
"cache 20, 6848($0)\n"
"cache 20, 6848($0)\n"
"cache 20, 6912($0)\n"
"cache 20, 6912($0)\n"
"cache 20, 6976($0)\n"
"cache 20, 6976($0)\n"
"cache 20, 7040($0)\n"
"cache 20, 7040($0)\n"
"cache 20, 7104($0)\n"
"cache 20, 7104($0)\n"
"cache 20, 7168($0)\n"
"cache 20, 7168($0)\n"
"cache 20, 7232($0)\n"
"cache 20, 7232($0)\n"
"cache 20, 7296($0)\n"
"cache 20, 7296($0)\n"
"cache 20, 7360($0)\n"
"cache 20, 7360($0)\n"
"cache 20, 7424($0)\n"
"cache 20, 7424($0)\n"
"cache 20, 7488($0)\n"
"cache 20, 7488($0)\n"
"cache 20, 7552($0)\n"
"cache 20, 7552($0)\n"
"cache 20, 7616($0)\n"
"cache 20, 7616($0)\n"
"cache 20, 7680($0)\n"
"cache 20, 7680($0)\n"
"cache 20, 7744($0)\n"
"cache 20, 7744($0)\n"
"cache 20, 7808($0)\n"
"cache 20, 7808($0)\n"
"cache 20, 7872($0)\n"
"cache 20, 7872($0)\n"
"cache 20, 7936($0)\n"
"cache 20, 7936($0)\n"
"cache 20, 8000($0)\n"
"cache 20, 8000($0)\n"
"cache 20, 8064($0)\n"
"cache 20, 8064($0)\n"
"cache 20, 8128($0)\n"
"cache 20, 8128($0)\n"
);
}
/* Exported function returns the address of module_info */
void* getModuleInfo(void)
{
fprintf(stdout,"me.c: getModuleInfo()\n");
//printf("me.c: getModuleInfo()\n");
return (void *) &module_info;
}
Code: Select all
// this stub is from the melib package, (c)mrbrown
#include <regdef.h>
#define STATUS $12
#define CAUSE $13
#define CONFIG $16
#define TAGLO $28
#define TAGHI $29
#define IXIST 0x01
#define DXIST 0x11
.global me_stub
.global me_stub_end
.set noreorder
.set noat
me_stub:
li k0, 0xbc100000
li t0, 7
sw t0, 80(k0)
mtc0 zero, TAGLO
mtc0 zero, TAGHI
li k1, 8192
a:
addi k1, k1, -64
bne k1, zero, a
cache IXIST, 0(k1)
li k1, 8192
b:
addi k1, k1, -64
bne k1, zero, b
cache DXIST, 0(k1)
mtc0 zero, CAUSE
li t0, 0xbc00002c
li t1, 0xbc000000
li t2, -1
c:
sw t2, 0(t1)
bne t1, t0, c
addiu t1, t1, 4
li k0, 0x20000000
mtc0 k0, STATUS
sync
li t0, 0xbfc00000
lw a0, 0x604(t0)
lw k0, 0x600(t0)
li sp, 0x80200000
jr k0
nop
me_stub_end:
Code: Select all
TARGET = memodule
OBJS = mestub.o me.o ../../../libavcodec/mod/me_idct.o ../../../libavcodec/mod/simple_idct.o ../mem64.o
# Define to build this as a prx (instead of a static elf)
BUILD_PRX=1
# Define the name of our custom exports (minus the .exp extension)
PRX_EXPORTS=exports.exp
USE_PSPSDK_LIBC = 1
#USE_KERNEL_LIBC = 1
#USE_KERNEL_LIBS = 1
INCDIR = . .. ../../../libavcodec/mod ../../../libavcodec ../../../libavformat ../../../libavutil
CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)
LIBDIR =
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak