00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "vm_local.h"
00026
00027 #pragma opt_pointer_analysis off
00028
00029
00030 typedef enum {
00031 R_REAL_STACK = 1,
00032
00033
00034
00035 R_STACK = 3,
00036 R_OPSTACK,
00037
00038
00039 R_MEMBASE,
00040 R_MEMMASK,
00041 R_ASMCALL,
00042 R_INSTRUCTIONS,
00043 R_NUM_INSTRUCTIONS,
00044 R_CVM,
00045
00046
00047 R_TOP = 11,
00048 R_SECOND = 12,
00049 R_EA = 2
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
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
00309 static unsigned *buf;
00310 static int compiledOfs;
00311
00312
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 );
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 );
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 );
00406 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -8 );
00407 } else {
00408 ltop();
00409 InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, -4 );
00410 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -8 );
00411 }
00412 rtopped = qfalse;
00413 }
00414
00415
00416 #if 0
00417 static void fltop() {
00418 if (rtopped == qfalse) {
00419 InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 );
00420 }
00421 }
00422 #endif
00423
00424 static void fltopandsecond() {
00425 InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 );
00426 InstImm( PPC_LFS, R_SECOND, R_OPSTACK, -4 );
00427 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -8 );
00428 rtopped = qfalse;
00429 return;
00430 }
00431
00432
00433
00434
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
00444 ((int *)itofConvert)[0] = 0x43300000;
00445 ((int *)itofConvert)[1] = 0x80000000;
00446 ((int *)itofConvert)[2] = 0x43300000;
00447
00448
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
00455
00456 for ( pass = -1 ; pass < 2 ; pass++ ) {
00457
00458 rtopped = qfalse;
00459
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
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 );
00491 rtopped = qfalse;
00492 break;
00493 case OP_ENTER:
00494 InstImm( PPC_ADDI, R_STACK, R_STACK, -Constant4() );
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 );
00512 pc++;
00513 instruction++;
00514 } else if (code[pc] == OP_LOAD2) {
00515 Inst( PPC_LHZX, R_TOP, R_TOP, R_MEMBASE );
00516 pc++;
00517 instruction++;
00518 } else if (code[pc] == OP_LOAD1) {
00519 Inst( PPC_LBZX, R_TOP, R_TOP, R_MEMBASE );
00520 pc++;
00521 instruction++;
00522 }
00523 if (code[pc] == OP_STORE4) {
00524 InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 );
00525 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
00526
00527 Inst( PPC_STWX, R_TOP, R_SECOND, R_MEMBASE );
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 );
00534 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
00535
00536 Inst( PPC_STHX, R_TOP, R_SECOND, R_MEMBASE );
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 );
00543 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
00544
00545 Inst( PPC_STBX, R_TOP, R_SECOND, R_MEMBASE );
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 );
00566 pc++;
00567 instruction++;
00568 } else if (code[pc] == OP_LOAD2) {
00569 Inst( PPC_LHZX, R_TOP, R_TOP, R_MEMBASE );
00570 pc++;
00571 instruction++;
00572 } else if (code[pc] == OP_LOAD1) {
00573 Inst( PPC_LBZX, R_TOP, R_TOP, R_MEMBASE );
00574 pc++;
00575 instruction++;
00576 }
00577 if (code[pc] == OP_STORE4) {
00578 InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 );
00579 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
00580
00581 Inst( PPC_STWX, R_TOP, R_SECOND, R_MEMBASE );
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 );
00588 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
00589
00590 Inst( PPC_STHX, R_TOP, R_SECOND, R_MEMBASE );
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 );
00597 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
00598
00599 Inst( PPC_STBX, R_TOP, R_SECOND, R_MEMBASE );
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();
00610 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
00611 InstImm( PPC_ADDI, R_EA, R_STACK, Constant1() );
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 );
00617 InstImm( PPC_STWU, R_SECOND, R_REAL_STACK, -16 );
00618
00619 Inst( PPC_MTSPR, R_ASMCALL, 9, 0 );
00620 Inst( PPC_BCCTR | 1, 20, 0, 0 );
00621
00622 InstImm( PPC_LWZ, R_SECOND, R_REAL_STACK, 0 );
00623 InstImm( PPC_ADDI, R_REAL_STACK, R_REAL_STACK, 16 );
00624 Inst( PPC_MTSPR, R_SECOND, 8, 0 );
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() );
00637 Inst( PPC_BCLR, 20, 0, 0 );
00638 rtopped = qfalse;
00639 break;
00640 case OP_LOAD4:
00641 ltop();
00642
00643 Inst( PPC_LWZX, R_TOP, R_TOP, R_MEMBASE );
00644 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
00645 rtopped = qtrue;
00646 break;
00647 case OP_LOAD2:
00648 ltop();
00649
00650 Inst( PPC_LHZX, R_TOP, R_TOP, R_MEMBASE );
00651 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
00652 rtopped = qtrue;
00653 break;
00654 case OP_LOAD1:
00655 ltop();
00656
00657 Inst( PPC_LBZX, R_TOP, R_TOP, R_MEMBASE );
00658 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
00659 rtopped = qtrue;
00660 break;
00661 case OP_STORE4:
00662 ltopandsecond();
00663
00664 Inst( PPC_STWX, R_TOP, R_SECOND, R_MEMBASE );
00665 rtopped = qfalse;
00666 break;
00667 case OP_STORE2:
00668 ltopandsecond();
00669
00670 Inst( PPC_STHX, R_TOP, R_SECOND, R_MEMBASE );
00671 rtopped = qfalse;
00672 break;
00673 case OP_STORE1:
00674 ltopandsecond();
00675
00676 Inst( PPC_STBX, R_TOP, R_SECOND, R_MEMBASE );
00677 rtopped = qfalse;
00678 break;
00679
00680 case OP_EQ:
00681 ltopandsecond();
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();
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
00707
00708 rtopped = qfalse;
00709 break;
00710 case OP_LTI:
00711 ltopandsecond();
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
00723 rtopped = qfalse;
00724 break;
00725 case OP_LEI:
00726 ltopandsecond();
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
00738 rtopped = qfalse;
00739 break;
00740 case OP_GTI:
00741 ltopandsecond();
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
00753 rtopped = qfalse;
00754 break;
00755 case OP_GEI:
00756 ltopandsecond();
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
00768 rtopped = qfalse;
00769 break;
00770 case OP_LTU:
00771 ltopandsecond();
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
00783 rtopped = qfalse;
00784 break;
00785 case OP_LEU:
00786 ltopandsecond();
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
00798 rtopped = qfalse;
00799 break;
00800 case OP_GTU:
00801 ltopandsecond();
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
00813 rtopped = qfalse;
00814 break;
00815 case OP_GEU:
00816 ltopandsecond();
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
00828 rtopped = qfalse;
00829 break;
00830
00831 case OP_EQF:
00832 fltopandsecond();
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
00844 rtopped = qfalse;
00845 break;
00846 case OP_NEF:
00847 fltopandsecond();
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
00859 rtopped = qfalse;
00860 break;
00861 case OP_LTF:
00862 fltopandsecond();
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
00874 rtopped = qfalse;
00875 break;
00876 case OP_LEF:
00877 fltopandsecond();
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
00889 rtopped = qfalse;
00890 break;
00891 case OP_GTF:
00892 fltopandsecond();
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
00904 rtopped = qfalse;
00905 break;
00906 case OP_GEF:
00907 fltopandsecond();
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
00919 rtopped = qfalse;
00920 break;
00921
00922 case OP_NEGI:
00923 ltop();
00924 InstImm( PPC_SUBFIC, R_TOP, R_TOP, 0 );
00925 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
00926 rtopped = qtrue;
00927 break;
00928 case OP_ADD:
00929 ltop();
00930 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );
00931 Inst( PPC_ADD, R_TOP, R_TOP, R_SECOND );
00932 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
00933 rtopped = qtrue;
00934 break;
00935 case OP_SUB:
00936 ltop();
00937 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );
00938 Inst( PPC_SUBF, R_TOP, R_TOP, R_SECOND );
00939 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
00940 rtopped = qtrue;
00941 break;
00942 case OP_DIVI:
00943 ltop();
00944 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );
00945 Inst( PPC_DIVW, R_TOP, R_SECOND, R_TOP );
00946 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
00947 rtopped = qtrue;
00948 break;
00949 case OP_DIVU:
00950 ltop();
00951 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );
00952 Inst( PPC_DIVWU, R_TOP, R_SECOND, R_TOP );
00953 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
00954 rtopped = qtrue;
00955 break;
00956 case OP_MODI:
00957 ltop();
00958 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );
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 );
00963 rtopped = qtrue;
00964 break;
00965 case OP_MODU:
00966 ltop();
00967 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );
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 );
00972 rtopped = qtrue;
00973 break;
00974 case OP_MULI:
00975 case OP_MULU:
00976 ltop();
00977 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );
00978 Inst( PPC_MULLW, R_TOP, R_SECOND, R_TOP );
00979 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
00980 rtopped = qtrue;
00981 break;
00982 case OP_BAND:
00983 ltop();
00984 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );
00985 Inst( PPC_AND, R_SECOND, R_TOP, R_TOP );
00986 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
00987 rtopped = qtrue;
00988 break;
00989 case OP_BOR:
00990 ltop();
00991 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );
00992 Inst( PPC_OR, R_SECOND, R_TOP, R_TOP );
00993 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
00994 rtopped = qtrue;
00995 break;
00996 case OP_BXOR:
00997 ltop();
00998 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );
00999 Inst( PPC_XOR, R_SECOND, R_TOP, R_TOP );
01000 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
01001 rtopped = qtrue;
01002 break;
01003 case OP_BCOM:
01004 ltop();
01005 Inst( PPC_NOR, R_TOP, R_TOP, R_TOP );
01006 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
01007 rtopped = qtrue;
01008 break;
01009 case OP_LSH:
01010 ltop();
01011 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );
01012 Inst( PPC_SLW, R_SECOND, R_TOP, R_TOP );
01013 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
01014 rtopped = qtrue;
01015 break;
01016 case OP_RSHI:
01017 ltop();
01018 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );
01019 Inst( PPC_SRAW, R_SECOND, R_TOP, R_TOP );
01020 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
01021 rtopped = qtrue;
01022 break;
01023 case OP_RSHU:
01024 ltop();
01025 InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );
01026 Inst( PPC_SRW, R_SECOND, R_TOP, R_TOP );
01027 InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
01028 rtopped = qtrue;
01029 break;
01030
01031 case OP_NEGF:
01032 InstImm( PPC_LFS, R_TOP<