Preemptive FAQ, since I've already fielded the same question twice involving putting large amounts of data in your addin. I also wrote up how you can link chunks of C and assembly together. Maybe more to come if multiple people bring up the same questions.


Code:
Q. I get an error like ".data will not fit into region RAM".  Help!

A. You have more than 64k of initialized data.  Usually, this is because you
   have some large array declared which you never write to (such as an image
   to be displayed at some time).  Declare such things with the const qualifier
   to put them in .rodata instead so the compiler knows they don't need to fit
   in to the 64k block of RAM available to us.
   
   Bad:
        char picture[] = {0, 1, 2, 3, ...., 65535};
   Good:
        const char picture[] = {0, 1, 2, 3, ..., 65535};
   
   If you need a lot of RAM at runtime, you should be able to get large amounts
   via malloc() instead of declaring large arrays within functions, which is
   generally preferred to large static allocations anyway.
       
   If you want to write to a large preinitialized buffer at some time, you'll
   have to copy it into a dynamically allocated chunk of RAM.  For example:
   
        const char initializedArray[] = {...};
        char *RWArray = malloc(sizeof(initializedArray));
        memcpy(RWArray, initializedArray, sizeof(initializedArray));


Q. How can I write subroutines for a C program in assembly (or call C routines
   from assembly)?

A. Declare the entry point of your function as global.  Beyond that, you'll
   usually want to provide a prototype so the compiler can better know what
   to expect from your function, and you need to obey the ABI, a quick
   description of which follows.
   
   Every register has a specified purpose in the ABI.  They are defined as
   either caller or callee saves.  If you change the value in a callee-saved
   register, be sure to restore it to its original value before returning.
    - r0-r1     Stores function return value, caller saves.
    - r2-r3     Scratch space, caller saves.
    - r4-r7     Function parameters, caller saves.
    - r8-r13    Scratch, callee saves.
    - r14       Frame pointer, callee saves.
    - r15       Stack pointer, callee saves.
    - MACH,MACL Callee saves.
   
   Parameters are passed in the order they are declared on r4 through r7.  For
   example, if you delared the function as `void foo(int a, char b, long c)',
   a gets passed in r4, b in r5, and c in r6.  Registers will always be filled,
   except if an argument's type is too large to fit in registers.  If a fourth
   argument of type 'long long' (64 bits) were to be added to the above
   example, the entire value would be passed on the stack, not half in r7 and
   half on the stack.  Aggregate types(struct/union) are always passed entirely
   on the stack.
   
   When arguments overflow the four registers allocated to them, they will be
   pushed on to the stack from last to first, putting the lowest-numbered
   argument which is not in registers at the lowest address.  Pushes to the
   stack are always aligned to 4 bytes.  If two bytes were pushed, for example,
   the first would be at (r15+2) and the other at (r15+3), with the two bytes
   at (r15+0) and (r15+1) having undefined values.
   
   Return values of 32 bits or less are returned entirely in r0.  If 8 bytes
   or smaller, r0 is the most significant part of the value and r1 is the least
   significant part.  Otherwise, the caller allocates a buffer in which the
   result should be stored, and passes a pointer to that buffer as a hidden
   last argument to the function.  Neither values returned nor passed in to
   functions will be automatically sign-extended.
   
   A short example of an assembly subroutine, assuming the following prototype:
    int strlen(char *str);
   
        .global _strlen     ; Global linkage
    _strlen:
        mov #0, r2
    _strlen_loop:
        mov.b @r4, r0
        cmp/eq #0, r0
        bt _strlen_done
        add #1, r2
        bra _strlen_loop
        add #1, r4          ; Delay slot
    _strlen_done:
        mov r2, r0
        rts
       
   To compile, include the prototype in a source or header file, and include
   the file containing your routine(s) in the sources to compile.  A good
   choice for the above example might be a file called strlen.s.
Wow, that's a pair of great tips, Tari! I especially like the second one, and may end up giving it a try. Smile
Keep in mind that Malloc() will only initialize about 128 kb of RAM. If you need more, you'll have to use either ASM or one of the ASM libraries that are being written.

But, I don't see any mention of banking in the ASM section. How to GCC deal with the banked registers?
Qwerty.55 wrote:
Keep in mind that Malloc() will only initialize about 128 kb of RAM. If you need more, you'll have to use either ASM or one of the ASM libraries that are being written.

Good to know. How then, do you go about getting larger chunks?

Qwerty.55 wrote:
But, I don't see any mention of banking in the ASM section. How to GCC deal with the banked registers?

It doesn't, as far as the docs lead me to believe. You can only access bank 1 when the processor is in privileged mode (otherwise they may as well not be banked at all), and I'd expect you can't make any assumptions about what the system as a whole might do with them, so don't touch them even if the whole system is running in privileged mode for some reason.
You get larger chunks by not telling the OS what you're doing :p

One way is to use the OS add-in stack, which has 512 KB and there are various other places in RAM that you can use.

As for banking, the processor always operates in privileged mode as far as I've seen. The OS doesn't appear change the privileges when loading add-ins.
There is also the 512 kb system stack which the OS barely touches. At the most I've only seen a few hundred bytes of data in there. The other thing available is the MCS of about 64 kb if you can find some way to archive its contents then reload it.
Qwerty.55 wrote:
As for banking, the processor always operates in privileged mode as far as I've seen. The OS doesn't appear change the privileges when loading add-ins.
Errr, security hole much? Very Happy I really can't wait to try porting Linux or some related lightweight OS over to this. Smile
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement