yaxpeax_core/arch/msp430/
syntaxed_render.rs

1use termion::color;
2use yaxpeax_msp430::{Opcode, Operand, Instruction, Width};
3use std::collections::HashMap;
4
5pub fn opcode_color(opcode: Opcode) -> &'static color::Fg<&'static dyn color::Color> {
6    match opcode {
7        Opcode::Invalid(_) => { &color::Fg(&color::Red) }
8        Opcode::CALL |
9        Opcode::RETI => { &color::Fg(&color::LightGreen) }
10        Opcode::JNE |
11        Opcode::JEQ |
12        Opcode::JNC |
13        Opcode::JC |
14        Opcode::JN |
15        Opcode::JGE |
16        Opcode::JL |
17        Opcode::JMP => { &color::Fg(&color::Green) }
18        Opcode::MOV => { &color::Fg(&color::LightMagenta) }
19        Opcode::RRA |
20        Opcode::SXT |
21        Opcode::PUSH |
22        Opcode::AND |
23        Opcode::XOR |
24        Opcode::BIT |
25        Opcode::BIC |
26        Opcode::RRC |
27        Opcode::SWPB |
28        Opcode::BIS => { &color::Fg(&color::LightYellow) }
29        Opcode::ADD |
30        Opcode::ADDC |
31        Opcode::SUBC |
32        Opcode::SUB |
33        Opcode::DADD |
34        Opcode::CMP => { &color::Fg(&color::Yellow) }
35    }
36}
37
38use arch::msp430::PartialInstructionContext;
39impl <T> ::SyntaxedRender<u16, T, ()> for Instruction where T: PartialInstructionContext {
40    fn render(&self, context: Option<&T>, _function_table: &HashMap<u16, ()>) -> String {
41        fn render_operand<T: PartialInstructionContext>(operand: &Operand, context: Option<&T>) -> String {
42            fn signed_hex(num: i16) -> String {
43                if num >= 0 {
44                    format!("+{:#x}", num)
45                } else {
46                    format!("-{:#x}", -num)
47                }
48            }
49            match operand {
50                Operand::Register(0) => { "pc".to_owned() },
51                Operand::Register(1) => { "sp".to_owned() },
52                Operand::Register(2) => { "sr".to_owned() },
53                Operand::Register(3) => { "cg".to_owned() }, // this really shouldn't come up, since any read/write to CG should normalize to const
54                Operand::Register(reg) => {
55                    format!("r{}", reg)
56                },
57                Operand::Indexed(0, offset) => {
58                    format!("{}(pc)", signed_hex(*offset as i16))
59                },
60                Operand::Indexed(1, offset) => {
61                    format!("{}(sp)", signed_hex(*offset as i16))
62                },
63                Operand::Indexed(2, offset) => {
64                    format!("{}(sr)", signed_hex(*offset as i16))
65                },
66                Operand::Indexed(3, offset) => {
67                    format!("{}(cg)", signed_hex(*offset as i16))
68                },
69                Operand::Indexed(reg, offset) => {
70                    format!("{}(r{})", signed_hex(*offset as i16), reg)
71                },
72                Operand::RegisterIndirect(0) => { "@pc".to_owned() }
73                Operand::RegisterIndirect(1) => { "@sp".to_owned() }
74                Operand::RegisterIndirect(2) => { "@sr".to_owned() }
75                Operand::RegisterIndirect(3) => { "@cg".to_owned() }
76                Operand::RegisterIndirect(reg) => {
77                    format!("@r{}", reg)
78                },
79                Operand::IndirectAutoinc(0) => { "@pc+".to_owned() }
80                Operand::IndirectAutoinc(1) => { "@sp+".to_owned() }
81                Operand::IndirectAutoinc(2) => { "@sr+".to_owned() }
82                Operand::IndirectAutoinc(3) => { "@cg+".to_owned() } // this one just makes no sense
83                Operand::IndirectAutoinc(reg) => {
84                    format!("@r{}+", reg)
85                },
86                Operand::Offset(offset) => {
87                    match context.and_then(|ctx| ctx.address()) {
88                        Some(address) => {
89                            // TODO: Uhhhh.. is this supposed to be instr len, not 2?
90                            format!("{:#x}", address.wrapping_add((*offset as u16).wrapping_mul(2)).wrapping_add(2))
91                        },
92                        None => {
93                            format!("{}(pc)", signed_hex(*offset as i16))
94                        }
95                    }
96                },
97                Operand::Symbolic(offset) => {
98                    match context.and_then(|ctx| ctx.address()) {
99                        Some(address) => {
100                            format!("{:#x}", address.wrapping_add(*offset))
101                        },
102                        None => {
103                            format!("{}(pc)", signed_hex(*offset as i16))
104                        }
105                    }
106                },
107                Operand::Immediate(imm) => {
108                    format!("#{:#x}", imm)
109                },
110                Operand::Absolute(offset) => {
111                    format!("&{:#x}", offset)
112                },
113                Operand::Const4 => {
114                    "4".to_owned()
115                },
116                Operand::Const8 => {
117                    "8".to_owned()
118                },
119                Operand::Const0 => {
120                    "0".to_owned()
121                },
122                Operand::Const1 => {
123                    "1".to_owned()
124                },
125                Operand::Const2 => {
126                    "2".to_owned()
127                },
128                Operand::ConstNeg1 => {
129                    "-1".to_owned()
130                },
131                Operand::Nothing => {
132                    "<No Operand>".to_owned()
133                }
134            }
135        }
136
137        // try to recover some of the "emulated" instructions... fall back with a naive render
138        match self {
139            Instruction { opcode: Opcode::MOV, operands: [Operand::Const0, Operand::Const0], op_width: _ } => {
140                format!("{}{}{}", color::Fg(color::Blue), "nop", color::Fg(color::Reset))
141            },
142            Instruction { opcode: Opcode::MOV, operands: [Operand::Const0, dest], op_width: _ } => {
143                let start_color = opcode_color(Opcode::MOV);
144                format!("{}{}{} {}", start_color, "clr", color::Fg(color::Reset), render_operand(&dest, context))
145            },
146            Instruction { opcode: Opcode::MOV, operands: [Operand::IndirectAutoinc(1), Operand::Register(0)], op_width: Width::W } => {
147                // this is a pop
148                let start_color = opcode_color(Opcode::CALL);
149                format!("{}{}{}", start_color, "ret", color::Fg(color::Reset))
150            },
151            Instruction { opcode: Opcode::MOV, operands: [Operand::IndirectAutoinc(1), dest], op_width: Width::W } => {
152                // this is a pop
153                let start_color = opcode_color(Opcode::PUSH);
154                format!("{}{}{} {}", start_color, "pop", color::Fg(color::Reset), render_operand(&dest, context))
155            },
156            Instruction { opcode: Opcode::MOV, operands: [src, Operand::Register(0)], op_width: Width::W } => {
157                // br [src]
158                let start_color = opcode_color(Opcode::JMP);
159                format!("{}{}{} {}", start_color, "br", color::Fg(color::Reset), render_operand(&src, context))
160            }
161            _ => {
162                let start_color = opcode_color(self.opcode);
163                let mut result = format!("{}{}{}{}", start_color, self.opcode, match self.op_width {
164                    Width::W => "",
165                    Width::B => ".b"
166                }, color::Fg(color::Reset));
167
168                match self.operands[0] {
169                    Operand::Nothing => { return result; },
170                    x @ _ => {
171                        result.push(' ');
172                        result.push_str(&render_operand(&x, context));
173                    }
174                };
175                match self.operands[1] {
176                    Operand::Nothing => { return result; },
177                    x @ _ => {
178                        result.push(',');
179                        result.push(' ');
180                        result.push_str(&render_operand(&x, context));
181                    }
182                };
183                result
184            }
185        }
186    }
187}
188