Startup Operations

The "no-system" code, defined in crt0.s, starts from _start at address 0x00000000. It sets the stack pointer, global pointer, and exception trap registers, and then jumps to __start_2.

This code makes the following calls:

void __start_2 (void)
{
  _zero_bss (&__bss_start, 0, &_end - &__bss_start);
  _init ();
  exit (main (0, 0, 0));
}

See zero_bss.

Note from the symbol table that __bss_start equals _end, so that the bss section has zero length.

Source: crt0.s

	#
	# crt0.s
	#
	# NIOS2 startup code
	#

	# Startup code
	# This will work with the simulator, which is
	# its real purpose.

	.section	.text
	.align	3
	.globl	_start
	.type	_start,@function

_start:

	# set up the stack pointer.
	movhi	sp, %hiadj(nasys_stack_top)
	addi	sp, sp, %lo(nasys_stack_top)

	# make sure it is aligned
	nor	sp, sp, sp
	ori	sp, sp, 0x7 # clear lowest three bits
	nor	sp, sp, sp

	# set up the global pointer.
	movhi	gp, %hiadj(_gp)
	addi	gp, gp, %lo(_gp)

	#set up the exception temporary
	movhi	et, %hiadj(_end)
	addi	et, et, %lo(_end)
	
	movhi	r2, %hiadj(__start_2)
	addi	r2, r2, %lo(__start_2)
	jmp	r2

Symbol Table

0000080c A __bss_start
0000080c A _edata
0000080c A _end
00008800 A _gp
00000808 G _impure_ptr
00000288 W _init
00000000 T _start
000002cc T _zero_bss
0000048c d impure_data
07ffff00 A nasys_stack_top

See key for the meaning of the symbol type characters.

Disassembly (__start)

00000000 <_start>:
   0:    06c20034     movhi    sp,2048
   4:    deffc004     addi    sp,sp,-256

   8:    def6303a     nor    sp,sp,sp
   c:    dec001d4     ori    sp,sp,7
  10:    def6303a     nor    sp,sp,sp

  14:    06800074     movhi    gp,1
  18:    d6a20004     addi    gp,gp,-30720

  1c:    06000034     movhi    et,0
  20:    c6020304     addi    et,et,2060

  24:    00800034     movhi    r2,0
  28:    1080a304     addi    r2,r2,652
  2c:    1000683a     jmp    r2

Simulation (_start)

spnasys_stack_top0x7ffff00
gp_gp0x8800
et_end0x80c

0x00000000 <_start>:      0x06c20034  movhi sp, 2048 [dstData=0x8000000 dstReg=sp]
0x00000004 <_start+0x4>:  0xdeffc004  addi sp, sp, -256 [dstData=0x7ffff00 dstReg=sp]
0x00000008 <_start+0x8>:  0xdef6303a  nor sp, sp, sp [dstData=0xf80000ff dstReg=sp]
0x0000000c <_start+0xc>:  0xdec001d4  ori sp, sp, 7 [dstData=0xf80000ff dstReg=sp]
0x00000010 <_start+0x10>: 0xdef6303a  nor sp, sp, sp [dstData=0x7ffff00 dstReg=sp]
0x00000014 <_start+0x14>: 0x06800074  movhi gp, 1 [dstData=0x10000 dstReg=gp]
0x00000018 <_start+0x18>: 0xd6a20004  addi gp, gp, -30720 [dstData=0x8800 dstReg=gp]
0x0000001c <_start+0x1c>: 0x06000034  movhi et, 0 [dstData=0x0 dstReg=et]
0x00000020 <_start+0x20>: 0xc6020304  addi et, et, 2060 [dstData=0x80c dstReg=et]
0x00000024 <_start+0x24>: 0x00800034  movhi r2, 0 [dstData=0x0 dstReg=r2]
0x00000028 <_start+0x28>: 0x1080a304  addi r2, r2, 652 [dstData=0x28c dstReg=r2]
0x0000002c <_start+0x2c>: 0x1000683a  jmp r2 [targetPcb=0x28c]

Source: nosys_crt0.c


extern void __bss_start;
extern void _end;

extern int main (int, char **, char **);

void __fake_init () { /* Do nothing */ }
void _init () __attribute__ ((weak, alias ("__fake_init")));
          
 
void
__start_2 (void)
{
  _zero_bss (&__bss_start, 0, &_end - &__bss_start);

  _init ();

  exit (main (0, 0, 0));
}

Disassembly (__start_2)

00000288 <__fake_init>:
 288:    f800283a     ret

0000028c <__start_2>:
 28c:    01000034     movhi    r4,0
 290:    21020304     addi    r4,r4,2060
 294:    01800034     movhi    r6,0
 298:    31820304     addi    r6,r6,2060
 29c:    deffff04     addi    sp,sp,-4
 2a0:    310dc83a     sub    r6,r6,r4
 2a4:    000b883a     mov    r5,zero
 2a8:    dfc00015     stw    ra,0(sp)
 2ac:    00002cc0     call    2cc <_zero_bss>
 2b0:    00002880     call    288 <__fake_init>
 2b4:    0009883a     mov    r4,zero
 2b8:    000b883a     mov    r5,zero
 2bc:    000d883a     mov    r6,zero
 2c0:    00000300     call    30 <main>
 2c4:    1009883a     mov    r4,r2
 2c8:    00002d80     call    2d8 <exit>

Simulation (__start_2)

The simulation extends to the call to main.

0x00000000 <_start>:    0x06c20034  movhi sp, 2048 [dstData=0x8000000 dstReg=sp]
0x00000004 <_start+0x4>:    0xdeffc004  addi sp, sp, -256 [dstData=0x7ffff00 dstReg=sp]
0x00000008 <_start+0x8>:    0xdef6303a  nor sp, sp, sp [dstData=0xf80000ff dstReg=sp]
0x0000000c <_start+0xc>:    0xdec001d4  ori sp, sp, 7 [dstData=0xf80000ff dstReg=sp]
0x00000010 <_start+0x10>:    0xdef6303a  nor sp, sp, sp [dstData=0x7ffff00 dstReg=sp]
0x00000014 <_start+0x14>:    0x06800074  movhi gp, 1 [dstData=0x10000 dstReg=gp]
0x00000018 <_start+0x18>:    0xd6a20004  addi gp, gp, -30720 [dstData=0x8800 dstReg=gp]
0x0000001c <_start+0x1c>:    0x06000034  movhi et, 0 [dstData=0x0 dstReg=et]
0x00000020 <_start+0x20>:    0xc6020304  addi et, et, 2060 [dstData=0x80c dstReg=et]
0x00000024 <_start+0x24>:    0x00800034  movhi r2, 0 [dstData=0x0 dstReg=r2]
0x00000028 <_start+0x28>:    0x1080a304  addi r2, r2, 652 [dstData=0x28c dstReg=r2]
0x0000002c <_start+0x2c>:    0x1000683a  jmp r2 [targetPcb=0x28c]
0x0000028c <__start_2>:      0x01000034  movhi r4, 0 [dstData=0x0 dstReg=r4]
0x00000290 <__start_2+0x4>:    0x21020304  addi r4, r4, 2060 [dstData=0x80c dstReg=r4]
0x00000294 <__start_2+0x8>:    0x01800034  movhi r6, 0 [dstData=0x0 dstReg=r6]
0x00000298 <__start_2+0xc>:    0x31820304  addi r6, r6, 2060 [dstData=0x80c dstReg=r6]
0x0000029c <__start_2+0x10>:    0xdeffff04  addi sp, sp, -4 [dstData=0x7fffefc dstReg=sp]
0x000002a0 <__start_2+0x14>:    0x310dc83a  sub r6, r6, r4 [dstData=0x0 dstReg=r6]
0x000002a4 <__start_2+0x18>:    0x000b883a  mov r5, r0 [dstData=0x0 dstReg=r5]
0x000002a8 <__start_2+0x1c>:    0xdfc00015  stw ra, 0(sp) [memAddr=0x7fffefc stData=0xdeadbeef]
0x000002ac <__start_2+0x20>:    0x00002cc0  call 0x2cc <_zero_bss> [dstData=0x2b0 dstReg=ra]

Execution of _zero_bss and memset takes place here.

0x000002b0 <__start_2+0x24>:    0x00002880  call 0x288 <__fake_init> [dstData=0x2b4 dstReg=ra]
0x00000288 <__fake_init>:       0xf800283a  ret [targetPcb=0x2b4]
0x000002b4 <__start_2+0x28>:    0x0009883a  mov r4, r0 [dstData=0x0 dstReg=r4]
0x000002b8 <__start_2+0x2c>:    0x000b883a  mov r5, r0 [dstData=0x0 dstReg=r5]
0x000002bc <__start_2+0x30>:    0x000d883a  mov r6, r0 [dstData=0x0 dstReg=r6]
0x000002c0 <__start_2+0x34>:    0x00000300  call 0x30 <main> [dstData=0x2c4 dstReg=ra]

Source: _zero_bss.c

_zero_bss just calls memset. In this example, there are no bytes to set since the bss section has zero length.


#include "config.h"
#include <string.h>

void 
_zero_bss (void *base, int c, size_t count)
{
  memset (base, c, count);
}

Disassembly (_zero_bss)

000002cc <_zero_bss>:
 2cc:    02000034     movhi    r8,0
 2d0:    4200ef04     addi    r8,r8,956
 2d4:    4000683a     jmp    r8

Simulation (_zero_bss)

0x000002cc <_zero_bss>:         0x02000034  movhi r8, 0 [dstData=0x0 dstReg=r8]
0x000002d0 <_zero_bss+0x4>:     0x4200ef04  addi r8, r8, 956 [dstData=0x3bc dstReg=r8]
0x000002d4 <_zero_bss+0x8>:     0x4000683a  jmp r8 [targetPcb=0x3bc]

Source: memset.c

/*
FUNCTION
	<<memset>>---set an area of memory

INDEX
	memset

ANSI_SYNOPSIS
	#include <string.h>
	void *memset(const void *<[dst]>, int <[c]>, size_t <[length]>);

TRAD_SYNOPSIS
	#include <string.h>
	void *memset(<[dst]>, <[c]>, <[length]>)
	void *<[dst]>;
	int <[c]>;
	size_t <[length]>;

DESCRIPTION
	This function converts the argument <[c]> into an unsigned
	char and fills the first <[length]> characters of the array
	pointed to by <[dst]> to the value.

RETURNS
	<<memset>> returns the value of <[m]>.

PORTABILITY
<<memset>> is ANSI C.

    <<memset>> requires no supporting OS subroutines.

QUICKREF
	memset ansi pure
*/

#include <string.h>

#define LBLOCKSIZE (sizeof(long))
#define UNALIGNED(X)   ((long)X & (LBLOCKSIZE - 1))
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)

_PTR 
_DEFUN (memset, (m, c, n),
	_PTR m _AND
	int c _AND
	size_t n)
{
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
  char *s = (char *) m;

  while (n-- != 0)
    {
      *s++ = (char) c;
    }

  return m;
#else
  char *s = (char *) m;
  int i;
  unsigned long buffer;
  unsigned long *aligned_addr;
  unsigned int d = c & 0xff;	/* To avoid sign extension, copy C to an
				   unsigned variable.  */

  if (!TOO_SMALL (n) && !UNALIGNED (m))
    {
      /* If we get this far, we know that n is large and m is word-aligned. */
      aligned_addr = (unsigned long*)m;

      /* Store D into each char sized location in BUFFER so that
         we can set large blocks quickly.  */
      if (LBLOCKSIZE == 4)
        {
          buffer = (d << 8) | d;
          buffer |= (buffer << 16);
        }
      else
        {
          buffer = 0;
          for (i = 0; i < LBLOCKSIZE; i++)
	    buffer = (buffer << 8) | d;
        }

      while (n >= LBLOCKSIZE*4)
        {
          *aligned_addr++ = buffer;
          *aligned_addr++ = buffer;
          *aligned_addr++ = buffer;
          *aligned_addr++ = buffer;
          n -= 4*LBLOCKSIZE;
        }

      while (n >= LBLOCKSIZE)
        {
          *aligned_addr++ = buffer;
          n -= LBLOCKSIZE;
        }
      /* Pick up the remainder with a bytewise loop.  */
      s = (char*)aligned_addr;
    }

  while (n--)
    {
      *s++ = (char)d;
    }

  return m;
#endif /* not PREFER_SIZE_OVER_SPEED */
}

Disassembly (memset.c)

000003bc <memset>:
 3bc:    008000c4     movi    r2,3
 3c0:    29403fcc     andi    r5,r5,255
 3c4:    2007883a     mov    r3,r4
 3c8:    11801a2e     bgeu    r2,r6,434 <memset+0x78>
 3cc:    2084703a     and    r2,r4,r2
 3d0:    1000181e     bne    r2,zero,434 <memset+0x78>
 3d4:    2806923a     slli    r3,r5,8
 3d8:    200f883a     mov    r7,r4
 3dc:    1946b03a     or    r3,r3,r5
 3e0:    1804943a     slli    r2,r3,16
 3e4:    1886b03a     or    r3,r3,r2
 3e8:    008003c4     movi    r2,15
 3ec:    11800a2e     bgeu    r2,r6,418 <memset+0x5c>
 3f0:    38c00015     stw    r3,0(r7)
 3f4:    39c00104     addi    r7,r7,4
 3f8:    38c00015     stw    r3,0(r7)
 3fc:    39c00104     addi    r7,r7,4
 400:    38c00015     stw    r3,0(r7)
 404:    39c00104     addi    r7,r7,4
 408:    38c00015     stw    r3,0(r7)
 40c:    31bffc04     addi    r6,r6,-16
 410:    39c00104     addi    r7,r7,4
 414:    11bff636     bltu    r2,r6,3f0 <memset+0x34>
 418:    008000c4     movi    r2,3
 41c:    1180042e     bgeu    r2,r6,430 <memset+0x74>
 420:    38c00015     stw    r3,0(r7)
 424:    31bfff04     addi    r6,r6,-4
 428:    39c00104     addi    r7,r7,4
 42c:    11bffc36     bltu    r2,r6,420 <memset+0x64>
 430:    3807883a     mov    r3,r7
 434:    31bfffc4     addi    r6,r6,-1
 438:    00bfffc4     movi    r2,-1
 43c:    30800426     beq    r6,r2,450 <memset+0x94>
 440:    19400005     stb    r5,0(r3)
 444:    31bfffc4     addi    r6,r6,-1
 448:    18c00044     addi    r3,r3,1
 44c:    30bffc1e     bne    r6,r2,440 <memset+0x84>
 450:    2005883a     mov    r2,r4
 454:    f800283a     ret

Simulation (memset)

In this example, memset is copying zero bytes, so execution is brief.

0x000003bc <memset>:            0x008000c4  movi r2, 3 [dstData=0x3 dstReg=r2]
0x000003c0 <memset+0x4>:        0x29403fcc  andi r5, r5, 255 [dstData=0x0 dstReg=r5]
0x000003c4 <memset+0x8>:        0x2007883a  mov r3, r4 [dstData=0x80c dstReg=r3]
0x000003c8 <memset+0xc>:        0x11801a2e  bgeu r2, r6, 0x434 <memset+0x78> [passed]
0x00000434 <memset+0x78>:       0x31bfffc4  addi r6, r6, -1 [dstData=0xffffffff dstReg=r6]
0x00000438 <memset+0x7c>:       0x00bfffc4  movi r2, -1 [dstData=0xffffffff dstReg=r2]
0x0000043c <memset+0x80>:       0x30800426  beq r6, r2, 0x450 <memset+0x94> [passed]
0x00000450 <memset+0x94>:       0x2005883a  mov r2, r4 [dstData=0x80c dstReg=r2]
0x00000454 <memset+0x98>:       0xf800283a  ret [targetPcb=0x2b0]


Maintained by John Loomis, last updated 5 April 2007