From justin.fletcher@ntlworld.com Mon Apr 19 22:58:16 2004 Date: Thu, 4 Sep 2003 01:17:19 +0100 From: Justin Fletcher Newsgroups: comp.sys.acorn.programmer Subject: Re: Justin's super-quick guide to compiling C for use from other languages On Thu, 4 Sep 2003, Philip Ludlam wrote: > On 3 Sep, in message @buttercup ? Excuse me, that sucks. 'world unique' ? I don't think so :-( > Justin Fletcher wrote: > > [snip] > > >Justin's super-quick guide to creating code to use from other languages in > >C... > > I'ld hate to see the long version :-) ! It'd be a lot drier and it'd probably make a lot more sense :-) I did kinda get carried away there, though. > [snip] > > >The registers passed in by BASIC are : > > > >R0-R7 A% - H% > > [snip] > > The one thing that got me when I read this was a bit near the end: > > >In our case, you might want r7 to always contain a pointer to some global > >structure. That's H% from your BASIC code. That restricts the number of > >parameters you can pass, but you also shouldn't need as many parameters. > > > >You might achieve this something like this : > > > >---- > >DIM globalmem% 8 > >H%=globalmem% > >REM +0 = list% value > >REM +4 = number of items in list (after sorting) > > [snip] > > >---- > > > >Notice that H% is initialised at the start of the code and we assume it is > >never modified in the BASIC. > > > >---- > >typedef struct globalmem_s { > > listdata_t *list; > > int nitems; > >} globalmem_t; > > > >globalmem_t __global_reg(4) *globalmem; > > > >void sort(void) > >{ > > int counted=0; > > /* Stuff... */ > > globalmem->nitems = counted; > >} > >---- > > Not being able to find a definition of __global_reg() I am firstly > womdering where I might find it. It's a Norcroft specific feature that you can find documented in some versions of the ARM SDK documentation, and the Aquarius pre-release notes. I don't remember if it's in the normal C manual itself but off the top of my head I don't believe it is. I have found a few references to the use of the __global_reg usage in a quick google search, but the most useful has to be the ADS_CompilerGuide_D PDF which is ARM DUI 0067D; see page 3-11 (PDF page 67). > And secondly, shouldn't it be passed the value 7 to correspond with r7 > and H% as H% is a ptr to globalmem? Registers 0-3 (a1-a4) are general purpose registers and therefore cannot be remapped. The register we want to remap is r7, which is known - in APCS - as v4, so '4' is the logical register we're using as our global register. The use of the __global_reg is something you'll just have to be careful with. It's very useful when you're integrating a load of C code into an assembler module - all your veneers to the C code effectively become : Push "r1-r3,r10,r12" MOV r10, r12 BL bit_of_c Pull "r1-r3,r10,r12" Or something similar (I use a macro that makes such things easier anyhow). Here, I'm using r10 as the global register and in one of the .h files I describe the entire module's workspace in terms of C structures, or at least the bits that I need to access. Do remember, though, that using the __global_reg directive will directly affect the object code's compatibility with other APCS variants. You have to ensure that the directive is used consistently in all the code you link against. You can interwork the code with different usage of __global_reg but you just need to keep yourself sane whilst doing so. Still, it's simpler than following through reentrant code. As an aside, I also recommend reading ARM DAI 0034A which, albeit quite old, contains handy hints for writing C code that's ARM-friendly. It's not huge, and you get used quite quickly to thinking about what you're doing in terms of register allocations, etc anyhow. In general a better algorithm always wins over a poor algorithm tailored for ARM, both in readability and portability. But that doesn't mean you should be sloppy :-) Is that a little clearer ? -- Gerph {djf0-.3w6e2w2.226,6q6w2q2,2.3,2m4} URL: http://www.movspclr.co.uk/ ... I can't seem to find myself again. My walls are closing in.