Merge pull request 'Added UN instruction and fixed UB' (#7) from fix-ub into master

Reviewed-on: https://git.ablecorp.us/AbleOS/holey-bytes/pulls/7
This commit is contained in:
Erin 2023-07-13 09:13:34 +00:00
commit a21f68ffa6
7 changed files with 164 additions and 131 deletions

33
Cargo.lock generated
View file

@ -165,12 +165,9 @@ dependencies = [
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.17" version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "logos" name = "logos"
@ -192,7 +189,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"regex-syntax", "regex-syntax",
"syn 2.0.18", "syn 2.0.25",
] ]
[[package]] [[package]]
@ -206,30 +203,30 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.17.1" version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]] [[package]]
name = "paste" name = "paste"
version = "1.0.12" version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" checksum = "b4b27ab7be369122c218afc2079489cdcb4b517c0a3fc386ff11e1fedfcc2b35"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.59" version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.28" version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -274,9 +271,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.18" version = "2.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -285,9 +282,9 @@ dependencies = [
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.9" version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"

View file

@ -27,7 +27,7 @@ macros::impl_both!(
bd(p0: R, p1: I) bd(p0: R, p1: I)
=> [LI], => [LI],
n() n()
=> [NOP, ECALL], => [UN, NOP, ECALL],
); );
impl Assembler { impl Assembler {
@ -36,6 +36,11 @@ impl Assembler {
pub fn i_brc(&mut self, p0: u8, p1: u8, p2: u8) { pub fn i_brc(&mut self, p0: u8, p1: u8, p2: u8) {
self.i_param_bbb(hbbytecode::opcode::BRC, p0, p1, p2) self.i_param_bbb(hbbytecode::opcode::BRC, p0, p1, p2)
} }
/// Append 12 zeroes (UN) at the end
pub fn finalise(&mut self) {
self.buf.extend([0; 12]);
}
} }
pub trait Imm { pub trait Imm {

View file

@ -48,6 +48,7 @@ fn main() -> Result<(), Box<dyn Error>> {
.eprint(("engine_internal", Source::from(&code))) .eprint(("engine_internal", Source::from(&code)))
.unwrap(); .unwrap();
} else { } else {
assembler.finalise();
std::io::stdout().lock().write_all(&assembler.buf).unwrap(); std::io::stdout().lock().write_all(&assembler.buf).unwrap();
} }

View file

@ -18,62 +18,63 @@ macro_rules! constmod {
constmod!(pub opcode(u8) { constmod!(pub opcode(u8) {
//! Opcode constant module //! Opcode constant module
NOP = 0, "N; Do nothing"; UN = 0, "N; Raises a trap";
NOP = 1, "N; Do nothing";
ADD = 2, "BBB; #0 ← #1 + #2";
SUB = 3, "BBB; #0 ← #1 - #2";
MUL = 4, "BBB; #0 ← #1 × #2";
AND = 5, "BBB; #0 ← #1 & #2";
OR = 6, "BBB; #0 ← #1 | #2";
XOR = 7, "BBB; #0 ← #1 ^ #2";
SL = 8, "BBB; #0 ← #1 « #2";
SR = 9, "BBB; #0 ← #1 » #2";
SRS = 10, "BBB; #0 ← #1 » #2 (signed)";
CMP = 11, "BBB; #0 ← #1 <=> #2";
CMPU = 12, "BBB; #0 ← #1 <=> #2 (unsigned)";
DIR = 13, "BBBB; #0 ← #2 / #3, #1 ← #2 % #3";
NEG = 14, "BB; #0 ← -#1";
NOT = 15, "BB; #0 ← !#1";
ADD = 1, "BBB; #0 ← #1 + #2"; ADDI = 16, "BBD; #0 ← #1 + imm #2";
SUB = 2, "BBB; #0 ← #1 - #2"; MULI = 17, "BBD; #0 ← #1 × imm #2";
MUL = 3, "BBB; #0 ← #1 × #2"; ANDI = 18, "BBD; #0 ← #1 & imm #2";
AND = 4, "BBB; #0 ← #1 & #2"; ORI = 19, "BBD; #0 ← #1 | imm #2";
OR = 5, "BBB; #0 ← #1 | #2"; XORI = 20, "BBD; #0 ← #1 ^ imm #2";
XOR = 6, "BBB; #0 ← #1 ^ #2"; SLI = 21, "BBD; #0 ← #1 « imm #2";
SL = 7, "BBB; #0 ← #1 « #2"; SRI = 22, "BBD; #0 ← #1 » imm #2";
SR = 8, "BBB; #0 ← #1 » #2"; SRSI = 23, "BBD; #0 ← #1 » imm #2 (signed)";
SRS = 9, "BBB; #0 ← #1 » #2 (signed)"; CMPI = 24, "BBD; #0 ← #1 <=> imm #2";
CMP = 10, "BBB; #0 ← #1 <=> #2"; CMPUI = 25, "BBD; #0 ← #1 <=> imm #2 (unsigned)";
CMPU = 11, "BBB; #0 ← #1 <=> #2 (unsigned)";
DIR = 12, "BBBB; #0 ← #2 / #3, #1 ← #2 % #3";
NEG = 13, "BB; #0 ← -#1";
NOT = 14, "BB; #0 ← !#1";
ADDI = 15, "BBD; #0 ← #1 + imm #2"; CP = 26, "BB; Copy #0 ← #1";
MULI = 16, "BBD; #0 ← #1 × imm #2"; SWA = 27, "BB; Swap #0 and #1";
ANDI = 17, "BBD; #0 ← #1 & imm #2"; LI = 28, "BD; #0 ← imm #1";
ORI = 18, "BBD; #0 ← #1 | imm #2"; LD = 29, "BBDB; #0 ← [#1 + imm #3], imm #4 bytes, overflowing";
XORI = 19, "BBD; #0 ← #1 ^ imm #2"; ST = 30, "BBDB; [#1 + imm #3] ← #0, imm #4 bytes, overflowing";
SLI = 20, "BBD; #0 ← #1 « imm #2"; BMC = 31, "BBD; [#0] ← [#1], imm #2 bytes";
SRI = 21, "BBD; #0 ← #1 » imm #2"; BRC = 32, "BBB; #0 ← #1, imm #2 registers";
SRSI = 22, "BBD; #0 ← #1 » imm #2 (signed)";
CMPI = 23, "BBD; #0 ← #1 <=> imm #2";
CMPUI = 24, "BBD; #0 ← #1 <=> imm #2 (unsigned)";
CP = 25, "BB; Copy #0 ← #1"; JAL = 33, "BD; Copy PC to #0 and unconditional jump [#1 + imm #2]";
SWA = 26, "BB; Swap #0 and #1"; JEQ = 34, "BBD; if #0 = #1 → jump imm #2";
LI = 27, "BD; #0 ← imm #1"; JNE = 35, "BBD; if #0 ≠ #1 → jump imm #2";
LD = 28, "BBDB; #0 ← [#1 + imm #3], imm #4 bytes, overflowing"; JLT = 36, "BBD; if #0 < #1 → jump imm #2";
ST = 29, "BBDB; [#1 + imm #3] ← #0, imm #4 bytes, overflowing"; JGT = 37, "BBD; if #0 > #1 → jump imm #2";
BMC = 30, "BBD; [#0] ← [#1], imm #2 bytes"; JLTU = 38, "BBD; if #0 < #1 → jump imm #2 (unsigned)";
BRC = 31, "BBB; #0 ← #1, imm #2 registers"; JGTU = 39, "BBD; if #0 > #1 → jump imm #2 (unsigned)";
ECALL = 40, "N; Issue system call";
JAL = 32, "BD; Copy PC to #0 and unconditional jump [#1 + imm #2]"; ADDF = 41, "BBB; #0 ← #1 +. #2";
JEQ = 33, "BBD; if #0 = #1 → jump imm #2"; SUBF = 42, "BBB; #0 ← #1 -. #2";
JNE = 34, "BBD; if #0 ≠ #1 → jump imm #2"; MULF = 43, "BBB; #0 ← #1 +. #2";
JLT = 35, "BBD; if #0 < #1 → jump imm #2"; DIRF = 44, "BBBB; #0 ← #2 / #3, #1 ← #2 % #3";
JGT = 36, "BBD; if #0 > #1 → jump imm #2"; FMAF = 45, "BBBB; #0 ← (#1 * #2) + #3";
JLTU = 37, "BBD; if #0 < #1 → jump imm #2 (unsigned)"; NEGF = 46, "BB; #0 ← -#1";
JGTU = 38, "BBD; if #0 > #1 → jump imm #2 (unsigned)"; ITF = 47, "BB; #0 ← #1 as float";
ECALL = 39, "N; Issue system call"; FTI = 48, "BB; #0 ← #1 as int";
ADDF = 40, "BBB; #0 ← #1 +. #2"; ADDFI = 49, "BBD; #0 ← #1 +. imm #2";
SUBF = 41, "BBB; #0 ← #1 -. #2"; MULFI = 50, "BBD; #0 ← #1 *. imm #2";
MULF = 42, "BBB; #0 ← #1 +. #2";
DIRF = 43, "BBBB; #0 ← #2 / #3, #1 ← #2 % #3";
FMAF = 44, "BBBB; #0 ← (#1 * #2) + #3";
NEGF = 45, "BB; #0 ← -#1";
ITF = 46, "BB; #0 ← #1 as float";
FTI = 47, "BB; #0 ← #1 as int";
ADDFI = 48, "BBD; #0 ← #1 +. imm #2";
MULFI = 49, "BBD; #0 ← #1 *. imm #2";
}); });
#[repr(packed)] #[repr(packed)]

View file

@ -9,6 +9,8 @@ pub enum ErrorKind {
Unimplemented, Unimplemented,
/// Attempted to copy over register boundary /// Attempted to copy over register boundary
RegisterArrayOverflow, RegisterArrayOverflow,
/// Program is not validly terminated
InvalidEnd,
} }
/// Error /// Error
@ -25,6 +27,22 @@ pub struct Error {
pub fn validate(mut program: &[u8]) -> Result<(), Error> { pub fn validate(mut program: &[u8]) -> Result<(), Error> {
use hbbytecode::opcode::*; use hbbytecode::opcode::*;
if program.len() < 12 {
return Err(Error {
kind: ErrorKind::InvalidEnd,
index: 0,
});
}
for (index, item) in program.iter().enumerate().skip(program.len() - 12) {
if *item != 0 {
return Err(Error {
kind: ErrorKind::InvalidEnd,
index,
});
}
}
let start = program; let start = program;
loop { loop {
// Match on instruction types and perform necessary checks // Match on instruction types and perform necessary checks
@ -46,7 +64,7 @@ pub fn validate(mut program: &[u8]) -> Result<(), Error> {
index: (program.as_ptr() as usize) - (start.as_ptr() as usize), index: (program.as_ptr() as usize) - (start.as_ptr() as usize),
}) })
} }
[NOP | ECALL, rest @ ..] [UN | NOP | ECALL, rest @ ..]
| [DIR | DIRF, _, _, _, _, rest @ ..] | [DIR | DIRF, _, _, _, _, rest @ ..]
| [ADD..=CMPU | BRC | ADDF..=MULF, _, _, _, rest @ ..] | [ADD..=CMPU | BRC | ADDF..=MULF, _, _, _, rest @ ..]
| [NEG..=NOT | CP..=SWA | NEGF..=FTI, _, _, rest @ ..] | [NEG..=NOT | CP..=SWA | NEGF..=FTI, _, _, rest @ ..]

View file

@ -6,10 +6,6 @@
// - Validation has to assure there is 256 registers (r0 - r255) // - Validation has to assure there is 256 registers (r0 - r255)
// - Instructions have to be valid as specified (values and sizes) // - Instructions have to be valid as specified (values and sizes)
// - Mapped pages should be at least 4 KiB // - Mapped pages should be at least 4 KiB
// - Yes, I am aware of the UB when jumping in-mid of instruction where
// the read byte corresponds to an instruction whose lenght exceets the
// program size. If you are (rightfully) worried about the UB, for now just
// append your program with 11 zeroes.
use self::mem::HandlePageFault; use self::mem::HandlePageFault;
@ -97,6 +93,9 @@ pub struct Vm<'a, PfHandler, const TIMER_QUOTIENT: usize> {
/// Program /// Program
program: &'a [u8], program: &'a [u8],
/// Cached program length (without unreachable end)
program_len: usize,
/// Program timer /// Program timer
timer: usize, timer: usize,
} }
@ -114,6 +113,7 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
memory: Default::default(), memory: Default::default(),
pfhandler: traph, pfhandler: traph,
pc: 0, pc: 0,
program_len: program.len() - 12,
program, program,
timer: 0, timer: 0,
} }
@ -131,13 +131,18 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
pub fn run(&mut self) -> Result<VmRunOk, VmRunError> { pub fn run(&mut self) -> Result<VmRunOk, VmRunError> {
use hbbytecode::opcode::*; use hbbytecode::opcode::*;
loop { loop {
// Fetch instruction // Check instruction boundary
let Some(&opcode) = self.program.get(self.pc) if self.pc >= self.program_len {
else { return Ok(VmRunOk::End) }; return Ok(VmRunOk::End);
}
// Big match // Big match
unsafe { unsafe {
match opcode { match *self.program.get_unchecked(self.pc) {
UN => {
param!(self, ());
return Err(VmRunError::Unreachable);
}
NOP => param!(self, ()), NOP => param!(self, ()),
ADD => binary_op!(self, as_u64, u64::wrapping_add), ADD => binary_op!(self, as_u64, u64::wrapping_add),
SUB => binary_op!(self, as_u64, u64::wrapping_sub), SUB => binary_op!(self, as_u64, u64::wrapping_sub),
@ -352,6 +357,9 @@ pub enum VmRunError {
/// Unhandled store access exception /// Unhandled store access exception
StoreAccessEx(u64), StoreAccessEx(u64),
/// Reached unreachable code
Unreachable,
} }
/// Virtual machine halt ok /// Virtual machine halt ok

107
spec.md
View file

@ -4,6 +4,7 @@
- All numbers are encoded little-endian - All numbers are encoded little-endian
- There is 256 registers, they are represented by a byte - There is 256 registers, they are represented by a byte
- Immediate values are 64 bit - Immediate values are 64 bit
- Program is by spec required to be terminated with 12 zero bytes
### Instruction encoding ### Instruction encoding
- Instruction parameters are packed (no alignment) - Instruction parameters are packed (no alignment)
@ -34,9 +35,10 @@
## No-op ## No-op
- N type - N type
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:----------:| |:------:|:----:|:-----------------------------:|
| 0 | NOP | Do nothing | | 0 | UN | Trigger unreachable code trap |
| 1 | NOP | Do nothing |
## Integer binary ops. ## Integer binary ops.
- BBB type - BBB type
@ -44,21 +46,21 @@
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:-----------------------:| |:------:|:----:|:-----------------------:|
| 1 | ADD | Wrapping addition | | 2 | ADD | Wrapping addition |
| 2 | SUB | Wrapping subtraction | | 3 | SUB | Wrapping subtraction |
| 3 | MUL | Wrapping multiplication | | 4 | MUL | Wrapping multiplication |
| 4 | AND | Bitand | | 5 | AND | Bitand |
| 5 | OR | Bitor | | 6 | OR | Bitor |
| 6 | XOR | Bitxor | | 7 | XOR | Bitxor |
| 7 | SL | Unsigned left bitshift | | 8 | SL | Unsigned left bitshift |
| 8 | SR | Unsigned right bitshift | | 9 | SR | Unsigned right bitshift |
| 9 | SRS | Signed right bitshift | | 10 | SRS | Signed right bitshift |
### Comparsion ### Comparsion
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:-------------------:| |:------:|:----:|:-------------------:|
| 10 | CMP | Signed comparsion | | 11 | CMP | Signed comparsion |
| 11 | CMPU | Unsigned comparsion | | 12 | CMPU | Unsigned comparsion |
#### Comparsion table #### Comparsion table
| #1 *op* #2 | Result | | #1 *op* #2 | Result |
@ -75,7 +77,7 @@
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:-------------------------------:| |:------:|:----:|:-------------------------------:|
| 12 | DIR | Divide and remainder combinated | | 13 | DIR | Divide and remainder combinated |
### Negations ### Negations
- Type BB - Type BB
@ -83,8 +85,8 @@
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:----------------:| |:------:|:----:|:----------------:|
| 13 | NEG | Bit negation | | 14 | NEG | Bit negation |
| 14 | NOT | Logical negation | | 15 | NOT | Logical negation |
## Integer immediate binary ops. ## Integer immediate binary ops.
- Type BBD - Type BBD
@ -92,22 +94,22 @@
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:-----------------------:| |:------:|:----:|:-----------------------:|
| 15 | ADDI | Wrapping addition | | 16 | ADDI | Wrapping addition |
| 16 | MULI | Wrapping subtraction | | 17 | MULI | Wrapping subtraction |
| 17 | ANDI | Bitand | | 18 | ANDI | Bitand |
| 18 | ORI | Bitor | | 19 | ORI | Bitor |
| 19 | XORI | Bitxor | | 20 | XORI | Bitxor |
| 20 | SLI | Unsigned left bitshift | | 21 | SLI | Unsigned left bitshift |
| 21 | SRI | Unsigned right bitshift | | 22 | SRI | Unsigned right bitshift |
| 22 | SRSI | Signed right bitshift | | 23 | SRSI | Signed right bitshift |
### Comparsion ### Comparsion
- Comparsion is the same as when RRR type - Comparsion is the same as when RRR type
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:-----:|:-------------------:| |:------:|:-----:|:-------------------:|
| 23 | CMPI | Signed comparsion | | 24 | CMPI | Signed comparsion |
| 24 | CMPUI | Unsigned comparsion | | 25 | CMPUI | Unsigned comparsion |
## Register value set / copy ## Register value set / copy
@ -117,7 +119,7 @@
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:------:| |:------:|:----:|:------:|
| 25 | CP | Copy | | 26 | CP | Copy |
### Swap ### Swap
- Type BB - Type BB
@ -125,7 +127,7 @@
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:------:| |:------:|:----:|:------:|
| 26 | SWA | Swap | | 27 | SWA | Swap |
### Load immediate ### Load immediate
- Type BD - Type BD
@ -133,7 +135,7 @@
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:--------------:| |:------:|:----:|:--------------:|
| 27 | LI | Load immediate | | 28 | LI | Load immediate |
## Memory operations ## Memory operations
- Type BBDH - Type BBDH
@ -142,8 +144,8 @@
### Load / Store ### Load / Store
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:---------------------------------------:| |:------:|:----:|:---------------------------------------:|
| 28 | LD | `#0 ← [#1 + imm #3], copy imm #4 bytes` | | 29 | LD | `#0 ← [#1 + imm #3], copy imm #4 bytes` |
| 29 | ST | `[#1 + imm #3] ← #0, copy imm #4 bytes` | | 30 | ST | `[#1 + imm #3] ← #0, copy imm #4 bytes` |
## Block copy ## Block copy
- Block copy source and target can overlap - Block copy source and target can overlap
@ -153,7 +155,7 @@
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:--------------------------------:| |:------:|:----:|:--------------------------------:|
| 30 | BMC | `[#1] ← [#0], copy imm #2 bytes` | | 31 | BMC | `[#1] ← [#0], copy imm #2 bytes` |
### Register copy ### Register copy
- Type BBB - Type BBB
@ -161,7 +163,7 @@
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:--------------------------------:| |:------:|:----:|:--------------------------------:|
| 31 | BRC | `#1 ← #0, copy imm #2 registers` | | 32 | BRC | `#1 ← #0, copy imm #2 registers` |
## Control flow ## Control flow
@ -170,7 +172,7 @@
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:-------------------------------------------------:| |:------:|:----:|:-------------------------------------------------:|
| 32 | JAL | Save current PC to `#0` and jump at `#1 + imm #2` | | 33 | JAL | Save current PC to `#0` and jump at `#1 + imm #2` |
### Conditional jumps ### Conditional jumps
- Type BBD - Type BBD
@ -178,19 +180,19 @@
| Opcode | Name | Comparsion | | Opcode | Name | Comparsion |
|:------:|:----:|:------------:| |:------:|:----:|:------------:|
| 33 | JEQ | = | | 34 | JEQ | = |
| 34 | JNE | ≠ | | 35 | JNE | ≠ |
| 35 | JLT | < (signed) | | 36 | JLT | < (signed) |
| 36 | JGT | > (signed) | | 37 | JGT | > (signed) |
| 37 | JLTU | < (unsigned) | | 38 | JLTU | < (unsigned) |
| 38 | JGTU | > (unsigned) | | 39 | JGTU | > (unsigned) |
### Environment call ### Environment call
- Type N - Type N
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:-----:|:-------------------------------------:| |:------:|:-----:|:-------------------------------------:|
| 39 | ECALL | Cause an trap to the host environment | | 40 | ECALL | Cause an trap to the host environment |
## Floating point operations ## Floating point operations
- Type BBB - Type BBB
@ -198,29 +200,29 @@
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:--------------:| |:------:|:----:|:--------------:|
| 40 | ADDF | Addition | | 41 | ADDF | Addition |
| 41 | SUBF | Subtraction | | 42 | SUBF | Subtraction |
| 42 | MULF | Multiplication | | 43 | MULF | Multiplication |
### Division-remainder ### Division-remainder
- Type BBBB - Type BBBB
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:-------------------------:| |:------:|:----:|:-------------------------:|
| 43 | DIRF | Same as for integer `DIR` | | 44 | DIRF | Same as for integer `DIR` |
### Fused Multiply-Add ### Fused Multiply-Add
- Type BBBB - Type BBBB
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:---------------------:| |:------:|:----:|:---------------------:|
| 44 | FMAF | `#0 ← (#1 * #2) + #3` | | 45 | FMAF | `#0 ← (#1 * #2) + #3` |
### Negation ### Negation
- Type BB - Type BB
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:----------:| |:------:|:----:|:----------:|
| 45 | NEGF | `#0 ← -#1` | | 46 | NEGF | `#0 ← -#1` |
### Conversion ### Conversion
- Type BB - Type BB
@ -229,8 +231,8 @@
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:------------:| |:------:|:----:|:------------:|
| 46 | ITF | Int to Float | | 47 | ITF | Int to Float |
| 47 | FTI | Float to Int | | 48 | FTI | Float to Int |
## Floating point immediate operations ## Floating point immediate operations
- Type BBD - Type BBD
@ -238,8 +240,8 @@
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:-----:|:--------------:| |:------:|:-----:|:--------------:|
| 48 | ADDFI | Addition | | 49 | ADDFI | Addition |
| 49 | MULFI | Multiplication | | 50 | MULFI | Multiplication |
# Registers # Registers
- There is 255 registers + one zero register (with index 0) - There is 255 registers + one zero register (with index 0)
@ -277,6 +279,7 @@ Program should at least implement these traps:
- Invalid instruction exception - Invalid instruction exception
- Load address exception - Load address exception
- Store address exception - Store address exception
- Unreachable instruction
and executing environment should be able to get information about them, and executing environment should be able to get information about them,
like the opcode of invalid instruction or attempted address to load/store. like the opcode of invalid instruction or attempted address to load/store.