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",
"dir", "neg", "not", "addi", "muli", "andi", "ori", "xori", "sli", "sri", "srsi",
"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)]
@ -161,7 +162,7 @@ pub fn assembly(code: &str, buf: &mut Vec<u8>) -> Result<(), Error> {
]);
Ok(())
}
NEG..=NOT | CP..=SWA => {
NEG..=NOT | CP..=SWA | NEGF..=FTI => {
expect_matches!(
self,
Token::Register(r0),

View file

@ -10,13 +10,15 @@
static_assert(CHAR_BIT == 8, "Cursed architectures are not supported");
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_SR, hbbc_Op_SRS, hbbc_Op_CMP, hbbc_Op_CMPU, hbbc_Op_DIR, hbbc_Op_NEG, hbbc_Op_NOT,
hbbc_Op_ADDI, hbbc_Op_MULI, hbbc_Op_ANDI, hbbc_Op_ORI, hbbc_Op_XORI, hbbc_Op_SLI, hbbc_Op_SRI,
hbbc_Op_SRSI, hbbc_Op_CMPI, hbbc_Op_CMPUI, hbbc_Op_CP, hbbc_Op_SWA, hbbc_Op_LI, hbbc_Op_LD,
hbbc_Op_ST, hbbc_Op_BMC, hbbc_Op_BRC, hbbc_Op_JMP, hbbc_Op_JEQ, hbbc_Op_JNE, hbbc_Op_JLT,
hbbc_Op_JGT, hbbc_Op_JLTU, hbbc_Op_JGTU, hbbc_Op_ECALL, hbbc_Op_ADDF, hbbc_Op_MULF,
hbbc_Op_DIRF, hbbc_Op_ADDFI, hbbc_Op_MULFI,
hbbc_Op_NOP , hbbc_Op_ADD , hbbc_Op_SUB , hbbc_Op_MUL , hbbc_Op_AND , hbbc_Op_OR ,
hbbc_Op_XOR , hbbc_Op_SL , hbbc_Op_SR , hbbc_Op_SRS , hbbc_Op_CMP , hbbc_Op_CMPU ,
hbbc_Op_DIR , hbbc_Op_NEG , hbbc_Op_NOT , hbbc_Op_ADDI , hbbc_Op_MULI , hbbc_Op_ANDI ,
hbbc_Op_ORI , hbbc_Op_XORI , hbbc_Op_SLI , hbbc_Op_SRI , hbbc_Op_SRSI , hbbc_Op_CMPI ,
hbbc_Op_CMPUI , hbbc_Op_CP , hbbc_Op_SWA , hbbc_Op_LI , hbbc_Op_LD , hbbc_Op_ST ,
hbbc_Op_BMC , hbbc_Op_BRC , hbbc_Op_JMP , hbbc_Op_JEQ , hbbc_Op_JNE , hbbc_Op_JLT ,
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;
static_assert(sizeof(hbbc_Opcode) == 1);

View file

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

View file

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

View file

@ -50,8 +50,7 @@ macro_rules! binary_op {
$handler(
Value::$ty(&$self.read_reg(a0)),
Value::$ty(&$self.read_reg(a1)),
)
.into(),
),
);
}};
}
@ -62,7 +61,7 @@ macro_rules! binary_op_imm {
let ParamBBD(tg, a0, imm) = param!($self, ParamBBD);
$self.write_reg(
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);
self.write_reg(
tg,
(self.read_reg(a0).as_i64().cmp(&self.read_reg(a1).as_i64()) as i64)
.into(),
self.read_reg(a0).as_i64().cmp(&self.read_reg(a1).as_i64()) as i64,
);
}
CMPU => {
let ParamBBB(tg, a0, a1) = param!(self, ParamBBB);
self.write_reg(
tg,
(self.read_reg(a0).as_u64().cmp(&self.read_reg(a1).as_u64()) as i64)
.into(),
self.read_reg(a0).as_u64().cmp(&self.read_reg(a1).as_u64()) as i64,
);
}
NOT => {
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 => {
let param = param!(self, ParamBB);
@ -171,16 +168,15 @@ impl<'a, T: HandleTrap> Vm<'a, T> {
match self.read_reg(param.1).as_u64() {
0 => 1_u64,
_ => 0,
}
.into(),
},
);
}
DIR => {
let ParamBBBB(dt, rt, a0, a1) = param!(self, ParamBBBB);
let a0 = self.read_reg(a0).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(rt, (a0.checked_rem(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));
}
ADDI => binary_op_imm!(self, as_u64, ops::Add::add),
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);
self.write_reg(
tg,
(self.read_reg(a0).as_i64().cmp(&Value::from(imm).as_i64()) as i64)
.into(),
self.read_reg(a0).as_i64().cmp(&Value::from(imm).as_i64()) as i64,
);
}
CMPUI => {
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 => {
let param = param!(self, ParamBB);
@ -217,7 +212,7 @@ impl<'a, T: HandleTrap> Vm<'a, T> {
}
LI => {
let param = param!(self, ParamBD);
self.write_reg(param.0, param.1.into());
self.write_reg(param.0, param.1);
}
LD => {
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);
}
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),
DIRF => {
let ParamBBBB(dt, rt, a0, a1) = param!(self, ParamBBBB);
let a0 = self.read_reg(a0).as_f64();
let a1 = self.read_reg(a1).as_f64();
self.write_reg(dt, (a0 / a1).into());
self.write_reg(rt, (a0 % a1).into());
self.write_reg(dt, a0 / a1);
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),
MULFI => binary_op_imm!(self, as_f64, ops::Mul::mul),
@ -314,9 +330,9 @@ impl<'a, T: HandleTrap> Vm<'a, T> {
/// Write a register.
/// Writing to register 0 is no-op.
#[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 {
*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"
imports_granularity = "One"
struct_field_align_threshold = 5
enum_discrim_align_threshold = 5

36
spec.md
View file

@ -199,14 +199,38 @@
| Opcode | Name | Action |
|:------:|:----:|:--------------:|
| 40 | ADDF | Addition |
| 41 | MULF | Multiplication |
| 41 | SUBF | Subtraction |
| 42 | MULF | Multiplication |
### Division-remainder
- Type BBBB
| Opcode | Name | Action |
|:------:|:----:|:--------------------------------------:|
| 42 | DIRF | Same flow applies as for integer `DIR` |
| Opcode | Name | Action |
|:------:|:----:|:-------------------------:|
| 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
- Type BBD
@ -214,8 +238,8 @@
| Opcode | Name | Action |
|:------:|:-----:|:--------------:|
| 43 | ADDFI | Addition |
| 44 | MULFI | Multiplication |
| 48 | ADDFI | Addition |
| 49 | MULFI | Multiplication |
# Registers
- There is 255 registers + one zero register (with index 0)