Skip to content

Instantly share code, notes, and snippets.

@ChillMagic
Last active July 21, 2024 02:07
Show Gist options
  • Select an option

  • Save ChillMagic/f70c84a278e817863bed2252adbd10d8 to your computer and use it in GitHub Desktop.

Select an option

Save ChillMagic/f70c84a278e817863bed2252adbd10d8 to your computer and use it in GitHub Desktop.
8086 decoder
#include <string>
#include <vector>
const char *getOpcodeKindName(const OpcodeKind &kind) {
switch (kind) {
case OpcodeKind::Original: return "Original";
case OpcodeKind::Move: return "Move";
case OpcodeKind::Store: return "Store";
case OpcodeKind::LoadEA: return "LoadEA";
case OpcodeKind::LoadES: return "LoadES";
case OpcodeKind::LoadDS: return "LoadDS";
case OpcodeKind::Add: return "Add";
case OpcodeKind::Sub: return "Sub";
case OpcodeKind::Adc: return "Adc";
case OpcodeKind::Sbb: return "Sbb";
case OpcodeKind::Inc: return "Inc";
case OpcodeKind::Dec: return "Dec";
case OpcodeKind::And: return "And";
case OpcodeKind::Or: return "Or";
case OpcodeKind::Xor: return "Xor";
case OpcodeKind::Push: return "Push";
case OpcodeKind::Pop: return "Pop";
case OpcodeKind::Cmp: return "Cmp";
case OpcodeKind::Test: return "Test";
case OpcodeKind::Jump: return "Jump";
case OpcodeKind::Call: return "Call";
case OpcodeKind::Return: return "Return";
case OpcodeKind::IntReturn: return "IntReturn";
case OpcodeKind::Int: return "Int";
case OpcodeKind::Nop: return "Nop";
case OpcodeKind::Rol: return "Rol";
case OpcodeKind::Ror: return "Ror";
case OpcodeKind::Rcl: return "Rcl";
case OpcodeKind::Rcr: return "Rcr";
case OpcodeKind::Shl: return "Shl";
case OpcodeKind::Shr: return "Shr";
case OpcodeKind::Sar: return "Sar";
case OpcodeKind::Daa: return "Daa";
case OpcodeKind::Das: return "Das";
case OpcodeKind::Aaa: return "Aaa";
case OpcodeKind::Aas: return "Aas";
case OpcodeKind::Aam: return "Aam";
case OpcodeKind::Aad: return "Aad";
case OpcodeKind::In: return "In";
case OpcodeKind::Out: return "Out";
case OpcodeKind::Xchg: return "Xchg";
case OpcodeKind::Not: return "Not";
case OpcodeKind::Neg: return "Neg";
case OpcodeKind::Mul: return "Mul";
case OpcodeKind::Div: return "Div";
case OpcodeKind::Imul: return "Imul";
case OpcodeKind::Idiv: return "Idiv";
case OpcodeKind::StringHandle: return "StringHandle";
case OpcodeKind::CallBack: return "CallBack";
case OpcodeKind::Other: return "Other";
default: return "[ILLEGAL]";
}
}
size_t getOpArgCount(const Opcode &code) {
return getOpcodeArgCount(code);
}
const char *getOpopkindName(const Opcode::Opopkind &opopkind) {
switch (opopkind) {
case Opcode::M: return "M";
case Opcode::R: return "R";
case Opcode::I: return "I";
case Opcode::C: return "C";
case Opcode::S: return "S";
case Opcode::P: return "P";
case Opcode::K: return "K";
}
return "?";
}
const char *get_str(uint8_t c);
std::string get_str2(uint16_t c) {
union {
uint8_t a[2];
uint16_t b;
} x;
x.b = c;
return std::string(get_str(x.a[1])) + get_str(x.a[0]);
}
std::string get_str4(uint32_t c) {
union {
uint16_t a[2];
uint32_t b;
} x;
x.b = c;
return std::string(get_str2(x.a[1])) + get_str2(x.a[0]);
}
template <typename T>
std::string get_signed_number(const T &num) {
if (num < 0) {
return std::to_string(num);
} else {
return "+" + std::to_string(num);
}
}
const char * getDSNameWithPrefix(const OpcodePrefix &prefix) {
switch (prefix) {
case OpcodePrefix::lea: return "";
case OpcodePrefix::seg_es: return "es+";
case OpcodePrefix::seg_cs: return "cs+";
case OpcodePrefix::seg_ss: return "ss+";
case OpcodePrefix::seg_ds: return "ds+";
default: return "ds+";
}
}
const char * getSSNameWithPrefix(const OpcodePrefix &prefix) {
switch (prefix) {
case OpcodePrefix::lea: return "";
case OpcodePrefix::seg_es: return "es+";
case OpcodePrefix::seg_cs: return "cs+";
case OpcodePrefix::seg_ss: return "ss+";
case OpcodePrefix::seg_ds: return "ds+";
default: return "ss+";
}
}
std::string get_rmea_string(const OpcodePrefix &prefix, uint8_t idx, uint16_t off) {
switch (idx) {
case 0: return std::string(getDSNameWithPrefix(prefix))+"bx+(i)si"+(off == 0 ? std::string() : get_signed_number(static_cast<int16_t>(off)));
case 1: return std::string(getDSNameWithPrefix(prefix))+"bx+(i)di"+(off == 0 ? std::string() : get_signed_number(static_cast<int16_t>(off)));
case 2: return std::string(getSSNameWithPrefix(prefix))+"bp+(i)si"+(off == 0 ? std::string() : get_signed_number(static_cast<int16_t>(off)));
case 3: return std::string(getSSNameWithPrefix(prefix))+"bp+(i)di"+(off == 0 ? std::string() : get_signed_number(static_cast<int16_t>(off)));
case 4: return std::string(getDSNameWithPrefix(prefix))+"si"+(off == 0 ? std::string() : get_signed_number(static_cast<int16_t>(off)));
case 5: return std::string(getDSNameWithPrefix(prefix))+"di"+(off == 0 ? std::string() : get_signed_number(static_cast<int16_t>(off)));
case 6: return std::string(getSSNameWithPrefix(prefix))+"bp"+(off == 0 ? std::string() : get_signed_number(static_cast<int16_t>(off)));
case 7: return std::string(getDSNameWithPrefix(prefix))+"bx"+(off == 0 ? std::string() : get_signed_number(static_cast<int16_t>(off)));
case 8: return std::string(getDSNameWithPrefix(prefix))+std::to_string(off);
default: fprintf(stderr, "illegal rmea index %02x\n", idx); std::exit(-1);
}
}
std::string getOpStr(const Opcode::Operate &operate, const Opcode &code) {
switch (operate.kind) {
case Opcode::M:
return std::string("M(") + get_rmea_string(code.getPrefix(), operate.idx, operate.value) + ")";
case Opcode::R:
return std::string("R(") + getRegisterName(Register(operate.idx)) + ")";
case Opcode::I:
return std::string("I(") + get_str2(operate.value) + ")";
case Opcode::C:
return std::string("C(") + get_str(operate.idx) + ")";
case Opcode::S:
return std::string("S(") + getSegmentName(SegmentK(operate.idx)) + ")";
case Opcode::P:
return std::string("P(") + (operate.idx == Opcode::getOpMask() ? get_str2(operate.value) : getRegisterName(Register(operate.idx))) + ")";
case Opcode::K:
return std::string("K(") + std::to_string(operate.idx) + ")";
default:
std::fprintf(stderr, "ERROR\n");
std::exit(-1);
}
}
uint32_t get_csip(uint16_t cs, uint16_t ip) {
return (uint32_t(cs) << 4) | uint32_t(ip);
}
std::string dumpOpcode(const Opcode &code, size_t offset, const std::vector<uint8_t> &memory) {
auto kind_name = getOpcodeKindName(code.getKind());
size_t op_count = getOpArgCount(code);
const char *prefix_char = "";
switch (code.getPrefix()) {
// case OpcodePrefix::none: prefix_char = ""; break;
// case OpcodePrefix::lea: prefix_char = ""; break;
// case OpcodePrefix::seg_es: prefix_char = "seg_es "; break;
// case OpcodePrefix::seg_cs: prefix_char = "seg_cs "; break;
// case OpcodePrefix::seg_ss: prefix_char = "seg_ss "; break;
// case OpcodePrefix::seg_ds: prefix_char = "seg_ds "; break;
case OpcodePrefix::repnz: prefix_char = "repnz "; break;
case OpcodePrefix::repz: prefix_char = "repz "; break;
default: prefix_char = ""; break;
}
if (op_count != -1) {
switch (op_count) {
case 0: return std::string(prefix_char) + kind_name;
case 1: return std::string(prefix_char) + std::string(kind_name) + " " + getOpStr(code.getOp<1>(), code);
case 2: return std::string(prefix_char) + std::string(kind_name) + " " + getOpStr(code.getOp<1>(), code) + " " + getOpStr(
code.getOp<2>(), code);
}
} else if (code.getKind() == OpcodeKind::Jump || code.getKind() == OpcodeKind::Call) {
uint32_t new_pos = offset + code.getLength() + (int16_t)code.getIMMData();
std::string new_pos_str = get_str4(new_pos);
std::string offset_str = std::string("(offset:") + std::to_string((int16_t)code.getIMMData()) + ")";
switch (code.getOp<2>().idx) {
case 0: return std::string(prefix_char) + kind_name + " " + new_pos_str + offset_str + " " + getOpStr(
code.getOp<1>(), code);
case 1: return std::string(prefix_char) + kind_name + " " + new_pos_str + offset_str;
case 2: return std::string(prefix_char) + kind_name + " " + getOpStr(code.getOp<1>(), code);
case 3: {
auto new_ip = code.getRMEAData();
auto new_cs = code.getIMMData();
uint32_t csip = get_csip(new_cs, new_ip);
return std::string(prefix_char) + kind_name + " " + get_str4(csip) + "(" + "cs:" + get_str2(new_cs) + " " + "ip:" + get_str2(new_ip) + ")";
}
case 4: return std::string(prefix_char) + kind_name + " " + getOpStr(code.getOp<1>(), code);
}
} else {
return std::string(prefix_char) + kind_name;
}
std::fprintf(stderr, "ILL OPCODE\n");
std::exit(-1);
}
#pragma once
#include <cstdint>
#include <cstddef>
#include <utility>
#include <cstdio>
#include <cstdlib>
#include <set>
using size_t = std::size_t;
class Fetcher {
public:
virtual ~Fetcher() = default;
uint8_t fetch_b() { auto result = _base_fetch_b(); count += 1; return result; }
uint16_t fetch_w() { auto result = _base_fetch_w(); count += 2; return result; }
uint16_t fetch_bs() { auto result = _base_fetch_bs(); count += 1; return result; }
virtual size_t getCount() const { return count; }
virtual void setCount(size_t new_count) { count = new_count; }
uint16_t fetch_with_judge(bool is_u8) {
if (is_u8) {
return fetch_b();
} else {
return fetch_w();
}
};
protected:
size_t count = 0;
virtual uint8_t _base_fetch_b() = 0;
virtual uint16_t _base_fetch_w() = 0;
virtual uint16_t _base_fetch_bs() = 0;
};
enum class Register {
r8_al,
r8_cl,
r8_dl,
r8_bl,
r8_ah,
r8_ch,
r8_dh,
r8_bh,
r16_ax,
r16_cx,
r16_dx,
r16_bx,
r16_sp,
r16_bp,
r16_si,
r16_di,
Unknown,
};
static Register joinRegister(uint8_t base /*0~7*/, bool is_u8) {
return Register(base | (is_u8 ? 0 : (1 << 3)));
}
const char *getRegisterName(const Register &reg) {
switch (reg) {
case Register::r8_al: return "r8::al";
case Register::r8_cl: return "r8::cl";
case Register::r8_dl: return "r8::dl";
case Register::r8_bl: return "r8::bl";
case Register::r8_ah: return "r8::ah";
case Register::r8_ch: return "r8::ch";
case Register::r8_dh: return "r8::dh";
case Register::r8_bh: return "r8::bh";
case Register::r16_ax: return "r16:ax";
case Register::r16_cx: return "r16:cx";
case Register::r16_dx: return "r16:dx";
case Register::r16_bx: return "r16:bx";
case Register::r16_sp: return "r16:sp";
case Register::r16_bp: return "r16:bp";
case Register::r16_si: return "r16:si";
case Register::r16_di: return "r16:di";
case Register::Unknown: return "unknow";
default: std::fprintf(stderr, "Unknown reg %d\n", static_cast<int>(reg)); std::exit(-1);
}
}
enum class SegmentK {
es,
cs,
ss,
ds,
fs,
gs,
Unknown,
};
const char *getSegmentName(const SegmentK &seg) {
switch (seg) {
case SegmentK::es: return "seg:es";
case SegmentK::cs: return "seg:cs";
case SegmentK::ss: return "seg:ss";
case SegmentK::ds: return "seg:ds";
case SegmentK::fs: return "seg:fs";
case SegmentK::gs: return "seg:gs";
case SegmentK::Unknown: return "unknow";
default: std::fprintf(stderr, "Unknown seg %d\n", static_cast<int>(seg)); std::exit(-1);
}
}
const char *get_str(uint8_t c) {
switch (c) {
case 0x00: return "00";
case 0x01: return "01";
case 0x02: return "02";
case 0x03: return "03";
case 0x04: return "04";
case 0x05: return "05";
case 0x06: return "06";
case 0x07: return "07";
case 0x08: return "08";
case 0x09: return "09";
case 0x0a: return "0a";
case 0x0b: return "0b";
case 0x0c: return "0c";
case 0x0d: return "0d";
case 0x0e: return "0e";
case 0x0f: return "0f";
case 0x10: return "10";
case 0x11: return "11";
case 0x12: return "12";
case 0x13: return "13";
case 0x14: return "14";
case 0x15: return "15";
case 0x16: return "16";
case 0x17: return "17";
case 0x18: return "18";
case 0x19: return "19";
case 0x1a: return "1a";
case 0x1b: return "1b";
case 0x1c: return "1c";
case 0x1d: return "1d";
case 0x1e: return "1e";
case 0x1f: return "1f";
case 0x20: return "20";
case 0x21: return "21";
case 0x22: return "22";
case 0x23: return "23";
case 0x24: return "24";
case 0x25: return "25";
case 0x26: return "26";
case 0x27: return "27";
case 0x28: return "28";
case 0x29: return "29";
case 0x2a: return "2a";
case 0x2b: return "2b";
case 0x2c: return "2c";
case 0x2d: return "2d";
case 0x2e: return "2e";
case 0x2f: return "2f";
case 0x30: return "30";
case 0x31: return "31";
case 0x32: return "32";
case 0x33: return "33";
case 0x34: return "34";
case 0x35: return "35";
case 0x36: return "36";
case 0x37: return "37";
case 0x38: return "38";
case 0x39: return "39";
case 0x3a: return "3a";
case 0x3b: return "3b";
case 0x3c: return "3c";
case 0x3d: return "3d";
case 0x3e: return "3e";
case 0x3f: return "3f";
case 0x40: return "40";
case 0x41: return "41";
case 0x42: return "42";
case 0x43: return "43";
case 0x44: return "44";
case 0x45: return "45";
case 0x46: return "46";
case 0x47: return "47";
case 0x48: return "48";
case 0x49: return "49";
case 0x4a: return "4a";
case 0x4b: return "4b";
case 0x4c: return "4c";
case 0x4d: return "4d";
case 0x4e: return "4e";
case 0x4f: return "4f";
case 0x50: return "50";
case 0x51: return "51";
case 0x52: return "52";
case 0x53: return "53";
case 0x54: return "54";
case 0x55: return "55";
case 0x56: return "56";
case 0x57: return "57";
case 0x58: return "58";
case 0x59: return "59";
case 0x5a: return "5a";
case 0x5b: return "5b";
case 0x5c: return "5c";
case 0x5d: return "5d";
case 0x5e: return "5e";
case 0x5f: return "5f";
case 0x60: return "60";
case 0x61: return "61";
case 0x62: return "62";
case 0x63: return "63";
case 0x64: return "64";
case 0x65: return "65";
case 0x66: return "66";
case 0x67: return "67";
case 0x68: return "68";
case 0x69: return "69";
case 0x6a: return "6a";
case 0x6b: return "6b";
case 0x6c: return "6c";
case 0x6d: return "6d";
case 0x6e: return "6e";
case 0x6f: return "6f";
case 0x70: return "70";
case 0x71: return "71";
case 0x72: return "72";
case 0x73: return "73";
case 0x74: return "74";
case 0x75: return "75";
case 0x76: return "76";
case 0x77: return "77";
case 0x78: return "78";
case 0x79: return "79";
case 0x7a: return "7a";
case 0x7b: return "7b";
case 0x7c: return "7c";
case 0x7d: return "7d";
case 0x7e: return "7e";
case 0x7f: return "7f";
case 0x80: return "80";
case 0x81: return "81";
case 0x82: return "82";
case 0x83: return "83";
case 0x84: return "84";
case 0x85: return "85";
case 0x86: return "86";
case 0x87: return "87";
case 0x88: return "88";
case 0x89: return "89";
case 0x8a: return "8a";
case 0x8b: return "8b";
case 0x8c: return "8c";
case 0x8d: return "8d";
case 0x8e: return "8e";
case 0x8f: return "8f";
case 0x90: return "90";
case 0x91: return "91";
case 0x92: return "92";
case 0x93: return "93";
case 0x94: return "94";
case 0x95: return "95";
case 0x96: return "96";
case 0x97: return "97";
case 0x98: return "98";
case 0x99: return "99";
case 0x9a: return "9a";
case 0x9b: return "9b";
case 0x9c: return "9c";
case 0x9d: return "9d";
case 0x9e: return "9e";
case 0x9f: return "9f";
case 0xa0: return "a0";
case 0xa1: return "a1";
case 0xa2: return "a2";
case 0xa3: return "a3";
case 0xa4: return "a4";
case 0xa5: return "a5";
case 0xa6: return "a6";
case 0xa7: return "a7";
case 0xa8: return "a8";
case 0xa9: return "a9";
case 0xaa: return "aa";
case 0xab: return "ab";
case 0xac: return "ac";
case 0xad: return "ad";
case 0xae: return "ae";
case 0xaf: return "af";
case 0xb0: return "b0";
case 0xb1: return "b1";
case 0xb2: return "b2";
case 0xb3: return "b3";
case 0xb4: return "b4";
case 0xb5: return "b5";
case 0xb6: return "b6";
case 0xb7: return "b7";
case 0xb8: return "b8";
case 0xb9: return "b9";
case 0xba: return "ba";
case 0xbb: return "bb";
case 0xbc: return "bc";
case 0xbd: return "bd";
case 0xbe: return "be";
case 0xbf: return "bf";
case 0xc0: return "c0";
case 0xc1: return "c1";
case 0xc2: return "c2";
case 0xc3: return "c3";
case 0xc4: return "c4";
case 0xc5: return "c5";
case 0xc6: return "c6";
case 0xc7: return "c7";
case 0xc8: return "c8";
case 0xc9: return "c9";
case 0xca: return "ca";
case 0xcb: return "cb";
case 0xcc: return "cc";
case 0xcd: return "cd";
case 0xce: return "ce";
case 0xcf: return "cf";
case 0xd0: return "d0";
case 0xd1: return "d1";
case 0xd2: return "d2";
case 0xd3: return "d3";
case 0xd4: return "d4";
case 0xd5: return "d5";
case 0xd6: return "d6";
case 0xd7: return "d7";
case 0xd8: return "d8";
case 0xd9: return "d9";
case 0xda: return "da";
case 0xdb: return "db";
case 0xdc: return "dc";
case 0xdd: return "dd";
case 0xde: return "de";
case 0xdf: return "df";
case 0xe0: return "e0";
case 0xe1: return "e1";
case 0xe2: return "e2";
case 0xe3: return "e3";
case 0xe4: return "e4";
case 0xe5: return "e5";
case 0xe6: return "e6";
case 0xe7: return "e7";
case 0xe8: return "e8";
case 0xe9: return "e9";
case 0xea: return "ea";
case 0xeb: return "eb";
case 0xec: return "ec";
case 0xed: return "ed";
case 0xee: return "ee";
case 0xef: return "ef";
case 0xf0: return "f0";
case 0xf1: return "f1";
case 0xf2: return "f2";
case 0xf3: return "f3";
case 0xf4: return "f4";
case 0xf5: return "f5";
case 0xf6: return "f6";
case 0xf7: return "f7";
case 0xf8: return "f8";
case 0xf9: return "f9";
case 0xfa: return "fa";
case 0xfb: return "fb";
case 0xfc: return "fc";
case 0xfd: return "fd";
case 0xfe: return "fe";
case 0xff: return "ff";
default: return "--";
}
}
struct MaskValueSetter {
uint8_t pos;
uint8_t len;
uint8_t mask;
explicit MaskValueSetter(uint8_t pos, uint8_t len)
: pos(pos), len(len), mask(getMask(pos, len)) {}
static uint8_t getMask(uint8_t pos, uint8_t len) {
uint8_t mask = 0x0;
for (uint8_t i = 0; i < len; i++) {
mask <<= 1;
mask |= 1;
}
return mask << pos;
}
void set(uint8_t &ref, uint8_t value) {
ref &= (uint8_t)~mask;
ref |= (value << pos) & mask;
}
uint8_t get(const uint8_t &ref) const {
return (ref & mask) >> pos;
}
uint8_t getMask() const {
return mask;
}
};
static Register getRegFromRM(uint8_t rm, bool is_u8) {
static Register lookupRMregb[] = {
Register::r8_al,
Register::r8_cl,
Register::r8_dl,
Register::r8_bl,
Register::r8_ah,
Register::r8_ch,
Register::r8_dh,
Register::r8_bh,
};
static Register lookupRMregw[] = {
Register::r16_ax,
Register::r16_cx,
Register::r16_dx,
Register::r16_bx,
Register::r16_sp,
Register::r16_bp,
Register::r16_si,
Register::r16_di,
};
if (is_u8) {
return lookupRMregb[(rm >> 3) & 0x7];
} else {
return lookupRMregw[(rm >> 3) & 0x7];
}
}
static Register getEARegFromRM(uint8_t rm, bool is_u8) {
static Register lookupRMEAregb[] = {
Register::r8_al,Register::r8_cl,Register::r8_dl,Register::r8_bl,Register::r8_ah,Register::r8_ch,Register::r8_dh,Register::r8_bh,
};
static Register lookupRMEAregw[] = {
Register::r16_ax,Register::r16_cx,Register::r16_dx,Register::r16_bx,Register::r16_sp,Register::r16_bp,Register::r16_si,Register::r16_di,
};
if (rm < 0xc0) {
return Register::Unknown;
} else if (is_u8) {
return lookupRMEAregb[rm & 0x7];
} else {
return lookupRMEAregw[rm & 0x7];
}
}
enum class OpcodeKind : uint8_t {
Original = 0x00,
Move,
Store,
LoadEA,
LoadES,
LoadDS,
Add,
Sub,
Adc,
Sbb,
Inc,
Dec,
And,
Or,
Xor,
Push,
Pop,
Cmp,
Test,
Jump,
Call,
Return,
IntReturn,
Int,
Nop,
Rol,
Ror,
Rcl,
Rcr,
Shl,
Shr,
Sar,
Daa,
Das,
Aaa,
Aas,
Aam,
Aad,
In,
Out,
Xchg,
Not,
Neg,
Mul,
Div,
Imul,
Idiv,
StringHandle,
CallBack, // TODO
Other,
};
enum class OpcodePrefix {
none = 0,
seg_es,
seg_cs,
seg_ss,
seg_ds,
repnz,
repz,
lea,
};
enum class StringHandleFunction {
MOVSB,
MOVSW,
CMPSB,
CMPSW,
STOSB,
STOSW,
LODSB,
LODSW,
SCASB,
SCASW,
};
struct Opcode {
union {
uint64_t code = 0;
uint8_t data[8];
};
public:
enum Opopkind {
M,
R,
I,
C,
S,
P,
K,
};
struct Operate {
Opopkind kind;
uint8_t idx;
uint16_t value;
template <typename IdxType>
explicit Operate(Opopkind kind, const IdxType &idx, uint16_t value = 0) : kind(kind), idx(static_cast<uint8_t>(idx)), value(value) {}
static Operate Immediate(uint16_t value) {
return Operate(Opopkind::I, 0, value);
}
};
public:
Opcode(uint64_t code = 0) : code(code) {}
public:
static Opcode illegal() {
Opcode result;
result.code = 0xffffffffffffffff;
return result;
}
bool is_illegal() const {
return this->code == illegal().code;
}
public:
void setKind(OpcodeKind kind) {
static MaskValueSetter setter(0, 7);
setter.set(data[7], (uint8_t)kind);
}
OpcodeKind getKind() const {
static MaskValueSetter setter(0, 7);
return OpcodeKind(setter.get(data[7]));
}
bool isU8() const {
static MaskValueSetter setter(7, 1);
return setter.get(data[7]) == 0;
}
void setU8(bool is_u8 = true) {
static MaskValueSetter setter(7, 1);
setter.set(data[7], is_u8 ? 0 : 1);
}
void setLength(size_t length) {
static MaskValueSetter setter(5, 3);
setter.set(data[0], length);
}
size_t getLength() const {
static MaskValueSetter setter(5, 3);
return setter.get(data[0]);
}
void setPrefix(OpcodePrefix prefix) {
static MaskValueSetter setter(2, 3);
setter.set(data[0], (uint8_t)prefix);
}
OpcodePrefix getPrefix() const {
static MaskValueSetter setter(2, 3);
return OpcodePrefix(setter.get(data[0]));
}
// opopkind: 2bits
// reg: 4bits
// rmea1: 5bits
// rmea2: 2bytes
// bytecount: data[7] 7,1
// op: 0,5
// opopkind: 5,3
// op1: data[6]
// op2: data[5]
// rmea2: data: 3,4
// imm: data: 3,4
static uint8_t getOpMask() {
static MaskValueSetter setter(0, 5);
return setter.getMask();
}
private:
template <uint8_t idx>
uint8_t getOpBase() const {
static MaskValueSetter setter(0, 5);
return setter.get(data[idx]);
}
template <uint8_t idx>
void setOpBase(uint8_t value) {
static MaskValueSetter setter(0, 5);
setter.set(data[idx], value);
}
template <uint8_t idx>
Opopkind getOpopkindBase() const {
static MaskValueSetter setter(5, 3);
return (Opopkind)setter.get(data[idx]);
}
template <uint8_t idx>
void setOpopkindBase(Opopkind value) {
static MaskValueSetter setter(5, 3);
setter.set(data[idx], value);
}
static constexpr uint8_t _get_data_idx(uint8_t idx) {
return idx == 1 ? 6 : 5;
}
public:
template <uint8_t idx>
void setOp(const Operate &operate) {
setOpopkindBase<_get_data_idx(idx)>(operate.kind);
setOpBase<_get_data_idx(idx)>(operate.idx);
switch (operate.kind) {
case M:
setRMEAData(operate.value);
break;
case I:
case P:
setIMMData(operate.value);
break;
case R:
case C:
case S:
case K:
break;
}
}
template <uint8_t idx>
Operate getOp() const {
Opopkind kind = getOpopkindBase<_get_data_idx(idx)>();
uint8_t data = getOpBase<_get_data_idx(idx)>();
uint16_t value = 0;
switch (kind) {
case M:
value = getRMEAData();
break;
case I:
case P:
value = getIMMData();
break;
case R:
case C:
case S:
case K:
break;
}
return Operate(kind, data, value);
}
public:
void setRMEAData(uint16_t rmea_data) {
// 4 3
*reinterpret_cast<uint16_t*>(data + 3) = rmea_data;
}
uint16_t getRMEAData() const {
// 4 3
return *reinterpret_cast<const uint16_t*>(data + 3);
}
void setIMMData(uint16_t imm_data) {
// 2 1
*reinterpret_cast<uint16_t*>(data + 1) = imm_data;
}
uint16_t getIMMData() const {
// 2 1
return *reinterpret_cast<const uint16_t*>(data + 1);
}
};
size_t getOpcodeArgCount(const Opcode &code) {
switch (code.getKind()) {
case OpcodeKind::Add:
case OpcodeKind::Or:
case OpcodeKind::Adc:
case OpcodeKind::Sbb:
case OpcodeKind::And:
case OpcodeKind::Sub:
case OpcodeKind::Xor:
case OpcodeKind::Cmp:
case OpcodeKind::Move:
case OpcodeKind::LoadEA:
case OpcodeKind::LoadES:
case OpcodeKind::LoadDS:
case OpcodeKind::Rol:
case OpcodeKind::Ror:
case OpcodeKind::Rcl:
case OpcodeKind::Rcr:
case OpcodeKind::Shl:
case OpcodeKind::Shr:
case OpcodeKind::Sar:
case OpcodeKind::Test:
case OpcodeKind::In:
case OpcodeKind::Out:
case OpcodeKind::Xchg:
return 2;
case OpcodeKind::Inc:
case OpcodeKind::Dec:
case OpcodeKind::Push:
case OpcodeKind::Pop:
case OpcodeKind::Not:
case OpcodeKind::Neg:
case OpcodeKind::Mul:
case OpcodeKind::Imul:
case OpcodeKind::Div:
case OpcodeKind::Idiv:
case OpcodeKind::Aam:
case OpcodeKind::Aad:
return 1;
case OpcodeKind::Nop:
case OpcodeKind::Daa:
case OpcodeKind::Das:
case OpcodeKind::Aaa:
case OpcodeKind::Aas:
return 0;
case OpcodeKind::Jump:
case OpcodeKind::Call:
case OpcodeKind::Int:
case OpcodeKind::Return:
case OpcodeKind::IntReturn:
case OpcodeKind::StringHandle:
case OpcodeKind::CallBack:
case OpcodeKind::Other:
return -1;
default:
std::fprintf(stderr, "error no inst count %d\n", (int)code.getKind());
std::exit(-1);
}
}
static Opcode GetRunCode(uint8_t c, Fetcher &fetcher) {
Opcode code;
size_t begin_count = fetcher.getCount();
auto fetch_b = [&]() {
return fetcher.fetch_b();
};
auto fetch_bs = [&]() {
return fetcher.fetch_bs();
};
auto fetch_w = [&]() {
return fetcher.fetch_w();
};
auto fetch_with_judge = [&](bool is_u8) -> uint16_t {
return fetcher.fetch_with_judge(is_u8);
};
auto fecth_rmea_data = [&](uint8_t rm) -> uint16_t {
uint8_t area = (rm >> 6) & 7;
switch (area) {
case 0x00:
if ((rm & 0x7) == 6) {
return fetch_w();
}
break;
case 0x01:
return fetch_bs();
case 0x02:
return fetch_w();
}
return 0;
};
auto get_rmea = [&](uint8_t rm, bool is_u8) -> Opcode::Operate {
if (rm < 0xc0) {
auto area = (rm >> 6) & 3;
auto index = rm & 0x7;
return Opcode::Operate(Opcode::M, ((area == 0 && index == 6) ? 8 : index), fecth_rmea_data(rm));
} else {
return Opcode::Operate(Opcode::R, getEARegFromRM(rm, is_u8));
}
};
auto create_eggeai = [&](int mode /* 0 E,G 1 G,E 2 A,I */, bool is_u8) {
switch (mode) {
case 0: // ? E,G
case 1: // ? G,E
{
uint8_t rm = fetch_b();
auto rmea = get_rmea(rm, is_u8);
auto rmr = Opcode::Operate(Opcode::R, getRegFromRM(rm, is_u8));
if (mode == 0) {
code.setOp<1>(rmea);
code.setOp<2>(rmr);
} else {
code.setOp<2>(rmea);
code.setOp<1>(rmr);
}
break;
}
case 2: // ? A,I
{
code.setOp<1>(Opcode::Operate(Opcode::R, is_u8 ? Register::r8_al : Register::r16_ax));
code.setOp<2>(Opcode::Operate::Immediate(fetch_with_judge(is_u8)));
break;
}
}
};
static std::set<uint8_t> prefix_set = { 0x26, 0x2e, 0x36, 0x3e, 0xf2, 0xf3 };
if (prefix_set.find(c) != prefix_set.end()) {
// Prefix
uint8_t next_c = fetch_b();
if (prefix_set.find(next_c) != prefix_set.end()) {
// TODO: Not Implement
fetcher.setCount(begin_count);
return Opcode::illegal();
}
auto next_code = GetRunCode(next_c, fetcher);
if (next_code.getPrefix() == OpcodePrefix::none) {
if (c < 0xf0) {
next_code.setPrefix(OpcodePrefix(((c >> 3) & 0x3) + 1));
} else {
next_code.setPrefix(c == 0xf2 ? OpcodePrefix::repnz : OpcodePrefix::repz);
}
}
next_code.setLength(next_code.getLength() + 1);
return next_code;
} else if (c < 0x40 && ((c & 0x7) < 6)) {
static OpcodeKind kind_map[8] = {
OpcodeKind::Add,
OpcodeKind::Or,
OpcodeKind::Adc,
OpcodeKind::Sbb,
OpcodeKind::And,
OpcodeKind::Sub,
OpcodeKind::Xor,
OpcodeKind::Cmp
};
code.setKind(kind_map[(c >> 3) & 0x7]);
bool is_u8 = !(c & 0x1);
code.setU8(is_u8);
uint8_t mode = (c & 0x07) >> 1;
create_eggeai(mode, is_u8);
} else if (c >= 0x40 && c < 0x60) {
static OpcodeKind kind_map[8] = {
OpcodeKind::Inc,
OpcodeKind::Dec,
OpcodeKind::Push,
OpcodeKind::Pop,
};
code.setKind(kind_map[(c >> 3) - 8]);
bool is_u8 = false;
code.setU8(is_u8);
Register reg = joinRegister(c & 0x7, is_u8);
code.setOp<1>(Opcode::Operate(Opcode::R, reg));
} else if ((0x60 <= c && c < 0x80) || (0xe0 <= c && c <= 0xe3)) {
code.setKind(OpcodeKind::Jump);
code.setOp<2>(Opcode::Operate(Opcode::K, 0));
code.setOp<1>(Opcode::Operate(Opcode::C, (c < 0x80) ? (c & 0xf) : (0x10 + (c & 0xf))));
uint16_t offset = fetch_bs();
code.setIMMData(offset);
} else if (c == 0xe9 || c == 0xeb) {
code.setKind(OpcodeKind::Jump);
code.setOp<2>(Opcode::Operate(Opcode::K, 1));
uint16_t offset;
if (c == 0xe9) {
offset = fetch_w();
} else {
offset = fetch_bs();
}
code.setIMMData(offset);
} else if (c == 0xea) {
code.setKind(OpcodeKind::Jump);
code.setOp<2>(Opcode::Operate(Opcode::K, 3));
code.setRMEAData(fetch_w()); // ip
code.setIMMData(fetch_w()); // cs
} else if (c >= 0xb0 && c < 0xc0) {
code.setKind(OpcodeKind::Move);
// reg = imm
auto reg = (Register)(c & 0xf);
code.setU8(!((c >> 3) & 0x1));
code.setOp<1>(Opcode::Operate(Opcode::R, reg));
code.setOp<2>(Opcode::Operate::Immediate(fetch_with_judge(code.isU8())));
} else if (c == 0x80 || c == 0x81 || c == 0x82 || c == 0x83) {
// ? E,I
static OpcodeKind kind_map[8] = {
OpcodeKind::Add,
OpcodeKind::Or,
OpcodeKind::Adc,
OpcodeKind::Sbb,
OpcodeKind::And,
OpcodeKind::Sub,
OpcodeKind::Xor,
OpcodeKind::Cmp
};
uint8_t rm = fetch_b();
code.setKind(kind_map[(rm >> 3) & 0x7]);
code.setU8((c == 0x80 || c == 0x82));
// Get RMEA
code.setOp<1>(get_rmea(rm, code.isU8()));
// Get IMM
uint16_t imm;
switch (c) {
case 0x80:
case 0x82: imm = fetch_b(); break;
case 0x81: imm = fetch_w(); break;
case 0x83: imm = fetch_bs(); break;
}
code.setOp<2>(Opcode::Operate::Immediate(imm));
} else if (c == 0x90 || (0xd8 <= c && c < 0xe0) || c == 0x9b /* WAIT */ || (c == 0xf0 || c == 0xf1) /* LOCK */) {
code.setKind(OpcodeKind::Nop);
} else if (0xd0 <= c && c <= 0xd3) {
static OpcodeKind kind_map[8] = {
OpcodeKind::Rol,
OpcodeKind::Ror,
OpcodeKind::Rcl,
OpcodeKind::Rcr,
OpcodeKind::Shl,
OpcodeKind::Shr,
OpcodeKind::Shl,
OpcodeKind::Sar
};
uint8_t rm = fetch_b();
code.setKind(kind_map[(rm >> 3) & 0x7]);
code.setU8(!(c & 0x1));
// Get RMEA
code.setOp<1>(get_rmea(rm, code.isU8()));
// Get REG/IMM
switch (c) {
case 0xd0:
case 0xd1:
code.setOp<2>(Opcode::Operate::Immediate(1));
break;
case 0xd2:
case 0xd3:
code.setOp<2>(Opcode::Operate(Opcode::R, Register::r8_cl));
break;
}
} else if (c == 0x27 || c == 0x2f || c == 0x37 || c == 0x3f) {
// TODO: Test this op
static OpcodeKind kind_map[8] = {
OpcodeKind::Daa,
OpcodeKind::Das,
OpcodeKind::Aaa,
OpcodeKind::Aas,
};
code.setKind(kind_map[(c >> 3) & 0x3]);
} else if (c == 0xd4 || c == 0xd5) {
// TODO: Test this op
static OpcodeKind kind_map[8] = {
OpcodeKind::Aam,
OpcodeKind::Aad,
};
code.setKind(kind_map[c - 0xd4]);
code.setOp<1>(Opcode::Operate::Immediate(fetch_b()));
} else if (c == 0x84 || c == 0x85 || c == 0xa8 || c == 0xa9) {
code.setKind(OpcodeKind::Test);
int mode;
bool is_u8;
switch (c) {
case 0x84: mode = 0; is_u8 = true; break;
case 0x85: mode = 0; is_u8 = false; break;
case 0xa8: mode = 2; is_u8 = true; break;
case 0xa9: mode = 2; is_u8 = false; break;
}
code.setU8(is_u8);
create_eggeai(mode, is_u8);
} else if ((0xe4 <= c && c <= 0xe7) || (0xec <= c && c <= 0xef)) {
// IN/OUT
bool is_u8 = !(c & 0x1);
bool is_in = !((c >> 1) & 0x1);
bool is_imm = !((c >> 3) & 0x1);
code.setKind(is_in ? OpcodeKind::In :OpcodeKind::Out);
code.setU8(is_u8);
Opcode::Operate port_op = is_imm ? Opcode::Operate(Opcode::P, Opcode::getOpMask(), fetch_b()) : Opcode::Operate(Opcode::P, Register::r16_dx);
Opcode::Operate reg_op = Opcode::Operate(Opcode::R, is_u8 ? Register::r8_al : Register::r16_ax);
if (is_in) {
code.setOp<1>(reg_op);
code.setOp<2>(port_op);
} else {
code.setOp<1>(port_op);
code.setOp<2>(reg_op);
}
} else if (c == 0x86 || c == 0x87) {
// XCHG E,G
code.setKind(OpcodeKind::Xchg);
bool is_u8 = !(c & 0x1);
create_eggeai(0, is_u8);
} else if (0x91 <= c && c <= 0x97) {
// XCHG R,A
code.setKind(OpcodeKind::Xchg);
code.setU8(false);
auto reg = Register((c & 0x7) | 0x8);
code.setOp<1>(Opcode::Operate(Opcode::R, reg));
code.setOp<2>(Opcode::Operate(Opcode::R, Register::r16_ax));
} else if (0x88 <= c && c <= 0x8b) {
// NOTICE: Ignore 0x89, pmode check
// MOV E,G G,E
code.setKind(OpcodeKind::Move);
bool is_u8 = !(c & 0x1);
code.setU8(is_u8);
create_eggeai(((c >> 1) & 0x1), is_u8);
} else if (c == 0xc6 || c == 0xc7) {
// MOV E,I
code.setKind(OpcodeKind::Move);
bool is_u8 = !(c & 0x1);
code.setU8(is_u8);
uint8_t rm = fetch_b();
code.setOp<1>(get_rmea(rm, is_u8));
code.setOp<2>(Opcode::Operate::Immediate(fetch_with_judge(is_u8)));
} else if (c == 0x8c || c == 0x8e) {
// MOV E,S S,E
code.setKind(OpcodeKind::Move);
bool is_u8 = false;
code.setU8(is_u8);
uint8_t rm = fetch_b();
auto seg = Opcode::Operate(Opcode::S, SegmentK((rm >> 3) & (c == 0x8c ? 0x7 : 0x3)));
auto rmea = get_rmea(rm, is_u8);
if (c == 0x8c) {
code.setOp<1>(rmea);
code.setOp<2>(seg);
} else {
code.setOp<1>(seg);
code.setOp<2>(rmea);
}
} else if (0xa0 <= c && c <= 0xa3) {
// MOV A,M2 M2,A
code.setKind(OpcodeKind::Move);
bool is_u8 = !(c & 0x1);
bool is_in = !(c & 0x2);
code.setU8(is_u8);
auto mem = Opcode::Operate(Opcode::M, 8, fetch_w());
auto reg = Opcode::Operate(Opcode::R, is_u8 ? Register::r8_al : Register::r16_ax);
if (is_in) {
code.setOp<1>(reg);
code.setOp<2>(mem);
} else {
code.setOp<1>(mem);
code.setOp<2>(reg);
}
} else if (c == 0xf6 || c == 0xf7) {
// Gpr3
bool is_u8 = !(c & 0x1);
uint8_t rm = fetch_b();
code.setU8(is_u8);
uint8_t which = (rm >> 3) & 0x7;
if (which == 0x00 || which == 0x01) {
// Test E,I
code.setKind(OpcodeKind::Test);
code.setOp<1>(get_rmea(rm, is_u8));
code.setOp<2>(Opcode::Operate::Immediate(fetch_with_judge(is_u8)));
} else {
// ? E
static OpcodeKind kind_map[8] = {
OpcodeKind::Not,
OpcodeKind::Neg,
OpcodeKind::Mul,
OpcodeKind::Imul,
OpcodeKind::Div,
OpcodeKind::Idiv,
};
code.setKind(kind_map[which-2]);
code.setOp<1>(get_rmea(rm, is_u8));
}
} else if ((0xa4 <= c && c <= 0xa7) || (0xaa <= c && c <= 0xaf)) {
StringHandleFunction flag;
switch (c & 0xf) {
case 0x4: flag = StringHandleFunction::MOVSB; break;
case 0x5: flag = StringHandleFunction::MOVSW; break;
case 0x6: flag = StringHandleFunction::CMPSB; break;
case 0x7: flag = StringHandleFunction::CMPSW; break;
case 0xa: flag = StringHandleFunction::STOSB; break;
case 0xb: flag = StringHandleFunction::STOSW; break;
case 0xc: flag = StringHandleFunction::LODSB; break;
case 0xd: flag = StringHandleFunction::LODSW; break;
case 0xe: flag = StringHandleFunction::SCASB; break;
case 0xf: flag = StringHandleFunction::SCASW; break;
}
code.setKind(OpcodeKind::StringHandle);
code.setU8(!(c & 0x1));
code.setIMMData((uint8_t)flag);
} else if (0xcc <= c && c <= 0xce) {
code.setKind(OpcodeKind::Int);
uint8_t idx = c - 0xcc;
code.setOp<1>(Opcode::Operate(Opcode::K, idx));
if (idx == 1) {
code.setOp<2>(Opcode::Operate::Immediate(fetch_b()));
}
} else if ((0xc0 <= c && c <= 0xc3) || (0xc8 <= c && c <= 0xcb)) {
code.setKind(OpcodeKind::Return);
code.setOp<1>(Opcode::Operate(Opcode::K, ((c & 0xf) >> 3)));
code.setOp<2>(Opcode::Operate::Immediate(((c & 0x1) == 0x0) ? fetch_w() : 0));
} else if (c == 0xcf) {
code.setKind(OpcodeKind::IntReturn);
} else if (c == 0x9a || c == 0xe8) {
code.setKind(OpcodeKind::Call);
code.setOp<2>(Opcode::Operate(Opcode::K, (c == 0x9a) ? 3 : 1));
if (c == 0x9a) {
code.setRMEAData(fetch_w()); // ip
code.setIMMData(fetch_w()); // cs
} else {
uint16_t offset = fetch_w();
code.setIMMData(offset);
}
} else if (c == 0x06 || c == 0x0e || c == 0x16 || c == 0x1e) {
code.setKind(OpcodeKind::Push);
code.setU8(false);
code.setOp<1>(Opcode::Operate(Opcode::S, SegmentK((c >> 3) & 0x3)));
} else if (c == 0x07 || c == 0x0f || c == 0x17 || c == 0x1f) {
code.setKind(OpcodeKind::Pop);
code.setU8(false);
code.setOp<1>(Opcode::Operate(Opcode::S, SegmentK((c >> 3) & 0x3)));
} else if (c == 0x8f) {
code.setKind(OpcodeKind::Pop);
code.setU8(false);
uint8_t rm = fetch_b();
code.setOp<1>(get_rmea(rm, false));
} else if (c == 0x8d || c == 0xc4 || c == 0xc5) {
switch (c) {
case 0x8d: code.setKind(OpcodeKind::LoadEA); break;
case 0xc4: code.setKind(OpcodeKind::LoadES); break;
case 0xc5: code.setKind(OpcodeKind::LoadDS); break;
}
code.setU8(false);
uint8_t rm = fetch_b();
if (rm >= 0xc0) {
fetcher.setCount(begin_count);
return Opcode::illegal();
}
auto rmr = Opcode::Operate(Opcode::R, getRegFromRM(rm, false));
auto rmea = get_rmea(rm, false);
code.setOp<1>(rmr);
code.setOp<2>(rmea);
if (code.getKind() == OpcodeKind::LoadEA) {
code.setPrefix(OpcodePrefix::lea);
}
} else if (c == 0xfe || c == 0xff) {
bool is_u8 = !(c & 0x1);
uint8_t rm = fetch_b();
code.setU8(is_u8);
uint8_t which = (rm >> 3) & 0x7;
if (which == 0x0 || which == 0x1) {
// ? E
code.setKind(which == 0x00 ? OpcodeKind::Inc : OpcodeKind::Dec);
code.setOp<1>(get_rmea(rm, is_u8));
} else if (c == 0xff && (which == 0x4 || which == 0x5)) {
if (which == 0x4) {
code.setKind(OpcodeKind::Jump);
code.setOp<2>(Opcode::Operate(Opcode::K, 2));
code.setOp<1>(get_rmea(rm, false));
} else {
code.setKind(OpcodeKind::Jump);
code.setOp<2>(Opcode::Operate(Opcode::K, 4));
if (rm >= 0xc0) {
fetcher.setCount(begin_count);
return Opcode::illegal();
}
code.setOp<1>(get_rmea(rm, false));
}
} else if (c == 0xff && (which == 0x2 || which == 0x3)) {
code.setKind(OpcodeKind::Call);
code.setOp<2>(Opcode::Operate(Opcode::K, (which == 0x2) ? 2 : 4));
if (which == 0x2) {
code.setOp<1>(get_rmea(rm, false));
} else {
if (rm >= 0xc0) {
fetcher.setCount(begin_count);
return Opcode::illegal();
}
code.setOp<1>(get_rmea(rm, false));
}
} else if (c == 0xfe && which == 0x7) {
code.setKind(OpcodeKind::CallBack);
code.setIMMData(fetch_w());
} else if (c == 0xff && which == 0x6) {
code.setKind(OpcodeKind::Push);
code.setOp<1>(get_rmea(rm, false));
} else {
fetcher.setCount(begin_count);
return Opcode::illegal();
}
} else {
code.setKind(OpcodeKind::Other);
code.setIMMData(c);
}
code.setLength(fetcher.getCount() - begin_count + 1);
return code;
}
#include "getruncode.hpp"
#include "dumpopcode.hpp"
#include <vector>
#include <set>
#include <deque>
class FileFetcher : public Fetcher {
FILE *file;
public:
explicit FileFetcher(FILE *file) : file(file) {}
protected:
uint8_t _base_fetch_b() final { uint8_t c; std::fread(&c, 1, 1, file); return c; }
uint16_t _base_fetch_w() final { uint16_t c; std::fread(&c, 2, 1, file); return c; }
uint16_t _base_fetch_bs() final { int8_t c; std::fread(&c, 1, 1, file); return c; }
};
class DataFetcher : public Fetcher {
const std::vector<uint8_t> &data;
bool status = true;
public:
explicit DataFetcher(const std::vector<uint8_t> &data) : data(data) {}
bool is_end() const {
return count >= data.size();
}
bool is_ok() const {
return status;
}
protected:
#define Check8 if (!check_base(1)) { return 0xff; }
#define Check16 if (!check_base(2)) { return 0xff00 | _base_fetch_b(); }
uint8_t _base_fetch_b() final { Check8; return data[count]; }
uint16_t _base_fetch_w() final { Check16; return *reinterpret_cast<const uint16_t*>(data.data() + count); }
uint16_t _base_fetch_bs() final { Check8; return *reinterpret_cast<const int8_t*>(data.data() + count); }
private:
bool check_base(size_t ask) {
bool result = count + ask < data.size();
status = status && result;
return result;
}
};
using RecordType = std::vector<std::pair<int, Opcode>>;
void do_decode(int idx, const std::vector<uint8_t> &data, RecordType &record, size_t start_offset = 0, bool stop_with_return = false, std::deque<uint32_t> *deque = nullptr) {
DataFetcher fetcher(data);
fetcher.setCount(start_offset);
while (!fetcher.is_end()) {
size_t offset = fetcher.getCount();
Opcode code = GetRunCode(fetcher.fetch_b(), fetcher);
if (record[offset].first == 0) {
record[offset] = std::make_pair(idx, code);
}
for (size_t i = offset + 1; i < offset + code.getLength(); ++i) {
record[i] = std::make_pair(-1, Opcode());
}
if (stop_with_return && (code.getKind() == OpcodeKind::Return || code.getKind() == OpcodeKind::IntReturn)) {
break;
}
if (deque) {
if (code.getKind() == OpcodeKind::Jump || code.getKind() == OpcodeKind::Call) {
uint32_t new_csip = -1;
// Ignore 2 4
switch (code.getOp<2>().idx) {
case 0:
case 1:
new_csip = offset + code.getLength() + (int16_t)code.getIMMData();
break;
case 3: {
auto new_ip = code.getRMEAData();
auto new_cs = code.getIMMData();
new_csip = get_csip(new_cs, new_ip);
break;
}
}
if (new_csip != -1) {
deque->push_back(new_csip);
}
}
}
bool do_break = false;
if (code.getKind() == OpcodeKind::Jump) {
// Ignore 4
if (code.getOp<2>().idx != 0) {
do_break = true;
}
}
if (do_break) {
break;
}
}
}
int main() {
FILE *file = fopen("MTE.bin", "rb");
std::fseek(file, 0, SEEK_END);
std::size_t file_length = std::ftell(file);
std::fseek(file, 0, SEEK_SET);
std::vector<uint8_t> data(file_length);
std::fread(data.data(), 1, file_length, file);
std::fseek(file, 0, SEEK_SET);
std::vector<std::pair<int, Opcode>> record(file_length);
// ID 1 decode
// do_decode(1, data, record);
// ID 2 decode
std::set<uint32_t> done;
static std::vector<uint32_t> record_start = {
0x00000,0x00135,0x0013e,0x0014a,0x00161,0x00181,0x001a3,0x001a6,0x001f1,0x00220,0x00282,0x00297,0x00a5a,0x00b1a,
0x00b54,0x00b9c,0x00be4,0x00d54,0x00d57,0x00d60,0x00d64,0x00da0,0x00da7,0x00dc4,0x00e24,0x00e2b,0x00e32,0x00e50,
0x00e5e,0x00e70,0x00e77,0x00e7c,0x01588,0x015c9,0x0161d,0x0165f,0x016c4,0x01718,0x0176c,0x01778,0x017fd,0x01852,
0x018b7,0x018c3,0x01967,0x019cc,0x01a07,0x01a13,0x01ad9,0x01b1b,0x01b50,0x01c16,0x01c60,0x01ca2,0x01cdf,0x01d17,
0x01df7,0x01e41,0x01e83,0x01ec0,0x01ef8,0x01fd5,0x01fe1,0x02096,0x020a2,0x02177,0x02183,0x02273,0x022c8,0x022d4,
0x023ea,0x023ee,0x0240e,0x02411,0x02417,0x02426,0x02456,0x02574,0x02579,0x0257e,0x02583,0x02586,0x0259b,0x025ee,
0x025f3,0x0261a,0x0261f,0x02624,0x02627,0x02652,0x02658,0x0270e,0x02713,0x02718,0x027de,0x028a2,0x028b4,0x028bb,
0x028d0,0x028d9,0x028df,0x028e2,0x0294e,0x02968,0x029bc,0x02a0a,0x02a1a,0x02a28,0x02a2e,0x02a36,0x02a44,0x02ac0,
0x02ae0,0x02ae6,0x02aec,0x02af2,0x02af8,0x02afe,0x02bf2,0x02bf8,0x02bfe,0x02c04,0x02c0a,0x02c10,0x02cfc,0x02d02,
0x02d08,0x02d0e,0x02d14,0x02d1a,0x02d20,0x02d26,0x02d2c,0x02d32,0x02d38,0x02d3e,0x02d44,0x02d4a,0x02d50,0x02f26,
0x02f2f,0x02f3c,0x02f80,0x02f85,0x02f8c,0x02f93,0x02fb6,0x02fde,0x02fe3,0x02ffe,0x0303d,0x03040,0x04762,0x04bc0,
0x04c7b,0x04ce2,0x04cee,0x04e11,0x04e1d,0x04f56,0x04fbd,0x05024,0x0508b,0x050f0,0x05155,0x05161,0x0524b,0x052d3,
0x052df,0x05466,0x05472,0x05560,0x055c7,0x055d3,0x0566d,0x05679,0x057de,0x057ea,0x058ac,0x05921,0x0592d,0x05a66,
0x05adc,0x05b43,0x05baa,0x05c0f,0x05c76,0x05cdb,0x05ce7,0x05e17,0x05e23,0x05f40,0x05f4c,0x0607c,0x06082,0x06090,
0x06093,0x0609a,0x060b5,0x060ce,0x060f2,0x06101,0x06142,0x06177,0x0619a,0x061b7,0x061c7,0x061f5,0x06200,0x06212,
0x06218,0x06224,0x0622a,0x06233,0x062e2,0x062e5,0x06350,0x0638c,0x06522,0x06536,0x06692,0x066ad,0x066f6,0x06718,
0x0673a,0x0675c,0x06784,0x0679f,0x067c2,0x06801,0x0682b,0x06832,0x06835,0x0685c,0x07be6,0x07bf4,0x07c15,0x07c22,
0x07c61,0x07cb2,0x07cc6,0x07ccb,0x07ce0,0x07cee,0x07d01,0x07d1d,0x07d3f,0x08c2a,0x08c9a,0x08c9d,0x08ca4,0x08cc1,
0x08cd9,0x08ce0,0x08ce3,0x08ce9,0x08cf6,0x08cfc,0x08cff,0x08d08,0x08d8c,0x08eb5,0x08ec5,0x08ee7,0x08ef9,0x08f22,
0x08f52,0x08f6a,0x08f84,0x08f87,0x08f8d,0x08fc0,0x08fc8,0x08fd0,0x09288,0x09296,0x09298,0x0929f,0x092a4,0x092bb,
0x092c6,0x092d3,0x092d8,0x092da,0x092dd,0x0930e,0x0931f,0x09323,0x09326,0x0933b,0x0933f,0x09348,0x09364,0x0939a,
0x093ac,0x093bf,0x093d8,0x093dd,0x093e0,0x093ec,0x09447,0x0945f,0x09480,0x0948c,0x094ba,0x09515,0x0952d,0x0954e,
0x0955a,0x095d8,0x09626,0x0963b,0x09640,0x0964a,0x09664,0x096b8,0x097ec,0x0986c,0x099d3,0x099d8,0x099e2,0x09a42,
0x09b9c,0x09c14,0x09c8e,0x09d06,0x09d7a,0x09d80,0x09d95,0x09d9d,0x09dac,0x09db5,0x09dc8,0x09de6,0x09de8,0x09de9,
0x09df4,0x09e78,0x09ea3,0x09ea9,0x09eaf,0x09eb2,0x09ebb,0x09ec7,0x09f0e,0x09f14,0x09f1a,0x09f22,0x09f7a,0x09f85,
0x09f95,0x09fae,0x09fb4,0x09fba,0x09fcc,0x09fd0,0x09fd6,0x09fd9,0x09fef,0x09ff8,0x0a07b,0x0a0f2,0x0a101,0x0a11b,
0x0a128,0x0a164,0x0a169,0x0a16c,0x0a184,0x0a1a1,0x0a1ab,0x0a1cc,0x0a1d9,0x0a1de,0x0a1e4,0x0a276,0x0a2a5,0x0a2ab,
0x0a2ae,0x0a2c7,0x0a2fa,0x0a30a,0x0a30d,0x0a313,0x0a316,0x0a342,0x0a348,0x0a34b,0x0a368,0x0a39b,0x0a3ac,0x0a3af,
0x0a3b5,0x0a3b8,0x0a3e4,0x0a3ea,0x0a406,0x0a409,0x0a40f,0x0a412,0x0a43e,0x0a447,0x0a464,0x0a497,0x0a68a,0x0a68e,
0x0a696,0x0a6a2,0x0a6a6,0x0a6a9,0x0a6bc,0x0a701,0x0a71a,0x0a71d,0x0a726,0x0a72c,0x0a738,0x0a73e,0x0a744,0x0a747,
0x0a75a,0x0a79f,0x0a7b8,0x0a7be,0x0a7c8,0x0a7ce,0x0a7d4,0x0a7d7,0x0a7ea,0x0a82f,0x0a84e,0x0a858,0x0a85e,0x0a864,
0x0a877,0x0a8bc,0x0a8d8,0x0a8e2,0x0a8eb,0x0a8f1,0x0a8f4,0x0a916,0x0a922,0x0a968,0x0a96e,0x0a976,0x0a986,0x0a9fa,
0x0aa0f,0x0aa66,0x0aa79,0x0aaaf,0x0aab2,0x0aad2,0x0aae0,0x0aaef,0x0aaf4,0x0ab1f,0x0ab34,0x0ab36,0x0ab3c,0x0ab44,
0x0ab74,0x0ab9c,0x0abb6,0x0abdf,0x0abe6,0x0ac03,0x0ac13,0x0ac24,0x0ac29,0x0ac2c,0x0ac41,0x0ac44,0x0ac48,0x0ac4b,
0x0ac4f,0x0ac53,0x0ac7a,0x0acdc,0x0ad3c,0x0ad52,0x0ad55,0x0ad5a,0x0ad6e,0x0ad71,0x0ad78,0x0ada6,0x0adaa,0x0adb3,
0x0adcf,0x0ae00,0x0ae09,0x0ae1e,0x0ae24,0x0ae36,0x0ae3a,0x0ae4c,0x0ae52,0x0ae65,0x0ae6e,0x0aef8,0x0aefc,0x0af00,
0x0af04,0x0af08,0x0af7c,0x0afa6,0x0b35f,0x0b367,0x0b36c,0x0b370,0x0b377,0x0b3c7,0x0b3d0,0x0b406,0x0b416,0x0b41e,
0x0b426,0x0b429,0x0b4b2,0x0b4c6,0x0b515,0x0b521,0x0b531,0x0b539,0x0b53e,0x0b542,0x0b549,0x0b54c,0x0b58c,0x0b594,
0x0b597,0x0b624,0x0b62a,0x0b658,0x0b660,0x0b67b,0x0b67e,0x0b682,0x0b685,0x0b689,0x0b68d,0x0b691,0x0b6b4,0x0b72c,
0x0b7a1,0x0b7a9,0x0b7b8,0x0b7bb,0x0b7cb,0x0b7ce,0x0b7d4,0x0b7f8,0x0b803,0x0b82e,0x0b8d6,0x0b8fb,0x0b902,0x0b92d,
0x0b96c,0x0b98b,0x0b9a4,0x0b9bd,0x0b9d6,0x0b9dc,0x0b9e2,0x0ba15,0x0ba1b,0x0ba21,0x0ba54,0x0ba5a,0x0ba60,0x0ba93,
0x0ba99,0x0ba9f,0x0bad2,0x0bad8,0x0bade,0x0bb29,0x0bb2e,0x0c08c,0x0c0c7,0x0c0f4,0x0c12f,0x0c15c,0x0c20e,0x0c2ba,
0x0c2c6,0x0c2d2,0x0c2eb,0x0c3ba,0x0c42a,0x0c48c,0x0d66f,0x0d67e,0x0d69d,0x0d6fb,0x0d705,0x0d762,0x0d7af,0x0d7ba,
0x0d7be,0x0d7c4,0x0d7ce,0x0d7d7,0x0d7f8,0x0d7fb,0x0d807,0x0d80c,0x0d814,0x0d827,0x0d848,0x0d84d,0x0d86b,0x0d897,
0x0d89f,0x0d8aa,0x0d8b7,0x0d8d6,0x0d8d7,0x0d8db,0x0d8e5,0x0d8e9,0x0d912,0x0d91a,0x0d920,0x0d936,0x0d93f,0x0d944,
0x0d958,0x0d95a,0x0d970,0x0d985,0x0d98a,0x0d9a8,0x0d9ac,0x0d9b0,0x0da3b,0x0da6d,0x0da73,0x0da80,0x0da85,0x0da89,
0x0da8d,0x0db36,0x0db46,0x0db68,0x0db70,0x0db76,0x0dba6,0x0dbc3,0x0dbd1,0x0dbd7,0x0dbd9,0x0dc48,0x0dc65,0x0dc6e,
0x0dc70,0x0dc83,0x0dc8c,0x0dcc4,0x0dcdb,0x0dce4,0x0dd17,0x0dd7e,0x0dd8a,0x0dda2,0x0ddbe,0x0ddda,0x0ddee,0x0ddfe,
0x0de1d,0x0de27,0x0de59,0x0de5f,0x0de75,0x0de7b,0x0de94,0x0de9e,0x0dea4,0x0deaa,0x0dede,0x0dee0,0x0dee2,0x0dee7,
0x0df0c,0x0df11,0x0df38,0x0df42,0x0df4c,0x0df60,0x0df70,0x0df75,0x0df7b,0x0dfcb,0x0dfe4,0x0dfed,0x0e006,0x0e010,
0x0e016,0x0e01c,0x0e021,0x0e028,0x0e02c,0x0e050,0x0e054,0x0e057,0x0e05c,0x0e062,0x0e07a,0x0e0a2,0x0e0a8,0x0e0ac,
0x0e0c6,0x0e0d0,0x0e0da,0x0e0e4,0x0e1c4,0x0e1d3,0x0e1d7,0x0e1eb,0x0e205,0x0e209,0x0e20e,0x0e214,0x0e21a,0x0e246,
0x0e256,0x0e27a,0x0e287,0x0e28e,0x0e2ab,0x0e2b0,0x0e2be,0x0e2c2,0x0e2e4,0x0e2e8,0x0e307,0x0e320,0x0e334,0x0e348,
0x0e34a,0x0e34e,0x0e358,0x0e35e,0x0e363,0x0e36f,0x0e375,0x0e37e,0x0e380,0x0e384,0x0e390,0x0e3be,0x0e3c4,0x0e3ca,
0x0e3ea,0x0e42c,0x0e44f,0x0e45f,0x0e464,0x0e46f,0x0e490,0x0e4a0,0x0e4a9,0x0e4ad,0x0e4c4,0x0e4d0,0x0e4df,0x0e4f6,
0x0e510,0x0e51e,0x0e523,0x0e530,0x0e53c,0x0e55d,0x0e576,0x0e57e,0x0e595,0x0e598,0x0e59e,0x0e5a4,0x0e5b1,0x0e5b4,
0x0e5ba,0x0e5c1,0x0e5da,0x0e5ee,0x0e5fd,0x0e603,0x0e609,0x0e612,0x0e617,0x0e619,0x0e632,0x0e63d,0x0e716,0x0e720,
0x0e727,0x0e72e,0x0e735,0x0e739,0x0e8c4,0x0e8df,0x0e8f3,0x0e8fe,0x0e90a,0x0e921,0x0e927,0x0e932,0x0e93d,0x0e961,
0x0e963,0x0e99a,0x0e9a4,0x0e9af,0x0e9d6,0x0e9eb,0x0e9ee,0x0ea22,0x0ea2e,0x0ea53,0x0ea55,0x0ea5d,0x0ea66,0x0ea70,
0x0ea71,0x0ea73,0x0ea82,0x0ea8c,0x0ea8d,0x0ea90,0x0ea94,0x0ea98,0x0ea9c,0x0ea9e,0x0eaaf,0x0eab2,0x0eab8,0x0eabe,
0x0eac4,0x0ead8,0x0eadb,0x0eae1,0x0eae7,0x0eb12,0x0eb24,0x0eb2a,0x0ebac,0x0ebbb,0x0ebce,0x0ebef,0x0ec10,0x0ec24,
0x0ec36,0x0ec3f,0x0ec47,0x0ec4c,0x0ec65,0x0ec6b,0x0ed1e,0x0ed24,0x0ed39,0x0ed43,0x0ed53,0x0ed78,0x0ed8d,0x0ed94,
0x0ed9b,0x0eda7,0x0edb9,0x0ee00,0x0ee76,0x0ee8c,0x0ee98,0x0eeaa,0x0eeb1,0x0eed1,0x0eed7,0x0eee5,0x0eef6,0x0ef01,
0x0ef06,0x0ef0a,0x0ef0d,0x0ef12,0x0ef1b,0x0ef2d,0x0ef36,0x0ef42,0x0ef4d,0x0ef54,0x0ef8b,0x0ef99,0x0ef9c,0x0efa8,
0x0efb9,0x0efd6,0x0efdf,0x0efea,0x0eff0,0x0eff6,0x0f001,0x0f009,0x0f016,0x0f01e,0x0f021,0x0f029,0x0f02a,0x0f032,
0x0f03b,0x0f050,0x0f058,0x0f05d,0x0f064,0x0f066,0x0f070,0x0f082,0x0f086,0x0f0ba,0x0f0c2,0x0f0cb,0x0f0df,0x0f0f0,
0x0f100,0x0f107,0x0f112,0x0f118,0x0f11f,0x0f123,0x0f128,0x0f12a,0x0f12f,0x0f133,0x0f13a,0x0f148,0x0f149,0x0f152,
0x0f158,0x0f161,0x0f16b,0x0f16c,0x0f174,0x0f17f,0x0f182,0x0f18b,0x0f18f,0x0f196,0x0f198,0x0f1a6,0x0f1a9,0x0f1ad,
0x0f1b1,0x0f1bc,0x0f1c5,0x0f1d0,0x0f1d5,0x0f1da,0x0f1dd,0x0f1f8,0x0f1fb,0x0f212,0x0f221,0x0f231,0x0f23b,0x0f247,
0x0f24b,0x0f24c,0x0f258,0x0f25e,0x0f266,0x0f26c,0x0f289,0x0f28f,0x0f295,0x0f2af,0x0f32c,0x0f340,0x0f348,0x0f35a,
0x0f363,0x0f383,0x0f3da,0x0f3e5,0x0f42d,0x0f445,0x0f44e,0x0f453,0x0f461,0x0f463,0x0f46c,0x0f47a,0x0f481,0x0f483,
0x0f491,0x0f4ec,0x0f4f8,0x0f4fd,0x0f50e,0x0f514,0x0f523,0x0f5f3,0x0f614,0x0f627,0x0f62d,0x0f632,0x0f637,0x0f65c,
0x0f668,0x0f696,0x0f6d8,0x0f71f,0x0f729,0x0f737,0x0f77d,0x0f798,0x0f7a5,0x0f7cf,0x0f7df,0x0f7f2,0x0f7fa,0x0f7ff,
0x0f801,0x0f805,0x0f807,0x0f80b,0x0f80f,0x0f812,0x0f816,0x0f819,0x0f81f,0x0f822,0x0f82c,0x0f82d,0x0f836,0x0f83d,
0x0f846,0x0f84b,0x0f852,0x0f854,0x0f85f,0x0f861,0x0f864,0x0f86f,0x0f871,0x0f87b,0x0f882,0x0f885,0x0f88a,0x0f893,
0x0f89a,0x0f89d,0x0f89f,0x0f8aa,0x0f8ac,0x0f8bb,0x0f8c8,0x0f8cb,0x0f8d6,0x0f8d9,0x0f8e4,0x0f8f3,0x0f8f5,0x0f8f9,
0x0f8fb,0x0f909,0x0f90b,0x0f90f,0x0f911,0x0f91f,0x0f921,0x0f927,0x0f92e,0x0f933,0x0f93f,0x0f946,0x0f94f,0x0f951,
0x0f95c,0x0f95e,0x0f965,0x0f971,0x0f973,0x0f97e,0x0f980,0x0f985,0x0f988,0x0f993,0x0f996,0x0f99c,0x0f9c9,0x0f9cd,
0x0f9ce,0x0f9d0,0x0f9d2,0x0f9d8,0x0f9de,0x0f9e0,0x0f9e2,0x0f9ed,0x0f9ef,0x0f9f0,0x0f9f2,0x0f9f4,0x0f9fa,0x0fa00,
0x0fa02,0x0fa04,0x0fa06,0x0fa13,0x0fa19,0x0fa1d,0x0fa2c,0x0fa51,0x0fa68,0x0fa6e,0x0fa7b,0x0fa7e,0x0fa87,0x0fa94,
0x0fa99,0x0faa3,0x0faa8,0x0fab2,0x0fab7,0x0fac7,0x0fad5,0x0fadb,0x0fadf,0x0fb8a,0x0fba7,0x0fbb2,0x0fbbc,0x0fbbf,
0x0fbcd,0x0fbdc,0x0fbdf,0x0fbf1,0x0fbf4,0x0fc06,0x0fc09,0x0fc1e,0x0fc2c,0x0fc32,0x0fc36,0x0fcd9,0x0fd07,0x0fd3c,
0x0fd47,0x0fd72,0x0fd73,0x0fd7a,0x0fd7d,0x0fd87,0x0fd92,0x0fdc1,0x0fdc2,0x0fdc9,0x0fdcc,0x0fe82,0x0feb8,0x0fecf,
0x0ff10,0x0ff11,0x0ff1d,0x0ff4b,0x0ff62,0x0ff97,0x0ff98,0x100c6,0x100f5,0x100ff,0x1010d,0x10124,0x1014d,0x1014e,
0x10153,0x10167,0x1016c,0x1019b,0x101a5,0x101b3,0x101ca,0x101f3,0x101f4,0x101f9,0x1020d,0x10212,0x1021b,0x10228,
0x10233,0x10235,0x1023e,0x10254,0x10256,0x10296,0x102b8,0x102bd,0x102ce,0x102db,0x102dd,0x102ee,0x102f0,0x102fc,
0x1030c,0x1031c,0x1031e,0x10321,0x1033e,0x10385,0x103ba,0x103dc,0x103e1,0x103f2,0x103ff,0x10401,0x10412,0x10414,
0x10420,0x10430,0x10440,0x10442,0x10445,0x10466,0x10711,0x10788,0x107af,0x107b9,0x107c6,0x107cb,0x107d5,0x107e0,
0x10801,0x10835,0x10883,0x108a4,0x108ac,0x108b1,0x108cf,0x108d7,0x108dc,0x108e4,0x108ef,0x108f7,0x10905,0x10912,
0x10914,0x10915,0x1093c,0x1093f,0x10947,0x10949,0x1094e,0x10953,0x10957,0x10976,0x1097a,0x1097e,0x10984,0x10988,
0x1098c,0x10992,0x10996,0x1099a,0x109a0,0x109a5,0x109ad,0x109b5,0x109c3,0x109d0,0x109d3,0x109d4,0x109d9,0x109e1,
0x109e9,0x109eb,0x109ef,0x109f3,0x109f7,0x109f8,0x10a12,0x10a5a,0x10a66,0x10a6f,0x10a70,0x10a7b,0x10a7c,0x10a88,
0x10a95,0x10a96,0x10aa5,0x10c96,0x10ca9,0x10cb5,0x10cba,0x10cc7,0x10cd2,0x10cda,0x10ce0,0x10ced,0x10d08,0x10d17,
0x10d1d,0x10d20,0x10d29,0x10d30,0x10d36,0x10d3c,0x10d44,0x10d4c,0x10d6f,0x10da0,0x10dca,0x10df1,0x10df9,0x10e9c,
0x10f42,0x10f55,0x10f5d,0x10f65,0x10fa5,0x10fab,0x10fc0,0x10fcc,0x10fff,0x11037,0x1103d,0x11054,0x11071,0x11077,
0x1108e,0x11094,0x110aa,0x110b0,0x110c6,0x110cc,0x110e2,0x110e8,0x1111a,0x11121,0x1112a,0x11139,0x11142,0x1114d,
0x11155,0x1115b,0x11163,0x11800,0x11807,0x11813,0x1181d,0x11820,0x11873,0x1187a,0x11880,0x11896,0x1189a,0x118a0,
0x118a7,0x118ac,0x118b8,0x118bd,0x118bf,0x118ee,0x118f7,0x118fa,0x118fb,0x118fc,0x11900,0x11906,0x1190d,0x11912,
0x11919,0x11925,0x11960,0x1196c,0x1196d,0x1196e,0x1197b,0x1197f,0x11982,0x11993,0x119a5,0x119cd,0x119d5,0x119e5,
0x119e9,0x119eb,0x119f6,0x11a00,0x11a11,0x11a30,0x11abf,0x11aca,0x11acf,0x11ae0,0x11afa,0x11b1d,0x11b34,0x11b3b,
0x11b3c,0x11b43,0x11b46,0x11bb6,0x11bd2,0x11bec,0x11bf5,0x11c28,0x11c31,0x11c37,0x11c58,0x11c70,0x11c81,0x11c99,
0x11ca0,0x11ca6,0x11cc0,0x11cd5,0x11d09,0x11d10,0x11d1b,0x11d2c,0x11d3b,0x11d50,0x11d67,0x11d71,0x11d8a,0x11d99,
0x11da3,0x11da9,0x11daf,0x11dcd,0x11dd1,0x11dd7,0x11df0,0x11df6,0x11dfc,0x11e10,0x11e17,0x11e1b,0x11e21,0x11e40,
0x11e47,0x11e4b,0x11e65,0x11e66,0x11e70,0x11e74,0x11e7d,0x11ed5,0x11ee1,0x11ee5,0x11eff,0x11f3f,0x11f42,0x11f48,
0x11f4e,0x11f6f,0x11f7e,0x11f87,0x11f8b,0x11fa0,0x12053,0x1205a,0x12061,0x1206a,0x1208c,0x12098,0x1209d,0x1209e,
0x120a5,0x120ac,0x120b3,0x120bb,0x120c0,0x120e5,0x120ed,0x120fc,0x120fd,0x12104,0x1210c,0x1210d,0x12116,0x12122,
0x1212b,0x1215e,0x12162,0x1216d,0x1216f,0x12178,0x1217d,0x12182,0x12184,0x12190,0x1219d,0x121a2,0x121ab,0x121b4,
0x121de,0x1225b,0x12261,0x12263,0x12265,0x1226b,0x12275,0x12277,0x12279,0x1227f,0xf574d,0xf578d,0xf5ccb,0xf5ccd,
};
std::deque<uint32_t> deque;
int idx = 0;
deque.insert(deque.end(), record_start.begin(), record_start.end());
while (!deque.empty()) {
auto offset = deque.front();
deque.pop_front();
if (done.find(offset) == done.end()) {
do_decode(++idx, data, record, offset, true, &deque);
done.insert(offset);
}
}
for (size_t offset = 0; offset < record.size(); ++offset) {
if (record.at(offset).first > 0) {
Opcode &code = record.at(offset).second;
std::string dump = dumpOpcode(code, offset, data);
fprintf(stderr, "[%08lx] %ld %04x %016lx %s\n", offset, code.getLength(), record.at(offset).first, code.code, dump.c_str());
} else if (record.at(offset).first == 0) {
fprintf(stderr, "[%08lx]\n", offset);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment