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 #define DEBUG_VM 0
00030
00031 #if DEBUG_VM
00032 static char *opnames[256] = {
00033 "OP_UNDEF",
00034
00035 "OP_IGNORE",
00036
00037 "OP_BREAK",
00038
00039 "OP_ENTER",
00040 "OP_LEAVE",
00041 "OP_CALL",
00042 "OP_PUSH",
00043 "OP_POP",
00044
00045 "OP_CONST",
00046
00047 "OP_LOCAL",
00048
00049 "OP_JUMP",
00050
00051
00052
00053 "OP_EQ",
00054 "OP_NE",
00055
00056 "OP_LTI",
00057 "OP_LEI",
00058 "OP_GTI",
00059 "OP_GEI",
00060
00061 "OP_LTU",
00062 "OP_LEU",
00063 "OP_GTU",
00064 "OP_GEU",
00065
00066 "OP_EQF",
00067 "OP_NEF",
00068
00069 "OP_LTF",
00070 "OP_LEF",
00071 "OP_GTF",
00072 "OP_GEF",
00073
00074
00075
00076 "OP_LOAD1",
00077 "OP_LOAD2",
00078 "OP_LOAD4",
00079 "OP_STORE1",
00080 "OP_STORE2",
00081 "OP_STORE4",
00082 "OP_ARG",
00083
00084 "OP_BLOCK_COPY",
00085
00086
00087
00088 "OP_SEX8",
00089 "OP_SEX16",
00090
00091 "OP_NEGI",
00092 "OP_ADD",
00093 "OP_SUB",
00094 "OP_DIVI",
00095 "OP_DIVU",
00096 "OP_MODI",
00097 "OP_MODU",
00098 "OP_MULI",
00099 "OP_MULU",
00100
00101 "OP_BAND",
00102 "OP_BOR",
00103 "OP_BXOR",
00104 "OP_BCOM",
00105
00106 "OP_LSH",
00107 "OP_RSHI",
00108 "OP_RSHU",
00109
00110 "OP_NEGF",
00111 "OP_ADDF",
00112 "OP_SUBF",
00113 "OP_DIVF",
00114 "OP_MULF",
00115
00116 "OP_CVIF",
00117 "OP_CVFI"
00118 };
00119 #endif
00120
00121 typedef enum {
00122 R_REAL_STACK = 1,
00123
00124
00125
00126 R_STACK = 3,
00127 R_OPSTACK,
00128
00129
00130 R_MEMBASE,
00131 R_MEMMASK,
00132 R_ASMCALL,
00133 R_INSTRUCTIONS,
00134 R_NUM_INSTRUCTIONS,
00135 R_CVM,
00136
00137
00138 R_TOP = 11,
00139 R_SECOND = 12,
00140 R_EA = 2
00141
00142 } regNums_t;
00143
00144 #define RG_REAL_STACK r1
00145 #define RG_STACK r3
00146 #define RG_OPSTACK r4
00147 #define RG_MEMBASE r5
00148 #define RG_MEMMASK r6
00149 #define RG_ASMCALL r7
00150 #define RG_INSTRUCTIONS r8
00151 #define RG_NUM_INSTRUCTIONS r9
00152 #define RG_CVM r10
00153 #define RG_TOP r12
00154 #define RG_SECOND r13
00155 #define RG_EA r14
00156
00157
00158 #define OP_STACK_MAX_DEPTH 12
00159
00160
00161
00162 static int opStackIntRegisters[OP_STACK_MAX_DEPTH] =
00163 {
00164 16, 17, 18, 19,
00165 20, 21, 22, 23,
00166 24, 25, 26, 27
00167 };
00168
00169 static unsigned int *opStackLoadInstructionAddr[OP_STACK_MAX_DEPTH];
00170
00171
00172
00173 static int opStackFloatRegisters[OP_STACK_MAX_DEPTH] =
00174 {
00175 0, 1, 2, 3,
00176 4, 5, 6, 7,
00177 8, 9, 10, 11
00178 };
00179
00180 static int opStackRegType[OP_STACK_MAX_DEPTH] =
00181 {
00182 0, 0, 0, 0,
00183 0, 0, 0, 0,
00184 0, 0, 0, 0
00185 };
00186
00187
00188 typedef enum {
00189 PPC_TDI = 0x08000000,
00190 PPC_TWI = 0x0c000000,
00191 PPC_MULLI = 0x1c000000,
00192 PPC_SUBFIC = 0x20000000,
00193 PPC_CMPI = 0x28000000,
00194 PPC_CMPLI = 0x2c000000,
00195 PPC_ADDIC = 0x30000000,
00196 PPC_ADDIC_ = 0x34000000,
00197 PPC_ADDI = 0x38000000,
00198 PPC_ADDIS = 0x3c000000,
00199 PPC_BC = 0x40000000,
00200 PPC_SC = 0x44000000,
00201 PPC_B = 0x48000000,
00202
00203 PPC_MCRF = 0x4c000000,
00204 PPC_BCLR = 0x4c000020,
00205 PPC_RFID = 0x4c000000,
00206 PPC_CRNOR = 0x4c000000,
00207 PPC_RFI = 0x4c000000,
00208 PPC_CRANDC = 0x4c000000,
00209 PPC_ISYNC = 0x4c000000,
00210 PPC_CRXOR = 0x4c000000,
00211 PPC_CRNAND = 0x4c000000,
00212 PPC_CREQV = 0x4c000000,
00213 PPC_CRORC = 0x4c000000,
00214 PPC_CROR = 0x4c000000,
00215
00216 PPC_BCCTR = 0x4c000420,
00217 PPC_RLWIMI = 0x50000000,
00218 PPC_RLWINM = 0x54000000,
00219 PPC_RLWNM = 0x5c000000,
00220 PPC_ORI = 0x60000000,
00221 PPC_ORIS = 0x64000000,
00222 PPC_XORI = 0x68000000,
00223 PPC_XORIS = 0x6c000000,
00224 PPC_ANDI_ = 0x70000000,
00225 PPC_ANDIS_ = 0x74000000,
00226 PPC_RLDICL = 0x78000000,
00227 PPC_RLDICR = 0x78000000,
00228 PPC_RLDIC = 0x78000000,
00229 PPC_RLDIMI = 0x78000000,
00230 PPC_RLDCL = 0x78000000,
00231 PPC_RLDCR = 0x78000000,
00232 PPC_CMP = 0x7c000000,
00233 PPC_TW = 0x7c000000,
00234 PPC_SUBFC = 0x7c000010,
00235 PPC_MULHDU = 0x7c000000,
00236 PPC_ADDC = 0x7c000014,
00237 PPC_MULHWU = 0x7c000000,
00238 PPC_MFCR = 0x7c000000,
00239 PPC_LWAR = 0x7c000000,
00240 PPC_LDX = 0x7c000000,
00241 PPC_LWZX = 0x7c00002e,
00242 PPC_SLW = 0x7c000030,
00243 PPC_CNTLZW = 0x7c000000,
00244 PPC_SLD = 0x7c000000,
00245 PPC_AND = 0x7c000038,
00246 PPC_CMPL = 0x7c000040,
00247 PPC_SUBF = 0x7c000050,
00248 PPC_LDUX = 0x7c000000,
00249
00250 PPC_DCBST = 0x7c000000,
00251 PPC_LWZUX = 0x7c00006c,
00252 PPC_CNTLZD = 0x7c000000,
00253 PPC_ANDC = 0x7c000000,
00254 PPC_TD = 0x7c000000,
00255 PPC_MULHD = 0x7c000000,
00256 PPC_MULHW = 0x7c000000,
00257 PPC_MTSRD = 0x7c000000,
00258 PPC_MFMSR = 0x7c000000,
00259 PPC_LDARX = 0x7c000000,
00260 PPC_DCBF = 0x7c000000,
00261 PPC_LBZX = 0x7c0000ae,
00262 PPC_NEG = 0x7c000000,
00263 PPC_MTSRDIN = 0x7c000000,
00264 PPC_LBZUX = 0x7c000000,
00265 PPC_NOR = 0x7c0000f8,
00266 PPC_SUBFE = 0x7c000000,
00267 PPC_ADDE = 0x7c000000,
00268 PPC_MTCRF = 0x7c000000,
00269 PPC_MTMSR = 0x7c000000,
00270 PPC_STDX = 0x7c000000,
00271 PPC_STWCX_ = 0x7c000000,
00272 PPC_STWX = 0x7c00012e,
00273 PPC_MTMSRD = 0x7c000000,
00274 PPC_STDUX = 0x7c000000,
00275 PPC_STWUX = 0x7c00016e,
00276 PPC_SUBFZE = 0x7c000000,
00277 PPC_ADDZE = 0x7c000000,
00278 PPC_MTSR = 0x7c000000,
00279 PPC_STDCX_ = 0x7c000000,
00280 PPC_STBX = 0x7c0001ae,
00281 PPC_SUBFME = 0x7c000000,
00282 PPC_MULLD = 0x7c000000,
00283
00284 PPC_ADDME = 0x7c000000,
00285 PPC_MULLW = 0x7c0001d6,
00286 PPC_MTSRIN = 0x7c000000,
00287 PPC_DCBTST = 0x7c000000,
00288 PPC_STBUX = 0x7c000000,
00289 PPC_ADD = 0x7c000214,
00290 PPC_DCBT = 0x7c000000,
00291 PPC_LHZX = 0x7c00022e,
00292 PPC_EQV = 0x7c000000,
00293 PPC_TLBIE = 0x7c000000,
00294 PPC_ECIWX = 0x7c000000,
00295 PPC_LHZUX = 0x7c000000,
00296 PPC_XOR = 0x7c000278,
00297 PPC_MFSPR = 0x7c0002a6,
00298 PPC_LWAX = 0x7c000000,
00299 PPC_LHAX = 0x7c000000,
00300 PPC_TLBIA = 0x7c000000,
00301 PPC_MFTB = 0x7c000000,
00302 PPC_LWAUX = 0x7c000000,
00303 PPC_LHAUX = 0x7c000000,
00304 PPC_STHX = 0x7c00032e,
00305 PPC_ORC = 0x7c000338,
00306 PPC_SRADI = 0x7c000000,
00307 PPC_SLBIE = 0x7c000000,
00308 PPC_ECOWX = 0x7c000000,
00309 PPC_STHUX = 0x7c000000,
00310 PPC_OR = 0x7c000378,
00311 PPC_DIVDU = 0x7c000000,
00312 PPC_DIVWU = 0x7c000396,
00313 PPC_MTSPR = 0x7c0003a6,
00314 PPC_DCBI = 0x7c000000,
00315 PPC_NAND = 0x7c000000,
00316 PPC_DIVD = 0x7c000000,
00317
00318 PPC_DIVW = 0x7c0003d6,
00319 PPC_SLBIA = 0x7c000000,
00320 PPC_MCRXR = 0x7c000000,
00321 PPC_LSWX = 0x7c000000,
00322 PPC_LWBRX = 0x7c000000,
00323 PPC_LFSX = 0x7c00042e,
00324 PPC_SRW = 0x7c000430,
00325 PPC_SRD = 0x7c000000,
00326 PPC_TLBSYNC = 0x7c000000,
00327 PPC_LFSUX = 0x7c000000,
00328 PPC_MFSR = 0x7c000000,
00329 PPC_LSWI = 0x7c000000,
00330 PPC_SYNC = 0x7c000000,
00331 PPC_LFDX = 0x7c000000,
00332 PPC_LFDUX = 0x7c000000,
00333 PPC_MFSRIN = 0x7c000000,
00334 PPC_STSWX = 0x7c000000,
00335 PPC_STWBRX = 0x7c000000,
00336 PPC_STFSX = 0x7c00052e,
00337 PPC_STFSUX = 0x7c000000,
00338 PPC_STSWI = 0x7c000000,
00339 PPC_STFDX = 0x7c000000,
00340 PPC_DCBA = 0x7c000000,
00341 PPC_STFDUX = 0x7c000000,
00342 PPC_LHBRX = 0x7c000000,
00343 PPC_SRAW = 0x7c000630,
00344 PPC_SRAD = 0x7c000000,
00345 PPC_SRAWI = 0x7c000000,
00346 PPC_EIEIO = 0x7c000000,
00347 PPC_STHBRX = 0x7c000000,
00348 PPC_EXTSH = 0x7c000734,
00349 PPC_EXTSB = 0x7c000774,
00350 PPC_ICBI = 0x7c000000,
00351
00352 PPC_STFIWX = 0x7c0007ae,
00353 PPC_EXTSW = 0x7c000000,
00354 PPC_DCBZ = 0x7c000000,
00355 PPC_LWZ = 0x80000000,
00356 PPC_LWZU = 0x84000000,
00357 PPC_LBZ = 0x88000000,
00358 PPC_LBZU = 0x8c000000,
00359 PPC_STW = 0x90000000,
00360 PPC_STWU = 0x94000000,
00361 PPC_STB = 0x98000000,
00362 PPC_STBU = 0x9c000000,
00363 PPC_LHZ = 0xa0000000,
00364 PPC_LHZU = 0xa4000000,
00365 PPC_LHA = 0xa8000000,
00366 PPC_LHAU = 0xac000000,
00367 PPC_STH = 0xb0000000,
00368 PPC_STHU = 0xb4000000,
00369 PPC_LMW = 0xb8000000,
00370 PPC_STMW = 0xbc000000,
00371 PPC_LFS = 0xc0000000,
00372 PPC_LFSU = 0xc4000000,
00373 PPC_LFD = 0xc8000000,
00374 PPC_LFDU = 0xcc000000,
00375 PPC_STFS = 0xd0000000,
00376 PPC_STFSU = 0xd4000000,
00377 PPC_STFD = 0xd8000000,
00378 PPC_STFDU = 0xdc000000,
00379 PPC_LD = 0xe8000000,
00380 PPC_LDU = 0xe8000001,
00381 PPC_LWA = 0xe8000002,
00382 PPC_FDIVS = 0xec000024,
00383 PPC_FSUBS = 0xec000028,
00384 PPC_FADDS = 0xec00002a,
00385
00386 PPC_FSQRTS = 0xec000000,
00387 PPC_FRES = 0xec000000,
00388 PPC_FMULS = 0xec000032,
00389 PPC_FMSUBS = 0xec000000,
00390 PPC_FMADDS = 0xec000000,
00391 PPC_FNMSUBS = 0xec000000,
00392 PPC_FNMADDS = 0xec000000,
00393 PPC_STD = 0xf8000000,
00394 PPC_STDU = 0xf8000001,
00395 PPC_FCMPU = 0xfc000000,
00396 PPC_FRSP = 0xfc000018,
00397 PPC_FCTIW = 0xfc000000,
00398 PPC_FCTIWZ = 0xfc00001e,
00399 PPC_FDIV = 0xfc000000,
00400 PPC_FSUB = 0xfc000028,
00401 PPC_FADD = 0xfc000000,
00402 PPC_FSQRT = 0xfc000000,
00403 PPC_FSEL = 0xfc000000,
00404 PPC_FMUL = 0xfc000000,
00405 PPC_FRSQRTE = 0xfc000000,
00406 PPC_FMSUB = 0xfc000000,
00407 PPC_FMADD = 0xfc000000,
00408 PPC_FNMSUB = 0xfc000000,
00409 PPC_FNMADD = 0xfc000000,
00410 PPC_FCMPO = 0xfc000000,
00411 PPC_MTFSB1 = 0xfc000000,
00412 PPC_FNEG = 0xfc000050,
00413 PPC_MCRFS = 0xfc000000,
00414 PPC_MTFSB0 = 0xfc000000,
00415 PPC_FMR = 0xfc000000,
00416 PPC_MTFSFI = 0xfc000000,
00417 PPC_FNABS = 0xfc000000,
00418 PPC_FABS = 0xfc000000,
00419
00420 PPC_MFFS = 0xfc000000,
00421 PPC_MTFSF = 0xfc000000,
00422 PPC_FCTID = 0xfc000000,
00423 PPC_FCTIDZ = 0xfc000000,
00424 PPC_FCFID = 0xfc000000
00425
00426 } ppcOpcodes_t;
00427
00428
00429
00430 static unsigned *buf;
00431 static int compiledOfs;
00432 static int pass;
00433
00434
00435 static byte *code;
00436 static int pc;
00437
00438 void AsmCall( void );
00439
00440 double itofConvert[2];
00441
00442 static int Constant4( void ) {
00443 int v;
00444
00445 v = code[pc] | (code[pc+1]<<8) | (code[pc+2]<<16) | (code[pc+3]<<24);
00446 pc += 4;
00447 return v;
00448 }
00449
00450 static int Constant1( void ) {
00451 int v;
00452
00453 v = code[pc];
00454 pc += 1;
00455 return v;
00456 }
00457
00458 static void Emit4( char *opname, int i ) {
00459 #if DEBUG_VM
00460 if(pass == 1)
00461 printf("\t\t\t%p %s\t%08lx\n",&buf[compiledOfs],opname,i&0x3ffffff);
00462 #endif
00463 buf[ compiledOfs ] = i;
00464 compiledOfs++;
00465 }
00466
00467 static void Inst( char *opname, int opcode, int destReg, int aReg, int bReg ) {
00468 unsigned r;
00469
00470 #if DEBUG_VM
00471 if(pass == 1)
00472 printf("\t\t\t%p %s\tr%d,r%d,r%d\n",&buf[compiledOfs],opname,destReg,aReg,bReg);
00473 #endif
00474 r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) ;
00475 buf[ compiledOfs ] = r;
00476 compiledOfs++;
00477 }
00478
00479 static void Inst4( char *opname, int opcode, int destReg, int aReg, int bReg, int cReg ) {
00480 unsigned r;
00481
00482 #if DEBUG_VM
00483 if(pass == 1)
00484 printf("\t\t\t%p %s\tr%d,r%d,r%d,r%d\n",&buf[compiledOfs],opname,destReg,aReg,bReg,cReg);
00485 #endif
00486 r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) | ( cReg << 6 );
00487 buf[ compiledOfs ] = r;
00488 compiledOfs++;
00489 }
00490
00491 static void InstImm( char *opname, int opcode, int destReg, int aReg, int immediate ) {
00492 unsigned r;
00493
00494 if ( immediate > 32767 || immediate < -32768 ) {
00495 Com_Error( ERR_FATAL, "VM_Compile: immediate value %i out of range, opcode %x,%d,%d", immediate, opcode, destReg, aReg );
00496 }
00497 #if DEBUG_VM
00498 if(pass == 1)
00499 printf("\t\t\t%p %s\tr%d,r%d,0x%x\n",&buf[compiledOfs],opname,destReg,aReg,immediate);
00500 #endif
00501 r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( immediate & 0xffff );
00502 buf[ compiledOfs ] = r;
00503 compiledOfs++;
00504 }
00505
00506 static void InstImmU( char *opname, int opcode, int destReg, int aReg, int immediate ) {
00507 unsigned r;
00508
00509 if ( immediate > 0xffff || immediate < 0 ) {
00510 Com_Error( ERR_FATAL, "VM_Compile: immediate value %i out of range", immediate );
00511 }
00512 #if DEBUG_VM
00513 if(pass == 1)
00514 printf("\t\t\t%p %s\tr%d,r%d,0x%x\n",&buf[compiledOfs],opname,destReg,aReg,immediate);
00515 #endif
00516 r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( immediate & 0xffff );
00517 buf[ compiledOfs ] = r;
00518 compiledOfs++;
00519 }
00520
00521 static int pop0, pop1, oc0, oc1;
00522 static vm_t *tvm;
00523 static int instruction;
00524 static byte *jused;
00525
00526 static void ltop() {
00527
00528
00529
00530 }
00531
00532 static void ltopandsecond() {
00533 #if 0
00534 if (pass>=0 && buf[compiledOfs-1] == (PPC_STWU | R_TOP<<21 | R_OPSTACK<<16 | 4 ) && jused[instruction]==0 ) {
00535 compiledOfs--;
00536 if (!pass) {
00537 tvm->instructionPointers[instruction] = compiledOfs * 4;
00538 }
00539 InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 );
00540 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
00541 } else if (pass>=0 && buf[compiledOfs-1] == (PPC_STW | R_TOP<<21 | R_OPSTACK<<16 | 0 ) && jused[instruction]==0 ) {
00542 compiledOfs--;
00543 if (!pass) {
00544 tvm->instructionPointers[instruction] = compiledOfs * 4;
00545 }
00546 InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, -4 );
00547 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -8 );
00548 } else {
00549 ltop();
00550 InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, -4 );
00551 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -8 );
00552 }
00553 rtopped = qfalse;
00554 #endif
00555 }
00556
00557 static void spillOpStack(int depth)
00558 {
00559
00560 int i;
00561
00562 for(i = 0; i < depth; i++)
00563 {
00564 assert(opStackRegType[i]);
00565 assert(opStackRegType[i] == 1);
00566 switch(opStackRegType[i])
00567 {
00568 case 1:
00569 InstImm( "stw", PPC_STW, opStackIntRegisters[i], R_OPSTACK, i*4+4);
00570 break;
00571 case 2:
00572 InstImm( "stfs", PPC_STFS, opStackFloatRegisters[i], R_OPSTACK, i*4+4);
00573 break;
00574 }
00575 opStackRegType[i] = 0;
00576 }
00577 }
00578
00579 static void loadOpStack(int depth)
00580 {
00581
00582
00583
00584 int i;
00585
00586 for(i = 0; i < depth; i++)
00587 {
00588 assert(opStackRegType[i] == 0);
00589
00590 opStackLoadInstructionAddr[i] = &buf[compiledOfs];
00591 InstImm( "lwz", PPC_LWZ, opStackIntRegisters[i], R_OPSTACK, i*4+4);
00592 opStackRegType[i] = 1;
00593 }
00594 }
00595
00596 static void makeInteger(int depth)
00597 {
00598
00599 assert(opStackRegType[depth] == 1);
00600
00601 if(opStackRegType[depth] == 2)
00602 {
00603 unsigned instruction;
00604 assert(opStackLoadInstructionAddr[depth]);
00605
00606 printf("patching float load at %p to int load\n",opStackLoadInstructionAddr[depth]);
00607
00608 instruction = *opStackLoadInstructionAddr[depth];
00609 instruction &= ~PPC_LFSX;
00610 instruction |= PPC_LWZX;
00611 *opStackLoadInstructionAddr[depth] = instruction;
00612 opStackLoadInstructionAddr[depth] = 0;
00613 opStackRegType[depth] = 1;
00614 #if 0
00615 InstImm( "stfs", PPC_STFS, opStackFloatRegisters[depth], R_OPSTACK, depth*4+4);
00616
00617
00618 Inst( "ori", PPC_ORI, 0, 0, 0 );
00619 Inst( "ori", PPC_ORI, 0, 0, 0 );
00620 Inst( "ori", PPC_ORI, 0, 0, 0 );
00621 Inst( "ori", PPC_ORI, 0, 0, 0 );
00622 InstImm( "lwz", PPC_LWZ, opStackIntRegisters[depth], R_OPSTACK, depth*4+4);
00623 opStackRegType[depth] = 1;
00624 #endif
00625 }
00626 }
00627
00628 static void makeFloat(int depth)
00629 {
00630
00631 if(opStackRegType[depth] == 1)
00632 {
00633 unsigned instruction;
00634 unsigned destReg, aReg, bReg, imm;
00635
00636 if(opStackLoadInstructionAddr[depth])
00637 {
00638
00639 instruction = *opStackLoadInstructionAddr[depth];
00640
00641 if((instruction & 0xfc000000) == PPC_LWZ)
00642 {
00643
00644
00645
00646 destReg = (instruction >> 21) & 31;
00647 aReg = (instruction >> 16) & 31;
00648 imm = instruction & 0xffff;
00649
00650
00651
00652
00653 destReg = (destReg - opStackIntRegisters[0]) + opStackFloatRegisters[0];
00654 instruction = PPC_LFS | ( destReg << 21 ) | ( aReg << 16 ) | imm ;
00655
00656
00657 }
00658 else
00659 {
00660
00661
00662
00663 destReg = (instruction >> 21) & 31;
00664 aReg = (instruction >> 16) & 31;
00665 bReg = (instruction >> 11) & 31;
00666
00667
00668
00669 destReg = (destReg - opStackIntRegisters[0]) + opStackFloatRegisters[0];
00670 instruction = PPC_LFSX | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) ;
00671
00672
00673 }
00674 *opStackLoadInstructionAddr[depth] = instruction;
00675 opStackLoadInstructionAddr[depth] = 0;
00676 }
00677 else
00678 {
00679
00680
00681
00682
00683 InstImm( "stw", PPC_STW, opStackIntRegisters[depth], R_OPSTACK, depth*4+4);
00684
00685
00686 Inst( "ori", PPC_ORI, 0, 0, 0 );
00687 Inst( "ori", PPC_ORI, 0, 0, 0 );
00688 Inst( "ori", PPC_ORI, 0, 0, 0 );
00689 Inst( "ori", PPC_ORI, 0, 0, 0 );
00690 InstImm( "lfs", PPC_LFS, opStackFloatRegisters[depth], R_OPSTACK, depth*4+4);
00691 }
00692 opStackRegType[depth] = 2;
00693 }
00694 }
00695
00696
00697 #if 0
00698 static void fltop() {
00699 if (rtopped == qfalse) {
00700 InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 );
00701 }
00702 }
00703 #endif
00704
00705 #if 0
00706 static void fltopandsecond() {
00707 InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 );
00708 InstImm( PPC_LFS, R_SECOND, R_OPSTACK, -4 );
00709 InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -8 );
00710 rtopped = qfalse;
00711 return;
00712 }
00713 #endif
00714
00715 #define assertInteger(depth) assert(opStackRegType[depth] == 1)
00716
00717
00718
00719
00720
00721
00722 void VM_Compile( vm_t *vm, vmHeader_t *header ) {
00723 int op;
00724 int maxLength;
00725 int v;
00726 int i;
00727 int opStackDepth;
00728
00729 int mainFunction;
00730
00731
00732 ((int *)itofConvert)[0] = 0x43300000;
00733 ((int *)itofConvert)[1] = 0x80000000;
00734 ((int *)itofConvert)[2] = 0x43300000;
00735
00736
00737 maxLength = header->codeLength * 8;
00738 buf = Z_Malloc( maxLength );
00739 jused = Z_Malloc(header->instructionCount + 2);
00740 Com_Memset(jused, 0, header->instructionCount+2);
00741
00742
00743
00744 for ( pass = -1 ; pass < 2 ; pass++ ) {
00745
00746
00747 pc = 0;
00748 mainFunction = 0;
00749 opStackDepth = 0;
00750
00751 pop0 = 343545;
00752 pop1 = 2443545;
00753 oc0 = -2343535;
00754 oc1 = 24353454;
00755 tvm = vm;
00756 code = (byte *)header + header->codeOffset;
00757 compiledOfs = 0;
00758 #ifndef __GNUC__
00759
00760 Emit4( (int)(buf+2) );
00761 Emit4( 0 );
00762 #endif
00763
00764 for ( instruction = 0 ; instruction < header->instructionCount ; instruction++ ) {
00765 if ( compiledOfs*4 > maxLength - 16 ) {
00766 Com_Error( ERR_DROP, "VM_Compile: maxLength exceeded" );
00767 }
00768
00769 op = code[ pc ];
00770 if ( !pass ) {
00771 vm->instructionPointers[ instruction ] = compiledOfs * 4;
00772 }
00773 pc++;
00774 switch ( op ) {
00775 case 0:
00776 break;
00777 case OP_BREAK:
00778 #if DEBUG_VM
00779 if(pass == 1)
00780 printf("%08lx BREAK\n",instruction);
00781 #endif
00782 InstImmU( "addi", PPC_ADDI, R_TOP, 0, 0 );
00783 InstImm( "lwz", PPC_LWZ, R_TOP, R_TOP, 0 );
00784 break;
00785 case OP_ENTER:
00786 opStackDepth = 0;
00787 v = Constant4();
00788 #if DEBUG_VM
00789 if(pass == 1)
00790 printf("%08x ENTER\t%04x\n",instruction,v);
00791 #endif
00792 opStackRegType[opStackDepth] = 0;
00793 mainFunction++;
00794 if(mainFunction == 1)
00795 {
00796
00797
00798
00799 InstImm( "addi", PPC_ADDI, R_REAL_STACK, R_REAL_STACK, -OP_STACK_MAX_DEPTH*4 );
00800 for(i = 0; i < OP_STACK_MAX_DEPTH; i++)
00801 InstImm( "stw", PPC_STW, opStackIntRegisters[i], R_REAL_STACK, i*4);
00802 }
00803 InstImm( "addi", PPC_ADDI, R_STACK, R_STACK, -v );
00804 break;
00805 case OP_CONST:
00806 v = Constant4();
00807 #if DEBUG_VM
00808 if(pass == 1)
00809 printf("%08x CONST\t%08x\n",instruction,v);
00810 #endif
00811 opStackLoadInstructionAddr[opStackDepth] = 0;
00812 if ( v < 32768 && v >= -32768 ) {
00813 InstImmU( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth], 0, v & 0xffff );
00814 } else {
00815 InstImmU( "addis", PPC_ADDIS, opStackIntRegisters[opStackDepth], 0, (v >> 16)&0xffff );
00816 if ( v & 0xffff ) {
00817 InstImmU( "ori", PPC_ORI, opStackIntRegisters[opStackDepth], opStackIntRegisters[opStackDepth], v & 0xffff );
00818 }
00819 }
00820 opStackRegType[opStackDepth] = 1;
00821 opStackDepth += 1;
00822 if (code[pc] == OP_JUMP) {
00823 jused[v] = 1;
00824 }
00825 break;
00826 case OP_LOCAL:
00827 oc1 = Constant4();
00828 #if DEBUG_VM
00829 if(pass == 1)
00830 printf("%08x LOCAL\t%08x\n",instruction,oc1);
00831 #endif
00832 if (code[pc] == OP_LOAD4 || code[pc] == OP_LOAD2 || code[pc] == OP_LOAD1) {
00833 oc1 &= vm->dataMask;
00834 }
00835 InstImm( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth], R_STACK, oc1 );
00836 opStackRegType[opStackDepth] = 1;
00837 opStackLoadInstructionAddr[opStackDepth] = 0;
00838 opStackDepth += 1;
00839 break;
00840 case OP_ARG:
00841 v = Constant1();
00842 #if DEBUG_VM
00843 if(pass == 1)
00844 printf("%08x ARG \t%08x\n",instruction,v);
00845 #endif
00846 InstImm( "addi", PPC_ADDI, R_EA, R_STACK, v );
00847 if(opStackRegType[opStackDepth-1] == 1)
00848 Inst( "stwx", PPC_STWX, opStackIntRegisters[opStackDepth-1], R_EA, R_MEMBASE );
00849 else
00850 Inst( "stfsx", PPC_STFSX, opStackFloatRegisters[opStackDepth-1], R_EA, R_MEMBASE );
00851 opStackRegType[opStackDepth-1] = 0;
00852 opStackLoadInstructionAddr[opStackDepth-1] = 0;
00853 opStackDepth -= 1;
00854
00855 break;
00856 case OP_CALL:
00857 #if DEBUG_VM
00858 if(pass == 1)
00859 printf("%08x CALL\n",instruction);
00860 #endif
00861 assertInteger(opStackDepth-1);
00862 assert(opStackDepth > 0);
00863 Inst( "mflr", PPC_MFSPR, R_SECOND, 8, 0 );
00864 InstImm( "stwu", PPC_STWU, R_SECOND, R_REAL_STACK, -16 );
00865
00866
00867 spillOpStack(opStackDepth);
00868
00869
00870
00871 InstImm( "addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, opStackDepth*4);
00872
00873 Inst( "mtctr", PPC_MTSPR, R_ASMCALL, 9, 0 );
00874 Inst( "bctrl", PPC_BCCTR | 1, 20, 0, 0 );
00875
00876
00877
00878
00879 InstImm("addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, -opStackDepth*4);
00880
00881
00882 loadOpStack(opStackDepth);
00883
00884 InstImm( "lwz", PPC_LWZ, R_SECOND, R_REAL_STACK, 0 );
00885 InstImm( "addi", PPC_ADDI, R_REAL_STACK, R_REAL_STACK, 16 );
00886 Inst( "mtlr", PPC_MTSPR, R_SECOND, 8, 0 );
00887 break;
00888 case OP_PUSH:
00889 #if DEBUG_VM
00890 if(pass == 1)
00891 printf("%08x PUSH\n",instruction);
00892 #endif
00893 opStackRegType[opStackDepth] = 1;
00894 opStackDepth += 1;
00895 break;
00896 case OP_POP:
00897 #if DEBUG_VM
00898 if(pass == 1)
00899 printf("%08x POP\n",instruction);
00900 #endif
00901 opStackDepth -= 1;
00902 opStackRegType[opStackDepth] = 0;
00903 opStackLoadInstructionAddr[opStackDepth-1] = 0;
00904 break;
00905 case OP_LEAVE:
00906 #if DEBUG_VM
00907 if(pass == 1)
00908 printf("%08x LEAVE\n",instruction);
00909 #endif
00910 assert(opStackDepth == 1);
00911 assert(opStackRegType[0] != 0);
00912
00913 switch(opStackRegType[0])
00914 {
00915 case 1:
00916 InstImm( "stw", PPC_STWU, opStackIntRegisters[0], R_OPSTACK, 4);
00917 break;
00918 case 2:
00919 InstImm( "stfs", PPC_STFSU, opStackFloatRegisters[0], R_OPSTACK, 4);
00920 break;
00921 }
00922 InstImm( "addi", PPC_ADDI, R_STACK, R_STACK, Constant4() );
00923 if(mainFunction == 1)
00924 {
00925 for(i = 0; i < OP_STACK_MAX_DEPTH; i++)
00926 InstImm( "lwz", PPC_LWZ, opStackIntRegisters[i], R_REAL_STACK, i*4);
00927 InstImm( "addi", PPC_ADDI, R_REAL_STACK, R_REAL_STACK, OP_STACK_MAX_DEPTH*4 );
00928 }
00929 opStackDepth--;
00930 opStackRegType[opStackDepth] = 0;
00931 opStackLoadInstructionAddr[opStackDepth] = 0;
00932 Inst( "blr", PPC_BCLR, 20, 0, 0 );
00933 break;
00934 case OP_LOAD4:
00935 #if DEBUG_VM
00936 if(pass == 1)
00937 printf("%08x LOAD4\n",instruction);
00938 #endif
00939
00940
00941
00942
00943
00944
00945 assertInteger(opStackDepth-1);
00946 opStackLoadInstructionAddr[opStackDepth-1] = &buf[ compiledOfs ];
00947 Inst( "lwzx", PPC_LWZX, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_MEMBASE );
00948 opStackRegType[opStackDepth-1] = 1;
00949 break;
00950 case OP_LOAD2:
00951 #if DEBUG_VM
00952 if(pass == 1)
00953 printf("%08x LOAD2\n",instruction);
00954 #endif
00955 assertInteger(opStackDepth-1);
00956 opStackLoadInstructionAddr[opStackDepth-1] = 0;
00957 Inst( "lhzx", PPC_LHZX, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_MEMBASE );
00958 opStackRegType[opStackDepth-1] = 1;
00959 break;
00960 case OP_LOAD1:
00961 #if DEBUG_VM
00962 if(pass == 1)
00963 printf("%08x LOAD1\n",instruction);
00964 #endif
00965 assertInteger(opStackDepth-1);
00966 opStackLoadInstructionAddr[opStackDepth-1] = 0;
00967 Inst( "lbzx", PPC_LBZX, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_MEMBASE );
00968 opStackRegType[opStackDepth-1] = 1;
00969 break;
00970 case OP_STORE4:
00971 #if DEBUG_VM
00972 if(pass == 1)
00973 printf("%08x STORE4\n",instruction);
00974 #endif
00975 assertInteger(opStackDepth-2);
00976 if(opStackRegType[opStackDepth-1] == 1)
00977 Inst( "stwx", PPC_STWX, opStackIntRegisters[opStackDepth-1],
00978 opStackIntRegisters[opStackDepth-2], R_MEMBASE );
00979 else
00980 Inst( "stfsx", PPC_STFSX, opStackFloatRegisters[opStackDepth-1],
00981 opStackIntRegisters[opStackDepth-2], R_MEMBASE );
00982 opStackRegType[opStackDepth-1] = 0;
00983 opStackRegType[opStackDepth-2] = 0;
00984 opStackLoadInstructionAddr[opStackDepth-1] = 0;
00985 opStackLoadInstructionAddr[opStackDepth-2] = 0;
00986 opStackDepth -= 2;
00987 break;
00988 case OP_STORE2:
00989 #if DEBUG_VM
00990 if(pass == 1)
00991 printf("%08x STORE2\n",instruction);
00992 #endif
00993 assertInteger(opStackDepth-1);
00994 assertInteger(opStackDepth-2);
00995 Inst( "sthx", PPC_STHX, opStackIntRegisters[opStackDepth-1],
00996 opStackIntRegisters[opStackDepth-2], R_MEMBASE );
00997 opStackRegType[opStackDepth-1] = 0;
00998 opStackRegType[opStackDepth-2] = 0;
00999 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01000 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01001 opStackDepth -= 2;
01002 break;
01003 case OP_STORE1:
01004 #if DEBUG_VM
01005 if(pass == 1)
01006 printf("%08x STORE1\n",instruction);
01007 #endif
01008 assertInteger(opStackDepth-1);
01009 assertInteger(opStackDepth-2);
01010 Inst( "stbx", PPC_STBX, opStackIntRegisters[opStackDepth-1],
01011 opStackIntRegisters[opStackDepth-2], R_MEMBASE );
01012 opStackRegType[opStackDepth-1] = 0;
01013 opStackRegType[opStackDepth-2] = 0;
01014 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01015 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01016 opStackDepth -= 2;
01017 break;
01018
01019 case OP_EQ:
01020 #if DEBUG_VM
01021 if(pass == 1)
01022 printf("%08x EQ\n",instruction);
01023 #endif
01024 assertInteger(opStackDepth-1);
01025 assertInteger(opStackDepth-2);
01026 Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01027 opStackRegType[opStackDepth-1] = 0;
01028 opStackRegType[opStackDepth-2] = 0;
01029 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01030 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01031 opStackDepth -= 2;
01032 i = Constant4();
01033 jused[i] = 1;
01034 InstImm( "bc", PPC_BC, 4, 2, 8 );
01035 if ( pass==1 ) {
01036 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
01037 } else {
01038 v = 0;
01039 }
01040 Emit4("b", PPC_B | (v&0x3ffffff) );
01041 break;
01042 case OP_NE:
01043 #if DEBUG_VM
01044 if(pass == 1)
01045 printf("%08x NE\n",instruction);
01046 #endif
01047 assertInteger(opStackDepth-1);
01048 assertInteger(opStackDepth-2);
01049 Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01050 opStackRegType[opStackDepth-1] = 0;
01051 opStackRegType[opStackDepth-2] = 0;
01052 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01053 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01054 opStackDepth -= 2;
01055 i = Constant4();
01056 jused[i] = 1;
01057 InstImm( "bc", PPC_BC, 12, 2, 8 );
01058 if ( pass==1 ) {
01059 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
01060 } else {
01061 v = 0;
01062 }
01063 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
01064
01065
01066 break;
01067 case OP_LTI:
01068 #if DEBUG_VM
01069 if(pass == 1)
01070 printf("%08x LTI\n",instruction);
01071 #endif
01072 assertInteger(opStackDepth-1);
01073 assertInteger(opStackDepth-2);
01074 Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01075 opStackRegType[opStackDepth-1] = 0;
01076 opStackRegType[opStackDepth-2] = 0;
01077 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01078 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01079 opStackDepth -= 2;
01080 i = Constant4();
01081 jused[i] = 1;
01082 InstImm( "bc", PPC_BC, 4, 0, 8 );
01083 if ( pass==1 ) {
01084 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
01085 } else {
01086 v = 0;
01087 }
01088 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
01089
01090 break;
01091 case OP_LEI:
01092 #if DEBUG_VM
01093 if(pass == 1)
01094 printf("%08x LEI\n",instruction);
01095 #endif
01096 assertInteger(opStackDepth-1);
01097 assertInteger(opStackDepth-2);
01098 Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01099 opStackRegType[opStackDepth-1] = 0;
01100 opStackRegType[opStackDepth-2] = 0;
01101 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01102 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01103 opStackDepth -= 2;
01104 i = Constant4();
01105 jused[i] = 1;
01106 InstImm( "bc", PPC_BC, 12, 1, 8 );
01107 if ( pass==1 ) {
01108 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
01109 } else {
01110 v = 0;
01111 }
01112 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
01113
01114 break;
01115 case OP_GTI:
01116 #if DEBUG_VM
01117 if(pass == 1)
01118 printf("%08x GTI\n",instruction);
01119 #endif
01120 assertInteger(opStackDepth-1);
01121 assertInteger(opStackDepth-2);
01122 Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01123 opStackRegType[opStackDepth-1] = 0;
01124 opStackRegType[opStackDepth-2] = 0;
01125 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01126 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01127 opStackDepth -= 2;
01128 i = Constant4();
01129 jused[i] = 1;
01130 InstImm( "bc", PPC_BC, 4, 1, 8 );
01131 if ( pass==1 ) {
01132 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
01133 } else {
01134 v = 0;
01135 }
01136 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
01137
01138 break;
01139 case OP_GEI:
01140 #if DEBUG_VM
01141 if(pass == 1)
01142 printf("%08x GEI\n",instruction);
01143 #endif
01144 assertInteger(opStackDepth-1);
01145 assertInteger(opStackDepth-2);
01146 Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01147 opStackRegType[opStackDepth-1] = 0;
01148 opStackRegType[opStackDepth-2] = 0;
01149 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01150 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01151 opStackDepth -= 2;
01152 i = Constant4();
01153 jused[i] = 1;
01154 InstImm( "bc", PPC_BC, 12, 0, 8 );
01155 if ( pass==1 ) {
01156 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
01157 } else {
01158 v = 0;
01159 }
01160 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
01161
01162 break;
01163 case OP_LTU:
01164 #if DEBUG_VM
01165 if(pass == 1)
01166 printf("%08x LTU\n",instruction);
01167 #endif
01168 assertInteger(opStackDepth-1);
01169 assertInteger(opStackDepth-2);
01170 Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01171 opStackRegType[opStackDepth-1] = 0;
01172 opStackRegType[opStackDepth-2] = 0;
01173 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01174 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01175 opStackDepth -= 2;
01176 i = Constant4();
01177 jused[i] = 1;
01178 InstImm( "bc", PPC_BC, 4, 0, 8 );
01179 if ( pass==1 ) {
01180 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
01181 } else {
01182 v = 0;
01183 }
01184 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
01185
01186 break;
01187 case OP_LEU:
01188 #if DEBUG_VM
01189 if(pass == 1)
01190 printf("%08x LEU\n",instruction);
01191 #endif
01192 assertInteger(opStackDepth-1);
01193 assertInteger(opStackDepth-2);
01194 Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01195 opStackRegType[opStackDepth-1] = 0;
01196 opStackRegType[opStackDepth-2] = 0;
01197 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01198 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01199 opStackDepth -= 2;
01200 i = Constant4();
01201 jused[i] = 1;
01202 InstImm( "bc", PPC_BC, 12, 1, 8 );
01203 if ( pass==1 ) {
01204 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
01205 } else {
01206 v = 0;
01207 }
01208 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
01209
01210 break;
01211 case OP_GTU:
01212 #if DEBUG_VM
01213 if(pass == 1)
01214 printf("%08x GTU\n",instruction);
01215 #endif
01216 assertInteger(opStackDepth-1);
01217 assertInteger(opStackDepth-2);
01218 Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01219 opStackRegType[opStackDepth-1] = 0;
01220 opStackRegType[opStackDepth-2] = 0;
01221 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01222 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01223 opStackDepth -= 2;
01224 i = Constant4();
01225 jused[i] = 1;
01226 InstImm( "bc", PPC_BC, 4, 1, 8 );
01227 if ( pass==1 ) {
01228 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
01229 } else {
01230 v = 0;
01231 }
01232 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
01233
01234 break;
01235 case OP_GEU:
01236 #if DEBUG_VM
01237 if(pass == 1)
01238 printf("%08x GEU\n",instruction);
01239 #endif
01240 assertInteger(opStackDepth-1);
01241 assertInteger(opStackDepth-2);
01242 Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01243 opStackRegType[opStackDepth-1] = 0;
01244 opStackRegType[opStackDepth-2] = 0;
01245 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01246 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01247 opStackDepth -= 2;
01248 i = Constant4();
01249 jused[i] = 1;
01250 InstImm( "bc", PPC_BC, 12, 0, 8 );
01251 if ( pass==1 ) {
01252 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
01253 } else {
01254 v = 0;
01255 }
01256 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
01257
01258 break;
01259
01260 case OP_EQF:
01261 #if DEBUG_VM
01262 if(pass == 1)
01263 printf("%08x EQF\n",instruction);
01264 #endif
01265 makeFloat(opStackDepth-1);
01266 makeFloat(opStackDepth-2);
01267 Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
01268 opStackRegType[opStackDepth-1] = 0;
01269 opStackRegType[opStackDepth-2] = 0;
01270 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01271 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01272 opStackDepth -= 2;
01273 i = Constant4();
01274 jused[i] = 1;
01275 InstImm( "bc", PPC_BC, 4, 2, 8 );
01276 if ( pass==1 ) {
01277 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
01278 } else {
01279 v = 0;
01280 }
01281 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
01282
01283 break;
01284 case OP_NEF:
01285 #if DEBUG_VM
01286 if(pass == 1)
01287 printf("%08x NEF\n",instruction);
01288 #endif
01289 makeFloat(opStackDepth-1);
01290 makeFloat(opStackDepth-2);
01291 Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
01292 opStackRegType[opStackDepth-1] = 0;
01293 opStackRegType[opStackDepth-2] = 0;
01294 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01295 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01296 opStackDepth -= 2;
01297 i = Constant4();
01298 jused[i] = 1;
01299 InstImm( "bc", PPC_BC, 12, 2, 8 );
01300 if ( pass==1 ) {
01301 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
01302 } else {
01303 v = 0;
01304 }
01305 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
01306
01307 break;
01308 case OP_LTF:
01309 #if DEBUG_VM
01310 if(pass == 1)
01311 printf("%08x LTF\n",instruction);
01312 #endif
01313 makeFloat(opStackDepth-1);
01314 makeFloat(opStackDepth-2);
01315 Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
01316 opStackRegType[opStackDepth-1] = 0;
01317 opStackRegType[opStackDepth-2] = 0;
01318 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01319 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01320 opStackDepth -= 2;
01321 i = Constant4();
01322 jused[i] = 1;
01323 InstImm( "bc", PPC_BC, 4, 0, 8 );
01324 if ( pass==1 ) {
01325 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
01326 } else {
01327 v = 0;
01328 }
01329 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
01330
01331 break;
01332 case OP_LEF:
01333 #if DEBUG_VM
01334 if(pass == 1)
01335 printf("%08x LEF\n",instruction);
01336 #endif
01337 makeFloat(opStackDepth-1);
01338 makeFloat(opStackDepth-2);
01339 Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
01340 opStackRegType[opStackDepth-1] = 0;
01341 opStackRegType[opStackDepth-2] = 0;
01342 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01343 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01344 opStackDepth -= 2;
01345 i = Constant4();
01346 jused[i] = 1;
01347 InstImm( "bc", PPC_BC, 12, 1, 8 );
01348 if ( pass==1 ) {
01349 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
01350 } else {
01351 v = 0;
01352 }
01353 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
01354
01355 break;
01356 case OP_GTF:
01357 #if DEBUG_VM
01358 if(pass == 1)
01359 printf("%08x GTF\n",instruction);
01360 #endif
01361 makeFloat(opStackDepth-1);
01362 makeFloat(opStackDepth-2);
01363 Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
01364 opStackRegType[opStackDepth-1] = 0;
01365 opStackRegType[opStackDepth-2] = 0;
01366 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01367 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01368 opStackDepth -= 2;
01369 i = Constant4();
01370 jused[i] = 1;
01371 InstImm( "bc", PPC_BC, 4, 1, 8 );
01372 if ( pass==1 ) {
01373 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
01374 } else {
01375 v = 0;
01376 }
01377 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
01378
01379 break;
01380 case OP_GEF:
01381 #if DEBUG_VM
01382 if(pass == 1)
01383 printf("%08x GEF\n",instruction);
01384 #endif
01385 makeFloat(opStackDepth-1);
01386 makeFloat(opStackDepth-2);
01387 Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
01388 opStackRegType[opStackDepth-1] = 0;
01389 opStackRegType[opStackDepth-2] = 0;
01390 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01391 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01392 opStackDepth -= 2;
01393 i = Constant4();
01394 jused[i] = 1;
01395 InstImm( "bc", PPC_BC, 12, 0, 8 );
01396 if ( pass==1 ) {
01397 v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
01398 } else {
01399 v = 0;
01400 }
01401 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
01402
01403 break;
01404
01405 case OP_NEGI:
01406 #if DEBUG_VM
01407 if(pass == 1)
01408 printf("%08x NEGI\n",instruction);
01409 #endif
01410 assertInteger(opStackDepth-1);
01411 InstImm( "subfic", PPC_SUBFIC, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 0 );
01412 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01413 break;
01414 case OP_ADD:
01415 #if DEBUG_VM
01416 if(pass == 1)
01417 printf("%08x ADD\n",instruction);
01418 #endif
01419 assertInteger(opStackDepth-1);
01420 assertInteger(opStackDepth-2);
01421 Inst( "add", PPC_ADD, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-2] );
01422 opStackRegType[opStackDepth-1] = 0;
01423 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01424 opStackDepth -= 1;
01425 break;
01426 case OP_SUB:
01427 #if DEBUG_VM
01428 if(pass == 1)
01429 printf("%08x SUB\n",instruction);
01430 #endif
01431 assertInteger(opStackDepth-1);
01432 assertInteger(opStackDepth-2);
01433 Inst( "subf", PPC_SUBF, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-2] );
01434 opStackRegType[opStackDepth-1] = 0;
01435 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01436 opStackDepth -= 1;
01437 break;
01438 case OP_DIVI:
01439 #if DEBUG_VM
01440 if(pass == 1)
01441 printf("%08x DIVI\n",instruction);
01442 #endif
01443 assertInteger(opStackDepth-1);
01444 assertInteger(opStackDepth-2);
01445 Inst( "divw", PPC_DIVW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01446 opStackRegType[opStackDepth-1] = 0;
01447 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01448 opStackDepth -= 1;
01449 break;
01450 case OP_DIVU:
01451 #if DEBUG_VM
01452 if(pass == 1)
01453 printf("%08x DIVU\n",instruction);
01454 #endif
01455 assertInteger(opStackDepth-1);
01456 assertInteger(opStackDepth-2);
01457 Inst( "divwu", PPC_DIVWU, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01458 opStackRegType[opStackDepth-1] = 0;
01459 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01460 opStackDepth -= 1;
01461 break;
01462 case OP_MODI:
01463 #if DEBUG_VM
01464 if(pass == 1)
01465 printf("%08x MODI\n",instruction);
01466 #endif
01467 assertInteger(opStackDepth-1);
01468 assertInteger(opStackDepth-2);
01469 Inst( "divw", PPC_DIVW, R_EA, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01470 Inst( "mullw", PPC_MULLW, R_EA, opStackIntRegisters[opStackDepth-1], R_EA );
01471 Inst( "subf", PPC_SUBF, opStackIntRegisters[opStackDepth-2], R_EA, opStackIntRegisters[opStackDepth-2] );
01472 opStackRegType[opStackDepth-1] = 0;
01473 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01474 opStackDepth -= 1;
01475 break;
01476 case OP_MODU:
01477 #if DEBUG_VM
01478 if(pass == 1)
01479 printf("%08x MODU\n",instruction);
01480 #endif
01481 assertInteger(opStackDepth-1);
01482 assertInteger(opStackDepth-2);
01483 Inst( "divwu", PPC_DIVWU, R_EA, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01484 Inst( "mullw", PPC_MULLW, R_EA, opStackIntRegisters[opStackDepth-1], R_EA );
01485 Inst( "subf", PPC_SUBF, opStackIntRegisters[opStackDepth-2], R_EA, opStackIntRegisters[opStackDepth-2] );
01486 opStackRegType[opStackDepth-1] = 0;
01487 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01488 opStackDepth -= 1;
01489 break;
01490 case OP_MULI:
01491 case OP_MULU:
01492 #if DEBUG_VM
01493 if(pass == 1)
01494 printf("%08x MULI\n",instruction);
01495 #endif
01496 assertInteger(opStackDepth-1);
01497 assertInteger(opStackDepth-2);
01498 Inst( "mullw", PPC_MULLW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-2] );
01499 opStackRegType[opStackDepth-1] = 0;
01500 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01501 opStackDepth -= 1;
01502 break;
01503 case OP_BAND:
01504 #if DEBUG_VM
01505 if(pass == 1)
01506 printf("%08x BAND\n",instruction);
01507 #endif
01508 assertInteger(opStackDepth-1);
01509 assertInteger(opStackDepth-2);
01510 Inst( "and", PPC_AND, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01511 opStackRegType[opStackDepth-1] = 0;
01512 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01513 opStackDepth -= 1;
01514 break;
01515 case OP_BOR:
01516 #if DEBUG_VM
01517 if(pass == 1)
01518 printf("%08x BOR\n",instruction);
01519 #endif
01520 assertInteger(opStackDepth-1);
01521 assertInteger(opStackDepth-2);
01522 Inst( "or", PPC_OR, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01523 opStackRegType[opStackDepth-1] = 0;
01524 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01525 opStackDepth -= 1;
01526 break;
01527 case OP_BXOR:
01528 #if DEBUG_VM
01529 if(pass == 1)
01530 printf("%08x BXOR\n",instruction);
01531 #endif
01532 assertInteger(opStackDepth-1);
01533 assertInteger(opStackDepth-2);
01534 Inst( "xor", PPC_XOR, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01535 opStackRegType[opStackDepth-1] = 0;
01536 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01537 opStackDepth -= 1;
01538 break;
01539 case OP_BCOM:
01540 #if DEBUG_VM
01541 if(pass == 1)
01542 printf("%08x BCOM\n",instruction);
01543 #endif
01544 assertInteger(opStackDepth-1);
01545 Inst( "nor", PPC_NOR, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1] );
01546 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01547 break;
01548 case OP_LSH:
01549 #if DEBUG_VM
01550 if(pass == 1)
01551 printf("%08x LSH\n",instruction);
01552 #endif
01553 assertInteger(opStackDepth-1);
01554 assertInteger(opStackDepth-2);
01555 Inst( "slw", PPC_SLW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01556 opStackRegType[opStackDepth-1] = 0;
01557 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01558 opStackDepth -= 1;
01559 break;
01560 case OP_RSHI:
01561 #if DEBUG_VM
01562 if(pass == 1)
01563 printf("%08x RSHI\n",instruction);
01564 #endif
01565 assertInteger(opStackDepth-1);
01566 assertInteger(opStackDepth-2);
01567 Inst( "sraw", PPC_SRAW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01568 opStackRegType[opStackDepth-1] = 0;
01569 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01570 opStackDepth -= 1;
01571 break;
01572 case OP_RSHU:
01573 #if DEBUG_VM
01574 if(pass == 1)
01575 printf("%08x RSHU\n",instruction);
01576 #endif
01577 assertInteger(opStackDepth-1);
01578 assertInteger(opStackDepth-2);
01579 Inst( "srw", PPC_SRW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
01580 opStackRegType[opStackDepth-1] = 0;
01581 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01582 opStackDepth -= 1;
01583 break;
01584
01585 case OP_NEGF:
01586 #if DEBUG_VM
01587 if(pass == 1)
01588 printf("%08x NEGF\n",instruction);
01589 #endif
01590 makeFloat(opStackDepth-1);
01591 Inst( "fneg", PPC_FNEG, opStackFloatRegisters[opStackDepth-1], 0, opStackFloatRegisters[opStackDepth-1] );
01592 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01593 break;
01594 case OP_ADDF:
01595 #if DEBUG_VM
01596 if(pass == 1)
01597 printf("%08x ADDF\n",instruction);
01598 #endif
01599 makeFloat(opStackDepth-1);
01600 makeFloat(opStackDepth-2);
01601 Inst( "fadds", PPC_FADDS, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
01602 opStackRegType[opStackDepth-1] = 0;
01603 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01604 opStackDepth -= 1;
01605 break;
01606 case OP_SUBF:
01607 #if DEBUG_VM
01608 if(pass == 1)
01609 printf("%08x SUBF\n",instruction);
01610 #endif
01611 makeFloat(opStackDepth-1);
01612 makeFloat(opStackDepth-2);
01613 Inst( "fsubs", PPC_FSUBS, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
01614 opStackRegType[opStackDepth-1] = 0;
01615 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01616 opStackDepth -= 1;
01617 break;
01618 case OP_DIVF:
01619 #if DEBUG_VM
01620 if(pass == 1)
01621 printf("%08x DIVF\n",instruction);
01622 #endif
01623 makeFloat(opStackDepth-1);
01624 makeFloat(opStackDepth-2);
01625 Inst( "fdivs", PPC_FDIVS, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
01626 opStackRegType[opStackDepth-1] = 0;
01627 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01628 opStackDepth -= 1;
01629 break;
01630 case OP_MULF:
01631 #if DEBUG_VM
01632 if(pass == 1)
01633 printf("%08x MULF\n",instruction);
01634 #endif
01635 makeFloat(opStackDepth-1);
01636 makeFloat(opStackDepth-2);
01637 Inst4( "fmuls", PPC_FMULS, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-2], 0, opStackFloatRegisters[opStackDepth-1] );
01638 opStackRegType[opStackDepth-1] = 0;
01639 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01640 opStackDepth -= 1;
01641 break;
01642
01643 case OP_CVIF:
01644 #if DEBUG_VM
01645 if(pass == 1)
01646 printf("%08x CVIF\n",instruction);
01647 #endif
01648 assertInteger(opStackDepth-1);
01649
01650 v = (int)&itofConvert;
01651 InstImmU( "addis", PPC_ADDIS, R_EA, 0, (v >> 16)&0xffff );
01652 InstImmU( "ori", PPC_ORI, R_EA, R_EA, v & 0xffff );
01653 InstImmU( "xoris", PPC_XORIS, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 0x8000 );
01654 InstImm( "stw", PPC_STW, opStackIntRegisters[opStackDepth-1], R_EA, 12 );
01655 InstImm( "lfd", PPC_LFD, opStackFloatRegisters[opStackDepth-1], R_EA, 0 );
01656 Inst( "ori", PPC_ORI, 0, 0, 0);
01657 Inst( "ori", PPC_ORI, 0, 0, 0);
01658 Inst( "ori", PPC_ORI, 0, 0, 0);
01659 InstImm( "lfd", PPC_LFD, 13, R_EA, 8 );
01660 Inst( "fsub", PPC_FSUB, opStackFloatRegisters[opStackDepth-1], 13, opStackFloatRegisters[opStackDepth-1] );
01661 opStackRegType[opStackDepth-1] = 2;
01662 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01663
01664 break;
01665 case OP_CVFI:
01666 #if DEBUG_VM
01667 if(pass == 1)
01668 printf("%08x CVFI\n",instruction);
01669 #endif
01670 makeFloat(opStackDepth-1);
01671
01672 InstImm( "addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, opStackDepth*4);
01673
01674 Inst( "fctiwz", PPC_FCTIWZ, opStackFloatRegisters[opStackDepth-1], 0, opStackFloatRegisters[opStackDepth-1] );
01675 Inst( "stfiwx", PPC_STFIWX, opStackFloatRegisters[opStackDepth-1], 0, R_OPSTACK );
01676 Inst( "ori", PPC_ORI, 0, 0, 0);
01677 Inst( "ori", PPC_ORI, 0, 0, 0);
01678 Inst( "ori", PPC_ORI, 0, 0, 0);
01679 Inst( "ori", PPC_ORI, 0, 0, 0);
01680 InstImm( "lwz", PPC_LWZ, opStackIntRegisters[opStackDepth-1], R_OPSTACK, 0 );
01681
01682 InstImm( "addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, -opStackDepth*4);
01683
01684 opStackRegType[opStackDepth-1] = 1;
01685 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01686 break;
01687 case OP_SEX8:
01688 #if DEBUG_VM
01689 if(pass == 1)
01690 printf("%08x SEX8\n",instruction);
01691 #endif
01692 assertInteger(opStackDepth-1);
01693 Inst( "extsb", PPC_EXTSB, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 0 );
01694 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01695 break;
01696 case OP_SEX16:
01697 #if DEBUG_VM
01698 if(pass == 1)
01699 printf("%08x SEX16\n",instruction);
01700 #endif
01701 assertInteger(opStackDepth-1);
01702 Inst( "extsh", PPC_EXTSH, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 0 );
01703 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01704 break;
01705
01706 case OP_BLOCK_COPY:
01707 v = Constant4() >> 2;
01708 #if DEBUG_VM
01709 if(pass == 1)
01710 printf("%08x BLOCK_COPY\t%08lx\n",instruction,v<<2);
01711 #endif
01712 assert(opStackDepth >= 2);
01713 assertInteger(opStackDepth-1);
01714 assertInteger(opStackDepth-2);
01715 InstImmU( "addi", PPC_ADDI, R_EA, 0, v );
01716
01717 Inst( "mtctr", PPC_MTSPR, R_EA, 9, 0 );
01718
01719 Inst( "add", PPC_ADD, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_MEMBASE );
01720 InstImm( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], -4 );
01721 Inst( "add", PPC_ADD, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], R_MEMBASE );
01722 InstImm( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], -4 );
01723
01724 InstImm( "lwzu", PPC_LWZU, R_EA, opStackIntRegisters[opStackDepth-1], 4 );
01725 InstImm( "stwu", PPC_STWU, R_EA, opStackIntRegisters[opStackDepth-2], 4 );
01726 Inst( "b", PPC_BC | 0xfff8 , 16, 0, 0 );
01727 opStackRegType[opStackDepth-1] = 0;
01728 opStackRegType[opStackDepth-2] = 0;
01729 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01730 opStackLoadInstructionAddr[opStackDepth-2] = 0;
01731 opStackDepth -= 2;
01732 break;
01733
01734 case OP_JUMP:
01735 #if DEBUG_VM
01736 if(pass == 1)
01737 printf("%08x JUMP\n",instruction);
01738 #endif
01739 assert(opStackDepth == 1);
01740 assertInteger(opStackDepth-1);
01741
01742 Inst( "rlwinm", PPC_RLWINM | ( 29 << 1 ), opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 2 );
01743
01744 Inst( "lwzx", PPC_LWZX, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_INSTRUCTIONS );
01745 Inst( "mtctr", PPC_MTSPR, opStackIntRegisters[opStackDepth-1], 9, 0 );
01746 Inst( "bctr", PPC_BCCTR, 20, 0, 0 );
01747 opStackRegType[opStackDepth-1] = 0;
01748 opStackLoadInstructionAddr[opStackDepth-1] = 0;
01749 opStackDepth -= 1;
01750 break;
01751 default:
01752 Com_Error( ERR_DROP, "VM_CompilePPC: bad opcode %i at instruction %i, offset %i", op, instruction, pc );
01753 }
01754 pop0 = pop1;
01755 pop1 = op;
01756 assert(opStackDepth >= 0);
01757 assert(opStackDepth < OP_STACK_MAX_DEPTH);
01758
01759
01760 }
01761
01762 Com_Printf( "VM file %s pass %d compiled to %i bytes of code\n", vm->name, (pass+1), compiledOfs*4 );
01763
01764 if ( pass == 0 ) {
01765
01766 vm->codeLength = compiledOfs * 4;
01767 vm->codeBase = Hunk_Alloc( vm->codeLength, h_low );
01768 Com_Memcpy( vm->codeBase, buf, vm->codeLength );
01769
01770
01771
01772 Z_Free( buf );
01773
01774
01775 for ( i = 0 ; i < header->instructionCount ; i++ ) {
01776 vm->instructionPointers[i] += (int)vm->codeBase;
01777
01778 }
01779
01780
01781 buf = (unsigned *)vm->codeBase;
01782 }
01783 }
01784 if(0)
01785 {
01786 char buf[256];
01787 printf("wait..\n");
01788 gets(buf);
01789 }
01790 Z_Free( jused );
01791 }
01792
01793
01794
01795
01796
01797
01798
01799
01800 int VM_CallCompiled( vm_t *vm, int *args ) {
01801 int stack[1024];
01802 int programStack;
01803 int stackOnEntry;
01804 byte *image;
01805
01806 currentVM = vm;
01807
01808
01809
01810
01811
01812 vm->currentlyInterpreting = qtrue;
01813
01814
01815 programStack = vm->programStack;
01816 stackOnEntry = programStack;
01817 image = vm->dataBase;
01818
01819
01820 programStack -= 48;
01821
01822 *(int *)&image[ programStack + 44] = args[9];
01823 *(int *)&image[ programStack + 40] = args[8];
01824 *(int *)&image[ programStack + 36] = args[7];
01825 *(int *)&image[ programStack + 32] = args[6];
01826 *(int *)&image[ programStack + 28] = args[5];
01827 *(int *)&image[ programStack + 24] = args[4];
01828 *(int *)&image[ programStack + 20] = args[3];
01829 *(int *)&image[ programStack + 16] = args[2];
01830 *(int *)&image[ programStack + 12] = args[1];
01831 *(int *)&image[ programStack + 8 ] = args[0];
01832 *(int *)&image[ programStack + 4 ] = 0;
01833 *(int *)&image[ programStack ] = -1;
01834
01835
01836
01837
01838
01839 #ifdef __GNUC__
01840 ((void(*)(int, int, int, int, int, int, int, int))(vm->codeBase))(
01841 programStack, (int)&stack,
01842 (int)image, vm->dataMask, (int)&AsmCall,
01843 (int)vm->instructionPointers, vm->instructionPointersLength,
01844 (int)vm );
01845 #else
01846 ((void(*)(int, int, int, int, int, int, int, int))(vm->codeBase))(
01847 programStack, (int)&stack,
01848 (int)image, vm->dataMask, *(int *)&AsmCall ,
01849 (int)vm->instructionPointers, vm->instructionPointersLength,
01850 (int)vm );
01851 #endif
01852 vm->programStack = stackOnEntry;
01853
01854 vm->currentlyInterpreting = qfalse;
01855
01856 return stack[1];
01857 }
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867 #ifdef __GNUC__
01868
01869 void AsmCall( void ) {
01870 asm (
01871
01872 " lwz r12,0(r4) \n"
01873 " addi r4,r4,-4 \n"
01874
01875
01876 " cmpwi r12,0 \n"
01877 " bc 12,0, systemTrap \n"
01878
01879
01880 " slwi r12,r12,2 \n"
01881
01882 " lwzx r12, r8, r12 \n"
01883 " mtctr r12 \n"
01884 );
01885
01886 #if defined(MACOS_X) && defined(__OPTIMIZE__)
01887
01888 #warning Mac OS X optimization on, not popping GCC AsmCall frame
01889 #else
01890
01891 asm (
01892 " lwz r1,0(r1) \n"
01893 " lmw r30,-8(r1) \n"
01894 );
01895 #endif
01896
01897 asm (
01898 " bcctr 20,0 \n"
01899
01900
01901 "systemTrap: \n"
01902
01903 " subfic r12,r12,-1 \n"
01904
01905
01906 " mflr r13 \n"
01907 " addi r1,r1,-92 \n"
01908 " stw r3,56(r1) \n"
01909 " stw r4,60(r1) \n"
01910 " stw r5,64(r1) \n"
01911 " stw r6,68(r1) \n"
01912 " stw r7,72(r1) \n"
01913 " stw r8,76(r1) \n"
01914 " stw r9,80(r1) \n"
01915 " stw r10,84(r1) \n"
01916 " stw r13,88(r1) \n"
01917
01918
01919 " addi r13,r3,-4 \n"
01920 " stw r13,0(r10) \n"
01921
01922
01923 " add r3,r3,r5 \n"
01924 " stwu r12,4(r3) \n"
01925
01926
01927
01928 " lwz r12,4(r10) \n"
01929 " mtctr r12 \n"
01930 " bcctrl 20,0 \n"
01931 " mr r12,r3 \n"
01932
01933
01934 " lwz r3,56(r1) \n"
01935 " lwz r4,60(r1) \n"
01936 " lwz r5,64(r1) \n"
01937 " lwz r6,68(r1) \n"
01938 " lwz r7,72(r1) \n"
01939 " lwz r8,76(r1) \n"
01940 " lwz r9,80(r1) \n"
01941 " lwz r10,84(r1) \n"
01942 " lwz r13,88(r1) \n"
01943 " addi r1,r1,92 \n"
01944
01945
01946 " mtlr r13 \n"
01947
01948
01949 " stwu r12,4(r4) \n"
01950
01951
01952 );
01953 }
01954 #else
01955
01956
01957
01958 void asm AsmCall( void ) {
01959
01960
01961
01962 lwz r12,0(r4)
01963
01964 addi r4,r4,-4
01965
01966
01967
01968
01969
01970 cmpwi r12,0
01971
01972 bc 12,0, systemTrap
01973
01974
01975
01976
01977
01978 slwi r12,r12,2
01979
01980
01981
01982 lwzx r12, r8, r12
01983
01984 mtctr r12
01985
01986
01987
01988 bcctr 20,0
01989
01990
01991
01992
01993
01994 systemTrap:
01995
01996
01997
01998 subfic r12,r12,-1
01999
02000
02001
02002
02003
02004 mflr r13
02005
02006 addi r1,r1,-92
02007
02008 stw r3,56(r1)
02009
02010 stw r4,60(r1)
02011
02012 stw r5,64(r1)
02013
02014 stw r6,68(r1)
02015
02016 stw r7,72(r1)
02017
02018 stw r8,76(r1)
02019
02020 stw r9,80(r1)
02021
02022 stw r10,84(r1)
02023
02024 stw r13,88(r1)
02025
02026
02027
02028
02029
02030 addi r13,r3,-4
02031
02032 stw r13,0(r10)
02033
02034
02035
02036
02037
02038 add r3,r3,r5
02039
02040 stwu r12,4(r3)
02041
02042
02043
02044
02045
02046
02047
02048 lwz r12,4(r10)
02049
02050
02051
02052
02053
02054 lwz r9,0(r12)
02055
02056 stw r2,52(r1)
02057
02058 lwz r2,4(r12)
02059
02060
02061
02062 mtctr r9
02063
02064 bcctrl 20,0
02065
02066
02067
02068 lwz r2,52(r1)
02069
02070
02071
02072 mr r12,r3
02073
02074
02075
02076
02077
02078 lwz r3,56(r1)
02079
02080 lwz r4,60(r1)
02081
02082 lwz r5,64(r1)
02083
02084 lwz r6,68(r1)
02085
02086 lwz r7,72(r1)
02087
02088 lwz r8,76(r1)
02089
02090 lwz r9,80(r1)
02091
02092 lwz r10,84(r1)
02093
02094 lwz r13,88(r1)
02095
02096 addi r1,r1,92
02097
02098
02099
02100
02101
02102 mtlr r13
02103
02104
02105
02106
02107
02108 stwu r12,4(r4)
02109
02110
02111
02112 blr
02113
02114 }
02115
02116
02117
02118
02119 #endif