> 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.)

Reply via email to