dump sreg, add new ops
This commit is contained in:
Generated
+1
@@ -146,6 +146,7 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"asm",
|
"asm",
|
||||||
"log",
|
"log",
|
||||||
|
"num-traits",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -61,7 +61,8 @@ pub enum Op {
|
|||||||
Sub(Wr, Rd),
|
Sub(Wr, Rd),
|
||||||
Mul(Wr, Rd),
|
Mul(Wr, Rd),
|
||||||
Div(Wr, Rd),
|
Div(Wr, Rd),
|
||||||
Mod(Wr, /*rem*/Wr, Rd),
|
Mod(Wr, Rd),
|
||||||
|
DivRem(Wr, /*rem*/Wr, Rd),
|
||||||
|
|
||||||
// /// Bitwise
|
// /// Bitwise
|
||||||
And(Wr, Rd),
|
And(Wr, Rd),
|
||||||
|
|||||||
@@ -131,6 +131,13 @@ pub fn parse_op(keyword: &str, far : bool, mut arg_tokens: impl Iterator<Item=Se
|
|||||||
|
|
||||||
"mod" => {
|
"mod" => {
|
||||||
HLOp::L(Op::Mod(
|
HLOp::L(Op::Mod(
|
||||||
|
parse_wr(arg_tokens.next())?,
|
||||||
|
parse_rd(arg_tokens.next())?
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
"divr" => {
|
||||||
|
HLOp::L(Op::DivRem(
|
||||||
parse_wr(arg_tokens.next())?,
|
parse_wr(arg_tokens.next())?,
|
||||||
parse_wr(arg_tokens.next())?,
|
parse_wr(arg_tokens.next())?,
|
||||||
parse_rd(arg_tokens.next())?
|
parse_rd(arg_tokens.next())?
|
||||||
|
|||||||
@@ -11,3 +11,4 @@ asm = { path = "../asm" }
|
|||||||
thiserror = "1.0.20"
|
thiserror = "1.0.20"
|
||||||
anyhow = "1.0.32"
|
anyhow = "1.0.32"
|
||||||
log = "0.4.11"
|
log = "0.4.11"
|
||||||
|
num-traits = "0.2.12"
|
||||||
|
|||||||
+162
-33
@@ -3,6 +3,8 @@ use asm::instr::{Op, Cond};
|
|||||||
use crate::fault::Fault;
|
use crate::fault::Fault;
|
||||||
use crate::frame::StackFrame;
|
use crate::frame::StackFrame;
|
||||||
use asm::data::literal::{Value, is_positive, is_negative, Addr};
|
use asm::data::literal::{Value, is_positive, is_negative, Addr};
|
||||||
|
use std::ops::{Rem, BitXor, Shl};
|
||||||
|
use num_traits::PrimInt;
|
||||||
|
|
||||||
pub type CyclesSpent = usize;
|
pub type CyclesSpent = usize;
|
||||||
|
|
||||||
@@ -12,6 +14,7 @@ pub struct EvalRes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RunThread {
|
impl RunThread {
|
||||||
|
// TODO unit tests
|
||||||
pub fn eval_op(&mut self) -> Result<EvalRes, Fault> {
|
pub fn eval_op(&mut self) -> Result<EvalRes, Fault> {
|
||||||
let mut cycles = 1;
|
let mut cycles = 1;
|
||||||
let mut advance = 1;
|
let mut advance = 1;
|
||||||
@@ -19,6 +22,8 @@ impl RunThread {
|
|||||||
let mut frame = &mut self.frame;
|
let mut frame = &mut self.frame;
|
||||||
|
|
||||||
let op = self.program.read(frame.pc);
|
let op = self.program.read(frame.pc);
|
||||||
|
|
||||||
|
debug!("------------------------");
|
||||||
debug!("{} | {:?}", frame.pc, op);
|
debug!("{} | {:?}", frame.pc, op);
|
||||||
|
|
||||||
/* Operations can be given different execution times when run in slow mode. */
|
/* Operations can be given different execution times when run in slow mode. */
|
||||||
@@ -144,72 +149,196 @@ impl RunThread {
|
|||||||
frame.status.clear();
|
frame.status.clear();
|
||||||
let mut a = frame.read(dst.as_rd())?;
|
let mut a = frame.read(dst.as_rd())?;
|
||||||
let mut b = frame.read(*src)?;
|
let mut b = frame.read(*src)?;
|
||||||
|
let (val, ov) = if let Some(v) = a.checked_add(b) {
|
||||||
let val = a.wrapping_add(b);
|
(v, false)
|
||||||
|
} else {
|
||||||
|
(a.wrapping_add(b), true)
|
||||||
|
};
|
||||||
frame.status.zero = (val == 0);
|
frame.status.zero = (val == 0);
|
||||||
frame.status.positive = is_positive(val);
|
frame.status.positive = is_positive(val);
|
||||||
frame.status.negative = is_negative(val);
|
frame.status.negative = is_negative(val);
|
||||||
frame.status.overflow = b > Value::MAX - a; // TODO check
|
frame.status.overflow = ov;
|
||||||
// TODO carry?
|
|
||||||
frame.write(*dst, val)?;
|
frame.write(*dst, val)?;
|
||||||
}
|
}
|
||||||
Op::Sub(dst, src) => {
|
Op::Sub(dst, src) => {
|
||||||
frame.status.clear();
|
frame.status.clear();
|
||||||
let mut a = frame.read(dst.as_rd())?;
|
let mut a = frame.read(dst.as_rd())?;
|
||||||
let mut b = frame.read(*src)?;
|
let mut b = frame.read(*src)?;
|
||||||
|
let (val, ov) = if let Some(v) = a.checked_sub(b) {
|
||||||
let val = a.wrapping_sub(b);
|
(v, false)
|
||||||
|
} else {
|
||||||
|
(a.wrapping_sub(b), true)
|
||||||
|
};
|
||||||
frame.status.zero = (val == 0);
|
frame.status.zero = (val == 0);
|
||||||
frame.status.positive = is_positive(val);
|
frame.status.positive = is_positive(val);
|
||||||
frame.status.negative = is_negative(val);
|
frame.status.negative = is_negative(val);
|
||||||
frame.status.overflow = b > a;
|
frame.status.overflow = ov;
|
||||||
// TODO carry?
|
|
||||||
frame.write(*dst, val)?;
|
frame.write(*dst, val)?;
|
||||||
}
|
}
|
||||||
Op::Mul(dst, src) => {
|
Op::Mul(dst, src) => {
|
||||||
frame.status.clear();
|
frame.status.clear();
|
||||||
let mut a = frame.read(dst.as_rd())?;
|
let mut a = frame.read(dst.as_rd())?;
|
||||||
let mut b = frame.read(*src)?;
|
let mut b = frame.read(*src)?;
|
||||||
|
let (val, ov) = if let Some(v) = a.checked_mul(b) {
|
||||||
let val = a.wrapping_mul(b);
|
(v, false)
|
||||||
|
} else {
|
||||||
|
(a.wrapping_mul(b), true)
|
||||||
|
};
|
||||||
frame.status.zero = (val == 0);
|
frame.status.zero = (val == 0);
|
||||||
frame.status.positive = is_positive(val);
|
frame.status.positive = is_positive(val);
|
||||||
frame.status.negative = is_negative(val);
|
frame.status.negative = is_negative(val);
|
||||||
//frame.status.overflow = b > a; // TODO detect overflow
|
frame.status.overflow = ov;
|
||||||
frame.write(*dst, val)?;
|
frame.write(*dst, val)?;
|
||||||
}
|
}
|
||||||
Op::Div(_, _) => {
|
Op::Div(dst, src) => {
|
||||||
unimplemented!()
|
frame.status.clear();
|
||||||
|
let mut a = frame.read(dst.as_rd())?;
|
||||||
|
let mut b = frame.read(*src)?;
|
||||||
|
if b == 0 {
|
||||||
|
frame.status.overflow = true;
|
||||||
|
// TODO ?
|
||||||
|
} else {
|
||||||
|
let (val, ov) = if let Some(v) = a.checked_div(b) {
|
||||||
|
(v, false)
|
||||||
|
} else {
|
||||||
|
(a.wrapping_div(b), true)
|
||||||
|
};
|
||||||
|
frame.status.zero = (val == 0);
|
||||||
|
frame.status.positive = is_positive(val);
|
||||||
|
frame.status.negative = is_negative(val);
|
||||||
|
frame.status.overflow = ov;
|
||||||
|
frame.write(*dst, val)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Op::Mod(_, _, _) => {
|
Op::Mod(dst, src) => {
|
||||||
unimplemented!()
|
frame.status.clear();
|
||||||
|
let mut a = frame.read(dst.as_rd())?;
|
||||||
|
let mut b = frame.read(*src)?;
|
||||||
|
if b == 0 {
|
||||||
|
frame.status.overflow = true;
|
||||||
|
// TODO ?
|
||||||
|
} else {
|
||||||
|
let (val, ov) = if let Some(v) = a.checked_rem(b) {
|
||||||
|
(v, false)
|
||||||
|
} else {
|
||||||
|
(a.wrapping_rem(b), true)
|
||||||
|
};
|
||||||
|
frame.status.zero = (val == 0);
|
||||||
|
frame.status.positive = is_positive(val);
|
||||||
|
frame.status.negative = is_negative(val);
|
||||||
|
frame.status.overflow = ov;
|
||||||
|
frame.write(*dst, val)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Op::And(_, _) => {
|
Op::DivRem(dst, remptr, src) => {
|
||||||
unimplemented!()
|
frame.status.clear();
|
||||||
|
let mut a = frame.read(dst.as_rd())?;
|
||||||
|
let mut b = frame.read(*src)?;
|
||||||
|
if b == 0 {
|
||||||
|
frame.status.overflow = true;
|
||||||
|
// TODO ?
|
||||||
|
} else {
|
||||||
|
let (val, rem, ov) = if let Some(v) = a.checked_div(b) {
|
||||||
|
(v, a.rem(b), false)
|
||||||
|
} else {
|
||||||
|
(a.wrapping_div(b), a.wrapping_rem(b), true)
|
||||||
|
};
|
||||||
|
frame.status.zero = (val == 0);
|
||||||
|
frame.status.positive = is_positive(val);
|
||||||
|
frame.status.negative = is_negative(val);
|
||||||
|
frame.status.overflow = ov;
|
||||||
|
frame.write(*dst, val)?;
|
||||||
|
frame.write(*remptr, rem)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Op::Or(_, _) => {
|
Op::And(dst, src) => {
|
||||||
unimplemented!()
|
frame.status.clear();
|
||||||
|
let mut val = frame.read(dst.as_rd())?;
|
||||||
|
let mut b = frame.read(*src)?;
|
||||||
|
val &= b;
|
||||||
|
frame.status.zero = (val == 0);
|
||||||
|
frame.status.positive = is_positive(val);
|
||||||
|
frame.status.negative = is_negative(val);
|
||||||
|
frame.write(*dst, val)?;
|
||||||
}
|
}
|
||||||
Op::Xor(_, _) => {
|
Op::Or(dst, src) => {
|
||||||
unimplemented!()
|
frame.status.clear();
|
||||||
|
let mut val = frame.read(dst.as_rd())?;
|
||||||
|
let mut b = frame.read(*src)?;
|
||||||
|
val |= b;
|
||||||
|
frame.status.zero = (val == 0);
|
||||||
|
frame.status.positive = is_positive(val);
|
||||||
|
frame.status.negative = is_negative(val);
|
||||||
|
frame.write(*dst, val)?;
|
||||||
}
|
}
|
||||||
Op::Cpl(_) => {
|
Op::Xor(dst, src) => {
|
||||||
unimplemented!()
|
frame.status.clear();
|
||||||
|
let mut val = frame.read(dst.as_rd())?;
|
||||||
|
let mut b = frame.read(*src)?;
|
||||||
|
val ^= b;
|
||||||
|
frame.status.zero = (val == 0);
|
||||||
|
frame.status.positive = is_positive(val);
|
||||||
|
frame.status.negative = is_negative(val);
|
||||||
|
frame.write(*dst, val)?;
|
||||||
}
|
}
|
||||||
Op::Rol(_, _) => {
|
Op::Cpl(dst) => {
|
||||||
unimplemented!()
|
frame.status.clear();
|
||||||
|
let mut val = frame.read(dst.as_rd())?;
|
||||||
|
val = !val;
|
||||||
|
frame.status.zero = (val == 0);
|
||||||
|
frame.status.positive = is_positive(val);
|
||||||
|
frame.status.negative = is_negative(val);
|
||||||
|
frame.write(*dst, val)?;
|
||||||
}
|
}
|
||||||
Op::Ror(_, _) => {
|
Op::Rol(dst, num) => {
|
||||||
unimplemented!()
|
frame.status.clear();
|
||||||
|
let mut val = frame.read(dst.as_rd())?;
|
||||||
|
let mut b = frame.read(*num)?;
|
||||||
|
val = val.rotate_left(b as u32); // FIXME check overflow
|
||||||
|
frame.status.zero = (val == 0);
|
||||||
|
frame.status.positive = is_positive(val);
|
||||||
|
frame.status.negative = is_negative(val);
|
||||||
|
frame.write(*dst, val)?;
|
||||||
}
|
}
|
||||||
Op::Lsl(_, _) => {
|
Op::Ror(dst, num) => {
|
||||||
unimplemented!()
|
frame.status.clear();
|
||||||
|
let mut val = frame.read(dst.as_rd())?;
|
||||||
|
let mut b = frame.read(*num)?;
|
||||||
|
val = val.rotate_right(b as u32); // FIXME check overflow
|
||||||
|
frame.status.zero = (val == 0);
|
||||||
|
frame.status.positive = is_positive(val);
|
||||||
|
frame.status.negative = is_negative(val);
|
||||||
|
frame.write(*dst, val)?;
|
||||||
}
|
}
|
||||||
Op::Lsr(_, _) => {
|
Op::Lsl(dst, num) => {
|
||||||
unimplemented!()
|
frame.status.clear();
|
||||||
|
let mut val = frame.read(dst.as_rd())?;
|
||||||
|
let mut b = frame.read(*num)?;
|
||||||
|
val = val << b;
|
||||||
|
frame.status.zero = (val == 0);
|
||||||
|
frame.status.positive = is_positive(val);
|
||||||
|
frame.status.negative = is_negative(val);
|
||||||
|
frame.write(*dst, val)?;
|
||||||
}
|
}
|
||||||
Op::Asr(_, _) => {
|
Op::Lsr(dst, num) => {
|
||||||
unimplemented!()
|
frame.status.clear();
|
||||||
|
let mut val = frame.read(dst.as_rd())?;
|
||||||
|
let mut b = frame.read(*num)?;
|
||||||
|
val = val >> b;
|
||||||
|
frame.status.zero = (val == 0);
|
||||||
|
frame.status.positive = is_positive(val);
|
||||||
|
frame.status.negative = is_negative(val);
|
||||||
|
frame.write(*dst, val)?;
|
||||||
|
}
|
||||||
|
Op::Asr(dst, num) => {
|
||||||
|
frame.status.clear();
|
||||||
|
let mut val = frame.read(dst.as_rd())?;
|
||||||
|
let mut b = frame.read(*num)?;
|
||||||
|
val = val.signed_shr(b as u32); // FIXME check overflow
|
||||||
|
frame.status.zero = (val == 0);
|
||||||
|
frame.status.positive = is_positive(val);
|
||||||
|
frame.status.negative = is_negative(val);
|
||||||
|
frame.write(*dst, val)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ use asm::data::literal::{Addr, Value};
|
|||||||
use asm::data::{Rd, SrcDisp, Register, Wr, DstDisp};
|
use asm::data::{Rd, SrcDisp, Register, Wr, DstDisp};
|
||||||
use crate::fault::Fault;
|
use crate::fault::Fault;
|
||||||
use asm::instr::Cond;
|
use asm::instr::Cond;
|
||||||
|
use std::fmt::{Display, Formatter, Write};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
pub const REG_COUNT: usize = 8;
|
pub const REG_COUNT: usize = 8;
|
||||||
|
|
||||||
@@ -25,6 +27,39 @@ pub struct StatusFlags {
|
|||||||
pub carry: bool,
|
pub carry: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for StatusFlags {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str("[")?;
|
||||||
|
if self.equal {
|
||||||
|
f.write_str(" E")?;
|
||||||
|
}
|
||||||
|
if self.zero {
|
||||||
|
f.write_str(" Z")?;
|
||||||
|
}
|
||||||
|
if self.lower {
|
||||||
|
f.write_str(" L")?;
|
||||||
|
}
|
||||||
|
if self.greater {
|
||||||
|
f.write_str(" G")?;
|
||||||
|
}
|
||||||
|
if self.positive {
|
||||||
|
f.write_str(" P")?;
|
||||||
|
}
|
||||||
|
if self.negative {
|
||||||
|
f.write_str(" N")?;
|
||||||
|
}
|
||||||
|
if self.overflow {
|
||||||
|
f.write_str(" V")?;
|
||||||
|
}
|
||||||
|
if self.carry {
|
||||||
|
f.write_str(" C")?;
|
||||||
|
}
|
||||||
|
f.write_str(" ]")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl StatusFlags {
|
impl StatusFlags {
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
*self = Self::default();
|
*self = Self::default();
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ impl RunThread {
|
|||||||
cycles, advance
|
cycles, advance
|
||||||
}) => {
|
}) => {
|
||||||
std::thread::sleep(CYCLE_TIME * (cycles as u32));
|
std::thread::sleep(CYCLE_TIME * (cycles as u32));
|
||||||
debug!("PC += {}", advance);
|
debug!("Step {}; Status = {}", advance, self.frame.status);
|
||||||
self.frame.pc.advance(advance);
|
self.frame.pc.advance(advance);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user