gcsx_entity.cpp 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142
  1. /* GCSx
  2. ** ENTITY.CPP
  3. **
  4. ** Entity support (instance of a script) (no edit-specific version)
  5. ** Includes bytecode interpreter
  6. */
  7. /*****************************************************************************
  8. ** Copyright (C) 2003-2006 Janson
  9. **
  10. ** This program is free software; you can redistribute it and/or modify
  11. ** it under the terms of the GNU General Public License as published by
  12. ** the Free Software Foundation; either version 2 of the License, or
  13. ** (at your option) any later version.
  14. **
  15. ** This program is distributed in the hope that it will be useful,
  16. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. ** GNU General Public License for more details.
  19. **
  20. ** You should have received a copy of the GNU General Public License
  21. ** along with this program; if not, write to the Free Software
  22. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
  23. *****************************************************************************/
  24. #include "all.h"
  25. // @TODO: respect ref
  26. Entity::Entity(int myId) { start_func
  27. id = myId;
  28. script = NULL;
  29. active = 0;
  30. scriptLocked = 0;
  31. scriptType = 0;
  32. ref = 0;
  33. runStatus = RUN_UNINIT;
  34. i = NULL;
  35. endOfLocals = 0;
  36. createStack(&stack);
  37. varTable[PROP_NAME].p = new string;
  38. varTable[PROP_SPRITE].p = NULL;
  39. varTable[PROP_PRIORITY].i = DEFAULT_PRIORITY;
  40. }
  41. Entity::~Entity() { start_func
  42. // @TODO: assert ref=0?
  43. wipeStack();
  44. destroyStack(&stack);
  45. setScript(NULL);
  46. // @TODO: this is only safe if we ensure to destroy entities before sprites
  47. setSprite(NULL);
  48. delete (string*)varTable[PROP_NAME].p;
  49. }
  50. void Entity::setSprite(Sprite* newSprite) { start_func
  51. if (varTable[PROP_SPRITE].p) --(((ObjectBase*)varTable[PROP_SPRITE].p)->ref);
  52. varTable[PROP_SPRITE].p = (ObjectBase*)newSprite;
  53. if (newSprite) ++newSprite->ref;
  54. }
  55. void Entity::setScript(Script* newScript) { start_func
  56. if ((script) && (scriptLocked))
  57. script->markUnlock();
  58. wipeStack();
  59. i = NULL;
  60. runStatus = RUN_UNINIT;
  61. scriptLocked = 0;
  62. script = newScript;
  63. if (script) scriptType = newScript->getId();
  64. if ((script) && (active))
  65. activateResource();
  66. }
  67. void Entity::activateResource() { start_func
  68. if ((script) && (!scriptLocked)) {
  69. assert(!i);
  70. assert((runStatus == RUN_UNINIT) || (runStatus == RUN_STOPPED));
  71. // @TODO: throw_File
  72. script->markLock();
  73. script->link();
  74. scriptLocked = 1;
  75. if (runStatus == RUN_UNINIT) {
  76. i = script->getCode();
  77. runStatus = RUN_INIT;
  78. }
  79. }
  80. }
  81. void Entity::deactivateResource() { start_func
  82. if ((script) && (scriptLocked) && (!i)) {
  83. assert((runStatus == RUN_UNINIT) || (runStatus == RUN_STOPPED));
  84. script->markUnlock();
  85. scriptLocked = 0;
  86. }
  87. }
  88. void Entity::setActive() { start_func
  89. if (!active) {
  90. activateResource();
  91. active = 1;
  92. }
  93. }
  94. void Entity::setInactive() { start_func
  95. if (active) {
  96. deactivateResource();
  97. active = 0;
  98. }
  99. }
  100. /*
  101. ** BYTECODE INTERPRETER follows
  102. **
  103. ** All functions except main loop can be considered throw_Interpret,
  104. ** therefore follow dynamic allocations CAREFULLY.
  105. */
  106. // @TODO: consolidate duplicate opcode/etc functions as much as possible
  107. // once mostly debugged and otherwise optimized (reduce space = optimize cache)
  108. //
  109. // State data- interpreter runs outside class to prevent passing 'this'
  110. // and allow simple function tables; all tables and data together.
  111. //
  112. static Uint32 opdata = 0;
  113. static Uint8 addrmode = 0;
  114. static Uint32* i_p = NULL;
  115. // A note on stack usage- an opcode should not push onto the stack until it's
  116. // done with it's operands, as we sometimes reference "popped" data directly
  117. // at it's original, technically-invalid position
  118. static Stack stackP;
  119. static Entity* entity = NULL;
  120. static StackEntry* operand = NULL;
  121. static StackEntry* operandGrab = NULL;
  122. static StackEntry* operandWrite = NULL;
  123. static Sint32 operandDataI = 0;
  124. static BCfloat operandDataF = 0;
  125. static const char* operandDataS = NULL;
  126. static void* operandDataP = NULL;
  127. // 'toDeref' should always contain anything needing dereferencing
  128. #define MAX_TODEREF 8
  129. // (room for at least 2 derefs per operand)
  130. static StackEntry toDeref[MAX_TODEREF];
  131. static StackEntry* toDerefPos = toDeref;
  132. static StackEntry* toDerefLast = toDeref + MAX_TODEREF;
  133. // Two-element array (flip-flops) to store temporary operands that
  134. // DON'T need dereferencing (int, float)
  135. static StackEntry tempOperand[2];
  136. static int tempPos = 0;
  137. // Pre-created 'empty' int/float/entity/object operands
  138. static StackEntry emptyOperand[4];
  139. typedef void (*OperandFunc)();
  140. typedef void (*OperandFuncDeref)(StackEntry*);
  141. // Operand function sequence- (/ means 'or')
  142. // opcodes[]
  143. // ->grabbers[] -> extractors[] / copiers[] -> extractors[]
  144. // ->grabbersStore[] -> converters[]
  145. // ->grabbersWrite[]
  146. // ->grabbersUse[] -> copiersUse[] / converters[]
  147. // Anyone can call dereferencers[] or referencers[] as needed
  148. // Anyone can call copiersUse[] with _UNDEF for existing type to create blank entries
  149. // Function tables-
  150. // Dereferencing table- Indexed via 8 bits of existing datatype
  151. // Referencing- only intended to support basic types
  152. // May clobber operand IF you call on a RETURN type
  153. static OperandFuncDeref dereferencers[STACK_TYPE_COUNT];
  154. static OperandFuncDeref referencers[STACK_TYPE_COUNT];
  155. // Copy/conversion tables- Indexed via 4 bits of desired datatype concatenated with 4 bits of existing datatype
  156. // copiersUse[] ensures the copy is a usable, properly ref counted StackEntry and does NOT put in "toderef"
  157. // copiersUse[] with _UNDEF existing is gauranteed to just make a blank entry, so can be
  158. // used for creating empties.; copiersUse[] expects it's result to be stored via assignment
  159. // copiers[] calls extractors immediately after or instead.
  160. static OperandFunc converters[256]; // into operand
  161. static OperandFunc copiers[256]; // into operandData* (clobbers operandGrab/2)
  162. static OperandFunc copiersUse[256]; // into operand
  163. // Extractor table- indexed by 8 bit operand; don't call if called copiers[]
  164. // @TODO: create specialized types for all grabbers[] that use extractors and
  165. // remove this array? (some functions are still needed for copiers[] array)
  166. static OperandFunc extractors[256]; // into operandData* (from operandGrab)
  167. // Decoder (grabber) table- indexed by 8 bit operand- grabs const into operandData*
  168. static OperandFunc grabbers[256]; // into operandData* (clobbers operandGrab/2)
  169. // Grabs non-const, pointer in operand ready to store/modify directly
  170. // Write "destroys" AND DEREFS original contents without conversion! and
  171. // also does not garauntee that the 'type' field is correct.
  172. static OperandFunc grabbersStore[256]; // into operand
  173. static OperandFunc grabbersWrite[256]; // into operandWrite
  174. // Grabs into a ready-to-use StackEntry in operand (proper ref counting and all)
  175. static OperandFunc grabbersUse[256]; // into operand
  176. // Opcode table
  177. static OperandFunc opcodes[OP_LAST];
  178. #ifdef INTERPRETASSERT
  179. static void interpretError() { start_func
  180. interpretAssert(0);
  181. }
  182. static void interpretErrorDeref(StackEntry*) { start_func
  183. interpretAssert(0);
  184. }
  185. #else
  186. #define interpretError NULL
  187. #define interpretErrorDeref NULL
  188. #endif
  189. static void doNothing() { start_func
  190. }
  191. //
  192. // dereferencers[]
  193. //
  194. // Dereferencing/destruction (the seDeref* functions already assert)
  195. static void derefNothing(StackEntry* s) { start_func
  196. }
  197. static void derefString(StackEntry* s) { start_func
  198. seDerefString(s);
  199. }
  200. static void derefArray(StackEntry* s) { start_func
  201. seDerefArray(s);
  202. }
  203. static void derefHash(StackEntry* s) { start_func
  204. seDerefHash(s);
  205. }
  206. static void derefEntity(StackEntry* s) { start_func
  207. Entity::seDerefEntity(s);
  208. }
  209. static void derefObject(StackEntry* s) { start_func
  210. seDerefObject(s);
  211. }
  212. static void derefReturn(StackEntry* s) { start_func
  213. interpretAssert(s->type == STACK_RETURNPTR);
  214. StackEntry* target = (StackEntry*)(s->data.p);
  215. if (target) {
  216. interpretAssert(target->type & STACK_REPLYPTR);
  217. interpretAssert((target->type | ~STACK_REPLYPTR) <= STACK_BASETYPE);
  218. // Generate empty of requested type
  219. // Assumes STACK_UNDEF is 0 otherwise we should have | STACK_UNDEF here
  220. interpretAssert(STACK_UNDEF == 0);
  221. copiersUse[(target->type | ~STACK_REPLYPTR) << 4]();
  222. *target = *operand;
  223. }
  224. }
  225. static void derefReply(StackEntry* s) { start_func
  226. interpretAssert(s->type == STACK_REPLYPTR);
  227. StackEntry* target = (StackEntry*)(s->data.p);
  228. interpretAssert(target);
  229. interpretAssert(target->type == STACK_RETURNPTR);
  230. target->data.p = NULL;
  231. }
  232. //
  233. // referencers[]
  234. //
  235. static void refNothing(StackEntry* s) { start_func
  236. }
  237. static void refString(StackEntry* s) { start_func
  238. s->data.p = new string(*(string*)s->data.p);
  239. }
  240. static void refArray(StackEntry* s) { start_func
  241. interpretAssert(s->type == STACK_ARRAY);
  242. refIncArray((Array*)s->data.p);
  243. }
  244. static void refHash(StackEntry* s) { start_func
  245. interpretAssert(s->type == STACK_HASH);
  246. refIncHash((Hash*)s->data.p);
  247. }
  248. static void refEntity(StackEntry* s) { start_func
  249. Entity::seRefEntity(s);
  250. }
  251. static void refObject(StackEntry* s) { start_func
  252. interpretAssert(s->type == STACK_OBJECT);
  253. if (s->data.p) ++(((ObjectBase*)s->data.p)->ref);
  254. }
  255. //
  256. // converters[]
  257. //
  258. // Converting- dereferences old operand, replaces with new in-place
  259. static void convertEmptyToInt() { start_func
  260. interpretAssert(operand->type != STACK_RETURNPTR);
  261. // (always deref, as it's not float/int at this point)
  262. dereferencers[operand->type](operand);
  263. operand->type = STACK_INT;
  264. operand->data.i = 0;
  265. }
  266. static void convertEmptyToFloat() { start_func
  267. interpretAssert(operand->type != STACK_RETURNPTR);
  268. dereferencers[operand->type](operand);
  269. operand->type = STACK_FLOAT;
  270. operand->data.f = 0.0;
  271. }
  272. static void convertEmptyToStr() { start_func
  273. interpretAssert(operand->type != STACK_RETURNPTR);
  274. dereferencers[operand->type](operand);
  275. operand->type = STACK_STRING;
  276. operand->data.p = new string(blankString);
  277. }
  278. static void convertEmptyToArray() { start_func
  279. interpretAssert(operand->type != STACK_RETURNPTR);
  280. dereferencers[operand->type](operand);
  281. // @TODO:
  282. }
  283. static void convertEmptyToHash() { start_func
  284. interpretAssert(operand->type != STACK_RETURNPTR);
  285. dereferencers[operand->type](operand);
  286. // @TODO:
  287. }
  288. static void convertEmptyToEntity() { start_func
  289. interpretAssert(operand->type != STACK_RETURNPTR);
  290. dereferencers[operand->type](operand);
  291. operand->type = STACK_ENTITY;
  292. operand->data.p = NULL;
  293. }
  294. static void convertEmptyToObject() { start_func
  295. interpretAssert(operand->type != STACK_RETURNPTR);
  296. dereferencers[operand->type](operand);
  297. operand->type = STACK_OBJECT;
  298. operand->data.p = NULL;
  299. }
  300. static void convertIntToFloat() { start_func
  301. operand->type = STACK_FLOAT;
  302. operand->data.f = (BCfloat)operand->data.i;
  303. }
  304. static void convertFloatToInt() { start_func
  305. operand->type = STACK_INT;
  306. operand->data.i = (Sint32)operand->data.f;
  307. }
  308. static void convertIntToString() { start_func
  309. operand->type = STACK_STRING;
  310. operand->data.p = new string(intToStr(operand->data.i));
  311. }
  312. static void convertStringToInt() { start_func
  313. operand->type = STACK_INT;
  314. string* myStr = (string*)operand->data.p;
  315. operand->data.i = strToInt(*myStr);
  316. delete myStr;
  317. }
  318. static void convertFloatToString() { start_func
  319. operand->type = STACK_STRING;
  320. operand->data.p = new string(floatToStr(operand->data.f));
  321. }
  322. static void convertStringToFloat() { start_func
  323. operand->type = STACK_FLOAT;
  324. string* myStr = (string*)operand->data.p;
  325. operand->data.f = strToFloat(*myStr);
  326. delete myStr;
  327. }
  328. //
  329. // copiers[]
  330. //
  331. // Copying- ignores old operand, replaces with new in operandData* (doesn't deref old)
  332. // New version is set up to deref for you automatically
  333. // Handles the work of extractors[] too
  334. static void copyCreateInt() { start_func
  335. operandDataI = emptyOperand[0].data.i;
  336. }
  337. static void copyCreateFloat() { start_func
  338. operandDataF = emptyOperand[1].data.f;
  339. }
  340. static void copyCreateStr() { start_func
  341. operandDataS = "";
  342. }
  343. static void copyCreateArray() { start_func
  344. // @TODO:
  345. }
  346. static void copyCreateHash() { start_func
  347. // @TODO:
  348. }
  349. static void copyCreateEntity() { start_func
  350. operandDataP = NULL;
  351. }
  352. static void copyCreateObject() { start_func
  353. operandDataP = NULL;
  354. }
  355. static void copyIntToFloat() { start_func
  356. operandDataF = (BCfloat)operandGrab->data.i;
  357. }
  358. static void copyFloatToInt() { start_func
  359. operandDataI = (Sint32)operandGrab->data.f;
  360. }
  361. static void copyIntToString() { start_func
  362. if (++toDerefPos == toDerefLast) toDerefPos = toDeref;
  363. interpretAssert(toDerefPos->type != STACK_RETURNPTR);
  364. dereferencers[toDerefPos->type](toDerefPos);
  365. // (need to set type to ensure dereferencing)
  366. toDerefPos->type = STACK_STRING;
  367. toDerefPos->data.p = new string(intToStr(toDerefPos->data.i));
  368. operandDataS = ((string*)toDerefPos->data.p)->c_str();
  369. }
  370. static void copyStringToInt() { start_func
  371. operandDataI = strToInt(*(string*)operandGrab->data.p);
  372. }
  373. static void copyFloatToString() { start_func
  374. if (++toDerefPos == toDerefLast) toDerefPos = toDeref;
  375. interpretAssert(toDerefPos->type != STACK_RETURNPTR);
  376. dereferencers[toDerefPos->type](toDerefPos);
  377. // (need to set type to ensure dereferencing)
  378. toDerefPos->type = STACK_STRING;
  379. toDerefPos->data.p = new string(floatToStr(operandGrab->data.f));
  380. operandDataS = ((string*)toDerefPos->data.p)->c_str();
  381. }
  382. static void copyStringToFloat() { start_func
  383. operandDataF = strToFloat(*(string*)operandGrab->data.p);
  384. }
  385. //
  386. // copiersUse[]
  387. //
  388. // Copying for Use- ignores old operand, replaces with new in operand (doesn't deref old)
  389. // 'Use' versions don't set new up to be deref'd either, expecting it will get stored VIA ASSIGNMENT
  390. static void copyCreateIntUse() { start_func
  391. operand = emptyOperand;
  392. }
  393. static void copyCreateFloatUse() { start_func
  394. operand = emptyOperand + 1;
  395. }
  396. static void copyCreateStrUse() { start_func
  397. operand = tempOperand + (tempPos ^= 1);
  398. operand->type = STACK_STRING;
  399. operand->data.p = new string;
  400. }
  401. static void copyCreateArrayUse() { start_func
  402. // @TODO:
  403. }
  404. static void copyCreateHashUse() { start_func
  405. // @TODO:
  406. }
  407. static void copyCreateEntityUse() { start_func
  408. operand = emptyOperand + 2;
  409. }
  410. static void copyCreateObjectUse() { start_func
  411. operand = emptyOperand + 3;
  412. }
  413. static void copyStringUse() { start_func
  414. string* prev = (string*)operand->data.p;
  415. operand = tempOperand + (tempPos ^= 1);
  416. operand->type = STACK_STRING;
  417. operand->data.p = new string(*prev);
  418. }
  419. static void copyIntToFloatUse() { start_func
  420. BCfloat result = (BCfloat)operand->data.i;
  421. operand = tempOperand + (tempPos ^= 1);
  422. operand->type = STACK_FLOAT;
  423. operand->data.f = result;
  424. }
  425. static void copyFloatToIntUse() { start_func
  426. Sint32 result = (Sint32)operand->data.f;
  427. operand = tempOperand + (tempPos ^= 1);
  428. operand->type = STACK_INT;
  429. operand->data.i = result;
  430. }
  431. static void copyIntToStringUse() { start_func
  432. Uint32 val = operand->data.i;
  433. operand = tempOperand + (tempPos ^= 1);
  434. operand->type = STACK_STRING;
  435. operand->data.p = new string(intToStr(val));
  436. }
  437. static void copyStringToIntUse() { start_func
  438. Sint32 result = strToInt(*(string*)operand->data.p);
  439. operand = tempOperand + (tempPos ^= 1);
  440. operand->type = STACK_INT;
  441. operand->data.i = result;
  442. }
  443. static void copyFloatToStringUse() { start_func
  444. BCfloat val = operand->data.f;
  445. operand = tempOperand + (tempPos ^= 1);
  446. operand->type = STACK_STRING;
  447. operand->data.p = new string(floatToStr(val));
  448. }
  449. static void copyStringToFloatUse() { start_func
  450. BCfloat result = strToFloat(*(string*)operand->data.p);
  451. operand = tempOperand + (tempPos ^= 1);
  452. operand->type = STACK_FLOAT;
  453. operand->data.f = result;
  454. }
  455. //
  456. // extractors[]
  457. //
  458. // Extracting- always goes in operandData* off of operandGrab
  459. static void extractInt() { start_func
  460. interpretAssert(operandGrab->type == STACK_INT);
  461. operandDataI = operandGrab->data.i;
  462. }
  463. static void extractFloat() { start_func
  464. interpretAssert(operandGrab->type == STACK_FLOAT);
  465. operandDataF = operandGrab->data.f;
  466. }
  467. static void extractStringConst() { start_func
  468. interpretAssert(operandGrab->type == STACK_STRING);
  469. operandDataS = ((string*)operandGrab->data.p)->c_str();
  470. }
  471. static void extractArray() { start_func
  472. interpretAssert(operandGrab->type == STACK_ARRAY);
  473. // @TODO:
  474. }
  475. static void extractHash() { start_func
  476. interpretAssert(operandGrab->type == STACK_HASH);
  477. // @TODO:
  478. }
  479. static void extractEntity() { start_func
  480. interpretAssert(operandGrab->type == STACK_ENTITY);
  481. operandDataP = operandGrab->data.p;
  482. }
  483. static void extractObject() { start_func
  484. interpretAssert(operandGrab->type == STACK_OBJECT);
  485. operandDataP = operandGrab->data.p;
  486. }
  487. //
  488. // grabbers[]
  489. //
  490. // Grabbing into operandData*, via operandGrab/2
  491. static void grabInt() { start_func
  492. operandDataI = *i_p++;
  493. }
  494. static void grabFloat() { start_func
  495. operandDataF = *((BCfloat*)i_p);
  496. i_p += bcFloatSize;
  497. }
  498. static void grabStringConst() { start_func
  499. operandDataS = (const char*)(i_p + *i_p);
  500. ++i_p;
  501. }
  502. static void grabThis() { start_func
  503. operandDataP = entity;
  504. }
  505. static void grabNothing() { start_func
  506. operandDataP = NULL;
  507. }
  508. static void grabStack() { start_func
  509. interpretAssert((stackP.top - stackP.data) - *i_p > entity->getEndOfLocals());
  510. interpretAssert(*i_p < (Uint32)(stackP.top - stackP.data));
  511. operandGrab = stackP.top - 1 - *i_p++;
  512. extractors[addrmode]();
  513. }
  514. // Int/Float optimized due to commonality (@TODO: strconst? all!?)
  515. static void grabStackInt() { start_func
  516. interpretAssert(*i_p < entity->getEndOfLocals());
  517. operandDataI = (stackP.top - 1 - *i_p++)->data.i;
  518. }
  519. static void grabStackFloat() { start_func
  520. interpretAssert(*i_p < entity->getEndOfLocals());
  521. operandDataF = (stackP.top - 1 - *i_p++)->data.f;
  522. }
  523. static void grabStackCopy() { start_func
  524. interpretAssert((stackP.top - stackP.data) - *i_p > entity->getEndOfLocals());
  525. interpretAssert(*i_p < (Uint32)(stackP.top - stackP.data));
  526. operandGrab = stackP.top - 1 - *i_p++;
  527. interpretAssert(operandGrab->type <= 0x0F);
  528. // @TODO: can optimize (once we start testing copy/convert)
  529. // if operand->type is already in the 0xF0 nibble (we don't
  530. // use operand->type anywhere else but as a dereferencers[] index!)
  531. // OR flip addrmode! (addrmode is only used with OM_* for this reason!
  532. // but may be "converted" silently to STACK_* or DATA_* somewhere- see *Write functions)
  533. copiers[((addrmode & 0x0F) << 4) | operandGrab->type]();
  534. }
  535. static void grabLocal() { start_func
  536. interpretAssert(*i_p < entity->getEndOfLocals());
  537. operandGrab = stackP.data + *i_p++;
  538. extractors[addrmode]();
  539. }
  540. // Int/Float optimized due to commonality (@TODO: strconst? all!?)
  541. static void grabLocalInt() { start_func
  542. interpretAssert(*i_p < entity->getEndOfLocals());
  543. operandDataI = (stackP.data + *i_p++)->data.i;
  544. }
  545. static void grabLocalFloat() { start_func
  546. interpretAssert(*i_p < entity->getEndOfLocals());
  547. operandDataF = (stackP.data + *i_p++)->data.f;
  548. }
  549. static void grabLocalCopy() { start_func
  550. interpretAssert(*i_p < entity->getEndOfLocals());
  551. operandGrab = stackP.data + *i_p++;
  552. interpretAssert(operandGrab->type <= 0x0F);
  553. copiers[((addrmode & 0x0F) << 4) | operandGrab->type]();
  554. }
  555. static void grabPop() { start_func
  556. interpretAssert((Uint32)(stackP.top - stackP.data) > entity->getEndOfLocals());
  557. if (++toDerefPos == toDerefLast) toDerefPos = toDeref;
  558. operandGrab = toDerefPos;
  559. interpretAssert(operandGrab->type != STACK_RETURNPTR);
  560. dereferencers[operandGrab->type](operandGrab);
  561. *operandGrab = *--stackP.top;
  562. extractors[addrmode]();
  563. }
  564. // Int/Float optimized due to commonality
  565. // @TODO: versions for other types like strconst? (do for Local/Stack versions too)
  566. static void grabPopInt() { start_func
  567. interpretAssert((Uint32)(stackP.top - stackP.data) > entity->getEndOfLocals());
  568. operandDataI = (--stackP.top)->data.i;
  569. }
  570. static void grabPopFloat() { start_func
  571. interpretAssert((Uint32)(stackP.top - stackP.data) > entity->getEndOfLocals());
  572. operandDataF = (--stackP.top)->data.f;
  573. }
  574. static void grabPopCopy() { start_func
  575. interpretAssert((Uint32)(stackP.top - stackP.data) > entity->getEndOfLocals());
  576. operandGrab = --stackP.top;
  577. interpretAssert(operandGrab->type <= 0x0F);
  578. // Instead of dereferencing immediately, we just add to the dereferencing array
  579. // so the copier has the most flexibility (to point to it still, etc.)
  580. if (++toDerefPos == toDerefLast) toDerefPos = toDeref;
  581. interpretAssert(toDerefPos->type != STACK_RETURNPTR);
  582. dereferencers[toDerefPos->type](toDerefPos);
  583. *toDerefPos = *operandGrab;
  584. copiers[((addrmode & 0x0F) << 4) | operandGrab->type]();
  585. }
  586. //
  587. // grabbersStore[]
  588. //
  589. static void grabStackStore() { start_func
  590. interpretAssert((stackP.top - stackP.data) - *i_p > entity->getEndOfLocals());
  591. interpretAssert(*i_p < (Uint32)(stackP.top - stackP.data));
  592. operand = stackP.top - 1 - *i_p++;
  593. }
  594. static void grabStackConvertStore() { start_func
  595. interpretAssert((stackP.top - stackP.data) - *i_p > entity->getEndOfLocals());
  596. interpretAssert(*i_p < (Uint32)(stackP.top - stackP.data));
  597. operand = stackP.top - 1 - *i_p++;
  598. interpretAssert(operand->type <= 0x0F);
  599. converters[((addrmode & 0x0F) << 4) | operand->type]();
  600. }
  601. static void grabLocalStore() { start_func
  602. interpretAssert(*i_p < entity->getEndOfLocals());
  603. operand = stackP.data + *i_p++;
  604. }
  605. static void grabLocalConvertStore() { start_func
  606. interpretAssert(*i_p < entity->getEndOfLocals());
  607. operand = stackP.data + *i_p++;
  608. interpretAssert(operand->type <= 0x0F);
  609. converters[((addrmode & 0x0F) << 4) | operand->type]();
  610. }
  611. //
  612. // grabbersWrite[]
  613. //
  614. static void grabStackNumWrite() { start_func
  615. interpretAssert((stackP.top - stackP.data) - *i_p > entity->getEndOfLocals());
  616. interpretAssert(*i_p < (Uint32)(stackP.top - stackP.data));
  617. operandWrite = stackP.top - 1 - *i_p++;
  618. }
  619. static void grabStackWrite() { start_func
  620. interpretAssert((stackP.top - stackP.data) - *i_p > entity->getEndOfLocals());
  621. interpretAssert(*i_p < (Uint32)(stackP.top - stackP.data));
  622. operandWrite = stackP.top - 1 - *i_p++;
  623. dereferencers[operandWrite->type](operandWrite);
  624. }
  625. static void grabLocalNumWrite() { start_func
  626. interpretAssert(*i_p < entity->getEndOfLocals());
  627. operandWrite = stackP.data + *i_p++;
  628. }
  629. static void grabLocalWrite() { start_func
  630. interpretAssert(*i_p < entity->getEndOfLocals());
  631. operandWrite = stackP.data + *i_p++;
  632. dereferencers[operandWrite->type](operandWrite);
  633. }
  634. //
  635. // grabbersUse[]
  636. //
  637. // Grabbing into StackEntry (properly referenced as it's own copy)
  638. static void grabIntUse() { start_func
  639. operand = tempOperand + (tempPos ^= 1);
  640. operand->type = STACK_INT;
  641. operand->data.i = *i_p++;
  642. }
  643. static void grabFloatUse() { start_func
  644. operand = tempOperand + (tempPos ^= 1);
  645. operand->type = STACK_INT;
  646. operand->data.f = *((BCfloat*)i_p);
  647. i_p += bcFloatSize;
  648. }
  649. static void grabStringUse() { start_func
  650. operand = tempOperand + (tempPos ^= 1);
  651. operand->type = STACK_STRING;
  652. operand->data.p = new string((const char*)(i_p + *i_p));
  653. ++i_p;
  654. }
  655. static void grabThisUse() { start_func
  656. operand = tempOperand + (tempPos ^= 1);
  657. operand->type = STACK_ENTITY;
  658. operand->data.p = entity;
  659. Entity::seRefEntity(operand);
  660. }
  661. static void grabNothingUse() { start_func
  662. operand = tempOperand + (tempPos ^= 1);
  663. // @TODO: faster to assign copy from empty operand?
  664. operand->type = STACK_ENTITY;
  665. operand->data.p = NULL;
  666. }
  667. static void grabStackUse() { start_func
  668. interpretAssert((stackP.top - stackP.data) - *i_p > entity->getEndOfLocals());
  669. interpretAssert(*i_p < (Uint32)(stackP.top - stackP.data));
  670. operand = tempOperand + (tempPos ^= 1);
  671. *operand = *(stackP.top - 1 - *i_p++);
  672. referencers[operand->type](operand);
  673. }
  674. static void grabStackNumUse() { start_func
  675. interpretAssert((stackP.top - stackP.data) - *i_p > entity->getEndOfLocals());
  676. interpretAssert(*i_p < (Uint32)(stackP.top - stackP.data));
  677. operand = stackP.top - 1 - *i_p++;
  678. }
  679. static void grabStackCopyUse() { start_func
  680. interpretAssert((stackP.top - stackP.data) - *i_p > entity->getEndOfLocals());
  681. interpretAssert(*i_p < (Uint32)(stackP.top - stackP.data));
  682. operand = stackP.top - 1 - *i_p++;
  683. interpretAssert(operand->type <= 0x0F);
  684. copiersUse[((addrmode & 0x0F) << 4) | operand->type]();
  685. }
  686. static void grabLocalUse() { start_func
  687. interpretAssert(*i_p < entity->getEndOfLocals());
  688. operand = tempOperand + (tempPos ^= 1);
  689. *operand = *(stackP.data + *i_p++);
  690. referencers[operand->type](operand);
  691. }
  692. static void grabLocalNumUse() { start_func
  693. interpretAssert((stackP.top - stackP.data) - *i_p > entity->getEndOfLocals());
  694. interpretAssert(*i_p < (Uint32)(stackP.top - stackP.data));
  695. operand = stackP.data + *i_p++;
  696. }
  697. static void grabLocalCopyUse() { start_func
  698. interpretAssert(*i_p < entity->getEndOfLocals());
  699. operand = stackP.data + *i_p++;
  700. interpretAssert(operand->type <= 0x0F);
  701. copiersUse[((addrmode & 0x0F) << 4) | operand->type]();
  702. }
  703. static void grabPopUse() { start_func
  704. interpretAssert((Uint32)(stackP.top - stackP.data) > entity->getEndOfLocals());
  705. operand = --stackP.top;
  706. }
  707. static void grabPopCopyUse() { start_func
  708. interpretAssert((Uint32)(stackP.top - stackP.data) > entity->getEndOfLocals());
  709. operand = --stackP.top;
  710. interpretAssert(operand->type <= 0x0F);
  711. converters[((addrmode & 0x0F) << 4) | operand->type]();
  712. }
  713. //
  714. // Opcode functions
  715. //
  716. // Standard operand pulling, when it can't be optimized
  717. #define OPERAND_0 \
  718. interpretAssert((opdata & 0xFFFFFF00) == 0);
  719. #define ASSERT_1 \
  720. interpretAssert(opdata & 0xFF00); \
  721. interpretAssert((opdata & 0xFFFF0000) == 0);
  722. #define OPERAND_1 \
  723. ASSERT_1 \
  724. grabbers[addrmode = opdata >> 8]();
  725. #define ASSERT_2 \
  726. interpretAssert(opdata & 0xFF00); \
  727. interpretAssert(opdata & 0xFF0000); \
  728. interpretAssert((opdata & 0xFF000000) == 0);
  729. #define OPERAND_2 \
  730. ASSERT_2 \
  731. grabbersStore[addrmode = opdata >> 8](); \
  732. grabbers[addrmode = opdata >> 16]();
  733. #define OPERAND_2CI \
  734. ASSERT_2 \
  735. grabbers[addrmode = opdata >> 8](); \
  736. Sint32 operandData2I = operandDataI; \
  737. grabbers[addrmode = opdata >> 16]();
  738. #define OPERAND_2CF \
  739. ASSERT_2 \
  740. grabbers[addrmode = opdata >> 8](); \
  741. BCfloat operandData2F = operandDataF; \
  742. grabbers[addrmode = opdata >> 16]();
  743. #define OPERAND_2CS \
  744. ASSERT_2 \
  745. grabbers[addrmode = opdata >> 8](); \
  746. const char* operandData2S = operandDataS; \
  747. grabbers[addrmode = opdata >> 16]();
  748. #define OPERAND_2CP \
  749. ASSERT_2 \
  750. grabbers[addrmode = opdata >> 8](); \
  751. void* operandData2P = operandDataP; \
  752. grabbers[addrmode = opdata >> 16]();
  753. #define ASSERT_3 \
  754. interpretAssert(opdata & 0xFF00); \
  755. interpretAssert(opdata & 0xFF0000); \
  756. interpretAssert(opdata & 0xFF000000);
  757. // Opcodes
  758. static void op_noop() { start_func
  759. OPERAND_0
  760. }
  761. void Entity::op_init() { start_func
  762. interpretAssert(entity->runStatus == RUN_INIT);
  763. OPERAND_0
  764. entity->runStatus = RUN_ACTIVE;
  765. entity->endOfLocals = stackP.top - stackP.data;
  766. }
  767. void Entity::op_idle() { start_func
  768. OPERAND_0
  769. entity->runStatus = RUN_IDLE;
  770. }
  771. static void op_jump() { start_func
  772. interpretAssert(((opdata & 0xFF00) >> 8) == OM_INT);
  773. ASSERT_1
  774. // @TODO: + 1 when creating?
  775. i_p += *((Sint32*)i_p) + 1;
  776. }
  777. void Entity::op_ret() { start_func
  778. interpretAssert(stackP.top);
  779. interpretAssert(((opdata & 0xFF00) >> 8) == OM_INT);
  780. interpretAssert(((opdata & 0xFF0000) >> 16) == OM_INT);
  781. interpretAssert(*i_p + *(i_p + 1) + 2 <= stackP.top - stackP.data - entity->getEndOfLocals());
  782. ASSERT_2
  783. // @TODO: this is one opcode that's had no real optimization attempts and
  784. // yet is reasonably important and should be looked at in more detail due to
  785. // its length. One specific optimization that probably isn't worth it is if
  786. // both parameters are 0 AND there's no return pointer, we don't have to do
  787. // anything. This would be better off as another opcode.
  788. // Return value
  789. operand = --stackP.top;
  790. // Pop function locals
  791. Uint32 toKill = *i_p++;
  792. while (toKill--) {
  793. --stackP.top;
  794. interpretAssert(stackP.top->type != STACK_RETURNPTR);
  795. dereferencers[stackP.top->type](stackP.top);
  796. }
  797. // (# of parameters)
  798. toKill = *i_p;
  799. // Jump back
  800. i_p = (Uint32*)((--stackP.top)->data.p);
  801. // @TODO: optimize away RUN_STOPPED and just use i_p=NULL for stopped?
  802. // @TODO: if stopped, assert stack is locals only left
  803. if (!i_p)
  804. entity->runStatus = RUN_STOPPED;
  805. // Pop parameters
  806. while (toKill--) {
  807. --stackP.top;
  808. interpretAssert(stackP.top->type != STACK_RETURNPTR);
  809. dereferencers[stackP.top->type](stackP.top);
  810. }
  811. // If at least one stack entry left and it's a return ptr...
  812. // (we don't need to check for endoflocals as locals can never be return ptrs)
  813. if ((stackP.top != stackP.data) && (stackP.top[-1].type == STACK_RETURNPTR)) {
  814. // Return or destroy value
  815. StackEntry* target = (StackEntry*)((--stackP.top)->data.p);
  816. if (target) {
  817. interpretAssert(target->type & STACK_REPLYPTR);
  818. interpretAssert((target->type | ~STACK_REPLYPTR) <= STACK_BASETYPE);
  819. interpretAssert(((target->type | ~STACK_REPLYPTR) == operand->type) ||
  820. ((target->type | ~STACK_REPLYPTR) == STACK_UNDEF));
  821. *target = *operand;
  822. }
  823. else {
  824. interpretAssert(operand->type != STACK_RETURNPTR);
  825. dereferencers[operand->type](operand);
  826. }
  827. }
  828. // Otherwise, push back onto stack UNLESS we stopped
  829. else {
  830. if (i_p) {
  831. *stackP.top++ = *operand;
  832. }
  833. else {
  834. interpretAssert(operand->type != STACK_RETURNPTR);
  835. dereferencers[operand->type](operand);
  836. }
  837. }
  838. }
  839. void Entity::op_retvoid() { start_func
  840. interpretAssert(stackP.top);
  841. interpretAssert(((opdata & 0xFF00) >> 8) == OM_INT);
  842. interpretAssert(((opdata & 0xFF0000) >> 16) == OM_INT);
  843. interpretAssert(*i_p + *(i_p + 1) + 1 <= stackP.top - stackP.data - entity->getEndOfLocals());
  844. ASSERT_2
  845. // @TODO: this is one opcode that's had no real optimization attempts and
  846. // yet is reasonably important and should be looked at in more detail due to
  847. // its length. One specific optimization that probably isn't worth it is if
  848. // both parameters are 0 AND there's no return pointer, we don't have to do
  849. // anything. This would be better off as another opcode.
  850. // Pop function locals
  851. Uint32 toKill = *i_p++;
  852. while (toKill--) {
  853. --stackP.top;
  854. interpretAssert(stackP.top->type != STACK_RETURNPTR);
  855. dereferencers[stackP.top->type](stackP.top);
  856. }
  857. // (# of parameters)
  858. toKill = *i_p;
  859. // Jump back
  860. i_p = (Uint32*)((--stackP.top)->data.p);
  861. // @TODO: optimize away RUN_STOPPED and just use i_p=NULL for stopped?
  862. // @TODO: if stopped, assert stack is locals only left
  863. if (!i_p)
  864. entity->runStatus = RUN_STOPPED;
  865. // Pop parameters
  866. while (toKill--) {
  867. --stackP.top;
  868. interpretAssert(stackP.top->type != STACK_RETURNPTR);
  869. dereferencers[stackP.top->type](stackP.top);
  870. }
  871. // If at least one stack entry left and it's a return ptr...
  872. // (we don't need to check for endoflocals as locals can never be return ptrs)
  873. if ((stackP.top != stackP.data) && (stackP.top[-1].type == STACK_RETURNPTR)) {
  874. // Return empty value
  875. StackEntry* target = (StackEntry*)((--stackP.top)->data.p);
  876. if (target) {
  877. interpretAssert(target->type & STACK_REPLYPTR);
  878. interpretAssert((target->type | ~STACK_REPLYPTR) <= STACK_BASETYPE);
  879. // Generate empty of requested type
  880. // Assumes STACK_UNDEF is 0 otherwise we should have | STACK_UNDEF here
  881. interpretAssert(STACK_UNDEF == 0);
  882. copiersUse[(target->type | ~STACK_REPLYPTR) << 4]();
  883. *target = *operand;
  884. }
  885. }
  886. }
  887. void Entity::op_stop() { start_func
  888. interpretAssert(entity->runStatus != RUN_INIT);
  889. OPERAND_0
  890. entity->runStatus = RUN_STOPPED;
  891. i_p = NULL;
  892. // wipe stack minus locals (small chance stack is completely empty)
  893. if (stackP.top) {
  894. Uint32 toKill = stackP.top - stackP.data - entity->endOfLocals;
  895. while (toKill--) {
  896. --stackP.top;
  897. // (return ptrs ok)
  898. dereferencers[stackP.top->type](stackP.top);
  899. }
  900. }
  901. }
  902. static void op_subr() { start_func
  903. interpretAssert(((opdata & 0xFF00) >> 8) == OM_INT);
  904. ASSERT_1
  905. prepStack(stackP);
  906. stackP.top->type = STACK_CODEPTR;
  907. // @TODO: perform + 1 on return? etc
  908. stackP.top++->data.p = i_p + 1;
  909. // @TODO: + 1 when creating?
  910. i_p += *((Sint32*)i_p) + 1;
  911. }
  912. void Entity::op_debug() { start_func
  913. OPERAND_1
  914. // No need to optimize this, and could turn up ANYTHING depending on
  915. // how we use it
  916. switch (addrmode) {
  917. // @TODO: remove the ones of these that can't appear anyway
  918. // @TODO: add script/object types to @/O
  919. case OM_ALL:
  920. debugWrite("%s: @ ALL", entity->getName()->c_str());
  921. break;
  922. case OM_ALL_OTHER:
  923. debugWrite("%s: @ ALL_OTHER", entity->getName()->c_str());
  924. break;
  925. case OM_NOTHING:
  926. debugWrite("%s: @ NOTHING", entity->getName()->c_str());
  927. break;
  928. case OM_THIS:
  929. debugWrite("%s: @ THIS", entity->getName()->c_str());
  930. break;
  931. case OM_POINTER:
  932. debugWrite("%s: * %p", entity->getName()->c_str(), operandDataS);
  933. break;
  934. default:
  935. switch (addrmode & 0x0F) {
  936. case OM_INT:
  937. debugWrite("%s: # %d", entity->getName()->c_str(), operandDataI);
  938. break;
  939. case OM_FLOAT:
  940. debugWrite("%s: %% %"BC_FLOAT_PRINTF, entity->getName()->c_str(), operandDataF);
  941. break;
  942. case OM_STR_CONST:
  943. debugWrite("%s: $ %s", entity->getName()->c_str(), operandDataS);
  944. break;
  945. case OM_ENTITY:
  946. if (operandDataP)
  947. debugWrite("%s: @ %s", entity->getName()->c_str(), ((Entity*)operandDataP)->getName()->c_str());
  948. else
  949. debugWrite("%s: @ NOTHING", entity->getName()->c_str());
  950. break;
  951. case OM_OBJECT:
  952. if (operandDataP)
  953. debugWrite("%s: O %p", entity->getName()->c_str(), operandDataP);
  954. else
  955. debugWrite("%s: O NOTHING", entity->getName()->c_str());
  956. break;
  957. case OM_ENTRY:
  958. case OM_ARRAY:
  959. case OM_HASH:
  960. // @TODO:
  961. break;
  962. }
  963. break;
  964. }
  965. }
  966. static void op_addI() { start_func
  967. OPERAND_2
  968. operand->data.i += operandDataI;
  969. }
  970. static void op_divI() { start_func
  971. OPERAND_2
  972. if (operandDataI)
  973. operand->data.i /= operandDataI;
  974. }
  975. static void op_modI() { start_func
  976. OPERAND_2
  977. if (operandDataI)
  978. operand->data.i %= operandDataI;
  979. }
  980. static void op_multI() { start_func
  981. OPERAND_2
  982. operand->data.i *= operandDataI;
  983. }
  984. static void op_subI() { start_func
  985. OPERAND_2
  986. operand->data.i -= operandDataI;
  987. }
  988. static void op_addF() { start_func
  989. OPERAND_2
  990. operand->data.f += operandDataF;
  991. }
  992. static void op_divF() { start_func
  993. OPERAND_2
  994. // (allow floating point div/0- results in INF)
  995. operand->data.f /= operandDataF;
  996. }
  997. static void op_multF() { start_func
  998. OPERAND_2
  999. operand->data.f *= operandDataF;
  1000. }
  1001. static void op_subF() { start_func
  1002. OPERAND_2
  1003. operand->data.f -= operandDataF;
  1004. }
  1005. static void op_andI() { start_func
  1006. OPERAND_2
  1007. operand->data.i &= operandDataI;
  1008. }
  1009. static void op_orI() { start_func
  1010. OPERAND_2
  1011. operand->data.i |= operandDataI;
  1012. }
  1013. static void op_shiftlI() { start_func
  1014. OPERAND_2
  1015. // Uint so bit shift operators do not sign-extend
  1016. (Uint32&)operand->data.i <<= operandDataI;
  1017. }
  1018. static void op_shiftrI() { start_func
  1019. OPERAND_2
  1020. // Uint so bit shift operators do not sign-extend
  1021. (Uint32&)operand->data.i >>= operandDataI;
  1022. }
  1023. static void op_xorI() { start_func
  1024. OPERAND_2
  1025. operand->data.i ^= operandDataI;
  1026. }
  1027. static void op_concatS() { start_func
  1028. OPERAND_2
  1029. ((string*)operand->data.p)->append(operandDataS);
  1030. }
  1031. static void op_iffalseO() { start_func
  1032. interpretAssert((((opdata & 0xFF0000) >> 16) == OM_OBJECT) || (((opdata & 0xFF0000) >> 16) == OM_ENTITY));
  1033. ASSERT_2
  1034. grabbers[addrmode = opdata >> 8]();
  1035. // @TODO: + 1 when creating?
  1036. if (operandDataP == NULL) i_p += *((Sint32*)i_p) + 1;
  1037. else ++i_p;
  1038. }
  1039. static void op_iftrueO() { start_func
  1040. interpretAssert((((opdata & 0xFF0000) >> 16) == OM_OBJECT) || (((opdata & 0xFF0000) >> 16) == OM_ENTITY));
  1041. ASSERT_2
  1042. grabbers[addrmode = opdata >> 8]();
  1043. // @TODO: + 1 when creating?
  1044. if (operandDataP) i_p += *((Sint32*)i_p) + 1;
  1045. else ++i_p;
  1046. }
  1047. static void op_iffalseI() { start_func
  1048. interpretAssert(((opdata & 0xFF0000) >> 16) == OM_INT);
  1049. ASSERT_2
  1050. grabbers[addrmode = opdata >> 8]();
  1051. // @TODO: + 1 when creating?
  1052. if (operandDataI == 0) i_p += *((Sint32*)i_p) + 1;
  1053. else ++i_p;
  1054. }
  1055. static void op_iftrueI() { start_func
  1056. interpretAssert(((opdata & 0xFF0000) >> 16) == OM_INT);
  1057. ASSERT_2
  1058. grabbers[addrmode = opdata >> 8]();
  1059. // @TODO: + 1 when creating?
  1060. if (operandDataI) i_p += *((Sint32*)i_p) + 1;
  1061. else ++i_p;
  1062. }
  1063. static void op_iffalseF() { start_func
  1064. interpretAssert(((opdata & 0xFF0000) >> 16) == OM_INT);
  1065. ASSERT_2
  1066. grabbers[addrmode = opdata >> 8]();
  1067. // @TODO: + 1 when creating?
  1068. if (operandDataF == 0.0) i_p += *((Sint32*)i_p) + 1;
  1069. else ++i_p;
  1070. }
  1071. static void op_iftrueF() { start_func
  1072. interpretAssert(((opdata & 0xFF0000) >> 16) == OM_INT);
  1073. ASSERT_2
  1074. grabbers[addrmode = opdata >> 8]();
  1075. // @TODO: + 1 when creating?
  1076. if (operandDataF != 0.0) i_p += *((Sint32*)i_p) + 1;
  1077. else ++i_p;
  1078. }
  1079. static void op_iffalseS() { start_func
  1080. interpretAssert(((opdata & 0xFF0000) >> 16) == OM_INT);
  1081. ASSERT_2
  1082. grabbers[addrmode = opdata >> 8]();
  1083. // @TODO: + 1 when creating?
  1084. if (*operandDataS == 0) i_p += *((Sint32*)i_p) + 1;
  1085. else ++i_p;
  1086. }
  1087. static void op_iftrueS() { start_func
  1088. interpretAssert(((opdata & 0xFF0000) >> 16) == OM_INT);
  1089. ASSERT_2
  1090. grabbers[addrmode = opdata >> 8]();
  1091. // @TODO: + 1 when creating?
  1092. if (*operandDataS) i_p += *((Sint32*)i_p) + 1;
  1093. else ++i_p;
  1094. }
  1095. static void op_eqO() { start_func
  1096. OPERAND_2CP
  1097. prepStack(stackP);
  1098. stackP.top->type = STACK_INT;
  1099. stackP.top++->data.i = (operandData2P == operandDataP);
  1100. }
  1101. static void op_neO() { start_func
  1102. OPERAND_2CP
  1103. prepStack(stackP);
  1104. stackP.top->type = STACK_INT;
  1105. stackP.top++->data.i = (operandData2P != operandDataP);
  1106. }
  1107. static void op_eqI() { start_func
  1108. OPERAND_2CI
  1109. prepStack(stackP);
  1110. stackP.top->type = STACK_INT;
  1111. stackP.top++->data.i = (operandData2I == operandDataI);
  1112. }
  1113. static void op_geI() { start_func
  1114. OPERAND_2CI
  1115. prepStack(stackP);
  1116. stackP.top->type = STACK_INT;
  1117. stackP.top++->data.i = (operandData2I >= operandDataI);
  1118. }
  1119. static void op_gtI() { start_func
  1120. OPERAND_2CI
  1121. prepStack(stackP);
  1122. stackP.top->type = STACK_INT;
  1123. stackP.top++->data.i = (operandData2I > operandDataI);
  1124. }
  1125. static void op_leI() { start_func
  1126. OPERAND_2CI
  1127. prepStack(stackP);
  1128. stackP.top->type = STACK_INT;
  1129. stackP.top++->data.i = (operandData2I <= operandDataI);
  1130. }
  1131. static void op_ltI() { start_func
  1132. OPERAND_2CI
  1133. prepStack(stackP);
  1134. stackP.top->type = STACK_INT;
  1135. stackP.top++->data.i = (operandData2I < operandDataI);
  1136. }
  1137. static void op_neI() { start_func
  1138. OPERAND_2CI
  1139. prepStack(stackP);
  1140. stackP.top->type = STACK_INT;
  1141. stackP.top++->data.i = (operandData2I != operandDataI);
  1142. }
  1143. static void op_eqF() { start_func
  1144. OPERAND_2CF
  1145. prepStack(stackP);
  1146. stackP.top->type = STACK_FLOAT;
  1147. stackP.top++->data.i = (operandData2F == operandDataF);
  1148. }
  1149. static void op_geF() { start_func
  1150. OPERAND_2CF
  1151. prepStack(stackP);
  1152. stackP.top->type = STACK_INT;
  1153. stackP.top++->data.i = (operandData2F >= operandDataF);
  1154. }
  1155. static void op_gtF() { start_func
  1156. OPERAND_2CF
  1157. prepStack(stackP);
  1158. stackP.top->type = STACK_INT;
  1159. stackP.top++->data.i = (operandData2F > operandDataF);
  1160. }
  1161. static void op_leF() { start_func
  1162. OPERAND_2CF
  1163. prepStack(stackP);
  1164. stackP.top->type = STACK_INT;
  1165. stackP.top++->data.i = (operandData2F <= operandDataF);
  1166. }
  1167. static void op_ltF() { start_func
  1168. OPERAND_2CF
  1169. prepStack(stackP);
  1170. stackP.top->type = STACK_INT;
  1171. stackP.top++->data.i = (operandData2F < operandDataF);
  1172. }
  1173. static void op_neF() { start_func
  1174. OPERAND_2CF
  1175. prepStack(stackP);
  1176. stackP.top->type = STACK_INT;
  1177. stackP.top++->data.i = (operandData2F != operandDataF);
  1178. }
  1179. static void op_eqS() { start_func
  1180. OPERAND_2CS
  1181. prepStack(stackP);
  1182. stackP.top->type = STACK_INT;
  1183. stackP.top++->data.i = myStricmp(operandData2S, operandDataS) == 0;
  1184. }
  1185. static void op_geS() { start_func
  1186. OPERAND_2CS
  1187. prepStack(stackP);
  1188. stackP.top->type = STACK_INT;
  1189. stackP.top++->data.i = myStricmp(operandData2S, operandDataS) >= 0;
  1190. }
  1191. static void op_gtS() { start_func
  1192. OPERAND_2CS
  1193. prepStack(stackP);
  1194. stackP.top->type = STACK_INT;
  1195. stackP.top++->data.i = myStricmp(operandData2S, operandDataS) > 0;
  1196. }
  1197. static void op_leS() { start_func
  1198. OPERAND_2CS
  1199. prepStack(stackP);
  1200. stackP.top->type = STACK_INT;
  1201. stackP.top++->data.i = myStricmp(operandData2S, operandDataS) <= 0;
  1202. }
  1203. static void op_ltS() { start_func
  1204. OPERAND_2CS
  1205. prepStack(stackP);
  1206. stackP.top->type = STACK_INT;
  1207. stackP.top++->data.i = myStricmp(operandData2S, operandDataS) < 0;
  1208. }
  1209. static void op_neS() { start_func
  1210. OPERAND_2CS
  1211. prepStack(stackP);
  1212. stackP.top->type = STACK_INT;
  1213. stackP.top++->data.i = myStricmp(operandData2S, operandDataS) != 0;
  1214. }
  1215. static void op_pushI() { start_func
  1216. OPERAND_1
  1217. prepStack(stackP);
  1218. stackP.top->type = STACK_INT;
  1219. stackP.top++->data.i = operandDataI;
  1220. }
  1221. static void op_pushF() { start_func
  1222. OPERAND_1
  1223. prepStack(stackP);
  1224. stackP.top->type = STACK_FLOAT;
  1225. stackP.top++->data.f = operandDataF;
  1226. }
  1227. // @TODO: Might be faster using grabbersUse (see op_pushAHO)
  1228. static void op_pushS() { start_func
  1229. OPERAND_1
  1230. prepStack(stackP);
  1231. stackP.top->type = STACK_STRING;
  1232. stackP.top++->data.p = new string(operandDataS);
  1233. }
  1234. static void op_pushAHO() { start_func
  1235. // (must prepstack BEFORE pulling operands anytime we use operand+prepstack together)
  1236. prepStack(stackP);
  1237. ASSERT_1
  1238. grabbersUse[addrmode = opdata >> 8]();
  1239. *stackP.top++ = *operand;
  1240. /* @TODO: this code snippet MIGHT be faster, but unlikely
  1241. OPERAND_1
  1242. prepStack(stackP);
  1243. stackP.top->type = STACK_OBJECT;
  1244. stackP.top++->data.p = operandDataP;
  1245. referencers[...];
  1246. */
  1247. }
  1248. static void op_createE() { start_func
  1249. OPERAND_0
  1250. prepStack(stackP);
  1251. stackP.top->type = STACK_ENTITY;
  1252. stackP.top++->data.p = NULL;
  1253. }
  1254. static void op_createO() { start_func
  1255. OPERAND_0
  1256. prepStack(stackP);
  1257. stackP.top->type = STACK_OBJECT;
  1258. stackP.top++->data.p = NULL;
  1259. }
  1260. // @TODO: consolidate into one, if they remain the same; may obsolete grabbersWrite[]
  1261. static void op_storeI() { start_func
  1262. ASSERT_2
  1263. grabbersUse[addrmode = opdata >> 8]();
  1264. grabbersWrite[addrmode = opdata >> 16]();
  1265. *operandWrite = *operand;
  1266. }
  1267. static void op_storeF() { start_func
  1268. ASSERT_2
  1269. grabbersUse[addrmode = opdata >> 8]();
  1270. grabbersWrite[addrmode = opdata >> 16]();
  1271. *operandWrite = *operand;
  1272. }
  1273. static void op_storeS() { start_func
  1274. ASSERT_2
  1275. grabbersUse[addrmode = opdata >> 8]();
  1276. grabbersWrite[addrmode = opdata >> 16]();
  1277. *operandWrite = *operand;
  1278. }
  1279. static void op_storeO() { start_func
  1280. ASSERT_2
  1281. grabbersUse[addrmode = opdata >> 8]();
  1282. grabbersWrite[addrmode = opdata >> 16]();
  1283. *operandWrite = *operand;
  1284. }
  1285. static void op_storeA() { start_func
  1286. ASSERT_2
  1287. grabbersUse[addrmode = opdata >> 8]();
  1288. grabbersWrite[addrmode = opdata >> 16]();
  1289. *operandWrite = *operand;
  1290. }
  1291. static void op_storeH() { start_func
  1292. ASSERT_2
  1293. grabbersUse[addrmode = opdata >> 8]();
  1294. grabbersWrite[addrmode = opdata >> 16]();
  1295. *operandWrite = *operand;
  1296. }
  1297. // @TODO: these have not been fully optimized yet
  1298. // further opcode splitting may be in order as well-
  1299. // ex: versions that garauntee it's not all/all_other/string/nothing(null)
  1300. static void op_getE() { start_func
  1301. ASSERT_3
  1302. interpretAssert(((opdata & 0xFF0000) >> 16) == OM_INT);
  1303. interpretAssert(((opdata & 0xFF000000) >> 24) == OM_INT);
  1304. // @TODO: doesn't support all/all_other/string
  1305. grabbers[addrmode = opdata >> 8]();
  1306. prepStack(stackP);
  1307. // could be NULL (nothing)
  1308. if (operandDataP) {
  1309. stackP.top->data = ((Entity*)operandDataP)->varTable[*i_p++];
  1310. stackP.top->type = *i_p++;
  1311. referencers[stackP.top->type](stackP.top);
  1312. stackP.top++;
  1313. }
  1314. else {
  1315. interpretAssert(*i_p <= STACK_BASETYPE);
  1316. // Generate empty of requested type
  1317. // Assumes STACK_UNDEF is 0 otherwise we should have | STACK_UNDEF here
  1318. interpretAssert(STACK_UNDEF == 0);
  1319. copiersUse[*i_p++ << 4]();
  1320. *stackP.top++ = *operand;
  1321. }
  1322. }
  1323. static void op_getO() { start_func
  1324. ASSERT_3
  1325. interpretAssert(((opdata & 0xFF0000) >> 16) == OM_INT);
  1326. interpretAssert(((opdata & 0xFF000000) >> 24) == OM_INT);
  1327. grabbers[addrmode = opdata >> 8]();
  1328. prepStack(stackP);
  1329. // could be NULL (nothing)
  1330. if (operandDataP) {
  1331. stackP.top->data = ((ObjectBase*)operandDataP)->members[*i_p++];
  1332. stackP.top->type = *i_p++;
  1333. referencers[stackP.top->type](stackP.top);
  1334. stackP.top++;
  1335. }
  1336. else {
  1337. interpretAssert(*i_p <= STACK_BASETYPE);
  1338. // Generate empty of requested type
  1339. // Assumes STACK_UNDEF is 0 otherwise we should have | STACK_UNDEF here
  1340. interpretAssert(STACK_UNDEF == 0);
  1341. copiersUse[*i_p++ << 4]();
  1342. *stackP.top++ = *operand;
  1343. }
  1344. }
  1345. static void op_setE() { start_func
  1346. ASSERT_3
  1347. interpretAssert(((opdata & 0xFF000000) >> 24) == OM_INT);
  1348. grabbersUse[addrmode = opdata >> 8]();
  1349. // @TODO: doesn't support all/all_other/string
  1350. grabbers[addrmode = opdata >> 16]();
  1351. if (operandDataP)
  1352. swap(((Entity*)operandDataP)->varTable[*i_p++], operand->data);
  1353. dereferencers[operand->type](operand);
  1354. }
  1355. static void op_setO() { start_func
  1356. ASSERT_3
  1357. interpretAssert(((opdata & 0xFF000000) >> 24) == OM_INT);
  1358. grabbersUse[addrmode = opdata >> 8]();
  1359. // @TODO: doesn't support all/all_other/string
  1360. grabbers[addrmode = opdata >> 16]();
  1361. if (operandDataP)
  1362. swap(((ObjectBase*)operandDataP)->members[*i_p++], operand->data);
  1363. dereferencers[operand->type](operand);
  1364. }
  1365. // Setting float or int can be optimized due to lack of deref need
  1366. // @TODO: but grabbersUse might be faster anyway? dblcheck
  1367. static void op_setEF() { start_func
  1368. ASSERT_3
  1369. interpretAssert((((opdata & 0xFF00) >> 8) & OM_BASETYPE) == OM_FLOAT);
  1370. interpretAssert(((opdata & 0xFF000000) >> 24) == OM_INT);
  1371. grabbers[addrmode = opdata >> 8]();
  1372. // @TODO: doesn't support all/all_other/string
  1373. grabbers[addrmode = opdata >> 16]();
  1374. if (operandDataP)
  1375. ((Entity*)operandDataP)->varTable[*i_p++].f = operandDataF;
  1376. }
  1377. static void op_setEI() { start_func
  1378. ASSERT_3
  1379. interpretAssert((((opdata & 0xFF00) >> 8) & OM_BASETYPE) == OM_INT);
  1380. interpretAssert(((opdata & 0xFF000000) >> 24) == OM_INT);
  1381. grabbers[addrmode = opdata >> 8]();
  1382. // @TODO: doesn't support all/all_other/string
  1383. grabbers[addrmode = opdata >> 16]();
  1384. if (operandDataP)
  1385. ((Entity*)operandDataP)->varTable[*i_p++].i = operandDataI;
  1386. }
  1387. static void op_setOF() { start_func
  1388. ASSERT_3
  1389. interpretAssert((((opdata & 0xFF00) >> 8) & OM_BASETYPE) == OM_FLOAT);
  1390. interpretAssert(((opdata & 0xFF000000) >> 24) == OM_INT);
  1391. grabbers[addrmode = opdata >> 8]();
  1392. // @TODO: doesn't support all/all_other/string
  1393. grabbers[addrmode = opdata >> 16]();
  1394. if (operandDataP)
  1395. ((ObjectBase*)operandDataP)->members[*i_p++].f = operandDataF;
  1396. }
  1397. static void op_setOI() { start_func
  1398. ASSERT_3
  1399. interpretAssert((((opdata & 0xFF00) >> 8) & OM_BASETYPE) == OM_INT);
  1400. interpretAssert(((opdata & 0xFF000000) >> 24) == OM_INT);
  1401. grabbers[addrmode = opdata >> 8]();
  1402. // @TODO: doesn't support all/all_other/string
  1403. grabbers[addrmode = opdata >> 16]();
  1404. if (operandDataP)
  1405. ((ObjectBase*)operandDataP)->members[*i_p++].i = operandDataI;
  1406. }
  1407. static void op_convert() { start_func
  1408. OPERAND_1
  1409. // (do nothing- pulling the operand did the work of converting it)
  1410. // @TODO: Optimization possible, as we're wasting time extracting- grabbersStore?
  1411. }
  1412. static void op_discard() { start_func
  1413. interpretAssert(stackP.top);
  1414. interpretAssert(((opdata & 0xFF00) >> 8) == OM_INT);
  1415. interpretAssert(*i_p > 0);
  1416. interpretAssert(*i_p <= stackP.top - stackP.data - entity->getEndOfLocals());
  1417. ASSERT_1
  1418. Uint32 toKill = *i_p++;
  1419. do {
  1420. --stackP.top;
  1421. // (return ptrs ok)
  1422. dereferencers[stackP.top->type](stackP.top);
  1423. } while (--toKill);
  1424. }
  1425. static void op_discardl() { start_func
  1426. interpretAssert(stackP.top);
  1427. interpretAssert(((opdata & 0xFF00) >> 8) == OM_INT);
  1428. interpretAssert(*i_p > 0);
  1429. interpretAssert(*i_p <= stackP.top - stackP.data - entity->getEndOfLocals());
  1430. ASSERT_1
  1431. // if debugging enabled, assert everything discarded is 0/1/2/128
  1432. #ifdef INTERPRETASSERT
  1433. Uint32 toKill = *i_p++;
  1434. do {
  1435. --stackP.top;
  1436. interpretAssert((stackP.top->type == STACK_INT) ||
  1437. (stackP.top->type == STACK_FLOAT) ||
  1438. (stackP.top->type == STACK_UNDEF) ||
  1439. (stackP.top->type == STACK_CODEPTR));
  1440. } while (--toKill);
  1441. #else
  1442. stackP.top -= *i_p++;
  1443. #endif
  1444. }
  1445. //
  1446. // Main interpreter loop
  1447. //
  1448. void Entity::cycle() { start_func
  1449. // Entity must be active and have a script.
  1450. if ((!active) || (!script)) return;
  1451. // If asserts on, we need to handle exceptions
  1452. #ifdef INTERPRETASSERT
  1453. try {
  1454. #endif
  1455. // Entity must not be stopped.
  1456. interpretAssert(runStatus != RUN_UNINIT);
  1457. if (runStatus == RUN_STOPPED) return;
  1458. if (runStatus == RUN_IDLE) runStatus = RUN_ACTIVE;
  1459. /*
  1460. // @TODO: temp chunk for benchmarking
  1461. int startTicks2 = SDL_GetTicks();
  1462. int a = 1;
  1463. int b = 1;
  1464. while (a < 10000000) {
  1465. a = a + 1;
  1466. if (a & 1) b = b + a;
  1467. }
  1468. debugWrite("(in C ticks: %d)", startTicks2 - SDL_GetTicks(), b);
  1469. debugWrite("%d %d", a, b);
  1470. */
  1471. #ifndef NDEBUG
  1472. int startTicks = SDL_GetTicks();
  1473. if (debugLevel() & DEBUG_INTERPRET)
  1474. debugWrite("%s [", getName()->c_str());
  1475. #endif
  1476. // Prepare state data
  1477. interpretAssert(i);
  1478. i_p = i;
  1479. stackP = stack;
  1480. entity = this;
  1481. do {
  1482. #ifndef NDEBUG
  1483. if (debugLevel() & DEBUG_INTERPRET) {
  1484. string toWrite;
  1485. debugBytecode(toWrite, i_p);
  1486. debugWrite(" %s", toWrite.c_str());
  1487. }
  1488. #endif
  1489. // Perform next opcode; includes pulling operands
  1490. // @TODO: assert valid opcode
  1491. opcodes[(opdata = *i_p++) & 0xFF]();
  1492. // Loop continuously until an opcode stops us
  1493. // @TODO: could just be == RUN_ACTIVE if we get rid of INIT state
  1494. } while ((runStatus != RUN_STOPPED) && (runStatus != RUN_IDLE));
  1495. // @TODO: reduce stack size if significant empty space?
  1496. // Copy changes in state data back
  1497. i = i_p;
  1498. stack = stackP;
  1499. #ifndef NDEBUG
  1500. if (debugLevel() & DEBUG_INTERPRET)
  1501. debugWrite("] %s (ticks: %d)", getName()->c_str(), SDL_GetTicks() - startTicks);
  1502. #endif
  1503. #ifdef INTERPRETASSERT
  1504. }
  1505. catch (InterpretException& e) {
  1506. runStatus = RUN_STOPPED;
  1507. i_p = NULL;
  1508. stack = stackP;
  1509. debugWrite("%s", e.details);
  1510. // @TODO: Display runtime error
  1511. }
  1512. #endif
  1513. }
  1514. void Entity::wipeStack() { start_func
  1515. // wipe stack including locals
  1516. if (stack.top) {
  1517. Uint32 toKill = stack.top - stack.data;
  1518. while (toKill--) {
  1519. --stack.top;
  1520. // (return ptrs ok)
  1521. dereferencers[stack.top->type](stack.top);
  1522. }
  1523. }
  1524. stack.top = stack.data;
  1525. endOfLocals = 0;
  1526. }
  1527. //
  1528. // Init/deinit
  1529. //
  1530. void fillInterpreterTables() { start_func
  1531. for (int i = 0; i < 256; ++i) {
  1532. converters[i] = interpretError;
  1533. copiers[i] = interpretError;
  1534. copiersUse[i] = interpretError;
  1535. grabbers[i] = interpretError;
  1536. grabbersStore[i] = interpretError;
  1537. grabbersWrite[i] = interpretError;
  1538. grabbersUse[i] = interpretError;
  1539. extractors[i] = interpretError;
  1540. }
  1541. for (int i = 0; i < STACK_TYPE_COUNT; ++i) {
  1542. dereferencers[i] = interpretErrorDeref;
  1543. referencers[i] = interpretErrorDeref;
  1544. }
  1545. // Referencing
  1546. referencers[STACK_INT] = refNothing;
  1547. referencers[STACK_FLOAT] = refNothing;
  1548. referencers[STACK_STRING] = refString;
  1549. referencers[STACK_ARRAY] = refArray;
  1550. referencers[STACK_HASH] = refHash;
  1551. referencers[STACK_ENTITY] = refEntity;
  1552. referencers[STACK_OBJECT] = refObject;
  1553. // Dereferencing
  1554. dereferencers[STACK_UNDEF] = derefNothing;
  1555. dereferencers[STACK_INT] = derefNothing;
  1556. dereferencers[STACK_FLOAT] = derefNothing;
  1557. dereferencers[STACK_STRING] = derefString;
  1558. dereferencers[STACK_ARRAY] = derefArray;
  1559. dereferencers[STACK_HASH] = derefHash;
  1560. dereferencers[STACK_ENTITY] = derefEntity;
  1561. dereferencers[STACK_OBJECT] = derefObject;
  1562. dereferencers[STACK_CODEPTR] = derefNothing;
  1563. dereferencers[STACK_RETURNPTR] = derefReturn;
  1564. for (int i = STACK_INDIRECT; i <= STACK_INDIRECT + STACK_BASETYPE; ++i) {
  1565. dereferencers[i] = derefNothing;
  1566. }
  1567. for (int i = STACK_REPLYPTR; i <= STACK_REPLYPTR + STACK_BASETYPE; ++i) {
  1568. dereferencers[i] = derefReply;
  1569. }
  1570. // Existing datatypes that we support (conversion)
  1571. // We support conversion from UNDEF so that we can use these
  1572. // arrays to quickly create empty values of any type as well
  1573. int existTypes[8] = {
  1574. STACK_UNDEF,
  1575. STACK_INT,
  1576. STACK_FLOAT,
  1577. STACK_STRING,
  1578. STACK_ARRAY,
  1579. STACK_HASH,
  1580. STACK_ENTITY,
  1581. STACK_OBJECT,
  1582. };
  1583. // Start by assuming every conversion "fails", returning empty
  1584. for (int i = 0; i < 8; ++i) {
  1585. converters[(OM_INT << 4) | existTypes[i]] = convertEmptyToInt;
  1586. copiers[(OM_INT << 4) | existTypes[i]] = copyCreateInt;
  1587. copiersUse[(OM_INT << 4) | existTypes[i]] = copyCreateIntUse;
  1588. converters[(OM_FLOAT << 4) | existTypes[i]] = convertEmptyToFloat;
  1589. copiers[(OM_FLOAT << 4) | existTypes[i]] = copyCreateFloat;
  1590. copiersUse[(OM_FLOAT << 4) | existTypes[i]] = copyCreateFloatUse;
  1591. converters[(OM_STR << 4) | existTypes[i]] = convertEmptyToStr;
  1592. copiers[(OM_STR_CONST << 4) | existTypes[i]] = copyCreateStr;
  1593. copiersUse[(OM_STR_CONST << 4) | existTypes[i]] = copyCreateStrUse;
  1594. converters[(OM_ARRAY << 4) | existTypes[i]] = convertEmptyToArray;
  1595. copiers[(OM_ARRAY << 4) | existTypes[i]] = copyCreateArray;
  1596. copiersUse[(OM_ARRAY << 4) | existTypes[i]] = copyCreateArrayUse;
  1597. converters[(OM_HASH << 4) | existTypes[i]] = convertEmptyToHash;
  1598. copiers[(OM_HASH << 4) | existTypes[i]] = copyCreateHash;
  1599. copiersUse[(OM_HASH << 4) | existTypes[i]] = copyCreateHashUse;
  1600. converters[(OM_ENTITY << 4) | existTypes[i]] = convertEmptyToEntity;
  1601. copiers[(OM_ENTITY << 4) | existTypes[i]] = copyCreateEntity;
  1602. copiersUse[(OM_ENTITY << 4) | existTypes[i]] = copyCreateEntityUse;
  1603. converters[(OM_OBJECT << 4) | existTypes[i]] = convertEmptyToObject;
  1604. copiers[(OM_OBJECT << 4) | existTypes[i]] = copyCreateObject;
  1605. copiersUse[(OM_OBJECT << 4) | existTypes[i]] = copyCreateObjectUse;
  1606. }
  1607. // Conversions/copies we explicitly support-
  1608. // int<->float<->string
  1609. // Copy/convert from type to itself also needs to be supported
  1610. // h<->h, a<->a, e<->e, and o<->o are special because the type may match
  1611. // but the subtype needs to be converted
  1612. converters[(OM_INT << 4) | STACK_INT] = doNothing;
  1613. converters[(OM_FLOAT << 4) | STACK_FLOAT] = doNothing;
  1614. converters[(OM_STR << 4) | STACK_STRING] = doNothing;
  1615. converters[(OM_INT << 4) | STACK_FLOAT] = convertFloatToInt;
  1616. converters[(OM_INT << 4) | STACK_STRING] = convertStringToInt;
  1617. converters[(OM_FLOAT << 4) | STACK_INT] = convertIntToFloat;
  1618. converters[(OM_FLOAT << 4) | STACK_STRING] = convertStringToFloat;
  1619. converters[(OM_STR << 4) | STACK_INT] = convertIntToString;
  1620. converters[(OM_STR << 4) | STACK_FLOAT] = convertFloatToString;
  1621. // Copiers know their value will be unmodified, so if copier
  1622. // needs to do nothing, we can just leave the old reference alone.
  1623. copiers[(OM_INT << 4) | STACK_INT] = extractInt;
  1624. copiers[(OM_FLOAT << 4) | STACK_FLOAT] = extractFloat;
  1625. copiers[(OM_STR_CONST << 4) | STACK_STRING] = extractStringConst;
  1626. copiers[(OM_INT << 4) | STACK_FLOAT] = copyFloatToInt;
  1627. copiers[(OM_INT << 4) | STACK_STRING] = copyStringToInt;
  1628. copiers[(OM_FLOAT << 4) | STACK_INT] = copyIntToFloat;
  1629. copiers[(OM_FLOAT << 4) | STACK_STRING] = copyStringToFloat;
  1630. copiers[(OM_STR_CONST << 4) | STACK_INT] = copyIntToString;
  1631. copiers[(OM_STR_CONST << 4) | STACK_FLOAT] = copyFloatToString;
  1632. // @TODO: temp, should be actual copy+convert and for hash/array
  1633. // include making a new copy even if no conversion
  1634. copiers[(OM_ENTITY << 4) | STACK_ENTITY] = extractEntity;
  1635. copiers[(OM_OBJECT << 4) | STACK_OBJECT] = extractObject;
  1636. copiers[(OM_ARRAY << 4) | STACK_ARRAY] = extractArray;
  1637. copiers[(OM_HASH << 4) | STACK_HASH] = extractHash;
  1638. // Copiers for use expect their result to be assigned somewhere,
  1639. // but not modified before then, so we just leave the old reference alone.
  1640. copiersUse[(OM_INT << 4) | STACK_INT] = doNothing;
  1641. copiersUse[(OM_FLOAT << 4) | STACK_FLOAT] = doNothing;
  1642. copiersUse[(OM_STR_CONST << 4) | STACK_STRING] = copyStringUse;
  1643. copiersUse[(OM_INT << 4) | STACK_FLOAT] = copyFloatToIntUse;
  1644. copiersUse[(OM_INT << 4) | STACK_STRING] = copyStringToIntUse;
  1645. copiersUse[(OM_FLOAT << 4) | STACK_INT] = copyIntToFloatUse;
  1646. copiersUse[(OM_FLOAT << 4) | STACK_STRING] = copyStringToFloatUse;
  1647. copiersUse[(OM_STR_CONST << 4) | STACK_INT] = copyIntToStringUse;
  1648. copiersUse[(OM_STR_CONST << 4) | STACK_FLOAT] = copyFloatToStringUse;
  1649. /* @TODO:
  1650. converters[(OM_ENTITY << 4) | STACK_ENTITY] (ensure if subtype doesn't match, = NULL)
  1651. converters[(OM_OBJECT << 4) | STACK_OBJECT] (ensure if subtype doesn't match, = NULL)
  1652. converters[(OM_ARRAY << 4) | STACK_ARRAY]
  1653. converters[(OM_HASH << 4) | STACK_HASH]
  1654. @TODO: copiers, note that copying to an entity/object doesn't need
  1655. to be dereferenced if we choose to just not ref++ it in the first place!
  1656. copiersUse needs to always ++ref even if nothing changes (entity/object)
  1657. both types of copiers for array/hash ALWAYS create a new copy even if no change.
  1658. */
  1659. // Grabbers
  1660. grabbers[OM_INT] = grabInt;
  1661. grabbers[OM_FLOAT] = grabFloat;
  1662. grabbers[OM_STR_CONST] = grabStringConst;
  1663. // @TODO: OM_ALL
  1664. // @TODO: OM_ALL_OTHER
  1665. grabbers[OM_NOTHING] = grabNothing;
  1666. grabbers[OM_THIS] = grabThis;
  1667. // @TODO: OM_POINTER?
  1668. grabbersUse[OM_INT] = grabIntUse;
  1669. grabbersUse[OM_FLOAT] = grabFloatUse;
  1670. grabbersUse[OM_STR_CONST] = grabStringUse;
  1671. // @TODO: OM_ALL
  1672. // @TODO: OM_ALL_OTHER
  1673. grabbersUse[OM_NOTHING] = grabNothingUse;
  1674. grabbersUse[OM_THIS] = grabThisUse;
  1675. // @TODO: OM_POINTER?
  1676. for (int i = OM_STACK; i < OM_STACK + OM_BASETYPE; ++i) {
  1677. grabbersStore[i] = grabStackConvertStore;
  1678. grabbersWrite[i] = grabStackWrite;
  1679. }
  1680. for (int i = OM_LOCAL; i < OM_LOCAL + OM_BASETYPE; ++i) {
  1681. grabbersStore[i] = grabLocalConvertStore;
  1682. grabbersWrite[i] = grabLocalWrite;
  1683. }
  1684. for (int i = OM_GLOBAL; i < OM_GLOBAL + OM_BASETYPE; ++i) {
  1685. grabbersStore[i] = interpretError; // @TODO: global+convert-in-place
  1686. grabbersWrite[i] = interpretError; // @TODO: global+convert-in-place
  1687. }
  1688. for (int i = OM_POP + OM_NO_CONVERT; i < OM_POP + OM_NO_CONVERT + OM_BASETYPE; ++i) {
  1689. grabbers[i] = grabPop;
  1690. grabbersUse[i] = grabPopUse;
  1691. }
  1692. grabbers[OM_POP + OM_NO_CONVERT + OM_INT] = grabPopInt;
  1693. grabbers[OM_POP + OM_NO_CONVERT + OM_FLOAT] = grabPopFloat;
  1694. // @TODO: specialized POP+ConstStr (shouldn't be able to have POP+Str)
  1695. for (int i = OM_STACK + OM_NO_CONVERT; i < OM_STACK + OM_NO_CONVERT + OM_BASETYPE; ++i) {
  1696. grabbers[i] = grabStack;
  1697. grabbersStore[i] = grabStackStore;
  1698. grabbersWrite[i] = grabStackWrite;
  1699. grabbersUse[i] = grabStackUse;
  1700. }
  1701. grabbers[OM_STACK + OM_NO_CONVERT + OM_INT] = grabStackInt;
  1702. grabbers[OM_STACK + OM_NO_CONVERT + OM_FLOAT] = grabStackFloat;
  1703. grabbersUse[OM_STACK + OM_NO_CONVERT + OM_INT] = grabStackNumUse;
  1704. grabbersUse[OM_STACK + OM_NO_CONVERT + OM_FLOAT] = grabStackNumUse;
  1705. grabbersWrite[OM_STACK + OM_NO_CONVERT + OM_INT] = grabStackNumWrite;
  1706. grabbersWrite[OM_STACK + OM_NO_CONVERT + OM_FLOAT] = grabStackNumWrite;
  1707. for (int i = OM_LOCAL + OM_NO_CONVERT; i < OM_LOCAL + OM_NO_CONVERT + OM_BASETYPE; ++i) {
  1708. grabbers[i] = grabLocal;
  1709. grabbersStore[i] = grabLocalStore;
  1710. grabbersWrite[i] = grabLocalWrite;
  1711. grabbersUse[i] = grabLocalUse;
  1712. }
  1713. grabbers[OM_LOCAL + OM_NO_CONVERT + OM_INT] = grabLocalInt;
  1714. grabbers[OM_LOCAL + OM_NO_CONVERT + OM_FLOAT] = grabLocalFloat;
  1715. grabbersUse[OM_LOCAL + OM_NO_CONVERT + OM_INT] = grabLocalNumUse;
  1716. grabbersUse[OM_LOCAL + OM_NO_CONVERT + OM_FLOAT] = grabLocalNumUse;
  1717. grabbersWrite[OM_LOCAL + OM_NO_CONVERT + OM_INT] = grabLocalNumWrite;
  1718. grabbersWrite[OM_LOCAL + OM_NO_CONVERT + OM_FLOAT] = grabLocalNumWrite;
  1719. for (int i = OM_GLOBAL + OM_NO_CONVERT; i < OM_GLOBAL + OM_NO_CONVERT + OM_BASETYPE; ++i) {
  1720. grabbers[i] = interpretError; // @TODO: global+no-convert
  1721. grabbersStore[i] = interpretError; // @TODO: global+no-convert
  1722. grabbersWrite[i] = interpretError; // @TODO: global+no-convert
  1723. grabbersUse[i] = interpretError; // @TODO: global+no-convert
  1724. }
  1725. // @TODO: global+no-convert+int/float
  1726. for (int i = OM_POP + OM_COPY; i < OM_POP + OM_COPY + OM_BASETYPE; ++i) {
  1727. grabbers[i] = grabPopCopy;
  1728. grabbersUse[i] = grabPopCopyUse;
  1729. }
  1730. for (int i = OM_STACK + OM_COPY; i < OM_STACK + OM_COPY + OM_BASETYPE; ++i) {
  1731. grabbers[i] = grabStackCopy;
  1732. grabbersUse[i] = grabStackCopyUse;
  1733. }
  1734. for (int i = OM_LOCAL + OM_COPY; i < OM_LOCAL + OM_COPY + OM_BASETYPE; ++i) {
  1735. grabbers[i] = grabLocalCopy;
  1736. grabbersUse[i] = grabLocalCopyUse;
  1737. }
  1738. for (int i = OM_GLOBAL + OM_COPY; i < OM_GLOBAL + OM_COPY + OM_BASETYPE; ++i) {
  1739. grabbers[i] = interpretError; // @TODO: global+copy-convert
  1740. grabbersUse[i] = interpretError; // @TODO: global+copy-convert
  1741. }
  1742. /* @TODO: indirects (unsure which modes will be needed yet)
  1743. for (int i = OM_POP + OM_INDIRECT; i < OM_POP + OM_INDIRECT + OM_BASETYPE; ++i) {
  1744. grabbers[i] = interpretError;
  1745. grabbersStore[i] = interpretError;
  1746. grabbersWrite[i] = interpretError;
  1747. grabbersUse[i] = interpretError;
  1748. }
  1749. for (int i = OM_STACK + OM_INDIRECT; i < OM_STACK + OM_INDIRECT + OM_BASETYPE; ++i) {
  1750. grabbers[i] = interpretError;
  1751. grabbersStore[i] = interpretError;
  1752. grabbersWrite[i] = interpretError;
  1753. grabbersUse[i] = interpretError;
  1754. }
  1755. */
  1756. // Extractors
  1757. for (int i = 0; i < 256; i += 16) {
  1758. extractors[i + OM_INT] = extractInt;
  1759. extractors[i + OM_FLOAT] = extractFloat;
  1760. // (should never occur) extractors[i + OM_STR] = extractStringConst;
  1761. extractors[i + OM_STR_CONST] = extractStringConst;
  1762. extractors[i + OM_ARRAY] = extractArray;
  1763. extractors[i + OM_HASH] = extractHash;
  1764. extractors[i + OM_ENTITY] = extractEntity;
  1765. extractors[i + OM_OBJECT] = extractObject;
  1766. }
  1767. // Opcodes
  1768. opcodes[OP_NOOP] = op_noop;
  1769. opcodes[OP_ADD] = op_addI;
  1770. opcodes[OP_ADDf] = op_addF;
  1771. opcodes[OP_AND] = op_andI;
  1772. opcodes[OP_CONCAT] = op_concatS;
  1773. opcodes[OP_CONVERT] = op_convert;
  1774. opcodes[OP_CREATEa] = interpretError; // @TODO:
  1775. opcodes[OP_CREATEe] = op_createE;
  1776. opcodes[OP_CREATEh] = interpretError; // @TODO:
  1777. opcodes[OP_CREATEo] = op_createO;
  1778. opcodes[OP_DEBUG] = Entity::op_debug;
  1779. opcodes[OP_DISCARD] = op_discard;
  1780. opcodes[OP_DISCARDL] = op_discardl;
  1781. opcodes[OP_DIV] = op_divI;
  1782. opcodes[OP_DIVf] = op_divF;
  1783. opcodes[OP_EQ] = op_eqI;
  1784. opcodes[OP_EQf] = op_eqF;
  1785. opcodes[OP_EQo] = op_eqO;
  1786. opcodes[OP_EQs] = op_eqS;
  1787. opcodes[OP_GE] = op_geI;
  1788. opcodes[OP_GEf] = op_geF;
  1789. opcodes[OP_GEs] = op_geS;
  1790. opcodes[OP_GT] = op_gtI;
  1791. opcodes[OP_GTf] = op_gtF;
  1792. opcodes[OP_GTs] = op_gtS;
  1793. opcodes[OP_IFFALSE] = op_iffalseI;
  1794. opcodes[OP_IFFALSEa] = interpretError; // @TODO:
  1795. opcodes[OP_IFFALSEf] = op_iffalseF;
  1796. opcodes[OP_IFFALSEh] = interpretError; // @TODO:
  1797. opcodes[OP_IFFALSEo] = op_iffalseO;
  1798. opcodes[OP_IFFALSEs] = op_iffalseS;
  1799. opcodes[OP_IFFALSEv] = interpretError; // @TODO:
  1800. opcodes[OP_IFTRUE] = op_iftrueI;
  1801. opcodes[OP_IFTRUEa] = interpretError; // @TODO:
  1802. opcodes[OP_IFTRUEf] = op_iftrueF;
  1803. opcodes[OP_IFTRUEh] = interpretError; // @TODO:
  1804. opcodes[OP_IFTRUEo] = op_iftrueO;
  1805. opcodes[OP_IFTRUEs] = op_iftrueS;
  1806. opcodes[OP_IFTRUEv] = interpretError; // @TODO:
  1807. opcodes[OP_INIT] = Entity::op_init;
  1808. opcodes[OP_JUMP] = op_jump;
  1809. opcodes[OP_LE] = op_leI;
  1810. opcodes[OP_LEf] = op_leF;
  1811. opcodes[OP_LEs] = op_leS;
  1812. opcodes[OP_LT] = op_ltI;
  1813. opcodes[OP_LTf] = op_ltF;
  1814. opcodes[OP_LTs] = op_ltS;
  1815. opcodes[OP_MOD] = op_modI;
  1816. opcodes[OP_MULT] = op_multI;
  1817. opcodes[OP_MULTf] = op_multF;
  1818. opcodes[OP_NE] = op_neI;
  1819. opcodes[OP_NEf] = op_neF;
  1820. opcodes[OP_NEo] = op_neO;
  1821. opcodes[OP_NEs] = op_neS;
  1822. opcodes[OP_OR] = op_orI;
  1823. opcodes[OP_PUSH] = op_pushI;
  1824. opcodes[OP_PUSHa] = op_pushAHO;
  1825. opcodes[OP_PUSHf] = op_pushF;
  1826. opcodes[OP_PUSHh] = op_pushAHO;
  1827. opcodes[OP_PUSHo] = op_pushAHO;
  1828. opcodes[OP_PUSHs] = op_pushS;
  1829. opcodes[OP_PUSHv] = interpretError; // @TODO:
  1830. opcodes[OP_RET] = Entity::op_ret;
  1831. opcodes[OP_SHIFTL] = op_shiftlI;
  1832. opcodes[OP_SHIFTR] = op_shiftrI;
  1833. opcodes[OP_STOP] = Entity::op_stop;
  1834. opcodes[OP_STORE] = op_storeI;
  1835. opcodes[OP_STOREa] = op_storeA;
  1836. opcodes[OP_STOREf] = op_storeF;
  1837. opcodes[OP_STOREh] = op_storeH;
  1838. opcodes[OP_STOREo] = op_storeO;
  1839. opcodes[OP_STOREs] = op_storeS;
  1840. opcodes[OP_STOREv] = interpretError; // @TODO:
  1841. opcodes[OP_SUB] = op_subI;
  1842. opcodes[OP_SUBf] = op_subF;
  1843. opcodes[OP_SUBR] = op_subr;
  1844. opcodes[OP_XOR] = op_xorI;
  1845. opcodes[OP_GETe] = op_getE;
  1846. opcodes[OP_SETe] = op_setE;
  1847. opcodes[OP_GETo] = op_getO;
  1848. opcodes[OP_SETo] = op_setO;
  1849. opcodes[OP_IDLE] = Entity::op_idle;
  1850. opcodes[OP_RETVOID] = Entity::op_retvoid;
  1851. opcodes[OP_SETef] = op_setEF;
  1852. opcodes[OP_SETei] = op_setEI;
  1853. opcodes[OP_SETof] = op_setOF;
  1854. opcodes[OP_SEToi] = op_setOI;
  1855. // Empty operands
  1856. emptyOperand[0].data.i = 0;
  1857. emptyOperand[0].type = STACK_INT;
  1858. emptyOperand[1].data.f = 0.0;
  1859. emptyOperand[1].type = STACK_FLOAT;
  1860. emptyOperand[2].data.p = NULL;
  1861. emptyOperand[2].type = STACK_ENTITY;
  1862. emptyOperand[3].data.p = NULL;
  1863. emptyOperand[3].type = STACK_OBJECT;
  1864. // Init deref array
  1865. for (int i = 0; i < MAX_TODEREF; ++i) {
  1866. toDeref[i].data.i = 0;
  1867. toDeref[i].type = STACK_INT;
  1868. }
  1869. }
  1870. void interpreterCleanup() { start_func
  1871. // Clear deref array
  1872. for (int i = 0; i < MAX_TODEREF; ++i) {
  1873. dereferencers[toDeref[i].type](toDeref + i);
  1874. toDeref[i].data.i = 0;
  1875. toDeref[i].type = STACK_INT;
  1876. }
  1877. }