Shop OBEX P1 Docs P2 Docs Learn Events
Inline assembler question — Parallax Forums

Inline assembler question

David BetzDavid Betz Posts: 14,516
edited 2013-01-04 16:53 in Propeller 1
I'm working on some pin functions for Propeller 2 and am having trouble with inline assembly. I've written the following inline function for setting the value of a pin:
static __inline__ void p2_setpin(uint32_t pin, uint32_t value)
{
    __asm__ volatile (
        "rcr %1, #1 wc\n\t"
        "setpc %0"
    : /* no outputs */
    : /* inputs */
        "r" (pin),
        "r" (value)
    : /* no clobbered registers */
    );
}

My problem is that the following generated code is wrong. It reuses r5 even though it is clobbered by the rcr instruction. Does anyone know how to fix this?

Source code fragment: (prop_setpin is a macro that calls p2_setpin with the same arguments)
_NATIVE
void main(volatile struct toggle_mailbox *m)
{
for (;;){
 prop_setpin(32, 1);
 prop_setpin(33, 1);
 prop_waitcnt(prop_getcnt() + *CLKFREQ_P);
 prop_waitcnt(prop_getcnt() + (*CLKFREQ_P >> 2));
}
...

Generated code:
_main
        rdlong  r4, .LC0
        mov     r1, r4
        shr     r1, #2
        mov     r2, #32
        mov     r5, #1
        mov     r3, #33
        mov     r6, #0
.L2
' 94 "propstuff.h" 1
        rcr r5, #1 wc
        setpc r2
' 0 "" 2
' 94 "propstuff.h" 1
        rcr r5, #1 wc
        setpc r3

Comments

  • David BetzDavid Betz Posts: 14,516
    edited 2013-01-01 07:43
    FYI, I fixed this with the following code:
    static __inline__ void p2_setpin(uint32_t pin, uint32_t value)
    {
        __asm__ volatile (
            "rcr %0, #1 wc\n\t"
            "setpc %1"
        : /* outputs */
            "=r" (value)
        : /* inputs */
            "r" (pin),
            "0" (value)
        : /* no clobbered registers */
        );
    }
    
  • jac_goudsmitjac_goudsmit Posts: 418
    edited 2013-01-02 01:08
    David Betz wrote: »
    FYI, I fixed this with the following code:

    I have to say I prefer the following notation for readability.
    Also I think instead of using value as input and output parameter, it's probably better to use it as output parameter with "+" meaning "input and output".
    static __inline__ void p2_setpin(uint32_t pin, uint32_t value)
    {
        __asm__ volatile (
            "rcr %[pin], #1 wc\n\t"
            "setpc %[value]"
        : /* outputs */
            [value] "+r" (value)
        : /* inputs */
            [pin] "r" (pin),
        : /* no clobbered registers */
        );
    }
    

    Note, I didn't test if this made a difference and my experience with inline assembly on GCC is still limited...

    ===Jac
  • David BetzDavid Betz Posts: 14,516
    edited 2013-01-02 04:12
    I have to say I prefer the following notation for readability.
    Also I think instead of using value as input and output parameter, it's probably better to use it as output parameter with "+" meaning "input and output".
    static __inline__ void p2_setpin(uint32_t pin, uint32_t value)
    {
        __asm__ volatile (
            "rcr %[pin], #1 wc\n\t"
            "setpc %[value]"
        : /* outputs */
            [value] "+r" (value)
        : /* inputs */
            [pin] "r" (pin),
        : /* no clobbered registers */
        );
    }
    

    Note, I didn't test if this made a difference and my experience with inline assembly on GCC is still limited...

    ===Jac
    I have to say that I've been unable to find any decent documentation on inline assembly for GCC. Almost everything you find is highly geared toward the x86. If anyone has a pointer to a more generic description or even a chip-specific description for a RISC architecture I'd love to see it.
  • jac_goudsmitjac_goudsmit Posts: 418
    edited 2013-01-02 19:15
    David Betz wrote: »
    I have to say that I've been unable to find any decent documentation on inline assembly for GCC.

    That's because I haven't written it yet :-)

    ===Jac
  • David BetzDavid Betz Posts: 14,516
    edited 2013-01-03 04:40
    That's because I haven't written it yet :-)

    ===Jac
    I didn't mean for the Propeller in particular. I meant for *any* non-x86 processor.
  • jac_goudsmitjac_goudsmit Posts: 418
    edited 2013-01-03 08:59
    David Betz wrote: »
    I didn't mean for the Propeller in particular. I meant for *any* non-x86 processor.

    That's because you haven't written it yet :-)

    (Sorry, I couldn't resist)

    But seriously: It's probably difficult to write a web page about inline assembly that doesn't focus on just one processor without giving a lot of information that's going to be useless to the reader. And because so many people use the x86, the x86-biased pages are obviously going to come out on top in Google results.

    Another problem is that many pages are apparently outdated so they don't mention the named parameters syntax that I used in the code fragment above. Actually I can't even find the page where I found out what the '+' modifier does, right now.

    Interestingly, googling for "Propeller gcc inline assembler" (without the quotes), does yield some pages about other processors such as ARM.

    ===Jac
  • David BetzDavid Betz Posts: 14,516
    edited 2013-01-03 11:44
    That's because you haven't written it yet :-)

    (Sorry, I couldn't resist)

    But seriously: It's probably difficult to write a web page about inline assembly that doesn't focus on just one processor without giving a lot of information that's going to be useless to the reader. And because so many people use the x86, the x86-biased pages are obviously going to come out on top in Google results.

    Another problem is that many pages are apparently outdated so they don't mention the named parameters syntax that I used in the code fragment above. Actually I can't even find the page where I found out what the '+' modifier does, right now.

    Interestingly, googling for "Propeller gcc inline assembler" (without the quotes), does yield some pages about other processors such as ARM.

    ===Jac
    I knew about the bracket syntax and used it in the existing propeller.h but left it out of propstuff.h out of laziness. I'll put it in when I merge propstuff.h into propeller.h.

    If you find a reference to "+" please let me know. I haven't ever seen that.
  • jac_goudsmitjac_goudsmit Posts: 418
    edited 2013-01-04 15:17
    David Betz wrote: »
    If you find a reference to "+" please let me know. I haven't ever seen that.

    Here you go: http://gcc.gnu.org/onlinedocs/gcc/Modifiers.html#Modifiers
    '+' Means that this operand is both read and written by the instruction. When the compiler fixes up the operands to satisfy the constraints, it needs to know which operands are inputs to the instruction and which are outputs from it. `=' identifies an output; `+' identifies an operand that is both input and output; all other operands are assumed to be input only.

    If you specify `=' or `+' in a constraint, you put it in the first character of the constraint string.
  • David BetzDavid Betz Posts: 14,516
    edited 2013-01-04 16:53
Sign In or Register to comment.