gcsx_bytecode.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  1. /* GCSx
  2. ** BYTECODE.CPP
  3. **
  4. ** Bytecode-related utilities/datatypes/structures
  5. */
  6. /*****************************************************************************
  7. ** Copyright (C) 2003-2006 Janson
  8. **
  9. ** This program is free software; you can redistribute it and/or modify
  10. ** it under the terms of the GNU General Public License as published by
  11. ** the Free Software Foundation; either version 2 of the License, or
  12. ** (at your option) any later version.
  13. **
  14. ** This program is distributed in the hope that it will be useful,
  15. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. ** GNU General Public License for more details.
  18. **
  19. ** You should have received a copy of the GNU General Public License
  20. ** along with this program; if not, write to the Free Software
  21. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
  22. *****************************************************************************/
  23. #include "all.h"
  24. string dataTypeToWart(const DataType& dt) { start_func
  25. string result = string(1, dt.baseType + 'C');
  26. result += 'A' + dt.flags;
  27. if (((dt.baseType == DATA_ENTITY) || (dt.baseType == DATA_OBJECT)) && (dt.subType))
  28. result = result + formatString("%X", dt.subType);
  29. return result;
  30. }
  31. const char* wartToDataType(const char* wart, DataType& result) { start_func
  32. assert(wart);
  33. int base = *wart++ - 'C';
  34. if ((base != DATA_VOID) && (base != DATA_VAR) && (base != DATA_INT) &&
  35. (base != DATA_FLOAT) && (base != DATA_STR) && (base != DATA_ENTITY) &&
  36. (base != DATA_OBJECT))
  37. return NULL;
  38. result.baseType = base;
  39. int flags = *wart++ - 'A';
  40. if ((flags != 0) && (flags != DATA_ARRAY) && (flags != DATA_HASH) &&
  41. (flags != DATA_CONST))
  42. return NULL;
  43. result.flags = flags;
  44. char* endptr;
  45. result.subType = strtol(wart, &endptr, 16);
  46. return endptr;
  47. }
  48. void destroyLabelMap(LabelMap* map) { start_func
  49. if (map) {
  50. // We clear one at a time to ensure we can delete hash keys at the right times
  51. LabelMap::iterator pos = map->begin();
  52. while (pos != map->end()) {
  53. const char* toDel = (*pos).first;
  54. map->erase(pos);
  55. delete[] toDel;
  56. pos = map->begin();
  57. }
  58. }
  59. }
  60. list<Label>& addLabelMap(LabelMap* map, const string& name) { start_func
  61. const char* cName = name.c_str();
  62. // (create new element with new name allocation?)
  63. if (map->find(cName) == map->end()) cName = newCpCopy(name);
  64. // Find or create new element
  65. return (*map)[cName];
  66. }
  67. void destroyFunctionMap(FunctionMap* map) { start_func
  68. if (map) {
  69. // We clear one at a time to ensure we can delete hash keys at the right times
  70. FunctionMap::iterator pos = map->begin();
  71. while (pos != map->end()) {
  72. const char* toDel = (*pos).first;
  73. delete[] (*pos).second.parameters;
  74. map->erase(pos);
  75. delete[] toDel;
  76. pos = map->begin();
  77. }
  78. }
  79. }
  80. Function& addFunctionMap(FunctionMap* map, const string& name) { start_func
  81. const char* cName = name.c_str();
  82. // (create new element with new name allocation?)
  83. if (map->find(cName) == map->end()) cName = newCpCopy(name);
  84. // Find or create new element
  85. return (*map)[cName];
  86. }
  87. void destroyVariableMap(VariableMap* map) { start_func
  88. if (map) {
  89. // We clear one at a time to ensure we can delete hash keys at the right times
  90. VariableMap::iterator pos = map->begin();
  91. while (pos != map->end()) {
  92. const char* toDel = (*pos).first;
  93. for (list<Variable>::iterator pos2 = (*pos).second.begin(); pos2 != (*pos).second.end(); ++pos2) {
  94. if (((*pos2).datatype.baseType == DATA_STR) &&
  95. ((*pos2).datatype.flags == DATA_CONST))
  96. delete[] (*pos2).val.constS;
  97. }
  98. map->erase(pos);
  99. delete[] toDel;
  100. pos = map->begin();
  101. }
  102. }
  103. }
  104. list<Variable>& addVariableMap(VariableMap* map, const string& name, const char*& storeName) { start_func
  105. const char* cName = name.c_str();
  106. VariableMap::iterator found = map->find(cName);
  107. // (create new element with new name allocation?)
  108. if (found == map->end()) {
  109. storeName = cName = newCpCopy(name);
  110. return (*map)[cName];
  111. }
  112. // Existing element and name allocation
  113. else {
  114. storeName = (*found).first;
  115. return (*found).second;
  116. }
  117. }
  118. #ifdef COMPILEASSERT
  119. void checkOpcode(Opcode opc, Uint8 mode1, Uint8 mode2, Uint8 mode3) { start_func
  120. // Basic checks
  121. bytecodeAssert((opc >= 0) && (opc < OP_LAST));
  122. // More detailed checks- validate mode combinations are legal
  123. Uint8 modes[3] = { mode1, mode2, mode3 };
  124. for (int pos = 0; pos < 3; ++pos) {
  125. Uint8 check = modes[pos];
  126. Uint8 basetype = check & OM_BASETYPE;
  127. // Reserved (unallocated) types or non-allowed literal types
  128. if (OM_IS_LITERAL(check)) {
  129. bytecodeAssert(basetype != OM_STR);
  130. bytecodeAssert(basetype != OM_ARRAY);
  131. bytecodeAssert(basetype != OM_HASH);
  132. bytecodeAssert((basetype <= OM_THIS) || (basetype == OM_POINTER));
  133. }
  134. else {
  135. bytecodeAssert(basetype < OM_RESERVED_1);
  136. }
  137. // Cannot use OM_INDIRECT with entry, array, hash, local, global (or const, see below)
  138. if (OM_IS_INDIRECT(check)) {
  139. bytecodeAssert(basetype != OM_ENTRY);
  140. bytecodeAssert(basetype != OM_ARRAY);
  141. bytecodeAssert(basetype != OM_HASH);
  142. bytecodeAssert(!OM_IS_LOCAL(check));
  143. bytecodeAssert(!OM_IS_GLOBAL(check));
  144. }
  145. // Cannot use OM_POP with entry, non-const, or convert
  146. if (OM_IS_POP(check)) {
  147. bytecodeAssert(basetype != OM_ENTRY);
  148. bytecodeAssert(basetype != OM_STR);
  149. bytecodeAssert(OM_IS_COPY(check) || OM_IS_KNOWN(check) || OM_IS_INDIRECT(check));
  150. }
  151. // CONST str must be copy, not convert
  152. // Regular str must be convert, not copy
  153. if (basetype == OM_STR) {
  154. bytecodeAssert(!OM_IS_COPY(check));
  155. }
  156. else if (basetype == OM_STR_CONST && !OM_IS_LITERAL(check)) {
  157. bytecodeAssert(OM_IS_COPY(check) || OM_IS_KNOWN(check) || OM_IS_INDIRECT(check));
  158. }
  159. }
  160. // @TODO: redo bytecode checks below using newer #defines
  161. /*
  162. // Most detailed of checks- validate mode combination for specific opcode
  163. int numP = 1;
  164. int goalTemplate = 0;
  165. int goalConst1 = 0;
  166. int goalConst2 = 0;
  167. int goalType;
  168. switch (opc) {
  169. case OP_NOOP:
  170. case OP_INIT:
  171. case OP_LOGAND:
  172. case OP_LOGOR:
  173. case OP_NOT:
  174. case OP_PRECALL:
  175. case OP_STOP:
  176. case OP_WAIT: {
  177. // No parameters
  178. bytecodeAssert(mode1 == OM_NONE);
  179. break;
  180. }
  181. case OP_DEBUG: // @TODO: debug changed use; replace with something else
  182. case OP_RET: {
  183. bytecodeAssert(mode1 == OM_INT);
  184. bytecodeAssert(mode2 == OM_INT);
  185. numP = 2;
  186. break;
  187. }
  188. case OP_CALL: {
  189. bytecodeAssert(mode1 == OM_CFUNCTION);
  190. break;
  191. }
  192. case OP_FORCEARRAY:
  193. case OP_FORCEHASH: {
  194. bytecodeAssert(mode1 == OM_STACK);
  195. bytecodeAssert(mode2 == OM_INT);
  196. numP = 2;
  197. break;
  198. }
  199. case OP_ITOF:
  200. case OP_ITOS:
  201. case OP_FTOI:
  202. case OP_FTOS:
  203. case OP_STOI:
  204. case OP_STOF:
  205. case OP_FORCEFLOAT:
  206. case OP_FORCEINT:
  207. case OP_FORCESTRING: {
  208. bytecodeAssert(mode1 == OM_STACK);
  209. break;
  210. }
  211. case OP_IFFALSE:
  212. case OP_IFTRUE: {
  213. // 1) [Pop]/[Stack]/[Local]/[Ptr](#)
  214. // 2) [Offset]
  215. bytecodeAssert((mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK)) ||
  216. ((mode1 & OM_POP) == OM_POP));
  217. bytecodeAssert((mode1 & OM_BASETYPE) == OM_INT);
  218. bytecodeAssert(mode2 == OM_OFFSET);
  219. numP = 2;
  220. break;
  221. }
  222. case OP_IFFALSEf:
  223. case OP_IFTRUEf: {
  224. // 1) [Pop]/[Stack]/[Local]/[Ptr](%)
  225. // 2) [Offset]
  226. bytecodeAssert((mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK)) ||
  227. ((mode1 & OM_POP) == OM_POP));
  228. bytecodeAssert((mode1 & OM_BASETYPE) == OM_FLOAT);
  229. bytecodeAssert(mode2 == OM_OFFSET);
  230. numP = 2;
  231. break;
  232. }
  233. case OP_JUMP: {
  234. bytecodeAssert(mode1 == OM_OFFSET);
  235. break;
  236. }
  237. case OP_CREATEARRAY:
  238. case OP_CREATEHASH:
  239. case OP_REPLY: {
  240. bytecodeAssert(mode1 == OM_INT);
  241. break;
  242. }
  243. case OP_SUBR: {
  244. bytecodeAssert((mode1 == OM_OFFSET) ||
  245. (mode1 == OM_FUNCTION));
  246. break;
  247. }
  248. case OP_SWAP: {
  249. bytecodeAssert(mode1 == OM_STACK);
  250. bytecodeAssert(mode2 == OM_STACK);
  251. numP = 2;
  252. break;
  253. }
  254. case OP_TYPEOF:
  255. case OP_COPY:
  256. case OP_PUSHv:
  257. case OP_POPv: {
  258. bytecodeAssert((mode1 == OM_STACK) ||
  259. (mode1 == OM_LOCAL) ||
  260. (mode1 == OM_GLOBAL));
  261. break;
  262. }
  263. case OP_DISCARD:
  264. case OP_DISCARDL: {
  265. // [Pop]/[Stack]/[Local]/[Ptr](#) or [Int]
  266. bytecodeAssert((mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK)) ||
  267. ((mode1 & OM_POP) == OM_POP) ||
  268. (mode1 == OM_INT));
  269. bytecodeAssert((mode1 & OM_BASETYPE) == OM_INT);
  270. break;
  271. }
  272. case OP_ARRAY:
  273. case OP_POPARRAY: {
  274. // 1) [Stack]/[Local]/[Ptr](a)
  275. // 2) [Pop]/[Stack]/[Local]/[Ptr](#) or [Int]
  276. bytecodeAssert(mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK));
  277. bytecodeAssert(mode1 & OM_ARRAY);
  278. bytecodeAssert((mode1 & OM_POP) != OM_POP);
  279. bytecodeAssert((mode2 & (OM_LOCAL | OM_GLOBAL | OM_STACK)) ||
  280. ((mode2 & OM_POP) == OM_POP) ||
  281. (mode2 == OM_INT));
  282. bytecodeAssert((mode2 & OM_BASETYPE) == OM_INT);
  283. numP = 2;
  284. break;
  285. }
  286. case OP_HASH:
  287. case OP_POPHASH: {
  288. // 1) [Stack]/[Local]/[Ptr](h)
  289. // 2) [Pop]/[Stack]/[Local]/[Ptr](c$) or [String]
  290. bytecodeAssert(mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK));
  291. bytecodeAssert(mode1 & OM_HASH);
  292. bytecodeAssert((mode1 & OM_POP) != OM_POP);
  293. bytecodeAssert((mode2 & (OM_LOCAL | OM_GLOBAL | OM_STACK)) ||
  294. ((mode2 & OM_POP) == OM_POP) ||
  295. (mode2 == OM_STR));
  296. bytecodeAssert((mode2 & OM_BASETYPE) == OM_STR);
  297. goalConst2 = 1;
  298. numP = 2;
  299. break;
  300. }
  301. case OP_CONCAT: {
  302. // 1) [Stack]/[Local]/[Ptr]($)
  303. // 2) [Pop]/[Stack]/[Local]/[Ptr](c$) or [String]
  304. bytecodeAssert(mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK));
  305. bytecodeAssert((mode1 & OM_BASETYPE) == OM_STR);
  306. bytecodeAssert(!(mode1 & OM_CONST));
  307. bytecodeAssert((mode2 & (OM_LOCAL | OM_GLOBAL | OM_STACK)) ||
  308. ((mode2 & OM_POP) == OM_POP) ||
  309. (mode2 == OM_STR));
  310. bytecodeAssert((mode2 & OM_BASETYPE) == OM_STR);
  311. goalConst2 = 1;
  312. numP = 2;
  313. break;
  314. }
  315. case OP_QUERY:
  316. case OP_SEND: {
  317. // 1) [Stack]/[Local]/[Ptr](#)
  318. // 2) [Pop]/[Stack]/[Local]/[Ptr](c$) or [String]
  319. // 3) [Int]
  320. bytecodeAssert(mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK));
  321. bytecodeAssert((mode1 & OM_BASETYPE) == OM_INT);
  322. bytecodeAssert((mode2 & (OM_LOCAL | OM_GLOBAL | OM_STACK)) ||
  323. ((mode2 & OM_POP) == OM_POP) ||
  324. (mode2 == OM_STR));
  325. bytecodeAssert((mode2 & OM_BASETYPE) == OM_STR);
  326. bytecodeAssert(mode3 == OM_INT);
  327. goalConst2 = 1;
  328. numP = 3;
  329. break;
  330. }
  331. case OP_QUERYs:
  332. case OP_SENDs: {
  333. // 1) [Pop]/[Stack]/[Local]/[Ptr](c$) or [String]
  334. // 2) [Pop]/[Stack]/[Local]/[Ptr](c$) or [String]
  335. // 3) [Int]
  336. bytecodeAssert((mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK)) ||
  337. ((mode1 & OM_POP) == OM_POP) ||
  338. (mode1 == OM_STR));
  339. bytecodeAssert((mode1 & OM_BASETYPE) == OM_STR);
  340. bytecodeAssert((mode2 & (OM_LOCAL | OM_GLOBAL | OM_STACK)) ||
  341. ((mode2 & OM_POP) == OM_POP) ||
  342. (mode2 == OM_STR));
  343. bytecodeAssert((mode2 & OM_BASETYPE) == OM_STR);
  344. bytecodeAssert(mode3 == OM_INT);
  345. goalConst1 = 1;
  346. goalConst2 = 1;
  347. numP = 3;
  348. break;
  349. }
  350. case OP_SUBRs: {
  351. // 1) [Stack]/[Local]/[Ptr]($)
  352. // 2) [Int]
  353. bytecodeAssert(mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK));
  354. bytecodeAssert((mode1 & OM_BASETYPE) == OM_STR);
  355. bytecodeAssert(!(mode1 & OM_CONST));
  356. bytecodeAssert(mode2 == OM_INT);
  357. numP = 2;
  358. break;
  359. }
  360. case OP_STORE: {
  361. // 1) [Stack]/[Local]/[Ptr](#)
  362. // 2) [Stack]/[Local]/[Ptr](#) or [Int]
  363. bytecodeAssert(mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK));
  364. bytecodeAssert((mode1 & OM_BASETYPE) == OM_INT);
  365. bytecodeAssert((mode2 & (OM_LOCAL | OM_GLOBAL | OM_STACK)) ||
  366. (mode2 == OM_INT));
  367. bytecodeAssert((mode2 & OM_BASETYPE) == OM_INT);
  368. numP = 2;
  369. break;
  370. }
  371. case OP_STOREf: {
  372. // 1) [Stack]/[Local]/[Ptr](%)
  373. // 2) [Stack]/[Local]/[Ptr](%) or [Float]
  374. bytecodeAssert(mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK));
  375. bytecodeAssert((mode1 & OM_BASETYPE) == OM_FLOAT);
  376. bytecodeAssert((mode2 & (OM_LOCAL | OM_GLOBAL | OM_STACK)) ||
  377. (mode2 == OM_FLOAT));
  378. bytecodeAssert((mode2 & OM_BASETYPE) == OM_FLOAT);
  379. numP = 2;
  380. break;
  381. }
  382. case OP_STOREs: {
  383. // 1) [Stack]/[Local]/[Ptr]($)
  384. // 2) [Stack]/[Local]/[Ptr](c$) or [String]
  385. bytecodeAssert(mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK));
  386. bytecodeAssert((mode1 & OM_BASETYPE) == OM_STR);
  387. bytecodeAssert(!(mode1 & OM_CONST));
  388. bytecodeAssert((mode2 & (OM_LOCAL | OM_GLOBAL | OM_STACK)) ||
  389. (mode2 == OM_STR));
  390. bytecodeAssert((mode2 & OM_BASETYPE) == OM_STR);
  391. goalConst2 = 1;
  392. numP = 2;
  393. break;
  394. }
  395. case OP_STOREa: {
  396. // 1) [Stack]/[Local]/[Ptr](a)
  397. // 2) [Stack]/[Local]/[Ptr](a)
  398. bytecodeAssert(mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK));
  399. bytecodeAssert(mode1 & OM_ARRAY);
  400. bytecodeAssert((mode1 & OM_POP) != OM_POP);
  401. bytecodeAssert(mode2 & (OM_LOCAL | OM_GLOBAL | OM_STACK));
  402. bytecodeAssert(mode2 & OM_ARRAY);
  403. bytecodeAssert((mode2 & OM_POP) != OM_POP);
  404. numP = 2;
  405. break;
  406. }
  407. case OP_STOREh: {
  408. // 1) [Stack]/[Local]/[Ptr](h)
  409. // 2) [Stack]/[Local]/[Ptr](h)
  410. bytecodeAssert(mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK));
  411. bytecodeAssert(mode1 & OM_HASH);
  412. bytecodeAssert((mode1 & OM_POP) != OM_POP);
  413. bytecodeAssert(mode2 & (OM_LOCAL | OM_GLOBAL | OM_STACK));
  414. bytecodeAssert(mode2 & OM_HASH);
  415. bytecodeAssert((mode2 & OM_POP) != OM_POP);
  416. numP = 2;
  417. break;
  418. }
  419. case OP_NEG:
  420. case OP_POP: {
  421. // [Stack]/[Local]/[Ptr](#)
  422. goalType = OM_INT;
  423. goalTemplate = 4;
  424. break;
  425. }
  426. case OP_NEGf:
  427. case OP_POPf: {
  428. // [Stack]/[Local]/[Ptr](%)
  429. goalType = OM_FLOAT;
  430. goalTemplate = 4;
  431. break;
  432. }
  433. case OP_POPs: {
  434. // [Stack]/[Local]/[Ptr]($)
  435. bytecodeAssert(!(mode1 & OM_CONST));
  436. goalType = OM_STR;
  437. goalTemplate = 4;
  438. break;
  439. }
  440. case OP_PUSH: {
  441. // [Stack]/[Local]/[Ptr](#) or [Int]
  442. goalType = OM_INT;
  443. goalTemplate = 3;
  444. break;
  445. }
  446. case OP_PUSHf: {
  447. // [Stack]/[Local]/[Ptr](%) or [Float]
  448. goalType = OM_FLOAT;
  449. goalTemplate = 3;
  450. break;
  451. }
  452. case OP_PUSHs: {
  453. // [Stack]/[Local]/[Ptr](c$) or [String]
  454. goalType = OM_STR;
  455. goalTemplate = 3;
  456. goalConst1 = 1;
  457. break;
  458. }
  459. case OP_POPa:
  460. case OP_PUSHa: {
  461. // [Stack]/[Local]/[Ptr](a)
  462. bytecodeAssert(mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK));
  463. bytecodeAssert(mode1 & OM_ARRAY);
  464. bytecodeAssert((mode1 & OM_POP) != OM_POP);
  465. break;
  466. }
  467. case OP_POPh:
  468. case OP_PUSHh: {
  469. // [Stack]/[Local]/[Ptr](h)
  470. bytecodeAssert(mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK));
  471. bytecodeAssert(mode1 & OM_HASH);
  472. bytecodeAssert((mode1 & OM_POP) != OM_POP);
  473. break;
  474. }
  475. case OP_ADD:
  476. case OP_AND:
  477. case OP_DIV:
  478. case OP_MOD:
  479. case OP_MULT:
  480. case OP_OR:
  481. case OP_SHIFTL:
  482. case OP_SHIFTR:
  483. case OP_SUB:
  484. case OP_XOR: {
  485. // 1) [Stack]/[Local]/[Ptr](#)
  486. // 2) [Pop]/[Stack]/[Local]/[Ptr](#) or [Int]
  487. goalType = OM_INT;
  488. goalTemplate = 1;
  489. break;
  490. }
  491. case OP_EQ:
  492. case OP_GE:
  493. case OP_GT:
  494. case OP_LE:
  495. case OP_LT:
  496. case OP_NE: {
  497. // 1) [Pop]/[Stack]/[Local]/[Ptr](#)
  498. // 2) [Pop]/[Stack]/[Local]/[Ptr](#) or [Int]
  499. goalType = OM_INT;
  500. goalTemplate = 2;
  501. break;
  502. }
  503. case OP_ADDf:
  504. case OP_DIVf:
  505. case OP_MULTf:
  506. case OP_SUBf: {
  507. // 1) [Stack]/[Local]/[Ptr](%)
  508. // 2) [Pop]/[Stack]/[Local]/[Ptr](%) or [Float]
  509. goalType = OM_FLOAT;
  510. goalTemplate = 1;
  511. break;
  512. }
  513. case OP_EQf:
  514. case OP_GEf:
  515. case OP_GTf:
  516. case OP_LEf:
  517. case OP_LTf:
  518. case OP_NEf: {
  519. // 1) [Pop]/[Stack]/[Local]/[Ptr](%)
  520. // 2) [Pop]/[Stack]/[Local]/[Ptr](%) or [Float]
  521. goalType = OM_FLOAT;
  522. goalTemplate = 2;
  523. break;
  524. }
  525. case OP_EQs:
  526. case OP_GEs:
  527. case OP_GTs:
  528. case OP_LEs:
  529. case OP_LTs:
  530. case OP_NEs: {
  531. // 1) [Pop]/[Stack]/[Local]/[Ptr](c$)
  532. // 2) [Pop]/[Stack]/[Local]/[Ptr](c$) or [String]
  533. goalType = OM_STR;
  534. goalTemplate = 2;
  535. goalConst1 = 1;
  536. goalConst2 = 1;
  537. break;
  538. }
  539. // To prevent warning
  540. case OP_LAST:
  541. bytecodeAssert(0);
  542. break;
  543. }
  544. // Some standardized templates
  545. switch (goalTemplate) {
  546. case 1:
  547. case 2: {
  548. // gT1)
  549. // p1) [Stack]/[Local]/[Ptr](type)
  550. // p2) [Pop]/[Stack]/[Local]/[Ptr](type) or [type]
  551. // gT2) same but p1) can be [Pop]
  552. if (goalTemplate == 1)
  553. bytecodeAssert(mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK));
  554. else
  555. bytecodeAssert((mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK)) ||
  556. ((mode1 & OM_POP) == OM_POP));
  557. bytecodeAssert((mode1 & OM_BASETYPE) == goalType);
  558. bytecodeAssert((mode2 & (OM_LOCAL | OM_GLOBAL | OM_STACK)) ||
  559. ((mode2 & OM_POP) == OM_POP) ||
  560. (mode2 == (mode2 & OM_BASETYPE)));
  561. bytecodeAssert((mode2 & OM_BASETYPE) == goalType);
  562. numP = 2;
  563. break;
  564. }
  565. case 3: {
  566. // [Stack]/[Local]/[Ptr](type) or [type]
  567. bytecodeAssert((mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK)) ||
  568. (mode1 == (mode1 & OM_BASETYPE)));
  569. bytecodeAssert((mode1 & OM_BASETYPE) == goalType);
  570. break;
  571. }
  572. case 4: {
  573. // [Stack]/[Local]/[Ptr](type)
  574. bytecodeAssert(mode1 & (OM_LOCAL | OM_GLOBAL | OM_STACK));
  575. bytecodeAssert((mode1 & OM_BASETYPE) == goalType);
  576. break;
  577. }
  578. }
  579. if (goalConst1)
  580. bytecodeAssert((mode1 == OM_STR) || (mode1 & OM_CONST));
  581. if (goalConst2)
  582. bytecodeAssert((mode2 == OM_STR) || (mode2 & OM_CONST));
  583. if (numP < 3) bytecodeAssert(mode3 == OM_NONE);
  584. if (numP < 2) bytecodeAssert(mode2 == OM_NONE);
  585. */
  586. }
  587. #endif
  588. const char* opcodeNames[] = {
  589. "NOOP ",
  590. "ADD ",
  591. "ADDf ",
  592. "AND ",
  593. "CONCAT ",
  594. "CONVERT ",
  595. "CREATEa ",
  596. "CREATEe ",
  597. "CREATEh ",
  598. "CREATEo ",
  599. "DEBUG ",
  600. "DISCARD ",
  601. "DISCARDL",
  602. "DIV ",
  603. "DIVf ",
  604. "EQ ",
  605. "EQf ",
  606. "EQo ",
  607. "EQs ",
  608. "GE ",
  609. "GEf ",
  610. "GEs ",
  611. "GT ",
  612. "GTf ",
  613. "GTs ",
  614. "IFFALSE ",
  615. "IFFALSEa",
  616. "IFFALSEf",
  617. "IFFALSEh",
  618. "IFFALSEo",
  619. "IFFALSEs",
  620. "IFFALSEv",
  621. "IFTRUE ",
  622. "IFTRUEa ",
  623. "IFTRUEf ",
  624. "IFTRUEh ",
  625. "IFTRUEo ",
  626. "IFTRUEs ",
  627. "IFTRUEv ",
  628. "INIT ",
  629. "JUMP ",
  630. "LE ",
  631. "LEf ",
  632. "LEs ",
  633. "LT ",
  634. "LTf ",
  635. "LTs ",
  636. "MOD ",
  637. "MULT ",
  638. "MULTf ",
  639. "NE ",
  640. "NEf ",
  641. "NEo ",
  642. "NEs ",
  643. "OR ",
  644. "PUSH ",
  645. "PUSHa ",
  646. "PUSHf ",
  647. "PUSHh ",
  648. "PUSHo ",
  649. "PUSHs ",
  650. "PUSHv ",
  651. "RET ",
  652. "SHIFTL ",
  653. "SHIFTR ",
  654. "STOP ",
  655. "STORE ",
  656. "STOREa ",
  657. "STOREf ",
  658. "STOREh ",
  659. "STOREo ",
  660. "STOREs ",
  661. "STOREv ",
  662. "SUB ",
  663. "SUBf ",
  664. "SUBR ",
  665. "XOR ",
  666. "GETe ",
  667. "SETe ",
  668. "GETo ",
  669. "SETo ",
  670. "IDLE ",
  671. "RETVOID ",
  672. "SETef ",
  673. "SETei ",
  674. "SETof ",
  675. "SEToi ",
  676. };
  677. typedef map<int, const LinkEntry*> LinkMap;
  678. LinkMap* linkMap = NULL;
  679. int linkPos = 0;
  680. void decompileBytecode(const Uint32* bytecode, const list<LinkEntry>* links) { start_func
  681. assert(bytecode);
  682. assert(links);
  683. Uint32 size = *bytecode++;
  684. Uint32 strOffset = *bytecode++;
  685. Uint32 pos = 0;
  686. debugWrite("Code: %d dw; Strings: %d dw; Links: %d", strOffset, size - strOffset, links->size());
  687. // Turn links into a map by position
  688. linkMap = new LinkMap;
  689. list<LinkEntry>::const_iterator end = links->end();
  690. for (list<LinkEntry>::const_iterator pos = links->begin(); pos != end; ++pos) {
  691. (*linkMap)[(*pos).offset] = &(*pos);
  692. }
  693. while (pos < strOffset) {
  694. string line = formatString("%04X ", pos);
  695. linkPos = pos;
  696. int sz = debugBytecode(line, bytecode);
  697. pos += sz;
  698. bytecode += sz;
  699. debugWrite("%s", line.c_str());
  700. }
  701. delete linkMap;
  702. linkMap = NULL;
  703. // Display strings
  704. while (pos < size) {
  705. debugWrite("%04X %s", pos, (const char*)bytecode);
  706. int sz = strlen((const char*)bytecode) / 4 + 1;
  707. pos += sz;
  708. bytecode += sz;
  709. }
  710. }
  711. int debugBytecode(string& line, const Uint32* bytecode) { start_func
  712. int used = 1;
  713. // Opcode
  714. Uint32 opcode = *bytecode++;
  715. line += opcodeNames[opcode & 0xFF];
  716. // Operands
  717. for (int o = 0; o < 3; ++o) {
  718. opcode >>= 8;
  719. Uint8 addrmode = opcode & 0xFF;
  720. if (addrmode) {
  721. // All operand modes pull a single 32bit operand out of bytecode except-
  722. // pop or 'none/all/this/all_other'- pull nothing
  723. // obj_entity+subtype- pulls an extra 32bit for subtype FIRST
  724. // literal/global pointer- pulls pointer size (may be 32bit or 64bit etc)
  725. // literal float- pulls float size (may be 32bit or more)
  726. if (OM_IS_POINTER(addrmode)) {
  727. void* operand = *(void**)(bytecode);
  728. bytecode += vPtrSize;
  729. used += vPtrSize;
  730. line += " [Ptr]";
  731. // (only show address if actually linked)
  732. if (operand) line += formatString("<%p>", operand);
  733. if (linkMap) ;// @TODO: display function from links
  734. }
  735. else {
  736. line += " ";
  737. // (copy OR convert in {})
  738. if (!OM_IS_LITERAL(addrmode) && OM_IS_CONVERT(addrmode)) line += "{";
  739. switch (addrmode & OM_BASETYPE) {
  740. case OM_ENTRY: line += "*"; break;
  741. case OM_INT: line += "#"; break;
  742. case OM_FLOAT: line += "%"; break;
  743. case OM_STR: line += "$"; break;
  744. case OM_STR_CONST: line += "c$"; break;
  745. case OM_ARRAY: line += "A"; break;
  746. case OM_HASH: line += "H"; break;
  747. case OM_ENTITY:
  748. if (!OM_IS_LITERAL(addrmode)) line += "e@";
  749. break;
  750. case OM_OBJECT:
  751. if (!OM_IS_LITERAL(addrmode)) line += "@";
  752. break;
  753. default:
  754. break;
  755. };
  756. // Subtype modes (any non literal object/entity conversion/copy, all, all_other)
  757. // @TODO: will also need 2 subtypes on array/hash conversion/copy
  758. if ((((addrmode & OM_BASETYPE) == OM_ENTITY || (addrmode & OM_BASETYPE) == OM_OBJECT) &&
  759. (addrmode & OM_FLAGS) != OM_NO_CONVERT && (addrmode & OM_FLAGS) != OM_INDIRECT &&
  760. (addrmode & OM_BASETYPE) != addrmode)
  761. || addrmode == OM_ALL || addrmode == OM_ALL_OTHER) {
  762. int subtype = *bytecode++;
  763. ++used;
  764. if (subtype) {
  765. line += "'";
  766. // @TODO: actual script or type name
  767. line += intToStr(subtype);
  768. line += "'";
  769. }
  770. }
  771. if (OM_IS_INDIRECT(addrmode)) line += "<-";
  772. else if (OM_IS_COPY(addrmode)) line += "}";
  773. else if (!OM_IS_LITERAL(addrmode) && OM_IS_CONVERT(addrmode)) line += "/Conv}";
  774. if (OM_IS_GLOBAL(addrmode)) line += "[G]";
  775. else if (OM_IS_LOCAL(addrmode)) line += "[L]";
  776. else if (OM_IS_STACK(addrmode)) line += "[S]";
  777. else if (OM_IS_POP(addrmode)) line += "[Pop]";
  778. // (else literal)
  779. if (!OM_IS_POP(addrmode)) {
  780. if (OM_IS_LITERAL(addrmode)) {
  781. switch (addrmode & OM_BASETYPE) {
  782. case OM_INT:
  783. line += intToStr(*bytecode++);
  784. ++used;
  785. break;
  786. case OM_FLOAT: {
  787. BCfloat operand = *(BCfloat*)(bytecode);
  788. bytecode += bcFloatSize;
  789. used += bcFloatSize;
  790. line += formatString("%"BC_FLOAT_PRINTF, operand);
  791. break;
  792. }
  793. case OM_STR_CONST: {
  794. int showString = *bytecode;
  795. line += intToStr(showString);
  796. ++used;
  797. // (show actual string)
  798. line += "\"";
  799. line += (const char*)(bytecode + showString);
  800. line += "\"";
  801. ++bytecode;
  802. break;
  803. }
  804. case OM_ALL:
  805. line += "ALL";
  806. break;
  807. case OM_ALL_OTHER:
  808. line += "ALL_OTHER";
  809. break;
  810. case OM_NOTHING:
  811. line += "NOTHING";
  812. break;
  813. case OM_THIS:
  814. line += "THIS";
  815. break;
  816. default:
  817. break;
  818. };
  819. }
  820. else if (OM_IS_GLOBAL(addrmode)) {
  821. void* operand = *(void**)(bytecode);
  822. bytecode += vPtrSize;
  823. used += vPtrSize;
  824. // (only show address if actually linked)
  825. if (operand) line += formatString("<%p>", operand);
  826. if (linkMap) {
  827. LinkMap::iterator found = linkMap->find(linkPos + used);
  828. if (found != linkMap->end()) line += (*found).second->name.c_str();
  829. }
  830. }
  831. else {
  832. line += intToStr(*bytecode++);
  833. ++used;
  834. }
  835. }
  836. }
  837. }
  838. }
  839. return used;
  840. }