Added copy opcode
This commit is contained in:
+80
-2
@@ -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
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user