Work..
Refactor disassembler to a struct. Implement more commands;
This commit is contained in:
parent
22a915ec85
commit
e5d93f689f
33
Cargo.lock
generated
33
Cargo.lock
generated
|
@ -22,6 +22,15 @@ dependencies = [
|
|||
"scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.3.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.4.10"
|
||||
|
@ -202,6 +211,20 @@ name = "fuchsia-cprng"
|
|||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "hexdump"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"arrayvec 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.3.0"
|
||||
|
@ -285,6 +308,11 @@ name = "numtoa"
|
|||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "odds"
|
||||
version = "0.2.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
|
@ -390,6 +418,7 @@ dependencies = [
|
|||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"enum-primitive-derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hexdump 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustyline 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -611,6 +640,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
"checksum approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08abcc3b4e9339e33a3d0a5ed15d84a687350c05689d825e0f6655eef9e76a94"
|
||||
"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392"
|
||||
"checksum arrayvec 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)" = "06f59fe10306bb78facd90d28c2038ad23ffaaefa85bac43c8a434cde383334f"
|
||||
"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71"
|
||||
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
|
||||
"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf"
|
||||
|
@ -633,6 +663,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
|
||||
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
|
||||
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||
"checksum hexdump 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "850f3f2c33d20c0f96c4485e087dd580ff041d720988ebf4c84a42acf739262b"
|
||||
"checksum itertools 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c4a9b56eb56058f43dc66e58f40a214b2ccbc9f3df51861b63d51dec7b65bc3f"
|
||||
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
|
||||
"checksum lexical-core 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d224b31f370c8dfc0dea1932d9e6bd451e65aef6f5f2318846664c04b42a796"
|
||||
"checksum libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "6281b86796ba5e4366000be6e9e18bf35580adf9e63fbe2294aadb587613a319"
|
||||
|
@ -644,6 +676,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
|
||||
"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
|
||||
"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||
"checksum odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "4eae0151b9dacf24fcc170d9995e511669a082856a91f958a2fe380bfab3fb22"
|
||||
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
||||
"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
|
||||
|
|
|
@ -12,4 +12,5 @@ bit = "^0.1"
|
|||
clap = {version = "2.33", features = ["color", "yaml"]}
|
||||
rustyline = "5.0.0"
|
||||
nom = "5.0.0"
|
||||
colored = "1.8"
|
||||
colored = "1.8"
|
||||
hexdump = "0.1.0"
|
|
@ -1,19 +1,35 @@
|
|||
use super::super::cpu::{Core, CpuPipelineAction, CpuError, CpuInstruction, CpuExecResult};
|
||||
use super::super::cpu::{Core, CpuState, CpuPipelineAction, CpuError, CpuInstruction, CpuResult, CpuExecResult};
|
||||
use super::super::sysbus::SysBus;
|
||||
use super::{ArmInstruction, ArmInstructionFormat};
|
||||
|
||||
use crate::bit::BitIndex;
|
||||
|
||||
impl Core {
|
||||
pub fn exec_arm(&mut self, sysbus: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
|
||||
match insn.fmt {
|
||||
ArmInstructionFormat::BX => {
|
||||
self.pc = self.get_reg(insn.rn());
|
||||
Ok((CpuInstruction::Arm(insn), CpuPipelineAction::Branch))
|
||||
},
|
||||
ArmInstructionFormat::B_BL => {
|
||||
self.pc = (self.pc as i32).wrapping_add(insn.branch_offset()) as u32;
|
||||
Ok((CpuInstruction::Arm(insn), CpuPipelineAction::Branch))
|
||||
}
|
||||
fmt => Err(CpuError::UnimplementedCpuInstruction(CpuInstruction::Arm(insn))),
|
||||
fn exec_b_bl(&mut self, sysbus: &mut SysBus, insn: ArmInstruction) -> CpuResult<CpuPipelineAction> {
|
||||
if insn.link_flag() {
|
||||
self.set_reg(14, self.pc & !0b1);
|
||||
}
|
||||
self.pc = (self.pc as i32).wrapping_add(insn.branch_offset()) as u32;
|
||||
Ok(CpuPipelineAction::Branch)
|
||||
}
|
||||
|
||||
fn exec_bx(&mut self, sysbus: &mut SysBus, insn: ArmInstruction) -> CpuResult<CpuPipelineAction> {
|
||||
let rn = self.get_reg(insn.rn());
|
||||
if rn.bit(0) {
|
||||
self.set_state(CpuState::THUMB);
|
||||
} else {
|
||||
self.set_state(CpuState::ARM);
|
||||
}
|
||||
|
||||
Ok(CpuPipelineAction::Branch)
|
||||
}
|
||||
|
||||
pub fn exec_arm(&mut self, sysbus: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
|
||||
let action = match insn.fmt {
|
||||
ArmInstructionFormat::BX => self.exec_bx(sysbus, insn),
|
||||
ArmInstructionFormat::B_BL => self.exec_b_bl(sysbus, insn),
|
||||
fmt => Err(CpuError::UnimplementedCpuInstruction(CpuInstruction::Arm(insn))),
|
||||
}?;
|
||||
Ok((CpuInstruction::Arm(insn), action))
|
||||
}
|
||||
}
|
|
@ -127,6 +127,10 @@ impl Core {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn set_state(&mut self, s: CpuState) {
|
||||
self.state = s;
|
||||
}
|
||||
|
||||
/// Resets the cpu
|
||||
pub fn reset(&mut self) {
|
||||
self.pc = 0;
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use rustyline::error::ReadlineError;
|
||||
use rustyline::Editor;
|
||||
|
||||
use colored::*;
|
||||
|
||||
use nom;
|
||||
use nom::bytes;
|
||||
use nom::IResult;
|
||||
use nom::bytes::complete::{tag, take_till1, take_till, take_while_m_n, take_while1};
|
||||
use nom::combinator::map_res;
|
||||
|
||||
use super::arm7tdmi::arm;
|
||||
use hexdump;
|
||||
|
||||
use super::arm7tdmi::cpu;
|
||||
use super::sysbus::SysBus;
|
||||
|
||||
use crate::disass::Disassembler;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Debugger {
|
||||
cpu: cpu::Core,
|
||||
|
@ -50,6 +50,7 @@ enum DebuggerCommand {
|
|||
Info,
|
||||
SingleStep,
|
||||
Continue,
|
||||
HexDump(u32, usize),
|
||||
Disass { addr: u32, num_opcodes: usize },
|
||||
AddBreakpoint(u32),
|
||||
ListBreakpoints,
|
||||
|
@ -92,6 +93,14 @@ fn parse_debugger_command(input: &str) -> DebuggerResult<DebuggerCommand> {
|
|||
"i" | "info" => Ok(Info),
|
||||
"s" | "step" => Ok(SingleStep),
|
||||
"c" | "continue" => Ok(Continue),
|
||||
"xxd" => {
|
||||
let (input, _) = whitespace(input).map_err(|_| DebuggerError::ParsingError("argument missing".to_string()))?;
|
||||
let (input, addr) = parse_hex_num(input)?;
|
||||
let (input, _) = whitespace(input).map_err(|_| DebuggerError::ParsingError("argument missing".to_string()))?;
|
||||
let (_, nbytes) = parse_num(input)?;
|
||||
let nbytes = nbytes as usize;
|
||||
Ok(HexDump(addr, nbytes))
|
||||
}
|
||||
"d" | "disass" => {
|
||||
let (input, _) = whitespace(input).map_err(|_| DebuggerError::ParsingError("argument missing".to_string()))?;
|
||||
let (input, addr) = parse_hex_num(input)?;
|
||||
|
@ -167,6 +176,30 @@ impl Debugger {
|
|||
println!("breakpoint 0x{:08x} reached!", self.cpu.pc)
|
||||
}
|
||||
}
|
||||
},
|
||||
HexDump(addr, nbytes) => {
|
||||
let bytes = match self.sysbus.get_bytes(addr, nbytes) {
|
||||
Some(bytes) => bytes,
|
||||
None => {
|
||||
println!("requested content out of bounds");
|
||||
return
|
||||
}
|
||||
};
|
||||
hexdump::hexdump(bytes);
|
||||
}
|
||||
Disass{ addr, num_opcodes } => {
|
||||
let bytes = match self.sysbus.get_bytes(addr, 4*num_opcodes) {
|
||||
Some(bytes) => bytes,
|
||||
None => {
|
||||
println!("requested content out of bounds");
|
||||
return
|
||||
}
|
||||
};
|
||||
let disass = Disassembler::new(addr, bytes);
|
||||
|
||||
for line in disass {
|
||||
println!("{}", line)
|
||||
}
|
||||
}
|
||||
Quit => {
|
||||
print!("Quitting!");
|
||||
|
|
55
src/disass.rs
Normal file
55
src/disass.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
use std::convert::TryFrom;
|
||||
|
||||
use std::io::ErrorKind;
|
||||
use std::io::{Cursor, Seek, SeekFrom};
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
|
||||
use super::arm7tdmi::arm;
|
||||
|
||||
pub struct Disassembler<'a> {
|
||||
base: u32,
|
||||
rdr: Cursor<&'a [u8]>,
|
||||
}
|
||||
|
||||
impl<'a> Disassembler<'a> {
|
||||
pub fn new(base: u32, bin: &'a [u8]) -> Disassembler {
|
||||
Disassembler {
|
||||
base: base,
|
||||
rdr: Cursor::new(bin),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Seek for Disassembler<'a> {
|
||||
fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
|
||||
self.rdr.seek(pos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Disassembler<'a> {
|
||||
type Item = String;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let mut line = String::new();
|
||||
let value: u32 = match self.rdr.read_u32::<LittleEndian>() {
|
||||
Ok(value) => value,
|
||||
Err(e) => match e.kind() {
|
||||
ErrorKind::UnexpectedEof => {
|
||||
return None;
|
||||
}
|
||||
_ => panic!("unexpected error"),
|
||||
},
|
||||
};
|
||||
|
||||
let addr = self.base + (self.rdr.position() - 4) as u32;
|
||||
line.push_str(&format!("{:8x}:\t{:08x} \t", addr, value));
|
||||
|
||||
match arm::ArmInstruction::try_from((value, addr)) {
|
||||
Ok(insn) => line.push_str(&format!("{}", insn)),
|
||||
Err(_) => line.push_str("<UNDEFINED>"),
|
||||
};
|
||||
|
||||
Some(line)
|
||||
}
|
||||
}
|
27
src/main.rs
27
src/main.rs
|
@ -1,8 +1,6 @@
|
|||
use std::convert::TryFrom;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::io::ErrorKind;
|
||||
|
||||
#[macro_use]
|
||||
extern crate enum_primitive_derive;
|
||||
|
@ -11,7 +9,6 @@ extern crate num_traits;
|
|||
extern crate bit;
|
||||
|
||||
extern crate byteorder;
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
|
@ -33,6 +30,9 @@ use arm7tdmi::cpu;
|
|||
mod debugger;
|
||||
use debugger::{Debugger, DebuggerError};
|
||||
|
||||
mod disass;
|
||||
use disass::Disassembler;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GBAError {
|
||||
IO(io::Error),
|
||||
|
@ -79,25 +79,10 @@ fn run_disass(matches: &ArgMatches) -> GBAResult<()> {
|
|||
let input = matches.value_of("INPUT").unwrap();
|
||||
let bin = read_bin_file(&input)?;
|
||||
|
||||
let mut rdr = io::Cursor::new(bin);
|
||||
loop {
|
||||
let value: u32 = match rdr.read_u32::<LittleEndian>() {
|
||||
Ok(value) => Ok(value),
|
||||
Err(e) => match e.kind() {
|
||||
ErrorKind::UnexpectedEof => {
|
||||
break;
|
||||
}
|
||||
_ => Err(e),
|
||||
},
|
||||
}?;
|
||||
let addr = (rdr.position() - 4) as u32;
|
||||
print!("{:8x}:\t{:08x} \t", addr, value);
|
||||
match arm::ArmInstruction::try_from((value, addr)) {
|
||||
Ok(insn) => println!("{}", insn),
|
||||
Err(_) => println!("<UNDEFINED>"),
|
||||
};
|
||||
let disassembler = Disassembler::new(0, &bin);
|
||||
for line in disassembler {
|
||||
println!("{}", line)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -31,4 +31,13 @@ impl SysBus {
|
|||
.read_u16::<LittleEndian>()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn get_bytes(&self, addr: u32, size: usize) -> Option<&[u8]> {
|
||||
let addr = addr as usize;
|
||||
if addr + size > self.bios_rom.len() {
|
||||
None
|
||||
} else {
|
||||
Some(&self.bios_rom[addr..addr + size])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue