#include "../game/q_shared.h"
#include "qcommon.h"
Include dependency graph for vm_local.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.
|
|
Definition at line 123 of file vm_local.h. |
|
|
Definition at line 124 of file vm_local.h. |
|
|
Definition at line 114 of file vm_local.h. |
|
|
Referenced by VM_CallInterpreted(), VM_LoadSymbols(), VM_ProfileSort(), VM_SymbolToValue(), VM_ValueToFunctionSymbol(), VM_ValueToSymbol(), and VM_VmProfile_f(). |
|
|
Definition at line 25 of file vm_local.h. 00025 {
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 OP_LOCAL,
00040
00041 OP_JUMP,
00042
00043 //-------------------
00044
00045 OP_EQ,
00046 OP_NE,
00047
00048 OP_LTI,
00049 OP_LEI,
00050 OP_GTI,
00051 OP_GEI,
00052
00053 OP_LTU,
00054 OP_LEU,
00055 OP_GTU,
00056 OP_GEU,
00057
00058 OP_EQF,
00059 OP_NEF,
00060
00061 OP_LTF,
00062 OP_LEF,
00063 OP_GTF,
00064 OP_GEF,
00065
00066 //-------------------
00067
00068 OP_LOAD1,
00069 OP_LOAD2,
00070 OP_LOAD4,
00071 OP_STORE1,
00072 OP_STORE2,
00073 OP_STORE4, // *(stack[top-1]) = stack[top]
00074 OP_ARG,
00075
00076 OP_BLOCK_COPY,
00077
00078 //-------------------
00079
00080 OP_SEX8,
00081 OP_SEX16,
00082
00083 OP_NEGI,
00084 OP_ADD,
00085 OP_SUB,
00086 OP_DIVI,
00087 OP_DIVU,
00088 OP_MODI,
00089 OP_MODU,
00090 OP_MULI,
00091 OP_MULU,
00092
00093 OP_BAND,
00094 OP_BOR,
00095 OP_BXOR,
00096 OP_BCOM,
00097
00098 OP_LSH,
00099 OP_RSHI,
00100 OP_RSHU,
00101
00102 OP_NEGF,
00103 OP_ADDF,
00104 OP_SUBF,
00105 OP_DIVF,
00106 OP_MULF,
00107
00108 OP_CVIF,
00109 OP_CVFI
00110 } opcode_t;
|
|
||||||||||||
|
Definition at line 1164 of file vm_ppc.c. References vm_t. Referenced by VM_Call(). 01164 {
01165 int stack[1024];
01166 int programStack;
01167 int stackOnEntry;
01168 byte *image;
01169
01170 currentVM = vm;
01171
01172 // interpret the code
01173 vm->currentlyInterpreting = qtrue;
01174
01175 // we might be called recursively, so this might not be the very top
01176 programStack = vm->programStack;
01177 stackOnEntry = programStack;
01178 image = vm->dataBase;
01179
01180 // set up the stack frame
01181 programStack -= 48;
01182
01183 *(int *)&image[ programStack + 44] = args[9];
01184 *(int *)&image[ programStack + 40] = args[8];
01185 *(int *)&image[ programStack + 36] = args[7];
01186 *(int *)&image[ programStack + 32] = args[6];
01187 *(int *)&image[ programStack + 28] = args[5];
01188 *(int *)&image[ programStack + 24] = args[4];
01189 *(int *)&image[ programStack + 20] = args[3];
01190 *(int *)&image[ programStack + 16] = args[2];
01191 *(int *)&image[ programStack + 12] = args[1];
01192 *(int *)&image[ programStack + 8 ] = args[0];
01193 *(int *)&image[ programStack + 4 ] = 0; // return stack
01194 *(int *)&image[ programStack ] = -1; // will terminate the loop on return
01195
01196 // off we go into generated code...
01197 // the PPC calling standard says the parms will all go into R3 - R11, so
01198 // no special asm code is needed here
01199 #ifdef __GNUC__
01200 ((void(*)(int, int, int, int, int, int, int, int))(vm->codeBase))(
01201 programStack, (int)&stack,
01202 (int)image, vm->dataMask, (int)&AsmCall,
01203 (int)vm->instructionPointers, vm->instructionPointersLength,
01204 (int)vm );
01205 #else
01206 ((void(*)(int, int, int, int, int, int, int, int))(vm->codeBase))(
01207 programStack, (int)&stack,
01208 (int)image, vm->dataMask, *(int *)&AsmCall /* skip function pointer header */,
01209 (int)vm->instructionPointers, vm->instructionPointersLength,
01210 (int)vm );
01211 #endif
01212 vm->programStack = stackOnEntry;
01213
01214 vm->currentlyInterpreting = qfalse;
01215
01216 return stack[1];
01217 }
|
|
||||||||||||
|
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:

|
||||||||||||
|
Definition at line 437 of file vm_ppc.c. References vm_t. Referenced by VM_Create(). 00437 {
00438 int op;
00439 int maxLength;
00440 int v;
00441 int i;
00442
00443 // set up the into-to-float variables
00444 ((int *)itofConvert)[0] = 0x43300000;
00445 ((int *)itofConvert)[1] = 0x80000000;
00446 ((int *)itofConvert)[2] = 0x43300000;
00447
00448 // allocate a very large temp buffer, we will shrink it later
00449 maxLength = header->codeLength * 8;
00450 buf = Z_Malloc( maxLength );
00451 jused = Z_Malloc(header->instructionCount + 2);
00452 Com_Memset(jused, 0, header->instructionCount+2);
00453
00454 // compile everything twice, so the second pass will have valid instruction
00455 // pointers for branches
00456 for ( pass = -1 ; pass < 2 ; pass++ ) {
00457
00458 rtopped = qfalse;
00459 // translate all instructions
00460 pc = 0;
00461
00462 pop0 = 343545;
00463 pop1 = 2443545;
00464 oc0 = -2343535;
00465 oc1 = 24353454;
00466 tvm = vm;
00467 code = (byte *)header + header->codeOffset;
00468 compiledOfs = 0;
00469 #ifndef __GNUC__
00470 // metrowerks seems to require this header in front of functions
00471 Emit4( (int)(buf+2) );
00472 Emit4( 0 );
00473 #endif
00474
00475 for ( instruction = 0 ; instruction < header->instructionCount ; instruction++ ) {
00476 if ( compiledOfs*4 > maxLength - 16 ) {
00477 Com_Error( ERR_DROP, "VM_Compile: maxLength exceeded" );
00478 }
00479
00480 op = code[ pc ];
00481 if ( !pass ) {
00482 vm->instructionPointers[ instruction ] = compiledOfs * 4;
00483 }
00484 pc++;
00485 switch ( op ) {
00486 case 0:
00487 break;
00488 case OP_BREAK:
00489 InstImmU( PPC_ADDI, R_TOP, 0, 0 );
00490 InstImm( PPC_LWZ, R_TOP, R_TOP, 0 ); // *(int *)0 to crash to debugger
00491 rtopped = qfalse;
00492 break;
00493 case OP_ENTER:
00494 InstImm( PPC_ADDI, R_STACK, R_STACK, -Constant4() ); // sub R_STACK, R_STACK, imm
00495 rtopped = qfalse;
00496 break;
00497 case OP_CONST:
00498 v = Constant4();
00499 if (code[pc] == OP_LOAD4 || code[pc] == OP_LOAD2 || code[pc] == OP_LOAD1) {
00500 v &= vm->dataMask;
00501 }
00502 if ( v < 32768 && v >= -32768 ) {
00503 InstImmU( PPC_ADDI, R_TOP, 0, v & 0xffff );
00504 } else {
00505 InstImmU( PPC_ADDIS, R_TOP, 0, (v >> 16)&0xffff );
00506 if ( v & 0xffff ) {
00507 InstImmU( PPC_ORI, R_TOP, R_TOP, v & 0xffff );
00508 }
00509 }
00510 if (code[pc] == OP_LOAD4) {
00511 Inst( PPC_LWZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
00512 pc++;
00513 instruction++;
00514 } else if (code[pc] == OP_LOAD2) {
00515 Inst( PPC_LHZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
00516 pc++;
00517 instruction++;
00518 } else if (code[pc] == OP_LOAD1) {
00519 Inst( PPC_LBZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
00520 pc++;
00521 instruction++;
00522 }
00523 if (code[pc] == OP_STORE4) {
00524 InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 ); // get value from opstack
00525 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
00526 //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
00527 Inst( PPC_STWX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
00528 pc++;
00529 instruction++;
00530 rtopped = qfalse;
00531 break;
00532 } else if (code[pc] == OP_STORE2) {
00533 InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 ); // get value from opstack
00534 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
00535 //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
00536 Inst( PPC_STHX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
00537 pc++;
00538 instruction++;
00539 rtopped = qfalse;
00540 break;
00541 } else if (code[pc] == OP_STORE1) {
00542 InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 ); // get value from opstack
00543 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
00544 //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
00545 Inst( PPC_STBX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
00546 pc++;
00547 instruction++;
00548 rtopped = qfalse;
00549 break;
00550 }
00551 if (code[pc] == OP_JUMP) {
00552 jused[v] = 1;
00553 }
00554 InstImm( PPC_STWU, R_TOP, R_OPSTACK, 4 );
00555 rtopped = qtrue;
00556 break;
00557 case OP_LOCAL:
00558 oc0 = oc1;
00559 oc1 = Constant4();
00560 if (code[pc] == OP_LOAD4 || code[pc] == OP_LOAD2 || code[pc] == OP_LOAD1) {
00561 oc1 &= vm->dataMask;
00562 }
00563 InstImm( PPC_ADDI, R_TOP, R_STACK, oc1 );
00564 if (code[pc] == OP_LOAD4) {
00565 Inst( PPC_LWZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
00566 pc++;
00567 instruction++;
00568 } else if (code[pc] == OP_LOAD2) {
00569 Inst( PPC_LHZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
00570 pc++;
00571 instruction++;
00572 } else if (code[pc] == OP_LOAD1) {
00573 Inst( PPC_LBZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
00574 pc++;
00575 instruction++;
00576 }
00577 if (code[pc] == OP_STORE4) {
00578 InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 ); // get value from opstack
00579 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
00580 //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
00581 Inst( PPC_STWX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
00582 pc++;
00583 instruction++;
00584 rtopped = qfalse;
00585 break;
00586 } else if (code[pc] == OP_STORE2) {
00587 InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 ); // get value from opstack
00588 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
00589 //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
00590 Inst( PPC_STHX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
00591 pc++;
00592 instruction++;
00593 rtopped = qfalse;
00594 break;
00595 } else if (code[pc] == OP_STORE1) {
00596 InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 ); // get value from opstack
00597 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
00598 //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
00599 Inst( PPC_STBX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
00600 pc++;
00601 instruction++;
00602 rtopped = qfalse;
00603 break;
00604 }
00605 InstImm( PPC_STWU, R_TOP, R_OPSTACK, 4 );
00606 rtopped = qtrue;
00607 break;
00608 case OP_ARG:
00609 ltop(); // get value from opstack
00610 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
00611 InstImm( PPC_ADDI, R_EA, R_STACK, Constant1() ); // location to put it
00612 Inst( PPC_STWX, R_TOP, R_EA, R_MEMBASE );
00613 rtopped = qfalse;
00614 break;
00615 case OP_CALL:
00616 Inst( PPC_MFSPR, R_SECOND, 8, 0 ); // move from link register
00617 InstImm( PPC_STWU, R_SECOND, R_REAL_STACK, -16 ); // save off the old return address
00618
00619 Inst( PPC_MTSPR, R_ASMCALL, 9, 0 ); // move to count register
00620 Inst( PPC_BCCTR | 1, 20, 0, 0 ); // jump and link to the count register
00621
00622 InstImm( PPC_LWZ, R_SECOND, R_REAL_STACK, 0 ); // fetch the old return address
00623 InstImm( PPC_ADDI, R_REAL_STACK, R_REAL_STACK, 16 );
00624 Inst( PPC_MTSPR, R_SECOND, 8, 0 ); // move to link register
00625 rtopped = qfalse;
00626 break;
00627 case OP_PUSH:
00628 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, 4 );
00629 rtopped = qfalse;
00630 break;
00631 case OP_POP:
00632 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
00633 rtopped = qfalse;
00634 break;
00635 case OP_LEAVE:
00636 InstImm( PPC_ADDI, R_STACK, R_STACK, Constant4() ); // add R_STACK, R_STACK, imm
00637 Inst( PPC_BCLR, 20, 0, 0 ); // branch unconditionally to link register
00638 rtopped = qfalse;
00639 break;
00640 case OP_LOAD4:
00641 ltop(); // get value from opstack
00642 //Inst( PPC_AND, R_MEMMASK, R_TOP, R_TOP ); // mask it
00643 Inst( PPC_LWZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
00644 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
00645 rtopped = qtrue;
00646 break;
00647 case OP_LOAD2:
00648 ltop(); // get value from opstack
00649 //Inst( PPC_AND, R_MEMMASK, R_TOP, R_TOP ); // mask it
00650 Inst( PPC_LHZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
00651 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
00652 rtopped = qtrue;
00653 break;
00654 case OP_LOAD1:
00655 ltop(); // get value from opstack
00656 //Inst( PPC_AND, R_MEMMASK, R_TOP, R_TOP ); // mask it
00657 Inst( PPC_LBZX, R_TOP, R_TOP, R_MEMBASE ); // load from memory base
00658 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
00659 rtopped = qtrue;
00660 break;
00661 case OP_STORE4:
00662 ltopandsecond(); // get value from opstack
00663 //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
00664 Inst( PPC_STWX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
00665 rtopped = qfalse;
00666 break;
00667 case OP_STORE2:
00668 ltopandsecond(); // get value from opstack
00669 //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
00670 Inst( PPC_STHX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
00671 rtopped = qfalse;
00672 break;
00673 case OP_STORE1:
00674 ltopandsecond(); // get value from opstack
00675 //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND ); // mask it
00676 Inst( PPC_STBX, R_TOP, R_SECOND, R_MEMBASE ); // store from memory base
00677 rtopped = qfalse;
00678 break;
00679
00680 case OP_EQ:
00681 ltopandsecond(); // get value from opstack
00682 Inst( PPC_CMP, 0, R_SECOND, R_TOP );
00683 i = Constant4();
00684 jused[i] = 1;
00685 InstImm( PPC_BC, 4, 2, 8 );
00686 if ( pass==1 ) {
00687 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
00688 } else {
00689 v = 0;
00690 }
00691 Emit4(PPC_B | (v&0x3ffffff) );
00692 rtopped = qfalse;
00693 break;
00694 case OP_NE:
00695 ltopandsecond(); // get value from opstack
00696 Inst( PPC_CMP, 0, R_SECOND, R_TOP );
00697 i = Constant4();
00698 jused[i] = 1;
00699 InstImm( PPC_BC, 12, 2, 8 );
00700 if ( pass==1 ) {
00701 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
00702 } else {
00703 v = 0;
00704 }
00705 Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
00706 // InstImm( PPC_BC, 4, 2, v );
00707
00708 rtopped = qfalse;
00709 break;
00710 case OP_LTI:
00711 ltopandsecond(); // get value from opstack
00712 Inst( PPC_CMP, 0, R_SECOND, R_TOP );
00713 i = Constant4();
00714 jused[i] = 1;
00715 InstImm( PPC_BC, 4, 0, 8 );
00716 if ( pass==1 ) {
00717 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
00718 } else {
00719 v = 0;
00720 }
00721 Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
00722 // InstImm( PPC_BC, 12, 0, v );
00723 rtopped = qfalse;
00724 break;
00725 case OP_LEI:
00726 ltopandsecond(); // get value from opstack
00727 Inst( PPC_CMP, 0, R_SECOND, R_TOP );
00728 i = Constant4();
00729 jused[i] = 1;
00730 InstImm( PPC_BC, 12, 1, 8 );
00731 if ( pass==1 ) {
00732 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
00733 } else {
00734 v = 0;
00735 }
00736 Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
00737 // InstImm( PPC_BC, 4, 1, v );
00738 rtopped = qfalse;
00739 break;
00740 case OP_GTI:
00741 ltopandsecond(); // get value from opstack
00742 Inst( PPC_CMP, 0, R_SECOND, R_TOP );
00743 i = Constant4();
00744 jused[i] = 1;
00745 InstImm( PPC_BC, 4, 1, 8 );
00746 if ( pass==1 ) {
00747 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
00748 } else {
00749 v = 0;
00750 }
00751 Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
00752 // InstImm( PPC_BC, 12, 1, v );
00753 rtopped = qfalse;
00754 break;
00755 case OP_GEI:
00756 ltopandsecond(); // get value from opstack
00757 Inst( PPC_CMP, 0, R_SECOND, R_TOP );
00758 i = Constant4();
00759 jused[i] = 1;
00760 InstImm( PPC_BC, 12, 0, 8 );
00761 if ( pass==1 ) {
00762 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
00763 } else {
00764 v = 0;
00765 }
00766 Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
00767 // InstImm( PPC_BC, 4, 0, v );
00768 rtopped = qfalse;
00769 break;
00770 case OP_LTU:
00771 ltopandsecond(); // get value from opstack
00772 Inst( PPC_CMPL, 0, R_SECOND, R_TOP );
00773 i = Constant4();
00774 jused[i] = 1;
00775 InstImm( PPC_BC, 4, 0, 8 );
00776 if ( pass==1 ) {
00777 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
00778 } else {
00779 v = 0;
00780 }
00781 Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
00782 // InstImm( PPC_BC, 12, 0, v );
00783 rtopped = qfalse;
00784 break;
00785 case OP_LEU:
00786 ltopandsecond(); // get value from opstack
00787 Inst( PPC_CMPL, 0, R_SECOND, R_TOP );
00788 i = Constant4();
00789 jused[i] = 1;
00790 InstImm( PPC_BC, 12, 1, 8 );
00791 if ( pass==1 ) {
00792 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
00793 } else {
00794 v = 0;
00795 }
00796 Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
00797 // InstImm( PPC_BC, 4, 1, v );
00798 rtopped = qfalse;
00799 break;
00800 case OP_GTU:
00801 ltopandsecond(); // get value from opstack
00802 Inst( PPC_CMPL, 0, R_SECOND, R_TOP );
00803 i = Constant4();
00804 jused[i] = 1;
00805 InstImm( PPC_BC, 4, 1, 8 );
00806 if ( pass==1 ) {
00807 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
00808 } else {
00809 v = 0;
00810 }
00811 Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
00812 // InstImm( PPC_BC, 12, 1, v );
00813 rtopped = qfalse;
00814 break;
00815 case OP_GEU:
00816 ltopandsecond(); // get value from opstack
00817 Inst( PPC_CMPL, 0, R_SECOND, R_TOP );
00818 i = Constant4();
00819 jused[i] = 1;
00820 InstImm( PPC_BC, 12, 0, 8 );
00821 if ( pass==1 ) {
00822 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
00823 } else {
00824 v = 0;
00825 }
00826 Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
00827 // InstImm( PPC_BC, 4, 0, v );
00828 rtopped = qfalse;
00829 break;
00830
00831 case OP_EQF:
00832 fltopandsecond(); // get value from opstack
00833 Inst( PPC_FCMPU, 0, R_TOP, R_SECOND );
00834 i = Constant4();
00835 jused[i] = 1;
00836 InstImm( PPC_BC, 4, 2, 8 );
00837 if ( pass==1 ) {
00838 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
00839 } else {
00840 v = 0;
00841 }
00842 Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
00843 // InstImm( PPC_BC, 12, 2, v );
00844 rtopped = qfalse;
00845 break;
00846 case OP_NEF:
00847 fltopandsecond(); // get value from opstack
00848 Inst( PPC_FCMPU, 0, R_TOP, R_SECOND );
00849 i = Constant4();
00850 jused[i] = 1;
00851 InstImm( PPC_BC, 12, 2, 8 );
00852 if ( pass==1 ) {
00853 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
00854 } else {
00855 v = 0;
00856 }
00857 Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
00858 // InstImm( PPC_BC, 4, 2, v );
00859 rtopped = qfalse;
00860 break;
00861 case OP_LTF:
00862 fltopandsecond(); // get value from opstack
00863 Inst( PPC_FCMPU, 0, R_SECOND, R_TOP );
00864 i = Constant4();
00865 jused[i] = 1;
00866 InstImm( PPC_BC, 4, 0, 8 );
00867 if ( pass==1 ) {
00868 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
00869 } else {
00870 v = 0;
00871 }
00872 Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
00873 // InstImm( PPC_BC, 12, 0, v );
00874 rtopped = qfalse;
00875 break;
00876 case OP_LEF:
00877 fltopandsecond(); // get value from opstack
00878 Inst( PPC_FCMPU, 0, R_SECOND, R_TOP );
00879 i = Constant4();
00880 jused[i] = 1;
00881 InstImm( PPC_BC, 12, 1, 8 );
00882 if ( pass==1 ) {
00883 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
00884 } else {
00885 v = 0;
00886 }
00887 Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
00888 // InstImm( PPC_BC, 4, 1, v );
00889 rtopped = qfalse;
00890 break;
00891 case OP_GTF:
00892 fltopandsecond(); // get value from opstack
00893 Inst( PPC_FCMPU, 0, R_SECOND, R_TOP );
00894 i = Constant4();
00895 jused[i] = 1;
00896 InstImm( PPC_BC, 4, 1, 8 );
00897 if ( pass==1 ) {
00898 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
00899 } else {
00900 v = 0;
00901 }
00902 Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
00903 // InstImm( PPC_BC, 12, 1, v );
00904 rtopped = qfalse;
00905 break;
00906 case OP_GEF:
00907 fltopandsecond(); // get value from opstack
00908 < |