1
0

opcode.inc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879
  1. // Copyright (C) 2012 Zeex
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a
  4. // copy of this software and associated documentation files (the "Software"),
  5. // to deal in the Software without restriction, including without limitation
  6. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  7. // and/or sell copies of the Software, and to permit persons to whom the
  8. // Software is furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  14. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  19. // DEALINGS IN THE SOFTWARE.
  20. #if defined OPCODE_INC
  21. #endinput
  22. #endif
  23. #define OPCODE_INC
  24. #if __Pawn >= 0x30A
  25. // Disable the recursion warning in the Russian compiler.
  26. #pragma warning push
  27. #pragma warning disable 207
  28. #pragma disablerecursion
  29. #pragma warning pop
  30. // Disable the recursion warning in the fast compiler.
  31. #pragma warning disable 238
  32. #endif
  33. #define OPCODE_MAX_INSN_NAME 15
  34. enum Opcode {
  35. OP_NONE, OP_LOAD_PRI, OP_LOAD_ALT,
  36. OP_LOAD_S_PRI, OP_LOAD_S_ALT, OP_LREF_PRI,
  37. OP_LREF_ALT, OP_LREF_S_PRI, OP_LREF_S_ALT,
  38. OP_LOAD_I, OP_LODB_I, OP_CONST_PRI,
  39. OP_CONST_ALT, OP_ADDR_PRI, OP_ADDR_ALT,
  40. OP_STOR_PRI, OP_STOR_ALT, OP_STOR_S_PRI,
  41. OP_STOR_S_ALT, OP_SREF_PRI, OP_SREF_ALT,
  42. OP_SREF_S_PRI, OP_SREF_S_ALT, OP_STOR_I,
  43. OP_STRB_I, OP_LIDX, OP_LIDX_B,
  44. OP_IDXADDR, OP_IDXADDR_B, OP_ALIGN_PRI,
  45. OP_ALIGN_ALT, OP_LCTRL, OP_SCTRL,
  46. OP_MOVE_PRI, OP_MOVE_ALT, OP_XCHG,
  47. OP_PUSH_PRI, OP_PUSH_ALT, OP_PUSH_R,
  48. OP_PUSH_C, OP_PUSH, OP_PUSH_S,
  49. OP_POP_PRI, OP_POP_ALT, OP_STACK,
  50. OP_HEAP, OP_PROC, OP_RET,
  51. OP_RETN, OP_CALL, OP_CALL_PRI,
  52. OP_JUMP, OP_JREL, OP_JZER,
  53. OP_JNZ, OP_JEQ, OP_JNEQ,
  54. OP_JLESS, OP_JLEQ, OP_JGRTR,
  55. OP_JGEQ, OP_JSLESS, OP_JSLEQ,
  56. OP_JSGRTR, OP_JSGEQ, OP_SHL,
  57. OP_SHR, OP_SSHR, OP_SHL_C_PRI,
  58. OP_SHL_C_ALT, OP_SHR_C_PRI, OP_SHR_C_ALT,
  59. OP_SMUL, OP_SDIV, OP_SDIV_ALT,
  60. OP_UMUL, OP_UDIV, OP_UDIV_ALT,
  61. OP_ADD, OP_SUB, OP_SUB_ALT,
  62. OP_AND, OP_OR, OP_XOR,
  63. OP_NOT, OP_NEG, OP_INVERT,
  64. OP_ADD_C, OP_SMUL_C, OP_ZERO_PRI,
  65. OP_ZERO_ALT, OP_ZERO, OP_ZERO_S,
  66. OP_SIGN_PRI, OP_SIGN_ALT, OP_EQ,
  67. OP_NEQ, OP_LESS, OP_LEQ,
  68. OP_GRTR, OP_GEQ, OP_SLESS,
  69. OP_SLEQ, OP_SGRTR, OP_SGEQ,
  70. OP_EQ_C_PRI, OP_EQ_C_ALT, OP_INC_PRI,
  71. OP_INC_ALT, OP_INC, OP_INC_S,
  72. OP_INC_I, OP_DEC_PRI, OP_DEC_ALT,
  73. OP_DEC, OP_DEC_S, OP_DEC_I,
  74. OP_MOVS, OP_CMPS, OP_FILL,
  75. OP_HALT, OP_BOUNDS, OP_SYSREQ_PRI,
  76. OP_SYSREQ_C, OP_FILE, OP_LINE,
  77. OP_SYMBOL, OP_SRANGE, OP_JUMP_PRI,
  78. OP_SWITCH, OP_CASETBL, OP_SWAP_PRI,
  79. OP_SWAP_ALT, OP_PUSH_ADR, OP_NOP,
  80. OP_SYSREQ_D, OP_SYMTAG, OP_BREAK,
  81. OP_LAST_
  82. };
  83. enum OpcodeInsnInfo {
  84. OpcodeInsnInfo_name[OPCODE_MAX_INSN_NAME],
  85. OpcodeInsnInfo_num_opers,
  86. bool:OpcodeInsnInfo_needs_reloc
  87. }
  88. static stock const insn_table[][OpcodeInsnInfo] = {
  89. { "none", 0, false },
  90. { "load.pri", 1, false },
  91. { "load.alt", 1, false },
  92. { "load.s.pri", 1, false },
  93. { "load.s.alt", 1, false },
  94. { "lref.pri", 1, false },
  95. { "lref.alt", 1, false },
  96. { "lref.s.pri", 1, false },
  97. { "lref.s.alt", 1, false },
  98. { "load.i", 0, false },
  99. { "lodb.i", 1, false },
  100. { "const.pri", 1, false },
  101. { "const.alt", 1, false },
  102. { "addr.pri", 1, false },
  103. { "addr.alt", 1, false },
  104. { "stor.pri", 1, false },
  105. { "stor.alt", 1, false },
  106. { "stor.s.pri", 1, false },
  107. { "stor.s.alt", 1, false },
  108. { "sref.pri", 1, false },
  109. { "sref.alt", 1, false },
  110. { "sref.s.pri", 1, false },
  111. { "sref.s.alt", 1, false },
  112. { "stor.i", 0, false },
  113. { "strb.i", 1, false },
  114. { "lidx", 0, false },
  115. { "lidx.b", 1, false },
  116. { "idxaddr", 0, false },
  117. { "idxaddr.b", 1, false },
  118. { "align.pri", 1, false },
  119. { "align.alt", 1, false },
  120. { "lctrl", 1, false },
  121. { "sctrl", 1, false },
  122. { "move.pri", 0, false },
  123. { "move.alt", 0, false },
  124. { "xchg", 0, false },
  125. { "push.pri", 0, false },
  126. { "push.alt", 0, false },
  127. { "push.r", 1, false },
  128. { "push.c", 1, false },
  129. { "push", 1, false },
  130. { "push.s", 1, false },
  131. { "pop.pri", 0, false },
  132. { "pop.alt", 0, false },
  133. { "stack", 1, false },
  134. { "heap", 1, false },
  135. { "proc", 0, false },
  136. { "ret", 0, false },
  137. { "retn", 0, false },
  138. { "call", 1, true },
  139. { "call.pri", 0, false },
  140. { "jump", 1, true },
  141. { "jrel", 1, false },
  142. { "jzer", 1, true },
  143. { "jnz", 1, true },
  144. { "jeq", 1, true },
  145. { "jneq", 1, true },
  146. { "jless", 1, true },
  147. { "jleq", 1, true },
  148. { "jgrtr", 1, true },
  149. { "jgeq", 1, true },
  150. { "jsless", 1, true },
  151. { "jsleq", 1, true },
  152. { "jsgrtr", 1, true },
  153. { "jsgeq", 1, true },
  154. { "shl", 0, false },
  155. { "shr", 0, false },
  156. { "sshr", 0, false },
  157. { "shl.c.pri", 1, false },
  158. { "shl.c.alt", 1, false },
  159. { "shr.c.pri", 1, false },
  160. { "shr.c.alt", 1, false },
  161. { "smul", 0, false },
  162. { "sdiv", 0, false },
  163. { "sdiv.alt", 0, false },
  164. { "umul", 0, false },
  165. { "udiv", 0, false },
  166. { "udiv.alt", 0, false },
  167. { "add", 0, false },
  168. { "sub", 0, false },
  169. { "sub.alt", 0, false },
  170. { "and", 0, false },
  171. { "or", 0, false },
  172. { "xort", 0, false },
  173. { "not", 0, false },
  174. { "neg", 0, false },
  175. { "invert", 0, false },
  176. { "add.c", 1, false },
  177. { "smul.c", 1, false },
  178. { "zero.pri", 0, false },
  179. { "zero.alt", 0, false },
  180. { "zero", 1, false },
  181. { "zero.s", 1, false },
  182. { "sign.pri", 0, false },
  183. { "sign.alt", 0, false },
  184. { "eq", 0, false },
  185. { "neq", 0, false },
  186. { "less", 0, false },
  187. { "leq", 0, false },
  188. { "grtr", 0, false },
  189. { "geq", 0, false },
  190. { "sless", 0, false },
  191. { "sleq", 0, false },
  192. { "sgrtr", 0, false },
  193. { "sgeq", 0, false },
  194. { "eq.c.pri", 1, false },
  195. { "eq.c.alt", 1, false },
  196. { "inc.pri", 0, false },
  197. { "inc.alt", 0, false },
  198. { "inc", 1, false },
  199. { "inc.s", 1, false },
  200. { "inc.i", 0, false },
  201. { "dec.pri", 0, false },
  202. { "dec.alt", 0, false },
  203. { "dec", 1, false },
  204. { "dec.s", 1, false },
  205. { "dec.i", 0, false },
  206. { "movs", 1, false },
  207. { "cmps", 1, false },
  208. { "fill", 1, false },
  209. { "halt", 1, false },
  210. { "bounds", 1, false },
  211. { "sysreq.pri", 1, false },
  212. { "sysreq.c", 1, false },
  213. { "file", -1, false }, // obsolete
  214. { "line", -1, false }, // obsolete
  215. { "symbol", -1, false }, // obsolete
  216. { "srange", -1, false }, // obsolete
  217. { "jump.pri", 0, false },
  218. { "switch", 1, true },
  219. { "casetbl", -1, true },
  220. { "swap.pri", 0, false },
  221. { "swap.alt", 0, false },
  222. { "push.adr", 1, false },
  223. { "nop", 0, false },
  224. { "sysreq.d", 1, false },
  225. { "symtag", 1, false }, // obsolete
  226. { "break", 0, false }
  227. };
  228. const NUM_OPCODES = _:OP_LAST_;
  229. static stock Opcode:ReadOpcodeNearThis(offset = 0) {
  230. new ret_addr;
  231. // Get return address + COD - DAT + offset.
  232. #emit load.s.alt 4
  233. #emit lctrl 0
  234. #emit add
  235. #emit move.alt
  236. #emit lctrl 1
  237. #emit xchg
  238. #emit sub
  239. #emit load.s.alt offset
  240. #emit add
  241. #emit stor.s.pri ret_addr
  242. #emit lref.s.pri ret_addr
  243. #emit stack 4
  244. #emit retn
  245. return OP_NONE; // make compiler happy
  246. }
  247. static stock bool:HaveToRelocateOpcodes() {
  248. return ReadOpcodeNearThis(-8) != OP_CALL;
  249. }
  250. // Based on this idea: http://forum.sa-mp.com/showthread.php?t=358084
  251. stock Opcode:RelocateOpcodeNow(Opcode:opcode) {
  252. if (!HaveToRelocateOpcodes()) {
  253. return opcode;
  254. }
  255. switch (opcode) {
  256. case OP_LOAD_PRI: {
  257. return ReadOpcodeNearThis(4);
  258. #emit load.pri 0
  259. }
  260. case OP_LOAD_ALT: {
  261. return ReadOpcodeNearThis(4);
  262. #emit load.alt 0
  263. }
  264. case OP_LOAD_S_PRI: {
  265. return ReadOpcodeNearThis(4);
  266. #emit load.s.pri 0
  267. }
  268. case OP_LOAD_S_ALT: {
  269. return ReadOpcodeNearThis(4);
  270. #emit load.s.alt 0
  271. }
  272. case OP_LREF_PRI: {
  273. return ReadOpcodeNearThis(4);
  274. #emit lref.pri 0
  275. }
  276. case OP_LREF_ALT: {
  277. return ReadOpcodeNearThis(4);
  278. #emit lref.alt 0
  279. }
  280. case OP_LREF_S_PRI: {
  281. return ReadOpcodeNearThis(4);
  282. #emit lref.s.pri 0
  283. }
  284. case OP_LREF_S_ALT: {
  285. return ReadOpcodeNearThis(4);
  286. #emit lref.s.alt 0
  287. }
  288. case OP_LOAD_I: {
  289. return ReadOpcodeNearThis(4);
  290. #emit load.i
  291. }
  292. case OP_LODB_I: {
  293. return ReadOpcodeNearThis(4);
  294. #emit lodb.i 1
  295. }
  296. case OP_CONST_PRI: {
  297. return ReadOpcodeNearThis(4);
  298. #emit const.pri 0
  299. }
  300. case OP_CONST_ALT: {
  301. return ReadOpcodeNearThis(4);
  302. #emit const.alt 0
  303. }
  304. case OP_ADDR_PRI: {
  305. return ReadOpcodeNearThis(4);
  306. #emit addr.pri 0
  307. }
  308. case OP_ADDR_ALT: {
  309. return ReadOpcodeNearThis(4);
  310. #emit addr.alt 0
  311. }
  312. case OP_STOR_PRI: {
  313. return ReadOpcodeNearThis(4);
  314. #emit stor.pri 0
  315. }
  316. case OP_STOR_ALT: {
  317. return ReadOpcodeNearThis(4);
  318. #emit stor.alt 0
  319. }
  320. case OP_STOR_S_PRI: {
  321. return ReadOpcodeNearThis(4);
  322. #emit stor.s.pri 0
  323. }
  324. case OP_STOR_S_ALT: {
  325. return ReadOpcodeNearThis(4);
  326. #emit stor.s.alt 0
  327. }
  328. case OP_SREF_PRI: {
  329. return ReadOpcodeNearThis(4);
  330. #emit sref.pri 0
  331. }
  332. case OP_SREF_ALT: {
  333. return ReadOpcodeNearThis(4);
  334. #emit sref.alt 0
  335. }
  336. case OP_SREF_S_PRI: {
  337. return ReadOpcodeNearThis(4);
  338. #emit sref.s.pri 0
  339. }
  340. case OP_SREF_S_ALT: {
  341. return ReadOpcodeNearThis(4);
  342. #emit sref.s.alt 0
  343. }
  344. case OP_STOR_I: {
  345. return ReadOpcodeNearThis(4);
  346. #emit stor.i
  347. }
  348. case OP_STRB_I: {
  349. return ReadOpcodeNearThis(4);
  350. #emit strb.i 1
  351. }
  352. case OP_LIDX: {
  353. return ReadOpcodeNearThis(4);
  354. #emit lidx
  355. }
  356. case OP_LIDX_B: {
  357. return ReadOpcodeNearThis(4);
  358. #emit lidx.b 0
  359. }
  360. case OP_IDXADDR: {
  361. return ReadOpcodeNearThis(4);
  362. #emit idxaddr
  363. }
  364. case OP_IDXADDR_B: {
  365. return ReadOpcodeNearThis(4);
  366. #emit idxaddr.b 0
  367. }
  368. case OP_ALIGN_PRI: {
  369. return ReadOpcodeNearThis(4);
  370. #emit align.pri 0
  371. }
  372. case OP_ALIGN_ALT: {
  373. return ReadOpcodeNearThis(4);
  374. #emit align.alt 0
  375. }
  376. case OP_LCTRL: {
  377. return ReadOpcodeNearThis(4);
  378. #emit lctrl 0
  379. }
  380. case OP_SCTRL: {
  381. return ReadOpcodeNearThis(4);
  382. #emit sctrl 0
  383. }
  384. case OP_MOVE_PRI: {
  385. return ReadOpcodeNearThis(4);
  386. #emit move.pri
  387. }
  388. case OP_MOVE_ALT: {
  389. return ReadOpcodeNearThis(4);
  390. #emit move.alt
  391. }
  392. case OP_XCHG: {
  393. return ReadOpcodeNearThis(4);
  394. #emit xchg
  395. }
  396. case OP_PUSH_PRI: {
  397. return ReadOpcodeNearThis(4);
  398. #emit push.pri
  399. }
  400. case OP_PUSH_ALT: {
  401. return ReadOpcodeNearThis(4);
  402. #emit push.alt
  403. }
  404. case OP_PUSH_C: {
  405. return ReadOpcodeNearThis(4);
  406. #emit push.c 0
  407. }
  408. case OP_PUSH: {
  409. return ReadOpcodeNearThis(4);
  410. #emit push 0
  411. }
  412. case OP_PUSH_S: {
  413. return ReadOpcodeNearThis(4);
  414. #emit push.s 0
  415. }
  416. case OP_POP_PRI: {
  417. return ReadOpcodeNearThis(4);
  418. #emit pop.pri
  419. }
  420. case OP_POP_ALT: {
  421. return ReadOpcodeNearThis(4);
  422. #emit pop.alt
  423. }
  424. case OP_STACK: {
  425. return ReadOpcodeNearThis(4);
  426. #emit stack 0
  427. }
  428. case OP_HEAP: {
  429. return ReadOpcodeNearThis(4);
  430. #emit heap 0
  431. }
  432. case OP_PROC: {
  433. return ReadOpcodeNearThis(4);
  434. #emit proc
  435. }
  436. case OP_RET: {
  437. return ReadOpcodeNearThis(4);
  438. #emit ret
  439. }
  440. case OP_RETN: {
  441. return ReadOpcodeNearThis(4);
  442. #emit retn
  443. }
  444. case OP_CALL: {
  445. // We can't do just "#emit call 0" - this will crash compiler for some reason (bug?).
  446. return ReadOpcodeNearThis(-8);
  447. }
  448. case OP_JUMP: {
  449. return ReadOpcodeNearThis(4);
  450. #emit jump 0
  451. }
  452. case OP_JZER: {
  453. return ReadOpcodeNearThis(4);
  454. #emit jzer 0
  455. }
  456. case OP_JNZ: {
  457. return ReadOpcodeNearThis(4);
  458. #emit jnz 0
  459. }
  460. case OP_JEQ: {
  461. return ReadOpcodeNearThis(4);
  462. #emit jeq 0
  463. }
  464. case OP_JNEQ: {
  465. return ReadOpcodeNearThis(4);
  466. #emit jneq 0
  467. }
  468. case OP_JLESS: {
  469. return ReadOpcodeNearThis(4);
  470. #emit jless 0
  471. }
  472. case OP_JLEQ: {
  473. return ReadOpcodeNearThis(4);
  474. #emit jleq 0
  475. }
  476. case OP_JGRTR: {
  477. return ReadOpcodeNearThis(4);
  478. #emit jgrtr 0
  479. }
  480. case OP_JGEQ: {
  481. return ReadOpcodeNearThis(4);
  482. #emit jgeq 0
  483. }
  484. case OP_JSLESS: {
  485. return ReadOpcodeNearThis(4);
  486. #emit jsless 0
  487. }
  488. case OP_JSLEQ: {
  489. return ReadOpcodeNearThis(4);
  490. #emit jsleq 0
  491. }
  492. case OP_JSGRTR: {
  493. return ReadOpcodeNearThis(4);
  494. #emit jsgrtr 0
  495. }
  496. case OP_JSGEQ: {
  497. return ReadOpcodeNearThis(4);
  498. #emit jsgeq 0
  499. }
  500. case OP_SHL: {
  501. return ReadOpcodeNearThis(4);
  502. #emit shl
  503. }
  504. case OP_SHR: {
  505. return ReadOpcodeNearThis(4);
  506. #emit shr
  507. }
  508. case OP_SSHR: {
  509. return ReadOpcodeNearThis(4);
  510. #emit sshr
  511. }
  512. case OP_SHL_C_PRI: {
  513. return ReadOpcodeNearThis(4);
  514. #emit shl.c.pri 0
  515. }
  516. case OP_SHL_C_ALT: {
  517. return ReadOpcodeNearThis(4);
  518. #emit shl.c.alt 0
  519. }
  520. case OP_SHR_C_PRI: {
  521. return ReadOpcodeNearThis(4);
  522. #emit shr.c.pri 0
  523. }
  524. case OP_SHR_C_ALT: {
  525. return ReadOpcodeNearThis(4);
  526. #emit shr.c.alt 0
  527. }
  528. case OP_SMUL: {
  529. return ReadOpcodeNearThis(4);
  530. #emit smul
  531. }
  532. case OP_SDIV: {
  533. return ReadOpcodeNearThis(4);
  534. #emit sdiv
  535. }
  536. case OP_SDIV_ALT: {
  537. return ReadOpcodeNearThis(4);
  538. #emit sdiv.alt
  539. }
  540. case OP_UMUL: {
  541. return ReadOpcodeNearThis(4);
  542. #emit umul
  543. }
  544. case OP_UDIV: {
  545. return ReadOpcodeNearThis(4);
  546. #emit udiv
  547. }
  548. case OP_UDIV_ALT: {
  549. return ReadOpcodeNearThis(4);
  550. #emit udiv.alt
  551. }
  552. case OP_ADD: {
  553. return ReadOpcodeNearThis(4);
  554. #emit add
  555. }
  556. case OP_SUB: {
  557. return ReadOpcodeNearThis(4);
  558. #emit sub
  559. }
  560. case OP_SUB_ALT: {
  561. return ReadOpcodeNearThis(4);
  562. #emit sub.alt
  563. }
  564. case OP_AND: {
  565. return ReadOpcodeNearThis(4);
  566. #emit and
  567. }
  568. case OP_OR: {
  569. return ReadOpcodeNearThis(4);
  570. #emit or
  571. }
  572. case OP_XOR: {
  573. return ReadOpcodeNearThis(4);
  574. #emit xor
  575. }
  576. case OP_NOT: {
  577. return ReadOpcodeNearThis(4);
  578. #emit not
  579. }
  580. case OP_NEG: {
  581. return ReadOpcodeNearThis(4);
  582. #emit neg
  583. }
  584. case OP_INVERT: {
  585. return ReadOpcodeNearThis(4);
  586. #emit invert
  587. }
  588. case OP_ADD_C: {
  589. return ReadOpcodeNearThis(4);
  590. #emit add.c 0
  591. }
  592. case OP_SMUL_C: {
  593. return ReadOpcodeNearThis(4);
  594. #emit smul.c 0
  595. }
  596. case OP_ZERO_PRI: {
  597. return ReadOpcodeNearThis(4);
  598. #emit zero.pri
  599. }
  600. case OP_ZERO_ALT: {
  601. return ReadOpcodeNearThis(4);
  602. #emit zero.alt
  603. }
  604. case OP_ZERO: {
  605. return ReadOpcodeNearThis(4);
  606. #emit zero 0
  607. }
  608. case OP_ZERO_S: {
  609. return ReadOpcodeNearThis(4);
  610. #emit zero.s 0
  611. }
  612. case OP_SIGN_PRI: {
  613. return ReadOpcodeNearThis(4);
  614. #emit sign.pri
  615. }
  616. case OP_SIGN_ALT: {
  617. return ReadOpcodeNearThis(4);
  618. #emit sign.alt
  619. }
  620. case OP_EQ: {
  621. return ReadOpcodeNearThis(4);
  622. #emit eq
  623. }
  624. case OP_NEQ: {
  625. return ReadOpcodeNearThis(4);
  626. #emit neq
  627. }
  628. case OP_LESS: {
  629. return ReadOpcodeNearThis(4);
  630. #emit less
  631. }
  632. case OP_LEQ: {
  633. return ReadOpcodeNearThis(4);
  634. #emit leq
  635. }
  636. case OP_GRTR: {
  637. return ReadOpcodeNearThis(4);
  638. #emit grtr
  639. }
  640. case OP_GEQ: {
  641. return ReadOpcodeNearThis(4);
  642. #emit geq
  643. }
  644. case OP_SLESS: {
  645. return ReadOpcodeNearThis(4);
  646. #emit sless
  647. }
  648. case OP_SLEQ: {
  649. return ReadOpcodeNearThis(4);
  650. #emit sleq
  651. }
  652. case OP_SGRTR: {
  653. return ReadOpcodeNearThis(4);
  654. #emit sgrtr
  655. }
  656. case OP_SGEQ: {
  657. return ReadOpcodeNearThis(4);
  658. #emit sgeq
  659. }
  660. case OP_EQ_C_PRI: {
  661. return ReadOpcodeNearThis(4);
  662. #emit eq.c.pri 0
  663. }
  664. case OP_EQ_C_ALT: {
  665. return ReadOpcodeNearThis(4);
  666. #emit eq.c.alt 0
  667. }
  668. case OP_INC_PRI: {
  669. return ReadOpcodeNearThis(4);
  670. #emit inc.pri
  671. }
  672. case OP_INC_ALT: {
  673. return ReadOpcodeNearThis(4);
  674. #emit inc.alt
  675. }
  676. case OP_INC: {
  677. return ReadOpcodeNearThis(4);
  678. #emit inc 0
  679. }
  680. case OP_INC_S: {
  681. return ReadOpcodeNearThis(4);
  682. #emit inc.s 0
  683. }
  684. case OP_INC_I: {
  685. return ReadOpcodeNearThis(4);
  686. #emit inc.i
  687. }
  688. case OP_DEC_PRI: {
  689. return ReadOpcodeNearThis(4);
  690. #emit dec.pri
  691. }
  692. case OP_DEC_ALT: {
  693. return ReadOpcodeNearThis(4);
  694. #emit dec.alt
  695. }
  696. case OP_DEC: {
  697. return ReadOpcodeNearThis(4);
  698. #emit dec 0
  699. }
  700. case OP_DEC_S: {
  701. return ReadOpcodeNearThis(4);
  702. #emit dec.s 0
  703. }
  704. case OP_DEC_I: {
  705. return ReadOpcodeNearThis(4);
  706. #emit dec.i
  707. }
  708. case OP_MOVS: {
  709. return ReadOpcodeNearThis(4);
  710. #emit movs 0
  711. }
  712. case OP_CMPS: {
  713. return ReadOpcodeNearThis(4);
  714. #emit cmps 0
  715. }
  716. case OP_FILL: {
  717. return ReadOpcodeNearThis(4);
  718. #emit fill 0
  719. }
  720. case OP_HALT: {
  721. return ReadOpcodeNearThis(4);
  722. #emit halt 0
  723. }
  724. case OP_BOUNDS: {
  725. return ReadOpcodeNearThis(4);
  726. #emit bounds 0
  727. }
  728. case OP_SYSREQ_C: {
  729. return ReadOpcodeNearThis(4);
  730. #emit sysreq.c 0
  731. }
  732. case OP_SWITCH: {
  733. static T = 1;
  734. #if debug > 0
  735. if (T) return ReadOpcodeNearThis(12);
  736. #else
  737. if (T) return ReadOpcodeNearThis(8);
  738. #endif
  739. switch (0) {
  740. case 0: {}
  741. }
  742. }
  743. case OP_CASETBL: {
  744. new x = 0;
  745. switch (x) { case 0: return ReadOpcodeNearThis(20); }
  746. }
  747. case OP_SWAP_PRI: {
  748. return ReadOpcodeNearThis(4);
  749. #emit swap.pri
  750. }
  751. case OP_SWAP_ALT: {
  752. return ReadOpcodeNearThis(4);
  753. #emit swap.alt
  754. }
  755. case OP_PUSH_ADR: {
  756. return ReadOpcodeNearThis(4);
  757. #emit push.adr 0
  758. }
  759. case OP_NOP: {
  760. return ReadOpcodeNearThis(4);
  761. #emit nop
  762. }
  763. case OP_SYSREQ_D: {
  764. // Since there's no way to #emit sysreq.d we have to compute its
  765. // address using a relative offset to another opcode, e.g. nop.
  766. new bool:is_crashdetect;
  767. #emit zero.pri
  768. #emit lctrl 0xFF
  769. #emit stor.s.pri is_crashdetect
  770. if (is_crashdetect) {
  771. // The offset is different when running under crashdetect as
  772. // it uses its own (modified) version of the VM. This value
  773. // value works only with crashdetect 4.13.
  774. return RelocateOpcodeNow(OP_NOP) - Opcode:0x1EA;
  775. } else {
  776. return RelocateOpcodeNow(OP_NOP) - Opcode:0x4F;
  777. }
  778. }
  779. case OP_BREAK: {
  780. return ReadOpcodeNearThis(4);
  781. #emit break
  782. }
  783. }
  784. return opcode;
  785. }
  786. static stock Opcode:opcode_table[NUM_OPCODES];
  787. static stock bool:opcode_table_is_ready = false;
  788. stock bool:IsOpcodeValid(Opcode:opcode) {
  789. return (OP_NONE <= opcode < Opcode:NUM_OPCODES);
  790. }
  791. static stock InitOpcodeTable() {
  792. for (new i = 0; i < NUM_OPCODES; i++) {
  793. opcode_table[i] = RelocateOpcodeNow(Opcode:i);
  794. }
  795. opcode_table_is_ready = true;
  796. }
  797. stock Opcode:RelocateOpcode(Opcode:opcode) {
  798. if (!opcode_table_is_ready) {
  799. InitOpcodeTable();
  800. }
  801. return opcode_table[_:opcode];
  802. }
  803. stock Opcode:UnrelocateOpcode(Opcode:opcode) {
  804. if (!opcode_table_is_ready) {
  805. InitOpcodeTable();
  806. }
  807. if (OP_NONE <= opcode < Opcode:NUM_OPCODES) {
  808. return opcode;
  809. }
  810. for (new i = 0; i < NUM_OPCODES; i++) {
  811. if (opcode_table[i] == opcode) {
  812. return Opcode:i;
  813. }
  814. }
  815. return opcode;
  816. }
  817. stock GetOpcodeInstructionInformation(Opcode:opcode) {
  818. if (OP_NONE < opcode < Opcode:NUM_OPCODES) {
  819. return insn_table[_:opcode];
  820. }
  821. return insn_table[0];
  822. }
  823. stock GetOpcodeInstructionName(Opcode:opcode) {
  824. static const ret[OPCODE_MAX_INSN_NAME] = "none";
  825. if (OP_NONE < opcode < Opcode:NUM_OPCODES) {
  826. // This doesn't work.
  827. //return insn_table[_:opcode][OpcodeInsnInfo_name];
  828. // Fake it without requiring `strcpy`.
  829. #emit CONST.alt insn_table
  830. #emit LOAD.S.pri opcode
  831. #emit IDXADDR
  832. #emit MOVE.alt
  833. #emit LOAD.I
  834. #emit ADD
  835. #emit LOAD.S.alt 16
  836. #emit MOVS 60 // 15 * 4
  837. #emit RETN
  838. // Check that the code is correct for the size of "OPCODE_MAX_INSN_NAME".
  839. #assert OPCODE_MAX_INSN_NAME == 15
  840. }
  841. return ret;
  842. }
  843. stock GetOpcodeInstructionParameters(Opcode:opcode) {
  844. if (OP_NONE < opcode < Opcode:NUM_OPCODES) {
  845. return insn_table[_:opcode][OpcodeInsnInfo_num_opers];
  846. }
  847. return 0;
  848. }
  849. stock bool:GetOpcodeInstructionRelocatable(Opcode:opcode) {
  850. if (OP_NONE < opcode < Opcode:NUM_OPCODES) {
  851. return insn_table[_:opcode][OpcodeInsnInfo_needs_reloc];
  852. }
  853. return false;
  854. }