1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
use crate::{Instruction, Opcode, Operand};
use crate::consts;

use std;
use std::fmt::{Display, Formatter};
impl Display for Instruction {
    fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> {
        write!(f, "{}", self.opcode)?;
        match self.operands[0] {
            Operand::Nothing => return Ok(()),
            x @ _ => {
                write!(f, " {}", x)?;
            }
        };
        match self.operands[1] {
            Operand::Nothing => return Ok(()),
            x @ _ => {
                write!(f, ", {}", x)?;
            }
        };
        Ok(())
    }
}

impl Display for Opcode {
    fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> {
        match self {
            Opcode::Invalid(a, b) => { write!(f, "invalid({:02x}{:02x})", a, b) },
            Opcode::NOP => { write!(f, "nop") },
            Opcode::MOVFF => { write!(f, "movff") },
            Opcode::MOVSF => { write!(f, "movsf") },
            Opcode::MOVSD => { write!(f, "movsd") },
            Opcode::CALL => { write!(f, "call") },
            Opcode::LFSR => { write!(f, "lfsr") },
            Opcode::GOTO => { write!(f, "goto") },
            Opcode::CALLW => { write!(f, "callw") },
            Opcode::CLRWDT => { write!(f, "clrwdt") },
            Opcode::DAW => { write!(f, "daw") },
            Opcode::POP => { write!(f, "pop") },
            Opcode::PUSH => { write!(f, "push") },
            Opcode::RESET => { write!(f, "reset") },
            Opcode::RETFIE => { write!(f, "retfie") },
            Opcode::RETFIE_FAST => { write!(f, "retfie_fast") },
            Opcode::RETURN => { write!(f, "return") },
            Opcode::RETURN_FAST => { write!(f, "return_fast") },
            Opcode::SLEEP => { write!(f, "sleep") },
            Opcode::TBLRD_I_S => { write!(f, "tblrd_i_s") },
            Opcode::TBLRD_S => { write!(f, "tblrd_s") },
            Opcode::TBLRD_S_D => { write!(f, "tblrd_s_d") },
            Opcode::TBLRD_S_I => { write!(f, "tblrd_s_i") },
            Opcode::TBLWT_I_S => { write!(f, "tblwt_i_s") },
            Opcode::TBLWT_S => { write!(f, "tblwt_s") },
            Opcode::TBLWT_S_D => { write!(f, "tblwt_s_d") },
            Opcode::TBLWT_S_I => { write!(f, "tblwt_s_i") },
            Opcode::MOVLB => { write!(f, "movlb") },
            Opcode::ADDLW => { write!(f, "addlw") },
            Opcode::MOVLW => { write!(f, "movlw") },
            Opcode::MULLW => { write!(f, "mullw") },
            Opcode::RETLW => { write!(f, "retlw") },
            Opcode::ANDLW => { write!(f, "andlw") },
            Opcode::XORLW => { write!(f, "xorlw") },
            Opcode::IORLW => { write!(f, "iorlw") },
            Opcode::SUBLW => { write!(f, "sublw") },
            Opcode::IORWF => { write!(f, "iorwf") },
            Opcode::ANDWF => { write!(f, "andwf") },
            Opcode::XORWF => { write!(f, "xorwf") },
            Opcode::COMF => { write!(f, "comf") },
            Opcode::MULWF => { write!(f, "mulwf") },
            Opcode::ADDWFC => { write!(f, "addwfc") },
            Opcode::ADDWF => { write!(f, "addwf") },
            Opcode::INCF => { write!(f, "incf") },
            Opcode::DECF => { write!(f, "decf") },
            Opcode::DECFSZ => { write!(f, "decfsz") },
            Opcode::RRCF => { write!(f, "rrcf") },
            Opcode::RLCF => { write!(f, "rlcf") },
            Opcode::SWAPF => { write!(f, "swapf") },
            Opcode::INCFSZ => { write!(f, "incfsz") },
            Opcode::RRNCF => { write!(f, "rrncf") },
            Opcode::RLNCF => { write!(f, "rlncf") },
            Opcode::INFSNZ => { write!(f, "infsnz") },
            Opcode::DCFSNZ => { write!(f, "dcfsnz") },
            Opcode::MOVF => { write!(f, "movf") },
            Opcode::SUBFWB => { write!(f, "subfwb") },
            Opcode::SUBWFB => { write!(f, "subwfb") },
            Opcode::SUBWF => { write!(f, "subwf") },
            Opcode::CPFSLT => { write!(f, "cpfslt") },
            Opcode::CPFSEQ => { write!(f, "cpfseq") },
            Opcode::CPFSGT => { write!(f, "cpfsgt") },
            Opcode::TSTFSZ => { write!(f, "tstfsz") },
            Opcode::SETF => { write!(f, "setf") },
            Opcode::CLRF => { write!(f, "clrf") },
            Opcode::NEGF => { write!(f, "negf") },
            Opcode::MOVWF => { write!(f, "movwf") },
            Opcode::BTG => { write!(f, "btg") },
            Opcode::BSF => { write!(f, "bsf") },
            Opcode::BCF => { write!(f, "bcf") },
            Opcode::BTFSS => { write!(f, "btfss") },
            Opcode::BTFSC => { write!(f, "btfsc") },
            Opcode::BZ => { write!(f, "bz") },
            Opcode::BNZ => { write!(f, "bnz") },
            Opcode::BC => { write!(f, "bc") },
            Opcode::BNC => { write!(f, "bnc") },
            Opcode::BOV => { write!(f, "bov") },
            Opcode::BNOV => { write!(f, "bnov") },
            Opcode::BN => { write!(f, "bn") },
            Opcode::BNN => { write!(f, "bnn") },
            Opcode::BRA => { write!(f, "bra") },
            Opcode::RCALL => { write!(f, "rcall") }
        }
    }
}

impl Display for Operand {
    fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> {
        match self {
            Operand::ImmediateU8(imm) => {
                write!(f, "#0x{:x}", imm)
            },
            Operand::ImmediateU32(imm) => {
                write!(f, "#0x{:x}", imm)
            },
            Operand::FileFSR(fsr) => {
                write!(f, "[FSR{}]", fsr)
            },
            Operand::File(file, banked) => {
                if *banked {
                    write!(f, "[banked 0x{:x}]", file)
                } else {
                    write!(f, "[{}]", consts::named_file(
                        if *file < 0x80 {
                            *file as u16
                        } else {
                            (*file as u16) | 0xf00u16
                        })
                    )
                }
            },
            Operand::AbsoluteFile(file) => {
                write!(f, "[{}]", consts::named_file(*file))
            },
            Operand::RedirectableFile(file, banked, direction) => {
                if *direction {
                    write!(f, "[todo -> F] ")?
                } else {
                    write!(f, "[todo -> W] ")?
                };

                if *banked {
                    write!(f, "[banked 0x{:x}]", file)
                } else {
                    write!(f, "[{}]", consts::named_file(
                        if *file < 0x80 {
                            *file as u16
                        } else {
                            (*file as u16) | 0xf00u16
                        })
                    )
                }
            },
            Operand::Nothing => {
                write!(f, "<No Operand>")
            }
        }
    }
}