aboutsummaryrefslogtreecommitdiff
path: root/src/disasm.rs
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2017-11-17 15:00:24 -0500
committerDeterminant <ted.sybil@gmail.com>2017-11-17 15:00:24 -0500
commit2f4262c1273108abfcce00e897c520f5a7f4be41 (patch)
tree0915021d63092913de7cc88fe39088f936a4126d /src/disasm.rs
parente2ccf6053d58a2a478814f4a26018989f6fa0f26 (diff)
rearrange the proj
Diffstat (limited to 'src/disasm.rs')
-rw-r--r--src/disasm.rs97
1 files changed, 97 insertions, 0 deletions
diff --git a/src/disasm.rs b/src/disasm.rs
new file mode 100644
index 0000000..c9b3696
--- /dev/null
+++ b/src/disasm.rs
@@ -0,0 +1,97 @@
+use mos6502::{make_optable, make_addrtable};
+
+mod disops {
+ make_optable!(OPS, &str);
+ ids2strs!(adc, and, asl, bcc, bcs, beq, bit, bmi,
+ bne, bpl, brk, bvc, bvs, clc, cld, cli,
+ clv, cmp, cpx, cpy, dec, dex, dey, eor,
+ inc, inx, iny, jmp, jsr, lda, ldx, ldy,
+ lsr, nop, ora, pha, php, pla, plp, rol,
+ ror, rti, rts, sbc, sec, sed, sei, sta,
+ stx, sty, tax, tay, tsx, txa, txs, tya, nil);
+}
+
+mod disaddr {
+ pub type T<'a, 'b> = &'a mut Iterator<Item=&'b u8>;
+ make_addrtable!(ADDR_MODES, fn (T) -> String);
+ fn acc(_code: T) -> String {
+ "a".to_string()
+ }
+ fn imm(code: T) -> String {
+ format!("#${:02x}", code.next().unwrap())
+ }
+ fn zpg(code: T) -> String {
+ format!("${:02x}", code.next().unwrap())
+ }
+ fn zpx(code: T) -> String {
+ format!("${:02x}, x", code.next().unwrap())
+ }
+ fn zpy(code: T) -> String {
+ format!("${:02x}, y", code.next().unwrap())
+ }
+ fn rel(code: T) -> String {
+ let b = *code.next().unwrap() as i8 as i16;
+ if b >= 0 {
+ format!("+${:02x}, x", b)
+ } else {
+ format!("-${:02x}, x", -b)
+ }
+ }
+ fn abs(code: T) -> String {
+ let low = *code.next().unwrap() as u16;
+ let high = *code.next().unwrap() as u16;
+ format!("${:04x}", (high << 8) | low)
+ }
+ fn abx(code: T) -> String {
+ let low = *code.next().unwrap() as u16;
+ let high = *code.next().unwrap() as u16;
+ format!("${:04x}, x", (high << 8) | low)
+ }
+ fn aby(code: T) -> String {
+ let low = *code.next().unwrap() as u16;
+ let high = *code.next().unwrap() as u16;
+ format!("${:04x}, y", (high << 8) | low)
+ }
+ fn ind(code: T) -> String {
+ let low = *code.next().unwrap() as u16;
+ let high = *code.next().unwrap() as u16;
+ format!("(${:04x})", (high << 8) | low)
+ }
+ fn xin(code: T) -> String {
+ format!("(${:02x}, x)", code.next().unwrap())
+ }
+ fn iny(code: T) -> String {
+ format!("(${:02x}), y", code.next().unwrap())
+ }
+ fn nil(_code: T) -> String {
+ "".to_string()
+ }
+}
+
+pub struct Disassembler<'a, T> where T: Iterator<Item=&'a u8> {
+ raw_code: T
+}
+
+impl<'a, T> Disassembler<'a, T> where T: Iterator<Item=&'a u8> {
+ pub fn new(raw_code: T) -> Self {
+ Disassembler{raw_code}
+ }
+ fn parse(opcode: u8, code: &mut T) -> String {
+ format!("{} {}", disops::OPS[opcode as usize],
+ disaddr::ADDR_MODES[opcode as usize](code))
+ }
+}
+
+impl<'a, T> Iterator for Disassembler<'a, T> where T: Iterator<Item=&'a u8> {
+ type Item = String;
+ fn next(&mut self) -> Option<Self::Item> {
+ match self.raw_code.next() {
+ Some(opcode) => Some(Disassembler::parse(*opcode, &mut self.raw_code)),
+ None => None
+ }
+ }
+}
+
+pub fn parse(opcode: u8, code: &[u8]) -> String {
+ Disassembler::parse(opcode, &mut code.iter())
+}