> Thanks for the information. I know the symbol should be unique.
> Actually, I changed the symbol many time (very unique), but the compiler
> still complains the same thing. If I move the same code (such as a
> function) to another code file, then everything is fine. I am just
> confused...
The problem is that you're copying the compiler *too* closely.
It uses symbols of the form "L%u:" itself. If you use "gcc -S"
on a source file where you get the error, you'll see it immediately.
As Steve recommended, use the "%u:" label feature. That's what it's
designed for, and the compiler doesn't use it.
For those who aren't familiar, it's a wonderful way to avoid having to
think of a uniquie label name for a small jump. You can have many
instances of a label such as "1:" in the source file, and you can
refer to it with "1b" or "1f". These ("1 backward" and "1 forward")
refer to the immediately preceding and following instance of "1:",
respectively.
(Internally, the assembler keeps a counter per label, and when you define
label i, it acts as if you typed printf("$%u$%u:", i, counter[i]++).
Then a reference to %ub comes out to ("$%u$%u", i, counter[i]-1) while
%uf comes out to ("$%u$%u", i, counter[i]). The magic symbols don't
actually involve $ but something really hard to type like control-A,
but you get the idea.)
As for this example source code:
> __asm__ (
> " tst %[x] \n"
> " jge 2f \n"
> " mov #-1,%[x1] \n"
> " jmp 2f \n"
> "6: \n"
> " add %[x],%A[z] \n"
> " addc %[x1],%B[z] \n"
> "1: \n"
> " rla %[x] \n"
> " rlc %[x1] \n"
> "2: \n"
> " rra %[y] \n"
> " jc 5f \n"
> " jne 1b \n"
> " jmp 4f \n"
> "5: \n"
> " sub %[x],%A[z] \n"
> " subc %[x1],%B[z] \n"
> "3: \n"
> " rla %[x] \n"
> " rlc %[x1] \n"
> " rra %[y] \n"
> " jnc 6b \n"
> " cmp #0xFFFF,%[y] \n"
> " jne 3b \n"
> "4: \n"
> //Shift to Q1.15 format (i.e. the top 16 bits are returned)
> " rla %A[z] \n"
> " rlc %B[z] \n"
> " mov %B[z],%[x1] \n"
> : [z] "+r"(z), [x1] "+r"(x1)
> : [x] "r"(x), [y] "r"(y));
Note:
- You can use asm() rather than __asm__() unless you're compiling
with "--ansi". "asm" is a sufficiently popular historical
keyword that GCC doesn't mind reserving it.
- You're not telling the compiler that you modify x and y.
It might get you for that!
Better would be to write:
: [z] "+r"(z), [x1] "+r"(x1), [x] "+r"(x), [y] "+r"(y));
or perhaps:
: [z] "=r"(z), [x1] "=r"(x1), [x] "+r"(x), [y] "+r"(y)
: "0" (0), "1" (0));
You could add a "%" annotation to x, since x and y are associative,
but that only matters if the inputs have different constraints.
I was also trying to come up with a cleverer bit of sign-extension code
based on "subc %[x1],%[x1]", but I couldn't figure out how to get the
carry flag set appropriately. The closest I could come is
bit #0x8000,%[x]
xor #1,SR
subc %[x1],%[x1]
...but I'm not sure what happens to SR if you write to it with
an instruction that sets the status flags. Which takes precedence?
And this is 4 cycles, just like the original branch-based code's
worst case.
Oh! You do a final rla/rlc on %[z] to get it in the right form.
How about doing that on %[x]/%[x1] to start instead:
(WARNING: untested.)
__asm__ (
" rla %[x] \n"
" subc %[x1],%[x1] \n" // x1 = carry - 1
" inv %[x1] \n"
" jmp 2f \n"
"6: \n"
" add %[x],%A[z] \n"
" addc %[x1],%B[z] \n"
"1: \n"
" rla %[x] \n"
" rlc %[x1] \n"
"2: \n"
" rra %[y] \n"
" jc 5f \n"
" jne 1b \n"
" jmp 4f \n"
"5: \n"
" sub %[x],%A[z] \n"
" subc %[x1],%B[z] \n"
"3: \n"
" rla %[x] \n"
" rlc %[x1] \n"
" rra %[y] \n"
" jnc 6b \n"
" cmp #0xFFFF,%[y] \n"
" jne 3b \n"
"4: \n"
" mov %B[z],%[x1] \n"
: [z] "=r"(z), [x1] "&r"(x1), [x] "+r"(x), [y] "+r"(y) : "0" (0));
(When everything's an output, the "&" on x1 isn't strictly necessary, but
it's better to leave it in.)