Bug 18407

Summary: Bfin simulator - error in handling >>> (S), when shift value > 16
Product: gdb Reporter: Igor Rayak <igorr>
Component: simAssignee: Mike Frysinger <vapier>
Status: RESOLVED FIXED    
Severity: normal CC: igorr, vapier
Priority: P2    
Version: 7.9   
Target Milestone: ---   
Host: Target: bfin-elf
Build: Last reconfirmed:
Attachments: suggested patch

Description Igor Rayak 2015-05-13 11:02:35 UTC
1. Let's compile the following code:
$ cat > test1.s
        .global __start
__start:
        LINK 0xc ;
        R1 = 2 ;
        R1 = R1 >>> 1;
        R1 = 2;
        R1 = R1 >> 1;
        R1 = 2;
        R1 = R1 >>> 1 (S);
        R1 = 2;
        .byte 0x82, 0xc6, 0xf9, 0x43 ;
        UNLINK;
        RTS;
$ bfin-linux-uclibc-gcc -nostdlib test1.s -o test1

2. Run objdump on it:
bfin-linux-uclibc-objdump -d test1

test1:     file format elf32-bfinfdpic

Disassembly of section .text:

00000074 <__start>:
  74:	00 e8 03 00 	LINK 0xc;		/* (12) */
  78:	11 60       	R1 = 0x2 (X);		/*		R1=0x2(  2) */
  7a:	82 c6 f9 03 	R1 = R1 >>> 0x1;
  7e:	11 60       	R1 = 0x2 (X);		/*		R1=0x2(  2) */
  80:	82 c6 f9 83 	R1 = R1 >> 0x1;
  84:	11 60       	R1 = 0x2 (X);		/*		R1=0x2(  2) */
  86:	82 c6 f9 43 	R1 = R1 << 0x3f (S);
  8a:	11 60       	R1 = 0x2 (X);		/*		R1=0x2(  2) */
  8c:	82 c6 f9 43 	R1 = R1 << 0x3f (S);
  90:	01 e8 00 00 	UNLINK;
  94:	10 00       	RTS;

3. Bug/Feature (binutils?) R1 = R1 >>> 1(S) is displayed as R1 = R1 << 0x3f (S);

4. Let's compile and run this code on VisualDSP++ environment simulator. 
in all 4 cases R1 will get the value 0x1 after the shift

5. Let's run the same test in bfin-simulator:
$ bfin-linux-uclibc-gdb test1
GNU gdb (GDB) 7.9
...<skip>
Reading symbols from test1...(no debugging symbols found)...done.
(gdb) b *0x74
Breakpoint 1 at 0x74
(gdb) set disassemble-next-line on
(gdb) target sim
Connected to the simulator.
(gdb) load
Loading section .text, size 0x24 lma 0x74
Start address 0x74
Transfer rate: 288 bits in <1 sec.
(gdb) r
Starting program: ./test1 

Breakpoint 1, 0x00000074 in _start ()
=> 0x00000074 <_start+0>:	00 e8 03 00	LINK 0xc;		/* (12) */
(gdb) display/x $r1
1: /x $r1 = 0x0
(gdb) si
0x00000078 in _start ()
=> 0x00000078 <_start+4>:	11 60	R1 = 0x2 (X);		/*		R1=0x2(  2) */
1: /x $r1 = 0x0
(gdb) si
0x0000007a in _start ()
=> 0x0000007a <_start+6>:	82 c6 f9 03	R1 = R1 >>> 0x1;
1: /x $r1 = 0x2
(gdb) si
0x0000007e in _start ()
=> 0x0000007e <_start+10>:	11 60	R1 = 0x2 (X);		/*		R1=0x2(  2) */
1: /x $r1 = 0x1
(gdb) si
0x00000080 in _start ()
=> 0x00000080 <_start+12>:	82 c6 f9 83	R1 = R1 >> 0x1;
1: /x $r1 = 0x2
(gdb) si
0x00000084 in _start ()
=> 0x00000084 <_start+16>:	11 60	R1 = 0x2 (X);		/*		R1=0x2(  2) */
1: /x $r1 = 0x1
(gdb) si
0x00000086 in _start ()
=> 0x00000086 <_start+18>:	82 c6 f9 43	R1 = R1 << 0x3f (S);
1: /x $r1 = 0x2
(gdb) si
0x0000008a in _start ()
=> 0x0000008a <_start+22>:	11 60	R1 = 0x2 (X);		/*		R1=0x2(  2) */
1: /x $r1 = 0x7fffffff
(gdb) 
 
6. Bug. After the last shift R1 should be equal to 0x1. Saturated shift Right is treated as saturated shift left.
Comment 1 Igor Rayak 2015-05-13 11:12:13 UTC
Created attachment 8310 [details]
suggested patch
Comment 2 Mike Frysinger 2015-05-13 16:02:00 UTC
which CPU are you running this against ?  historically, we dropped support for BF535 and only went for newer processors as customers had already moved away from it and it had too many quirks wrt all other versions.
Comment 3 Igor Rayak 2015-05-13 16:16:19 UTC
r u asking which CPU I'm simulating on visualDSP++? It gives the same results on both simulators supplied with visualDSP++, e.g. bf535 and all others. If I recall correctly I've checked it on bf532.

in any case it's strange that objdump creates something which cannot be compiled:
e.g. R1 = R1 >>> 1 (S) after compiled, converted to R1 = R1 << 0x3f (S) by objdump, and later cannot be compiled by gcc. Which seems to be wrong, unrelated to CPU type.
Comment 4 Mike Frysinger 2015-05-13 16:56:24 UTC
i'm not terribly interested in how the vdsp sim operates :).  the gnu sim should match the hardware.  if you're seeing a diff between bf532 in the sim and real hardware, then that def needs fixing.

unfortunately i'm traveling atm and won't have access to bfin hardware for a while to run some tests.

wrt objdump, i agree it's a bit weird.  i'll take a look at that too.  there are some cases where the hardware actually respects the full shift amount even though it's not documented in the PRM.  the disassembler can also be pretty basic in its decoding ... i've been meaning to sync the sim & opcodes at some point.
Comment 5 Sourceware Commits 2015-10-11 07:43:03 UTC
The master branch has been updated by Michael Frysinger <vapier@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=3f946aa82518e878aea2cba4b6a9bcc651412c5c

commit 3f946aa82518e878aea2cba4b6a9bcc651412c5c
Author: Mike Frysinger <vapier@gentoo.org>
Date:   Sun Oct 11 03:32:11 2015 -0400

    sim: bfin: handle negative left saturated shifts as ashifts [BZ #18407]
    
    When handling left saturated ashifts with negative immediates, they
    should be treated as right ashifts.  This matches hardware behavior.
    
    Reported-by: Igor Rayak <igorr@gitatechnologies.com>
Comment 6 Mike Frysinger 2015-10-11 07:43:41 UTC
thanks, i've committed a fix to the master branch now