1 #include "mips_emulator.h"
2 #include <capstone.h>
3
4 namespace REDasm {
5
MIPSEmulator(DisassemblerAPI * disassembler)6 MIPSEmulator::MIPSEmulator(DisassemblerAPI *disassembler): EmulatorT<u32>(disassembler)
7 {
8 EMULATE_INSTRUCTION(MIPS_INS_LB, &MIPSEmulator::emulateLxx);
9 EMULATE_INSTRUCTION(MIPS_INS_LBU, &MIPSEmulator::emulateLxx);
10 EMULATE_INSTRUCTION(MIPS_INS_LH, &MIPSEmulator::emulateLxx);
11 EMULATE_INSTRUCTION(MIPS_INS_LWR, &MIPSEmulator::emulateLxx);
12 EMULATE_INSTRUCTION(MIPS_INS_LWL, &MIPSEmulator::emulateLxx);
13 EMULATE_INSTRUCTION(MIPS_INS_LW, &MIPSEmulator::emulateLxx);
14 EMULATE_INSTRUCTION(MIPS_INS_LHU, &MIPSEmulator::emulateLxx);
15
16 EMULATE_INSTRUCTION(MIPS_INS_SB, &MIPSEmulator::emulateSxx);
17 EMULATE_INSTRUCTION(MIPS_INS_SH, &MIPSEmulator::emulateSxx);
18 EMULATE_INSTRUCTION(MIPS_INS_SWL, &MIPSEmulator::emulateSxx);
19 EMULATE_INSTRUCTION(MIPS_INS_SW, &MIPSEmulator::emulateSxx);
20 EMULATE_INSTRUCTION(MIPS_INS_SWR, &MIPSEmulator::emulateSxx);
21
22 EMULATE_INSTRUCTION(MIPS_INS_ADD, &MIPSEmulator::emulateMath);
23 EMULATE_INSTRUCTION(MIPS_INS_ADDI, &MIPSEmulator::emulateMath);
24 EMULATE_INSTRUCTION(MIPS_INS_ADDIU, &MIPSEmulator::emulateMath);
25 EMULATE_INSTRUCTION(MIPS_INS_ADDU, &MIPSEmulator::emulateMath);
26 EMULATE_INSTRUCTION(MIPS_INS_SUB, &MIPSEmulator::emulateMath);
27 EMULATE_INSTRUCTION(MIPS_INS_SUBU, &MIPSEmulator::emulateMath);
28 EMULATE_INSTRUCTION(MIPS_INS_MUL, &MIPSEmulator::emulateMath);
29 EMULATE_INSTRUCTION(MIPS_INS_AND, &MIPSEmulator::emulateMath);
30 EMULATE_INSTRUCTION(MIPS_INS_ANDI, &MIPSEmulator::emulateMath);
31 EMULATE_INSTRUCTION(MIPS_INS_OR, &MIPSEmulator::emulateMath);
32 EMULATE_INSTRUCTION(MIPS_INS_ORI, &MIPSEmulator::emulateMath);
33 EMULATE_INSTRUCTION(MIPS_INS_XOR, &MIPSEmulator::emulateMath);
34 EMULATE_INSTRUCTION(MIPS_INS_XORI, &MIPSEmulator::emulateMath);
35 EMULATE_INSTRUCTION(MIPS_INS_SLL, &MIPSEmulator::emulateMath);
36 EMULATE_INSTRUCTION(MIPS_INS_SLLV, &MIPSEmulator::emulateMath);
37 EMULATE_INSTRUCTION(MIPS_INS_SRL, &MIPSEmulator::emulateMath);
38 EMULATE_INSTRUCTION(MIPS_INS_SRLV, &MIPSEmulator::emulateMath);
39 EMULATE_INSTRUCTION(MIPS_INS_SRAV, &MIPSEmulator::emulateMath);
40 EMULATE_INSTRUCTION(MIPS_INS_LUI, &MIPSEmulator::emulateLui);
41
42 //EMULATE_INSTRUCTION(MIPS_INS_MULT, &MIPSEmulator::emulateMath);
43 //EMULATE_INSTRUCTION(MIPS_INS_MULTU, &MIPSEmulator::emulateMath);
44 //EMULATE_INSTRUCTION(MIPS_INS_DIV, &MIPSEmulator::emulateMath);
45 //EMULATE_INSTRUCTION(MIPS_INS_DIVU, &MIPSEmulator::emulateMath);
46 }
47
emulate(const InstructionPtr & instruction)48 void MIPSEmulator::emulate(const InstructionPtr &instruction)
49 {
50 this->writeReg(MIPS_REG_ZERO, 0); // Initialize $zero
51 return Emulator::emulate(instruction);
52 }
53
emulateMath(const InstructionPtr & instruction)54 void MIPSEmulator::emulateMath(const InstructionPtr &instruction) { this->aluOp(instruction, 0, 1, 2); }
55
emulateLui(const InstructionPtr & instruction)56 void MIPSEmulator::emulateLui(const InstructionPtr &instruction)
57 {
58 u64 value = 0;
59
60 if(!this->read(instruction->op(1), &value))
61 return;
62
63 this->writeOp(instruction->op(0), static_cast<u32>(value << 16));
64 }
65
emulateLxx(const InstructionPtr & instruction)66 void MIPSEmulator::emulateLxx(const InstructionPtr &instruction)
67 {
68 size_t size = 0;
69
70 if((instruction->id == MIPS_INS_LB) || (instruction->id == MIPS_INS_LBU))
71 size = sizeof(u8);
72 else if((instruction->id == MIPS_INS_LH) || (instruction->id == MIPS_INS_LHU))
73 size = sizeof(u16);
74 else if((instruction->id == MIPS_INS_LW) || (instruction->id == MIPS_INS_LWL) || (instruction->id == MIPS_INS_LWR))
75 size = sizeof(u32);
76 else
77 {
78 this->unhandled(instruction);
79 return;
80 }
81
82 u32 regvalue = 0, value = 0;
83 const Operand *op1 = instruction->op(0), *op2 = instruction->op(1);
84
85 if(!this->readOp(op2, &value))
86 return;
87
88 value += static_cast<u32>(op2->disp.displacement);
89
90 if(!this->readMem(static_cast<u32>(value), &value, static_cast<u32>(size)))
91 return;
92
93 this->readOp(op1, ®value);
94
95 if(instruction->id == MIPS_INS_LWL)
96 regvalue = (regvalue & 0xFFFF) | (value & 0xFFFF0000);
97 else if(instruction->id == MIPS_INS_LWR)
98 regvalue = (regvalue & 0xFFFF) | (value & 0x0000FFFF);
99 else
100 regvalue = value;
101
102 this->writeOp(op1, regvalue);
103 }
104
emulateSxx(const InstructionPtr & instruction)105 void MIPSEmulator::emulateSxx(const InstructionPtr &instruction)
106 {
107 size_t size = 0;
108
109 if(instruction->id == MIPS_INS_SB)
110 size = sizeof(u8);
111 else if(instruction->id == MIPS_INS_SH)
112 size = sizeof(u16);
113 else if((instruction->id == MIPS_INS_SW) || (instruction->id == MIPS_INS_SWL) || (instruction->id == MIPS_INS_SWR))
114 size = sizeof(u32);
115 else
116 {
117 this->unhandled(instruction);
118 return;
119 }
120
121 u32 regvalue = 0, memloc = 0, memvalue = 0;
122 const Operand *op1 = instruction->op(0), *op2 = instruction->op(1);
123
124 if(!this->readOp(op1, ®value) || !this->readOp(op2, &memloc))
125 return;
126
127 this->readMem(static_cast<u32>(memloc), &memvalue, static_cast<u32>(size));
128
129 if(instruction->id == MIPS_INS_SWL)
130 regvalue = (regvalue & 0xFFFF) | (memvalue & 0xFFFF0000);
131 else if(instruction->id == MIPS_INS_SWR)
132 regvalue = (regvalue & 0xFFFF) | (memvalue & 0x0000FFFF);
133
134 this->writeMem(memloc, regvalue);
135 }
136
137 } // namespace REDasm
138