Home > Software engineering >  Loading variable addresses into registers PowerPC inline Assembly
Loading variable addresses into registers PowerPC inline Assembly

Time:01-18

I am trying to put together and example of coding inline assembly code in a 'C' program. I have not had any success. I am using GCC 4.9.0. As near as I can tell my syntax is correct. However the build blows up with the following errors:

/tmp/ccqC2wtq.s:48: Error: syntax error; found `(', expected `,'
Makefile:51: recipe for target 'all' failed
/tmp/ccqC2wtq.s:48: Error: junk at end of line: `(31)'
/tmp/ccqC2wtq.s:49: Error: syntax error; found `(', expected `,'
/tmp/ccqC2wtq.s:49: Error: junk at end of line: `(9)'

These are related to the input/output/clobbers lines in the code. Anyone have an idea where I went wrong?

  asm volatile("li 7, %0\n"           // load destination address
               "li 8, %1\n"           // load source address

               "li 9, 100\n"              // load count

               // save source address for return
               "mr   3,7\n"

               // prepare for loop
               "subi 8,8,1\n"
               "subi 9,9,1\n"

               // perform copy
               "1:\n"
               "lbzu 10,2(8)\n"

               "stbu 10,2(7)\n"
               "subi 9,9,1\n"              // Decrement the count
               "bne  1b\n"          // If zero, we've finished

               "blr\n"

               : // no outputs
               : "m" (array), "m" (stringArray)
               : "r7", "r8"
               );

CodePudding user response:

It's not clear what you are trying to do with the initial instructions:

li 7, %0
li 8, %1

Do you want to load the address of the variables into those registers? In general, this is not possible because the address is not representable in an immediate operand. The easiest way out is to avoid using r7 and r8, and instead use %0 and %1 directly as the register names. It seems that you want to use these registers as base addresses, so you should use the b constraint:

               : "b" (array), "b" (stringArray)

Then GCC will take care of the details of materializing the address in a suitable fashion.

You cannot return using blr from inline assembler because it's not possible to tear down the stack frame GCC created. You also need to double-check the clobbers and make sure that you list all the things you clobber (including condition codes, memory, and overwritten input operands).

CodePudding user response:

I was able to get this working by declaring a pair of pointers and initializing them with the addresses of the arrays. I didn't realize that the addresses wouldn't be available directly. I've used inline assembly very sparsely in the past, usually just to raise or lower interrupt masks, not to do anything that references variables. I just had some folks who wanted an example. And the "blr" was leftover when I copied a snipet of a pure assembly routine to use as a starting point. Thanks for the responses. The final code piece looks like this:

int main()
{
    char * stringArrayPtr;
    unsigned char * myArrayPtr;

    unsigned char myArray[100];

    stringArrayPtr = (char *)&stringArray;
    myArrayPtr     = myArray;

    asm volatile(
                 "lwz 7,%[myArrayPtr]\n"       // load destination address
                 "lwz 8, %[stringArrayPtr]\n"  // load source address

                 "li 9, 100\n"                 // load count
                 "mr 3,7\n"                    // save source address for return

                 "subi 8,8,1\n"                // prepare for loop
                 "subi 9,9,1\n"

                 "1:\n"                        // perform copy
                 "lbzu 10,1(8)\n"
                 "stbu 10,1(7)\n"
                 "subic. 9,9,1\n"              // Decrement the count
                 "bne  1b\n"                   // If zero, we've finished

                 // The outputs / inputs / clobbered list
                 // No output variables are specified here
                 // See GCC documentation on extended assembly for details.
                 : 
                 : [stringArrayPtr] "m" (stringArrayPtr), [myArrayPtr]"m"(myArrayPtr)
                 : "7","8","9","10"
                 );
}
  • Related