Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

vm_interpreted.c File Reference

#include "vm_local.h"

Include dependency graph for vm_interpreted.c:

Include dependency graph

Go to the source code of this file.

Defines

#define DEBUGSTR   va("%s%i", VM_Indent(vm), opStack-stack )
#define loadWord(addr)   *((int *)addr)
#define MAX_STACK   256
#define r2   codeImage[programCounter]
#define STACK_MASK   (MAX_STACK-1)

Functions

int VM_CallInterpreted (vm_t *vm, int *args)
char * VM_Indent (vm_t *vm)
void VM_PrepareInterpreter (vm_t *vm, vmHeader_t *header)
void VM_StackTrace (vm_t *vm, int programCounter, int programStack)


Define Documentation

#define DEBUGSTR   va("%s%i", VM_Indent(vm), opStack-stack )
 

Definition at line 311 of file vm_interpreted.c.

Referenced by VM_CallInterpreted().

#define loadWord addr   )     *((int *)addr)
 

Definition at line 126 of file vm_interpreted.c.

Referenced by VM_PrepareInterpreter().

#define MAX_STACK   256
 

Definition at line 307 of file vm_interpreted.c.

#define r2   codeImage[programCounter]
 

Referenced by CG_DrawAreaPowerUp(), Display_CursorType(), f3(), and VM_CallInterpreted().

#define STACK_MASK   (MAX_STACK-1)
 

Definition at line 308 of file vm_interpreted.c.


Function Documentation

int VM_CallInterpreted vm_t vm,
int *  args
 

Definition at line 313 of file vm_interpreted.c.

References vm_s::breakCount, vm_s::breakFunction, byte, vm_s::callLevel, vm_s::codeBase, vm_s::codeLength, Com_Error(), Com_Printf(), count, vm_s::currentlyInterpreting, vm_s::dataBase, vm_s::dataMask, DEBUGSTR, ERR_DROP, i, vm_s::instructionPointers, OP_ADD, OP_ADDF, OP_ARG, OP_BAND, OP_BCOM, OP_BLOCK_COPY, OP_BOR, OP_BREAK, OP_BXOR, OP_CALL, OP_CONST, OP_CVFI, OP_CVIF, OP_DIVF, OP_DIVI, OP_DIVU, OP_ENTER, OP_EQ, OP_EQF, OP_GEF, OP_GEI, OP_GEU, OP_GTF, OP_GTI, OP_GTU, OP_JUMP, OP_LEAVE, OP_LEF, OP_LEI, OP_LEU, OP_LOAD1, OP_LOAD2, OP_LOAD4, OP_LOCAL, OP_LSH, OP_LTF, OP_LTI, OP_LTU, OP_MODI, OP_MODU, OP_MULF, OP_MULI, OP_MULU, OP_NE, OP_NEF, OP_NEGF, OP_NEGI, OP_POP, OP_PUSH, OP_RSHI, OP_RSHU, OP_SEX16, OP_SEX8, OP_STORE1, OP_STORE2, OP_STORE4, OP_SUB, OP_SUBF, vmSymbol_s::profileCount, vm_s::programStack, r, r2, src, vm_s::stackBottom, vm_s::systemCall, v1, VM_Debug(), vm_debugLevel, vm_t, VM_ValueToFunctionSymbol(), VM_ValueToSymbol(), and vmSymbol_t.

Referenced by VM_Call().

00313                                               {
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     // interpret the code
00328     vm->currentlyInterpreting = qtrue;
00329 
00330     // we might be called recursively, so this might not be the very top
00331     programStack = stackOnEntry = vm->programStack;
00332 
00333 #ifdef DEBUG_VM
00334     profileSymbol = VM_ValueToFunctionSymbol( vm, 0 );
00335     // uncomment this for debugging breakpoints
00336     vm->breakFunction = 0;
00337 #endif
00338     // set up the stack frame 
00339 
00340     image = vm->dataBase;
00341     codeImage = (int *)vm->codeBase;
00342     dataMask = vm->dataMask;
00343     
00344     // leave a free spot at start of stack so
00345     // that as long as opStack is valid, opStack-1 will
00346     // not corrupt anything
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; // return stack
00363     *(int *)&image[ programStack ] = -1;    // will terminate the loop on return
00364 
00365     vm->callLevel = 0;
00366     
00367     VM_Debug(0);
00368 
00369 //  vm_debugLevel=2;
00370     // main interpreter loop, will exit when a LEAVE instruction
00371     // grabs the -1 program counter
00372 
00373 #define r2 codeImage[programCounter]
00374 
00375     while ( 1 ) {
00376         int     opcode, r0, r1;
00377 //      unsigned int    r2;
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" );  // this should be scanned on load!
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             // single byte offset from programStack
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                 // MrE: copy range check
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             // save current program counter
00496             *(int *)&image[ programStack ] = programCounter;
00497             
00498             // jump to the location on the stack
00499             programCounter = r0;
00500             opStack--;
00501             if ( programCounter < 0 ) {
00502                 // system call
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                 // save the stack to allow recursive VM entry
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 //VM_LogSyscalls( (int *)&image[ programStack + 4 ] );
00521                 r = vm->systemCall( (int *)&image[ programStack + 4 ] );
00522 
00523 #ifdef DEBUG_VM
00524                 // this is just our stack frame pointer, only needed
00525                 // for debugging
00526                 *(int *)&image[ programStack + 4 ] = stomped;
00527 #endif
00528 
00529                 // save return value
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         // push and pop are only needed for discarded or bad function return values
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             // get size of stack frame
00557             v1 = r2;
00558 
00559             programCounter += 4;
00560             programStack -= v1;
00561 #ifdef DEBUG_VM
00562             // save old stack frame for debugging traces
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                     // this is to allow setting breakpoints here in the debugger
00568                     vm->breakCount++;
00569 //                  vm_debugLevel = 2;
00570 //                  VM_StackTrace( vm, programCounter, programStack );
00571                 }
00572                 vm->callLevel++;
00573             }
00574 #endif
00575             goto nextInstruction;
00576         case OP_LEAVE:
00577             // remove our stack frame
00578             v1 = r2;
00579 
00580             programStack += v1;
00581 
00582             // grab the saved program counter
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             // check for leaving the VM
00592             if ( programCounter == -1 ) {
00593                 goto done;
00594             }
00595             goto nextInstruction;
00596 
00597         /*
00598         ===================================================================
00599         BRANCHES
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;    //vm->instructionPointers[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;    //vm->instructionPointers[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;    //vm->instructionPointers[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;    //vm->instructionPointers[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;    //vm->instructionPointers[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;    //vm->instructionPointers[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;    //vm->instructionPointers[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;    //vm->instructionPointers[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;    //vm->instructionPointers[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;    //vm->instructionPointers[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;    //vm->instructionPointers[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;    //vm->instructionPointers[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;    //vm->instructionPointers[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;    //vm->instructionPointers[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;    //vm->instructionPointers[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;    //vm->instructionPointers[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     // return the result
00888     return *opStack;
00889 }

Here is the call graph for this function:

char* VM_Indent vm_t vm  ) 
 

Definition at line 129 of file vm_interpreted.c.

References vm_s::callLevel, string(), and vm_t.

00129                             {
00130     static char *string = "                                        ";
00131     if ( vm->callLevel > 20 ) {
00132         return string;
00133     }
00134     return string + 2 * ( 20 - vm->callLevel );
00135 }

Here is the call graph for this function:

void VM_PrepareInterpreter vm_t vm,
vmHeader_t header
 

Definition at line 155 of file vm_interpreted.c.

References byte, code, vm_s::codeBase, vm_s::codeLength, Com_Error(), ERR_FATAL, h_high, header, Hunk_Alloc(), vm_s::instructionPointers, loadWord, op, OP_ARG, OP_BLOCK_COPY, OP_CONST, OP_ENTER, OP_EQ, OP_EQF, OP_GEF, OP_GEI, OP_GEU, OP_GTF, OP_GTI, OP_GTU, OP_LEAVE, OP_LEF, OP_LEI, OP_LEU, OP_LOCAL, OP_LTF, OP_LTI, OP_LTU, OP_NE, OP_NEF, and vm_t.

Referenced by VM_Create().

00155                                                            {
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 );          // we're now int aligned
00163 //  memcpy( vm->codeBase, (byte *)header + header->codeOffset, vm->codeLength );
00164 
00165     // we don't need to translate the instructions, but we still need
00166     // to find each instructions starting point for jumps
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         // these are the only opcodes that aren't a single byte
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 }

Here is the call graph for this function:

void VM_StackTrace vm_t vm,
int  programCounter,
int  programStack
 

Definition at line 137 of file vm_interpreted.c.

References Com_Printf(), count, vm_s::dataBase, vm_t, and VM_ValueToSymbol().

00137                                                                      {
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 }

Here is the call graph for this function:


Generated on Thu Aug 25 14:56:13 2005 for Quake III Arena by  doxygen 1.3.9.1