Shop OBEX P1 Docs P2 Docs Learn Events
How to write ASM functions — Parallax Forums

How to write ASM functions

KyeKye Posts: 2,200
edited 2013-03-21 19:29 in Propeller 1
Is their some information on this? Let's say I want to create an .S file with assembly code with an .h file that has the function definitions. How do I go about writing the assembly code?

Also, let's say I want to use the fast cache with my asm code. Can I easily do this? Or should I write the code in C? And if I write the code in C, how to I tell the compiler it needs to cache things?

I need to implement a bunch of low level I/OI operations and I'm going to try to make them as fast as possible. My model is XMMC using an octal SPI bus.

The type of stuff I need to do is like...

RC Time
Pulse In
Pulse Out
Shift In
Shift Out
Pin High
Pin Low
etc.

Thank you,

Comments

  • ersmithersmith Posts: 6,054
    edited 2013-03-21 19:29
    There's some documentation in gas.pdf on writing LMM/CMM/XMM assembly code. Basically you use "brs" (for short branches, <256 bytes) or "brw" (for longer branches) instead of "jmp", "lcall" instead of "call", and "lret" instead of "ret" in order to write LMM code. "lcall" and "lret" use the "lr" register (register 15) so make sure to save/restore this if you want to nest calls.

    You can also put your assembly language functions into the LMM/XMM kernel itself. Use ".section .kernel" to introduce code that's going in the kernel.There's not a lot of room in the kernel, so you may quickly run out of memory! You can write pretty much normal PASM style code, except that GAS uses byte addresses instead of long addresses (that's a pretty big gotcha, but is generally only a problem for self-modifying code). C always adds an underscore in front of function names (so the C function "bar" is in assembly "_bar"). Generally you'll want to declare such functions as _NATIVE in the C headers, so they can be called with "call" and can return with "ret". Make sure to declare both a _foo and _foo_ret symbol, and make them both global if they are to be visible outside of the current function. Parameters are passed in r0-r5, and return values go in r0. So for example a function that just increments its argument would look something like:
       .global _inc1
       .global _inc1_ret
       .section .kernel
    _inc1
        add r0, #1
    _inc1_ret
        ret
    
    and it would be declared in C with:
    #include <propeller.h>
    extern _NATIVE int inc1(int x);
    

    You can declare _NATIVE functions in C (where they will go into the kernel by default). So the above could be written in C with:
    _NATIVE int inc1(int x) { return x+1; }
    
    which on any reasonable optimization setting will produce equivalent assembly output to the hand coded example above.

    If a C function is declared with _FCACHE it will be loaded in its entirely into the fcache before execution, if it fits and is otherwise compatible with fcache. That's probably the easiest way to guarantee timing with C functions in XMM and LMM modes (it's what we use for the serial I/O).

    Using the fast cache for assembly code is possible, but a bit awkward (and it isn't documented yet). Your best bet is to look at the output from the C compiler to see how to do this.

    Eric
Sign In or Register to comment.