forked from MightyPork/crsn
add new rdwr access type to guard against illegal writes that can be caught at compile time
This commit is contained in:
@@ -6,6 +6,7 @@ pub use rd::Rd;
|
|||||||
pub use rd::RdObj;
|
pub use rd::RdObj;
|
||||||
pub use reg::Register;
|
pub use reg::Register;
|
||||||
pub use wr::Wr;
|
pub use wr::Wr;
|
||||||
|
pub use rdwr::RdWr;
|
||||||
|
|
||||||
use crate::asm::data::literal::{as_signed, is_negative, Value};
|
use crate::asm::data::literal::{as_signed, is_negative, Value};
|
||||||
|
|
||||||
@@ -15,8 +16,8 @@ pub mod literal;
|
|||||||
pub mod reg;
|
pub mod reg;
|
||||||
|
|
||||||
mod rd;
|
mod rd;
|
||||||
|
|
||||||
mod wr;
|
mod wr;
|
||||||
|
mod rdwr;
|
||||||
|
|
||||||
/// Data source disposition
|
/// Data source disposition
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||||
@@ -134,6 +135,12 @@ pub enum WrData {
|
|||||||
Discard,
|
Discard,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WrData {
|
||||||
|
pub fn is_readable(self) -> bool {
|
||||||
|
self != Self::Discard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for WrData {
|
impl Display for WrData {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
|||||||
@@ -12,9 +12,6 @@ impl Rd {
|
|||||||
pub const fn new(src: RdData) -> Self {
|
pub const fn new(src: RdData) -> Self {
|
||||||
Rd(src)
|
Rd(src)
|
||||||
}
|
}
|
||||||
pub const fn data(self) -> RdData {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
pub const fn immediate(val: Value) -> Rd {
|
pub const fn immediate(val: Value) -> Rd {
|
||||||
Rd(RdData::Immediate(val))
|
Rd(RdData::Immediate(val))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use crate::asm::data::{Rd, WrData, Wr};
|
||||||
|
|
||||||
|
/// Data destination argument (read-write)
|
||||||
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||||
|
pub struct RdWr(pub WrData);
|
||||||
|
|
||||||
|
impl RdWr {
|
||||||
|
pub fn new(dst: WrData) -> Self {
|
||||||
|
if !dst.is_readable() {
|
||||||
|
panic!("Not readable: {}", dst);
|
||||||
|
}
|
||||||
|
RdWr(dst)
|
||||||
|
}
|
||||||
|
pub fn wr(self) -> Wr {
|
||||||
|
Wr(self.0)
|
||||||
|
}
|
||||||
|
pub fn rd(self) -> Rd {
|
||||||
|
Rd(self.0.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RdWr> for Rd {
|
||||||
|
fn from(rdwr: RdWr) -> Self {
|
||||||
|
rdwr.rd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RdWr> for Wr {
|
||||||
|
fn from(rdwr: RdWr) -> Self {
|
||||||
|
rdwr.wr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&RdWr> for Rd {
|
||||||
|
fn from(rdwr: &RdWr) -> Self {
|
||||||
|
rdwr.rd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&RdWr> for Wr {
|
||||||
|
fn from(rdwr: &RdWr) -> Self {
|
||||||
|
rdwr.wr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for RdWr {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for RdWr {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "RdWr({})", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,21 +5,22 @@ use crate::asm::data::{Rd, WrData};
|
|||||||
|
|
||||||
/// Data destination argument (read-write)
|
/// Data destination argument (read-write)
|
||||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||||
pub struct Wr(WrData);
|
pub struct Wr(pub WrData);
|
||||||
|
|
||||||
impl Wr {
|
impl Wr {
|
||||||
pub fn new(dst: WrData) -> Self {
|
pub fn new(dst: WrData) -> Self {
|
||||||
Wr(dst)
|
Wr(dst)
|
||||||
}
|
}
|
||||||
pub fn d(self) -> WrData {
|
pub fn discard() -> Wr {
|
||||||
self.0
|
Wr(WrData::Discard)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_rd(self) -> Rd {
|
pub fn as_rd(self) -> Rd {
|
||||||
Rd(self.0.into())
|
Rd(self.0.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn discard() -> Wr {
|
pub fn is_readable(self) -> bool {
|
||||||
Wr(WrData::Discard)
|
self.0.is_readable()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_discard(self) -> bool {
|
pub fn is_discard(self) -> bool {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use sexp::{Sexp, SourcePosition};
|
use sexp::{Sexp, SourcePosition};
|
||||||
|
|
||||||
use crate::asm::data::{Rd, RdData, RdObj, Wr};
|
use crate::asm::data::{Rd, RdData, RdObj, Wr, RdWr};
|
||||||
use crate::asm::error::CrsnError;
|
use crate::asm::error::CrsnError;
|
||||||
use crate::asm::parse::parse_data::{parse_rd, parse_wr};
|
use crate::asm::parse::parse_data::{parse_rd, parse_wr};
|
||||||
use crate::asm::parse::ParserContext;
|
use crate::asm::parse::ParserContext;
|
||||||
@@ -109,4 +109,17 @@ impl<'a> TokenParser<'a> {
|
|||||||
pub fn next_wr(&mut self) -> Result<Wr, CrsnError> {
|
pub fn next_wr(&mut self) -> Result<Wr, CrsnError> {
|
||||||
parse_wr(self.next_or_err()?, self.pcx)
|
parse_wr(self.next_or_err()?, self.pcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the next entry as write location
|
||||||
|
pub fn next_rdwr(&mut self) -> Result<RdWr, CrsnError> {
|
||||||
|
let next = self.next_or_err()?;
|
||||||
|
let pos = next.pos().clone();
|
||||||
|
let wr = parse_wr(next, self.pcx)?;
|
||||||
|
|
||||||
|
if !wr.is_readable() {
|
||||||
|
return Err(CrsnError::Parse("Argument is not readable!".into(), pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(RdWr::new(wr.0))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use sexp::SourcePosition;
|
use sexp::SourcePosition;
|
||||||
|
|
||||||
use crate::asm::data::{Rd, RdObj, Wr};
|
use crate::asm::data::{Rd, RdObj, Wr, RdWr};
|
||||||
use crate::asm::data::literal::{DebugMsg, Label, RoutineName};
|
use crate::asm::data::literal::{DebugMsg, Label, RoutineName};
|
||||||
use crate::asm::instr::Op;
|
use crate::asm::instr::Op;
|
||||||
use crate::asm::instr::op::OpKind;
|
use crate::asm::instr::op::OpKind;
|
||||||
@@ -73,7 +73,7 @@ pub enum BuiltinOp {
|
|||||||
/// Copy value
|
/// Copy value
|
||||||
MoveValue { dst: Wr, src: Rd },
|
MoveValue { dst: Wr, src: Rd },
|
||||||
/// Swap two registers
|
/// Swap two registers
|
||||||
SwapValues { a: Wr, b: Wr },
|
SwapValues { a: RdWr, b: RdWr },
|
||||||
/// Store runtime status to a register
|
/// Store runtime status to a register
|
||||||
StoreFlags { dst: Wr },
|
StoreFlags { dst: Wr },
|
||||||
/// Load runtime status from a register
|
/// Load runtime status from a register
|
||||||
|
|||||||
@@ -110,10 +110,10 @@ impl OpTrait for BuiltinOp {
|
|||||||
state.write(*dst, val)?;
|
state.write(*dst, val)?;
|
||||||
}
|
}
|
||||||
BuiltinOp::SwapValues { a, b } => {
|
BuiltinOp::SwapValues { a, b } => {
|
||||||
let aa = state.read(a.as_rd())?;
|
let aa = state.read(a)?;
|
||||||
let bb = state.read(b.as_rd())?;
|
let bb = state.read(b)?;
|
||||||
state.write(*a, bb)?;
|
state.write(a, bb)?;
|
||||||
state.write(*b, aa)?;
|
state.write(b, aa)?;
|
||||||
}
|
}
|
||||||
BuiltinOp::StoreFlags { dst } => {
|
BuiltinOp::StoreFlags { dst } => {
|
||||||
let packed = state.frame.status.store();
|
let packed = state.frame.status.store();
|
||||||
|
|||||||
@@ -185,8 +185,8 @@ pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: Tok
|
|||||||
|
|
||||||
"swap" => {
|
"swap" => {
|
||||||
BuiltinOp::SwapValues {
|
BuiltinOp::SwapValues {
|
||||||
a: args.next_wr()?,
|
a: args.next_rdwr()?,
|
||||||
b: args.next_wr()?,
|
b: args.next_rdwr()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,8 +93,9 @@ impl RunState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Read a `Rd` value
|
/// Read a `Rd` value
|
||||||
pub fn read(&mut self, rd: Rd) -> Result<Value, Fault> {
|
pub fn read(&mut self, rd: impl Into<Rd>) -> Result<Value, Fault> {
|
||||||
match rd.data() {
|
let rd = rd.into();
|
||||||
|
match rd.0 {
|
||||||
RdData::Register(Register::Gen(rn)) => {
|
RdData::Register(Register::Gen(rn)) => {
|
||||||
if likely(rn < REG_COUNT as u8) {
|
if likely(rn < REG_COUNT as u8) {
|
||||||
trace!("Rd {:?} = {}", rd, self.frame.gen[rn as usize]);
|
trace!("Rd {:?} = {}", rd, self.frame.gen[rn as usize]);
|
||||||
@@ -161,10 +162,12 @@ impl RunState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Write a value to a `Wr` location
|
/// Write a value to a `Wr` location
|
||||||
pub fn write(&mut self, wr: Wr, val: Value) -> Result<(), Fault> {
|
pub fn write(&mut self, wr: impl Into<Wr>, val: Value) -> Result<(), Fault> {
|
||||||
|
let wr = wr.into();
|
||||||
|
|
||||||
trace!("WR {:?} := {}", wr, val);
|
trace!("WR {:?} := {}", wr, val);
|
||||||
|
|
||||||
match wr.d() {
|
match wr.0 {
|
||||||
WrData::Register(Register::Gen(rn)) => {
|
WrData::Register(Register::Gen(rn)) => {
|
||||||
if likely(rn < REG_COUNT as u8) {
|
if likely(rn < REG_COUNT as u8) {
|
||||||
self.frame.gen[rn as usize] = val;
|
self.frame.gen[rn as usize] = val;
|
||||||
|
|||||||
+66
-66
@@ -30,19 +30,19 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
|||||||
}
|
}
|
||||||
|
|
||||||
"inc" => {
|
"inc" => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Add {
|
ArithOp::Add {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
b: Rd::immediate(1),
|
b: Rd::immediate(1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"dec" => {
|
"dec" => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Sub {
|
ArithOp::Sub {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
b: Rd::immediate(1),
|
b: Rd::immediate(1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,10 +57,10 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Add {
|
ArithOp::Add {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
b: args.next_rd()?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,10 +80,10 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Sub {
|
ArithOp::Sub {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
b: args.next_rd()?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,10 +103,10 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Mul {
|
ArithOp::Mul {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
b: args.next_rd()?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,13 +119,13 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
|||||||
"divr" => {
|
"divr" => {
|
||||||
match args.len() {
|
match args.len() {
|
||||||
3 => {
|
3 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
let rem = args.next_wr()?;
|
let rem = args.next_wr()?;
|
||||||
let div = args.next_rd()?;
|
let div = args.next_rd()?;
|
||||||
ArithOp::Div {
|
ArithOp::Div {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
rem,
|
rem,
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
div,
|
div,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,12 +154,12 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
let div = args.next_rd()?;
|
let div = args.next_rd()?;
|
||||||
ArithOp::Div {
|
ArithOp::Div {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
rem: Wr::discard(),
|
rem: Wr::discard(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
div,
|
div,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,11 +179,11 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
let div = args.next_rd()?;
|
let div = args.next_rd()?;
|
||||||
ArithOp::Mod {
|
ArithOp::Mod {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
div,
|
div,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,10 +203,10 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::And {
|
ArithOp::And {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
b: args.next_rd()?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,10 +226,10 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Or {
|
ArithOp::Or {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
b: args.next_rd()?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,10 +249,10 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Xor {
|
ArithOp::Xor {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
b: args.next_rd()?,
|
b: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -271,10 +271,10 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Cpl {
|
ArithOp::Cpl {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -293,18 +293,18 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Rol {
|
ArithOp::Rol {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
n: args.next_rd()?,
|
n: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Rol {
|
ArithOp::Rol {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
n: Rd::immediate(1),
|
n: Rd::immediate(1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -324,18 +324,18 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Ror {
|
ArithOp::Ror {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
n: args.next_rd()?,
|
n: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Ror {
|
ArithOp::Ror {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
n: Rd::immediate(1),
|
n: Rd::immediate(1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -355,18 +355,18 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Lsl {
|
ArithOp::Lsl {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
n: args.next_rd()?,
|
n: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Lsl {
|
ArithOp::Lsl {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
n: Rd::immediate(1),
|
n: Rd::immediate(1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -386,18 +386,18 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Lsr {
|
ArithOp::Lsr {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
n: args.next_rd()?,
|
n: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Lsr {
|
ArithOp::Lsr {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
n: Rd::immediate(1),
|
n: Rd::immediate(1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -417,18 +417,18 @@ pub(crate) fn parse<'a>(pos: &SourcePosition, keyword: &str, mut args: TokenPars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Asr {
|
ArithOp::Asr {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
n: args.next_rd()?,
|
n: args.next_rd()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let dst = args.next_wr()?;
|
let dst = args.next_rdwr()?;
|
||||||
ArithOp::Asr {
|
ArithOp::Asr {
|
||||||
dst,
|
dst: dst.wr(),
|
||||||
a: dst.as_rd(),
|
a: dst.rd(),
|
||||||
n: Rd::immediate(1),
|
n: Rd::immediate(1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user