#![deny(
clippy::unwrap_used,
clippy::expect_used,
clippy::panic,
clippy::unreachable
)]
use super::super::MMixAssembler;
use super::super::Rule;
use super::super::operands::ZForm;
use super::super::tree::Children;
use super::MMixInstruction;
impl MMixAssembler {
fn parse_trap_family_operands(
&self,
pair: pest::iterators::Pair<Rule>,
mnem: &str,
) -> Result<(u8, u8, u8), String> {
let mut parts = Children::of(pair);
let _mnem = parts.next();
let Some(operands) = parts.next() else {
return Ok((0, 0, 0));
};
match operands.as_rule() {
Rule::operand_list_three => {
let mut ops = Children::of(operands);
let x = self.parse_reg_or_byte(ops.required()?, mnem)?;
let y = self.parse_reg_or_byte(ops.required()?, mnem)?;
let z = self.parse_reg_or_byte(ops.required()?, mnem)?;
Ok((x, y, z))
}
Rule::operand_list_two => {
let mut ops = Children::of(operands);
let x = self.parse_reg_or_byte(ops.required()?, mnem)?;
let yz = self.imm_wyde(ops.required()?, mnem)?;
let (y, z) = Self::split_hi_lo_byte(yz);
Ok((x, y, z))
}
Rule::operand_list_one => {
let mut ops = Children::of(operands);
let xyz = self.imm_three_bytes(ops.required()?, mnem)?;
let (x, y, z) = Self::split_xyz_bytes(xyz);
Ok((x, y, z))
}
_ => Err(parts.unexpected(&operands)),
}
}
pub(super) fn parse_inst_trap(
&self,
pair: pest::iterators::Pair<Rule>,
) -> Result<MMixInstruction, String> {
let (x, y, z) = self.parse_trap_family_operands(pair, "TRAP")?;
Ok(MMixInstruction::TRAP(x, y, z))
}
pub(super) fn parse_inst_get(
&self,
pair: pest::iterators::Pair<Rule>,
) -> Result<MMixInstruction, String> {
let mut parts = Children::of(pair);
let _mnem = parts.next();
let mut ops = Children::of(parts.required()?);
let x = self.parse_register(ops.required()?)?;
let z = self.special_register(ops.required()?, "GET")?;
Ok(MMixInstruction::GET(x, z))
}
pub(super) fn parse_inst_put_auto(
&self,
pair: pest::iterators::Pair<Rule>,
) -> Result<MMixInstruction, String> {
let mut parts = Children::of(pair);
let _mnem = parts.next();
let mut ops = Children::of(parts.required()?);
let x = self.special_register(ops.required()?, "PUT")?;
match self.lower_z_operand(ops.required()?, "PUT")? {
ZForm::Reg(z) => Ok(MMixInstruction::PUT(x, z)),
ZForm::Imm(z) => Ok(MMixInstruction::PUTI(x, z)),
}
}
pub(super) fn parse_inst_puti(
&self,
pair: pest::iterators::Pair<Rule>,
) -> Result<MMixInstruction, String> {
let mut parts = Children::of(pair);
let _mnem = parts.next();
let mut ops = Children::of(parts.required()?);
let x = self.special_register(ops.required()?, "PUTI")?;
let z = self.imm_byte(ops.required()?, "PUTI")?;
Ok(MMixInstruction::PUTI(x, z))
}
pub(super) fn parse_inst_save(
&self,
pair: pest::iterators::Pair<Rule>,
) -> Result<MMixInstruction, String> {
let mut parts = Children::of(pair);
let _mnem = parts.next();
let mut ops = Children::of(parts.required()?);
let x = self.parse_register(ops.required()?)?;
let z = self.imm_byte(ops.required()?, "SAVE")?;
Ok(MMixInstruction::SAVE(x, z))
}
pub(super) fn parse_inst_unsave(
&self,
pair: pest::iterators::Pair<Rule>,
) -> Result<MMixInstruction, String> {
let mut parts = Children::of(pair);
let _mnem = parts.next();
let operands = parts.required()?;
match operands.as_rule() {
Rule::operand_list_two => {
let mut ops = Children::of(operands);
let x = self.imm_byte(ops.required()?, "UNSAVE")?;
let z = self.parse_register(ops.required()?)?;
Ok(MMixInstruction::UNSAVE(x, z))
}
Rule::operand_list_one => {
let mut ops = Children::of(operands);
let z = self.parse_register(ops.required()?)?;
Ok(MMixInstruction::UNSAVE(0, z))
}
_ => Err(parts.unexpected(&operands)),
}
}
pub(super) fn parse_inst_resume(
&self,
pair: pest::iterators::Pair<Rule>,
) -> Result<MMixInstruction, String> {
let mut parts = Children::of(pair);
let _mnem = parts.next();
let xyz = match parts.next() {
Some(op) => self.imm_three_bytes(Children::of(op).required()?, "RESUME")?,
None => 0,
};
Ok(MMixInstruction::RESUME(xyz))
}
pub(super) fn parse_inst_trip(
&self,
pair: pest::iterators::Pair<Rule>,
) -> Result<MMixInstruction, String> {
let (x, y, z) = self.parse_trap_family_operands(pair, "TRIP")?;
Ok(MMixInstruction::TRIP(x, y, z))
}
pub(super) fn parse_inst_swym(
&self,
pair: pest::iterators::Pair<Rule>,
) -> Result<MMixInstruction, String> {
let (x, y, z) = self.parse_trap_family_operands(pair, "SWYM")?;
Ok(MMixInstruction::SWYM(x, y, z))
}
pub(super) fn parse_inst_sync(
&self,
pair: pest::iterators::Pair<Rule>,
) -> Result<MMixInstruction, String> {
let mut parts = Children::of(pair);
let _mnem = parts.next();
let xyz = match parts.next() {
Some(op) => self.imm_three_bytes(Children::of(op).required()?, "SYNC")?,
None => 0,
};
Ok(MMixInstruction::SYNC(xyz))
}
}