A strange behaviour with a lui instruction when single stepping with gdb


(Masayuki Ishikawa) #1

Hello, recently I bought SparkFun RED-V Things Plus which has SiFive FE310-G002 to port NuttX OS.

And during porting NuttX to the board, I found a strange behavior with a lui (load upper immediate) instruction. To reproduce this (perhaps a hardware bug) symptom is very easy.

int hello_main(int argc, FAR char *argv[])
{
  uint32_t a = 0x10000;
  printf("Hello lui! (a=0x%x) \n", a);
  return 0;
}

If I run the above program without gdb, it works without problem.
However, If I add a breakpoint to the hello_main function and continue to run by ‘stepi’ (single step instruction) the program shows incorrect value.

Breakpoint 1, hello_main (argc=1, argv=0x80002eb8) at hello_main.c:55                        
55        printf("Hello lui! (a=0x%x) \n", a);                                               
(gdb) stepi                                                                                  
0x2001b750      55        printf("Hello lui! (a=0x%x) \n", a);                               
(gdb) stepi                                                                                  
0x2001b752      55        printf("Hello lui! (a=0x%x) \n", a);                               
(gdb) disas                                                                                  
Dump of assembler code for function hello_main:                                              
   0x2001b74c <+0>:     lui     a0,0x2001e                                                   
   0x2001b750 <+4>:     addi    sp,sp,-16                                                    
=> 0x2001b752 <+6>:     lui     a1,0x10 
   0x2001b754 <+8>:     addi    a0,a0,1776 # 0x2001e6f0                                      
   0x2001b758 <+12>:    sw      ra,12(sp)                                                    
   0x2001b75a <+14>:    jal     ra,0x2001c2aa <printf>                                       
   0x2001b75e <+18>:    lw      ra,12(sp)                                                    
   0x2001b760 <+20>:    li      a0,0                                                         
   0x2001b762 <+22>:    addi    sp,sp,16                                                     
   0x2001b764 <+24>:    ret                                                                  
End of assembler dump.                                                                       
(gdb) p /x $a1                                                                               
$1 = 0x80002eb8                                                                              
(gdb) stepi                                                                                  
0x2001b754      55        printf("Hello lui! (a=0x%x) \n", a);       
(gdb) p /x $a1                                               
$2 = 0xffff0000   <== incorrect value is always loaded

As far as I tested, this symptom
(1) does not happen without gdb
(2) does not depend register name.
(3) depends on the immediate value (the range is 0x10-1f ?)
(4) does not happen with gdb + qemu (fe310_e)

Because I don’t have any other FE310-G002 chips, so I’m not sure this issue depends on individual chip.

Thanks,
Masayuki Ishikawa


Debugger behaves wrong on `jalr` instruction