An ISA definition for Kingdom Hearts 2 AI https://govanify.com/post/kh2ai/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

527 lines
9.5KB

  1. #
  2. #
  3. # Instructions
  4. #
  5. #
  6. # 0x1 =========
  7. # standard push
  8. # so this is how the game does it, it pushes a value, normal stuff. THE. THING.
  9. # IS. it can sometime push an address too, that a syscall relocates. so we're
  10. # going to have to be hacky to get the entire file to be analyzed. sad day.
  11. # ssub_opc is always equal 0, we just define it in a more specific fashion to
  12. # prefer push.v over _push.v, which is dynamically created by the analyzer
  13. :push.v full_ext is opcode=0 & ( sub_opc=1 | sub_opc=0 ) ; full_ext {
  14. push(full_ext:4);
  15. }
  16. #:pushc CLABEL is opcode=0 & ( sub_opc=1 | sub_opc=0 ) ; CLABEL & full_ext {
  17. # push(full_ext:4);
  18. #}
  19. #push and add
  20. :push2_unk0 is opcode_ext=0 & sub_opc_ext=2 & opesub=0 {
  21. }
  22. # push and add to pointer
  23. :push.ap rn, ope2 is opcode_ext=0 & sub_opc_ext=2 & opesub=1 & ope2 & rn {
  24. }
  25. :push2_unk2 is opcode_ext=0 & sub_opc_ext=2 & opesub=2 {
  26. }
  27. :push.l LABEL02 is opcode_ext=0 & sub_opc_ext=2 & opesub=3 & LABEL02 {
  28. push(LABEL02:4);
  29. }
  30. :push3_unk0 is opcode_ext=0 & sub_opc_ext=3 & opesub=0 {
  31. }
  32. #push and add
  33. :push.a rn, ope2 is opcode_ext=0 & sub_opc_ext=3 & opesub=1 & ope2 & rn {
  34. }
  35. #push and add
  36. :push3_unk2 is opcode_ext=0 & sub_opc_ext=3 & opesub=2 {
  37. }
  38. # never used in practice... push pointer as data and not label
  39. :push.ln NOT_LABEL03 is opcode_ext=0 & sub_opc_ext=3 & opesub=3 & NOT_LABEL03 {
  40. push(NOT_LABEL03);
  41. }
  42. # 0x1 =========
  43. # sometimes it has arguments, to check!
  44. # this is a pop_at!!!!!
  45. :pop_unk0 is opcode_ext=1 & ope3=0 & ope2 & rn {
  46. }
  47. :pop.a rn, ope2 is opcode_ext=1 & ope3=1 & ope2 & rn {
  48. }
  49. :popat_unk2 is opcode_ext=1 & ope3=2 & ope2 & rn {
  50. }
  51. # no shit this isn't used in practice
  52. :pop.l LABEL02 is opcode_ext=1 & ope3=3 & LABEL02 {
  53. push(LABEL02:4);
  54. }
  55. :unk2_unk0 is opcode_ext=2 & ope3=0; opcode{
  56. }
  57. :unk2_unk1 is opcode_ext=2 & ope3=1; opcode{
  58. }
  59. :unk2_unk2 is opcode_ext=2 & ope3=2; opcode{
  60. }
  61. :unk2_unk3 is opcode_ext=2 & ope3=3; opcode{
  62. }
  63. # push and add to stack
  64. :push.as ope2 is opcode_ext=3 & ope2{
  65. local tmp:4 = sp;
  66. pop(tmp);
  67. tmp=tmp+ope2;
  68. push(tmp);
  69. }
  70. :unk4 is opcode=4 {
  71. }
  72. # 0x5 =========
  73. # comparison ops
  74. # convert float to int
  75. :cfti is opcode=5 & sub_opc=0 & ssub_opc=0{
  76. local tmp:4 = sp;
  77. pop(tmp);
  78. tmp = round(tmp);
  79. push(tmp);
  80. }
  81. # convert to negative
  82. :neg is opcode=5 & sub_opc=0 & ssub_opc=2{
  83. local tmp:4 = sp;
  84. pop(tmp);
  85. tmp=-tmp;
  86. push(tmp);
  87. }
  88. # invert
  89. :inv is opcode=5 & sub_opc=0 & ssub_opc=3{
  90. local tmp:4 = sp;
  91. pop(tmp);
  92. tmp = ~tmp;
  93. push(tmp);
  94. }
  95. # is equal zero
  96. :eqz is opcode=5 & sub_opc=0 & ( ssub_opc=4 | ssub_opc=8 ){
  97. local tmp:4 = sp;
  98. pop(tmp);
  99. local ret = (tmp == 0);
  100. push(ret);
  101. }
  102. # absolute
  103. :abs is opcode=5 & sub_opc=0 & ssub_opc=5{
  104. local tmp:4 = sp;
  105. pop(tmp);
  106. if(tmp s<= 0) goto <min>;
  107. goto <done>;
  108. <min>
  109. tmp=-tmp;
  110. <done>
  111. push(tmp);
  112. }
  113. # most significant bit
  114. :msb is opcode=5 & sub_opc=0 & ssub_opc=6{
  115. local tmp:4 = sp;
  116. pop(tmp);
  117. tmp = tmp >> 0x1F;
  118. push(tmp);
  119. }
  120. # inferior to one
  121. :info is opcode=5 & sub_opc=0 & ssub_opc=7{
  122. local tmp:4 = sp;
  123. pop(tmp);
  124. push((tmp s< 1));
  125. }
  126. # not equal to zero
  127. :neqz is opcode=5 & sub_opc=0 & ssub_opc=9{
  128. local tmp:4 = sp;
  129. pop(tmp);
  130. push((tmp != 0));
  131. }
  132. # most significant bit inverted
  133. :msbi is opcode=5 & sub_opc=0 & ssub_opc=0xA{
  134. local tmp:4 = sp;
  135. pop(tmp);
  136. tmp = tmp >> 0x1F;
  137. push(~tmp);
  138. }
  139. # is positive
  140. :ipos is opcode=5 & sub_opc=0 & ssub_opc=0xb{
  141. local tmp:4 = sp;
  142. pop(tmp);
  143. push((tmp s> 0));
  144. }
  145. # 0x5 --- floats
  146. # convert int to float
  147. :citf is opcode=5 & sub_opc=1 & ssub_opc=0{
  148. local tmp:4 = sp;
  149. pop(tmp);
  150. tmp=int2float(tmp);
  151. push(tmp);
  152. }
  153. # convert to negative (float)
  154. :negf is opcode=5 & sub_opc=1 & ssub_opc=2{
  155. }
  156. # ABS (float)
  157. :absf is opcode=5 & sub_opc=1 & ssub_opc=5{
  158. local tmp:4 = sp;
  159. pop(tmp);
  160. tmp=abs(tmp);
  161. push(tmp);
  162. }
  163. # inferior to zero (float)
  164. :infzf is opcode=5 & sub_opc=1 & ssub_opc=6{
  165. local tmp:4 = sp;
  166. pop(tmp);
  167. push((tmp f< 0));
  168. }
  169. # inferior or equal to zero (float)
  170. :infoezf is opcode=5 & sub_opc=1 & ssub_opc=7{
  171. local tmp:4 = sp;
  172. pop(tmp);
  173. push((tmp f<= 0));
  174. }
  175. # equal to zero (float)
  176. :eqzf is opcode=5 & sub_opc=1 & ssub_opc=8{
  177. local tmp:4 = sp;
  178. pop(tmp);
  179. push((tmp f== 0));
  180. }
  181. # not equal to zero (float)
  182. :neqzf is opcode=5 & sub_opc=1 & ssub_opc=9{
  183. local tmp:4 = sp;
  184. pop(tmp);
  185. push((tmp f!= 0));
  186. }
  187. # superior or equal to zero (float)
  188. :supoezf is opcode=5 & sub_opc=1 & ssub_opc=0xA{
  189. local tmp:4 = sp;
  190. pop(tmp);
  191. push((tmp f>= 0));
  192. }
  193. # superior to zero (float)
  194. :supzf is opcode=5 & sub_opc=1 & ssub_opc=0xB{
  195. local tmp:4 = sp;
  196. pop(tmp);
  197. push((tmp f> 0));
  198. }
  199. # 0x5 =========
  200. # 0x6 =========
  201. # APU operations
  202. # addition
  203. :add is opcode=6 & sub_opc=0 & ssub_opc=0{
  204. local tmp:4 = sp;
  205. local tmp2:4 = sp;
  206. pop(tmp);
  207. pop(tmp2);
  208. push(tmp2+tmp);
  209. }
  210. # substraction
  211. :sub is opcode=6 & sub_opc=0 & ssub_opc=1{
  212. local tmp:4 = sp;
  213. local tmp2:4 = sp;
  214. pop(tmp);
  215. pop(tmp2);
  216. push(tmp2-tmp);
  217. }
  218. # multiplication
  219. :mul is opcode=6 & sub_opc=0 & ssub_opc=2{
  220. local tmp:4 = sp;
  221. local tmp2:4 = sp;
  222. pop(tmp);
  223. pop(tmp2);
  224. push(tmp2 * tmp);
  225. }
  226. # division
  227. :div is opcode=6 & sub_opc=0 & ssub_opc=3{
  228. local tmp:4 = sp;
  229. local tmp2:4 = sp;
  230. pop(tmp);
  231. pop(tmp2);
  232. push(tmp2 s/ tmp);
  233. }
  234. # modulo
  235. :mod is opcode=6 & sub_opc=0 & ssub_opc=4{
  236. local tmp:4 = sp;
  237. local tmp2:4 = sp;
  238. pop(tmp);
  239. pop(tmp2);
  240. push(tmp2 s% tmp);
  241. }
  242. # logical and
  243. :and is opcode=6 & sub_opc=0 & ssub_opc=5{
  244. local tmp:4 = sp;
  245. local tmp2:4 = sp;
  246. pop(tmp);
  247. pop(tmp2);
  248. push(tmp2&tmp);
  249. }
  250. # logical or
  251. :or is opcode=6 & sub_opc=0 & ssub_opc=6{
  252. local tmp:4 = sp;
  253. local tmp2:4 = sp;
  254. pop(tmp);
  255. pop(tmp2);
  256. push(tmp2|tmp);
  257. }
  258. # logical exclusive or
  259. :xor is opcode=6 & sub_opc=0 & ssub_opc=7{
  260. local tmp:4 = sp;
  261. local tmp2:4 = sp;
  262. pop(tmp);
  263. pop(tmp2);
  264. push(tmp2^tmp);
  265. }
  266. # shift logical left
  267. :sll is opcode=6 & sub_opc=0 & ssub_opc=8{
  268. local tmp:4 = sp;
  269. local tmp2:4 = sp;
  270. pop(tmp);
  271. pop(tmp2);
  272. push(tmp2<<(tmp&0x1F));
  273. }
  274. # shift right arithmetic
  275. :sra is opcode=6 & sub_opc=0 & ssub_opc=9{
  276. local tmp:4 = sp;
  277. local tmp2:4 = sp;
  278. pop(tmp);
  279. pop(tmp2);
  280. push(tmp2>>(tmp&0x1F));
  281. }
  282. # not equal to zero (2 variable stack edition)
  283. :eqzv is opcode=6 & sub_opc=0 & ssub_opc=0xA{
  284. local tmp:4 = sp;
  285. local tmp2:4 = sp;
  286. pop(tmp);
  287. pop(tmp2);
  288. local ret:4 = 1;
  289. if(tmp!=0) goto <next>;
  290. goto <end>;
  291. <next>
  292. if(tmp2==0) goto <end>;
  293. ret=0;
  294. <end>
  295. push(ret);
  296. }
  297. # equal to zero (2 variable stack edition)
  298. :neqzv is opcode=6 & sub_opc=0 & ssub_opc=0xB{
  299. local tmp:4 = sp;
  300. local tmp2:4 = sp;
  301. pop(tmp);
  302. pop(tmp2);
  303. local ret:4 = 1;
  304. if(tmp==0) goto <next>;
  305. goto <end>;
  306. <next>
  307. if(tmp2!=0) goto <end>;
  308. ret=0;
  309. <end>
  310. push(ret);
  311. }
  312. # addition (float)
  313. :addf is opcode=6 & sub_opc=1 & ssub_opc=0{
  314. local tmp:4 = sp;
  315. local tmp2:4 = sp;
  316. pop(tmp);
  317. pop(tmp2);
  318. push(tmp2 f+ tmp);
  319. }
  320. # substraction (float)
  321. :subf is opcode=6 & sub_opc=1 & ssub_opc=1{
  322. local tmp:4 = sp;
  323. local tmp2:4 = sp;
  324. pop(tmp);
  325. pop(tmp2);
  326. push(tmp2 f- tmp);
  327. }
  328. # multiplication (float)
  329. :mulf is opcode=6 & sub_opc=1 & ssub_opc=2{
  330. local tmp:4 = sp;
  331. local tmp2:4 = sp;
  332. pop(tmp);
  333. pop(tmp2);
  334. push(tmp2 f* tmp);
  335. }
  336. # division (float)
  337. :divf is opcode=6 & sub_opc=1 & ssub_opc=3{
  338. local tmp:4 = sp;
  339. local tmp2:4 = sp;
  340. pop(tmp);
  341. pop(tmp2);
  342. push(tmp2 f/ tmp);
  343. }
  344. # modulo (float)
  345. :modf is opcode=6 & sub_opc=1 & ssub_opc=4{
  346. local tmp:4 = sp;
  347. local tmp2:4 = sp;
  348. pop(tmp);
  349. pop(tmp2);
  350. # primitive doesn't exist, so we do with what we can
  351. local ret:4 = fmod(tmp2, tmp);
  352. push(ret);
  353. }
  354. # 0x6 =========
  355. :jmp7_unk1 LABEL8 is opcode_ext=7 & ope3=0 & LABEL8 {
  356. call LABEL8;
  357. }
  358. :jmp7_unk2 LABEL8 is opcode_ext=7 & ope3=1 & LABEL8 {
  359. call LABEL8;
  360. }
  361. :jmp7_unk3 LABEL8 is opcode_ext=7 & ope3=2 & LABEL8 {
  362. call LABEL8;
  363. }
  364. # jump
  365. # TODO: verify first arg!
  366. :jmp ope3, LABEL8 is opcode_ext=8 & LABEL8 & ope3 {
  367. call LABEL8;
  368. }
  369. # 0x9 =========
  370. :exit iarg is opcode=9 & ( ssub_opc=0 | ssub_opc=1 ) & iarg{
  371. exit(iarg:1);
  372. }
  373. # return
  374. :ret is opcode=9 & ssub_opc=2{
  375. return[ra];
  376. }
  377. # push cached -> push last cached pushed element to stack
  378. # don't ask me, this entire ISA is cursed
  379. :push.ca is opcode=9 & ssub_opc=3{
  380. }
  381. # push copy -> push last pushed element to stack
  382. :push.c is opcode=9 & ssub_opc=5{
  383. }
  384. # sinus; arg in radians
  385. :sin is opcode=9 & ssub_opc=6{
  386. local tmp:4 = sp;
  387. pop(tmp);
  388. local ret:4 = sin(tmp);
  389. push(ret);
  390. }
  391. # cosinus; arg in radians
  392. :cos is opcode=9 & ssub_opc=7{
  393. local tmp:4 = sp;
  394. pop(tmp);
  395. local ret:4 = cos(tmp);
  396. push(ret);
  397. }
  398. # degrees to radians
  399. # /!\ radians are [0-2pi] in this engine
  400. :degr is opcode=9 & ssub_opc=8{
  401. local tmp:4 = sp;
  402. pop(tmp);
  403. local ret:4 = degrees_to_radians(tmp);
  404. push(ret);
  405. }
  406. # radians to degree
  407. :radd is opcode=9 & ssub_opc=9{
  408. local tmp:4 = sp;
  409. pop(tmp);
  410. local ret:4 = radians_to_degrees(tmp);
  411. push(ret);
  412. }
  413. # 0x9 =========
  414. #:syscall opesub,ope2 is opcode_ext=0xA & opesub & ope2 {
  415. # if (opesub:4==1) goto <table1>;
  416. # <table1>
  417. # if (ope2:4==6) goto <_syscall1_6>;
  418. # # unknown args or no changes necessary
  419. # system_call(opesub:4,ope2:4);
  420. # goto <done>;
  421. # <_syscall1_6>
  422. # syscall1_6();
  423. # goto <done>;
  424. # <done>
  425. #}
  426. :syscall opesub,ope2 is opcode_ext=0xA & opesub & ope2 {
  427. system_call(opesub:4,ope2:4);
  428. }
  429. :unkB is opcode=0xB {
  430. }