Added copy opcode

This commit is contained in:
2022-08-06 01:18:14 -05:00
parent fa5dc84ad2
commit 25afdb8890
2 changed files with 92 additions and 12 deletions
+80 -2
View File
@@ -208,8 +208,11 @@ impl CPU {
} else { } else {
match instruction.opcode { match instruction.opcode {
Opcode::Nop => { /* No action required */ } Opcode::Nop => { /* No action required */ }
Opcode::Rand => { Opcode::Copy => {
todo!() let dest = self.pop_data();
let src = self.pop_data();
let len = self.pop_data();
self.copy_region(len, dest, src);
} }
Opcode::Not => { Opcode::Not => {
let x = self.pop_data(); let x = self.pop_data();
@@ -417,6 +420,25 @@ impl CPU {
); );
} }
fn copy_region(&mut self, len: Word, dest: Word, src: Word) {
// Degenerate cases:
if dest == src || len == 0 { return }
// Now, check if we're moving to a greater or lesser address:
if dest > src {
// If the dest is greater, we need to move from the end of the range backwards,
// in case there's overlap:
for offset in (0..len.into()).rev() {
self.memory.poke(dest + offset, self.memory.peek(src + offset))
}
} else {
// Dest is before src, so we'll move from low index to high, in case of overlap:
for offset in 0..len.into() {
self.memory.poke(dest + offset, self.memory.peek(src + offset))
}
}
}
pub fn interrupt(&mut self, irq: usize, arg: Option<Word>) { pub fn interrupt(&mut self, irq: usize, arg: Option<Word>) {
if irq >= self.iv.len() { if irq >= self.iv.len() {
panic!("Invalid interrupt: {}", irq) panic!("Invalid interrupt: {}", irq)
@@ -685,6 +707,62 @@ mod tests {
simple_opcode_test(vec![0x800010, 2], Arshift, vec![0xe00004]); simple_opcode_test(vec![0x800010, 2], Arshift, vec![0xe00004]);
} }
#[test]
fn test_cpu_copy() {
// No overlap, forwards
memory_opcode_test(
vec![3, 2048, 2051],
vec![1, 2, 3, 4, 5, 6],
Copy,
vec![],
Some(vec![1, 2, 3, 1, 2, 3]),
);
// No overlap, backwards
memory_opcode_test(
vec![3, 2051, 2048],
vec![1, 2, 3, 4, 5, 6],
Copy,
vec![],
Some(vec![4, 5, 6, 4, 5, 6]),
);
// Overlap, move forward
memory_opcode_test(
vec![3, 2048, 2050],
vec![1, 2, 3, 4, 5, 6],
Copy,
vec![],
Some(vec![1, 2, 1, 2, 3, 6]),
);
// Overlap, move backwards
memory_opcode_test(
vec![3, 2051, 2049],
vec![1, 2, 3, 4, 5, 6],
Copy,
vec![],
Some(vec![1, 4, 5, 6, 5, 6]),
);
// Degenerate cases
memory_opcode_test(
vec![0, 2051, 2049],
vec![1, 2, 3, 4, 5, 6],
Copy,
vec![],
Some(vec![1, 2, 3, 4, 5, 6]),
);
memory_opcode_test(
vec![5, 2048, 2048],
vec![1, 2, 3, 4, 5, 6],
Copy,
vec![],
Some(vec![1, 2, 3, 4, 5, 6]),
);
}
#[test] #[test]
fn test_cpu_call_stack() { fn test_cpu_call_stack() {
call_stack_opcode_test(vec![5000], vec![], Call, vec![], vec![1025], 5000.into()); call_stack_opcode_test(vec![5000], vec![], Call, vec![], vec![1025], 5000.into());
+12 -10
View File
@@ -9,7 +9,7 @@ pub enum Opcode {
Mul, Mul,
Div, Div,
Mod, Mod,
Rand, Copy,
And, And,
Or, Or,
Xor, Xor,
@@ -82,8 +82,8 @@ impl Display for Opcode {
Opcode::Mod => { Opcode::Mod => {
write!(f, "mod") write!(f, "mod")
} }
Opcode::Rand => { Opcode::Copy => {
write!(f, "rand") write!(f, "copy")
} }
Opcode::And => { Opcode::And => {
write!(f, "and") write!(f, "and")
@@ -206,7 +206,7 @@ impl TryFrom<u8> for Opcode {
3 => Mul, 3 => Mul,
4 => Div, 4 => Div,
5 => Mod, 5 => Mod,
6 => Rand, 6 => Copy,
7 => And, 7 => And,
8 => Or, 8 => Or,
9 => Xor, 9 => Xor,
@@ -259,7 +259,7 @@ impl<'a> TryFrom<&'a str> for Opcode {
"mul" => Mul, "mul" => Mul,
"div" => Div, "div" => Div,
"mod" => Mod, "mod" => Mod,
"rand" => Rand, "copy" => Copy,
"and" => And, "and" => And,
"or" => Or, "or" => Or,
"xor" => Xor, "xor" => Xor,
@@ -309,7 +309,7 @@ impl From<Opcode> for u8 {
Opcode::Mul => 3, Opcode::Mul => 3,
Opcode::Div => 4, Opcode::Div => 4,
Opcode::Mod => 5, Opcode::Mod => 5,
Opcode::Rand => 6, Opcode::Copy => 6,
Opcode::And => 7, Opcode::And => 7,
Opcode::Or => 8, Opcode::Or => 8,
Opcode::Xor => 9, Opcode::Xor => 9,
@@ -354,14 +354,14 @@ impl Opcode {
pub fn arity(self) -> usize { pub fn arity(self) -> usize {
use Opcode::*; use Opcode::*;
match self { match self {
Nop | Rand | Ret | Hlt | Sdp | Popr | Peekr | Debug => 0, Nop | Ret | Hlt | Sdp | Popr | Peekr | Debug => 0,
Not | Pop | Dup | Jmp | Jmpr | Call | Load | Loadw | Setint | Pushr | Pick => 1, Not | Pop | Dup | Jmp | Jmpr | Call | Load | Loadw | Setint | Pushr | Pick => 1,
Add | Sub | Mul | Div | Mod | And | Or | Xor | Gt | Lt | Agt | Alt | Lshift Add | Sub | Mul | Div | Mod | And | Or | Xor | Gt | Lt | Agt | Alt | Lshift
| Rshift | Arshift | Swap | Brz | Brnz | Store | Storew | Setsdp | Setiv => 2, | Rshift | Arshift | Swap | Brz | Brnz | Store | Storew | Setsdp | Setiv => 2,
Rot => 3, Rot | Copy => 3,
} }
} }
@@ -372,7 +372,7 @@ impl Opcode {
match self { match self {
Peekr | Popr | Ret => 1, Peekr | Popr | Ret => 1,
Nop | Rand | Hlt | Sdp | Debug | Not | Pop | Dup | Jmp | Jmpr | Call | Load | Loadw Nop | Copy | Hlt | Sdp | Debug | Not | Pop | Dup | Jmp | Jmpr | Call | Load | Loadw
| Setint | Setiv | Pushr | Add | Sub | Mul | Div | Mod | And | Or | Xor | Gt | Lt | Setint | Setiv | Pushr | Add | Sub | Mul | Div | Mod | And | Or | Xor | Gt | Lt
| Agt | Alt | Lshift | Rshift | Arshift | Swap | Brz | Brnz | Store | Storew | Agt | Alt | Lshift | Rshift | Arshift | Swap | Brz | Brnz | Store | Storew
| Setsdp | Rot | Pick => 0, | Setsdp | Rot | Pick => 0,
@@ -397,7 +397,7 @@ impl Opcode {
match self { match self {
Sdp => 2, Sdp => 2,
Peekr | Rand | Dup => 1, Peekr | Dup => 1,
Nop | Hlt | Debug | Not | Call | Load | Loadw | Pushr | Popr | Pick | Rot | Swap => 0, Nop | Hlt | Debug | Not | Call | Load | Loadw | Pushr | Popr | Pick | Rot | Swap => 0,
@@ -405,6 +405,8 @@ impl Opcode {
| Alt | Lshift | Rshift | Arshift | Ret => -1, | Alt | Lshift | Rshift | Arshift | Ret => -1,
Setint | Store | Storew | Setsdp | Setiv | Brz | Brnz => -2, Setint | Store | Storew | Setsdp | Setiv | Brz | Brnz => -2,
Copy => -3,
} }
} }
} }