dump sreg, add new ops

pull/21/head
Ondřej Hruška 4 years ago
parent f7e0998696
commit f652ff6669
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 1
      Cargo.lock
  2. 3
      asm/src/instr/op.rs
  3. 7
      asm/src/parse/parse_op.rs
  4. 1
      runtime/Cargo.toml
  5. 195
      runtime/src/exec/mod.rs
  6. 35
      runtime/src/frame.rs
  7. 2
      runtime/src/run_thread.rs

1
Cargo.lock generated

@ -146,6 +146,7 @@ dependencies = [
"anyhow",
"asm",
"log",
"num-traits",
"thiserror",
]

@ -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"

@ -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::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::Rol(_, _) => {
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::Ror(_, _) => {
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::Lsl(_, _) => {
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::Lsr(_, _) => {
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(_, _) => {
unimplemented!()
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) => {

Loading…
Cancel
Save