/* This file is used for testing purposes only. Do not copy this file to installation prefix. */ #ifndef LIBREGEXIS024_BYTE_CODE_DISASSEMBLER_H #define LIBREGEXIS024_BYTE_CODE_DISASSEMBLER_H #include "vibe_check.h" #include #include #include #include #include #include #include #include using namespace regexis024; struct landing_place_resolvance{ size_t name_id; bool visited = false; landing_place_resolvance() = default; landing_place_resolvance(size_t nameId, bool visited) : name_id(nameId), visited(visited) {} }; void print_disassembly(size_t prgSize, uint8_t* prg){ std::vector names = { "Александр", "Мария", "Иван", "Анна", "Дмитрий", "Екатерина", "Алексей", "Ольга", "Михаил", "София", "Сергей", "Анастасия", "Артем", "Виктория", "Андрей", "Елена", "Максим", "Алиса", "Павел", "Наталья", "Денис", "Юлия", "Владимир", "Маргарита", "Никита", "Дарья", "Илья", "Алина", "Роман", "Евгения", "Кирилл", "Елизавета", "Антон", "Татьяна", "Владислав", "Валерия", "Георгий", "Ксения", "Арсений", "Милана", "Даниил", "Вероника", "Тимофей", "Арина", "Николай", "Кристина", "Степан", "Алёна", "Игорь", "Алла", "Григорий", "Ева", "Олег", "Яна", "Семен", "Марина", "Федор", "Светлана", "Василий", "Людмила" }; uint64_t used_names = 0; /* From program position -> to names[ind] & */ std::map bookmarks; near_ptr_t IP = 0; auto check_inboundness = [&](int region){ if (!vmprog_check_inboundness(prgSize, IP, region)) { fprintf(stderr, "This program can't be decomposed into commands in a trivial way"); std::terminate(); } }; auto extract_b = [&]() -> uint8_t{ check_inboundness(1); return vmprog_extract_b(&IP, prg); }; auto extract_w = [&]() -> uint16_t { check_inboundness(2); return vmprog_extract_w(&IP, prg); }; auto extract_dw = [&]() -> uint32_t { check_inboundness(4); return vmprog_extract_dw(&IP, prg); }; auto extract_qw = [&]() -> uint64_t { check_inboundness(8); return vmprog_extract_qw(&IP, prg); }; auto extract_instruction = [&]() -> uint8_t{ return extract_b(); }; auto extract_sslot_id = [&]() -> sslot_id_t{ return extract_dw(); }; auto extract_near_pointer = [&]() -> near_ptr_t{ return extract_qw(); }; auto extract_track_array_index = [&]() -> tai_t{ return extract_w(); }; bool second_phase = false; auto fph_register_landing = [&](near_ptr_t pos){ if (!second_phase){ if (bookmarks.count(pos) == 0){ if (used_names == names.size()) names.push_back("Закладка_" + std::to_string(used_names)); bookmarks.insert({pos, {used_names, false}}); used_names++; } } }; auto get_bookmark_in_2phase = [&](near_ptr_t pos) -> std::string { if (bookmarks.count(pos) == 0) { fprintf(stderr, "Bruh\n"); std::terminate(); } return names[bookmarks[pos].name_id]; }; auto one_reading = [&](){ while (IP < prgSize) { near_ptr_t start_pos = IP; if (second_phase){ if (bookmarks.count(IP) != 0){ printf("%s:\n", get_bookmark_in_2phase(IP).c_str()); bookmarks[IP].visited = true; } } uint8_t opcode = extract_instruction(); switch (opcode) { #define secPrint(fmt, ...) if (second_phase) {printf("% 3lu) " fmt, start_pos, __VA_ARGS__);} } break; #define secPrintNoArg(str) if (second_phase) {printf("% 3lu) " str, start_pos);} } break; #define instCase(oper_code) case opcodes::oper_code: { #define jcMess(cond, sz_uppercase, x_t, extract_method, printf_sign) \ instCase(JC ## cond ## _ ## sz_uppercase) \ x_t x = extract_method(); \ near_ptr_t dest = extract_near_pointer(); \ fph_register_landing(dest); \ secPrint("JC" #cond "_" #sz_uppercase " %" printf_sign " $%s\n", x, get_bookmark_in_2phase(dest).c_str()) #define jcCacaphony(cond) \ jcMess(cond, B, uint8_t, extract_b, PRIu8) \ jcMess(cond, W, uint16_t, extract_w, PRIu16) \ jcMess(cond, DW, uint32_t, extract_dw, PRIu32) \ jcMess(cond, QW, uint64_t, extract_qw, PRIu64) #define simpleDimple(name) instCase(name) secPrintNoArg(#name "\n") instCase(READ) uint32_t ssid = extract_sslot_id(); secPrint("READ %u\n", ssid) simpleDimple(READZ) instCase(JUMP) uint32_t dest = extract_near_pointer(); fph_register_landing(dest); secPrint("JUMP $%s\n", get_bookmark_in_2phase(dest).c_str()) jcCacaphony(EQUAL) jcCacaphony(LESS) jcCacaphony(GRTR) instCase(FORK) uint32_t ssid = extract_sslot_id(); near_ptr_t dest = extract_near_pointer(); fph_register_landing(dest); secPrint("FORK %u $%s\n", ssid, get_bookmark_in_2phase(dest).c_str()) simpleDimple(MATCH) simpleDimple(DIE) instCase(PARAM_READ_SS_NUMBER) sslot_id_t ssid_max_plus_one = extract_sslot_id(); secPrint("PARAM_READ_SS_NUMBER %u\n", ssid_max_plus_one) instCase(PARAM_FORK_SS_NUMBER) sslot_id_t ssid_max_plus_one = extract_sslot_id(); secPrint("PARAM_FORK_SS_NUMBER %u\n", ssid_max_plus_one) instCase(PARAM_SELARR_LEN) tai_t tai_max_plus_one = extract_track_array_index(); secPrint("PARAM_SELARR_LEN %hu\n", tai_max_plus_one) instCase(PARAM_COLSIFTFUNC_SET) near_ptr_t entry = extract_near_pointer(); fph_register_landing(entry); secPrint("PARAM_COLSIFTFUNC_SET $%s\n", get_bookmark_in_2phase(entry).c_str()) simpleDimple(PARAM_COLSIFTFUNC_WIPE) instCase(MSG_MULTISTART_ALLOWED) uint8_t is_allowed = extract_b(); secPrint("MSG_MULTISTART_ALLOWED %hhu\n", is_allowed) instCase(MSG_FED_INPUT_EXTENDED) uint8_t left = extract_b(); uint8_t right = extract_b(); sslot_id_t part = extract_sslot_id(); secPrint("MSG_FED_INPUT_EXTENDED %hhu %hhu %u\n", left, right, part) instCase(DMOV_RABX_SELARR) tai_t i = extract_track_array_index(); secPrint("DMOV_RABX_SELARR %hu\n", i) instCase(DDIST_RABX_SELARR) tai_t s = extract_track_array_index(); tai_t e = extract_track_array_index(); secPrint("DDIST_RABX_SELARR %hu %hu\n", s, e); simpleDimple(SIFTPRIOR_MIN_RABX) simpleDimple(SIFTPRIOR_MAX_RABX) simpleDimple(SIFT_DONE) instCase(MOV_COLARR_IMM) tai_t tai = extract_track_array_index(); uint64_t imm = extract_qw(); secPrint("MOV_COLARR_IMM %hu %lu\n", tai, imm); instCase(MOV_COLARR_BTPOS) tai_t tai = extract_track_array_index(); secPrint("MOV_COLARR_BTPOS %hu\n", tai); instCase(MOV_SELARR_IMM) tai_t tai = extract_track_array_index(); uint64_t imm = extract_qw(); secPrint("MOV_SELARR_IMM %hu %lu\n", tai, imm); instCase(MOV_SELARR_CHPOS) tai_t tai = extract_track_array_index(); secPrint("MOV_SELARR_CHPOS %hu\n", tai); simpleDimple(INIT) simpleDimple(THROW) default: fprintf(stderr, "Bad opcode\n"); std::terminate(); #undef secPrint #undef secPrintNoArg #undef instCase #undef jcMess #undef jcCacaphony #undef simpleDimple } } }; one_reading(); second_phase = true; IP = 0; one_reading(); } #endif //LIBREGEXIS024_BYTE_CODE_DISASSEMBLER_H