Add interrupts draft to spec
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
115
vm.md
115
vm.md
@@ -25,8 +25,17 @@ CPU registers are addressed by a value between 0-63 (6 bits). All registers are
|
||||
* FLAGS - CPU flags
|
||||
* STATUS - Generic status code
|
||||
* NIL - Always zero for reading and will never change after writing.
|
||||
* IVT - Interrupt vector table pointer
|
||||
* R0-R31
|
||||
* (26 unused registers)
|
||||
* (25 reserved registers)
|
||||
|
||||
The following registers are caller-save (i.e., their value may change after a function call):
|
||||
|
||||
* FLAGS
|
||||
* STATUS
|
||||
* IVT
|
||||
|
||||
The rest are callee-save.
|
||||
|
||||
## CPU Flags
|
||||
|
||||
@@ -190,6 +199,7 @@ wrapping around to 0.
|
||||
* Push the current stack frame pointer
|
||||
* Push the IP of the next instruction
|
||||
* Update the IP (i.e., jump) to the value at the given source.
|
||||
* Update the frame pointer to the current stack pointer - 16
|
||||
* Ret
|
||||
* Opcode: 0x2001
|
||||
* When this instruction is executed, these actions occur:
|
||||
@@ -209,6 +219,31 @@ wrapping around to 0.
|
||||
* When this instruction is executed, these actions occur:
|
||||
* Decrement the stack pointer by the size of value at the destination.
|
||||
* Copy the value at the stack pointer into the destination.
|
||||
* Int
|
||||
* Opcode: 0x2004
|
||||
* Params: Source, Source
|
||||
* When this instruction is executed, these actions occur:
|
||||
* Push the current stack frame pointer
|
||||
* Push the IP of the next instruction to be called
|
||||
* Push the FLAGS register
|
||||
* Push the STATUS register
|
||||
* Push the R0 register
|
||||
* Push the R1 register
|
||||
* Update the IP (i.e., jump) to the address of the given interrupt vector in the IVT
|
||||
* Update the R0 register to the value in the first parameter
|
||||
* Update the R1 register to the value in the second parameter
|
||||
* Update the frame pointer to the current stack pointer - 48
|
||||
* IRet
|
||||
* Opcode: 0x2005
|
||||
* When this instruction is executed, these actions occur:
|
||||
* Update the stack pointer to the current frame pointer + 48
|
||||
* Pop the old R1 value
|
||||
* Pop the old R0 value
|
||||
* Pop the old STATUS value
|
||||
* Pop the old FLAGS value
|
||||
* Pop the IP of the next instruction
|
||||
* Pop the old stack frame
|
||||
* Restore the last 6 values in an undefined order
|
||||
|
||||
## Data movement
|
||||
|
||||
@@ -225,6 +260,84 @@ wrapping around to 0.
|
||||
* Dump
|
||||
* Opcode: 0xF002
|
||||
|
||||
# Interrupts
|
||||
|
||||
Interrupts are signaled explicitly from software or from hardware signaling the CPU. When an
|
||||
interrupt signal is set, the CPU will finish whatever instruction it is executing, and then begin
|
||||
handling the interrupt whose signal was set. Software interrupts may be invoked using the `int`
|
||||
instruction, supplying the index of the interrupt to invoke. Hardware interrupts are invoked
|
||||
directly by a hardware event, e.g. a keypress. Hardware and software interrupts are treated equally
|
||||
in the CPU, and as such, they are all maskable.
|
||||
|
||||
## Interrupt vector table
|
||||
|
||||
Interrupts are defined by the IVT register. The address stored in the IVT register must be a
|
||||
multiple of 64. The IVT always has 512 entries, with 8 bytes for each entry. Thus, the entire table
|
||||
is 512 * 8 = 4096 bytes, or one page.
|
||||
|
||||
## Interrupt table entries
|
||||
|
||||
Interrupt table entries make up the interrupt vector table, each entry being 64 bits (8 bytes) long.
|
||||
|
||||
* 1 bit - Enabled
|
||||
* 4 bits - Reserved, set to 0
|
||||
* 59 bits - Interrupt address, multiplied by 64 for the start address
|
||||
|
||||
## Interrupt handling
|
||||
|
||||
After an interrupt is signaled, the CPU looks up the index of the interrupt in the IVT, calculates
|
||||
its address, sets up the stack for the interrupt handler, and jumps to the interrupt handler's
|
||||
address.
|
||||
|
||||
The interrupt stack is structured similarly to a normal call stack, but since interrupts may be
|
||||
invoked at any time, it saves additional state. Interrupt handlers have two explicit arguments: the
|
||||
interrupt index itself, and an auxiliary 64-bit value or pointer specific to that interrupt. The
|
||||
index is stored in the R0 register, and the auxiliary value is stored in the R1 register. These
|
||||
registers, along with the FP, IP, FLAGS, and STATUS registers are saved on the stack before calling
|
||||
an interrupt handler.
|
||||
|
||||
Before an interrupt handler is called, these actions occur:
|
||||
|
||||
* Push the current stack frame pointer
|
||||
* Push the IP of the next instruction to be called
|
||||
* Push the FLAGS register
|
||||
* Push the STATUS register
|
||||
* Push the R0 register
|
||||
* Push the R1 register
|
||||
|
||||
Interrupt handlers must be exited using the `iret` instruction.
|
||||
|
||||
## Exceptions
|
||||
|
||||
The first 256 interrupt vectors are reserved for CPU and hardware-sourced events - these are known
|
||||
as exceptions. Exceptions may occur for a number of reasons:
|
||||
|
||||
* Illegal operation attempted, e.g. divide by zero or accessing protected memory
|
||||
* Illegal operation attempted while handling an interrupt (double fault)
|
||||
* A hardware event occurred, e.g. a timer tick
|
||||
|
||||
The following list defines all exceptions that the CPU may invoke. All other vectors in 0-255 not
|
||||
defined in this table are reserved and may be used in the future.
|
||||
|
||||
* Divide by zero
|
||||
* Interrupt vector: 0
|
||||
* Auxiliary: N/A
|
||||
* Invoked upon a divide-by-zero
|
||||
* Invalid opcode
|
||||
* Interrupt vector: 1
|
||||
* Auxiliary: N/A
|
||||
* Attempted to invoke an illegal opcode
|
||||
* Illegal memory address
|
||||
* Interrupt vector: 2
|
||||
* Auxiliary: Memory address causing the interrupt
|
||||
* Attempted to access a memory address in an illegal way - either it's out of bounds or is
|
||||
protected in some way.
|
||||
* Hardware event
|
||||
* Interrupt vector: 3
|
||||
* Auxiliary: Pointer to the hardware event structure.
|
||||
* A hardware device has an event that needs attention.
|
||||
* Interrupt vector 4-255: Reserved for future use
|
||||
|
||||
# Binary object format
|
||||
|
||||
The binary object format is composed of a header followed by sections that make up the content of
|
||||
|
||||
Reference in New Issue
Block a user