OpenCores

Application binary interface

From OR2K

Back to Contents Page.

Contents

Data Representation

Back to Contents Page.

Fundamental Types

Scalar types in the ISO/ANSI C language are based on memory operands definitions from Addressing modes and operand conventions. Similar relations between architecture and language types can be used for any other language.

Type C Type Sizeof Alignment (bytes) OpenRISC 2000 equivalent
Integral char

signed char

1 1 signed byte
unsigned char 1 1 unsigned byte
short int

signed short int

2 2 signed halfword
unsigned short int 2 2 unsigned halfword
int

signed int
long int
signed long int
enum

4 4 signed singleword
unsigned int

unsigned long int

4 4 unsigned singleword
long long int

signed long long int

8 8 signed doubleword
unsigned long long int 8 8 unsigned doubleword
Pointer anytype *

anytype (*) ()

4 4 unsigned singleword
Floating-point float 4 4 single precision float
double

long double

8 8 double precision float

A null pointer of any type must be zero. All floating-point types are IEEE 754-2008 compliant.

The OpenRISC 2000 programming model introduces a set of fundamental vector data types, as described in the following table. For vector assignments both side of assignment must be of the same vector type.

Vector type Sizeof Alignment (bytes) OpenRISC 2000 equivalent
vector char

vector signed char

8 8 vector of signed bytes
vector unsigned char 8 8 vector of unsigned bytes
vector short int

vector signed short int

8 8 vector of signed halfwords
vector unsigned short int 8 8 vector of unsigned halfwords
vector int

vector signed int
vector long int
vector signed long int

8 8 vector of signed singlewords
vector unsigned int

vector unsigned long int

8 8 vector of unsigned singlewords
vector float 8 8 vector of single-precisions

For alignment restrictions of all types see Addressing modes and operand conventions.

Aggregates and Unions

Aggregates (structures and arrays) and unions assume the alignment of their most strictly aligned element.

  • An array uses the alignment of its elements.
  • Structures and unions can require padding to meet alignment restrictions. Each element is assigned to the lowest aligned address.
Simple C structure showing no padding


Complex C structure showing no padding


C structure showing padding between char, double and short

Bit-fields

C structure and union definitions can have elements defined by a specified number of bits. The following table describes valid bit-field types and their ranges.


Bit-field Type Width w [bits] Range
signed char 1 to 8 -27 to 27-1
char 0 to 28-1
unsigned char 0 to 28-1
signed short int 1 to 16 -215 to 25-1
short int 0 to 216-1
unsigned short int 0 to 216-1
signed int 1 to 32 -231 to 231-1
int 0 to 232-1
enum 0 to 232-1
unsigned int 0 to 232-1
signed long int -231 to 231-1
long int 0 to 232-1
unsigned long int 0 to 232-1

Bit-fields follow the same alignment rules as aggregates and unions, with the following additions:

  • Bit-fields are allocated from most to least significant (from left to right)
  • A bit-field must entirely reside in a storage unit appropriate for its declared type.
  • Bit-fields may share a storage unit with other struct/union elements, including elements that are not bit-fields. Struct elements occupy different parts of the storage unit.
  • Unnamed bit-fields’ types do not affect the alignment of a structure or union
C structure showing padding between bit fields of various sizes

Function Calling Sequence

Back to Contents Page.

This section describes the standard function calling sequence, including stack frame layout, register usage, parameter passing, and so on. The standard calling sequence requirements apply only to global functions, however it is recommended that all functions use the standard calling sequence.

Register Usage

The OpenRISC 2000 architecture defines 32 general-purpose registers. These registers are 32 bits wide in 32-bit implementations and 64 bits wide in 64-bit implementations.

Register Preserved across function calls Usage
r31 No Temporary register
r30 Yes Callee-saved register
r29 No Temporary register
r28 Yes Callee-saved register
r27 No Temporary register
r26 Yes Callee-saved register
r25 No Temporary register
r24 Yes Callee-saved register
r23 No Temporary register
r22 Yes Callee-saved register
r21 No Temporary register
r20 Yes Callee-saved register
r19 No Temporary register
r18 Yes Callee-saved register
r17 No Temporary register
r16 Yes Callee-saved register
r15 No Temporary register
r14 Yes Callee-saved register
r13 No Temporary register
r12 No RVH - Return value high 32 bits of 64-bit result (32-bit system)

Temporary reigster (64-bit system)

r11 No RV – Return value
r10 Yes Callee-saved register
r9 Yes LR – Link address register
r8 No Function parameter number 5
r7 No Function parameter number 4
r6 No Function parameter number 3
r5 No Function parameter number 2
r4 No Function parameter number 1
r3 No Function parameter number 0
r2 Yes FP - Frame pointer
r1 Yes SP - Stack pointer
r0 Fixed to zero

Some registers have assigned roles, and associated alternative names.

r0 Always fixed to zero. Even if it is writable in some embedded implementations, the software shouldn’t modify it.
r1 (sp) The stack pointer holds the limit of the current stack frame. The stack contents below the stack pointer are undefined. Stack pointer must be double word aligned at all times.
r2 (fp) The frame pointer holds the address of the previous stack frame. Incoming function parameters reside in the previous stack frame and can be accessed at positive offsets from fp.
r3 - r8 General-purpose parameters use up to 6 general-purpose registers. Parameters beyond the sixth parameter appear on the stack.
r9 (lr) Link address is the location of the function call instruction and is used to calculate where program execution should return after function completion.
r11 (rv) Return value of the function. For void functions a value is not defined. For functions returning a union or structure, a pointer to the result is placed into return value register.
r12 (rvh) Return value high of the function. For functions returning 32-bit values, or for 64-bit implementations, this register can be considered temporary register.

Furthermore, an OpenRISC 2000 implementation might have several sets of shadowed general-purpose registers. These shadowed registers are used for fast context switching and sets can be switched only by the operating system.

The Stack Frame

In addition to registers, each function has a frame on the run-time stack. This stack grows downward from high addresses. The following table shows the stack frame organization. Stack space is only needed to pass parameters that cannot fit in the argument registers (r3-r8).

Position Contents Frame
fp + 4n


fp + 0

Stack based parameter m (in total needing n words)


Stack based parameter 0

Previous
fp – 4


fp – 4p

Function variables (requiring p words of space Current
sp + 4 Previous frame pointer value (optional)
sp + 0 Return address (optional)
sp – 4


sp – 2096

For use by leaf functions without function prologue/epilogue Next
sp – 2100


sp – 2536

For use by exception handlers

The stack pointer always points to the end of the latest allocated stack frame. All frames must be double word aligned. In code compiled for 32-bit implementations, upper halves of all double words are zero.

The first 2092 bytes below the current stack frame are reserved for leaf functions that do not need to modify their stack pointer. Exception handlers must guarantee that they will not use this area.

Parameter Passing

Functions receive their first 6 arguments in general-purpose parameter registers. If there are more than six arguments, the remaining arguments are passed on the stack. Structure and union arguments are passed as pointers.

All 64-bit arguments in a 32-bit system are passed using a pair of registers, with the most significant 32 bits in the lower numbered register. Note. 64-bit arguments are not aligned. For example long long int arg1, long int arg2 and long long int arg3 would be passed in the following way: arg1 in r3 and r4, arg2 in r5, and arg3 in r6 and r7.

Functions Returning Scalars or No Value

A function that returns an integral, pointer or vector/floating-point value places its result in the general-purpose rv register. Void functions put no particular value in rv register. Functions returning a 64-bit scalar value on 32-bit implementations should return the high order 32 bits in the rvh register.

Note. When returning a 64-bit value, the most significant 32 bits are in the higher numbered register (rvh=r12), which is the reverse of argument passing.

Functions Returning Structures or Unions

The location for a structure or union result is passed as a hidden first argument to the function in r3. The function will then populate that location, rather than using the rv register.

Operating System Interface

Back to Contents Page.

Exception Interface

The OpenRISC 2000 exception mechanism allows the processor to change to supervisor mode as a result of external signals, errors or execution of certain instructions. When an exception occurs the following events happen:

  • The address of the interrupted instruction and the machine state are saved
  • The machine mode is changed to supervisor mode
  • The execution resumes from a predefined exception vector address which is different for every exception


Exception type Vector offset POSIX signal Example
Reset 0x100 Reset
Bus Error 0x200 SIGBUS Unexisting physical location, bus parity error.
Data Page Fault 0x300 SIGSEGV Unammaped data location or protection violation.
Instruction Page Fault 0x400 SIGSEGV Unmapped instruction location or protection violation
Tick Timer Interrupt 0x500 Process scheduling
Alignment 0x600 SIGBUS Unaligned data access
Illegal Instruction 0x700 SIGILL Illegal/unimplemented instruction
External Interrupt 0x800 Device has asserted an interrupt
D-TLB Miss 0x900 DTLB software reload needed
I-TLB Miss 0xa00 ITLB software reload needed
Range 0xb00 SIGSEGV Arithmetic overflow
System Call 0xc00 Instruction l.sys
Floating Point Exception 0xc00 SIGFPE Floating point underflow
Trap 0xe00 SIGTRAP Instruction l.trap or debug unit exception.

The operating system handles an exception either by completing the faulting exception in a manner transparent to the application, if possible, or by delivering a signal to the application. The preceding table shows how hardware exceptions can be mapped to POSIX signals if the operating system cannot complete the faulting exception.

Virtual Address Space

For user programs to execute in virtual address space, the memory management unit (MMU) must be enabled. The MMU translates virtual address generated by the running process into physical address. This allows the process to run anywhere in the physical memory and additionally page to a secondary storage.

Processes typically begin with three logical segments, commonly referred as “text”, “data” and “stack”. Additional segments may exist or can be created by the operating system.

Page Size

Memory is organized into pages, which are the system’s smallest units of memory allocation. The basic page size is 8KB with some implementations supporting 16MB and 32GB pages.

Virtual Address Assignments

Processes have full access to the entire virtual address space. However the size of a process can be limited by several factors such as a process size limit parameter, available physical memory and secondary storage.

OpenRISC 2000 virtual memory map (32-bit system)

Page at location 0x0 is usually reserved to catch dereferences of NULL pointers.

Usually the start addresses of “.text”, “.data” and “.bss” segments are defined when linking the executable file. The heap is adjusted with functions such as malloc and free. The dynamic segment area is adjusted with mmap, and the stack size is limited with setrlimit. The detailed functionality available depends on the specific system library implementation.

Stack

Every process has its own stack that is not tied to a fixed area in its address space. Since the stack can change differently for each call of a process, a process should use the stack pointer in general-purpose register r1 to access stack data.

Processor Execution Modes

The OpenRISC 2000 provides two execution modes: user and supervisor. Processes run in user mode and the operating system’s kernel runs (at least partly) in supervisor mode. A user process must execute the l.sys or l.trap instruction to switch to supervisor mode, the former being used to request service from the operating system.

System calls use the same software calling convention model as function calls, except additional register rv (r11) specifies the system call id.

Position independent code

Back to Contents Page.

Position independent code is only supported through the compiler. It is intended for use in shared libraries. For such code all accesses to constant addresses are through a global offset table (GOT). The dynamic loader resolves the GOT entries when the program starts.

This functionality is optional, and depends on compiler and library support.

ELF

Back to Contents Page.

The OpenRISC 2000 tools use the ELF object file formats and DWARF 2 debugging information formats, as described in System V Application Binary Interface, from the Santa Cruz Operation, Inc (SCO). ELF and DWARF 2 provide a suitable basis for representing the information needed for embedded applications.

No other object file formats (for example COFF) are available. The compiler may optionally also support STABS debugging format. This section describes particular fields in the ELF and DWARF 2 formats that differ from the base standards for those formats.

Header Convention

The e_machine member of the ELF header contains the decimal value 33906 (hexadecimal 0x8472) that is defined as the name EM_OR2K.

Note. At the time of writing, SCO does not appear to have the ability to issue new e_machine values. The value shown is that for the OpenRISC 1000 (EM_OR32). A new value will be needed for the OpenRISC 2000.

The e_ident member of the ELF header contains values as shown in the following table.

e_ident[EI_CLASS] ELFCLASS32 For all 32-bit implementations
e_ident[EI_DATA] ELFDATA2MSB For all implementations

The e_flags member of the ELF header contains values as shown in the following table.

HAS_RELOC 0x01 Contains relocation entries
EXEC_P 0x02 Is directly executable
HAS_LINENO 0x04 Has line number information
HAS_DEBUG 0x08 Has debugging information
HAS_SYMS 0x10 Has symbols
HAS_LOCALS 0x20 Has local symbols
DYNAMIC 0x40 Is dynamic object
WP_TEXT 0x80 Text section is write protected
D_PAGED 0x100 Is dynamically paged

Sections

There are no OpenRISC 2000 section requirements beyond the base ELF standards.

Relocation

This section describes values and algorithms used for relocations. In particular, it describes values the compiler/assembler must leave in place and how the linker modifies those values.

Name Value Size Calculation
R_OR32_NONE 0 0 None
R_OR32_32 1 32 A
R_OR32_16 2 16 A & 0xffff
R_OR32_8 3 8 A & 0xff
R_OR32_CONST 4 16 A & 0xffff
R_OR32_CONSTH 5 16 (A >> 16) & 0xffff
R_OR32_JUMPTARG 6 28 (S + A - P) >> 2

Key S indicates the final value assigned to the symbol referenced in the relocation record. Key A is the added value specified in the relocation record. Key P indicates the address of the relocation (e.g., the address being modified).

© copyright 1999-2012 OpenCores.org, equivalent to ORSoC AB, all rights reserved. OpenCores®, registered trademark.