This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Pass in an immediate value to an inline assembly function

Note: This was originally posted on 6th March 2009 at http://forums.arm.com

Hi,

I would like to pass in an immediate value to an inline assembly function, such as in this example:

inline int foo(int a, int b, const int immed)
{
   register int result;
   __asm
   {
      add   result, a, b, lsl #immed
   };
   return(result);
}

I am calling foo() with values of 5 or 6 for the immed operand, such as
z = foo(a, b, 5);

For the RVCT 3.0 armcc compiler, I get this error message for the immed operand: "Operand should be constant"

Is there any way to pass in the immediate value, which is known at compile time?


Note the analogous GCC version for the foo() definition has the additional syntax of "i"(immed) for the immediate operand, which allows for successful compilation.  That is, I don't have the problem for GCC.

Thanks
  • Note: This was originally posted on 9th March 2009 at http://forums.arm.com

    > both of the following yield the same compiler error about needing a constant:
    > pkhbt     result, a, b, lsl #immed

    This is for the same reason as before.

    > pkhbt   result, a, b, lsl immed

    The is because there is no shift-by-register version of this instruction (see the ARM ARM or "ARM and Thumb-2 Instruction Set Quick Reference Card" on www.arm.com->Documentation), so the compiler is treating it as the #immed case, for which the # is documented as optional.

    > d. My GCC version of the inline declarations allowed me to write the main program code as
    > z = foo(a, b, 5);
    > y = foo(a, b, 7);

    Quite possibly something not supported in RVCT - I don't know. (We're a long way away from portable C here!!!)

    > Unless I find a solution, I'll have to have calls like
    > z = foo5(a, b ),  where foo5 does the lsl by 5
    > or
    > y = foo7(a, b ), where foo7 does the lsl by 7.

    Yep - and no impact of final code size assuming it all inlines successfully.

    I guess you could generate accessors for these functions using a macro to keep your source changes localised. Something like..
    #define foo(a,b,c) foo##c((a),(b))

    Getting really ugly, you could also factorize the implementations with a macro something like...
    #define IMPLEMENT_FOO_N(shiftby) \
    __inline int foo##shiftby(int a, int b) \
    {\
       register int result;\
       __asm\
       {\
          add   result, (a), (b), lsl 0##shiftby \
       };\
       return(result);\
    }

    IMPLEMENT_FOO_N(5);
    IMPLEMENT_FOO_N(7);
  • Note: This was originally posted on 9th March 2009 at http://forums.arm.com

    Hi unclep,
    These are great answers and suggestions.
    I now feel my questions have been answered.

    Thanks