Hi all:
Most tests in the or1ksim's test suite are written in C and do not
initialise the BSS section properly. They still work because the
simulator initialises all memories with zeroes. This is an excerpt from
file default.cfg used by most test cases:
section memory
pattern = 0x00
type = unknown /* Fastest */
...
I changed that configuration to "type = exitnops" and some of the tests
stopped working. There is no guarantee that all RAM contents will be
zeroed on reset, so decided to add code to clear the BSS section properly.
On a side note, I found this type of code at several places like the
OpenRISC bootloaders:
/* Clear the BSS section */
l.movhi r3, hi(_bstart)
l.ori r3, r3, lo(_bstart)
l.movhi r4, hi(_bend)
l.ori r4, r4, lo(_bend)
bss_clear_loop:
l.sw 0(r3),r0
l.sfgtu r3, r4
l.bnf bss_clear_loop
l.addi r3, r3, 4
Note that this code writes at least 32 bits worth of zeroes, but the BSS
section could be empty, so it could be writing out of bounds.
Going back to or1ksim's test suite, the first think I did was to add
symbols _bstart and _bend to linker script file default.ld like this:
.bss :
{
_bstart = .;
*(.bss)
_bend = .;
} > ram
In the case of <or1ksim repository>/testsuite/test-code-or1k/basic ,
that produced the following results:
0000327c l d .bss 00000000 .bss
00002580 l .text 00000000 bss_clear_loop
0000327c l O .bss 00000004 period.1455
00003280 g O .bss 00000100 int_handlers
0000327c g .bss 00000000 _bstart
00003280 g .bss 00000000 _bend
Note that int_handlers is 0x100 bytes long (it's an array), but it does
not come up in the resulting length ( _bend - _bstart ).
I then changed the linker script file to this:
.bss :
{
*(.bss)
} > ram
_bstart = ADDR(.bss);
_bend = _bstart + SIZEOF(.bss);
And got these results:
0000327c l d .bss 00000000 .bss
00002580 l .text 00000000 bss_clear_loop
0000327c l O .bss 00000004 period.1455
00003280 g O .bss 00000100 int_handlers
0000327c g .bss 00000000 _bstart
00003380 g *ABS* 00000000 _bend
That worked. Then I did yet another test to confirm the problem, I added
2 new symbols to the first version like this:
.bss :
{
_bstart = .;
*(.bss)
_bend = .;
} > ram
_BSS_BEGIN = ADDR(.bss);
_BSS_END = _BSS_BEGIN + SIZEOF(.bss);
And this is what I got:
0000328c l d .bss 00000000 .bss
0000328c l O .bss 00000004 period.1455
00003290 g O .bss 00000100 int_handlers
0000328c g .bss 00000000 _bstart
0000328c g .bss 00000000 _BSS_BEGIN
00003390 g *ABS* 00000000 _BSS_END
00003290 g .bss 00000000 _bend
Note that, while _bstart and _BSS_BEGIN have the same value, _BSS_END
and _bend do not (!).
I certainly did not expect that behaviour. Does anybody here know why
the results are different? I am using the svn head versions from
OpenCore's gnusrc repository (gcc-4.5.1 and binutils-2.20.1).
The assembly code that clears BSS writes 32-bits at a time, therefore,
if BSS's size is not aligned, it might clear up to 3 bytes beyond the
end. This is not normally a problem, as the start of the next section is
normally aligned and those (up to) 3 bytes should be padding anyway. In
the past, I've made sure that the BSS section length is aligned with
this trick:
. = ALIGN(., 4);
However, that does not seem to work for the OpenRISC toolchain either. I
added a couple of "char xxxx" variables and BSS's size was no longer
aligned. It's not so important, but I'm worried that something may not
be working properly in the OpenRISC port. Or maybe I don't quite
understand what's going on with the linker script.
Thanks,
R. Diez
_______________________________________________
OpenRISC mailing list
[email protected]
http://lists.openrisc.net/listinfo/openrisc