Skip to content

Architecture

Rui Figueira edited this page Aug 19, 2022 · 3 revisions

Architecture

Register set

The instruction set is mostly orthogonal, and as such the hardware doesn't impose many rules on how registers are used.

NOTE : Despite this, in practice, when developing any piece of non-trivial code, it's necessary to agree to set of rules on how registers can be used. This allows, for example, to reuse code from other people. See ABI.

Integer registers

Name Purpose
r0 ... r11 General purpose registers
r12/ip Normally called scratch register. Some instructions and architecture features use this register specifically.
Also used in interrupt handling.
r13/sp Stack pointer.
Although the architecture doesn't explicitly require this register to be the stack pointer, some pseudo instructions do so (e.g: push,pop,fpush,fpop)
r14/lr Link register.
Holds the return address of a bl instruction (branch with linking).
Also holds the crtsk value of the interrupted context when an interrupt happens.
r15/pc Instruction pointer.
Points to the next instruction to be executed.

Floating point registers

Name Purpose
f0 ... f15 General purpose registers

Control registers

Control registers are mostly for advanced features, such as controlling user/supervisor mode, context switching, interrupt handling, etc.

Name Purpose
cr0/flags Flags register
cr1/criqmsk IRQ masking register
cr2/crtsk Current task (aka: context) physical address.
When an interrupt happens, the full interrupted context is saved to memory address [crtsk]. This allows the interrupt handler to resume the interrupted context
cr3 ... cr7 General purpose at the moment.
The OS can use these for whatever it wants.
WARNING: Some of these might be used by the architecture in the future.
cr8/crirqs IRQ pins. A bit set to 1 means that device needs servicing.
cr9 ... cr15 General purpose at the moment.
The OS can use it for whatever it wants.
WARNING: Some of these might be used by the architecture in the future.

The flags register layout

\3\3\2\2\2\2\2\2\ \2\2\2\2\1\1\1\1\ \1\1\1\1\1\1\ \ \ \ \ \ \ \ \ \ \ \ 
 \1\0\9\8\7\6\5\4\ \3\2\1\0\9\8\7\6\ \5\4\3\2\1\0\9\8\ \7\6\5\4\3\2\1\0\
  N Z C V S [      Reserved for future use              ] [Process Key]
  | | | | |
  | | | | !--- Supervisor mode
  | | | !----- Overflow
  | | !------- Carry
  | !--------- Zero
  !----------- Negative

  • Contrary to most architectures, the condition flags (N,Z,C,V) are only set by the cmp/fcmp instructions
  • When in user mode, only the condition flags can set by the user. Bits 26 to 0 can only be set while in supervisor mode

Control registers permissions

Access to write or read control registers varies, depending on the cpu mode and the register in question. Attempting to read or write a register when not allowed will generated an IllegalInstruction exception.

Supervisor
Read
Supervisor
Write
User mode
Read
User mode
Write
cr0 Y Y Y Y(1)
cr1 Y Y N N
cr2 Y Y N N
cr3 Y Y N N
cr4 Y Y N N
cr5 Y Y N N
cr6 Y Y N N
cr7 Y Y N N
- - - - -
cr8 Y N N N
cr9 Y Y N N
cr10 Y Y N N
cr11 Y Y N N
cr12 Y Y N N
cr13 Y Y N N
cr14 Y Y N N
cr15 Y Y N N

(1) Write is allowed, but anything other than the condition flags will be ignored.

Registers and context switching

To allow creation of a complex OS, multithreaded programs, or simply coroutines, the entire register set can be saved/loaded with dedicated instructions (see ctxswitch/fullctxswitch). What registers can be saved/loaded depends on if the CPU is in user or supervisor mode. For this, you can think of a context simply as a user mode context or a full context. A user mode context consists of the integer registers (r0...r15) and floating point registers (f0...f15).
A full context consists of the integer registers (r0...r15), floating point registers (f0...f15), and the cr0...cr7 control registers.

The cr8...cr15 control registers are not included in the saving/loading of a context. For example, consider the cr8 (aka crirqs) register. It represents what devices need attention. This information is not context sensitive, and therefore doesn't make sense to copy/save when context switching.

Reserved memory addresses

Some address ranges are reserved for special purposes, as follow:

Address Size Purpose
0x0 4 bytes Reset handler address. When booting, this contains the address to jump to.
0x4 128 bytes
(4*32)
IRQ vector table. This is an array of 32 words, where each entry is the address to jump to when the respective IRQ pin is set.
0x84 224 bytes Full context to load when an interrupt/exception is raised.

To better understand this, a very simple boot file would look like this:

.text
.word _startup; Reset handler
.zero 128; Interrupt vector table: 4*32
.zero 224; Interrupt context

_startup:
; … your startup code

A more complex boot file, where you specify the IRQ handlers:

.text

.word _startup; Reset handler

.word _cpuExceptionHandler; IRQ 0 - CPU
.word _genericIRQHandler ; IRQ 1
; ... handlers for IRQ 2 .. 30
.word _genericIRQHandler ; IRQ 31

.zero 224; Interrupt context

_startup:
; … your startup code

1 2 3 4 5

Clone this wiki locally