- updated assembler to support new shift implementation
- updated emulator to support new shift implementation - updated emulator to rename NoReg to Null as in the common lib
This commit is contained in:
@@ -223,19 +223,31 @@ fn build_shift_instruction(
|
|||||||
opcode: Opcode,
|
opcode: Opcode,
|
||||||
args: &[crate::assembler::model::Token],
|
args: &[crate::assembler::model::Token],
|
||||||
) -> Result<Instruction, AssembleError> {
|
) -> Result<Instruction, AssembleError> {
|
||||||
let Some(reg_token) = args.first() else {
|
let Some(src_reg) = args.first() else {
|
||||||
return Err(AssembleError::MissingArgument(0));
|
return Err(AssembleError::MissingArgument(0));
|
||||||
};
|
};
|
||||||
let Some(amount_token) = args.get(1) else {
|
let Some(r_shamt) = args.get(1) else {
|
||||||
|
return Err(AssembleError::MissingArgument(0));
|
||||||
|
};
|
||||||
|
let Some(i_shamt) = args.get(2) else {
|
||||||
|
return Err(AssembleError::MissingArgument(1));
|
||||||
|
};
|
||||||
|
let Some(dest_reg) = args.get(3) else {
|
||||||
return Err(AssembleError::MissingArgument(1));
|
return Err(AssembleError::MissingArgument(1));
|
||||||
};
|
};
|
||||||
|
|
||||||
let reg = expect_token!(reg_token, Register)?;
|
let src = expect_token!(src_reg, Register)?;
|
||||||
let amount = expect_token!(amount_token, Immediate)? as u8;
|
let r_shamt = expect_token!(r_shamt, Register)?;
|
||||||
|
let i_shamt = expect_token!(i_shamt, Immediate)? as u8;
|
||||||
|
let dest = expect_token!(dest_reg, Register)?;
|
||||||
|
|
||||||
match opcode {
|
match opcode {
|
||||||
Opcode::Shl => Ok(Instruction::ShiftLeft(args!(R, sr1: reg, shamt: amount))),
|
Opcode::Shl => Ok(Instruction::ShiftLeft(
|
||||||
Opcode::Shr => Ok(Instruction::ShiftRight(args!(R, sr1: reg, shamt: amount))),
|
args!(R, sr1: src, sr2: r_shamt, shamt: i_shamt, dr: dest),
|
||||||
|
)),
|
||||||
|
Opcode::Shr => Ok(Instruction::ShiftRight(
|
||||||
|
args!(R, sr1: src, sr2: r_shamt, shamt: i_shamt, dr: dest),
|
||||||
|
)),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use crate::assembler::TokenType;
|
||||||
use crate::{assembler::AssembleError, expect_token, expect_type, node};
|
use crate::{assembler::AssembleError, expect_token, expect_type, node};
|
||||||
|
|
||||||
use crate::assembler::model::{Node, Opcode, Token};
|
use crate::assembler::model::{Node, Opcode, Token};
|
||||||
@@ -114,9 +115,10 @@ impl Parser {
|
|||||||
|
|
||||||
let mut offset = Token::Immediate(0);
|
let mut offset = Token::Immediate(0);
|
||||||
if let Ok(next) = self.peek_next()
|
if let Ok(next) = self.peek_next()
|
||||||
&& expect_type!(next, Immediate).is_ok() {
|
&& expect_type!(next, Immediate).is_ok()
|
||||||
offset = self.next()?;
|
{
|
||||||
}
|
offset = self.next()?;
|
||||||
|
}
|
||||||
|
|
||||||
args = vec![base, dest, offset];
|
args = vec![base, dest, offset];
|
||||||
}
|
}
|
||||||
@@ -125,9 +127,10 @@ impl Parser {
|
|||||||
let dest = expect_type!(self.next()?, Register, Symbol)?;
|
let dest = expect_type!(self.next()?, Register, Symbol)?;
|
||||||
let mut offset = Token::Immediate(0);
|
let mut offset = Token::Immediate(0);
|
||||||
if let Ok(next) = self.peek_next()
|
if let Ok(next) = self.peek_next()
|
||||||
&& expect_type!(next, Immediate).is_ok() {
|
&& expect_type!(next, Immediate).is_ok()
|
||||||
offset = self.next()?;
|
{
|
||||||
}
|
offset = self.next()?;
|
||||||
|
}
|
||||||
args = vec![base, dest, offset];
|
args = vec![base, dest, offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,15 +149,49 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Opcode::Not | Opcode::Cmp => {
|
Opcode::Not | Opcode::Cmp => {
|
||||||
let reg1 = expect_type!(self.next()?, Register, Symbol)?;
|
let src = expect_type!(self.next()?, Register, Symbol)?;
|
||||||
let reg2 = expect_type!(self.next()?, Register, Symbol)?;
|
let dest = expect_type!(self.next()?, Register, Symbol)?;
|
||||||
args = vec![reg1, reg2];
|
args = vec![src, dest];
|
||||||
}
|
}
|
||||||
|
|
||||||
Opcode::Shl | Opcode::Shr => {
|
Opcode::Shl | Opcode::Shr => {
|
||||||
let reg = expect_type!(self.next()?, Register, Symbol)?;
|
let src = expect_type!(self.next()?, Register, Symbol)?;
|
||||||
let num = expect_type!(self.next()?, Immediate)?;
|
|
||||||
args = vec![reg, num];
|
// First operand after src: could be immediate or register
|
||||||
|
let first = self.next()?;
|
||||||
|
|
||||||
|
let (r_shamt, i_shamt) = match first {
|
||||||
|
Token::Register(_) => (
|
||||||
|
first,
|
||||||
|
if let Ok(tok) = self.peek_next() {
|
||||||
|
if expect_type!(tok, Immediate).is_ok() {
|
||||||
|
self.next()?
|
||||||
|
} else {
|
||||||
|
Token::Immediate(0)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Token::Immediate(0)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Token::Immediate(_) => (Token::Register(Register::Zero), first),
|
||||||
|
_ => {
|
||||||
|
return Err(AssembleError::UnexpectedToken(
|
||||||
|
first,
|
||||||
|
TokenType::Immediate,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let dest = if let Ok(tok) = self.peek_next() {
|
||||||
|
if expect_type!(tok, Register).is_ok() {
|
||||||
|
self.next()?
|
||||||
|
} else {
|
||||||
|
src.clone() // Default to src if no dest specified
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
src.clone() // Default to src if no dest specified
|
||||||
|
};
|
||||||
|
|
||||||
|
args = vec![src, r_shamt, i_shamt, dest];
|
||||||
}
|
}
|
||||||
|
|
||||||
Opcode::Inc | Opcode::Dec => {
|
Opcode::Inc | Opcode::Dec => {
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ impl RegFile {
|
|||||||
Register::Sts => &mut self.sts,
|
Register::Sts => &mut self.sts,
|
||||||
Register::Cir => &mut self.cir,
|
Register::Cir => &mut self.cir,
|
||||||
Register::Pcx => &mut self.pcx,
|
Register::Pcx => &mut self.pcx,
|
||||||
_ => return Err(ProcessorError::InvalidRegister(Register::NoReg as u8)),
|
_ => return Err(ProcessorError::InvalidRegister(Register::Null as u8)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,7 +321,7 @@ impl RegFile {
|
|||||||
Register::Cir => self.cir,
|
Register::Cir => self.cir,
|
||||||
Register::Pcx => self.pcx,
|
Register::Pcx => self.pcx,
|
||||||
Register::Zero => 0,
|
Register::Zero => 0,
|
||||||
_ => return Err(ProcessorError::InvalidRegister(Register::NoReg as u8)),
|
_ => return Err(ProcessorError::InvalidRegister(Register::Null as u8)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -349,17 +349,13 @@ impl Executable for Instruction {
|
|||||||
// Left shifts the value in Reg by the given amount (either a register, or a
|
// Left shifts the value in Reg by the given amount (either a register, or a
|
||||||
// literal value)
|
// literal value)
|
||||||
Self::ShiftLeft(a) => {
|
Self::ShiftLeft(a) => {
|
||||||
let reg = cpu.get(a.sr1)?;
|
*cpu.reg(a.dr)? = shl(cpu.get(a.sr1)?, a.shamt + cpu.get(a.sr2)? as u8);
|
||||||
let val = a.shamt;
|
|
||||||
*cpu.reg(a.sr1)? = shl(reg, val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Right shifts the value in Reg by the given amount (either a register, or a
|
// Right shifts the value in Reg by the given amount (either a register, or a
|
||||||
// literal value).
|
// literal value).
|
||||||
Self::ShiftRight(a) => {
|
Self::ShiftRight(a) => {
|
||||||
let regval = cpu.get(a.sr1)?;
|
*cpu.reg(a.dr)? = shr(cpu.get(a.sr1)?, a.shamt + cpu.get(a.sr2)? as u8);
|
||||||
let val = a.shamt;
|
|
||||||
*cpu.reg(a.sr1)? = shr(regval, val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds the value of Src2 to Src1 and writes the result to a.dr
|
// Adds the value of Src2 to Src1 and writes the result to a.dr
|
||||||
|
|||||||
Reference in New Issue
Block a user