00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "vm_local.h"
00023
00024 #ifdef DEBUG_VM // bk001204
00025 static char *opnames[256] = {
00026 "OP_UNDEF",
00027
00028 "OP_IGNORE",
00029
00030 "OP_BREAK",
00031
00032 "OP_ENTER",
00033 "OP_LEAVE",
00034 "OP_CALL",
00035 "OP_PUSH",
00036 "OP_POP",
00037
00038 "OP_CONST",
00039
00040 "OP_LOCAL",
00041
00042 "OP_JUMP",
00043
00044
00045
00046 "OP_EQ",
00047 "OP_NE",
00048
00049 "OP_LTI",
00050 "OP_LEI",
00051 "OP_GTI",
00052 "OP_GEI",
00053
00054 "OP_LTU",
00055 "OP_LEU",
00056 "OP_GTU",
00057 "OP_GEU",
00058
00059 "OP_EQF",
00060 "OP_NEF",
00061
00062 "OP_LTF",
00063 "OP_LEF",
00064 "OP_GTF",
00065 "OP_GEF",
00066
00067
00068
00069 "OP_LOAD1",
00070 "OP_LOAD2",
00071 "OP_LOAD4",
00072 "OP_STORE1",
00073 "OP_STORE2",
00074 "OP_STORE4",
00075 "OP_ARG",
00076
00077 "OP_BLOCK_COPY",
00078
00079
00080
00081 "OP_SEX8",
00082 "OP_SEX16",
00083
00084 "OP_NEGI",
00085 "OP_ADD",
00086 "OP_SUB",
00087 "OP_DIVI",
00088 "OP_DIVU",
00089 "OP_MODI",
00090 "OP_MODU",
00091 "OP_MULI",
00092 "OP_MULU",
00093
00094 "OP_BAND",
00095 "OP_BOR",
00096 "OP_BXOR",
00097 "OP_BCOM",
00098
00099 "OP_LSH",
00100 "OP_RSHI",
00101 "OP_RSHU",
00102
00103 "OP_NEGF",
00104 "OP_ADDF",
00105 "OP_SUBF",
00106 "OP_DIVF",
00107 "OP_MULF",
00108
00109 "OP_CVIF",
00110 "OP_CVFI"
00111 };
00112 #endif
00113
00114 #if idppc
00115 #if defined(__GNUC__)
00116 static inline unsigned int loadWord(void *addr) {
00117 unsigned int word;
00118
00119 asm("lwbrx %0,0,%1" : "=r" (word) : "r" (addr));
00120 return word;
00121 }
00122 #else
00123 #define loadWord(addr) __lwbrx(addr,0)
00124 #endif
00125 #else
00126 #define loadWord(addr) *((int *)addr)
00127 #endif
00128
00129 char *VM_Indent( vm_t *vm ) {
00130 static char *string = " ";
00131 if ( vm->callLevel > 20 ) {
00132 return string;
00133 }
00134 return string + 2 * ( 20 - vm->callLevel );
00135 }
00136
00137 void VM_StackTrace( vm_t *vm, int programCounter, int programStack ) {
00138 int count;
00139
00140 count = 0;
00141 do {
00142 Com_Printf( "%s\n", VM_ValueToSymbol( vm, programCounter ) );
00143 programStack = *(int *)&vm->dataBase[programStack+4];
00144 programCounter = *(int *)&vm->dataBase[programStack];
00145 } while ( programCounter != -1 && ++count < 32 );
00146
00147 }
00148
00149
00150
00151
00152
00153
00154
00155 void VM_PrepareInterpreter( vm_t *vm, vmHeader_t *header ) {
00156 int op;
00157 int pc;
00158 byte *code;
00159 int instruction;
00160 int *codeBase;
00161
00162 vm->codeBase = Hunk_Alloc( vm->codeLength*4, h_high );
00163
00164
00165
00166
00167 pc = 0;
00168 instruction = 0;
00169 code = (byte *)header + header->codeOffset;
00170 codeBase = (int *)vm->codeBase;
00171
00172 while ( instruction < header->instructionCount ) {
00173 vm->instructionPointers[ instruction ] = pc;
00174 instruction++;
00175
00176 op = code[ pc ];
00177 codeBase[pc] = op;
00178 if ( pc > header->codeLength ) {
00179 Com_Error( ERR_FATAL, "VM_PrepareInterpreter: pc > header->codeLength" );
00180 }
00181
00182 pc++;
00183
00184
00185 switch ( op ) {
00186 case OP_ENTER:
00187 case OP_CONST:
00188 case OP_LOCAL:
00189 case OP_LEAVE:
00190 case OP_EQ:
00191 case OP_NE:
00192 case OP_LTI:
00193 case OP_LEI:
00194 case OP_GTI:
00195 case OP_GEI:
00196 case OP_LTU:
00197 case OP_LEU:
00198 case OP_GTU:
00199 case OP_GEU:
00200 case OP_EQF:
00201 case OP_NEF:
00202 case OP_LTF:
00203 case OP_LEF:
00204 case OP_GTF:
00205 case OP_GEF:
00206 case OP_BLOCK_COPY:
00207 codeBase[pc+0] = loadWord(&code[pc]);
00208 pc += 4;
00209 break;
00210 case OP_ARG:
00211 codeBase[pc+0] = code[pc];
00212 pc += 1;
00213 break;
00214 default:
00215 break;
00216 }
00217
00218 }
00219 pc = 0;
00220 instruction = 0;
00221 code = (byte *)header + header->codeOffset;
00222 codeBase = (int *)vm->codeBase;
00223
00224 while ( instruction < header->instructionCount ) {
00225 op = code[ pc ];
00226 instruction++;
00227 pc++;
00228 switch ( op ) {
00229 case OP_ENTER:
00230 case OP_CONST:
00231 case OP_LOCAL:
00232 case OP_LEAVE:
00233 case OP_EQ:
00234 case OP_NE:
00235 case OP_LTI:
00236 case OP_LEI:
00237 case OP_GTI:
00238 case OP_GEI:
00239 case OP_LTU:
00240 case OP_LEU:
00241 case OP_GTU:
00242 case OP_GEU:
00243 case OP_EQF:
00244 case OP_NEF:
00245 case OP_LTF:
00246 case OP_LEF:
00247 case OP_GTF:
00248 case OP_GEF:
00249 case OP_BLOCK_COPY:
00250 switch(op) {
00251 case OP_EQ:
00252 case OP_NE:
00253 case OP_LTI:
00254 case OP_LEI:
00255 case OP_GTI:
00256 case OP_GEI:
00257 case OP_LTU:
00258 case OP_LEU:
00259 case OP_GTU:
00260 case OP_GEU:
00261 case OP_EQF:
00262 case OP_NEF:
00263 case OP_LTF:
00264 case OP_LEF:
00265 case OP_GTF:
00266 case OP_GEF:
00267 codeBase[pc] = vm->instructionPointers[codeBase[pc]];
00268 break;
00269 default:
00270 break;
00271 }
00272 pc += 4;
00273 break;
00274 case OP_ARG:
00275 pc += 1;
00276 break;
00277 default:
00278 break;
00279 }
00280
00281 }
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 #define MAX_STACK 256
00308 #define STACK_MASK (MAX_STACK-1)
00309
00310
00311 #define DEBUGSTR va("%s%i", VM_Indent(vm), opStack-stack )
00312
00313 int VM_CallInterpreted( vm_t *vm, int *args ) {
00314 int stack[MAX_STACK];
00315 int *opStack;
00316 int programCounter;
00317 int programStack;
00318 int stackOnEntry;
00319 byte *image;
00320 int *codeImage;
00321 int v1;
00322 int dataMask;
00323 #ifdef DEBUG_VM
00324 vmSymbol_t *profileSymbol;
00325 #endif
00326
00327
00328 vm->currentlyInterpreting = qtrue;
00329
00330
00331 programStack = stackOnEntry = vm->programStack;
00332
00333 #ifdef DEBUG_VM
00334 profileSymbol = VM_ValueToFunctionSymbol( vm, 0 );
00335
00336 vm->breakFunction = 0;
00337 #endif
00338
00339
00340 image = vm->dataBase;
00341 codeImage = (int *)vm->codeBase;
00342 dataMask = vm->dataMask;
00343
00344
00345
00346
00347 opStack = stack;
00348 programCounter = 0;
00349
00350 programStack -= 48;
00351
00352 *(int *)&image[ programStack + 44] = args[9];
00353 *(int *)&image[ programStack + 40] = args[8];
00354 *(int *)&image[ programStack + 36] = args[7];
00355 *(int *)&image[ programStack + 32] = args[6];
00356 *(int *)&image[ programStack + 28] = args[5];
00357 *(int *)&image[ programStack + 24] = args[4];
00358 *(int *)&image[ programStack + 20] = args[3];
00359 *(int *)&image[ programStack + 16] = args[2];
00360 *(int *)&image[ programStack + 12] = args[1];
00361 *(int *)&image[ programStack + 8 ] = args[0];
00362 *(int *)&image[ programStack + 4 ] = 0;
00363 *(int *)&image[ programStack ] = -1;
00364
00365 vm->callLevel = 0;
00366
00367 VM_Debug(0);
00368
00369
00370
00371
00372
00373 #define r2 codeImage[programCounter]
00374
00375 while ( 1 ) {
00376 int opcode, r0, r1;
00377
00378
00379 nextInstruction:
00380 r0 = ((int *)opStack)[0];
00381 r1 = ((int *)opStack)[-1];
00382 nextInstruction2:
00383 opcode = codeImage[ programCounter++ ];
00384 #ifdef DEBUG_VM
00385 if ( (unsigned)programCounter > vm->codeLength ) {
00386 Com_Error( ERR_DROP, "VM pc out of range" );
00387 }
00388
00389 if ( opStack < stack ) {
00390 Com_Error( ERR_DROP, "VM opStack underflow" );
00391 }
00392 if ( opStack >= stack+MAX_STACK ) {
00393 Com_Error( ERR_DROP, "VM opStack overflow" );
00394 }
00395
00396 if ( programStack <= vm->stackBottom ) {
00397 Com_Error( ERR_DROP, "VM stack overflow" );
00398 }
00399
00400 if ( programStack & 3 ) {
00401 Com_Error( ERR_DROP, "VM program stack misaligned" );
00402 }
00403
00404 if ( vm_debugLevel > 1 ) {
00405 Com_Printf( "%s %s\n", DEBUGSTR, opnames[opcode] );
00406 }
00407 profileSymbol->profileCount++;
00408 #endif
00409
00410 switch ( opcode ) {
00411 #ifdef DEBUG_VM
00412 default:
00413 Com_Error( ERR_DROP, "Bad VM instruction" );
00414 #endif
00415 case OP_BREAK:
00416 vm->breakCount++;
00417 goto nextInstruction2;
00418 case OP_CONST:
00419 opStack++;
00420 r1 = r0;
00421 r0 = *opStack = r2;
00422
00423 programCounter += 4;
00424 goto nextInstruction2;
00425 case OP_LOCAL:
00426 opStack++;
00427 r1 = r0;
00428 r0 = *opStack = r2+programStack;
00429
00430 programCounter += 4;
00431 goto nextInstruction2;
00432
00433 case OP_LOAD4:
00434 #ifdef DEBUG_VM
00435 if ( *opStack & 3 ) {
00436 Com_Error( ERR_DROP, "OP_LOAD4 misaligned" );
00437 }
00438 #endif
00439 r0 = *opStack = *(int *)&image[ r0&dataMask ];
00440 goto nextInstruction2;
00441 case OP_LOAD2:
00442 r0 = *opStack = *(unsigned short *)&image[ r0&dataMask ];
00443 goto nextInstruction2;
00444 case OP_LOAD1:
00445 r0 = *opStack = image[ r0&dataMask ];
00446 goto nextInstruction2;
00447
00448 case OP_STORE4:
00449 *(int *)&image[ r1&(dataMask & ~3) ] = r0;
00450 opStack -= 2;
00451 goto nextInstruction;
00452 case OP_STORE2:
00453 *(short *)&image[ r1&(dataMask & ~1) ] = r0;
00454 opStack -= 2;
00455 goto nextInstruction;
00456 case OP_STORE1:
00457 image[ r1&dataMask ] = r0;
00458 opStack -= 2;
00459 goto nextInstruction;
00460
00461 case OP_ARG:
00462
00463 *(int *)&image[ codeImage[programCounter] + programStack ] = r0;
00464 opStack--;
00465 programCounter += 1;
00466 goto nextInstruction;
00467
00468 case OP_BLOCK_COPY:
00469 {
00470 int *src, *dest;
00471 int i, count, srci, desti;
00472
00473 count = r2;
00474
00475 srci = r0 & dataMask;
00476 desti = r1 & dataMask;
00477 count = ((srci + count) & dataMask) - srci;
00478 count = ((desti + count) & dataMask) - desti;
00479
00480 src = (int *)&image[ r0&dataMask ];
00481 dest = (int *)&image[ r1&dataMask ];
00482 if ( ( (int)src | (int)dest | count ) & 3 ) {
00483 Com_Error( ERR_DROP, "OP_BLOCK_COPY not dword aligned" );
00484 }
00485 count >>= 2;
00486 for ( i = count-1 ; i>= 0 ; i-- ) {
00487 dest[i] = src[i];
00488 }
00489 programCounter += 4;
00490 opStack -= 2;
00491 }
00492 goto nextInstruction;
00493
00494 case OP_CALL:
00495
00496 *(int *)&image[ programStack ] = programCounter;
00497
00498
00499 programCounter = r0;
00500 opStack--;
00501 if ( programCounter < 0 ) {
00502
00503 int r;
00504 int temp;
00505 #ifdef DEBUG_VM
00506 int stomped;
00507
00508 if ( vm_debugLevel ) {
00509 Com_Printf( "%s---> systemcall(%i)\n", DEBUGSTR, -1 - programCounter );
00510 }
00511 #endif
00512
00513 temp = vm->callLevel;
00514 vm->programStack = programStack - 4;
00515 #ifdef DEBUG_VM
00516 stomped = *(int *)&image[ programStack + 4 ];
00517 #endif
00518 *(int *)&image[ programStack + 4 ] = -1 - programCounter;
00519
00520
00521 r = vm->systemCall( (int *)&image[ programStack + 4 ] );
00522
00523 #ifdef DEBUG_VM
00524
00525
00526 *(int *)&image[ programStack + 4 ] = stomped;
00527 #endif
00528
00529
00530 opStack++;
00531 *opStack = r;
00532 programCounter = *(int *)&image[ programStack ];
00533 vm->callLevel = temp;
00534 #ifdef DEBUG_VM
00535 if ( vm_debugLevel ) {
00536 Com_Printf( "%s<--- %s\n", DEBUGSTR, VM_ValueToSymbol( vm, programCounter ) );
00537 }
00538 #endif
00539 } else {
00540 programCounter = vm->instructionPointers[ programCounter ];
00541 }
00542 goto nextInstruction;
00543
00544
00545 case OP_PUSH:
00546 opStack++;
00547 goto nextInstruction;
00548 case OP_POP:
00549 opStack--;
00550 goto nextInstruction;
00551
00552 case OP_ENTER:
00553 #ifdef DEBUG_VM
00554 profileSymbol = VM_ValueToFunctionSymbol( vm, programCounter );
00555 #endif
00556
00557 v1 = r2;
00558
00559 programCounter += 4;
00560 programStack -= v1;
00561 #ifdef DEBUG_VM
00562
00563 *(int *)&image[programStack+4] = programStack + v1;
00564 if ( vm_debugLevel ) {
00565 Com_Printf( "%s---> %s\n", DEBUGSTR, VM_ValueToSymbol( vm, programCounter - 5 ) );
00566 if ( vm->breakFunction && programCounter - 5 == vm->breakFunction ) {
00567
00568 vm->breakCount++;
00569
00570
00571 }
00572 vm->callLevel++;
00573 }
00574 #endif
00575 goto nextInstruction;
00576 case OP_LEAVE:
00577
00578 v1 = r2;
00579
00580 programStack += v1;
00581
00582
00583 programCounter = *(int *)&image[ programStack ];
00584 #ifdef DEBUG_VM
00585 profileSymbol = VM_ValueToFunctionSymbol( vm, programCounter );
00586 if ( vm_debugLevel ) {
00587 vm->callLevel--;
00588 Com_Printf( "%s<--- %s\n", DEBUGSTR, VM_ValueToSymbol( vm, programCounter ) );
00589 }
00590 #endif
00591
00592 if ( programCounter == -1 ) {
00593 goto done;
00594 }
00595 goto nextInstruction;
00596
00597
00598
00599
00600
00601
00602
00603 case OP_JUMP:
00604 programCounter = r0;
00605 programCounter = vm->instructionPointers[ programCounter ];
00606 opStack--;
00607 goto nextInstruction;
00608
00609 case OP_EQ:
00610 opStack -= 2;
00611 if ( r1 == r0 ) {
00612 programCounter = r2;
00613 goto nextInstruction;
00614 } else {
00615 programCounter += 4;
00616 goto nextInstruction;
00617 }
00618
00619 case OP_NE:
00620 opStack -= 2;
00621 if ( r1 != r0 ) {
00622 programCounter = r2;
00623 goto nextInstruction;
00624 } else {
00625 programCounter += 4;
00626 goto nextInstruction;
00627 }
00628
00629 case OP_LTI:
00630 opStack -= 2;
00631 if ( r1 < r0 ) {
00632 programCounter = r2;
00633 goto nextInstruction;
00634 } else {
00635 programCounter += 4;
00636 goto nextInstruction;
00637 }
00638
00639 case OP_LEI:
00640 opStack -= 2;
00641 if ( r1 <= r0 ) {
00642 programCounter = r2;
00643 goto nextInstruction;
00644 } else {
00645 programCounter += 4;
00646 goto nextInstruction;
00647 }
00648
00649 case OP_GTI:
00650 opStack -= 2;
00651 if ( r1 > r0 ) {
00652 programCounter = r2;
00653 goto nextInstruction;
00654 } else {
00655 programCounter += 4;
00656 goto nextInstruction;
00657 }
00658
00659 case OP_GEI:
00660 opStack -= 2;
00661 if ( r1 >= r0 ) {
00662 programCounter = r2;
00663 goto nextInstruction;
00664 } else {
00665 programCounter += 4;
00666 goto nextInstruction;
00667 }
00668
00669 case OP_LTU:
00670 opStack -= 2;
00671 if ( ((unsigned)r1) < ((unsigned)r0) ) {
00672 programCounter = r2;
00673 goto nextInstruction;
00674 } else {
00675 programCounter += 4;
00676 goto nextInstruction;
00677 }
00678
00679 case OP_LEU:
00680 opStack -= 2;
00681 if ( ((unsigned)r1) <= ((unsigned)r0) ) {
00682 programCounter = r2;
00683 goto nextInstruction;
00684 } else {
00685 programCounter += 4;
00686 goto nextInstruction;
00687 }
00688
00689 case OP_GTU:
00690 opStack -= 2;
00691 if ( ((unsigned)r1) > ((unsigned)r0) ) {
00692 programCounter = r2;
00693 goto nextInstruction;
00694 } else {
00695 programCounter += 4;
00696 goto nextInstruction;
00697 }
00698
00699 case OP_GEU:
00700 opStack -= 2;
00701 if ( ((unsigned)r1) >= ((unsigned)r0) ) {
00702 programCounter = r2;
00703 goto nextInstruction;
00704 } else {
00705 programCounter += 4;
00706 goto nextInstruction;
00707 }
00708
00709 case OP_EQF:
00710 if ( ((float *)opStack)[-1] == *(float *)opStack ) {
00711 programCounter = r2;
00712 opStack -= 2;
00713 goto nextInstruction;
00714 } else {
00715 programCounter += 4;
00716 opStack -= 2;
00717 goto nextInstruction;
00718 }
00719
00720 case OP_NEF:
00721 if ( ((float *)opStack)[-1] != *(float *)opStack ) {
00722 programCounter = r2;
00723 opStack -= 2;
00724 goto nextInstruction;
00725 } else {
00726 programCounter += 4;
00727 opStack -= 2;
00728 goto nextInstruction;
00729 }
00730
00731 case OP_LTF:
00732 if ( ((float *)opStack)[-1] < *(float *)opStack ) {
00733 programCounter = r2;
00734 opStack -= 2;
00735 goto nextInstruction;
00736 } else {
00737 programCounter += 4;
00738 opStack -= 2;
00739 goto nextInstruction;
00740 }
00741
00742 case OP_LEF:
00743 if ( ((float *)opStack)[-1] <= *(float *)opStack ) {
00744 programCounter = r2;
00745 opStack -= 2;
00746 goto nextInstruction;
00747 } else {
00748 programCounter += 4;
00749 opStack -= 2;
00750 goto nextInstruction;
00751 }
00752
00753 case OP_GTF:
00754 if ( ((float *)opStack)[-1] > *(float *)opStack ) {
00755 programCounter = r2;
00756 opStack -= 2;
00757 goto nextInstruction;
00758 } else {
00759 programCounter += 4;
00760 opStack -= 2;
00761 goto nextInstruction;
00762 }
00763
00764 case OP_GEF:
00765 if ( ((float *)opStack)[-1] >= *(float *)opStack ) {
00766 programCounter = r2;
00767 opStack -= 2;
00768 goto nextInstruction;
00769 } else {
00770 programCounter += 4;
00771 opStack -= 2;
00772 goto nextInstruction;
00773 }
00774
00775
00776
00777
00778 case OP_NEGI:
00779 *opStack = -r0;
00780 goto nextInstruction;
00781 case OP_ADD:
00782 opStack[-1] = r1 + r0;
00783 opStack--;
00784 goto nextInstruction;
00785 case OP_SUB:
00786 opStack[-1] = r1 - r0;
00787 opStack--;
00788 goto nextInstruction;
00789 case OP_DIVI:
00790 opStack[-1] = r1 / r0;
00791 opStack--;
00792 goto nextInstruction;
00793 case OP_DIVU:
00794 opStack[-1] = ((unsigned)r1) / ((unsigned)r0);
00795 opStack--;
00796 goto nextInstruction;
00797 case OP_MODI:
00798 opStack[-1] = r1 % r0;
00799 opStack--;
00800 goto nextInstruction;
00801 case OP_MODU:
00802 opStack[-1] = ((unsigned)r1) % (unsigned)r0;
00803 opStack--;
00804 goto nextInstruction;
00805 case OP_MULI:
00806 opStack[-1] = r1 * r0;
00807 opStack--;
00808 goto nextInstruction;
00809 case OP_MULU:
00810 opStack[-1] = ((unsigned)r1) * ((unsigned)r0);
00811 opStack--;
00812 goto nextInstruction;
00813
00814 case OP_BAND:
00815 opStack[-1] = ((unsigned)r1) & ((unsigned)r0);
00816 opStack--;
00817 goto nextInstruction;
00818 case OP_BOR:
00819 opStack[-1] = ((unsigned)r1) | ((unsigned)r0);
00820 opStack--;
00821 goto nextInstruction;
00822 case OP_BXOR:
00823 opStack[-1] = ((unsigned)r1) ^ ((unsigned)r0);
00824 opStack--;
00825 goto nextInstruction;
00826 case OP_BCOM:
00827 opStack[-1] = ~ ((unsigned)r0);
00828 goto nextInstruction;
00829
00830 case OP_LSH:
00831 opStack[-1] = r1 << r0;
00832 opStack--;
00833 goto nextInstruction;
00834 case OP_RSHI:
00835 opStack[-1] = r1 >> r0;
00836 opStack--;
00837 goto nextInstruction;
00838 case OP_RSHU:
00839 opStack[-1] = ((unsigned)r1) >> r0;
00840 opStack--;
00841 goto nextInstruction;
00842
00843 case OP_NEGF:
00844 *(float *)opStack = -*(float *)opStack;
00845 goto nextInstruction;
00846 case OP_ADDF:
00847 *(float *)(opStack-1) = *(float *)(opStack-1) + *(float *)opStack;
00848 opStack--;
00849 goto nextInstruction;
00850 case OP_SUBF:
00851 *(float *)(opStack-1) = *(float *)(opStack-1) - *(float *)opStack;
00852 opStack--;
00853 goto nextInstruction;
00854 case OP_DIVF:
00855 *(float *)(opStack-1) = *(float *)(opStack-1) / *(float *)opStack;
00856 opStack--;
00857 goto nextInstruction;
00858 case OP_MULF:
00859 *(float *)(opStack-1) = *(float *)(opStack-1) * *(float *)opStack;
00860 opStack--;
00861 goto nextInstruction;
00862
00863 case OP_CVIF:
00864 *(float *)opStack = (float)*opStack;
00865 goto nextInstruction;
00866 case OP_CVFI:
00867 *opStack = (int) *(float *)opStack;
00868 goto nextInstruction;
00869 case OP_SEX8:
00870 *opStack = (signed char)*opStack;
00871 goto nextInstruction;
00872 case OP_SEX16:
00873 *opStack = (short)*opStack;
00874 goto nextInstruction;
00875 }
00876 }
00877
00878 done:
00879 vm->currentlyInterpreting = qfalse;
00880
00881 if ( opStack != &stack[1] ) {
00882 Com_Error( ERR_DROP, "Interpreter error: opStack = %i", opStack - stack );
00883 }
00884
00885 vm->programStack = stackOnEntry;
00886
00887
00888 return *opStack;
00889 }