From 68c9b336375aedff63e3dd76773258fb2dccd3b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sat, 17 Oct 2020 23:58:24 +0200 Subject: [PATCH] basic float arith, wip float trig, abs --- crsn/src/asm/data/literal.rs | 2 +- crsn/src/asm/data/rd.rs | 21 ++- crsn/src/asm/parse/arg_parser.rs | 2 +- crsn/src/runtime/frame/status.rs | 7 + crsn/src/runtime/run_thread/state.rs | 7 + crsn_arith/src/defs.rs | 54 ++++-- crsn_arith/src/exec.rs | 185 +++++++++++++++++- crsn_arith/src/parse.rs | 269 ++++++++++++++++++++++++++- crsn_buf/src/parse.rs | 6 +- crsn_screen/src/parse.rs | 4 +- 10 files changed, 521 insertions(+), 36 deletions(-) diff --git a/crsn/src/asm/data/literal.rs b/crsn/src/asm/data/literal.rs index a202442..272484c 100644 --- a/crsn/src/asm/data/literal.rs +++ b/crsn/src/asm/data/literal.rs @@ -9,7 +9,7 @@ pub type Value = u64; #[inline(always)] pub const fn is_positive(val: Value) -> bool { - 0 == (val & 0x8000_0000_0000_0000) + 0 == (val & 0x8000_0000_0000_0000) && val != 0 } #[inline(always)] diff --git a/crsn/src/asm/data/rd.rs b/crsn/src/asm/data/rd.rs index 27a86ee..edbc875 100644 --- a/crsn/src/asm/data/rd.rs +++ b/crsn/src/asm/data/rd.rs @@ -14,11 +14,28 @@ impl Rd { pub const fn new(src: RdData) -> Self { Rd(src) } - pub const fn immediate(val: Value) -> Rd { + + pub const fn new_imm(val: Value) -> Rd { Rd(RdData::Immediate(val)) } - pub fn is_immediate_equal(self, other: Value) -> bool { + /// Construct new from float + pub fn new_float(val: f64) -> Rd { // TODO const when stabilized + Rd(RdData::Immediate(val.to_bits())) + } + + /// Convert immediate read to float + pub fn imm_to_float(self) -> Rd { + match self { + Rd(RdData::Immediate(v)) => { + let signed : i64 = unsafe { std::mem::transmute(v) }; + Rd::new_float(signed as f64) + } + other => other + } + } + + pub fn is_imm_equal(self, other: Value) -> bool { match self.0 { RdData::Immediate(val) => { val == other diff --git a/crsn/src/asm/parse/arg_parser.rs b/crsn/src/asm/parse/arg_parser.rs index 596be39..e1ba4a1 100644 --- a/crsn/src/asm/parse/arg_parser.rs +++ b/crsn/src/asm/parse/arg_parser.rs @@ -291,7 +291,7 @@ impl<'a> TokenParser<'a> { pub fn parse_wr_rd_rd_or_n(&mut self, n : Value) -> Result<(Wr, Rd, Rd), CrsnError> { if self.len() == 1 { let rw = self.next_rdwr()?; - Ok((rw.wr(), rw.rd(), Rd::immediate(n))) + Ok((rw.wr(), rw.rd(), Rd::new_imm(n))) } else if self.len() == 2 { let rw = self.next_rdwr()?; let rd = self.next_rd()?; diff --git a/crsn/src/runtime/frame/status.rs b/crsn/src/runtime/frame/status.rs index b14d8c3..0137169 100644 --- a/crsn/src/runtime/frame/status.rs +++ b/crsn/src/runtime/frame/status.rs @@ -78,6 +78,13 @@ impl StatusFlags { self.negative = is_negative(val); } + #[inline(always)] + pub fn update_float(&mut self, val: f64) { + self.zero = val == 0.0; + self.positive = val > 0.0; + self.negative = val < 0.0; + } + #[inline(always)] pub fn test(&self, cond: Cond) -> bool { match cond { diff --git a/crsn/src/runtime/run_thread/state.rs b/crsn/src/runtime/run_thread/state.rs index 3022e82..7e0f9a4 100644 --- a/crsn/src/runtime/run_thread/state.rs +++ b/crsn/src/runtime/run_thread/state.rs @@ -102,6 +102,13 @@ impl RunState { self.frame.status.update(val); } + /// Update status flags using a variable. + /// The update is additive - call `clear_status()` first if desired! + #[inline(always)] + pub fn update_status_float(&mut self, val: f64) { + self.frame.status.update_float(val); + } + /// Read object handle value pub fn read_obj(&mut self, rdo: impl Into) -> Result { rdo.into().read(self) diff --git a/crsn_arith/src/defs.rs b/crsn_arith/src/defs.rs index 3e96dbb..7bfba33 100644 --- a/crsn_arith/src/defs.rs +++ b/crsn_arith/src/defs.rs @@ -27,8 +27,10 @@ pub enum ArithOp { SignExtend { dst: Wr, src: Rd, mask: BitMask }, Add { dst: Wr, a: Rd, b: Rd }, + Abs { dst: Wr, a: Rd }, Sub { dst: Wr, a: Rd, b: Rd }, Mul { dst: Wr, a: Rd, b: Rd }, + Pow { dst: Wr, a: Rd, pow: Rd }, Div { dst: Wr, rem: Wr, a: Rd, div: Rd }, // "Mod" is functionally equivalent to "Div" with the result discarded, // but status flags are updated by the remainder @@ -46,18 +48,42 @@ pub enum ArithOp { Lsr { dst: Wr, a: Rd, n: Rd }, Asr { dst: Wr, a: Rd, n: Rd }, - // IntToFloat { dst: Wr, a: Rd }, - // FloatToInt { dst: Wr, a: Rd }, - // FloatTest { a: Rd }, - // FloatCompare { a: Rd, b: Rd }, - // FloatRangeTest { val: Rd, a: Rd, b: Rd }, - // FloatRng { dst: Wr, min: Rd, max: Rd }, - // FloatRound { dst: Wr, a: Rd, b: Rd }, - // FloatCeil { dst: Wr, a: Rd, b: Rd }, - // FloatFloor { dst: Wr, a: Rd, b: Rd }, - // FloatAdd { dst: Wr, a: Rd, b: Rd }, - // FloatSub { dst: Wr, a: Rd, b: Rd }, - // FloatMul { dst: Wr, a: Rd, b: Rd }, - // FloatDiv { dst: Wr, rem: Wr, a: Rd, div: Rd }, - // FloatMod { dst: Wr, a: Rd, div: Rd }, + IntToFloat { dst: Wr, a: Rd }, + FloatToInt { dst: Wr, a: Rd, mode: FloatToIntMode }, + FloatTest { a: Rd }, + FloatCompare { a: Rd, b: Rd }, + FloatRangeTest { val: Rd, a: Rd, b: Rd }, + FloatRng { dst: Wr, min: Rd, max: Rd }, + FloatAdd { dst: Wr, a: Rd, b: Rd }, + FloatSub { dst: Wr, a: Rd, b: Rd }, + FloatMul { dst: Wr, a: Rd, b: Rd }, + FloatPow { dst: Wr, a: Rd, pow: Rd }, + FloatRoot { dst: Wr, a: Rd, root: Rd }, + FloatHyp { dst: Wr, a: Rd, b: Rd }, + FloatDiv { dst: Wr, rem: Wr, a: Rd, div: Rd }, + FloatMod { dst: Wr, a: Rd, div: Rd }, + FloatAbs { dst: Wr, a: Rd }, + + FloatSin { dst: Wr, f: Rd }, + FloatAsin { dst: Wr, a: Rd }, + FloatCos { dst: Wr, f: Rd }, + FloatAcos { dst: Wr, a: Rd }, + FloatTan { dst: Wr, f: Rd }, + FloatAtan { dst: Wr, a: Rd }, + FloatAtan2 { dst: Wr, y: Rd, x: Rd }, + FloatCot { dst: Wr, f: Rd }, + FloatAcot { dst: Wr, a: Rd }, +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum FloatToIntMode { + Floor, + Ceil, + Round, +} + +impl Default for FloatToIntMode { + fn default() -> Self { + Self::Round + } } diff --git a/crsn_arith/src/exec.rs b/crsn_arith/src/exec.rs index c2f3966..cf4b1b8 100644 --- a/crsn_arith/src/exec.rs +++ b/crsn_arith/src/exec.rs @@ -10,14 +10,35 @@ use crsn::sexp; use crsn::sexp::Sexp; use crsn::utils::A; -use crate::defs::ArithOp; +use crate::defs::{ArithOp, FloatToIntMode}; use crsn::asm::instr::cond::Flag; use rand::Rng; +#[inline] +fn f2u(f: f64) -> u64 { + unsafe { std::mem::transmute(f) } +} + +#[inline] +fn u2f(f: u64) -> f64 { + unsafe { std::mem::transmute(f) } +} + +#[inline] +fn i2u(f: i64) -> u64 { + unsafe { std::mem::transmute(f) } +} + +#[inline] +fn u2i(f: u64) -> i64 { + unsafe { std::mem::transmute(f) } +} + impl OpTrait for ArithOp { fn execute(&self, _ti: &ThreadInfo, state: &mut RunState) -> Result { let eres = EvalRes::default(); match self { + // Integers ArithOp::Test { a } => { state.clear_status(); let res = state.read(a)?; @@ -142,6 +163,122 @@ impl OpTrait for ArithOp { state.write(dst, remainder)?; } } + + // Floating point + + ArithOp::FloatToInt { dst, a, mode } => { + state.clear_status(); + let val : f64 = u2f(state.read(a)?); + let res = i2u(match mode { + FloatToIntMode::Floor => val.floor(), + FloatToIntMode::Ceil => val.ceil(), + FloatToIntMode::Round => val.round(), + } as i64); + state.update_status(res); + state.write(dst, res)?; + } + ArithOp::IntToFloat { dst, a } => { + state.clear_status(); + let val : f64 = u2i(state.read(a)?) as f64; + state.update_status_float(val); + state.write(dst, f2u(val))?; + } + ArithOp::FloatTest { a } => { + state.clear_status(); + let res = u2f(state.read(a)?); + state.update_status_float(res); + } + ArithOp::FloatCompare { a, b } => { + state.clear_status(); + let x = u2f(state.read(a)?); + let y = u2f(state.read(b)?); + state.set_flag(Flag::Equal, x == y); + state.set_flag(Flag::Lower, x < y); + state.set_flag(Flag::Greater, x > y); + // Test flags are set when both arguments have the property + if x == y { + state.update_status_float(x); + } + } + ArithOp::FloatRangeTest { val, a, b } => { + state.clear_status(); + let val = u2f(state.read(val)?); + let a = u2f(state.read(a)?); + let b = u2f(state.read(b)?); + state.set_flag(Flag::Equal, val >= a && val <= b); + state.set_flag(Flag::Lower, val < a); + state.set_flag(Flag::Greater, val > b); + state.update_status_float(val); + } + ArithOp::FloatRng { dst, min, max } => { + state.clear_status(); + let min = u2f(state.read(min)?); + let max = u2f(state.read(max)?); + + let val = if min == max { + min + } else if min > max { + state.set_flag(Flag::Invalid, true); + min + } else { + rand::thread_rng() + .gen_range(min, max) + }; + state.write(dst, f2u(val))?; + state.update_status_float(val); + } + ArithOp::FloatAdd { dst, a, b } => { + state.clear_status(); + let x = u2f(state.read(a)?); + let y = u2f(state.read(b)?); + let res = x + y; + state.update_status_float(res); + state.write(dst, f2u(res))?; + } + ArithOp::FloatSub { dst, a, b } => { + state.clear_status(); + let x = u2f(state.read(a)?); + let y = u2f(state.read(b)?); + let res = x - y; + state.update_status_float(res); + state.write(dst, f2u(res))?; + } + ArithOp::FloatMul { dst, a, b } => { + state.clear_status(); + let x = u2f(state.read(a)?); + let y = u2f(state.read(b)?); + let res = x * y; + state.update_status_float(res); + state.write(dst, f2u(res))?; + } + ArithOp::FloatDiv { dst, rem, a, div } => { + state.clear_status(); + let x = u2f(state.read(a)?); + let d = u2f(state.read(div)?); + if d == 0.0 { + state.set_flag(Flag::Invalid, true); + } else { + let res = x / d; + let remainder = x % d; + state.update_status_float(res); + state.write(dst, f2u(res))?; + state.write(rem, f2u(remainder))?; + } + } + ArithOp::FloatMod { dst, a, div } => { + state.clear_status(); + let x = u2f(state.read(a)?); + let d = u2f(state.read(div)?); + if d == 0.0 { + state.set_flag(Flag::Invalid, true); + } else { + let rem = x % d; + state.update_status_float(rem); + state.write(dst, f2u(rem))?; + } + } + + // Bitwise ArithOp::And { dst, a, b } => { state.clear_status(); let x = state.read(a)?; @@ -282,6 +419,8 @@ impl OpTrait for ArithOp { state.update_status(res); state.write(dst, res)?; } + + _ => unimplemented!() // TODO implement float trig etc } Ok(eres) @@ -289,19 +428,19 @@ impl OpTrait for ArithOp { fn to_sexp(&self) -> Sexp { match self { - ArithOp::Add { dst, a, b } => to_sexp_2_or_3("add", dst, a, b), - ArithOp::Test { a } => sexp::list(&[A("test"), A(a)]), + ArithOp::Test { a } => sexp::list(&[A("tst"), A(a)]), ArithOp::Compare { a, b } => sexp::list(&[A("cmp"), A(a), A(b)]), ArithOp::RangeTest { val, a: start, b: end } => sexp::list(&[A("rcmp"), A(val), A(start), A(end)]), ArithOp::Rng { dst, min, max } => { - if min.is_immediate_equal(0) && max.is_immediate_equal(u64::MAX) { + if min.is_imm_equal(0) && max.is_imm_equal(u64::MAX) { sexp::list(&[A("rng"), A(dst)]) - } else if min.is_immediate_equal(0) { + } else if min.is_imm_equal(0) { sexp::list(&[A("rng"), A(dst), A(max)]) } else { sexp::list(&[A("rng"), A(dst), A(min), A(max)]) } } + ArithOp::Add { dst, a, b } => to_sexp_2_or_3("add", dst, a, b), ArithOp::Sub { dst, a, b } => to_sexp_2_or_3("sub", dst, a, b), ArithOp::Mul { dst, a, b } => to_sexp_2_or_3("mul", dst, a, b), ArithOp::Div { dst, rem, a, div } => { @@ -316,6 +455,40 @@ impl OpTrait for ArithOp { } } ArithOp::Mod { dst, a, div } => to_sexp_2_or_3("mod", dst, a, div), + + // TODO render as float + ArithOp::FloatTest { a } => sexp::list(&[A("tstf"), A(a)]), + ArithOp::FloatCompare { a, b } => sexp::list(&[A("cmpf"), A(a), A(b)]), + ArithOp::FloatRangeTest { val, a: start, b: end } => sexp::list(&[A("rcmpf"), A(val), A(start), A(end)]), + ArithOp::FloatRng { dst, min, max } => { + if min.is_imm_equal(0f64.to_bits()) && max.is_imm_equal(f64::MAX.to_bits()) { + sexp::list(&[A("rngf"), A(dst)]) + } else if min.is_imm_equal(0) { + sexp::list(&[A("rngf"), A(dst), A(max)]) + } else { + sexp::list(&[A("rngf"), A(dst), A(min), A(max)]) + } + } + ArithOp::FloatAdd { dst, a, b } => to_sexp_2_or_3("addf", dst, a, b), + ArithOp::FloatSub { dst, a, b } => to_sexp_2_or_3("subf", dst, a, b), + ArithOp::FloatMul { dst, a, b } => to_sexp_2_or_3("mulf", dst, a, b), + ArithOp::FloatDiv { dst, rem, a, div } => { + if rem.is_discard() { + to_sexp_2_or_3("divf", dst, a, div) + } else { + if &dst.as_rd() == a { + sexp::list(&[A("divrf"), A(dst), A(rem), A(div)]) + } else { + sexp::list(&[A("divrf"), A(dst), A(rem), A(a), A(div)]) + } + } + } + ArithOp::FloatMod { dst, a, div } => to_sexp_2_or_3("modf", dst, a, div), + ArithOp::IntToFloat { dst, a } => to_sexp_1_or_2("itf", dst, a), + ArithOp::FloatToInt { dst, a, mode: FloatToIntMode::Floor } => to_sexp_1_or_2("ftif", dst, a), + ArithOp::FloatToInt { dst, a, mode: FloatToIntMode::Round } => to_sexp_1_or_2("ftir", dst, a), + ArithOp::FloatToInt { dst, a, mode: FloatToIntMode::Ceil } => to_sexp_1_or_2("ftic", dst, a), + ArithOp::And { dst, a, b } => to_sexp_2_or_3("and", dst, a, b), ArithOp::Or { dst, a, b } => to_sexp_2_or_3("or", dst, a, b), ArithOp::Xor { dst, a, b } => to_sexp_2_or_3("xor", dst, a, b), @@ -333,6 +506,8 @@ impl OpTrait for ArithOp { ArithOp::Clz { dst, src, mask: slice } => to_sexp_1_or_2(&format!("clz{}", slice), dst, src), ArithOp::Clo { dst, src, mask: slice } => to_sexp_1_or_2(&format!("clo{}", slice), dst, src), ArithOp::SignExtend { dst, src, mask: slice } => to_sexp_1_or_2(&format!("se{}", slice), dst, src), + + _ => unimplemented!() // FIXME } } } diff --git a/crsn_arith/src/parse.rs b/crsn_arith/src/parse.rs index 3e085f7..c689991 100644 --- a/crsn_arith/src/parse.rs +++ b/crsn_arith/src/parse.rs @@ -4,9 +4,7 @@ use crsn::asm::instr::op::OpKind; use crsn::asm::parse::arg_parser::TokenParser; use crsn::module::ParseRes; use crsn::sexp::SourcePosition; - -use crate::defs::ArithOp; - +use crate::defs::{ArithOp, FloatToIntMode}; pub(crate) fn parse<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result, CrsnError> { Ok(ParseRes::ext(match keyword { @@ -33,14 +31,14 @@ pub(crate) fn parse<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenP 1 => { ArithOp::Rng { dst: args.next_wr()?, - min: Rd::immediate(0), - max: Rd::immediate(u64::MAX), + min: Rd::new_imm(0), + max: Rd::new_imm(u64::MAX), } } 2 => { ArithOp::Rng { dst: args.next_wr()?, - min: Rd::immediate(0), + min: Rd::new_imm(0), max: args.next_rd()?, } } @@ -61,12 +59,12 @@ pub(crate) fn parse<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenP "inc" => { let (dst, a) = args.parse_wr_rd()?; - ArithOp::Add { dst, a, b: Rd::immediate(1) } + ArithOp::Add { dst, a, b: Rd::new_imm(1) } } "dec" => { let (dst, a) = args.parse_wr_rd()?; - ArithOp::Sub { dst, a, b: Rd::immediate(1) } + ArithOp::Sub { dst, a, b: Rd::new_imm(1) } } "add" => { @@ -74,6 +72,11 @@ pub(crate) fn parse<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenP ArithOp::Add { dst, a, b } } + "abs" => { + let (dst, a) = args.parse_wr_rd()?; + ArithOp::Abs { dst, a } + } + "sub" => { let (dst, a, b) = args.parse_wr_rd_rd()?; ArithOp::Sub { dst, a, b } @@ -84,6 +87,11 @@ pub(crate) fn parse<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenP ArithOp::Mul { dst, a, b } } + "pow" => { + let (dst, a, pow) = args.parse_wr_rd_rd()?; + ArithOp::Pow { dst, a, pow } + } + "divr" => { match args.len() { 3 => { @@ -191,6 +199,251 @@ pub(crate) fn parse<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenP ArithOp::Rbit { dst, src } } + "cmpf" => { + let parsed = ArithOp::FloatCompare { + a: args.next_rd()?.imm_to_float(), + b: args.next_rd()?.imm_to_float(), + }; + args.ensure_empty("two input arguments")?; + parsed + } + + "frcmp" => { + let parsed = ArithOp::FloatRangeTest { + val: args.next_rd()?.imm_to_float(), + a: args.next_rd()?.imm_to_float(), + b: args.next_rd()?.imm_to_float(), + }; + args.ensure_empty("3 arguments (value, min, max)")?; + parsed + } + + "ftst" => { + let arg = args.next_rd()?; + args.ensure_empty("1 input argument")?; + ArithOp::FloatTest { a: arg.imm_to_float() } + } + + "frng" => { + let parsed = match args.len() { + 1 => { + ArithOp::FloatRng { + dst: args.next_wr()?, + min: Rd::new_float(0.0), + max: Rd::new_float(f64::MAX), + } + } + 2 => { + ArithOp::FloatRng { + dst: args.next_wr()?, + min: Rd::new_float(0.0), + max: args.next_rd()?.imm_to_float(), + } + } + 3 => { + ArithOp::FloatRng { + dst: args.next_wr()?, + min: args.next_rd()?.imm_to_float(), + max: args.next_rd()?.imm_to_float(), + } + } + _ => { + return Err(CrsnError::Parse("Rng requires 1, 2 or 3 arguments".into(), op_pos.clone())); + } + }; + args.ensure_empty("1 (dst) or 3 (dst, min, max) arguments")?; + parsed + } + + "fadd" => { + let (dst, a, b) = args.parse_wr_rd_rd()?; + ArithOp::FloatAdd { + dst, + a: a.imm_to_float(), + b: b.imm_to_float(), + } + } + + "fsub" => { + let (dst, a, b) = args.parse_wr_rd_rd()?; + ArithOp::FloatSub { + dst, + a: a.imm_to_float(), + b: b.imm_to_float(), + } + } + + "fmul" => { + let (dst, a, b) = args.parse_wr_rd_rd()?; + ArithOp::FloatMul { + dst, + a: a.imm_to_float(), + b: b.imm_to_float(), + } + } + + "fpow" => { + let (dst, a, pow) = args.parse_wr_rd_rd()?; + ArithOp::FloatPow { + dst, + a: a.imm_to_float(), + pow: pow.imm_to_float() + } + } + + "froot" => { + let (dst, a, root) = args.parse_wr_rd_rd()?; + ArithOp::FloatRoot { + dst, + a: a.imm_to_float(), + root: root.imm_to_float() + } + } + + "fhyp" => { + let (dst, a, b) = args.parse_wr_rd_rd()?; + ArithOp::FloatHyp { + dst, + a: a.imm_to_float(), + b: a.imm_to_float(), + } + } + + "fdiv" => { + let (dst, a, div) = args.parse_wr_rd_rd()?; + ArithOp::FloatDiv { + dst, + rem: Wr::discard(), + a: a.imm_to_float(), + div: div.imm_to_float(), + } + } + + "fdivr" => { + match args.len() { + 3 => { + let dst = args.next_rdwr()?; + let rem = args.next_wr()?; + let div = args.next_rd()?; + ArithOp::FloatDiv { + dst: dst.wr(), + rem, + a: dst.rd().imm_to_float(), + div: div.imm_to_float(), + } + } + 4 => { + ArithOp::FloatDiv { + dst: args.next_wr()?, + rem: args.next_wr()?, + a: args.next_rd()?.imm_to_float(), + div: args.next_rd()?.imm_to_float(), + } + } + _ => { + return Err(CrsnError::Parse("DivRF requires 3 or 4 arguments".into(), op_pos.clone())); + } + } + } + + "fmod" => { + let (dst, a, div) = args.parse_wr_rd_rd()?; + ArithOp::FloatMod { + dst, + a: a.imm_to_float(), + div: div.imm_to_float(), + } + } + + "itf" => { + let (dst, a) = args.parse_wr_rd()?; + ArithOp::IntToFloat { + dst, + a: a.imm_to_float() + } + } + + "fti" | "ftir" => { + let (dst, a) = args.parse_wr_rd()?; + ArithOp::FloatToInt { + dst, + a: a.imm_to_float(), + mode: FloatToIntMode::Round + } + } + + "ftic" => { + let (dst, a) = args.parse_wr_rd()?; + ArithOp::FloatToInt { + dst, + a: a.imm_to_float(), + mode: FloatToIntMode::Ceil + } + } + + "ftif" => { + let (dst, a) = args.parse_wr_rd()?; + ArithOp::FloatToInt { + dst, + a: a.imm_to_float(), + mode: FloatToIntMode::Floor + } + } + + "fabs" => { + let (dst, a) = args.parse_wr_rd()?; + ArithOp::FloatAbs { dst, a: f.imm_to_float() } + } + + "fsin" => { + let (dst, f) = args.parse_wr_rd()?; + ArithOp::FloatSin { dst, f: f.imm_to_float() } + } + + "fasin" => { + let (dst, a) = args.parse_wr_rd()?; + ArithOp::FloatAsin { dst, a: a.imm_to_float() } + } + + "fcos" => { + let (dst, f) = args.parse_wr_rd()?; + ArithOp::FloatCos { dst, f: f.imm_to_float() } + } + + "facos" => { + let (dst, a) = args.parse_wr_rd()?; + ArithOp::FloatAcos { dst, a: a.imm_to_float() } + } + + "ftan" => { + let (dst, f) = args.parse_wr_rd()?; + ArithOp::FloatTan { dst, f: f.imm_to_float() } + } + + "fatan" => { + let (dst, a) = args.parse_wr_rd()?; + ArithOp::FloatAtan { dst, a: a.imm_to_float() } + } + + "fatan2" => { + let (dst, a, b) = args.parse_wr_rd_rd()?; + ArithOp::FloatAtan2 { + dst, + y: a.imm_to_float(), + x: b.imm_to_float(), + } + } + + "fcot" => { + let (dst, f) = args.parse_wr_rd()?; + ArithOp::FloatCot { dst, f: f.imm_to_float() } + } + + "facot" => { + let (dst, a) = args.parse_wr_rd()?; + ArithOp::FloatAcot { dst, a: a.imm_to_float() } + } + other => { if let Some((dst, src, mask)) = args.parse_masked_wr_rd(other, "clz")? { if !dst.disp_equals(src) && mask.dst_pos != 0 { diff --git a/crsn_buf/src/parse.rs b/crsn_buf/src/parse.rs index 10e04ac..209967b 100644 --- a/crsn_buf/src/parse.rs +++ b/crsn_buf/src/parse.rs @@ -21,7 +21,7 @@ pub(crate) fn parse<'a>(_pos: &SourcePosition, keyword: &str, mut args: TokenPar let value = match args.next() { None => { - BufValue::Zeros(Rd::immediate(0)) + BufValue::Zeros(Rd::new_imm(0)) } Some(tok @ Sexp::Atom(Atom::S(_), _)) | Some(tok @ Sexp::Atom(Atom::I(_), _)) | @@ -112,7 +112,7 @@ pub(crate) fn parse<'a>(_pos: &SourcePosition, keyword: &str, mut args: TokenPar "bfrpush" => { BufOps::Insert { obj: args.next_rdobj()?, - idx: Rd::immediate(0), + idx: Rd::new_imm(0), value: args.next_rd()?, } } @@ -121,7 +121,7 @@ pub(crate) fn parse<'a>(_pos: &SourcePosition, keyword: &str, mut args: TokenPar BufOps::Remove { dst: args.next_wr()?, obj: args.next_rdobj()?, - idx: Rd::immediate(0), + idx: Rd::new_imm(0), } } diff --git a/crsn_screen/src/parse.rs b/crsn_screen/src/parse.rs index 95c0d5b..9f6fb78 100644 --- a/crsn_screen/src/parse.rs +++ b/crsn_screen/src/parse.rs @@ -24,7 +24,7 @@ pub(crate) fn parse<'a>(_pos: &SourcePosition, keyword: &str, mut args: TokenPar color: if args.len() > 0 { args.next_rd()? } else { - Rd::immediate(0) // black + Rd::new_imm(0) // black }, } } @@ -60,7 +60,7 @@ pub(crate) fn parse<'a>(_pos: &SourcePosition, keyword: &str, mut args: TokenPar force: if args.have_more() { args.next_rd()? } else { - Rd::immediate(1) + Rd::new_imm(1) }, } }