Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
21 years ago

Bug in NIOS2 GCC ?

Could this be a bug in the NIOS2-GCC ?

char testsub(void) {
  return __builtin_ldbio (0x1000);
}

Generates the following Assembly code (Using -O2 and -fomit-frame-pointer):

movi r3, 4096
ldhio r2, 0(r3)
slli r2, r2, 24
srai r2, r2, 24
ret

Why doesn't it just generate a ldbio r2, 0(r3)

I also found the following Code in the (Nios Homedir)/bin/nios2-gnutools/src/gcc/gcc/config/nios2/nios2.md File (available only if GCC Sources are installed) :

(define_insn "ldbio"
   UNSPEC_LDBIO))
   (use (match_operand:SI 1 "memory_operand" "m"))]
  ""
  "ldhio\t%0, %1"
  )

Does anybody know why GCC translates every __builtin_ldbio into a ldhio?

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Sgan,

    Thank you very much for finding this issue in the compiler. You are correct that there is a bug here, __builtin_ldbio() should be translating to a ldbio instruction, not a ldhio. This issue will be fixed for the next release of the compiler. If this is causing you a particular issue, I recommend either using __builtin_ldbuio() and sign extending it, or using extended assembly statements.

    That said, there is a related conversation elsewhere on the forum that you may be interested in.

    http://www.niosforum.com/forum/index.php?a...ct=st&f=2&t=435 (http://www.niosforum.com/forum/index.php?act=st&f=2&t=435)

    This discusses some of the other issues that you point out here, as even if this bug did not exist, the generated assembly would be:

    movi r3, 4096
    ldbio r2, 0(r3)
    slli r2, r2, 24
    srai r2, r2, 24
    ret

    in this case as __builtin_ldXio returns ints.

    Jonah
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Well, the Subroutine testfunc above at least returns the correct result, because of the shifts... BUT look at this:

    long testsub(void) {
      return __builtin_ldbio (0x1000);
    }

    When you compile this code, you can be sure that you get wrong results... the generated assembly code looks like this:

    movhi r3, 4096
    ldhio r2, 0(r3)
    ret

    With this code, you can be sure you get wrong results...

    Simon
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Sgan,

    <div class='quotetop'>QUOTE </div>

    --- Quote Start ---

    With this code, you can be sure you get wrong results...[/b]

    --- Quote End ---

    You are correct. Which is why I recommend not using the defective builtin.

    <div class='quotetop'>QUOTE </div>

    --- Quote Start ---

    Thank you very much for finding this issue in the compiler. You are correct that there is a bug here, __builtin_ldbio() should be translating to a ldbio instruction, not a ldhio. This issue will be fixed for the next release of the compiler. If this is causing you a particular issue, I recommend either using __builtin_ldbuio() and sign extending it, or using extended assembly statements.[/b]

    --- Quote End ---

    Let me elaborate on the above. What I recommend your code look like is this:

    int testsub1(void) {
      char x = __builtin_ldbuio ((void *)0x1000);
      return (int)x; // sign extend x
    }

    Or using asm statements:

    int testsub2(void) {
      int x;
      asm ("ldbio %, 0(%)" :  "=r" (x) :  "r" (0x1000));
      return x;
    }
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Jonah,

    Just wanted to say thanks! I used your asm example in my legacy NiosII port just this hour with great results!

    This may be a topic for another thread, but is there any way to read one and only one byte from an 8 bit peripheral? I did the trick of ignoring the bottom 2 address bits to read one and only one address, but still issues 4 read pulses. Not always good with an 8 bit fifo. LDWIO is smart enough to grab all 4 fifo pops into a single long word, but there aren&#39;t always 4 bytes in the fifo.

    Ken