RL78 Application Binary Interface for GCC

 

ELF Machine Number: 197

ELF32 format will be used.

ELF relocations are RELA (addend in reloc, not opcode). Relocation numbers and functions match the RX relocations at the moment, minus any Red Hat specific relocations. (add table later)

ELF Flags - TBD

·         Absence/presence of MUL/DIV

·         Other hardware variants

·         78K0 / 78K0R compatibility flags

 

Debug format - the debug format is DWARF-2. Dwarf2 frame and unwind information will be encoded, and dwarf2 exception unwinding will be used. Dwarf2 register numbers 0 through 31 are assigned according to the "virtual" values in the table below. SP is register 32. PC is register 33.

Types

Type

Size, bits

Char

8

short, int

16

long

32

long long

64

void *

16

void __far *

32

float, double

32

long double

64

Note about pointers: The RL78 has a 20-bit address space, and special "bank" registers (CS/ES) to access them, but working with a default 32-bit pointer is very expensive. The above table uses a 16-bit pointer for performance reasons. GCC supports named address spaces, and includes supporting 32-bit (er, 20-bit) pointers via the "__far" named address space as an extension.

Register Usage

The RL78 has four sets of eight 8-bit registers. These registers can be used as 16-bit registers in hardware, or 32- or 64-bit registers via software emulation.

BANK 0

BANK 1

BANK 2

BANK 3

SADDR

HW/Reg

Virtual

SADDR

HW/Reg

Virtual

SADDR

HW/Reg

Virtual

SADDR

HW/Reg

Virtual

FFEF8

X / $r0

R0

FFEF0

X / $r0

R8

FFEE8

X / $r0

R16

FFEE0

X / $r0

R24

FFEF9

A / $r1

R1

FFEF1

A / $r1

R9

FFEE9

A / $r1

R17

FFEE1

A / $r1

R25

FFEFA

C / $r2

R2

FFEF2

C / $r2

R10

FFEEA

C / $r2

R18

FFEE2

C / $r2

R26

FFEFB

B / $r3

R3

FFEF3

B / $r3

R11

FFEEB

B / $r3

R19

FFEE3

B / $r3

R27

FFEFC

E / $r4

R4

FFEF4

E / $r4

R12

FFEEC

E / $r4

R20

FFEE4

E / $r4

R28

FFEFD

D / $r5

R5

FFEF5

D / $r5

R13

FFEED

D / $r5

R21

FFEE5

D / $r5

R29

FFEFE

L / $r6

R6

FFEF6

L / $r6

R14

FFEEE

L / $r6

R22

FFEE6

L / $r6

R30

FFEFF

H / $r7

R7

FFEF7

H / $r7

R15

FFEEF

H / $r7

R23

FFEE7

H / $r7

R31

For the purposes of this spec, the registers are named R0 through R31, with R0 being $r0 in bank 0 and R31 being $r7 in bank 3. These 32 registers are referred to as "virtual registers" as the method of accessing them varies depending on the hardware's state (mostly, the register bank select bits).

The assembler does not use these alternate names; the compiler must arrange for suitable #defines or SADDR encodings to access these registers. The compiler will assume bank 0 is active at all times (i.e. functions assume bank 0 is active at the start of the function), so R0 through R7 correspond to $r0 through $r7.

Arguments to functions are always passed on the stack, with the first argument in the parameter list pushed last. Note: this is the common "args on stack" layout most compilers use. 16-bit and larger types shall be 16-bit aligned. If an 8-bit type is passed between two 16-bit types, the 8-bit type shall be padded towards the LSB (i.e. towards address zero, so it ends up on an even address too).

Return values shall be returned in R8..Rn for as many registers as are needed to store the value. That lets us store 8, 16, 32, and 64 bit values in the same place, without using up all the "real" registers (AX, BC, etc) that might be needed to compute the return value.

Structs, unions, and other aggregates of 8 bytes or less are returned in virtual registers r8-r15. Otherwise, the aggregate will returned in the struct return area allocated by the caller. A pointer to that struct return area will be passed (on the stack) as a hidden first argument.

Registers R0 through R15 (banks 0 and 1) are not preserved across function calls (i.e. functions may change them without needing to restore the old value). Bank 0 must be selected at function entry and exit. Registers R16 through R23 (bank 2) must be preserved across function calls (i.e. functions that change them must restore the old value before returning). Registers R24 through R31 (bank 3) are reserved for interrupt handlers.

 

There are currently no global registers, such as small-data-pointers or constant-pool-base.