Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++

Bug in NIOS2 GCC ?

Altera_Forum
Honored Contributor II
2,376 Views

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?
0 Kudos
4 Replies
Altera_Forum
Honored Contributor II
914 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
914 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
914 Views

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; }
0 Kudos
Altera_Forum
Honored Contributor II
914 Views

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
0 Kudos
Reply