Advertisement
Guest User

Untitled

a guest
Oct 23rd, 2019
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.18 KB | None | 0 0
  1. #include "vmdisasm.h"
  2.  
  3. #include <array>
  4. #include <vector>
  5. #include <string>
  6.  
  7. using namespace snes;
  8.  
  9. koei::opcode_database_t<256> koei::opcode_db(koei::vm_opcode_database_populate);
  10. koei::opcode_database_t<48> koei::opcode_db_long(koei::vm_opcode_database_long_populate);
  11.  
  12. //-------+----------------+-------+-------------------------------------
  13. // code | nickname | args | operation
  14. //-------+----------------+-------+-------------------------------------
  15. #if 0
  16. // 00-0F | LOADL quick | 0 | left = <quick>
  17. // 10-1F | LOADR quick | 0 | right = <quick>
  18. // 20-2F | STORE quick | 0 | <quick> = left
  19. // 30-3F | PUSH quick | 0 | push <quick>
  20. // 40-4F | LOADL qimm | 0 | left = <qimm>
  21. // 50-5F | LOADR qimm | 0 | right = <qimm>
  22. // 60-6F | PUSH qimm | 0 | push <qimm>
  23. // 70-7F | ADD qimm | 0 | left = left + <qimm>
  24. #endif
  25.  
  26. #if 0
  27. // 80 | (illegal) | --- | (illegal)
  28. // 81 | LOADL near | 1 | left = <near>
  29. // 82 | LOADL far | 2 | left = <far>
  30. // 83 | LOADR near | 1 | right = <near>
  31. // 84 | LOADR far | 2 | right = <far>
  32. // 85 | STORE near | 1 | <near> = left
  33. // 86 | STORE far | 2 | <far> = left
  34. // 87 | PUSH near | 1 | push <near>
  35. // 88 | PUSH far | 2 | push <far>
  36. // 89 | BYTE LOADL imm1| 1 | left = (int8)<imm1>
  37. // 8A | LOADL imm2 | 2 | left = <imm2>
  38. // 8B | BYTE LOADR imm1| 1 | right = (int8)<imm1>
  39. // 8C | LOADR imm2 | 2 | right = <imm2>
  40. // 8D | BYTE PUSH imm1 | 1 | push (int8)<imm1>
  41. // 8E | PUSH imm2 | 2 | push <imm2>
  42. // 8F | BYTE ADD imm1 | 1 | left = left + (int8)<imm1>
  43.  
  44. // 90 | ADD imm2 | 2 | left = left + <imm2>
  45. // 91-9F | (illegal) | --- | (illegal)
  46. #endif
  47.  
  48. #if 0
  49. // A0 | BYTE LOADL far | 2 | left = (uint8)<far>
  50. // A1 | BYTE LOADR far | 2 | right = (uint8)<far>
  51. // A2 | BYTE STORE far | 2 | (uint8)<far> = left
  52. // A3 | BYTE PUSH far | 2 | push (uint8)<far>
  53. // A4 | LOADL abs | 2 | left = <abs>
  54. // A5 | BYTE LOADL abs | 2 | left = (uint8)<abs>
  55. // A6 | LOADR abs | 2 | right = <abs>
  56. // A7 | BYTE LOADR abs | 2 | right = (uint8)<abs>
  57. // A8 | STORE abs | 2 | <abs> = left
  58. // A9 | BYTE STORE abs | 2 | (uint8)<abs> = left
  59. // AA | PUSH abs | 2 | push <abs>
  60. // AB | BYTE PUSH abs | 2 | push (uint8)<abs>
  61. // AC | CALL abs | 2 | call <abs>
  62. // AD | COPY imm2 | 2 | copy <imm2> bytes from *left to *right
  63. // AE | UNSTACK imm1 | 1 | stackptr = stackptr + (uint8)<imm1>
  64. // AF | UNSTACK imm2 | 2 | stackptr = stackptr + <imm2>
  65.  
  66. // B0 | DEREF | 0 | left = *left
  67. // B1 | POPSTORE | 0 | pop right; *right = left
  68. // B2 | NOP | 0 | no operation
  69. // B3 | PUSHL | 0 | push left
  70. // B4 | POPR | 0 | pop right
  71. // B5 | MULT | 0 | left = left * right
  72. // B6 | SDIV | 0 | left = (int16)left / (int16)right
  73. // B7 | LONG (prefix) | var. | (prefix for 32-bit instructions)
  74. // B8 | UDIV | 0 | left = (uint16)left / (uint16)right
  75. // B9 | SMOD | 0 | left = (int16)left % (int16)right
  76. // BA | UMOD | 0 | left = (uint16)left % (uint16)right
  77. // BB | ADD | 0 | left = left + right
  78. // BC | SUB | 0 | left = left - right
  79. // BD | LSHIFT | 0 | left = left << right
  80. // BE | URSHIFT | 0 | left = (uint16)left >> right
  81. // BF | SRSHIFT | 0 | left = (int16)left >> right
  82.  
  83. // C0 | CMPEQ | 0 | left = (left == right)
  84. // C1 | CMPNE | 0 | left = (left != right)
  85. // C2 | SCMPLT | 0 | left = ((int16)left < (int16)right)
  86. // C3 | SCMPLE | 0 | left = ((int16)left <= (int16)right)
  87. // C4 | SCMPGT | 0 | left = ((int16)left > (int16)right)
  88. // C5 | SCMPGE | 0 | left = ((int16)left >= (int16)right)
  89. // C6 | UCMPLT | 0 | left = ((uint16)left < (uint16)right)
  90. // C7 | UCMPLE | 0 | left = ((uint16)left <= (uint16)right)
  91. // C8 | UCMPGT | 0 | left = ((uint16)left > (uint16)right)
  92. // C9 | UCMPGE | 0 | left = ((uint16)left >= (uint16)right)
  93. // CA | NOT | 0 | left = !left
  94. // CB | MINUS | 0 | left = -left
  95. // CC | COMPL | 0 | left = ~left
  96. // CD | SWAP | 0 | swap left <-> right
  97. // CE | (illegal) | --- | (illegal)
  98. // CF | RETURN | 0 | return from function
  99. #endif
  100.  
  101. #if 0
  102. // D0 | INC | 0 | ++left
  103. // D1 | DEC | 0 | --left
  104. // D2 | LSHIFT1 | 0 | left = left << 1
  105. // D3 | BYTE DEREF | 0 | left = *(uint8 *)left
  106. // D4 | BYTE POPSTORE | 0 | pop right; *(uint8 *)right = left
  107. // D5 | SWITCH offs,num|2+2+tbl| contiguous switch (see below)
  108. // D6 | JUMP abs | 2 | instrptr = <abs>
  109. // D7 | JUMPT abs | 2 | if (left != 0) instrptr = <abs>
  110. // D8 | JUMPF abs | 2 | if (left == 0) instrptr = <abs>
  111. // D9 | SWITCH num | 2+tbl | noncontiguous switch (see below)
  112. // DA | AND | 0 | left = left & right
  113. // DB | OR | 0 | left = left | right
  114. // DC | XOR | 0 | left = left ^ right
  115. // DD | CALLPTR | 0 | call *left
  116. // DE | LEAL far | 2 | left = &<far>
  117. // DF | LEAR far | 2 | right = &<far>
  118.  
  119. // E0 | SLOADBF sz,pos | 1+1 | signed bitfield extract (see below)
  120. // E1 | ULOADBF sz,pos | 1+1 | unsigned bitfield extract (see below)
  121. // E2 | STOREBF sz,pos | 1+1 | bitfield insert (see below)
  122. // E3 | JUMP back | 1 | instrptr += <back>-256
  123. // E4 | JUMPT back | 1 | if (left != 0) instrptr += <back>-256
  124. // E5 | JUMPF back | 1 | if (left == 0) instrptr += <back>-256
  125. // E6 | JUMP ahead | 1 | instrptr += <ahead>
  126. // E7 | JUMPT ahead | 1 | if (left != 0) instrptr += <ahead>
  127. // E8 | JUMPF ahead | 1 | if (left == 0) instrptr += <ahead>
  128. // E9 | CALL abs,imm1 | 2+1 | call <abs>; stackptr += (uint8)<imm1>
  129. // EA | CALLPTR imm1 | 1 | call *left; stackptr += (uint8)<imm1>
  130. // EB-FE | (illegal) | --- | (illegal)
  131. // FF | BREAK | --- | debug breakpoint
  132. #endif
  133.  
  134.  
  135. void snes::koei::vm_opcode_database_populate(koei::opcode_database_t<256> &db)
  136. {
  137. db.add_opcode_data(0x00, 0x0f, opcode_data_t("ldl", "l = %s", mode_t::quick_frame_relative));
  138. db.add_opcode_data(0x10, 0x1f, opcode_data_t("ldr", "r = %s", mode_t::quick_frame_relative));
  139. db.add_opcode_data(0x20, 0x2f, opcode_data_t("store", "%s = l", mode_t::quick_frame_relative));
  140. db.add_opcode_data(0x30, 0x3f, opcode_data_t("push", "push %s", mode_t::quick_frame_relative));
  141. db.add_opcode_data(0x40, 0x4f, opcode_data_t("ldl", "l = %s", mode_t::quick_immediate));
  142. db.add_opcode_data(0x50, 0x5f, opcode_data_t("ldr", "r = %s", mode_t::quick_immediate));
  143. db.add_opcode_data(0x60, 0x6f, opcode_data_t("push", "push %s", mode_t::quick_immediate));
  144. db.add_opcode_data(0x70, 0x7f, opcode_data_t("add", "l += %s", mode_t::quick_immediate));
  145.  
  146. db.add_opcode_data(0x80, opcode_data_t("bad", "illegal 80"));
  147.  
  148. db.add_opcode_data(0x81, opcode_data_t("ldl", "l = %s", mode_t::near_frame_relative));
  149. db.add_opcode_data(0x82, opcode_data_t("ldl", "l = %s", mode_t::far_frame_relative));
  150. db.add_opcode_data(0x83, opcode_data_t("ldr", "r = %s", mode_t::near_frame_relative));
  151. db.add_opcode_data(0x84, opcode_data_t("ldr", "r = %s", mode_t::far_frame_relative));
  152. db.add_opcode_data(0x85, opcode_data_t("store", "%s = l", mode_t::near_frame_relative));
  153. db.add_opcode_data(0x86, opcode_data_t("store", "%s = l", mode_t::far_frame_relative));
  154. db.add_opcode_data(0x87, opcode_data_t("push", "push %s", mode_t::near_frame_relative));
  155. db.add_opcode_data(0x88, opcode_data_t("push", "push %s", mode_t::far_frame_relative));
  156. db.add_opcode_data(0x89, opcode_data_t("ldl", "l = %s", mode_t::immediate_byte));
  157. db.add_opcode_data(0x8a, opcode_data_t("ldl", "l = %s", mode_t::immediate));
  158. db.add_opcode_data(0x8b, opcode_data_t("ldr", "r = %s", mode_t::immediate_byte));
  159. db.add_opcode_data(0x8c, opcode_data_t("ldr", "r = %s", mode_t::immediate));
  160. db.add_opcode_data(0x8d, opcode_data_t("push" , "push %s", mode_t::immediate_byte));
  161. db.add_opcode_data(0x8e, opcode_data_t("push", "push %s", mode_t::immediate));
  162. db.add_opcode_data(0x8f, opcode_data_t("add", "l += %s", mode_t::immediate_byte));
  163. db.add_opcode_data(0x90, opcode_data_t("add", "l += %s", mode_t::immediate));
  164.  
  165. db.add_opcode_data(0x91, 0x9f, opcode_data_t("bad", "illegal 91"));
  166.  
  167. db.add_opcode_data(0xa0, opcode_data_t("ldl", "l = (u8)%s", mode_t::far_frame_relative));
  168. db.add_opcode_data(0xa1, opcode_data_t("ldr", "r = (u8)%s", mode_t::far_frame_relative));
  169. db.add_opcode_data(0xa2, opcode_data_t("store", "(u8)%s = l", mode_t::far_frame_relative));
  170. db.add_opcode_data(0xa3, opcode_data_t("push", "push (u8)%s", mode_t::far_frame_relative));
  171. db.add_opcode_data(0xa4, opcode_data_t("ldl", "l = %s", mode_t::absolute));
  172. db.add_opcode_data(0xa5, opcode_data_t("ldl", "l = *(u8*)%s", mode_t::absolute));
  173. db.add_opcode_data(0xa6, opcode_data_t("ldr", "r = %s", mode_t::absolute));
  174. db.add_opcode_data(0xa7, opcode_data_t("ldr", "r = *(u8*)%s", mode_t::absolute));
  175. db.add_opcode_data(0xa8, opcode_data_t("store", "*%s = l", mode_t::absolute));
  176. db.add_opcode_data(0xa9, opcode_data_t("store", "*(u8*)%s = l", mode_t::absolute));
  177. db.add_opcode_data(0xaa, opcode_data_t("push", "push *%s", mode_t::absolute));
  178. db.add_opcode_data(0xab, opcode_data_t("push", "push *(u8*)%s", mode_t::absolute));
  179. db.add_opcode_data(0xac, opcode_data_t("call", "call %s", mode_t::call_absolute));
  180. db.add_opcode_data(0xad, opcode_data_t("copy", "copy %s bytes from *l to *r", mode_t::immediate));
  181. db.add_opcode_data(0xae, opcode_data_t("unstack", "stackptr += %s", mode_t::immediate_byte));
  182. db.add_opcode_data(0xaf, opcode_data_t("unstack", "stackptr += %s", mode_t::immediate));
  183. db.add_opcode_data(0xb0, opcode_data_t("deref", "l = *l"));
  184. db.add_opcode_data(0xb1, opcode_data_t("popstore", "pop r, *r = l"));
  185. db.add_opcode_data(0xb2, opcode_data_t("nop", "no operation"));
  186. db.add_opcode_data(0xb3, opcode_data_t("pushl", "push l"));
  187. db.add_opcode_data(0xb4, opcode_data_t("popr", "pop r"));
  188. db.add_opcode_data(0xb5, opcode_data_t("mul", "l *= r"));
  189. db.add_opcode_data(0xb6, opcode_data_t("sdiv", "l /= r"));
  190.  
  191. db.add_opcode_data(0xb7, opcode_data_t("long", "long %s", mode_t::extended));
  192.  
  193. db.add_opcode_data(0xb8, opcode_data_t("udiv", "l /= (u)r"));
  194. db.add_opcode_data(0xb9, opcode_data_t("smod", "l %= r"));
  195. db.add_opcode_data(0xba, opcode_data_t("umod", "l %= (u)r"));
  196. db.add_opcode_data(0xbb, opcode_data_t("add", "l += r"));
  197. db.add_opcode_data(0xbc, opcode_data_t("sub", "l -= r"));
  198. db.add_opcode_data(0xbd, opcode_data_t("shl", "l <<= r"));
  199. db.add_opcode_data(0xbe, opcode_data_t("shru", "l >>= r (u)"));
  200. db.add_opcode_data(0xbf, opcode_data_t("shr", "l >>= r"));
  201. db.add_opcode_data(0xc0, opcode_data_t("cmpeq", "l == r"));
  202. db.add_opcode_data(0xc1, opcode_data_t("cmpne", "l != r"));
  203. db.add_opcode_data(0xc2, opcode_data_t("cmplt", "l < r"));
  204. db.add_opcode_data(0xc3, opcode_data_t("cmple", "l <= r"));
  205. db.add_opcode_data(0xc4, opcode_data_t("cmpgt", "l > r"));
  206. db.add_opcode_data(0xc5, opcode_data_t("cmpge", "l >= r"));
  207. db.add_opcode_data(0xc6, opcode_data_t("cmpltu", "l < r (u)"));
  208. db.add_opcode_data(0xc7, opcode_data_t("cmpleu", "l <= r (u)"));
  209. db.add_opcode_data(0xc8, opcode_data_t("cmpgtu", "l > r (u)"));
  210. db.add_opcode_data(0xc9, opcode_data_t("cmpgeu", "l >= r (u)"));
  211. db.add_opcode_data(0xca, opcode_data_t("not", "l = !l"));
  212. db.add_opcode_data(0xcb, opcode_data_t("neg", "l = -l"));
  213. db.add_opcode_data(0xcc, opcode_data_t("compl", "l = ~l"));
  214. db.add_opcode_data(0xcd, opcode_data_t("swap", "swap l <-> r"));
  215.  
  216. db.add_opcode_data(0xce, opcode_data_t("bad", "illegal ce"));
  217.  
  218. db.add_opcode_data(0xcf, opcode_data_t("ret", "return"));
  219. db.add_opcode_data(0xd0, opcode_data_t("inc", "l++"));
  220. db.add_opcode_data(0xd1, opcode_data_t("dec", "l--"));
  221. db.add_opcode_data(0xd2, opcode_data_t("shl1", "l <<= 1"));
  222. db.add_opcode_data(0xd3, opcode_data_t("deref", "l = *(u8 *)l"));
  223. db.add_opcode_data(0xd4, opcode_data_t("popstore", "pop r, *(u8 *)r = l"));
  224. db.add_opcode_data(0xd5, opcode_data_t("switch", "switch (contiguous)", mode_t::switch_c));
  225. db.add_opcode_data(0xd6, opcode_data_t("goto", "goto %s", mode_t::absolute_goto));
  226. db.add_opcode_data(0xd7, opcode_data_t("bnz", "if (l) goto %s", mode_t::absolute_goto));
  227. db.add_opcode_data(0xd8, opcode_data_t("bz", "if (!l) goto %s", mode_t::absolute_goto));
  228. db.add_opcode_data(0xd9, opcode_data_t("switchnc", "switch (noncontiguous)", mode_t::switch_nc));
  229. db.add_opcode_data(0xda, opcode_data_t("and", "l &= r"));
  230. db.add_opcode_data(0xdb, opcode_data_t("or", "l |= r"));
  231. db.add_opcode_data(0xdc, opcode_data_t("xor", "l ^= r"));
  232. db.add_opcode_data(0xdd, opcode_data_t("call", "call *l", mode_t::call));
  233. db.add_opcode_data(0xde, opcode_data_t("leal", "l = &%s", mode_t::far_frame_relative));
  234. db.add_opcode_data(0xdf, opcode_data_t("lear", "r = &%s", mode_t::far_frame_relative));
  235. db.add_opcode_data(0xe0, opcode_data_t("bfes", "bitfield extract signed"));
  236. db.add_opcode_data(0xe1, opcode_data_t("bfeu", "bitfield extract"));
  237. db.add_opcode_data(0xe2, opcode_data_t("bfi", "bitfield insert"));
  238. db.add_opcode_data(0xe3, opcode_data_t("jmp", "IP += %s", mode_t::branch_back));
  239. db.add_opcode_data(0xe4, opcode_data_t("jmpnz", "if (l) IP += %s", mode_t::branch_back));
  240. db.add_opcode_data(0xe5, opcode_data_t("jmpz", "if (!l) IP += %s", mode_t::branch_back));
  241. db.add_opcode_data(0xe6, opcode_data_t("jmp", "IP += %s", mode_t::branch_forward));
  242. db.add_opcode_data(0xe7, opcode_data_t("jmpnz", "if (l) IP += %s", mode_t::branch_forward));
  243. db.add_opcode_data(0xe8, opcode_data_t("jmpz", "if (!l) IP += %s", mode_t::branch_forward));
  244. db.add_opcode_data(0xe9, opcode_data_t("call", "call %s", mode_t::call_stack));
  245. db.add_opcode_data(0xea, opcode_data_t("call", "call %s", mode_t::call_stack));
  246.  
  247. db.add_opcode_data(0xeb, 0xfe, opcode_data_t("bad", "illegal eb"));
  248. db.add_opcode_data(0xff, opcode_data_t("break", "debug breakpoint"));
  249. }
  250.  
  251. #if 0
  252. // LONG sub-codes
  253. // 00 | (illegal) | --- | (illegal)
  254. // 01 | MULT | 0 | left = left * right
  255. // 02 | SDIV | 0 | left = (int32)left / (int32)right
  256. // 03 | ADD | 0 | left = left + right
  257. // 04 | SUB | 0 | left = left - right
  258. // 05 | MINUS | 0 | left = -left
  259. // 06 | CMPEQ | 0 | left = (left == right)
  260. // 07 | CMPNE | 0 | left = (left != right)
  261. // 08 | SCMPLT | 0 | left = ((int32)left < (int32)right)
  262. // 09 | SCMPLE | 0 | left = ((int32)left <= (int32)right)
  263. // 0A | SCMPGT | 0 | left = ((int32)left > (int32)right)
  264. // 0B | SCMPGE | 0 | left = ((int32)left >= (int32)right)
  265. // 0C | LOADL far | 2 | left = <far>
  266. // 0D | LOADR far | 2 | right = <far>
  267. // 0E | STORE far | 2 | <far> = left
  268. // 0F | PUSH far | 2 | push <far>
  269. // 10 | LOADL abs | 2 | left = <abs>
  270. // 11 | LOADR abs | 2 | right = <abs>
  271. // 12 | STORE abs | 2 | <abs> = left
  272. // 13 | PUSH abs | 2 | push <abs>
  273. // 14 | PUSHL | 0 | push left
  274. // 15 | POPR | 0 | pop right
  275. // 16 | DEREF | 0 | left = *(int32 *)left
  276. // 17 | POPSTORE | 0 | pop right; *(int32 *)right = left
  277. // 18 | LOADL imm4| 4 | left = <imm4>
  278. // 19 | LOADR imm4| 4 | right = <imm4>
  279. // 1A | SWAP | 0 | swap left <-> right
  280. // 1B | INC | 0 | ++left
  281. // 1C | DEC | 0 | --left
  282. // 1D | BOOL | 0 | left = ((int32)left != 0)
  283. // 1E | SMOD | 0 | left = (int32)left % (int32)right
  284. // 1F | LSHIFT | 0 | left = left << right
  285. // 20 | SRSHIFT | 0 | left = (int32)left >> right
  286. // 21 | COMPL | 0 | left = ~left
  287. // 22 | AND | 0 | left = left & right
  288. // 23 | OR | 0 | left = left | right
  289. // 24 | XOR | 0 | left = left ^ right
  290. // 25 | SEXTEND | 0 | left = (int32)(int16)left
  291. // 26 | UEXTEND | 0 | left = (uint32)(uint16)left
  292. // 27 | NOP | 0 | no operation
  293. // 28 | NOT (?) | 0 | apparently bugged (see below)
  294. // 29 | UCMPLT | 0 | left = ((uint32)left < (uint32)right)
  295. // 2A | UCMPLE | 0 | left = ((uint32)left <= (uint32)right)
  296. // 2B | UCMPGT | 0 | left = ((uint32)left > (uint32)right)
  297. // 2C | UCMPGE | 0 | left = ((uint32)left >= (uint32)right)
  298. // 2D | URSHIFT | 0 | left = (uint32)left >> right
  299. // 2E | UDIV | 0 | left = (uint32)left / (uint32)right
  300. // 2F | UMOD | 0 | left = (uint32)left % (uint32)right
  301. #endif
  302.  
  303. void snes::koei::vm_opcode_database_long_populate(koei::opcode_database_t<48> &db)
  304. {
  305. db.add_opcode_data(0x00, opcode_data_t("bad", "illegal 00"));
  306. db.add_opcode_data(0x01, opcode_data_t("mul", "l *= r"));
  307. db.add_opcode_data(0x02, opcode_data_t("sdiv", "l /= r (signed)"));
  308. db.add_opcode_data(0x03, opcode_data_t("add", "l += r"));
  309. db.add_opcode_data(0x04, opcode_data_t("sub", "l -= r"));
  310. db.add_opcode_data(0x05, opcode_data_t("neg", "l = -l"));
  311. db.add_opcode_data(0x06, opcode_data_t("cmpeq", "l == r"));
  312. db.add_opcode_data(0x07, opcode_data_t("cmpne", "l != r"));
  313. db.add_opcode_data(0x08, opcode_data_t("cmplt", "l < r (signed)"));
  314. db.add_opcode_data(0x09, opcode_data_t("cmple", "l <= r (signed)"));
  315. db.add_opcode_data(0x0A, opcode_data_t("cmpgt", "l > r)"));
  316. db.add_opcode_data(0x0B, opcode_data_t("cmpge", "l >= r)"));
  317. db.add_opcode_data(0x0C, opcode_data_t("ldl", "l = %s", mode_t::far_frame_relative));
  318. db.add_opcode_data(0x0D, opcode_data_t("ldr", "r = %s", mode_t::far_frame_relative));
  319. db.add_opcode_data(0x0E, opcode_data_t("store", "%s = l", mode_t::far_frame_relative));
  320. db.add_opcode_data(0x0F, opcode_data_t("push", "push %s", mode_t::far_frame_relative));
  321. db.add_opcode_data(0x10, opcode_data_t("ldl", "l = *(%s)", mode_t::absolute));
  322. db.add_opcode_data(0x11, opcode_data_t("ldr", "r = *(%s)", mode_t::absolute));
  323. db.add_opcode_data(0x12, opcode_data_t("store", "*(%s) = l", mode_t::absolute));
  324. db.add_opcode_data(0x13, opcode_data_t("push", "push *(%s)", mode_t::absolute));
  325. db.add_opcode_data(0x14, opcode_data_t("pushl", "push l"));
  326. db.add_opcode_data(0x15, opcode_data_t("pop r", "pop r"));
  327. db.add_opcode_data(0x16, opcode_data_t("deref", "l = *(i32 *)l"));
  328. db.add_opcode_data(0x17, opcode_data_t("popstore", "pop r, *(i32 *)r = l"));
  329. db.add_opcode_data(0x18, opcode_data_t("ldl", "l = %s", mode_t::immediate));
  330. db.add_opcode_data(0x19, opcode_data_t("ldr", "r = %s", mode_t::immediate));
  331. db.add_opcode_data(0x1A, opcode_data_t("swap", "swap l <-> r"));
  332. db.add_opcode_data(0x1B, opcode_data_t("inc", "l++"));
  333. db.add_opcode_data(0x1C, opcode_data_t("dec", "l--"));
  334. db.add_opcode_data(0x1D, opcode_data_t("bool", "l != 0"));
  335. db.add_opcode_data(0x1E, opcode_data_t("smod", "l %= r (signed)"));
  336. db.add_opcode_data(0x1F, opcode_data_t("shl", "l <<= r"));
  337. db.add_opcode_data(0x20, opcode_data_t("shr", "l >>= r (signed)"));
  338. db.add_opcode_data(0x21, opcode_data_t("comp", "l = ~l"));
  339. db.add_opcode_data(0x22, opcode_data_t("and", "l &= r"));
  340. db.add_opcode_data(0x23, opcode_data_t("or", "l |= r"));
  341. db.add_opcode_data(0x24, opcode_data_t("xor", "l ^= r"));
  342. db.add_opcode_data(0x25, opcode_data_t("sext", "l = sign extend"));
  343. db.add_opcode_data(0x26, opcode_data_t("uext", "l = zero extend"));
  344. db.add_opcode_data(0x27, opcode_data_t("nop", "no operation"));
  345. db.add_opcode_data(0x28, opcode_data_t("not", "l = !l"));
  346. db.add_opcode_data(0x29, opcode_data_t("cmpltu", "l < r"));
  347. db.add_opcode_data(0x2A, opcode_data_t("cmpleu", "l <= r"));
  348. db.add_opcode_data(0x2B, opcode_data_t("cmpgtu", "l > r"));
  349. db.add_opcode_data(0x2C, opcode_data_t("cmpgeu", "l >= r"));
  350. db.add_opcode_data(0x2D, opcode_data_t("shru", "l >>= r"));
  351. db.add_opcode_data(0x2E, opcode_data_t("divu", "l /= r"));
  352. db.add_opcode_data(0x2F, opcode_data_t("modu", "l %= r"));
  353. }
  354.  
  355. namespace koei_disasm
  356. {
  357. const int qoffset[16] =
  358. {
  359. -24, -22, -20, -18, -16, -14, -12, -10,
  360. -8, -6, -4, -2, 11, 13, 15, 17,
  361. };
  362.  
  363. const char *qname[16] =
  364. {
  365. "var12",
  366. "var11",
  367. "var10",
  368. "var9",
  369. "var8",
  370. "var7",
  371. "var6",
  372. "var5",
  373. "var4",
  374. "var3",
  375. "var2",
  376. "var1",
  377. "arg1",
  378. "arg2",
  379. "arg3",
  380. "arg4",
  381. };
  382.  
  383. void print_frame_relative(char *pbuf, const int data)
  384. {
  385. switch (data) {
  386. case 0: strcpy(pbuf, "FP.return_addr"); break;
  387. case 2: strcpy(pbuf, "FP.old_SP"); break;
  388. case 4: strcpy(pbuf, "FP.old_FP"); break;
  389. case 6: strcpy(pbuf, "FP.old_PC"); break;
  390. case 8: strcpy(pbuf, "FP.resv"); break;
  391. case 9: strcpy(pbuf, "FP.caller_PC"); break;
  392. default:
  393. if (data > 0) {
  394. if (data >= 11 && (data & 1)) {
  395. sprintf(pbuf, "FP.arg%i", ((data - 11) / 2) + 1);
  396. } else {
  397. sprintf(pbuf, "FP[%i]", data);
  398. }
  399. } else {
  400. if (data <= -2 && (data & 1) == 0) {
  401. sprintf(pbuf, "FP.var%i", ((2 - data) / 2) + 1);
  402. } else {
  403. sprintf(pbuf, "FP[%i]", data);
  404. }
  405. }
  406. break;
  407. }
  408. }
  409. }
  410.  
  411. int koei::disasm_t::disassemble(const u08 *mem, char *result)
  412. {
  413. addr_map_t::const_iterator function_iter;
  414. addr_map_t::const_iterator data_iter;
  415.  
  416. std::vector<char> data_buffer(256);
  417. data_buffer[0] = 0;
  418. char *dbuf = data_buffer.data();
  419.  
  420. std::vector<char> parameters_buffer(256);
  421. parameters_buffer[0] = 0;
  422. char *pbuf = parameters_buffer.data();
  423.  
  424. result[0] = 0;
  425.  
  426. if (opt.absolute_address) {
  427. char buf[16];
  428. ASSERT(zero);
  429. int diff = uintptr_t(mem) - uintptr_t(zero);
  430. sprintf(buf, "%06x ", diff);
  431. strcat(result, buf);
  432. }
  433.  
  434. if (opt.address) {
  435. char buf[16];
  436. sprintf(buf, "%06lx ", reg.PCl);
  437. strcat(result, buf);
  438. }
  439.  
  440. // print instruction mnemonic
  441. const u08 opcode = mem[0];
  442. const koei::opcode_data_t &op_data = koei::opcode_db[opcode];
  443.  
  444. const char *fmt = nullptr;
  445. const char *ibuf = op_data.short_name;
  446. if (opt.pretty_ops && op_data.long_name) {
  447. fmt = op_data.long_name;
  448. }
  449.  
  450. int inc = 0;
  451.  
  452. sval = -65536;
  453. data = -1;
  454.  
  455. // print parameters
  456. switch (op_data.mode) {
  457. case mode_t::quick_frame_relative:
  458. data = opcode & 0xf;
  459. strcpy(pbuf, koei_disasm::qname[data]);
  460. if (fmt) {
  461. sprintf(dbuf, fmt, pbuf);
  462. }
  463. inc = 1;
  464. break;
  465.  
  466. case mode_t::quick_immediate:
  467. data = opcode & 0xf;
  468. sprintf(pbuf, "#%i", data);
  469. if (fmt) {
  470. sprintf(dbuf, fmt, pbuf);
  471. }
  472. inc = 1;
  473. break;
  474.  
  475. case mode_t::immediate_byte:
  476. data = mem[1];
  477. if (data >= 0x20 && data <= 0x7e) {
  478. sprintf(pbuf, "#$%.2x \'%c\'", data, char(data));
  479. } else {
  480. sprintf(pbuf, "#$%.2x", data);
  481. }
  482. if (fmt) {
  483. sprintf(dbuf, fmt, pbuf);
  484. }
  485. inc = 2;
  486. break;
  487.  
  488. case mode_t::immediate:
  489. data = mem[1] + mem[2] * 256;
  490. data_iter = data_map.find(data);
  491. //local_data_map[data];
  492. if (data_iter == data_map.end()) {
  493. sprintf(pbuf, "#$%.4x", data);
  494. } else {
  495. sprintf(pbuf, "%s", data_iter->second.c_str());
  496. }
  497. if (fmt) {
  498. sprintf(dbuf, fmt, pbuf);
  499. }
  500. inc = 3;
  501. break;
  502.  
  503. case mode_t::near_frame_relative:
  504. data = *(char *)(&mem[1]);
  505. koei_disasm::print_frame_relative(pbuf, data);
  506. if (fmt) {
  507. sprintf(dbuf, fmt, pbuf);
  508. }
  509. inc = 2;
  510. break;
  511.  
  512. case mode_t::far_frame_relative:
  513. data = *(short *)(&mem[1]);
  514. koei_disasm::print_frame_relative(pbuf, data);
  515. if (fmt) {
  516. sprintf(dbuf, fmt, pbuf);
  517. }
  518. inc = 3;
  519. break;
  520.  
  521. case mode_t::absolute:
  522. data = mem[1] + mem[2] * 256;
  523. data_iter = data_map.find(data);
  524. //local_data_map[data];
  525. if (data_iter == data_map.end()) {
  526. sprintf(pbuf, "$%.4x", data);
  527. } else {
  528. sprintf(pbuf, "%s", data_iter->second.c_str());
  529. }
  530. if (fmt) {
  531. sprintf(dbuf, fmt, pbuf);
  532. }
  533. inc = 3;
  534. break;
  535.  
  536. case mode_t::absolute_goto:
  537. data = mem[1] + mem[2] * 256;
  538. function_iter = func_map.find(data);
  539. if (function_iter == func_map.end()) {
  540. if (data > reg.PC) {
  541. sprintf(pbuf, "label_%.4x", data);
  542. line_label[data] = pbuf;
  543. } else {
  544. sprintf(pbuf, "$%.4x", data);
  545. }
  546. } else {
  547. sprintf(pbuf, "%s", function_iter->second.c_str());
  548. }
  549. if (fmt) {
  550. sprintf(dbuf, fmt, pbuf);
  551. }
  552. inc = 3;
  553. break;
  554.  
  555. case mode_t::call_absolute:
  556. data = mem[1] + mem[2] * 256;
  557. function_iter = func_map.find(data | (reg.PCl & 0xff0000));
  558. local_func_map[data | (reg.PCl & 0xff0000)];
  559. if (function_iter == func_map.end()) {
  560. sprintf(pbuf, "$%.4x", data);
  561. } else {
  562. sprintf(pbuf, "%s", function_iter->second.c_str());
  563. }
  564. if (fmt) {
  565. sprintf(dbuf, fmt, pbuf);
  566. }
  567. inc = 3;
  568. break;
  569.  
  570. case mode_t::call:
  571. sprintf(pbuf, "*left");
  572. inc = 1;
  573. break;
  574.  
  575. case mode_t::switch_c:
  576. inc = 1;
  577. // smallest case (signed negative)
  578. sval = i16(mem[inc] + mem[inc + 1] * 256);
  579. inc += 2;
  580. // cases
  581. data = mem[inc] + mem[inc + 1] * 256;
  582. inc += 2;
  583. if (data < 256) {
  584. sprintf(pbuf, "%i to %i, %i cases", sval, sval + data - 1, data);
  585. // default target
  586. inc += 2;
  587. // target
  588. inc += data * 2;
  589. } else {
  590. // unusual number of switch cases, likely not valid code
  591. BREAK();
  592. inc = 0;
  593. }
  594. break;
  595.  
  596. case mode_t::switch_nc:
  597. inc = 1;
  598. data = mem[inc] + mem[inc + 1] * 256;
  599. if (data < 256) {
  600. sprintf(pbuf, "%i cases", data);
  601. // number of cases
  602. inc += 2;
  603. // cases = value : target
  604. inc += data * 2 * 2;
  605. // default target
  606. inc += 2;
  607. } else {
  608. // unusual number of switch cases, likely not valid code
  609. BREAK();
  610. inc = 0;
  611. }
  612. break;
  613.  
  614. case mode_t::call_stack:
  615. switch (opcode) {
  616. // call abs; stackptr += imm8
  617. case 0xe9:
  618. data = mem[1] + mem[2] * 256;
  619. sval = mem[3];
  620. function_iter = func_map.find(data | (reg.PCl & 0xff0000));
  621. local_func_map[data | (reg.PCl & 0xff0000)];
  622. if (function_iter == func_map.end()) {
  623. sprintf(pbuf, "$%.4x +%i", data, sval);
  624. } else {
  625. sprintf(pbuf, "%s +%i", function_iter->second.c_str(), sval);
  626. }
  627. if (fmt) {
  628. sprintf(dbuf, fmt, pbuf);
  629. }
  630. inc = 4;
  631. break;
  632. // call *l; stackptr += imm8
  633. case 0xea:
  634. sval = mem[1];
  635. sprintf(pbuf, "*l +%i", sval);
  636. if (fmt) {
  637. sprintf(dbuf, fmt, pbuf);
  638. }
  639. inc = 2;
  640. break;
  641. }
  642. break;
  643.  
  644. case mode_t::branch_back:
  645. data = mem[1] - 256;
  646. sprintf(pbuf, "$%.4x", reg.PC + data);
  647. inc = 2;
  648. break;
  649.  
  650. case mode_t::branch_forward:
  651. data = mem[1];
  652. sprintf(pbuf, "$%.4x", reg.PC + data);
  653. inc = 2;
  654. break;
  655.  
  656. case mode_t::extended:
  657. inc = disassemble_long(&mem[1], pbuf);
  658. if (fmt) {
  659. sprintf(dbuf, fmt, pbuf);
  660. }
  661. break;
  662.  
  663. case mode_t::null:
  664. inc = 1;
  665. break;
  666.  
  667. default:
  668. BREAK();
  669. };
  670.  
  671. if (!fmt) {
  672. // instruction
  673. strcat(result, ibuf);
  674. // parameters
  675. if (pbuf[0]) {
  676. strcat(result, " ");
  677. strcat(result, pbuf);
  678. }
  679. } else {
  680. if (!dbuf[0]) {
  681. strcat(result, fmt);
  682. } else {
  683. strcat(result, dbuf);
  684. }
  685. }
  686.  
  687. // hexdump
  688. if (opt.hexdump && inc > 0) {
  689. int line_length = 32;
  690. if (opt.absolute_address) {
  691. line_length += 7;
  692. }
  693. if (opt.address) {
  694. line_length += 7;
  695. }
  696. std::vector<char> buf2(inc * 2 + 2);
  697. for (int i = 0; i < buf2.size(); i++) {
  698. buf2[i] = 0;
  699. }
  700. char *buf = buf2.data();
  701.  
  702. for (int i = 0; i < inc; i++) {
  703. sprintf(buf + i * 2, "%.2x", mem[i]);
  704. }
  705. if (strlen(result) < line_length) {
  706. for (int i = strlen(result); i < line_length; i++) {
  707. result[i] = ' ';
  708. }
  709. result[line_length] = 0;
  710. }
  711. strcat(result, "; ");
  712. strcat(result, buf);
  713. }
  714.  
  715. switch (op_data.mode) {
  716. case mode_t::switch_c:
  717. if (data < 256) {
  718. strcat(result, "\n; ");
  719. strcat(result, pbuf);
  720. strcat(result, ": ");
  721. for (int i = 0; i < data; i++) {
  722. const int case_value = i16(sval + i);
  723. const int case_address = mem[1 + 2 * 2 + (i + 1) * 2] + mem[1 + 2 * 2 + (i + 1) * 2 + 1] * 256;
  724. if (case_address > reg.PC) {
  725. sprintf(pbuf, "case %i", case_value);
  726. line_label[case_address] = pbuf;
  727. }
  728. sprintf(pbuf, "%i=$%04x ", case_value, case_address);
  729. strcat(result, pbuf);
  730. }
  731. const int default_address = mem[1 + 2 * 2] + mem[1 + 2 * 2 + 1] * 256;
  732. if (default_address > reg.PC) {
  733. sprintf(pbuf, "default");
  734. line_label[default_address] = pbuf;
  735. }
  736. sprintf(pbuf, "default=$%04x", default_address);
  737. strcat(result, pbuf);
  738. }
  739. break;
  740.  
  741. case mode_t::switch_nc:
  742. if (data < 256) {
  743. strcat(result, "\n; ");
  744. strcat(result, pbuf);
  745. strcat(result, ": ");
  746. for (int i = 0; i < data; i++) {
  747. const int case_value = mem[3 + i * 4] + mem[3 + i * 4 + 1] * 256;
  748. const int case_address = mem[3 + i * 4 + 2] + mem[3 + i * 4 + 3] * 256;
  749. if (case_address > reg.PC) {
  750. sprintf(pbuf, "case $%04x", case_value);
  751. line_label[case_address] = pbuf;
  752. }
  753. sprintf(pbuf, "$%04x=$%04x ", case_value, case_address);
  754. strcat(result, pbuf);
  755. }
  756. const int default_address = mem[3 + data * 4] + mem[3 + data * 4 + 1] * 256;
  757. if (default_address > reg.PC) {
  758. sprintf(pbuf, "default");
  759. line_label[default_address] = pbuf;
  760. }
  761. sprintf(pbuf, "default=$%04x", default_address);
  762. strcat(result, pbuf);
  763. }
  764. break;
  765. }
  766.  
  767. #if 0
  768. if (opt.newline_on_return) {
  769. switch (opcode) {
  770. // return
  771. case 0xCF:
  772. strcat(result, "\n");
  773. break;
  774. }
  775. }
  776. #endif
  777.  
  778. reg.PCl += inc;
  779. return inc;
  780. }
  781.  
  782. int koei::disasm_t::disassemble_long(const u08 *mem, char *result)
  783. {
  784. int inc = 0;
  785. sval = -65536;
  786. data = -1;
  787.  
  788. std::vector<char> data_buffer(256);
  789. data_buffer[0] = 0;
  790. char *dbuf = data_buffer.data();
  791.  
  792. std::vector<char> parameters_buffer(256);
  793. parameters_buffer[0] = 0;
  794. char *pbuf = parameters_buffer.data();
  795.  
  796. const u08 long_opcode = mem[0];
  797. const koei::opcode_data_t &op_data = long_opcode >= 0 && long_opcode < 0x30 ?
  798. koei::opcode_db_long[long_opcode] :
  799. koei::opcode_db_long[0];
  800.  
  801. const char *fmt = nullptr;
  802. const char *ibuf = op_data.short_name;
  803. if (opt.pretty_ops && op_data.long_name) {
  804. fmt = op_data.long_name;
  805. }
  806.  
  807. switch (op_data.mode) {
  808. case mode_t::absolute:
  809. data = *(u16 *)(&mem[1]);
  810. sprintf(pbuf, "$%.4x", data);
  811. if (fmt) {
  812. sprintf(dbuf, fmt, pbuf);
  813. }
  814. inc = 4;
  815. break;
  816.  
  817. case mode_t::far_frame_relative:
  818. data = *(i16 *)(&mem[1]);
  819. koei_disasm::print_frame_relative(pbuf, data);
  820. if (fmt) {
  821. sprintf(dbuf, fmt, pbuf);
  822. }
  823. inc = 4;
  824. break;
  825.  
  826. case mode_t::immediate:
  827. //data = mem[1] + (mem[2] << 8) + (mem[3] << 16) + (mem[4] << 24);
  828. data = *(u32 *)(&mem[1]);
  829. sprintf(pbuf, "$%.4x", data);
  830. if (fmt) {
  831. sprintf(dbuf, fmt, pbuf);
  832. }
  833. inc = 6;
  834. break;
  835.  
  836. case mode_t::null:
  837. inc = 2;
  838. break;
  839. }
  840.  
  841. if (long_opcode == 0 || long_opcode > 0x30) {
  842. char buf[16];
  843. inc = 0;
  844. sprintf(buf, "bad $%.2x", long_opcode);
  845. strcat(result, buf);
  846. } else {
  847. if (!fmt) {
  848. // instruction
  849. strcat(result, ibuf);
  850. // parameters
  851. if (pbuf[0]) {
  852. strcat(result, " ");
  853. strcat(result, pbuf);
  854. }
  855. } else {
  856. if (!dbuf[0]) {
  857. strcat(result, fmt);
  858. } else {
  859. strcat(result, dbuf);
  860. }
  861. }
  862. }
  863.  
  864. return inc;
  865. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement