gcsx_entity.cpp 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140
  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. }
  1313. else {
  1314. interpretAssert(*i_p <= STACK_BASETYPE);
  1315. // Generate empty of requested type
  1316. // Assumes STACK_UNDEF is 0 otherwise we should have | STACK_UNDEF here
  1317. interpretAssert(STACK_UNDEF == 0);
  1318. copiersUse[*i_p++ << 4]();
  1319. *stackP.top++ = *operand;
  1320. }
  1321. }
  1322. static void op_getO() { start_func
  1323. ASSERT_3
  1324. interpretAssert(((opdata & 0xFF0000) >> 16) == OM_INT);
  1325. interpretAssert(((opdata & 0xFF000000) >> 24) == OM_INT);
  1326. grabbers[addrmode = opdata >> 8]();
  1327. prepStack(stackP);
  1328. // could be NULL (nothing)
  1329. if (operandDataP) {
  1330. stackP.top->data = ((ObjectBase*)operandDataP)->members[*i_p++];
  1331. stackP.top->type = *i_p++;
  1332. referencers[stackP.top->type](stackP.top++);
  1333. }
  1334. else {
  1335. interpretAssert(*i_p <= STACK_BASETYPE);
  1336. // Generate empty of requested type
  1337. // Assumes STACK_UNDEF is 0 otherwise we should have | STACK_UNDEF here
  1338. interpretAssert(STACK_UNDEF == 0);
  1339. copiersUse[*i_p++ << 4]();
  1340. *stackP.top++ = *operand;
  1341. }
  1342. }
  1343. static void op_setE() { start_func
  1344. ASSERT_3
  1345. interpretAssert(((opdata & 0xFF000000) >> 24) == OM_INT);
  1346. grabbersUse[addrmode = opdata >> 8]();
  1347. // @TODO: doesn't support all/all_other/string
  1348. grabbers[addrmode = opdata >> 16]();
  1349. if (operandDataP)
  1350. swap(((Entity*)operandDataP)->varTable[*i_p++], operand->data);
  1351. dereferencers[operand->type](operand);
  1352. }
  1353. static void op_setO() { start_func
  1354. ASSERT_3
  1355. interpretAssert(((opdata & 0xFF000000) >> 24) == OM_INT);
  1356. grabbersUse[addrmode = opdata >> 8]();
  1357. // @TODO: doesn't support all/all_other/string
  1358. grabbers[addrmode = opdata >> 16]();
  1359. if (operandDataP)
  1360. swap(((ObjectBase*)operandDataP)->members[*i_p++], operand->data);
  1361. dereferencers[operand->type](operand);
  1362. }
  1363. // Setting float or int can be optimized due to lack of deref need
  1364. // @TODO: but grabbersUse might be faster anyway? dblcheck
  1365. static void op_setEF() { start_func
  1366. ASSERT_3
  1367. interpretAssert((((opdata & 0xFF00) >> 8) & OM_BASETYPE) == OM_FLOAT);
  1368. interpretAssert(((opdata & 0xFF000000) >> 24) == OM_INT);
  1369. grabbers[addrmode = opdata >> 8]();
  1370. // @TODO: doesn't support all/all_other/string
  1371. grabbers[addrmode = opdata >> 16]();
  1372. if (operandDataP)
  1373. ((Entity*)operandDataP)->varTable[*i_p++].f = operandDataF;
  1374. }
  1375. static void op_setEI() { start_func
  1376. ASSERT_3
  1377. interpretAssert((((opdata & 0xFF00) >> 8) & OM_BASETYPE) == OM_INT);
  1378. interpretAssert(((opdata & 0xFF000000) >> 24) == OM_INT);
  1379. grabbers[addrmode = opdata >> 8]();
  1380. // @TODO: doesn't support all/all_other/string
  1381. grabbers[addrmode = opdata >> 16]();
  1382. if (operandDataP)
  1383. ((Entity*)operandDataP)->varTable[*i_p++].i = operandDataI;
  1384. }
  1385. static void op_setOF() { start_func
  1386. ASSERT_3
  1387. interpretAssert((((opdata & 0xFF00) >> 8) & OM_BASETYPE) == OM_FLOAT);
  1388. interpretAssert(((opdata & 0xFF000000) >> 24) == OM_INT);
  1389. grabbers[addrmode = opdata >> 8]();
  1390. // @TODO: doesn't support all/all_other/string
  1391. grabbers[addrmode = opdata >> 16]();
  1392. if (operandDataP)
  1393. ((ObjectBase*)operandDataP)->members[*i_p++].f = operandDataF;
  1394. }
  1395. static void op_setOI() { start_func
  1396. ASSERT_3
  1397. interpretAssert((((opdata & 0xFF00) >> 8) & OM_BASETYPE) == OM_INT);
  1398. interpretAssert(((opdata & 0xFF000000) >> 24) == OM_INT);
  1399. grabbers[addrmode = opdata >> 8]();
  1400. // @TODO: doesn't support all/all_other/string
  1401. grabbers[addrmode = opdata >> 16]();
  1402. if (operandDataP)
  1403. ((ObjectBase*)operandDataP)->members[*i_p++].i = operandDataI;
  1404. }
  1405. static void op_convert() { start_func
  1406. OPERAND_1
  1407. // (do nothing- pulling the operand did the work of converting it)
  1408. // @TODO: Optimization possible, as we're wasting time extracting- grabbersStore?
  1409. }
  1410. static void op_discard() { start_func
  1411. interpretAssert(stackP.top);
  1412. interpretAssert(((opdata & 0xFF00) >> 8) == OM_INT);
  1413. interpretAssert(*i_p > 0);
  1414. interpretAssert(*i_p <= stackP.top - stackP.data - entity->getEndOfLocals());
  1415. ASSERT_1
  1416. Uint32 toKill = *i_p++;
  1417. do {
  1418. --stackP.top;
  1419. // (return ptrs ok)
  1420. dereferencers[stackP.top->type](stackP.top);
  1421. } while (--toKill);
  1422. }
  1423. static void op_discardl() { start_func
  1424. interpretAssert(stackP.top);
  1425. interpretAssert(((opdata & 0xFF00) >> 8) == OM_INT);
  1426. interpretAssert(*i_p > 0);
  1427. interpretAssert(*i_p <= stackP.top - stackP.data - entity->getEndOfLocals());
  1428. ASSERT_1
  1429. // if debugging enabled, assert everything discarded is 0/1/2/128
  1430. #ifdef INTERPRETASSERT
  1431. Uint32 toKill = *i_p++;
  1432. do {
  1433. --stackP.top;
  1434. interpretAssert((stackP.top->type == STACK_INT) ||
  1435. (stackP.top->type == STACK_FLOAT) ||
  1436. (stackP.top->type == STACK_UNDEF) ||
  1437. (stackP.top->type == STACK_CODEPTR));
  1438. } while (--toKill);
  1439. #else
  1440. stackP.top -= *i_p++;
  1441. #endif
  1442. }
  1443. //
  1444. // Main interpreter loop
  1445. //
  1446. void Entity::cycle() { start_func
  1447. // Entity must be active and have a script.
  1448. if ((!active) || (!script)) return;
  1449. // If asserts on, we need to handle exceptions
  1450. #ifdef INTERPRETASSERT
  1451. try {
  1452. #endif
  1453. // Entity must not be stopped.
  1454. interpretAssert(runStatus != RUN_UNINIT);
  1455. if (runStatus == RUN_STOPPED) return;
  1456. if (runStatus == RUN_IDLE) runStatus = RUN_ACTIVE;
  1457. /*
  1458. // @TODO: temp chunk for benchmarking
  1459. int startTicks2 = SDL_GetTicks();
  1460. int a = 1;
  1461. int b = 1;
  1462. while (a < 10000000) {
  1463. a = a + 1;
  1464. if (a & 1) b = b + a;
  1465. }
  1466. debugWrite("(in C ticks: %d)", startTicks2 - SDL_GetTicks(), b);
  1467. debugWrite("%d %d", a, b);
  1468. */
  1469. #ifndef NDEBUG
  1470. int startTicks = SDL_GetTicks();
  1471. if (debugLevel() & DEBUG_INTERPRET)
  1472. debugWrite("%s [", getName()->c_str());
  1473. #endif
  1474. // Prepare state data
  1475. interpretAssert(i);
  1476. i_p = i;
  1477. stackP = stack;
  1478. entity = this;
  1479. do {
  1480. #ifndef NDEBUG
  1481. if (debugLevel() & DEBUG_INTERPRET) {
  1482. string toWrite;
  1483. debugBytecode(toWrite, i_p);
  1484. debugWrite(" %s", toWrite.c_str());
  1485. }
  1486. #endif
  1487. // Perform next opcode; includes pulling operands
  1488. // @TODO: assert valid opcode
  1489. opcodes[(opdata = *i_p++) & 0xFF]();
  1490. // Loop continuously until an opcode stops us
  1491. // @TODO: could just be == RUN_ACTIVE if we get rid of INIT state
  1492. } while ((runStatus != RUN_STOPPED) && (runStatus != RUN_IDLE));
  1493. // @TODO: reduce stack size if significant empty space?
  1494. // Copy changes in state data back
  1495. i = i_p;
  1496. stack = stackP;
  1497. #ifndef NDEBUG
  1498. if (debugLevel() & DEBUG_INTERPRET)
  1499. debugWrite("] %s (ticks: %d)", getName()->c_str(), SDL_GetTicks() - startTicks);
  1500. #endif
  1501. #ifdef INTERPRETASSERT
  1502. }
  1503. catch (InterpretException& e) {
  1504. runStatus = RUN_STOPPED;
  1505. i_p = NULL;
  1506. stack = stackP;
  1507. debugWrite("%s", e.details);
  1508. // @TODO: Display runtime error
  1509. }
  1510. #endif
  1511. }
  1512. void Entity::wipeStack() { start_func
  1513. // wipe stack including locals
  1514. if (stack.top) {
  1515. Uint32 toKill = stack.top - stack.data;
  1516. while (toKill--) {
  1517. --stack.top;
  1518. // (return ptrs ok)
  1519. dereferencers[stack.top->type](stack.top);
  1520. }
  1521. }
  1522. stack.top = stack.data;
  1523. endOfLocals = 0;
  1524. }
  1525. //
  1526. // Init/deinit
  1527. //
  1528. void fillInterpreterTables() { start_func
  1529. for (int i = 0; i < 256; ++i) {
  1530. converters[i] = interpretError;
  1531. copiers[i] = interpretError;
  1532. copiersUse[i] = interpretError;
  1533. grabbers[i] = interpretError;
  1534. grabbersStore[i] = interpretError;
  1535. grabbersWrite[i] = interpretError;
  1536. grabbersUse[i] = interpretError;
  1537. extractors[i] = interpretError;
  1538. }
  1539. for (int i = 0; i < STACK_TYPE_COUNT; ++i) {
  1540. dereferencers[i] = interpretErrorDeref;
  1541. referencers[i] = interpretErrorDeref;
  1542. }
  1543. // Referencing
  1544. referencers[STACK_INT] = refNothing;
  1545. referencers[STACK_FLOAT] = refNothing;
  1546. referencers[STACK_STRING] = refString;
  1547. referencers[STACK_ARRAY] = refArray;
  1548. referencers[STACK_HASH] = refHash;
  1549. referencers[STACK_ENTITY] = refEntity;
  1550. referencers[STACK_OBJECT] = refObject;
  1551. // Dereferencing
  1552. dereferencers[STACK_UNDEF] = derefNothing;
  1553. dereferencers[STACK_INT] = derefNothing;
  1554. dereferencers[STACK_FLOAT] = derefNothing;
  1555. dereferencers[STACK_STRING] = derefString;
  1556. dereferencers[STACK_ARRAY] = derefArray;
  1557. dereferencers[STACK_HASH] = derefHash;
  1558. dereferencers[STACK_ENTITY] = derefEntity;
  1559. dereferencers[STACK_OBJECT] = derefObject;
  1560. dereferencers[STACK_CODEPTR] = derefNothing;
  1561. dereferencers[STACK_RETURNPTR] = derefReturn;
  1562. for (int i = STACK_INDIRECT; i <= STACK_INDIRECT + STACK_BASETYPE; ++i) {
  1563. dereferencers[i] = derefNothing;
  1564. }
  1565. for (int i = STACK_REPLYPTR; i <= STACK_REPLYPTR + STACK_BASETYPE; ++i) {
  1566. dereferencers[i] = derefReply;
  1567. }
  1568. // Existing datatypes that we support (conversion)
  1569. // We support conversion from UNDEF so that we can use these
  1570. // arrays to quickly create empty values of any type as well
  1571. int existTypes[8] = {
  1572. STACK_UNDEF,
  1573. STACK_INT,
  1574. STACK_FLOAT,
  1575. STACK_STRING,
  1576. STACK_ARRAY,
  1577. STACK_HASH,
  1578. STACK_ENTITY,
  1579. STACK_OBJECT,
  1580. };
  1581. // Start by assuming every conversion "fails", returning empty
  1582. for (int i = 0; i < 8; ++i) {
  1583. converters[(OM_INT << 4) | existTypes[i]] = convertEmptyToInt;
  1584. copiers[(OM_INT << 4) | existTypes[i]] = copyCreateInt;
  1585. copiersUse[(OM_INT << 4) | existTypes[i]] = copyCreateIntUse;
  1586. converters[(OM_FLOAT << 4) | existTypes[i]] = convertEmptyToFloat;
  1587. copiers[(OM_FLOAT << 4) | existTypes[i]] = copyCreateFloat;
  1588. copiersUse[(OM_FLOAT << 4) | existTypes[i]] = copyCreateFloatUse;
  1589. converters[(OM_STR << 4) | existTypes[i]] = convertEmptyToStr;
  1590. copiers[(OM_STR_CONST << 4) | existTypes[i]] = copyCreateStr;
  1591. copiersUse[(OM_STR_CONST << 4) | existTypes[i]] = copyCreateStrUse;
  1592. converters[(OM_ARRAY << 4) | existTypes[i]] = convertEmptyToArray;
  1593. copiers[(OM_ARRAY << 4) | existTypes[i]] = copyCreateArray;
  1594. copiersUse[(OM_ARRAY << 4) | existTypes[i]] = copyCreateArrayUse;
  1595. converters[(OM_HASH << 4) | existTypes[i]] = convertEmptyToHash;
  1596. copiers[(OM_HASH << 4) | existTypes[i]] = copyCreateHash;
  1597. copiersUse[(OM_HASH << 4) | existTypes[i]] = copyCreateHashUse;
  1598. converters[(OM_ENTITY << 4) | existTypes[i]] = convertEmptyToEntity;
  1599. copiers[(OM_ENTITY << 4) | existTypes[i]] = copyCreateEntity;
  1600. copiersUse[(OM_ENTITY << 4) | existTypes[i]] = copyCreateEntityUse;
  1601. converters[(OM_OBJECT << 4) | existTypes[i]] = convertEmptyToObject;
  1602. copiers[(OM_OBJECT << 4) | existTypes[i]] = copyCreateObject;
  1603. copiersUse[(OM_OBJECT << 4) | existTypes[i]] = copyCreateObjectUse;
  1604. }
  1605. // Conversions/copies we explicitly support-
  1606. // int<->float<->string
  1607. // Copy/convert from type to itself also needs to be supported
  1608. // h<->h, a<->a, e<->e, and o<->o are special because the type may match
  1609. // but the subtype needs to be converted
  1610. converters[(OM_INT << 4) | STACK_INT] = doNothing;
  1611. converters[(OM_FLOAT << 4) | STACK_FLOAT] = doNothing;
  1612. converters[(OM_STR << 4) | STACK_STRING] = doNothing;
  1613. converters[(OM_INT << 4) | STACK_FLOAT] = convertFloatToInt;
  1614. converters[(OM_INT << 4) | STACK_STRING] = convertStringToInt;
  1615. converters[(OM_FLOAT << 4) | STACK_INT] = convertIntToFloat;
  1616. converters[(OM_FLOAT << 4) | STACK_STRING] = convertStringToFloat;
  1617. converters[(OM_STR << 4) | STACK_INT] = convertIntToString;
  1618. converters[(OM_STR << 4) | STACK_FLOAT] = convertFloatToString;
  1619. // Copiers know their value will be unmodified, so if copier
  1620. // needs to do nothing, we can just leave the old reference alone.
  1621. copiers[(OM_INT << 4) | STACK_INT] = extractInt;
  1622. copiers[(OM_FLOAT << 4) | STACK_FLOAT] = extractFloat;
  1623. copiers[(OM_STR_CONST << 4) | STACK_STRING] = extractStringConst;
  1624. copiers[(OM_INT << 4) | STACK_FLOAT] = copyFloatToInt;
  1625. copiers[(OM_INT << 4) | STACK_STRING] = copyStringToInt;
  1626. copiers[(OM_FLOAT << 4) | STACK_INT] = copyIntToFloat;
  1627. copiers[(OM_FLOAT << 4) | STACK_STRING] = copyStringToFloat;
  1628. copiers[(OM_STR_CONST << 4) | STACK_INT] = copyIntToString;
  1629. copiers[(OM_STR_CONST << 4) | STACK_FLOAT] = copyFloatToString;
  1630. // @TODO: temp, should be actual copy+convert and for hash/array
  1631. // include making a new copy even if no conversion
  1632. copiers[(OM_ENTITY << 4) | STACK_ENTITY] = extractEntity;
  1633. copiers[(OM_OBJECT << 4) | STACK_OBJECT] = extractObject;
  1634. copiers[(OM_ARRAY << 4) | STACK_ARRAY] = extractArray;
  1635. copiers[(OM_HASH << 4) | STACK_HASH] = extractHash;
  1636. // Copiers for use expect their result to be assigned somewhere,
  1637. // but not modified before then, so we just leave the old reference alone.
  1638. copiersUse[(OM_INT << 4) | STACK_INT] = doNothing;
  1639. copiersUse[(OM_FLOAT << 4) | STACK_FLOAT] = doNothing;
  1640. copiersUse[(OM_STR_CONST << 4) | STACK_STRING] = copyStringUse;
  1641. copiersUse[(OM_INT << 4) | STACK_FLOAT] = copyFloatToIntUse;
  1642. copiersUse[(OM_INT << 4) | STACK_STRING] = copyStringToIntUse;
  1643. copiersUse[(OM_FLOAT << 4) | STACK_INT] = copyIntToFloatUse;
  1644. copiersUse[(OM_FLOAT << 4) | STACK_STRING] = copyStringToFloatUse;
  1645. copiersUse[(OM_STR_CONST << 4) | STACK_INT] = copyIntToStringUse;
  1646. copiersUse[(OM_STR_CONST << 4) | STACK_FLOAT] = copyFloatToStringUse;
  1647. /* @TODO:
  1648. converters[(OM_ENTITY << 4) | STACK_ENTITY] (ensure if subtype doesn't match, = NULL)
  1649. converters[(OM_OBJECT << 4) | STACK_OBJECT] (ensure if subtype doesn't match, = NULL)
  1650. converters[(OM_ARRAY << 4) | STACK_ARRAY]
  1651. converters[(OM_HASH << 4) | STACK_HASH]
  1652. @TODO: copiers, note that copying to an entity/object doesn't need
  1653. to be dereferenced if we choose to just not ref++ it in the first place!
  1654. copiersUse needs to always ++ref even if nothing changes (entity/object)
  1655. both types of copiers for array/hash ALWAYS create a new copy even if no change.
  1656. */
  1657. // Grabbers
  1658. grabbers[OM_INT] = grabInt;
  1659. grabbers[OM_FLOAT] = grabFloat;
  1660. grabbers[OM_STR_CONST] = grabStringConst;
  1661. // @TODO: OM_ALL
  1662. // @TODO: OM_ALL_OTHER
  1663. grabbers[OM_NOTHING] = grabNothing;
  1664. grabbers[OM_THIS] = grabThis;
  1665. // @TODO: OM_POINTER?
  1666. grabbersUse[OM_INT] = grabIntUse;
  1667. grabbersUse[OM_FLOAT] = grabFloatUse;
  1668. grabbersUse[OM_STR_CONST] = grabStringUse;
  1669. // @TODO: OM_ALL
  1670. // @TODO: OM_ALL_OTHER
  1671. grabbersUse[OM_NOTHING] = grabNothingUse;
  1672. grabbersUse[OM_THIS] = grabThisUse;
  1673. // @TODO: OM_POINTER?
  1674. for (int i = OM_STACK; i < OM_STACK + OM_BASETYPE; ++i) {
  1675. grabbersStore[i] = grabStackConvertStore;
  1676. grabbersWrite[i] = grabStackWrite;
  1677. }
  1678. for (int i = OM_LOCAL; i < OM_LOCAL + OM_BASETYPE; ++i) {
  1679. grabbersStore[i] = grabLocalConvertStore;
  1680. grabbersWrite[i] = grabLocalWrite;
  1681. }
  1682. for (int i = OM_GLOBAL; i < OM_GLOBAL + OM_BASETYPE; ++i) {
  1683. grabbersStore[i] = interpretError; // @TODO: global+convert-in-place
  1684. grabbersWrite[i] = interpretError; // @TODO: global+convert-in-place
  1685. }
  1686. for (int i = OM_POP + OM_NO_CONVERT; i < OM_POP + OM_NO_CONVERT + OM_BASETYPE; ++i) {
  1687. grabbers[i] = grabPop;
  1688. grabbersUse[i] = grabPopUse;
  1689. }
  1690. grabbers[OM_POP + OM_NO_CONVERT + OM_INT] = grabPopInt;
  1691. grabbers[OM_POP + OM_NO_CONVERT + OM_FLOAT] = grabPopFloat;
  1692. // @TODO: specialized POP+ConstStr (shouldn't be able to have POP+Str)
  1693. for (int i = OM_STACK + OM_NO_CONVERT; i < OM_STACK + OM_NO_CONVERT + OM_BASETYPE; ++i) {
  1694. grabbers[i] = grabStack;
  1695. grabbersStore[i] = grabStackStore;
  1696. grabbersWrite[i] = grabStackWrite;
  1697. grabbersUse[i] = grabStackUse;
  1698. }
  1699. grabbers[OM_STACK + OM_NO_CONVERT + OM_INT] = grabStackInt;
  1700. grabbers[OM_STACK + OM_NO_CONVERT + OM_FLOAT] = grabStackFloat;
  1701. grabbersUse[OM_STACK + OM_NO_CONVERT + OM_INT] = grabStackNumUse;
  1702. grabbersUse[OM_STACK + OM_NO_CONVERT + OM_FLOAT] = grabStackNumUse;
  1703. grabbersWrite[OM_STACK + OM_NO_CONVERT + OM_INT] = grabStackNumWrite;
  1704. grabbersWrite[OM_STACK + OM_NO_CONVERT + OM_FLOAT] = grabStackNumWrite;
  1705. for (int i = OM_LOCAL + OM_NO_CONVERT; i < OM_LOCAL + OM_NO_CONVERT + OM_BASETYPE; ++i) {
  1706. grabbers[i] = grabLocal;
  1707. grabbersStore[i] = grabLocalStore;
  1708. grabbersWrite[i] = grabLocalWrite;
  1709. grabbersUse[i] = grabLocalUse;
  1710. }
  1711. grabbers[OM_LOCAL + OM_NO_CONVERT + OM_INT] = grabLocalInt;
  1712. grabbers[OM_LOCAL + OM_NO_CONVERT + OM_FLOAT] = grabLocalFloat;
  1713. grabbersUse[OM_LOCAL + OM_NO_CONVERT + OM_INT] = grabLocalNumUse;
  1714. grabbersUse[OM_LOCAL + OM_NO_CONVERT + OM_FLOAT] = grabLocalNumUse;
  1715. grabbersWrite[OM_LOCAL + OM_NO_CONVERT + OM_INT] = grabLocalNumWrite;
  1716. grabbersWrite[OM_LOCAL + OM_NO_CONVERT + OM_FLOAT] = grabLocalNumWrite;
  1717. for (int i = OM_GLOBAL + OM_NO_CONVERT; i < OM_GLOBAL + OM_NO_CONVERT + OM_BASETYPE; ++i) {
  1718. grabbers[i] = interpretError; // @TODO: global+no-convert
  1719. grabbersStore[i] = interpretError; // @TODO: global+no-convert
  1720. grabbersWrite[i] = interpretError; // @TODO: global+no-convert
  1721. grabbersUse[i] = interpretError; // @TODO: global+no-convert
  1722. }
  1723. // @TODO: global+no-convert+int/float
  1724. for (int i = OM_POP + OM_COPY; i < OM_POP + OM_COPY + OM_BASETYPE; ++i) {
  1725. grabbers[i] = grabPopCopy;
  1726. grabbersUse[i] = grabPopCopyUse;
  1727. }
  1728. for (int i = OM_STACK + OM_COPY; i < OM_STACK + OM_COPY + OM_BASETYPE; ++i) {
  1729. grabbers[i] = grabStackCopy;
  1730. grabbersUse[i] = grabStackCopyUse;
  1731. }
  1732. for (int i = OM_LOCAL + OM_COPY; i < OM_LOCAL + OM_COPY + OM_BASETYPE; ++i) {
  1733. grabbers[i] = grabLocalCopy;
  1734. grabbersUse[i] = grabLocalCopyUse;
  1735. }
  1736. for (int i = OM_GLOBAL + OM_COPY; i < OM_GLOBAL + OM_COPY + OM_BASETYPE; ++i) {
  1737. grabbers[i] = interpretError; // @TODO: global+copy-convert
  1738. grabbersUse[i] = interpretError; // @TODO: global+copy-convert
  1739. }
  1740. /* @TODO: indirects (unsure which modes will be needed yet)
  1741. for (int i = OM_POP + OM_INDIRECT; i < OM_POP + OM_INDIRECT + OM_BASETYPE; ++i) {
  1742. grabbers[i] = interpretError;
  1743. grabbersStore[i] = interpretError;
  1744. grabbersWrite[i] = interpretError;
  1745. grabbersUse[i] = interpretError;
  1746. }
  1747. for (int i = OM_STACK + OM_INDIRECT; i < OM_STACK + OM_INDIRECT + OM_BASETYPE; ++i) {
  1748. grabbers[i] = interpretError;
  1749. grabbersStore[i] = interpretError;
  1750. grabbersWrite[i] = interpretError;
  1751. grabbersUse[i] = interpretError;
  1752. }
  1753. */
  1754. // Extractors
  1755. for (int i = 0; i < 256; i += 16) {
  1756. extractors[i + OM_INT] = extractInt;
  1757. extractors[i + OM_FLOAT] = extractFloat;
  1758. // (should never occur) extractors[i + OM_STR] = extractStringConst;
  1759. extractors[i + OM_STR_CONST] = extractStringConst;
  1760. extractors[i + OM_ARRAY] = extractArray;
  1761. extractors[i + OM_HASH] = extractHash;
  1762. extractors[i + OM_ENTITY] = extractEntity;
  1763. extractors[i + OM_OBJECT] = extractObject;
  1764. }
  1765. // Opcodes
  1766. opcodes[OP_NOOP] = op_noop;
  1767. opcodes[OP_ADD] = op_addI;
  1768. opcodes[OP_ADDf] = op_addF;
  1769. opcodes[OP_AND] = op_andI;
  1770. opcodes[OP_CONCAT] = op_concatS;
  1771. opcodes[OP_CONVERT] = op_convert;
  1772. opcodes[OP_CREATEa] = interpretError; // @TODO:
  1773. opcodes[OP_CREATEe] = op_createE;
  1774. opcodes[OP_CREATEh] = interpretError; // @TODO:
  1775. opcodes[OP_CREATEo] = op_createO;
  1776. opcodes[OP_DEBUG] = Entity::op_debug;
  1777. opcodes[OP_DISCARD] = op_discard;
  1778. opcodes[OP_DISCARDL] = op_discardl;
  1779. opcodes[OP_DIV] = op_divI;
  1780. opcodes[OP_DIVf] = op_divF;
  1781. opcodes[OP_EQ] = op_eqI;
  1782. opcodes[OP_EQf] = op_eqF;
  1783. opcodes[OP_EQo] = op_eqO;
  1784. opcodes[OP_EQs] = op_eqS;
  1785. opcodes[OP_GE] = op_geI;
  1786. opcodes[OP_GEf] = op_geF;
  1787. opcodes[OP_GEs] = op_geS;
  1788. opcodes[OP_GT] = op_gtI;
  1789. opcodes[OP_GTf] = op_gtF;
  1790. opcodes[OP_GTs] = op_gtS;
  1791. opcodes[OP_IFFALSE] = op_iffalseI;
  1792. opcodes[OP_IFFALSEa] = interpretError; // @TODO:
  1793. opcodes[OP_IFFALSEf] = op_iffalseF;
  1794. opcodes[OP_IFFALSEh] = interpretError; // @TODO:
  1795. opcodes[OP_IFFALSEo] = op_iffalseO;
  1796. opcodes[OP_IFFALSEs] = op_iffalseS;
  1797. opcodes[OP_IFFALSEv] = interpretError; // @TODO:
  1798. opcodes[OP_IFTRUE] = op_iftrueI;
  1799. opcodes[OP_IFTRUEa] = interpretError; // @TODO:
  1800. opcodes[OP_IFTRUEf] = op_iftrueF;
  1801. opcodes[OP_IFTRUEh] = interpretError; // @TODO:
  1802. opcodes[OP_IFTRUEo] = op_iftrueO;
  1803. opcodes[OP_IFTRUEs] = op_iftrueS;
  1804. opcodes[OP_IFTRUEv] = interpretError; // @TODO:
  1805. opcodes[OP_INIT] = Entity::op_init;
  1806. opcodes[OP_JUMP] = op_jump;
  1807. opcodes[OP_LE] = op_leI;
  1808. opcodes[OP_LEf] = op_leF;
  1809. opcodes[OP_LEs] = op_leS;
  1810. opcodes[OP_LT] = op_ltI;
  1811. opcodes[OP_LTf] = op_ltF;
  1812. opcodes[OP_LTs] = op_ltS;
  1813. opcodes[OP_MOD] = op_modI;
  1814. opcodes[OP_MULT] = op_multI;
  1815. opcodes[OP_MULTf] = op_multF;
  1816. opcodes[OP_NE] = op_neI;
  1817. opcodes[OP_NEf] = op_neF;
  1818. opcodes[OP_NEo] = op_neO;
  1819. opcodes[OP_NEs] = op_neS;
  1820. opcodes[OP_OR] = op_orI;
  1821. opcodes[OP_PUSH] = op_pushI;
  1822. opcodes[OP_PUSHa] = op_pushAHO;
  1823. opcodes[OP_PUSHf] = op_pushF;
  1824. opcodes[OP_PUSHh] = op_pushAHO;
  1825. opcodes[OP_PUSHo] = op_pushAHO;
  1826. opcodes[OP_PUSHs] = op_pushS;
  1827. opcodes[OP_PUSHv] = interpretError; // @TODO:
  1828. opcodes[OP_RET] = Entity::op_ret;
  1829. opcodes[OP_SHIFTL] = op_shiftlI;
  1830. opcodes[OP_SHIFTR] = op_shiftrI;
  1831. opcodes[OP_STOP] = Entity::op_stop;
  1832. opcodes[OP_STORE] = op_storeI;
  1833. opcodes[OP_STOREa] = op_storeA;
  1834. opcodes[OP_STOREf] = op_storeF;
  1835. opcodes[OP_STOREh] = op_storeH;
  1836. opcodes[OP_STOREo] = op_storeO;
  1837. opcodes[OP_STOREs] = op_storeS;
  1838. opcodes[OP_STOREv] = interpretError; // @TODO:
  1839. opcodes[OP_SUB] = op_subI;
  1840. opcodes[OP_SUBf] = op_subF;
  1841. opcodes[OP_SUBR] = op_subr;
  1842. opcodes[OP_XOR] = op_xorI;
  1843. opcodes[OP_GETe] = op_getE;
  1844. opcodes[OP_SETe] = op_setE;
  1845. opcodes[OP_GETo] = op_getO;
  1846. opcodes[OP_SETo] = op_setO;
  1847. opcodes[OP_IDLE] = Entity::op_idle;
  1848. opcodes[OP_RETVOID] = Entity::op_retvoid;
  1849. opcodes[OP_SETef] = op_setEF;
  1850. opcodes[OP_SETei] = op_setEI;
  1851. opcodes[OP_SETof] = op_setOF;
  1852. opcodes[OP_SEToi] = op_setOI;
  1853. // Empty operands
  1854. emptyOperand[0].data.i = 0;
  1855. emptyOperand[0].type = STACK_INT;
  1856. emptyOperand[1].data.f = 0.0;
  1857. emptyOperand[1].type = STACK_FLOAT;
  1858. emptyOperand[2].data.p = NULL;
  1859. emptyOperand[2].type = STACK_ENTITY;
  1860. emptyOperand[3].data.p = NULL;
  1861. emptyOperand[3].type = STACK_OBJECT;
  1862. // Init deref array
  1863. for (int i = 0; i < MAX_TODEREF; ++i) {
  1864. toDeref[i].data.i = 0;
  1865. toDeref[i].type = STACK_INT;
  1866. }
  1867. }
  1868. void interpreterCleanup() { start_func
  1869. // Clear deref array
  1870. for (int i = 0; i < MAX_TODEREF; ++i) {
  1871. dereferencers[toDeref[i].type](toDeref + i);
  1872. toDeref[i].data.i = 0;
  1873. toDeref[i].type = STACK_INT;
  1874. }
  1875. }