GP2X Embedding Assembler In C


Simon

Still Fresh
Joined
Jan 11, 2007
Messages
47
Hi all

Im interested in learning some assembler for the gp2x, wrapped in C.

Quick question tho - how do I know which registers I can use and which I cant? Obviously the compile C side of things will be using registers, but how do I know which are in use?

or does it push all the registers to a stack before running the embedded bit?

Thanks
 
You need to read the ARM APCS Docs (http://www.heyrick.co.uk/assembler/apcsintro.html) and the GCC documentation relating to the "asm" keyword (http://gcc.gnu.org/onlinedocs/). There is a lot you can do which would take a long time to describe in a simple post like this, so it's best to read up.

The APCS docs will give you the basics though, but your just starting out, I'd shove any register you use on the pseudo-stack (R13) and then look at the gcc generated code later to see any redundant stack pushing and popping. If you replace an entire function with asm, you can kill R0 - R3 without saving them as the first four function parameters are stored in these regs.
 
yeh, I considered just pushing to a stack, but for me any redundancy just isnt acceptable :D I come from a 6502 assembler background so squeezing performance is ingrained in me :D

Good idea of looking at the compiled code though. Ill check out the docs, thanks!
 
ensure you look at the docs for the 'asm' keyword very closely. It's not simply a matter of inserting asm in your C - it's very powerful and can help you optimise. For example, if you want a particular variable in a certain register, or an unused register without pushing&popping/etc, it can do all this for you. It can even do things like when you ask for variable "X", it can say "Well, that variable is already in register Y, so just use that.".

For example, instead of this:

Code:
unsigned long REGPARAM2 CPUFUNC(op_0000_0)(u32 opcode)
{
	u32 dstreg = opcode & 7;
{{	s8 src = get_ibyte (2);
{	s8 dst = m68k_dreg(regs, dstreg);
	src |= dst;
	CLEAR_CZNV;
	SET_ZFLG (((s8)(src)) == 0);
	SET_NFLG (((s8)(src)) < 0);
	m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
}}}	m68k_incpc (4);
return 12 * 256;
}

you might just want to rewrite the flags calculation part:

Code:
unsigned long REGPARAM2 CPUFUNC(op_0000_0)(u32 opcode)
{
	u32 dstreg = opcode & 7;
{{	s8 src = get_ibyte (2);
{	s8 dst = m68k_dreg(regs, dstreg);
asm volatile ("mov %0, %0, lsl #24;orrs %0, %0, %2, lsl #24; mrs %1, cpsr; bic %1, %1, #0x30000000; mov %0, %0, lsr #24" : "+r" (src), "=r" (regs.flags_cznv) : "r" (dst));
	m68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ~0xff) | ((src) & 0xff);
}}}	m68k_incpc (4);
return 12 * 256;
}
 
Back
Top