Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "vmdisasm.h"
- #include <array>
- #include <vector>
- #include <string>
- using namespace snes;
- koei::opcode_database_t<256> koei::opcode_db(koei::vm_opcode_database_populate);
- koei::opcode_database_t<48> koei::opcode_db_long(koei::vm_opcode_database_long_populate);
- //-------+----------------+-------+-------------------------------------
- // code | nickname | args | operation
- //-------+----------------+-------+-------------------------------------
- #if 0
- // 00-0F | LOADL quick | 0 | left = <quick>
- // 10-1F | LOADR quick | 0 | right = <quick>
- // 20-2F | STORE quick | 0 | <quick> = left
- // 30-3F | PUSH quick | 0 | push <quick>
- // 40-4F | LOADL qimm | 0 | left = <qimm>
- // 50-5F | LOADR qimm | 0 | right = <qimm>
- // 60-6F | PUSH qimm | 0 | push <qimm>
- // 70-7F | ADD qimm | 0 | left = left + <qimm>
- #endif
- #if 0
- // 80 | (illegal) | --- | (illegal)
- // 81 | LOADL near | 1 | left = <near>
- // 82 | LOADL far | 2 | left = <far>
- // 83 | LOADR near | 1 | right = <near>
- // 84 | LOADR far | 2 | right = <far>
- // 85 | STORE near | 1 | <near> = left
- // 86 | STORE far | 2 | <far> = left
- // 87 | PUSH near | 1 | push <near>
- // 88 | PUSH far | 2 | push <far>
- // 89 | BYTE LOADL imm1| 1 | left = (int8)<imm1>
- // 8A | LOADL imm2 | 2 | left = <imm2>
- // 8B | BYTE LOADR imm1| 1 | right = (int8)<imm1>
- // 8C | LOADR imm2 | 2 | right = <imm2>
- // 8D | BYTE PUSH imm1 | 1 | push (int8)<imm1>
- // 8E | PUSH imm2 | 2 | push <imm2>
- // 8F | BYTE ADD imm1 | 1 | left = left + (int8)<imm1>
- // 90 | ADD imm2 | 2 | left = left + <imm2>
- // 91-9F | (illegal) | --- | (illegal)
- #endif
- #if 0
- // A0 | BYTE LOADL far | 2 | left = (uint8)<far>
- // A1 | BYTE LOADR far | 2 | right = (uint8)<far>
- // A2 | BYTE STORE far | 2 | (uint8)<far> = left
- // A3 | BYTE PUSH far | 2 | push (uint8)<far>
- // A4 | LOADL abs | 2 | left = <abs>
- // A5 | BYTE LOADL abs | 2 | left = (uint8)<abs>
- // A6 | LOADR abs | 2 | right = <abs>
- // A7 | BYTE LOADR abs | 2 | right = (uint8)<abs>
- // A8 | STORE abs | 2 | <abs> = left
- // A9 | BYTE STORE abs | 2 | (uint8)<abs> = left
- // AA | PUSH abs | 2 | push <abs>
- // AB | BYTE PUSH abs | 2 | push (uint8)<abs>
- // AC | CALL abs | 2 | call <abs>
- // AD | COPY imm2 | 2 | copy <imm2> bytes from *left to *right
- // AE | UNSTACK imm1 | 1 | stackptr = stackptr + (uint8)<imm1>
- // AF | UNSTACK imm2 | 2 | stackptr = stackptr + <imm2>
- // B0 | DEREF | 0 | left = *left
- // B1 | POPSTORE | 0 | pop right; *right = left
- // B2 | NOP | 0 | no operation
- // B3 | PUSHL | 0 | push left
- // B4 | POPR | 0 | pop right
- // B5 | MULT | 0 | left = left * right
- // B6 | SDIV | 0 | left = (int16)left / (int16)right
- // B7 | LONG (prefix) | var. | (prefix for 32-bit instructions)
- // B8 | UDIV | 0 | left = (uint16)left / (uint16)right
- // B9 | SMOD | 0 | left = (int16)left % (int16)right
- // BA | UMOD | 0 | left = (uint16)left % (uint16)right
- // BB | ADD | 0 | left = left + right
- // BC | SUB | 0 | left = left - right
- // BD | LSHIFT | 0 | left = left << right
- // BE | URSHIFT | 0 | left = (uint16)left >> right
- // BF | SRSHIFT | 0 | left = (int16)left >> right
- // C0 | CMPEQ | 0 | left = (left == right)
- // C1 | CMPNE | 0 | left = (left != right)
- // C2 | SCMPLT | 0 | left = ((int16)left < (int16)right)
- // C3 | SCMPLE | 0 | left = ((int16)left <= (int16)right)
- // C4 | SCMPGT | 0 | left = ((int16)left > (int16)right)
- // C5 | SCMPGE | 0 | left = ((int16)left >= (int16)right)
- // C6 | UCMPLT | 0 | left = ((uint16)left < (uint16)right)
- // C7 | UCMPLE | 0 | left = ((uint16)left <= (uint16)right)
- // C8 | UCMPGT | 0 | left = ((uint16)left > (uint16)right)
- // C9 | UCMPGE | 0 | left = ((uint16)left >= (uint16)right)
- // CA | NOT | 0 | left = !left
- // CB | MINUS | 0 | left = -left
- // CC | COMPL | 0 | left = ~left
- // CD | SWAP | 0 | swap left <-> right
- // CE | (illegal) | --- | (illegal)
- // CF | RETURN | 0 | return from function
- #endif
- #if 0
- // D0 | INC | 0 | ++left
- // D1 | DEC | 0 | --left
- // D2 | LSHIFT1 | 0 | left = left << 1
- // D3 | BYTE DEREF | 0 | left = *(uint8 *)left
- // D4 | BYTE POPSTORE | 0 | pop right; *(uint8 *)right = left
- // D5 | SWITCH offs,num|2+2+tbl| contiguous switch (see below)
- // D6 | JUMP abs | 2 | instrptr = <abs>
- // D7 | JUMPT abs | 2 | if (left != 0) instrptr = <abs>
- // D8 | JUMPF abs | 2 | if (left == 0) instrptr = <abs>
- // D9 | SWITCH num | 2+tbl | noncontiguous switch (see below)
- // DA | AND | 0 | left = left & right
- // DB | OR | 0 | left = left | right
- // DC | XOR | 0 | left = left ^ right
- // DD | CALLPTR | 0 | call *left
- // DE | LEAL far | 2 | left = &<far>
- // DF | LEAR far | 2 | right = &<far>
- // E0 | SLOADBF sz,pos | 1+1 | signed bitfield extract (see below)
- // E1 | ULOADBF sz,pos | 1+1 | unsigned bitfield extract (see below)
- // E2 | STOREBF sz,pos | 1+1 | bitfield insert (see below)
- // E3 | JUMP back | 1 | instrptr += <back>-256
- // E4 | JUMPT back | 1 | if (left != 0) instrptr += <back>-256
- // E5 | JUMPF back | 1 | if (left == 0) instrptr += <back>-256
- // E6 | JUMP ahead | 1 | instrptr += <ahead>
- // E7 | JUMPT ahead | 1 | if (left != 0) instrptr += <ahead>
- // E8 | JUMPF ahead | 1 | if (left == 0) instrptr += <ahead>
- // E9 | CALL abs,imm1 | 2+1 | call <abs>; stackptr += (uint8)<imm1>
- // EA | CALLPTR imm1 | 1 | call *left; stackptr += (uint8)<imm1>
- // EB-FE | (illegal) | --- | (illegal)
- // FF | BREAK | --- | debug breakpoint
- #endif
- void snes::koei::vm_opcode_database_populate(koei::opcode_database_t<256> &db)
- {
- db.add_opcode_data(0x00, 0x0f, opcode_data_t("ldl", "l = %s", mode_t::quick_frame_relative));
- db.add_opcode_data(0x10, 0x1f, opcode_data_t("ldr", "r = %s", mode_t::quick_frame_relative));
- db.add_opcode_data(0x20, 0x2f, opcode_data_t("store", "%s = l", mode_t::quick_frame_relative));
- db.add_opcode_data(0x30, 0x3f, opcode_data_t("push", "push %s", mode_t::quick_frame_relative));
- db.add_opcode_data(0x40, 0x4f, opcode_data_t("ldl", "l = %s", mode_t::quick_immediate));
- db.add_opcode_data(0x50, 0x5f, opcode_data_t("ldr", "r = %s", mode_t::quick_immediate));
- db.add_opcode_data(0x60, 0x6f, opcode_data_t("push", "push %s", mode_t::quick_immediate));
- db.add_opcode_data(0x70, 0x7f, opcode_data_t("add", "l += %s", mode_t::quick_immediate));
- db.add_opcode_data(0x80, opcode_data_t("bad", "illegal 80"));
- db.add_opcode_data(0x81, opcode_data_t("ldl", "l = %s", mode_t::near_frame_relative));
- db.add_opcode_data(0x82, opcode_data_t("ldl", "l = %s", mode_t::far_frame_relative));
- db.add_opcode_data(0x83, opcode_data_t("ldr", "r = %s", mode_t::near_frame_relative));
- db.add_opcode_data(0x84, opcode_data_t("ldr", "r = %s", mode_t::far_frame_relative));
- db.add_opcode_data(0x85, opcode_data_t("store", "%s = l", mode_t::near_frame_relative));
- db.add_opcode_data(0x86, opcode_data_t("store", "%s = l", mode_t::far_frame_relative));
- db.add_opcode_data(0x87, opcode_data_t("push", "push %s", mode_t::near_frame_relative));
- db.add_opcode_data(0x88, opcode_data_t("push", "push %s", mode_t::far_frame_relative));
- db.add_opcode_data(0x89, opcode_data_t("ldl", "l = %s", mode_t::immediate_byte));
- db.add_opcode_data(0x8a, opcode_data_t("ldl", "l = %s", mode_t::immediate));
- db.add_opcode_data(0x8b, opcode_data_t("ldr", "r = %s", mode_t::immediate_byte));
- db.add_opcode_data(0x8c, opcode_data_t("ldr", "r = %s", mode_t::immediate));
- db.add_opcode_data(0x8d, opcode_data_t("push" , "push %s", mode_t::immediate_byte));
- db.add_opcode_data(0x8e, opcode_data_t("push", "push %s", mode_t::immediate));
- db.add_opcode_data(0x8f, opcode_data_t("add", "l += %s", mode_t::immediate_byte));
- db.add_opcode_data(0x90, opcode_data_t("add", "l += %s", mode_t::immediate));
- db.add_opcode_data(0x91, 0x9f, opcode_data_t("bad", "illegal 91"));
- db.add_opcode_data(0xa0, opcode_data_t("ldl", "l = (u8)%s", mode_t::far_frame_relative));
- db.add_opcode_data(0xa1, opcode_data_t("ldr", "r = (u8)%s", mode_t::far_frame_relative));
- db.add_opcode_data(0xa2, opcode_data_t("store", "(u8)%s = l", mode_t::far_frame_relative));
- db.add_opcode_data(0xa3, opcode_data_t("push", "push (u8)%s", mode_t::far_frame_relative));
- db.add_opcode_data(0xa4, opcode_data_t("ldl", "l = %s", mode_t::absolute));
- db.add_opcode_data(0xa5, opcode_data_t("ldl", "l = *(u8*)%s", mode_t::absolute));
- db.add_opcode_data(0xa6, opcode_data_t("ldr", "r = %s", mode_t::absolute));
- db.add_opcode_data(0xa7, opcode_data_t("ldr", "r = *(u8*)%s", mode_t::absolute));
- db.add_opcode_data(0xa8, opcode_data_t("store", "*%s = l", mode_t::absolute));
- db.add_opcode_data(0xa9, opcode_data_t("store", "*(u8*)%s = l", mode_t::absolute));
- db.add_opcode_data(0xaa, opcode_data_t("push", "push *%s", mode_t::absolute));
- db.add_opcode_data(0xab, opcode_data_t("push", "push *(u8*)%s", mode_t::absolute));
- db.add_opcode_data(0xac, opcode_data_t("call", "call %s", mode_t::call_absolute));
- db.add_opcode_data(0xad, opcode_data_t("copy", "copy %s bytes from *l to *r", mode_t::immediate));
- db.add_opcode_data(0xae, opcode_data_t("unstack", "stackptr += %s", mode_t::immediate_byte));
- db.add_opcode_data(0xaf, opcode_data_t("unstack", "stackptr += %s", mode_t::immediate));
- db.add_opcode_data(0xb0, opcode_data_t("deref", "l = *l"));
- db.add_opcode_data(0xb1, opcode_data_t("popstore", "pop r, *r = l"));
- db.add_opcode_data(0xb2, opcode_data_t("nop", "no operation"));
- db.add_opcode_data(0xb3, opcode_data_t("pushl", "push l"));
- db.add_opcode_data(0xb4, opcode_data_t("popr", "pop r"));
- db.add_opcode_data(0xb5, opcode_data_t("mul", "l *= r"));
- db.add_opcode_data(0xb6, opcode_data_t("sdiv", "l /= r"));
- db.add_opcode_data(0xb7, opcode_data_t("long", "long %s", mode_t::extended));
- db.add_opcode_data(0xb8, opcode_data_t("udiv", "l /= (u)r"));
- db.add_opcode_data(0xb9, opcode_data_t("smod", "l %= r"));
- db.add_opcode_data(0xba, opcode_data_t("umod", "l %= (u)r"));
- db.add_opcode_data(0xbb, opcode_data_t("add", "l += r"));
- db.add_opcode_data(0xbc, opcode_data_t("sub", "l -= r"));
- db.add_opcode_data(0xbd, opcode_data_t("shl", "l <<= r"));
- db.add_opcode_data(0xbe, opcode_data_t("shru", "l >>= r (u)"));
- db.add_opcode_data(0xbf, opcode_data_t("shr", "l >>= r"));
- db.add_opcode_data(0xc0, opcode_data_t("cmpeq", "l == r"));
- db.add_opcode_data(0xc1, opcode_data_t("cmpne", "l != r"));
- db.add_opcode_data(0xc2, opcode_data_t("cmplt", "l < r"));
- db.add_opcode_data(0xc3, opcode_data_t("cmple", "l <= r"));
- db.add_opcode_data(0xc4, opcode_data_t("cmpgt", "l > r"));
- db.add_opcode_data(0xc5, opcode_data_t("cmpge", "l >= r"));
- db.add_opcode_data(0xc6, opcode_data_t("cmpltu", "l < r (u)"));
- db.add_opcode_data(0xc7, opcode_data_t("cmpleu", "l <= r (u)"));
- db.add_opcode_data(0xc8, opcode_data_t("cmpgtu", "l > r (u)"));
- db.add_opcode_data(0xc9, opcode_data_t("cmpgeu", "l >= r (u)"));
- db.add_opcode_data(0xca, opcode_data_t("not", "l = !l"));
- db.add_opcode_data(0xcb, opcode_data_t("neg", "l = -l"));
- db.add_opcode_data(0xcc, opcode_data_t("compl", "l = ~l"));
- db.add_opcode_data(0xcd, opcode_data_t("swap", "swap l <-> r"));
- db.add_opcode_data(0xce, opcode_data_t("bad", "illegal ce"));
- db.add_opcode_data(0xcf, opcode_data_t("ret", "return"));
- db.add_opcode_data(0xd0, opcode_data_t("inc", "l++"));
- db.add_opcode_data(0xd1, opcode_data_t("dec", "l--"));
- db.add_opcode_data(0xd2, opcode_data_t("shl1", "l <<= 1"));
- db.add_opcode_data(0xd3, opcode_data_t("deref", "l = *(u8 *)l"));
- db.add_opcode_data(0xd4, opcode_data_t("popstore", "pop r, *(u8 *)r = l"));
- db.add_opcode_data(0xd5, opcode_data_t("switch", "switch (contiguous)", mode_t::switch_c));
- db.add_opcode_data(0xd6, opcode_data_t("goto", "goto %s", mode_t::absolute_goto));
- db.add_opcode_data(0xd7, opcode_data_t("bnz", "if (l) goto %s", mode_t::absolute_goto));
- db.add_opcode_data(0xd8, opcode_data_t("bz", "if (!l) goto %s", mode_t::absolute_goto));
- db.add_opcode_data(0xd9, opcode_data_t("switchnc", "switch (noncontiguous)", mode_t::switch_nc));
- db.add_opcode_data(0xda, opcode_data_t("and", "l &= r"));
- db.add_opcode_data(0xdb, opcode_data_t("or", "l |= r"));
- db.add_opcode_data(0xdc, opcode_data_t("xor", "l ^= r"));
- db.add_opcode_data(0xdd, opcode_data_t("call", "call *l", mode_t::call));
- db.add_opcode_data(0xde, opcode_data_t("leal", "l = &%s", mode_t::far_frame_relative));
- db.add_opcode_data(0xdf, opcode_data_t("lear", "r = &%s", mode_t::far_frame_relative));
- db.add_opcode_data(0xe0, opcode_data_t("bfes", "bitfield extract signed"));
- db.add_opcode_data(0xe1, opcode_data_t("bfeu", "bitfield extract"));
- db.add_opcode_data(0xe2, opcode_data_t("bfi", "bitfield insert"));
- db.add_opcode_data(0xe3, opcode_data_t("jmp", "IP += %s", mode_t::branch_back));
- db.add_opcode_data(0xe4, opcode_data_t("jmpnz", "if (l) IP += %s", mode_t::branch_back));
- db.add_opcode_data(0xe5, opcode_data_t("jmpz", "if (!l) IP += %s", mode_t::branch_back));
- db.add_opcode_data(0xe6, opcode_data_t("jmp", "IP += %s", mode_t::branch_forward));
- db.add_opcode_data(0xe7, opcode_data_t("jmpnz", "if (l) IP += %s", mode_t::branch_forward));
- db.add_opcode_data(0xe8, opcode_data_t("jmpz", "if (!l) IP += %s", mode_t::branch_forward));
- db.add_opcode_data(0xe9, opcode_data_t("call", "call %s", mode_t::call_stack));
- db.add_opcode_data(0xea, opcode_data_t("call", "call %s", mode_t::call_stack));
- db.add_opcode_data(0xeb, 0xfe, opcode_data_t("bad", "illegal eb"));
- db.add_opcode_data(0xff, opcode_data_t("break", "debug breakpoint"));
- }
- #if 0
- // LONG sub-codes
- // 00 | (illegal) | --- | (illegal)
- // 01 | MULT | 0 | left = left * right
- // 02 | SDIV | 0 | left = (int32)left / (int32)right
- // 03 | ADD | 0 | left = left + right
- // 04 | SUB | 0 | left = left - right
- // 05 | MINUS | 0 | left = -left
- // 06 | CMPEQ | 0 | left = (left == right)
- // 07 | CMPNE | 0 | left = (left != right)
- // 08 | SCMPLT | 0 | left = ((int32)left < (int32)right)
- // 09 | SCMPLE | 0 | left = ((int32)left <= (int32)right)
- // 0A | SCMPGT | 0 | left = ((int32)left > (int32)right)
- // 0B | SCMPGE | 0 | left = ((int32)left >= (int32)right)
- // 0C | LOADL far | 2 | left = <far>
- // 0D | LOADR far | 2 | right = <far>
- // 0E | STORE far | 2 | <far> = left
- // 0F | PUSH far | 2 | push <far>
- // 10 | LOADL abs | 2 | left = <abs>
- // 11 | LOADR abs | 2 | right = <abs>
- // 12 | STORE abs | 2 | <abs> = left
- // 13 | PUSH abs | 2 | push <abs>
- // 14 | PUSHL | 0 | push left
- // 15 | POPR | 0 | pop right
- // 16 | DEREF | 0 | left = *(int32 *)left
- // 17 | POPSTORE | 0 | pop right; *(int32 *)right = left
- // 18 | LOADL imm4| 4 | left = <imm4>
- // 19 | LOADR imm4| 4 | right = <imm4>
- // 1A | SWAP | 0 | swap left <-> right
- // 1B | INC | 0 | ++left
- // 1C | DEC | 0 | --left
- // 1D | BOOL | 0 | left = ((int32)left != 0)
- // 1E | SMOD | 0 | left = (int32)left % (int32)right
- // 1F | LSHIFT | 0 | left = left << right
- // 20 | SRSHIFT | 0 | left = (int32)left >> right
- // 21 | COMPL | 0 | left = ~left
- // 22 | AND | 0 | left = left & right
- // 23 | OR | 0 | left = left | right
- // 24 | XOR | 0 | left = left ^ right
- // 25 | SEXTEND | 0 | left = (int32)(int16)left
- // 26 | UEXTEND | 0 | left = (uint32)(uint16)left
- // 27 | NOP | 0 | no operation
- // 28 | NOT (?) | 0 | apparently bugged (see below)
- // 29 | UCMPLT | 0 | left = ((uint32)left < (uint32)right)
- // 2A | UCMPLE | 0 | left = ((uint32)left <= (uint32)right)
- // 2B | UCMPGT | 0 | left = ((uint32)left > (uint32)right)
- // 2C | UCMPGE | 0 | left = ((uint32)left >= (uint32)right)
- // 2D | URSHIFT | 0 | left = (uint32)left >> right
- // 2E | UDIV | 0 | left = (uint32)left / (uint32)right
- // 2F | UMOD | 0 | left = (uint32)left % (uint32)right
- #endif
- void snes::koei::vm_opcode_database_long_populate(koei::opcode_database_t<48> &db)
- {
- db.add_opcode_data(0x00, opcode_data_t("bad", "illegal 00"));
- db.add_opcode_data(0x01, opcode_data_t("mul", "l *= r"));
- db.add_opcode_data(0x02, opcode_data_t("sdiv", "l /= r (signed)"));
- db.add_opcode_data(0x03, opcode_data_t("add", "l += r"));
- db.add_opcode_data(0x04, opcode_data_t("sub", "l -= r"));
- db.add_opcode_data(0x05, opcode_data_t("neg", "l = -l"));
- db.add_opcode_data(0x06, opcode_data_t("cmpeq", "l == r"));
- db.add_opcode_data(0x07, opcode_data_t("cmpne", "l != r"));
- db.add_opcode_data(0x08, opcode_data_t("cmplt", "l < r (signed)"));
- db.add_opcode_data(0x09, opcode_data_t("cmple", "l <= r (signed)"));
- db.add_opcode_data(0x0A, opcode_data_t("cmpgt", "l > r)"));
- db.add_opcode_data(0x0B, opcode_data_t("cmpge", "l >= r)"));
- db.add_opcode_data(0x0C, opcode_data_t("ldl", "l = %s", mode_t::far_frame_relative));
- db.add_opcode_data(0x0D, opcode_data_t("ldr", "r = %s", mode_t::far_frame_relative));
- db.add_opcode_data(0x0E, opcode_data_t("store", "%s = l", mode_t::far_frame_relative));
- db.add_opcode_data(0x0F, opcode_data_t("push", "push %s", mode_t::far_frame_relative));
- db.add_opcode_data(0x10, opcode_data_t("ldl", "l = *(%s)", mode_t::absolute));
- db.add_opcode_data(0x11, opcode_data_t("ldr", "r = *(%s)", mode_t::absolute));
- db.add_opcode_data(0x12, opcode_data_t("store", "*(%s) = l", mode_t::absolute));
- db.add_opcode_data(0x13, opcode_data_t("push", "push *(%s)", mode_t::absolute));
- db.add_opcode_data(0x14, opcode_data_t("pushl", "push l"));
- db.add_opcode_data(0x15, opcode_data_t("pop r", "pop r"));
- db.add_opcode_data(0x16, opcode_data_t("deref", "l = *(i32 *)l"));
- db.add_opcode_data(0x17, opcode_data_t("popstore", "pop r, *(i32 *)r = l"));
- db.add_opcode_data(0x18, opcode_data_t("ldl", "l = %s", mode_t::immediate));
- db.add_opcode_data(0x19, opcode_data_t("ldr", "r = %s", mode_t::immediate));
- db.add_opcode_data(0x1A, opcode_data_t("swap", "swap l <-> r"));
- db.add_opcode_data(0x1B, opcode_data_t("inc", "l++"));
- db.add_opcode_data(0x1C, opcode_data_t("dec", "l--"));
- db.add_opcode_data(0x1D, opcode_data_t("bool", "l != 0"));
- db.add_opcode_data(0x1E, opcode_data_t("smod", "l %= r (signed)"));
- db.add_opcode_data(0x1F, opcode_data_t("shl", "l <<= r"));
- db.add_opcode_data(0x20, opcode_data_t("shr", "l >>= r (signed)"));
- db.add_opcode_data(0x21, opcode_data_t("comp", "l = ~l"));
- db.add_opcode_data(0x22, opcode_data_t("and", "l &= r"));
- db.add_opcode_data(0x23, opcode_data_t("or", "l |= r"));
- db.add_opcode_data(0x24, opcode_data_t("xor", "l ^= r"));
- db.add_opcode_data(0x25, opcode_data_t("sext", "l = sign extend"));
- db.add_opcode_data(0x26, opcode_data_t("uext", "l = zero extend"));
- db.add_opcode_data(0x27, opcode_data_t("nop", "no operation"));
- db.add_opcode_data(0x28, opcode_data_t("not", "l = !l"));
- db.add_opcode_data(0x29, opcode_data_t("cmpltu", "l < r"));
- db.add_opcode_data(0x2A, opcode_data_t("cmpleu", "l <= r"));
- db.add_opcode_data(0x2B, opcode_data_t("cmpgtu", "l > r"));
- db.add_opcode_data(0x2C, opcode_data_t("cmpgeu", "l >= r"));
- db.add_opcode_data(0x2D, opcode_data_t("shru", "l >>= r"));
- db.add_opcode_data(0x2E, opcode_data_t("divu", "l /= r"));
- db.add_opcode_data(0x2F, opcode_data_t("modu", "l %= r"));
- }
- namespace koei_disasm
- {
- const int qoffset[16] =
- {
- -24, -22, -20, -18, -16, -14, -12, -10,
- -8, -6, -4, -2, 11, 13, 15, 17,
- };
- const char *qname[16] =
- {
- "var12",
- "var11",
- "var10",
- "var9",
- "var8",
- "var7",
- "var6",
- "var5",
- "var4",
- "var3",
- "var2",
- "var1",
- "arg1",
- "arg2",
- "arg3",
- "arg4",
- };
- void print_frame_relative(char *pbuf, const int data)
- {
- switch (data) {
- case 0: strcpy(pbuf, "FP.return_addr"); break;
- case 2: strcpy(pbuf, "FP.old_SP"); break;
- case 4: strcpy(pbuf, "FP.old_FP"); break;
- case 6: strcpy(pbuf, "FP.old_PC"); break;
- case 8: strcpy(pbuf, "FP.resv"); break;
- case 9: strcpy(pbuf, "FP.caller_PC"); break;
- default:
- if (data > 0) {
- if (data >= 11 && (data & 1)) {
- sprintf(pbuf, "FP.arg%i", ((data - 11) / 2) + 1);
- } else {
- sprintf(pbuf, "FP[%i]", data);
- }
- } else {
- if (data <= -2 && (data & 1) == 0) {
- sprintf(pbuf, "FP.var%i", ((2 - data) / 2) + 1);
- } else {
- sprintf(pbuf, "FP[%i]", data);
- }
- }
- break;
- }
- }
- }
- int koei::disasm_t::disassemble(const u08 *mem, char *result)
- {
- addr_map_t::const_iterator function_iter;
- addr_map_t::const_iterator data_iter;
- std::vector<char> data_buffer(256);
- data_buffer[0] = 0;
- char *dbuf = data_buffer.data();
- std::vector<char> parameters_buffer(256);
- parameters_buffer[0] = 0;
- char *pbuf = parameters_buffer.data();
- result[0] = 0;
- if (opt.absolute_address) {
- char buf[16];
- ASSERT(zero);
- int diff = uintptr_t(mem) - uintptr_t(zero);
- sprintf(buf, "%06x ", diff);
- strcat(result, buf);
- }
- if (opt.address) {
- char buf[16];
- sprintf(buf, "%06lx ", reg.PCl);
- strcat(result, buf);
- }
- // print instruction mnemonic
- const u08 opcode = mem[0];
- const koei::opcode_data_t &op_data = koei::opcode_db[opcode];
- const char *fmt = nullptr;
- const char *ibuf = op_data.short_name;
- if (opt.pretty_ops && op_data.long_name) {
- fmt = op_data.long_name;
- }
- int inc = 0;
- sval = -65536;
- data = -1;
- // print parameters
- switch (op_data.mode) {
- case mode_t::quick_frame_relative:
- data = opcode & 0xf;
- strcpy(pbuf, koei_disasm::qname[data]);
- if (fmt) {
- sprintf(dbuf, fmt, pbuf);
- }
- inc = 1;
- break;
- case mode_t::quick_immediate:
- data = opcode & 0xf;
- sprintf(pbuf, "#%i", data);
- if (fmt) {
- sprintf(dbuf, fmt, pbuf);
- }
- inc = 1;
- break;
- case mode_t::immediate_byte:
- data = mem[1];
- if (data >= 0x20 && data <= 0x7e) {
- sprintf(pbuf, "#$%.2x \'%c\'", data, char(data));
- } else {
- sprintf(pbuf, "#$%.2x", data);
- }
- if (fmt) {
- sprintf(dbuf, fmt, pbuf);
- }
- inc = 2;
- break;
- case mode_t::immediate:
- data = mem[1] + mem[2] * 256;
- data_iter = data_map.find(data);
- //local_data_map[data];
- if (data_iter == data_map.end()) {
- sprintf(pbuf, "#$%.4x", data);
- } else {
- sprintf(pbuf, "%s", data_iter->second.c_str());
- }
- if (fmt) {
- sprintf(dbuf, fmt, pbuf);
- }
- inc = 3;
- break;
- case mode_t::near_frame_relative:
- data = *(char *)(&mem[1]);
- koei_disasm::print_frame_relative(pbuf, data);
- if (fmt) {
- sprintf(dbuf, fmt, pbuf);
- }
- inc = 2;
- break;
- case mode_t::far_frame_relative:
- data = *(short *)(&mem[1]);
- koei_disasm::print_frame_relative(pbuf, data);
- if (fmt) {
- sprintf(dbuf, fmt, pbuf);
- }
- inc = 3;
- break;
- case mode_t::absolute:
- data = mem[1] + mem[2] * 256;
- data_iter = data_map.find(data);
- //local_data_map[data];
- if (data_iter == data_map.end()) {
- sprintf(pbuf, "$%.4x", data);
- } else {
- sprintf(pbuf, "%s", data_iter->second.c_str());
- }
- if (fmt) {
- sprintf(dbuf, fmt, pbuf);
- }
- inc = 3;
- break;
- case mode_t::absolute_goto:
- data = mem[1] + mem[2] * 256;
- function_iter = func_map.find(data);
- if (function_iter == func_map.end()) {
- if (data > reg.PC) {
- sprintf(pbuf, "label_%.4x", data);
- line_label[data] = pbuf;
- } else {
- sprintf(pbuf, "$%.4x", data);
- }
- } else {
- sprintf(pbuf, "%s", function_iter->second.c_str());
- }
- if (fmt) {
- sprintf(dbuf, fmt, pbuf);
- }
- inc = 3;
- break;
- case mode_t::call_absolute:
- data = mem[1] + mem[2] * 256;
- function_iter = func_map.find(data | (reg.PCl & 0xff0000));
- local_func_map[data | (reg.PCl & 0xff0000)];
- if (function_iter == func_map.end()) {
- sprintf(pbuf, "$%.4x", data);
- } else {
- sprintf(pbuf, "%s", function_iter->second.c_str());
- }
- if (fmt) {
- sprintf(dbuf, fmt, pbuf);
- }
- inc = 3;
- break;
- case mode_t::call:
- sprintf(pbuf, "*left");
- inc = 1;
- break;
- case mode_t::switch_c:
- inc = 1;
- // smallest case (signed negative)
- sval = i16(mem[inc] + mem[inc + 1] * 256);
- inc += 2;
- // cases
- data = mem[inc] + mem[inc + 1] * 256;
- inc += 2;
- if (data < 256) {
- sprintf(pbuf, "%i to %i, %i cases", sval, sval + data - 1, data);
- // default target
- inc += 2;
- // target
- inc += data * 2;
- } else {
- // unusual number of switch cases, likely not valid code
- BREAK();
- inc = 0;
- }
- break;
- case mode_t::switch_nc:
- inc = 1;
- data = mem[inc] + mem[inc + 1] * 256;
- if (data < 256) {
- sprintf(pbuf, "%i cases", data);
- // number of cases
- inc += 2;
- // cases = value : target
- inc += data * 2 * 2;
- // default target
- inc += 2;
- } else {
- // unusual number of switch cases, likely not valid code
- BREAK();
- inc = 0;
- }
- break;
- case mode_t::call_stack:
- switch (opcode) {
- // call abs; stackptr += imm8
- case 0xe9:
- data = mem[1] + mem[2] * 256;
- sval = mem[3];
- function_iter = func_map.find(data | (reg.PCl & 0xff0000));
- local_func_map[data | (reg.PCl & 0xff0000)];
- if (function_iter == func_map.end()) {
- sprintf(pbuf, "$%.4x +%i", data, sval);
- } else {
- sprintf(pbuf, "%s +%i", function_iter->second.c_str(), sval);
- }
- if (fmt) {
- sprintf(dbuf, fmt, pbuf);
- }
- inc = 4;
- break;
- // call *l; stackptr += imm8
- case 0xea:
- sval = mem[1];
- sprintf(pbuf, "*l +%i", sval);
- if (fmt) {
- sprintf(dbuf, fmt, pbuf);
- }
- inc = 2;
- break;
- }
- break;
- case mode_t::branch_back:
- data = mem[1] - 256;
- sprintf(pbuf, "$%.4x", reg.PC + data);
- inc = 2;
- break;
- case mode_t::branch_forward:
- data = mem[1];
- sprintf(pbuf, "$%.4x", reg.PC + data);
- inc = 2;
- break;
- case mode_t::extended:
- inc = disassemble_long(&mem[1], pbuf);
- if (fmt) {
- sprintf(dbuf, fmt, pbuf);
- }
- break;
- case mode_t::null:
- inc = 1;
- break;
- default:
- BREAK();
- };
- if (!fmt) {
- // instruction
- strcat(result, ibuf);
- // parameters
- if (pbuf[0]) {
- strcat(result, " ");
- strcat(result, pbuf);
- }
- } else {
- if (!dbuf[0]) {
- strcat(result, fmt);
- } else {
- strcat(result, dbuf);
- }
- }
- // hexdump
- if (opt.hexdump && inc > 0) {
- int line_length = 32;
- if (opt.absolute_address) {
- line_length += 7;
- }
- if (opt.address) {
- line_length += 7;
- }
- std::vector<char> buf2(inc * 2 + 2);
- for (int i = 0; i < buf2.size(); i++) {
- buf2[i] = 0;
- }
- char *buf = buf2.data();
- for (int i = 0; i < inc; i++) {
- sprintf(buf + i * 2, "%.2x", mem[i]);
- }
- if (strlen(result) < line_length) {
- for (int i = strlen(result); i < line_length; i++) {
- result[i] = ' ';
- }
- result[line_length] = 0;
- }
- strcat(result, "; ");
- strcat(result, buf);
- }
- switch (op_data.mode) {
- case mode_t::switch_c:
- if (data < 256) {
- strcat(result, "\n; ");
- strcat(result, pbuf);
- strcat(result, ": ");
- for (int i = 0; i < data; i++) {
- const int case_value = i16(sval + i);
- const int case_address = mem[1 + 2 * 2 + (i + 1) * 2] + mem[1 + 2 * 2 + (i + 1) * 2 + 1] * 256;
- if (case_address > reg.PC) {
- sprintf(pbuf, "case %i", case_value);
- line_label[case_address] = pbuf;
- }
- sprintf(pbuf, "%i=$%04x ", case_value, case_address);
- strcat(result, pbuf);
- }
- const int default_address = mem[1 + 2 * 2] + mem[1 + 2 * 2 + 1] * 256;
- if (default_address > reg.PC) {
- sprintf(pbuf, "default");
- line_label[default_address] = pbuf;
- }
- sprintf(pbuf, "default=$%04x", default_address);
- strcat(result, pbuf);
- }
- break;
- case mode_t::switch_nc:
- if (data < 256) {
- strcat(result, "\n; ");
- strcat(result, pbuf);
- strcat(result, ": ");
- for (int i = 0; i < data; i++) {
- const int case_value = mem[3 + i * 4] + mem[3 + i * 4 + 1] * 256;
- const int case_address = mem[3 + i * 4 + 2] + mem[3 + i * 4 + 3] * 256;
- if (case_address > reg.PC) {
- sprintf(pbuf, "case $%04x", case_value);
- line_label[case_address] = pbuf;
- }
- sprintf(pbuf, "$%04x=$%04x ", case_value, case_address);
- strcat(result, pbuf);
- }
- const int default_address = mem[3 + data * 4] + mem[3 + data * 4 + 1] * 256;
- if (default_address > reg.PC) {
- sprintf(pbuf, "default");
- line_label[default_address] = pbuf;
- }
- sprintf(pbuf, "default=$%04x", default_address);
- strcat(result, pbuf);
- }
- break;
- }
- #if 0
- if (opt.newline_on_return) {
- switch (opcode) {
- // return
- case 0xCF:
- strcat(result, "\n");
- break;
- }
- }
- #endif
- reg.PCl += inc;
- return inc;
- }
- int koei::disasm_t::disassemble_long(const u08 *mem, char *result)
- {
- int inc = 0;
- sval = -65536;
- data = -1;
- std::vector<char> data_buffer(256);
- data_buffer[0] = 0;
- char *dbuf = data_buffer.data();
- std::vector<char> parameters_buffer(256);
- parameters_buffer[0] = 0;
- char *pbuf = parameters_buffer.data();
- const u08 long_opcode = mem[0];
- const koei::opcode_data_t &op_data = long_opcode >= 0 && long_opcode < 0x30 ?
- koei::opcode_db_long[long_opcode] :
- koei::opcode_db_long[0];
- const char *fmt = nullptr;
- const char *ibuf = op_data.short_name;
- if (opt.pretty_ops && op_data.long_name) {
- fmt = op_data.long_name;
- }
- switch (op_data.mode) {
- case mode_t::absolute:
- data = *(u16 *)(&mem[1]);
- sprintf(pbuf, "$%.4x", data);
- if (fmt) {
- sprintf(dbuf, fmt, pbuf);
- }
- inc = 4;
- break;
- case mode_t::far_frame_relative:
- data = *(i16 *)(&mem[1]);
- koei_disasm::print_frame_relative(pbuf, data);
- if (fmt) {
- sprintf(dbuf, fmt, pbuf);
- }
- inc = 4;
- break;
- case mode_t::immediate:
- //data = mem[1] + (mem[2] << 8) + (mem[3] << 16) + (mem[4] << 24);
- data = *(u32 *)(&mem[1]);
- sprintf(pbuf, "$%.4x", data);
- if (fmt) {
- sprintf(dbuf, fmt, pbuf);
- }
- inc = 6;
- break;
- case mode_t::null:
- inc = 2;
- break;
- }
- if (long_opcode == 0 || long_opcode > 0x30) {
- char buf[16];
- inc = 0;
- sprintf(buf, "bad $%.2x", long_opcode);
- strcat(result, buf);
- } else {
- if (!fmt) {
- // instruction
- strcat(result, ibuf);
- // parameters
- if (pbuf[0]) {
- strcat(result, " ");
- strcat(result, pbuf);
- }
- } else {
- if (!dbuf[0]) {
- strcat(result, fmt);
- } else {
- strcat(result, dbuf);
- }
- }
- }
- return inc;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement