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:
commit
a21f68ffa6
33
Cargo.lock
generated
33
Cargo.lock
generated
|
@ -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"
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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 @ ..]
|
||||||
|
|
|
@ -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
107
spec.md
|
@ -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.
|
||||||
|
|
Loading…
Reference in a new issue