OzVM - Preliminary Description of the Machine, Opcodes, and Instructions
OzVM is a simple register-based, RISC-style processor. The machine maintains 256 general-purpose 64-bit registers, one 32-bit instruction pointer, and a 32-bit addressable memory region. The specification defines 120 operations supporting 10 data types, covering 4 sizes of integers and 2 sizes of floating-point numbers. Any register may be used for either integer or floating-point calculations.
Memory access to the valid memory is enforced - access outside that memory results in undefined behavior. The specific amount of memory available to the machine is unspecified. Currently, available memory is fixed at load-time with no support for run-time memory allocation.
Absent from the machine specification is any native support for interrupts, exceptions, or multithreading. That includes no support for ALU and FPU exceptions such as overflow, underflow, etc.
Registers | Description | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0-31 | Integer / pointer | ||||||||||||
| |||||||||||||
32-63 | Floating-point | ||||||||||||
| |||||||||||||
64-65 | Reserved for compiler | ||||||||||||
66-255 | Unused |
Each opcode is a 32-bit field describing the operation and the registers, possibly followed by a 32-bit immediate value.
Mandatory | Contingent | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
There are ten fundamental types. Each instruction supports some subset of these types.
Type | Description | ILP32 C-type |
---|---|---|
I1 | 8-bit signed integer | char |
I2 | 16-bit signed integer | short |
I4 | 32-bit signed integer | int |
I8 | 64-bit signed integer | long long |
F4 | 32-bit floating-point | float |
F8 | 64-bit floating-point | double |
U1 | 8-bit unsigned integer | unsigned char |
U2 | 16-bit unsigned integer | unsigned short |
U4 | 32-bit unsigned integer | unsigned int |
U8 | 64-bit unsigned integer | unsigned long long |
There are 120 unique opcodes, one for each type of instruction. Note, the copy to register instructions (C_R_...) on 8-bit and 16-bit types (I1, I2, U1, U2) always write a full 32-bits to the destination register, zero- or sign-extended as appropriate.
Instruction | Types | Operation | Description |
---|---|---|---|
Nop | n/a | none | No operation |
C_R_R | I1, I2, U1, U2, U4, U8 | REG(r1) = REG(r2) | Copy to register from register |
C_R_I | I1, I2, U1, U2, U4 | REG(r1) = imm | Copy to register from immediate |
C_R_MRI | I1, I2, U1, U2, U4, U8 | REG(r1) = MEM( REG(r2) + imm ) | Copy to register from memory at register+immediate |
C_R_MRR | I1, I2, U1, U2, U4, U8 | REG(r1) = MEM( REG(r2) + REG(r3) ) | Copy to register from memory at register+register |
C_MRI_R | U1, U2, U4, U8 | MEM( REG(r1) + imm ) = REG(r2) | Copy to memory at register+immediate from register |
C_MRR_R | U1, U2, U4, U8 | MEM( REG(r1) + REG(r2) ) = REG(r3) | Copy to memory at register+register from register |
Cvt_F4 | F8, I4, I8, U4, U8 | (F4)REG(r1) = (type)REG(r2) | Convert to F4 from (type) |
Cvt_F8 | F4, I4, I8, U4, U8 | (F8)REG(r1) = (type)REG(r2) | Convert to F8 from (type) |
Cvt_U4 | F4, F8, U8 | (U4)REG(r1) = (type)REG(r2) | Convert to U4 from (type) |
Cvt_U8 | F4, F8, I4, U4 | (U8)REG(r1) = (type)REG(r2) | Convert to U8 from (type) |
Add | F4, F8, U4, U8 | REG(r1) = REG(r2) + REG(r3) | Add |
Sub | F4, F8, U4, U8 | REG(r1) = REG(r2) - REG(r3) | Subtract |
Mul | F4, F8, I4, I8, U4, U8 | REG(r1) = REG(r2) * REG(r3) | Multiply |
Div | F4, F8, I4, I8, U4, U8 | REG(r1) = REG(r2) / REG(r3) | Divide |
Mod | I4, I8, U4, U8 | REG(r1) = REG(r2) % REG(r3) | Modulo |
Neg | F4, F8, I4, I8 | REG(r1) = - REG(r2) | Negate |
And | U4, U8 | REG(r1) = REG(r2) & REG(r3) | Binary and |
Or | U4, U8 | REG(r1) = REG(r2) | REG(r3) | Binary or |
Xor | U4, U8 | REG(r1) = REG(r2) ^ REG(r3) | Binary exclusive-or |
Com | U4, U8 | REG(r1) = ~ REG(r2) | Binary compliment |
Lsh | U4, U8 | REG(r1) = REG(r2) << REG(r3) | Left-shift variable number of bits |
Rsh | I4, I8, U4, U8 | REG(r1) = REG(r2) >> REG(r3) | Right-shift variable number of bits |
Lsh_C | U4, U8 | REG(r1) = REG(r2) << r3 | Left-shift constant number of bits |
Rsh_C | I4, I8, U4, U8 | REG(r1) = REG(r2) >> r3 | Right-shift constant number of bits |
Jump | U4 | IP = imm if r1 == 0 IP = REG(r1) otherwise |
Load instruction pointer with new value |
Link | U4 | REG(r2) = address of next instruction, then execute Jump |
Copy instruction pointer of next instruction, then jump |
Beq | F4, F8, U4, U8 | if REG(r2) == REG(r3) then IP += imm | Branch if equal |
Bne | F4, F8, U4, U8 | if REG(r2) != REG(r3) then IP += imm | Branch if not-equal |
Ble | F4, F8, I4, I8, U4, U8 | if REG(r2) <= REG(r3) then IP += imm | Branch if less-than or equal |
Blt | F4, F8, I4, I8, U4, U8 | if REG(r2) < REG(r3) then IP += imm | Branch if less-than |
Trap | U4 | call system function REG(r1) argument in REG(r2) |
Trap, call system function |
$Revision: 1.1.1.1 $ $Date: 2001/09/18 10:45:25 $