Skip to content

Commit

Permalink
Merge pull request #117 from AluVM/macroasm
Browse files Browse the repository at this point in the history
Improvements to macro assembly
  • Loading branch information
dr-orlovsky authored May 6, 2024
2 parents 32234e4 + 4058c09 commit e654e88
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 52 deletions.
18 changes: 9 additions & 9 deletions src/isa/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ impl Bytecode for ControlFlowOp {
fn instr_byte(&self) -> u8 {
match self {
ControlFlowOp::Fail => INSTR_FAIL,
ControlFlowOp::Succ => INSTR_SUCC,
ControlFlowOp::Test => INSTR_TEST,
ControlFlowOp::Jmp(_) => INSTR_JMP,
ControlFlowOp::Jif(_) => INSTR_JIF,
ControlFlowOp::Routine(_) => INSTR_ROUTINE,
Expand All @@ -242,7 +242,7 @@ impl Bytecode for ControlFlowOp {
{
match self {
ControlFlowOp::Fail => {}
ControlFlowOp::Succ => {}
ControlFlowOp::Test => {}
ControlFlowOp::Jmp(pos) | ControlFlowOp::Jif(pos) | ControlFlowOp::Routine(pos) => {
writer.write_u16(*pos)?
}
Expand All @@ -261,7 +261,7 @@ impl Bytecode for ControlFlowOp {
{
Ok(match reader.read_u8()? {
INSTR_FAIL => Self::Fail,
INSTR_SUCC => Self::Succ,
INSTR_TEST => Self::Test,
INSTR_JMP => Self::Jmp(reader.read_u16()?),
INSTR_JIF => Self::Jif(reader.read_u16()?),
INSTR_ROUTINE => Self::Routine(reader.read_u16()?),
Expand Down Expand Up @@ -1043,8 +1043,8 @@ impl Bytecode for BytesOp {
writer.write_bool(false)?;
}
BytesOp::Extr(src, dst, index, offset) | BytesOp::Inj(src, dst, index, offset) => {
writer.write_u5(src)?;
writer.write_u3(dst)?;
writer.write_u4(src)?;
writer.write_u4(dst)?;
writer.write_u4(index)?;
writer.write_u4(offset)?;
}
Expand Down Expand Up @@ -1126,14 +1126,14 @@ impl Bytecode for BytesOp {
op
}
INSTR_EXTR => Self::Extr(
reader.read_u5()?.into(),
reader.read_u3()?.into(),
reader.read_u4()?.into(),
reader.read_u4()?.into(),
reader.read_u4()?.into(),
reader.read_u4()?.into(),
),
INSTR_INJ => Self::Inj(
reader.read_u5()?.into(),
reader.read_u3()?.into(),
reader.read_u4()?.into(),
reader.read_u4()?.into(),
reader.read_u4()?.into(),
reader.read_u4()?.into(),
),
Expand Down
19 changes: 12 additions & 7 deletions src/isa/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,12 @@ impl InstructionSet for ControlFlowOp {
regs.st0 = false;
ExecStep::Stop
}
ControlFlowOp::Succ => {
regs.st0 = true;
ExecStep::Stop
ControlFlowOp::Test => {
if regs.st0 {
ExecStep::Next
} else {
ExecStep::Stop
}
}
ControlFlowOp::Jmp(offset) => {
regs.jmp().map(|_| ExecStep::Jump(*offset)).unwrap_or(ExecStep::Stop)
Expand Down Expand Up @@ -1317,7 +1320,7 @@ impl InstructionSet for BytesOp {
let offset = regs.a16[*offset as u8 as usize].filter(|e| *e < s_len)?;
let end = offset
.checked_add(dst.layout().bytes())
.filter(|e| *e < s_len)
.filter(|e| *e <= s_len)
.unwrap_or_else(|| {
regs.st0 = false;
s_len
Expand Down Expand Up @@ -1775,7 +1778,9 @@ mod tests {
assert_eq!(register.get_n(RegA::A16, Reg32::Reg1), MaybeNumber::none());
assert_eq!(register.get_n(RegA::A16, Reg32::Reg2), MaybeNumber::none());
assert!(!register.st0);
ControlFlowOp::Succ.exec(&mut register, lib_site, &());
CmpOp::StInv.exec(&mut register, lib_site, &());
assert!(register.st0);
ControlFlowOp::Test.exec(&mut register, lib_site, &());

let s1 = [0u8; u16::MAX as usize];
let s2 = [0u8; u16::MAX as usize];
Expand Down Expand Up @@ -1903,8 +1908,8 @@ mod tests {
&(),
);
assert!(!register.st0);
ControlFlowOp::Succ.exec(&mut register, lib_site, &());
assert!(register.st0);
ControlFlowOp::Test.exec(&mut register, lib_site, &());
assert!(!register.st0);
CmpOp::EqR(NoneEqFlag::NonEqual, RegR::R512, Reg32::Reg0, Reg32::Reg2).exec(
&mut register,
lib_site,
Expand Down
37 changes: 19 additions & 18 deletions src/isa/instr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,10 @@ pub enum ControlFlowOp {
#[display("fail")]
Fail,

/// Completes program execution writing `true` to `st0` (indicating program success). Does not
/// modify value of call stack registers.
#[display("succ")]
Succ,
/// Checks the value of `st0` register. If the value is `false`, stops execution of the
/// program. Otherwise, it is a no-operation.
#[display("test")]
Test,

/// Unconditionally jumps to an offset. Increments `cy0`.
#[display("jmp {0:#06X}")]
Expand Down Expand Up @@ -421,35 +421,35 @@ pub enum CmpOp {
/// `wrap` flag is provided).
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Display)]
pub enum ArithmeticOp {
/// Adds values from two integer arithmetic registers and puts result into the first register.
/// Adds values from two integer arithmetic registers and puts result into the second register.
#[display("add.{0} {1}{2},{1}{3}")]
AddA(IntFlags, RegA, Reg32, Reg32),

/// Adds values from two float arithmetic registers and puts result into the first register.
/// Adds values from two float arithmetic registers and puts result into the second register.
#[display("add.{0} {1}{2},{1}{3}")]
AddF(RoundingFlag, RegF, Reg32, Reg32),

/// Subtracts values from two integer arithmetic registers and puts result into the first
/// Subtracts values from two integer arithmetic registers and puts result into the second
/// register.
#[display("sub.{0} {1}{2},{1}{3}")]
SubA(IntFlags, RegA, Reg32, Reg32),

/// Subtracts values from two float arithmetic registers and puts result into the first
/// Subtracts values from two float arithmetic registers and puts result into the second
/// register.
#[display("sub.{0} {1}{2},{1}{3}")]
SubF(RoundingFlag, RegF, Reg32, Reg32),

/// Multiplies values from two integer arithmetic registers and puts result into the first
/// Multiplies values from two integer arithmetic registers and puts result into the second
/// register.
#[display("mul.{0} {1}{2},{1}{3}")]
MulA(IntFlags, RegA, Reg32, Reg32),

/// Multiplies values from two float arithmetic registers and puts result into the first
/// Multiplies values from two float arithmetic registers and puts result into the second
/// register.
#[display("mul.{0} {1}{2},{1}{3}")]
MulF(RoundingFlag, RegF, Reg32, Reg32),

/// Divides values from two integer arithmetic registers and puts result into the first
/// Divides values from two integer arithmetic registers and puts result into the second
/// register.
///
/// Since the division operation may not result in overflow, the overflow flag is used to
Expand All @@ -462,14 +462,15 @@ pub enum ArithmeticOp {
#[display("div.{0} {1}{2},{1}{3}")]
DivA(IntFlags, RegA, Reg32, Reg32),

/// Divides values from two float arithmetic registers and puts result into the first register.
/// Divides values from two float arithmetic registers and puts result into the second
/// register.
#[display("div.{0} {1}{2},{1}{3}")]
DivF(RoundingFlag, RegF, Reg32, Reg32),

/// Modulo division.
///
/// Puts a reminder of the division of source register on destination register into the
/// the first register.
/// second register.
#[display("rem {0}{1},{2}{3}")]
Rem(RegA, Reg32, RegA, Reg32),

Expand Down Expand Up @@ -697,18 +698,18 @@ pub enum BytesOp {
/// If the source string register - or offset register is uninitialized, sets destination to
/// uninitialized state and `st0` to `false`.
#[display("extr {0},{1}{2},a16{3}")]
Extr(/** `s` register index */ RegS, RegR, Reg16, /** `a16` register with offset */ Reg16),
Extr(/** `s` register index */ RegS, RegAR, Reg16, /** `a16` register with offset */ Reg16),

/// Inject general `R` register value at a given position to string register, replacing value
/// of the corresponding bytes. If the insert offset is larger than the current length of the
/// string, the length is extended and all bytes inbetween previous length and the new length
/// are initialized with zeros. If the length of the inserted string plus insert offset exceeds
/// the maximum string register length (2^16 bytes), than the destination register is set to
/// the maximum string register length (2^16 bytes), then the destination register is set to
/// `None` state and `st0` is set to `false`. Otherwise, `st0` value is not modified.
#[display("inj {0},{1}{2},{1}{3}")]
Inj(
/** `s` register index acting as the source and destination */ RegS,
RegR,
RegAR,
Reg16,
/** `a16` register with offset */ Reg16,
),
Expand Down Expand Up @@ -753,7 +754,7 @@ pub enum BytesOp {
/// Rule on `st0` changes: if at least one of the destination registers is set to `None`, or
/// `offset` value exceeds source string length, `st0` is set to `false`; otherwise its value
/// is not modified
#[display("splt.{2} {0},a16{1},{3},{4}")]
#[display("splt.{0} {2},a16{1},{3},{4}")]
Splt(
SplitFlag,
/** `a16` register index with offset value */ Reg32,
Expand Down Expand Up @@ -791,7 +792,7 @@ pub enum BytesOp {
/// </pre>
///
/// In all of these cases `st0` is set to `false`. Otherwise, `st0` value is not modified.
#[display("ins.{3} {0},{1},a16{2}")]
#[display("ins.{0} {1},a16{2},{2}")]
Ins(
InsertFlag,
/** `a16` register index with offset value for insert location */ Reg32,
Expand Down
Loading

0 comments on commit e654e88

Please sign in to comment.