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