Updated flots

This commit is contained in:
Erin 2023-07-07 15:22:03 +02:00
parent 3919aa8100
commit 2d34ed61d0
7 changed files with 95 additions and 46 deletions

View file

@ -62,7 +62,8 @@ tokendef![
"nop", "add", "sub", "mul", "and", "or", "xor", "sl", "sr", "srs", "cmp", "cmpu", "nop", "add", "sub", "mul", "and", "or", "xor", "sl", "sr", "srs", "cmp", "cmpu",
"dir", "neg", "not", "addi", "muli", "andi", "ori", "xori", "sli", "sri", "srsi", "dir", "neg", "not", "addi", "muli", "andi", "ori", "xori", "sli", "sri", "srsi",
"cmpi", "cmpui", "cp", "swa", "li", "ld", "st", "bmc", "brc", "jmp", "jeq", "jne", "cmpi", "cmpui", "cp", "swa", "li", "ld", "st", "bmc", "brc", "jmp", "jeq", "jne",
"jlt", "jgt", "jltu", "jgtu", "ecall", "addf", "mulf", "dirf", "addfi", "mulfi", "jlt", "jgt", "jltu", "jgtu", "ecall", "addf", "subf", "mulf", "dirf", "fma", "negf",
"itf", "fti", "addfi", "mulfi",
]; ];
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@ -161,7 +162,7 @@ pub fn assembly(code: &str, buf: &mut Vec<u8>) -> Result<(), Error> {
]); ]);
Ok(()) Ok(())
} }
NEG..=NOT | CP..=SWA => { NEG..=NOT | CP..=SWA | NEGF..=FTI => {
expect_matches!( expect_matches!(
self, self,
Token::Register(r0), Token::Register(r0),

View file

@ -10,13 +10,15 @@
static_assert(CHAR_BIT == 8, "Cursed architectures are not supported"); static_assert(CHAR_BIT == 8, "Cursed architectures are not supported");
enum hbbc_Opcode: uint8_t { enum hbbc_Opcode: uint8_t {
hbbc_Op_NOP, hbbc_Op_ADD, hbbc_Op_MUL, hbbc_Op_AND, hbbc_Op_OR, hbbc_Op_XOR, hbbc_Op_SL, hbbc_Op_NOP , hbbc_Op_ADD , hbbc_Op_SUB , hbbc_Op_MUL , hbbc_Op_AND , hbbc_Op_OR ,
hbbc_Op_SR, hbbc_Op_SRS, hbbc_Op_CMP, hbbc_Op_CMPU, hbbc_Op_DIR, hbbc_Op_NEG, hbbc_Op_NOT, hbbc_Op_XOR , hbbc_Op_SL , hbbc_Op_SR , hbbc_Op_SRS , hbbc_Op_CMP , hbbc_Op_CMPU ,
hbbc_Op_ADDI, hbbc_Op_MULI, hbbc_Op_ANDI, hbbc_Op_ORI, hbbc_Op_XORI, hbbc_Op_SLI, hbbc_Op_SRI, hbbc_Op_DIR , hbbc_Op_NEG , hbbc_Op_NOT , hbbc_Op_ADDI , hbbc_Op_MULI , hbbc_Op_ANDI ,
hbbc_Op_SRSI, hbbc_Op_CMPI, hbbc_Op_CMPUI, hbbc_Op_CP, hbbc_Op_SWA, hbbc_Op_LI, hbbc_Op_LD, hbbc_Op_ORI , hbbc_Op_XORI , hbbc_Op_SLI , hbbc_Op_SRI , hbbc_Op_SRSI , hbbc_Op_CMPI ,
hbbc_Op_ST, hbbc_Op_BMC, hbbc_Op_BRC, hbbc_Op_JMP, hbbc_Op_JEQ, hbbc_Op_JNE, hbbc_Op_JLT, hbbc_Op_CMPUI , hbbc_Op_CP , hbbc_Op_SWA , hbbc_Op_LI , hbbc_Op_LD , hbbc_Op_ST ,
hbbc_Op_JGT, hbbc_Op_JLTU, hbbc_Op_JGTU, hbbc_Op_ECALL, hbbc_Op_ADDF, hbbc_Op_MULF, hbbc_Op_BMC , hbbc_Op_BRC , hbbc_Op_JMP , hbbc_Op_JEQ , hbbc_Op_JNE , hbbc_Op_JLT ,
hbbc_Op_DIRF, hbbc_Op_ADDFI, hbbc_Op_MULFI, hbbc_Op_JGT , hbbc_Op_JLTU , hbbc_Op_JGTU , hbbc_Op_ECALL , hbbc_Op_ADDF , hbbc_Op_SUBF ,
hbbc_Op_MULF , hbbc_Op_DIRF , hbbc_Op_FMA , hbbc_Op_NEGF , hbbc_Op_ITF , hbbc_Op_FTI ,
hbbc_Op_ADDFI , hbbc_Op_MULFI ,
} typedef hbbc_Opcode; } typedef hbbc_Opcode;
static_assert(sizeof(hbbc_Opcode) == 1); static_assert(sizeof(hbbc_Opcode) == 1);

View file

@ -32,7 +32,7 @@ constmod!(pub opcode(u8) {
CMP = 10, "BBB; #0 ← #1 <=> #2"; CMP = 10, "BBB; #0 ← #1 <=> #2";
CMPU = 11, "BBB; #0 ← #1 <=> #2 (unsigned)"; CMPU = 11, "BBB; #0 ← #1 <=> #2 (unsigned)";
DIR = 12, "BBBB; #0 ← #2 / #3, #1 ← #2 % #3"; DIR = 12, "BBBB; #0 ← #2 / #3, #1 ← #2 % #3";
NEG = 13, "BB; #0 ← ~#1"; NEG = 13, "BB; #0 ← -#1";
NOT = 14, "BB; #0 ← !#1"; NOT = 14, "BB; #0 ← !#1";
ADDI = 15, "BBD; #0 ← #1 + imm #2"; ADDI = 15, "BBD; #0 ← #1 + imm #2";
@ -63,12 +63,17 @@ constmod!(pub opcode(u8) {
JGTU = 38, "BBD; if #0 > #1 → jump imm #2 (unsigned)"; JGTU = 38, "BBD; if #0 > #1 → jump imm #2 (unsigned)";
ECALL = 39, "N; Issue system call"; ECALL = 39, "N; Issue system call";
ADDF = 40, "BBB; #0 ← #1 +. #2"; ADDF = 40, "BBB; #0 ← #1 +. #2";
MULF = 41, "BBB; #0 ← #1 +. #2"; SUBF = 41, "BBB; #0 ← #1 -. #2";
DIRF = 42, "BBBB; #0 ← #2 / #3, #1 ← #2 % #3"; MULF = 42, "BBB; #0 ← #1 +. #2";
DIRF = 43, "BBBB; #0 ← #2 / #3, #1 ← #2 % #3";
FMA = 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 = 43, "BBD; #0 ← #1 +. imm #2"; ADDFI = 48, "BBD; #0 ← #1 +. imm #2";
MULFI = 44, "BBD; #0 ← #1 *. imm #2"; MULFI = 49, "BBD; #0 ← #1 *. imm #2";
}); });
#[repr(packed)] #[repr(packed)]

View file

@ -15,7 +15,7 @@ pub enum ErrorKind {
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Error { pub struct Error {
/// Kind /// Kind
pub kind: ErrorKind, pub kind: ErrorKind,
/// Location in bytecode /// Location in bytecode
pub index: usize, pub index: usize,
} }
@ -34,7 +34,7 @@ pub fn validate(mut program: &[u8]) -> Result<(), Error> {
if usize::from(*reg) * 8 + usize::from(*count) > 2048 => if usize::from(*reg) * 8 + usize::from(*count) > 2048 =>
{ {
return Err(Error { return Err(Error {
kind: ErrorKind::RegisterArrayOverflow, kind: ErrorKind::RegisterArrayOverflow,
index: (program.as_ptr() as usize) - (start.as_ptr() as usize), index: (program.as_ptr() as usize) - (start.as_ptr() as usize),
}) })
} }
@ -42,20 +42,20 @@ pub fn validate(mut program: &[u8]) -> Result<(), Error> {
if src.checked_add(*count).is_none() || dst.checked_add(*count).is_none() => if src.checked_add(*count).is_none() || dst.checked_add(*count).is_none() =>
{ {
return Err(Error { return Err(Error {
kind: ErrorKind::RegisterArrayOverflow, kind: ErrorKind::RegisterArrayOverflow,
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 @ ..] [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, _, _, rest @ ..] | [NEG..=NOT | CP..=SWA | NEGF..=FTI, _, _, rest @ ..]
| [LI | JMP, _, _, _, _, _, _, _, _, _, rest @ ..] | [LI | JMP, _, _, _, _, _, _, _, _, _, rest @ ..]
| [ADDI..=CMPUI | BMC | JEQ..=JGTU | ADDFI..=MULFI, _, _, _, _, _, _, _, _, _, _, rest @ ..] | [ADDI..=CMPUI | BMC | JEQ..=JGTU | ADDFI..=MULFI, _, _, _, _, _, _, _, _, _, _, rest @ ..]
| [LD..=ST, _, _, _, _, _, _, _, _, _, _, _, _, rest @ ..] => rest, | [LD..=ST, _, _, _, _, _, _, _, _, _, _, _, _, rest @ ..] => rest,
_ => { _ => {
return Err(Error { return Err(Error {
kind: ErrorKind::InvalidInstruction, kind: ErrorKind::InvalidInstruction,
index: (program.as_ptr() as usize) - (start.as_ptr() as usize), index: (program.as_ptr() as usize) - (start.as_ptr() as usize),
}) })
} }

View file

@ -50,8 +50,7 @@ macro_rules! binary_op {
$handler( $handler(
Value::$ty(&$self.read_reg(a0)), Value::$ty(&$self.read_reg(a0)),
Value::$ty(&$self.read_reg(a1)), Value::$ty(&$self.read_reg(a1)),
) ),
.into(),
); );
}}; }};
} }
@ -62,7 +61,7 @@ macro_rules! binary_op_imm {
let ParamBBD(tg, a0, imm) = param!($self, ParamBBD); let ParamBBD(tg, a0, imm) = param!($self, ParamBBD);
$self.write_reg( $self.write_reg(
tg, tg,
$handler(Value::$ty(&$self.read_reg(a0)), Value::$ty(&imm.into())).into(), $handler(Value::$ty(&$self.read_reg(a0)), Value::$ty(&imm.into())),
); );
}}; }};
} }
@ -148,21 +147,19 @@ impl<'a, T: HandleTrap> Vm<'a, T> {
let ParamBBB(tg, a0, a1) = param!(self, ParamBBB); let ParamBBB(tg, a0, a1) = param!(self, ParamBBB);
self.write_reg( self.write_reg(
tg, tg,
(self.read_reg(a0).as_i64().cmp(&self.read_reg(a1).as_i64()) as i64) self.read_reg(a0).as_i64().cmp(&self.read_reg(a1).as_i64()) as i64,
.into(),
); );
} }
CMPU => { CMPU => {
let ParamBBB(tg, a0, a1) = param!(self, ParamBBB); let ParamBBB(tg, a0, a1) = param!(self, ParamBBB);
self.write_reg( self.write_reg(
tg, tg,
(self.read_reg(a0).as_u64().cmp(&self.read_reg(a1).as_u64()) as i64) self.read_reg(a0).as_u64().cmp(&self.read_reg(a1).as_u64()) as i64,
.into(),
); );
} }
NOT => { NOT => {
let param = param!(self, ParamBB); let param = param!(self, ParamBB);
self.write_reg(param.0, (!self.read_reg(param.1).as_u64()).into()); self.write_reg(param.0, !self.read_reg(param.1).as_u64());
} }
NEG => { NEG => {
let param = param!(self, ParamBB); let param = param!(self, ParamBB);
@ -171,16 +168,15 @@ impl<'a, T: HandleTrap> Vm<'a, T> {
match self.read_reg(param.1).as_u64() { match self.read_reg(param.1).as_u64() {
0 => 1_u64, 0 => 1_u64,
_ => 0, _ => 0,
} },
.into(),
); );
} }
DIR => { DIR => {
let ParamBBBB(dt, rt, a0, a1) = param!(self, ParamBBBB); let ParamBBBB(dt, rt, a0, a1) = param!(self, ParamBBBB);
let a0 = self.read_reg(a0).as_u64(); let a0 = self.read_reg(a0).as_u64();
let a1 = self.read_reg(a1).as_u64(); let a1 = self.read_reg(a1).as_u64();
self.write_reg(dt, (a0.checked_div(a1).unwrap_or(u64::MAX)).into()); self.write_reg(dt, a0.checked_div(a1).unwrap_or(u64::MAX));
self.write_reg(rt, (a0.checked_rem(a1).unwrap_or(u64::MAX)).into()); self.write_reg(rt, a0.checked_rem(a1).unwrap_or(u64::MAX));
} }
ADDI => binary_op_imm!(self, as_u64, ops::Add::add), ADDI => binary_op_imm!(self, as_u64, ops::Add::add),
MULI => binary_op_imm!(self, as_u64, ops::Mul::mul), MULI => binary_op_imm!(self, as_u64, ops::Mul::mul),
@ -194,13 +190,12 @@ impl<'a, T: HandleTrap> Vm<'a, T> {
let ParamBBD(tg, a0, imm) = param!(self, ParamBBD); let ParamBBD(tg, a0, imm) = param!(self, ParamBBD);
self.write_reg( self.write_reg(
tg, tg,
(self.read_reg(a0).as_i64().cmp(&Value::from(imm).as_i64()) as i64) self.read_reg(a0).as_i64().cmp(&Value::from(imm).as_i64()) as i64,
.into(),
); );
} }
CMPUI => { CMPUI => {
let ParamBBD(tg, a0, imm) = param!(self, ParamBBD); let ParamBBD(tg, a0, imm) = param!(self, ParamBBD);
self.write_reg(tg, (self.read_reg(a0).as_u64().cmp(&imm) as i64).into()); self.write_reg(tg, self.read_reg(a0).as_u64().cmp(&imm) as i64);
} }
CP => { CP => {
let param = param!(self, ParamBB); let param = param!(self, ParamBB);
@ -217,7 +212,7 @@ impl<'a, T: HandleTrap> Vm<'a, T> {
} }
LI => { LI => {
let param = param!(self, ParamBD); let param = param!(self, ParamBD);
self.write_reg(param.0, param.1.into()); self.write_reg(param.0, param.1);
} }
LD => { LD => {
let ParamBBDH(dst, base, off, count) = param!(self, ParamBBDH); let ParamBBDH(dst, base, off, count) = param!(self, ParamBBDH);
@ -280,13 +275,34 @@ impl<'a, T: HandleTrap> Vm<'a, T> {
.ecall(&mut self.registers, &mut self.pc, &mut self.memory); .ecall(&mut self.registers, &mut self.pc, &mut self.memory);
} }
ADDF => binary_op!(self, as_f64, ops::Add::add), ADDF => binary_op!(self, as_f64, ops::Add::add),
SUBF => binary_op!(self, as_f64, ops::Sub::sub),
MULF => binary_op!(self, as_f64, ops::Mul::mul), MULF => binary_op!(self, as_f64, ops::Mul::mul),
DIRF => { DIRF => {
let ParamBBBB(dt, rt, a0, a1) = param!(self, ParamBBBB); let ParamBBBB(dt, rt, a0, a1) = param!(self, ParamBBBB);
let a0 = self.read_reg(a0).as_f64(); let a0 = self.read_reg(a0).as_f64();
let a1 = self.read_reg(a1).as_f64(); let a1 = self.read_reg(a1).as_f64();
self.write_reg(dt, (a0 / a1).into()); self.write_reg(dt, a0 / a1);
self.write_reg(rt, (a0 % a1).into()); self.write_reg(rt, a0 % a1);
}
FMA => {
let ParamBBBB(dt, a0, a1, a2) = param!(self, ParamBBBB);
self.write_reg(
dt,
self.read_reg(a0).as_f64() * self.read_reg(a1).as_f64()
+ self.read_reg(a2).as_f64(),
);
}
NEGF => {
let ParamBB(dt, a0) = param!(self, ParamBB);
self.write_reg(dt, -self.read_reg(a0).as_f64());
}
ITF => {
let ParamBB(dt, a0) = param!(self, ParamBB);
self.write_reg(dt, self.read_reg(a0).as_i64() as f64);
}
FTI => {
let ParamBB(dt, a0) = param!(self, ParamBB);
self.write_reg(dt, self.read_reg(a0).as_f64() as i64);
} }
ADDFI => binary_op_imm!(self, as_f64, ops::Add::add), ADDFI => binary_op_imm!(self, as_f64, ops::Add::add),
MULFI => binary_op_imm!(self, as_f64, ops::Mul::mul), MULFI => binary_op_imm!(self, as_f64, ops::Mul::mul),
@ -314,9 +330,9 @@ impl<'a, T: HandleTrap> Vm<'a, T> {
/// Write a register. /// Write a register.
/// Writing to register 0 is no-op. /// Writing to register 0 is no-op.
#[inline] #[inline]
unsafe fn write_reg(&mut self, n: u8, value: Value) { unsafe fn write_reg(&mut self, n: u8, value: impl Into<Value>) {
if n != 0 { if n != 0 {
*self.registers.get_unchecked_mut(n as usize) = value; *self.registers.get_unchecked_mut(n as usize) = value.into();
} }
} }
} }

View file

@ -1,3 +1,4 @@
hex_literal_case = "Upper" hex_literal_case = "Upper"
imports_granularity = "One" imports_granularity = "One"
struct_field_align_threshold = 5 struct_field_align_threshold = 5
enum_discrim_align_threshold = 5

36
spec.md
View file

@ -199,14 +199,38 @@
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:--------------:| |:------:|:----:|:--------------:|
| 40 | ADDF | Addition | | 40 | ADDF | Addition |
| 41 | MULF | Multiplication | | 41 | SUBF | Subtraction |
| 42 | MULF | Multiplication |
### Division-remainder ### Division-remainder
- Type BBBB - Type BBBB
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:----:|:--------------------------------------:| |:------:|:----:|:-------------------------:|
| 42 | DIRF | Same flow applies as for integer `DIR` | | 43 | DIRF | Same as for integer `DIR` |
### Fused Multiply-Add
- Type BBBB
| Opcode | Name | Action |
|:------:|:----:|:---------------------:|
| 44 | FMA | `#0 ← (#1 * #2) + #3` |
### Negation
- Type BB
| Opcode | Name | Action |
|:------:|:----:|:----------:|
| 45 | NEGF | `#0 ← -#1` |
### Conversion
- Type BB
- Signed
- `#0 ← #1 as _`
| Opcode | Name | Action |
|:------:|:----:|:------------:|
| 46 | ITF | Int to Float |
| 47 | FTI | Float to Int |
## Floating point immediate operations ## Floating point immediate operations
- Type BBD - Type BBD
@ -214,8 +238,8 @@
| Opcode | Name | Action | | Opcode | Name | Action |
|:------:|:-----:|:--------------:| |:------:|:-----:|:--------------:|
| 43 | ADDFI | Addition | | 48 | ADDFI | Addition |
| 44 | MULFI | Multiplication | | 49 | MULFI | Multiplication |
# Registers # Registers
- There is 255 registers + one zero register (with index 0) - There is 255 registers + one zero register (with index 0)