Added formatter for Instruction to output assembly

This commit is contained in:
transistor 2021-10-15 11:12:47 -07:00
parent eba1f9c9fc
commit 1732c90f5b
3 changed files with 173 additions and 6 deletions

View File

@ -821,7 +821,7 @@ impl M68kDecoder {
(0..((self.end - self.start) / 2)).map(|offset|
Ok(format!("{:04x} ", system.get_bus().read_beu16((self.start + (offset * 2)) as Address).unwrap()))
).collect();
println!("{:#010x}: {}\n\t{:?}\n", self.start, ins_data.unwrap(), self.instruction);
println!("{:#010x}: {}\n\t{}\n", self.start, ins_data.unwrap(), self.instruction);
}
}
@ -906,6 +906,66 @@ pub fn sign_extend_to_long(value: u32, from: Size) -> i32 {
}
}
impl fmt::Display for Sign {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Sign::Signed => write!(f, "s"),
Sign::Unsigned => write!(f, "u"),
}
}
}
impl fmt::Display for ShiftDirection {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ShiftDirection::Right => write!(f, "r"),
ShiftDirection::Left => write!(f, "l"),
}
}
}
impl fmt::Display for Size {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Size::Byte => write!(f, "b"),
Size::Word => write!(f, "w"),
Size::Long => write!(f, "l"),
}
}
}
impl fmt::Display for Condition {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Condition::True => write!(f, "t"),
Condition::False => write!(f, "f"),
Condition::High => write!(f, "h"),
Condition::LowOrSame => write!(f, "ls"),
Condition::CarryClear => write!(f, "cc"),
Condition::CarrySet => write!(f, "cs"),
Condition::NotEqual => write!(f, "ne"),
Condition::Equal => write!(f, "eq"),
Condition::OverflowClear => write!(f, "oc"),
Condition::OverflowSet => write!(f, "os"),
Condition::Plus => write!(f, "p"),
Condition::Minus => write!(f, "m"),
Condition::GreaterThanOrEqual => write!(f, "ge"),
Condition::LessThan => write!(f, "lt"),
Condition::GreaterThan => write!(f, "gt"),
Condition::LessThanOrEqual => write!(f, "le"),
}
}
}
impl fmt::Display for ControlRegister {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ControlRegister::VBR => write!(f, "%vbr"),
}
}
}
impl fmt::Display for Target {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
@ -915,11 +975,117 @@ impl fmt::Display for Target {
Target::IndirectAReg(reg) => write!(f, "(%a{})", reg),
Target::IndirectARegInc(reg) => write!(f, "(%a{})+", reg),
Target::IndirectARegDec(reg) => write!(f, "-(%a{})", reg),
Target::IndirectARegOffset(reg, offset) => write!(f, "(%a{} + #{})", reg, offset),
Target::IndirectARegXRegOffset(reg, rtype, xreg, offset, _) => write!(f, "(%a{} + %{}{} + #{})", reg, if *rtype == RegisterType::Data { 'd' } else { 'a' }, xreg, offset),
Target::IndirectARegOffset(reg, offset) => write!(f, "(%a{} + #{:04x})", reg, offset),
Target::IndirectARegXRegOffset(reg, rtype, xreg, offset, _) => write!(f, "(%a{} + %{}{} + #{:04x})", reg, if *rtype == RegisterType::Data { 'd' } else { 'a' }, xreg, offset),
Target::IndirectMemory(value) => write!(f, "(#{:08x})", value),
Target::IndirectPCOffset(offset) => write!(f, "(%pc + #{})", offset),
Target::IndirectPCXRegOffset(rtype, xreg, offset, _) => write!(f, "(%pc + %{}{} + #{})", if *rtype == RegisterType::Data { 'd' } else { 'a' }, xreg, offset),
Target::IndirectPCOffset(offset) => write!(f, "(%pc + #{:04x})", offset),
Target::IndirectPCXRegOffset(rtype, xreg, offset, _) => write!(f, "(%pc + %{}{} + #{:04x})", if *rtype == RegisterType::Data { 'd' } else { 'a' }, xreg, offset),
}
}
}
fn fmt_movem_mask(mask: u16) -> String {
format!("something")
}
impl fmt::Display for Instruction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Instruction::ABCD(src, dest) => write!(f, "abcd\t{}, {}", src, dest),
Instruction::ADD(src, dest, size) => write!(f, "add{}\t{}, {}", size, src, dest),
Instruction::AND(src, dest, size) => write!(f, "and{}\t{}, {}", size, src, dest),
Instruction::ANDtoCCR(value) => write!(f, "andb\t{:02x}, %ccr", value),
Instruction::ANDtoSR(value) => write!(f, "andw\t{:04x}, %sr", value),
Instruction::ASd(src, dest, size, dir) => write!(f, "as{}{}\t{}, {}", dir, size, src, dest),
Instruction::Bcc(cond, offset) => write!(f, "b{}\t{}", cond, offset),
Instruction::BRA(offset) => write!(f, "bra\t{}", offset),
Instruction::BSR(offset) => write!(f, "bra\t{}", offset),
Instruction::BCHG(src, dest, size) => write!(f, "bchg{}\t{}, {}", size, src, dest),
Instruction::BCLR(src, dest, size) => write!(f, "bclr{}\t{}, {}", size, src, dest),
Instruction::BSET(src, dest, size) => write!(f, "bset{}\t{}, {}", size, src, dest),
Instruction::BTST(src, dest, size) => write!(f, "btst{}\t{}, {}", size, src, dest),
//Instruction::BKPT(value),
Instruction::CHK(target, reg, size) => write!(f, "chk{}\t{}, %d{}", size, target, reg),
Instruction::CLR(target, size) => write!(f, "clr{}\t{}", size, target),
Instruction::CMP(src, dest, size) => write!(f, "cmp{}\t{}, {}", size, src, dest),
Instruction::CMPA(target, reg, size) => write!(f, "cmpa{}\t{}, %a{}", size, target, reg),
Instruction::DBcc(cond, reg, offset) => write!(f, "db{}\t%d{}, {}", cond, reg, offset),
Instruction::DIV(src, dest, size, sign) => write!(f, "div{}{}\t{}, {}", sign, size, src, dest),
Instruction::EOR(src, dest, size) => write!(f, "eor{}\t{}, {}", size, src, dest),
Instruction::EORtoCCR(value) => write!(f, "eorb\t{:02x}, %ccr", value),
Instruction::EORtoSR(value) => write!(f, "eorw\t{:04x}, %sr", value),
Instruction::EXG(src, dest) => write!(f, "exg\t{}, {}", src, dest),
Instruction::EXT(reg, size) => write!(f, "ext{}\t%d{}", size, reg),
Instruction::ILLEGAL => write!(f, "illegal"),
Instruction::JMP(target) => write!(f, "jmp\t{}", target),
Instruction::JSR(target) => write!(f, "jsr\t{}", target),
Instruction::LEA(target, reg) => write!(f, "lea\t{}, %a{}", target, reg),
Instruction::LINK(reg, offset) => write!(f, "link\t%a{}, {}", reg, offset),
Instruction::LSd(src, dest, size, dir) => write!(f, "ls{}{}\t{}, {}", dir, size, src, dest),
Instruction::MOVE(src, dest, size) => write!(f, "move{}\t{}, {}", size, src, dest),
Instruction::MOVEA(target, reg, size) => write!(f, "movea{}\t{}, %a{}", size, target, reg),
Instruction::MOVEfromSR(target) => write!(f, "movew\t%sr, {}", target),
Instruction::MOVEtoSR(target) => write!(f, "movew\t{}, %sr", target),
Instruction::MOVEfromCCR(target) => write!(f, "moveb\t%ccr, {}", target),
Instruction::MOVEtoCCR(target) => write!(f, "moveb\t{}, %ccr", target),
Instruction::MOVEC(target, reg, dir) => match dir {
Direction::ToTarget => write!(f, "movec\t{}, {}", reg, target),
Direction::FromTarget => write!(f, "movec\t{}, {}", target, reg),
},
Instruction::MOVEM(target, size, dir, mask) => match dir {
Direction::ToTarget => write!(f, "movem{}\t{}, {}", size, fmt_movem_mask(*mask), target),
Direction::FromTarget => write!(f, "movem{}\t{}, {}", size, target, fmt_movem_mask(*mask)),
},
//Instruction::MOVEP(reg, target, size, dir),
Instruction::MOVEQ(value, reg) => write!(f, "moveq\t#{:02x}, %d{}", value, reg),
Instruction::MOVEUSP(target, dir) => match dir {
Direction::ToTarget => write!(f, "movel\t%usp, {}", target),
Direction::FromTarget => write!(f, "movel\t{}, %usp", target),
},
Instruction::MUL(src, dest, size, sign) => write!(f, "mul{}{}\t{}, {}", sign, size, src, dest),
Instruction::NBCD(target) => write!(f, "nbcd\t{}", target),
Instruction::NEG(target, size) => write!(f, "neg{}\t{}", size, target),
Instruction::NEGX(target, size) => write!(f, "negx{}\t{}", size, target),
Instruction::NOP => write!(f, "nop"),
Instruction::NOT(target, size) => write!(f, "not{}\t{}", size, target),
Instruction::OR(src, dest, size) => write!(f, "or{}\t{}, {}", size, src, dest),
Instruction::ORtoCCR(value) => write!(f, "orb\t{:02x}, %ccr", value),
Instruction::ORtoSR(value) => write!(f, "orw\t{:04x}, %sr", value),
Instruction::PEA(target) => write!(f, "pea\t{}", target),
Instruction::RESET => write!(f, "reset"),
Instruction::ROd(src, dest, size, dir) => write!(f, "ro{}{}\t{}, {}", dir, size, src, dest),
Instruction::ROXd(src, dest, size, dir) => write!(f, "rox{}{}\t{}, {}", dir, size, src, dest),
Instruction::RTE => write!(f, "rte"),
Instruction::RTR => write!(f, "rtr"),
Instruction::RTS => write!(f, "rts"),
Instruction::RTD(offset) => write!(f, "rtd\t{}", offset),
Instruction::SBCD(src, dest) => write!(f, "sbcd\t{}, {}", src, dest),
Instruction::Scc(cond, target) => write!(f, "s{}\t{}", cond, target),
Instruction::STOP(value) => write!(f, "stop\t#{:04x}", value),
Instruction::SUB(src, dest, size) => write!(f, "sub{}\t{}, {}", size, src, dest),
Instruction::SWAP(reg) => write!(f, "swap\t%d{}", reg),
Instruction::TAS(target) => write!(f, "tas\t{}", target),
Instruction::TST(target, size) => write!(f, "tst{}\t{}", size, target),
Instruction::TRAP(num) => write!(f, "trap\t{}", num),
Instruction::TRAPV => write!(f, "trapv"),
Instruction::UNLK(reg) => write!(f, "unlk\t%a{}", reg),
_ => write!(f, "UNIMPL"),
}
}
}

View File

@ -46,6 +46,7 @@ fn main() {
//cpu.add_breakpoint(0x10bc9c);
//cpu.add_breakpoint(0x106a94);
//cpu.add_breakpoint(0x10b79c);
//cpu.decoder.dump_disassembly(&mut system, 0x100000, 0x2000);
system.add_interruptable_device(wrap_interruptable(cpu)).unwrap();
loop {

View File

@ -2,7 +2,7 @@
* add exception for privileged instructions. Should you separate them in the `match` or just put a guard into the instructions, and if the latter, can
you use the emulator's errors to surface the execption up to the `step_internal` function but not to `System`?
* make functions to print assembly out
* make it possible to break out of the current execution, into the debugger
* how can you add 68030 support? Should it be all one module that checks maybe during decode if the instruction is supported? Should it 'inherit' from the MC68010 object
* make tests for each instruction