| View previous topic :: View next topic |
| Author |
Message |
Fanjita
Joined: 28 Sep 2005 Posts: 217
|
Posted: Fri Sep 30, 2005 6:42 pm Post subject: Register usage for inline assembly with gcc |
|
|
One of the main stumbling blocks I found for using the toolchain for 2.0 exploit development was setting up the registers for syscalls.
Initially I was trying
void sceAnyOldFunction(void *parm1, int parm2)
{
asm("syscall 0x2100");
}
as seen in various forums. But this assumes that the parameters are already in registers $a0, $a1 etc. I found out the hard way that that's not true if the compiler optimisation flags are on.
I eventually came up with the workaround of:
asm __volatile__ ("move $4, %0;"
"move $5, %1;"
"syscall 0x2100;"
: // no output regs
: "r" (parm1), "r" (parm2)
: "$4","$5"
);
which does work under optimisation, but is wasteful. I'm sure there's a better way of doing this by using the correct constraint parameters, but all the docs I could find on this were incomprehensible (to me).
Is there anyone with a better working knowledge of gcc, who can explain how this should be done?
Thanks. |
|
| Back to top |
|
 |
holger
Joined: 18 Aug 2005 Posts: 204
|
Posted: Fri Sep 30, 2005 7:19 pm Post subject: |
|
|
| you can specify in the "r" constraints into which registers the variables should get passed. Read the gcc info pages for details. (if I remember correctly for most architectures things like "r4" and "r5" worked, but not for all... some had different semantics) |
|
| Back to top |
|
 |
groepaz

Joined: 01 Sep 2005 Posts: 305
|
|
| Back to top |
|
 |
Fanjita
Joined: 28 Sep 2005 Posts: 217
|
Posted: Mon Oct 03, 2005 5:08 am Post subject: |
|
|
Groepaz - unfortunately I'm not sure yoru code helps - it still allows GCC to allocate to its choice of registers.
Holger - thanks for your tip, I'll try that to see if it helps for the PSP.
I found lots of info on this for x86-architectures, but nothing much that helped apply it to the PSP. Looks like r4, r5 etc. is promising though. |
|
| Back to top |
|
 |
holger
Joined: 18 Aug 2005 Posts: 204
|
Posted: Mon Oct 03, 2005 5:26 am Post subject: |
|
|
try something like this:
| Code: |
void func (void *arg)
{
register void *ptr __asm__ ("a0") = arg;
__asm__ volatile ("/*asm code here*/": "=r"(ptr) : "r"(ptr) : "memory");
}
|
|
|
| Back to top |
|
 |
Fanjita
Joined: 28 Sep 2005 Posts: 217
|
Posted: Mon Oct 03, 2005 7:04 am Post subject: |
|
|
Heh, that's exactly what I've been trying since posting (since there are no explicit names for the registers in the MIPS-variant asm constraints).
This variant seems to work, and generate the right opcodes:
int sceCtrlReadBufferPositive(SceCtrlData *pad_data, int count)
{
register SceCtrlData * lpaddata asm("$4") = pad_data;
register SceCtrlData * lcount asm("$5") = count;
asm __volatile__ (
"syscall 0x215b;"
: // no output regs
: "r" (lpaddata), "r" (lcount)
);
}
Just a shame that the 'register' modifier can't be used against the function parameters directly, i.e.
int sceBlah(register int param asm("$4"))
{
}
because that would be much neater. :) |
|
| Back to top |
|
 |
mrbrown
Joined: 17 Jan 2004 Posts: 1536
|
Posted: Mon Oct 03, 2005 10:17 am Post subject: |
|
|
| Um, your arguments are already in the correct registers for the syscall. What are you trying to do exactly? |
|
| Back to top |
|
 |
Fanjita
Joined: 28 Sep 2005 Posts: 217
|
Posted: Mon Oct 03, 2005 10:52 am Post subject: |
|
|
The point is that the arguments aren't guaranteed to be in the right registers, unless appropriate constraints are supplied.
The classic
void func(int foo)
{
asm ("syscall bar")
}
format works OK if optimisation is turned off, but with optimisation gcc tends to inline the functions, and not bother setting up the registers.
The constraints given force the use of the correct registers, and don't appear to cause the generation of any surplus opcodes - which was my end goal, even though it looks pretty ugly. |
|
| Back to top |
|
 |
Jim

Joined: 02 Jul 2005 Posts: 487 Location: Sydney
|
Posted: Mon Oct 03, 2005 11:39 am Post subject: |
|
|
A few possibilities:
Compile with -fno-inline.
Maybe __declspec(noinline) works with C too.
Put the syscall functions in a different C file.
Jim _________________ http://www.dbfinteractive.com |
|
| Back to top |
|
 |
Fanjita
Joined: 28 Sep 2005 Posts: 217
|
Posted: Mon Oct 03, 2005 7:41 pm Post subject: |
|
|
The thing is, I don't mind letting the compiler inline the functions, so long as it gets the registers right. Letting it optimise my code (so long as it can do it safely) seems like A Good Thing(tm).
As I said, declaring register local variables seems to be the way to do it - it works, it's safe, it results in tight code, it just doesn't look nice (but I don't really care about that). |
|
| Back to top |
|
 |
holger
Joined: 18 Aug 2005 Posts: 204
|
Posted: Mon Oct 03, 2005 7:43 pm Post subject: |
|
|
| isn't the "asm volatile" tag enough to tell gcc that it should not optimize away that section? |
|
| Back to top |
|
 |
Jim

Joined: 02 Jul 2005 Posts: 487 Location: Sydney
|
Posted: Mon Oct 03, 2005 9:44 pm Post subject: |
|
|
| Quote: | | The thing is, I don't mind letting the compiler inline the functions, so long as it gets the registers right |
Are you sure you need to optimise down to this level?
Every syscall is cycle critical?
I think you need to reconsider your priorities!
Jim _________________ http://www.dbfinteractive.com |
|
| Back to top |
|
 |
holger
Joined: 18 Aug 2005 Posts: 204
|
Posted: Mon Oct 03, 2005 10:14 pm Post subject: |
|
|
| function inlining is enabled by default for -O2. |
|
| Back to top |
|
 |
mrbrown
Joined: 17 Jan 2004 Posts: 1536
|
Posted: Tue Oct 04, 2005 3:54 am Post subject: |
|
|
| Jim wrote: | | Maybe __declspec(noinline) works with C too. |
__declspec? MSVC now are we? :P
Try __attribute__(noinline) instead :). |
|
| Back to top |
|
 |
|