Inline Assembly: Labels and Other Things
SRLM
Posts: 5,045
This is the code that I'm using as an example for this question:
1) Is the label and branch above correct form? It seems to work for me in both CMM and LMM modes, but I don't know if that's just luck or it's the way it's done.
1.5) Also, is the label guaranteed to be unique, or can it collide? I think I can answer this one by looking at the generated .s file (with -save-temps). It appears that any inline ASM labels are, in fact, global.
2) If the code above has the correct jumping scheme, what about DJNZ? Is there a corollary? I also see that there is BRS and BRW. Is one preferred over the other?
3) What about GAS local labels? They are of the form 1:, so a jump would be
Reference:
http://stackoverflow.com/questions/3898435/labels-in-gcc-inline-assembly
4) Is it possible to call a C/C++ function from assembly? From this page (link, section 5.1.2) I see it's possible to give a function an ASM name. So, is there a way to call that function?
5) For inline assembly, what is the difference for LMM and CMM modes? Can I use the same ASM code for both and in all optimizations?
6) Is there a way to move this assembly into an external .S file, but still execute it as if it was "inline" (ie, not in a new cog)?
7) I'm using the variables that I declare with standard C/C++ syntax. Do I have to do anything special with their addressing? ie, where do they live: in the cog or the hub? Can I have as many as I want, and address them all the same? Continuing this line of thought, what about hub operations such as rdbyte and wrlong? Are these used?
8)Can we use char literals in the inline assembly? I tried using single quotes (ie, #'A'), but it doesn't seem to do anything.
9)Does mova vs. mov have any effect for inline assembly? This code gives the same result both ways:
10) What are the Propeller specific inline constraints? I don't see it listed here: http://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html#Machine-Constraints
Thanks for any and all responses.
int strlenASM(char * string){ int i = 0; int t1; //C version: // for(; string[i] != '\0'; i++){ // } __asm__ volatile ( "strloop: " "rdbyte %[t1], %[string]\n\t" "cmp %[t1], #0 wz\n\t" "if_nz add %[i], #1\n\t" "if_nz add %[string], #1\n\t" /*"if_nz jmp #strloop"*/ "if_nz brw #strloop" : /*outputs (+inputs) */ [i] "+r" (i) : /*inputs */ [string] "r" (string), [t1] "r" (t1) ); return i; }
1) Is the label and branch above correct form? It seems to work for me in both CMM and LMM modes, but I don't know if that's just luck or it's the way it's done.
1.5) Also, is the label guaranteed to be unique, or can it collide? I think I can answer this one by looking at the generated .s file (with -save-temps). It appears that any inline ASM labels are, in fact, global.
2) If the code above has the correct jumping scheme, what about DJNZ? Is there a corollary? I also see that there is BRS and BRW. Is one preferred over the other?
3) What about GAS local labels? They are of the form 1:, so a jump would be
jmp #1But that conflicts with literal constants. Is that a jump to address 1, or label 1:? I know that PropGCC doesn't support local labels of the form ":label:", but is this different?
Reference:
http://stackoverflow.com/questions/3898435/labels-in-gcc-inline-assembly
4) Is it possible to call a C/C++ function from assembly? From this page (link, section 5.1.2) I see it's possible to give a function an ASM name. So, is there a way to call that function?
5) For inline assembly, what is the difference for LMM and CMM modes? Can I use the same ASM code for both and in all optimizations?
6) Is there a way to move this assembly into an external .S file, but still execute it as if it was "inline" (ie, not in a new cog)?
7) I'm using the variables that I declare with standard C/C++ syntax. Do I have to do anything special with their addressing? ie, where do they live: in the cog or the hub? Can I have as many as I want, and address them all the same? Continuing this line of thought, what about hub operations such as rdbyte and wrlong? Are these used?
8)Can we use char literals in the inline assembly? I tried using single quotes (ie, #'A'), but it doesn't seem to do anything.
9)Does mova vs. mov have any effect for inline assembly? This code gives the same result both ways:
__asm__ volatile ( "mov %[t2], #48\n\t" "wrbyte %[t2], %[string]" : /*outputs (+inputs) */ [string] "+r" (string) : /*inputs */ [t2] "r" (t2) );
10) What are the Propeller specific inline constraints? I don't see it listed here: http://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html#Machine-Constraints
Thanks for any and all responses.
Comments
As you note, they are global. You can make them unique for multiple invocations (e.g. if you want this in a macro used multiple places) by appending the label with %= everywhere it is used. %= expands to a unique integer in every snippet of assembly code (the same integer throughout the asm).
There is no equivalent to DJNZ in CMM or LMM mode. BRS is preferred for short branches (within +-511 bytes); in both CMM and LMM it expands to smaller code than BRW.
I've never really tried using GAS local labels. I'd stick with the %= form if I were you.
Yes. By default C functions have their own name but with an underscore prepended (so to call strcpy you have to use _strcpy). The exact form of the call depends on the memory model and whether the function is declared _NATIVE or not. _NATIVE functions are always called with the call instruction. COG mode functions are called with jmpret lr,#_func. LMM mode functions are called with lcall #_func.
Generally you can, although you'll get better (smaller) code if you use the CMM macros like brw, lcall, and so on rather than calling into the kernel directly.
Sure, just declare the entry point as .global and then call it from another file.
Variables are always in HUB memory unless they are declared as _COGMEM. Note though that local variables in functions are often allocated to registers (and function parameters are always in registers, at least for the first 6 parameters) so to access those from assembly you have to use the GNU inline assembly syntax. But for global and static variables just use rdlong/wrlong (for normal variables) or mov (for _COGMEM variables).
No, GAS doesn't understand char literals.
For immediate constants mov and mova are the same, I think.
The Propeller port hasn't been integrated into official GCC releases yet. The PDF from http://code.google.com/p/propgcc does have some Propeller specific documentation. For constraints it says: Note that the W constraint doesn't actually work properly, and does not match anything (it isn't used in the propeller machine description, so we didn't notice it until recently).
Thanks for the good questions,
Eric
As a side note, I really like inline PASM. Before I started, I was bothered by the syntax (the really archaic notation and the "\n\t" on each line), and the lack of documentation in general. But, after spending a few days working on it, inline PASM has turned out to be a cool feature.