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

vm_ppc.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 // vm_ppc.c
00023 // ppc dynamic compiler
00024 
00025 #include "vm_local.h"
00026 
00027 #pragma opt_pointer_analysis off
00028 
00029 
00030 typedef enum {
00031     R_REAL_STACK = 1,
00032     // registers 3-11 are the parameter passing registers
00033     
00034     // state
00035     R_STACK = 3,            // local
00036     R_OPSTACK,              // global
00037 
00038     // constants    
00039     R_MEMBASE,          // global
00040     R_MEMMASK,
00041     R_ASMCALL,          // global
00042     R_INSTRUCTIONS,     // global
00043     R_NUM_INSTRUCTIONS, // global
00044     R_CVM,              // currentVM
00045     
00046     // temps
00047     R_TOP = 11,
00048     R_SECOND = 12,
00049     R_EA = 2                // effective address calculation
00050      
00051 } regNums_t;
00052 
00053 #define RG_REAL_STACK       r1
00054 #define RG_STACK            r3
00055 #define RG_OPSTACK          r4
00056 #define RG_MEMBASE          r5
00057 #define RG_MEMMASK          r6
00058 #define RG_ASMCALL          r7
00059 #define RG_INSTRUCTIONS     r8
00060 #define RG_NUM_INSTRUCTIONS r9
00061 #define RG_CVM              r10
00062 #define RG_TOP              r12
00063 #define RG_SECOND           r13
00064 #define RG_EA               r14
00065 
00066 // this doesn't have the low order bits set for instructions i'm not using...
00067 typedef enum {
00068     PPC_TDI     = 0x08000000,
00069     PPC_TWI     = 0x0c000000,
00070     PPC_MULLI   = 0x1c000000,
00071     PPC_SUBFIC  = 0x20000000,
00072     PPC_CMPI    = 0x28000000,
00073     PPC_CMPLI   = 0x2c000000,
00074     PPC_ADDIC   = 0x30000000,
00075     PPC_ADDIC_  = 0x34000000,
00076     PPC_ADDI    = 0x38000000,
00077     PPC_ADDIS   = 0x3c000000,
00078     PPC_BC      = 0x40000000,
00079     PPC_SC      = 0x44000000,
00080     PPC_B       = 0x48000000,
00081 
00082     PPC_MCRF    = 0x4c000000,
00083     PPC_BCLR    = 0x4c000020,
00084     PPC_RFID    = 0x4c000000,
00085     PPC_CRNOR   = 0x4c000000,
00086     PPC_RFI     = 0x4c000000,
00087     PPC_CRANDC  = 0x4c000000,
00088     PPC_ISYNC   = 0x4c000000,
00089     PPC_CRXOR   = 0x4c000000,
00090     PPC_CRNAND  = 0x4c000000,
00091     PPC_CREQV   = 0x4c000000,
00092     PPC_CRORC   = 0x4c000000,
00093     PPC_CROR    = 0x4c000000,
00094 //------------
00095     PPC_BCCTR   = 0x4c000420,
00096     PPC_RLWIMI  = 0x50000000,
00097     PPC_RLWINM  = 0x54000000,
00098     PPC_RLWNM   = 0x5c000000,
00099     PPC_ORI     = 0x60000000,
00100     PPC_ORIS    = 0x64000000,
00101     PPC_XORI    = 0x68000000,
00102     PPC_XORIS   = 0x6c000000,
00103     PPC_ANDI_   = 0x70000000,
00104     PPC_ANDIS_  = 0x74000000,
00105     PPC_RLDICL  = 0x78000000,
00106     PPC_RLDICR  = 0x78000000,
00107     PPC_RLDIC   = 0x78000000,
00108     PPC_RLDIMI  = 0x78000000,
00109     PPC_RLDCL   = 0x78000000,
00110     PPC_RLDCR   = 0x78000000,
00111     PPC_CMP     = 0x7c000000,
00112     PPC_TW      = 0x7c000000,
00113     PPC_SUBFC   = 0x7c000010,
00114     PPC_MULHDU  = 0x7c000000,
00115     PPC_ADDC    = 0x7c000014,
00116     PPC_MULHWU  = 0x7c000000,
00117     PPC_MFCR    = 0x7c000000,
00118     PPC_LWAR    = 0x7c000000,
00119     PPC_LDX     = 0x7c000000,
00120     PPC_LWZX    = 0x7c00002e,
00121     PPC_SLW     = 0x7c000030,
00122     PPC_CNTLZW  = 0x7c000000,
00123     PPC_SLD     = 0x7c000000,
00124     PPC_AND     = 0x7c000038,
00125     PPC_CMPL    = 0x7c000040,
00126     PPC_SUBF    = 0x7c000050,
00127     PPC_LDUX    = 0x7c000000,
00128 //------------
00129     PPC_DCBST   = 0x7c000000,
00130     PPC_LWZUX   = 0x7c00006c,
00131     PPC_CNTLZD  = 0x7c000000,
00132     PPC_ANDC    = 0x7c000000,
00133     PPC_TD      = 0x7c000000,
00134     PPC_MULHD   = 0x7c000000,
00135     PPC_MULHW   = 0x7c000000,
00136     PPC_MTSRD   = 0x7c000000,
00137     PPC_MFMSR   = 0x7c000000,
00138     PPC_LDARX   = 0x7c000000,
00139     PPC_DCBF    = 0x7c000000,
00140     PPC_LBZX    = 0x7c0000ae,
00141     PPC_NEG     = 0x7c000000,
00142     PPC_MTSRDIN = 0x7c000000,
00143     PPC_LBZUX   = 0x7c000000,
00144     PPC_NOR     = 0x7c0000f8,
00145     PPC_SUBFE   = 0x7c000000,
00146     PPC_ADDE    = 0x7c000000,
00147     PPC_MTCRF   = 0x7c000000,
00148     PPC_MTMSR   = 0x7c000000,
00149     PPC_STDX    = 0x7c000000,
00150     PPC_STWCX_  = 0x7c000000,
00151     PPC_STWX    = 0x7c00012e,
00152     PPC_MTMSRD  = 0x7c000000,
00153     PPC_STDUX   = 0x7c000000,
00154     PPC_STWUX   = 0x7c00016e,
00155     PPC_SUBFZE  = 0x7c000000,
00156     PPC_ADDZE   = 0x7c000000,
00157     PPC_MTSR    = 0x7c000000,
00158     PPC_STDCX_  = 0x7c000000,
00159     PPC_STBX    = 0x7c0001ae,
00160     PPC_SUBFME  = 0x7c000000,
00161     PPC_MULLD   = 0x7c000000,
00162 //------------
00163     PPC_ADDME   = 0x7c000000,
00164     PPC_MULLW   = 0x7c0001d6,
00165     PPC_MTSRIN  = 0x7c000000,
00166     PPC_DCBTST  = 0x7c000000,
00167     PPC_STBUX   = 0x7c000000,
00168     PPC_ADD     = 0x7c000214,
00169     PPC_DCBT    = 0x7c000000,
00170     PPC_LHZX    = 0x7c00022e,
00171     PPC_EQV     = 0x7c000000,
00172     PPC_TLBIE   = 0x7c000000,
00173     PPC_ECIWX   = 0x7c000000,
00174     PPC_LHZUX   = 0x7c000000,
00175     PPC_XOR     = 0x7c000278,
00176     PPC_MFSPR   = 0x7c0002a6,
00177     PPC_LWAX    = 0x7c000000,
00178     PPC_LHAX    = 0x7c000000,
00179     PPC_TLBIA   = 0x7c000000,
00180     PPC_MFTB    = 0x7c000000,
00181     PPC_LWAUX   = 0x7c000000,
00182     PPC_LHAUX   = 0x7c000000,
00183     PPC_STHX    = 0x7c00032e,
00184     PPC_ORC     = 0x7c000338,
00185     PPC_SRADI   = 0x7c000000,
00186     PPC_SLBIE   = 0x7c000000,
00187     PPC_ECOWX   = 0x7c000000,
00188     PPC_STHUX   = 0x7c000000,
00189     PPC_OR      = 0x7c000378,
00190     PPC_DIVDU   = 0x7c000000,
00191     PPC_DIVWU   = 0x7c000396,
00192     PPC_MTSPR   = 0x7c0003a6,
00193     PPC_DCBI    = 0x7c000000,
00194     PPC_NAND    = 0x7c000000,
00195     PPC_DIVD    = 0x7c000000,
00196 //------------
00197     PPC_DIVW    = 0x7c0003d6,
00198     PPC_SLBIA   = 0x7c000000,
00199     PPC_MCRXR   = 0x7c000000,
00200     PPC_LSWX    = 0x7c000000,
00201     PPC_LWBRX   = 0x7c000000,
00202     PPC_LFSX    = 0x7c000000,
00203     PPC_SRW     = 0x7c000430,
00204     PPC_SRD     = 0x7c000000,
00205     PPC_TLBSYNC = 0x7c000000,
00206     PPC_LFSUX   = 0x7c000000,
00207     PPC_MFSR    = 0x7c000000,
00208     PPC_LSWI    = 0x7c000000,
00209     PPC_SYNC    = 0x7c000000,
00210     PPC_LFDX    = 0x7c000000,
00211     PPC_LFDUX   = 0x7c000000,
00212     PPC_MFSRIN  = 0x7c000000,
00213     PPC_STSWX   = 0x7c000000,
00214     PPC_STWBRX  = 0x7c000000,
00215     PPC_STFSX   = 0x7c000000,
00216     PPC_STFSUX  = 0x7c000000,
00217     PPC_STSWI   = 0x7c000000,
00218     PPC_STFDX   = 0x7c000000,
00219     PPC_DCBA    = 0x7c000000,
00220     PPC_STFDUX  = 0x7c000000,
00221     PPC_LHBRX   = 0x7c000000,
00222     PPC_SRAW    = 0x7c000630,
00223     PPC_SRAD    = 0x7c000000,
00224     PPC_SRAWI   = 0x7c000000,
00225     PPC_EIEIO   = 0x7c000000,
00226     PPC_STHBRX  = 0x7c000000,
00227     PPC_EXTSH   = 0x7c000734,
00228     PPC_EXTSB   = 0x7c000774,
00229     PPC_ICBI    = 0x7c000000,
00230 //------------
00231     PPC_STFIWX  = 0x7c0007ae,
00232     PPC_EXTSW   = 0x7c000000,
00233     PPC_DCBZ    = 0x7c000000,
00234     PPC_LWZ     = 0x80000000,
00235     PPC_LWZU    = 0x84000000,
00236     PPC_LBZ     = 0x88000000,
00237     PPC_LBZU    = 0x8c000000,
00238     PPC_STW     = 0x90000000,
00239     PPC_STWU    = 0x94000000,
00240     PPC_STB     = 0x98000000,
00241     PPC_STBU    = 0x9c000000,
00242     PPC_LHZ     = 0xa0000000,
00243     PPC_LHZU    = 0xa4000000,
00244     PPC_LHA     = 0xa8000000,
00245     PPC_LHAU    = 0xac000000,
00246     PPC_STH     = 0xb0000000,
00247     PPC_STHU    = 0xb4000000,
00248     PPC_LMW     = 0xb8000000,
00249     PPC_STMW    = 0xbc000000,
00250     PPC_LFS     = 0xc0000000,
00251     PPC_LFSU    = 0xc4000000,
00252     PPC_LFD     = 0xc8000000,
00253     PPC_LFDU    = 0xcc000000,
00254     PPC_STFS    = 0xd0000000,
00255     PPC_STFSU   = 0xd4000000,
00256     PPC_STFD    = 0xd8000000,
00257     PPC_STFDU   = 0xdc000000,
00258     PPC_LD      = 0xe8000000,
00259     PPC_LDU     = 0xe8000001,
00260     PPC_LWA     = 0xe8000002,
00261     PPC_FDIVS   = 0xec000024,
00262     PPC_FSUBS   = 0xec000028,
00263     PPC_FADDS   = 0xec00002a,
00264 //------------
00265     PPC_FSQRTS  = 0xec000000,
00266     PPC_FRES    = 0xec000000,
00267     PPC_FMULS   = 0xec000032,
00268     PPC_FMSUBS  = 0xec000000,
00269     PPC_FMADDS  = 0xec000000,
00270     PPC_FNMSUBS = 0xec000000,
00271     PPC_FNMADDS = 0xec000000,
00272     PPC_STD     = 0xf8000000,
00273     PPC_STDU    = 0xf8000001,
00274     PPC_FCMPU   = 0xfc000000,
00275     PPC_FRSP    = 0xfc000018,
00276     PPC_FCTIW   = 0xfc000000,
00277     PPC_FCTIWZ  = 0xfc00001e,
00278     PPC_FDIV    = 0xfc000000,
00279     PPC_FSUB    = 0xfc000028,
00280     PPC_FADD    = 0xfc000000,
00281     PPC_FSQRT   = 0xfc000000,
00282     PPC_FSEL    = 0xfc000000,
00283     PPC_FMUL    = 0xfc000000,
00284     PPC_FRSQRTE = 0xfc000000,
00285     PPC_FMSUB   = 0xfc000000,
00286     PPC_FMADD   = 0xfc000000,
00287     PPC_FNMSUB  = 0xfc000000,
00288     PPC_FNMADD  = 0xfc000000,
00289     PPC_FCMPO   = 0xfc000000,
00290     PPC_MTFSB1  = 0xfc000000,
00291     PPC_FNEG    = 0xfc000050,
00292     PPC_MCRFS   = 0xfc000000,
00293     PPC_MTFSB0  = 0xfc000000,
00294     PPC_FMR     = 0xfc000000,
00295     PPC_MTFSFI  = 0xfc000000,
00296     PPC_FNABS   = 0xfc000000,
00297     PPC_FABS    = 0xfc000000,
00298 //------------
00299     PPC_MFFS    = 0xfc000000,
00300     PPC_MTFSF   = 0xfc000000,
00301     PPC_FCTID   = 0xfc000000,
00302     PPC_FCTIDZ  = 0xfc000000,
00303     PPC_FCFID   = 0xfc000000
00304     
00305 } ppcOpcodes_t;
00306 
00307 
00308 // the newly generated code
00309 static  unsigned    *buf;
00310 static  int     compiledOfs;    // in dwords
00311 
00312 // fromt the original bytecode
00313 static  byte    *code;
00314 static  int     pc;
00315 
00316 void AsmCall( void );
00317 
00318 double  itofConvert[2];
00319 
00320 static int  Constant4( void ) {
00321     int     v;
00322 
00323     v = code[pc] | (code[pc+1]<<8) | (code[pc+2]<<16) | (code[pc+3]<<24);
00324     pc += 4;
00325     return v;
00326 }
00327 
00328 static int  Constant1( void ) {
00329     int     v;
00330 
00331     v = code[pc];
00332     pc += 1;
00333     return v;
00334 }
00335 
00336 static void Emit4( int i ) {
00337     buf[ compiledOfs ] = i;
00338     compiledOfs++;
00339 }
00340 
00341 static void Inst( int opcode, int destReg, int aReg, int bReg ) {
00342     unsigned        r;
00343 
00344     r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) ;
00345     buf[ compiledOfs ] = r;
00346     compiledOfs++;
00347 }
00348 
00349 static void Inst4( int opcode, int destReg, int aReg, int bReg, int cReg ) {
00350     unsigned        r;
00351 
00352     r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) | ( cReg << 6 );
00353     buf[ compiledOfs ] = r;
00354     compiledOfs++;
00355 }
00356 
00357 static void InstImm( int opcode, int destReg, int aReg, int immediate ) {
00358     unsigned        r;
00359     
00360     if ( immediate > 32767 || immediate < -32768 ) {
00361         Com_Error( ERR_FATAL, "VM_Compile: immediate value %i out of range, opcode %x,%d,%d", immediate, opcode, destReg, aReg );
00362     }
00363     r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( immediate & 0xffff );
00364     buf[ compiledOfs ] = r;
00365     compiledOfs++;
00366 }
00367 
00368 static void InstImmU( int opcode, int destReg, int aReg, int immediate ) {
00369     unsigned        r;
00370     
00371     if ( immediate > 0xffff || immediate < 0 ) {
00372         Com_Error( ERR_FATAL, "VM_Compile: immediate value %i out of range", immediate );
00373     }
00374     r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( immediate & 0xffff );
00375     buf[ compiledOfs ] = r;
00376     compiledOfs++;
00377 }
00378 
00379 static qboolean rtopped;
00380 static int pop0, pop1, oc0, oc1;
00381 static vm_t *tvm;
00382 static int instruction;
00383 static byte *jused;
00384 static int pass;
00385 
00386 static void ltop() {
00387     if (rtopped == qfalse) {
00388     InstImm( PPC_LWZ, R_TOP, R_OPSTACK, 0 );        // get value from opstack
00389     }
00390 }
00391 
00392 static void ltopandsecond() {
00393     if (pass>=0 && buf[compiledOfs-1] == (PPC_STWU |  R_TOP<<21 | R_OPSTACK<<16 | 4 ) && jused[instruction]==0 ) {
00394     compiledOfs--;
00395     if (!pass) {
00396         tvm->instructionPointers[instruction] = compiledOfs * 4;
00397     }
00398     InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 ); // get value from opstack
00399     InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
00400     } else if (pass>=0 && buf[compiledOfs-1] == (PPC_STW |  R_TOP<<21 | R_OPSTACK<<16 | 0 )  && jused[instruction]==0 ) {
00401     compiledOfs--;
00402     if (!pass) {
00403         tvm->instructionPointers[instruction] = compiledOfs * 4;
00404     }
00405     InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, -4 );    // get value from opstack
00406     InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -8 );
00407     } else {
00408     ltop();     // get value from opstack
00409     InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, -4 );    // get value from opstack
00410     InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -8 );
00411     }
00412     rtopped = qfalse;
00413 }
00414 
00415 // TJW: Unused
00416 #if 0
00417 static void fltop() {
00418     if (rtopped == qfalse) {
00419     InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 );        // get value from opstack
00420     }
00421 }
00422 #endif
00423 
00424 static void fltopandsecond() {
00425     InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 );        // get value from opstack
00426     InstImm( PPC_LFS, R_SECOND, R_OPSTACK, -4 );    // get value from opstack
00427     InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -8 );
00428     rtopped = qfalse;
00429     return;
00430 }
00431 
00432 /*
00433 =================
00434 VM_Compile
00435 =================
00436 */
00437 void VM_Compile( vm_t *vm, vmHeader_t *header ) {
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                 Inst( PPC_FCMPU, 0, R_SECOND, R_TOP );
00909                 i = Constant4();
00910         jused[i] = 1;
00911                 InstImm( PPC_BC, 12, 0, 8 );
00912                 if ( pass==1 ) {
00913                     v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
00914                 } else {
00915                     v = 0;
00916                 }
00917                 Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
00918 //                InstImm( PPC_BC, 4, 0, v );
00919         rtopped = qfalse;
00920                 break;
00921 
00922             case OP_NEGI:
00923                 ltop();     // get value from opstack
00924                 InstImm( PPC_SUBFIC, R_TOP, R_TOP, 0 );
00925                 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );        // save value to opstack
00926         rtopped = qtrue;
00927                 break;
00928             case OP_ADD:
00929                 ltop();     // get value from opstack
00930                 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );       // get value from opstack
00931                 Inst( PPC_ADD, R_TOP, R_TOP, R_SECOND );
00932                 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );        // save value to opstack
00933         rtopped = qtrue;
00934                 break;
00935             case OP_SUB:
00936                 ltop();     // get value from opstack
00937                 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );       // get value from opstack
00938                 Inst( PPC_SUBF, R_TOP, R_TOP, R_SECOND );
00939                 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );        // save value to opstack
00940         rtopped = qtrue;
00941                 break;
00942             case OP_DIVI:
00943                 ltop();     // get value from opstack
00944                 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );       // get value from opstack
00945                 Inst( PPC_DIVW, R_TOP, R_SECOND, R_TOP );
00946                 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );        // save value to opstack
00947         rtopped = qtrue;
00948                 break;
00949             case OP_DIVU:
00950                 ltop();     // get value from opstack
00951                 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );       // get value from opstack
00952                 Inst( PPC_DIVWU, R_TOP, R_SECOND, R_TOP );
00953                 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );        // save value to opstack
00954         rtopped = qtrue;
00955                 break;
00956             case OP_MODI:
00957                 ltop();     // get value from opstack
00958                 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );       // get value from opstack
00959                 Inst( PPC_DIVW, R_EA, R_SECOND, R_TOP );
00960                 Inst( PPC_MULLW, R_EA, R_TOP, R_EA );
00961                 Inst( PPC_SUBF, R_TOP, R_EA, R_SECOND );
00962                 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );        // save value to opstack
00963         rtopped = qtrue;
00964                 break;
00965             case OP_MODU:
00966                 ltop();     // get value from opstack
00967                 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );       // get value from opstack
00968                 Inst( PPC_DIVWU, R_EA, R_SECOND, R_TOP );
00969                 Inst( PPC_MULLW, R_EA, R_TOP, R_EA );
00970                 Inst( PPC_SUBF, R_TOP, R_EA, R_SECOND );
00971                 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );        // save value to opstack
00972         rtopped = qtrue;
00973                 break;
00974             case OP_MULI:
00975             case OP_MULU:
00976                 ltop();     // get value from opstack
00977                 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );       // get value from opstack
00978                 Inst( PPC_MULLW, R_TOP, R_SECOND, R_TOP );
00979                 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );        // save value to opstack
00980         rtopped = qtrue;
00981                 break;
00982             case OP_BAND:
00983                 ltop();     // get value from opstack
00984                 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );       // get value from opstack
00985                 Inst( PPC_AND, R_SECOND, R_TOP, R_TOP );
00986                 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );        // save value to opstack
00987         rtopped = qtrue;
00988                 break;
00989             case OP_BOR:
00990                 ltop();     // get value from opstack
00991                 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );       // get value from opstack
00992                 Inst( PPC_OR, R_SECOND, R_TOP, R_TOP );
00993                 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );        // save value to opstack
00994         rtopped = qtrue;
00995                 break;
00996             case OP_BXOR:
00997                 ltop();     // get value from opstack
00998                 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );       // get value from opstack
00999                 Inst( PPC_XOR, R_SECOND, R_TOP, R_TOP );
01000                 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );        // save value to opstack
01001         rtopped = qtrue;
01002                 break;
01003             case OP_BCOM:
01004                 ltop();     // get value from opstack
01005                 Inst( PPC_NOR, R_TOP, R_TOP, R_TOP );
01006                 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );        // save value to opstack
01007         rtopped = qtrue;
01008                 break;
01009             case OP_LSH:
01010                 ltop();     // get value from opstack
01011                 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );       // get value from opstack
01012                 Inst( PPC_SLW, R_SECOND, R_TOP, R_TOP );
01013                 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );        // save value to opstack
01014         rtopped = qtrue;
01015                 break;
01016             case OP_RSHI:
01017                 ltop();     // get value from opstack
01018                 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );       // get value from opstack
01019                 Inst( PPC_SRAW, R_SECOND, R_TOP, R_TOP );
01020                 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );        // save value to opstack
01021         rtopped = qtrue;
01022                 break;
01023             case OP_RSHU:
01024                 ltop();     // get value from opstack
01025                 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );       // get value from opstack
01026                 Inst( PPC_SRW, R_SECOND, R_TOP, R_TOP );
01027                 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );        // save value to opstack
01028         rtopped = qtrue;
01029                 break;
01030 
01031             case OP_NEGF:
01032                 InstImm( PPC_LFS, R_TOP<