1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4 
5 This file is part of Quake III Arena source code.
6 
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11 
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 ===========================================================================
21 */
22 // vm_ppc.c
23 // ppc dynamic compiler
24 
25 #include "vm_local.h"
26 #include <sys/mman.h>
27 
28 #define DEBUG_VM 0
29 
30 #if DEBUG_VM
31 static char	*opnames[256] = {
32 	"OP_UNDEF",
33 
34 	"OP_IGNORE",
35 
36 	"OP_BREAK",
37 
38 	"OP_ENTER",
39 	"OP_LEAVE",
40 	"OP_CALL",
41 	"OP_PUSH",
42 	"OP_POP",
43 
44 	"OP_CONST",
45 
46 	"OP_LOCAL",
47 
48 	"OP_JUMP",
49 
50 	//-------------------
51 
52 	"OP_EQ",
53 	"OP_NE",
54 
55 	"OP_LTI",
56 	"OP_LEI",
57 	"OP_GTI",
58 	"OP_GEI",
59 
60 	"OP_LTU",
61 	"OP_LEU",
62 	"OP_GTU",
63 	"OP_GEU",
64 
65 	"OP_EQF",
66 	"OP_NEF",
67 
68 	"OP_LTF",
69 	"OP_LEF",
70 	"OP_GTF",
71 	"OP_GEF",
72 
73 	//-------------------
74 
75 	"OP_LOAD1",
76 	"OP_LOAD2",
77 	"OP_LOAD4",
78 	"OP_STORE1",
79 	"OP_STORE2",
80 	"OP_STORE4",
81 	"OP_ARG",
82 
83 	"OP_BLOCK_COPY",
84 
85 	//-------------------
86 
87 	"OP_SEX8",
88 	"OP_SEX16",
89 
90 	"OP_NEGI",
91 	"OP_ADD",
92 	"OP_SUB",
93 	"OP_DIVI",
94 	"OP_DIVU",
95 	"OP_MODI",
96 	"OP_MODU",
97 	"OP_MULI",
98 	"OP_MULU",
99 
100 	"OP_BAND",
101 	"OP_BOR",
102 	"OP_BXOR",
103 	"OP_BCOM",
104 
105 	"OP_LSH",
106 	"OP_RSHI",
107 	"OP_RSHU",
108 
109 	"OP_NEGF",
110 	"OP_ADDF",
111 	"OP_SUBF",
112 	"OP_DIVF",
113 	"OP_MULF",
114 
115 	"OP_CVIF",
116 	"OP_CVFI"
117 };
118 #endif
119 
120 typedef enum {
121     R_REAL_STACK = 1,
122 	// registers 3-11 are the parameter passing registers
123 
124 	// state
125 	R_STACK = 3,			// local
126 	R_OPSTACK,				// global
127 
128 	// constants
129 	R_MEMBASE,			// global
130 	R_MEMMASK,
131 	R_ASMCALL,			// global
132     R_INSTRUCTIONS,		// global
133     R_NUM_INSTRUCTIONS,	// global
134     R_CVM,				// currentVM
135 
136 	// temps
137 	R_TOP = 11,
138 	R_SECOND = 12,
139 	R_EA = 2				// effective address calculation
140 
141 } regNums_t;
142 
143 #define	RG_REAL_STACK		r1
144 #define	RG_STACK			r3
145 #define	RG_OPSTACK			r4
146 #define	RG_MEMBASE			r5
147 #define	RG_MEMMASK			r6
148 #define	RG_ASMCALL			r7
149 #define	RG_INSTRUCTIONS		r8
150 #define	RG_NUM_INSTRUCTIONS	r9
151 #define	RG_CVM				r10
152 #define	RG_TOP				r12
153 #define	RG_SECOND			r13
154 #define	RG_EA 				r14
155 
156 // The deepest value I saw in the Quake3 games was 9.
157 #define OP_STACK_MAX_DEPTH	16
158 
159 // These are all volatile and thus must be saved upon entry to the VM code.
160 // NOTE: These are General Purpose Registers (GPR) numbers like the
161 //       R_ definitions in the regNums_t enum above (31 is the max)
162 static int opStackIntRegisters[OP_STACK_MAX_DEPTH] =
163 {
164 	16, 17, 18, 19,
165 	20, 21, 22, 23,
166 	24, 25, 26, 27,
167 	28, 29, 30, 31
168 };
169 
170 static unsigned int *opStackLoadInstructionAddr[OP_STACK_MAX_DEPTH];
171 
172 // We use different registers for the floating point
173 // operand stack (these are volatile in the PPC ABI)
174 // NOTE: these are Floating Point Register (FPR) numbers, not
175 //       General Purpose Register (GPR) numbers
176 static int opStackFloatRegisters[OP_STACK_MAX_DEPTH] =
177 {
178 	0, 1, 2, 3,
179 	4, 5, 6, 7,
180 	8, 9, 10, 11,
181 	12, 13, 14, 15
182 };
183 
184 static int opStackRegType[OP_STACK_MAX_DEPTH] =
185 {
186 	0, 0, 0, 0,
187 	0, 0, 0, 0,
188 	0, 0, 0, 0,
189 	0, 0, 0, 0
190 };
191 
192 // this doesn't have the low order bits set for instructions i'm not using...
193 typedef enum {
194 	PPC_TDI		= 0x08000000,
195 	PPC_TWI		= 0x0c000000,
196 	PPC_MULLI	= 0x1c000000,
197 	PPC_SUBFIC	= 0x20000000,
198 	PPC_CMPI	= 0x28000000,
199 	PPC_CMPLI	= 0x2c000000,
200 	PPC_ADDIC	= 0x30000000,
201 	PPC_ADDIC_	= 0x34000000,
202 	PPC_ADDI	= 0x38000000,
203 	PPC_ADDIS	= 0x3c000000,
204 	PPC_BC		= 0x40000000,
205 	PPC_SC		= 0x44000000,
206 	PPC_B		= 0x48000000,
207 
208 	PPC_MCRF	= 0x4c000000,
209 	PPC_BCLR	= 0x4c000020,
210 	PPC_RFID	= 0x4c000000,
211 	PPC_CRNOR	= 0x4c000000,
212 	PPC_RFI		= 0x4c000000,
213 	PPC_CRANDC	= 0x4c000000,
214 	PPC_ISYNC	= 0x4c000000,
215 	PPC_CRXOR	= 0x4c000000,
216 	PPC_CRNAND	= 0x4c000000,
217 	PPC_CREQV	= 0x4c000000,
218 	PPC_CRORC	= 0x4c000000,
219 	PPC_CROR	= 0x4c000000,
220 //------------
221 	PPC_BCCTR	= 0x4c000420,
222 	PPC_RLWIMI	= 0x50000000,
223 	PPC_RLWINM	= 0x54000000,
224 	PPC_RLWNM	= 0x5c000000,
225 	PPC_ORI		= 0x60000000,
226 	PPC_ORIS	= 0x64000000,
227 	PPC_XORI	= 0x68000000,
228 	PPC_XORIS	= 0x6c000000,
229 	PPC_ANDI_	= 0x70000000,
230 	PPC_ANDIS_	= 0x74000000,
231 	PPC_RLDICL	= 0x78000000,
232 	PPC_RLDICR	= 0x78000000,
233 	PPC_RLDIC	= 0x78000000,
234 	PPC_RLDIMI	= 0x78000000,
235 	PPC_RLDCL	= 0x78000000,
236 	PPC_RLDCR	= 0x78000000,
237 	PPC_CMP		= 0x7c000000,
238 	PPC_TW		= 0x7c000000,
239 	PPC_SUBFC	= 0x7c000010,
240 	PPC_MULHDU	= 0x7c000000,
241 	PPC_ADDC	= 0x7c000014,
242 	PPC_MULHWU	= 0x7c000000,
243 	PPC_MFCR	= 0x7c000000,
244 	PPC_LWAR	= 0x7c000000,
245 	PPC_LDX		= 0x7c000000,
246 	PPC_LWZX	= 0x7c00002e,
247 	PPC_SLW		= 0x7c000030,
248 	PPC_CNTLZW	= 0x7c000000,
249 	PPC_SLD		= 0x7c000000,
250 	PPC_AND		= 0x7c000038,
251 	PPC_CMPL	= 0x7c000040,
252 	PPC_SUBF	= 0x7c000050,
253 	PPC_LDUX	= 0x7c000000,
254 //------------
255 	PPC_DCBST	= 0x7c000000,
256 	PPC_LWZUX	= 0x7c00006c,
257 	PPC_CNTLZD	= 0x7c000000,
258 	PPC_ANDC	= 0x7c000000,
259 	PPC_TD		= 0x7c000000,
260 	PPC_MULHD	= 0x7c000000,
261 	PPC_MULHW	= 0x7c000000,
262 	PPC_MTSRD	= 0x7c000000,
263 	PPC_MFMSR	= 0x7c000000,
264 	PPC_LDARX	= 0x7c000000,
265 	PPC_DCBF	= 0x7c000000,
266 	PPC_LBZX	= 0x7c0000ae,
267 	PPC_NEG		= 0x7c000000,
268 	PPC_MTSRDIN	= 0x7c000000,
269 	PPC_LBZUX	= 0x7c000000,
270 	PPC_NOR		= 0x7c0000f8,
271 	PPC_SUBFE	= 0x7c000000,
272 	PPC_ADDE	= 0x7c000000,
273 	PPC_MTCRF	= 0x7c000000,
274 	PPC_MTMSR	= 0x7c000000,
275 	PPC_STDX	= 0x7c000000,
276 	PPC_STWCX_	= 0x7c000000,
277 	PPC_STWX	= 0x7c00012e,
278 	PPC_MTMSRD	= 0x7c000000,
279 	PPC_STDUX	= 0x7c000000,
280 	PPC_STWUX	= 0x7c00016e,
281 	PPC_SUBFZE	= 0x7c000000,
282 	PPC_ADDZE	= 0x7c000000,
283 	PPC_MTSR	= 0x7c000000,
284 	PPC_STDCX_	= 0x7c000000,
285 	PPC_STBX	= 0x7c0001ae,
286 	PPC_SUBFME	= 0x7c000000,
287 	PPC_MULLD	= 0x7c000000,
288 //------------
289 	PPC_ADDME	= 0x7c000000,
290 	PPC_MULLW	= 0x7c0001d6,
291 	PPC_MTSRIN	= 0x7c000000,
292 	PPC_DCBTST	= 0x7c000000,
293 	PPC_STBUX	= 0x7c000000,
294 	PPC_ADD		= 0x7c000214,
295 	PPC_DCBT	= 0x7c000000,
296 	PPC_LHZX	= 0x7c00022e,
297 	PPC_EQV		= 0x7c000000,
298 	PPC_TLBIE	= 0x7c000000,
299 	PPC_ECIWX	= 0x7c000000,
300 	PPC_LHZUX	= 0x7c000000,
301 	PPC_XOR		= 0x7c000278,
302 	PPC_MFSPR	= 0x7c0002a6,
303 	PPC_LWAX	= 0x7c000000,
304 	PPC_LHAX	= 0x7c000000,
305 	PPC_TLBIA	= 0x7c000000,
306 	PPC_MFTB	= 0x7c000000,
307 	PPC_LWAUX	= 0x7c000000,
308 	PPC_LHAUX	= 0x7c000000,
309 	PPC_STHX	= 0x7c00032e,
310 	PPC_ORC		= 0x7c000338,
311 	PPC_SRADI	= 0x7c000000,
312 	PPC_SLBIE	= 0x7c000000,
313 	PPC_ECOWX	= 0x7c000000,
314 	PPC_STHUX	= 0x7c000000,
315 	PPC_OR		= 0x7c000378,
316 	PPC_DIVDU	= 0x7c000000,
317 	PPC_DIVWU	= 0x7c000396,
318 	PPC_MTSPR	= 0x7c0003a6,
319 	PPC_DCBI	= 0x7c000000,
320 	PPC_NAND	= 0x7c000000,
321 	PPC_DIVD	= 0x7c000000,
322 //------------
323 	PPC_DIVW	= 0x7c0003d6,
324 	PPC_SLBIA	= 0x7c000000,
325 	PPC_MCRXR	= 0x7c000000,
326 	PPC_LSWX	= 0x7c000000,
327 	PPC_LWBRX	= 0x7c000000,
328 	PPC_LFSX	= 0x7c00042e,
329 	PPC_SRW		= 0x7c000430,
330 	PPC_SRD		= 0x7c000000,
331 	PPC_TLBSYNC	= 0x7c000000,
332 	PPC_LFSUX	= 0x7c000000,
333 	PPC_MFSR	= 0x7c000000,
334 	PPC_LSWI	= 0x7c000000,
335 	PPC_SYNC	= 0x7c000000,
336 	PPC_LFDX	= 0x7c000000,
337 	PPC_LFDUX	= 0x7c000000,
338 	PPC_MFSRIN	= 0x7c000000,
339 	PPC_STSWX	= 0x7c000000,
340 	PPC_STWBRX	= 0x7c000000,
341 	PPC_STFSX	= 0x7c00052e,
342 	PPC_STFSUX	= 0x7c000000,
343 	PPC_STSWI	= 0x7c000000,
344 	PPC_STFDX	= 0x7c000000,
345 	PPC_DCBA	= 0x7c000000,
346 	PPC_STFDUX	= 0x7c000000,
347 	PPC_LHBRX	= 0x7c000000,
348 	PPC_SRAW	= 0x7c000630,
349 	PPC_SRAD	= 0x7c000000,
350 	PPC_SRAWI	= 0x7c000000,
351 	PPC_EIEIO	= 0x7c000000,
352 	PPC_STHBRX	= 0x7c000000,
353 	PPC_EXTSH	= 0x7c000734,
354 	PPC_EXTSB	= 0x7c000774,
355 	PPC_ICBI	= 0x7c000000,
356 //------------
357 	PPC_STFIWX	= 0x7c0007ae,
358 	PPC_EXTSW	= 0x7c000000,
359 	PPC_DCBZ	= 0x7c000000,
360 	PPC_LWZ		= 0x80000000,
361 	PPC_LWZU	= 0x84000000,
362 	PPC_LBZ		= 0x88000000,
363 	PPC_LBZU	= 0x8c000000,
364 	PPC_STW		= 0x90000000,
365 	PPC_STWU	= 0x94000000,
366 	PPC_STB		= 0x98000000,
367 	PPC_STBU	= 0x9c000000,
368 	PPC_LHZ		= 0xa0000000,
369 	PPC_LHZU	= 0xa4000000,
370 	PPC_LHA		= 0xa8000000,
371 	PPC_LHAU	= 0xac000000,
372 	PPC_STH		= 0xb0000000,
373 	PPC_STHU	= 0xb4000000,
374 	PPC_LMW		= 0xb8000000,
375 	PPC_STMW	= 0xbc000000,
376 	PPC_LFS		= 0xc0000000,
377 	PPC_LFSU	= 0xc4000000,
378 	PPC_LFD		= 0xc8000000,
379 	PPC_LFDU	= 0xcc000000,
380 	PPC_STFS	= 0xd0000000,
381 	PPC_STFSU	= 0xd4000000,
382 	PPC_STFD	= 0xd8000000,
383 	PPC_STFDU	= 0xdc000000,
384 	PPC_LD		= 0xe8000000,
385 	PPC_LDU		= 0xe8000001,
386 	PPC_LWA		= 0xe8000002,
387 	PPC_FDIVS	= 0xec000024,
388 	PPC_FSUBS	= 0xec000028,
389 	PPC_FADDS	= 0xec00002a,
390 //------------
391 	PPC_FSQRTS	= 0xec000000,
392 	PPC_FRES	= 0xec000000,
393 	PPC_FMULS	= 0xec000032,
394 	PPC_FMSUBS	= 0xec000000,
395 	PPC_FMADDS	= 0xec000000,
396 	PPC_FNMSUBS	= 0xec000000,
397 	PPC_FNMADDS	= 0xec000000,
398 	PPC_STD		= 0xf8000000,
399 	PPC_STDU	= 0xf8000001,
400 	PPC_FCMPU	= 0xfc000000,
401 	PPC_FRSP	= 0xfc000018,
402 	PPC_FCTIW	= 0xfc000000,
403 	PPC_FCTIWZ	= 0xfc00001e,
404 	PPC_FDIV	= 0xfc000000,
405 	PPC_FSUB	= 0xfc000028,
406 	PPC_FADD	= 0xfc000000,
407 	PPC_FSQRT	= 0xfc000000,
408 	PPC_FSEL	= 0xfc000000,
409 	PPC_FMUL	= 0xfc000000,
410 	PPC_FRSQRTE	= 0xfc000000,
411 	PPC_FMSUB	= 0xfc000000,
412 	PPC_FMADD	= 0xfc000000,
413 	PPC_FNMSUB	= 0xfc000000,
414 	PPC_FNMADD	= 0xfc000000,
415 	PPC_FCMPO	= 0xfc000000,
416 	PPC_MTFSB1	= 0xfc000000,
417 	PPC_FNEG	= 0xfc000050,
418 	PPC_MCRFS	= 0xfc000000,
419 	PPC_MTFSB0	= 0xfc000000,
420 	PPC_FMR		= 0xfc000000,
421 	PPC_MTFSFI	= 0xfc000000,
422 	PPC_FNABS	= 0xfc000000,
423 	PPC_FABS	= 0xfc000000,
424 //------------
425 	PPC_MFFS	= 0xfc000000,
426 	PPC_MTFSF	= 0xfc000000,
427 	PPC_FCTID	= 0xfc000000,
428 	PPC_FCTIDZ	= 0xfc000000,
429 	PPC_FCFID	= 0xfc000000
430 
431 } ppcOpcodes_t;
432 
433 
434 // the newly generated code
435 static	unsigned	*buf;
436 static	int		compiledOfs;	// in dwords
437 static int pass;
438 
439 // fromt the original bytecode
440 static	byte	*code;
441 static	int		pc;
442 
443 void AsmCall( void );
444 
445 double	itofConvert[2];
446 
Constant4(void)447 static int	Constant4( void ) {
448 	int		v;
449 
450 	v = code[pc] | (code[pc+1]<<8) | (code[pc+2]<<16) | (code[pc+3]<<24);
451 	pc += 4;
452 	return v;
453 }
454 
Constant1(void)455 static int	Constant1( void ) {
456 	int		v;
457 
458 	v = code[pc];
459 	pc += 1;
460 	return v;
461 }
462 
Emit4(char * opname,int i)463 static void Emit4( char *opname, int i ) {
464 	#if DEBUG_VM
465 	if(pass == 1)
466 		printf("\t\t\t%p %s\t%08lx\n",&buf[compiledOfs],opname,i&0x3ffffff);
467 	#endif
468 	buf[ compiledOfs ] = i;
469 	compiledOfs++;
470 }
471 
Inst(char * opname,int opcode,int destReg,int aReg,int bReg)472 static void Inst( char *opname, int opcode, int destReg, int aReg, int bReg ) {
473     unsigned		r;
474 
475 	#if DEBUG_VM
476 	if(pass == 1)
477 		printf("\t\t\t%p %s\tr%d,r%d,r%d\n",&buf[compiledOfs],opname,destReg,aReg,bReg);
478 	#endif
479     r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) ;
480     buf[ compiledOfs ] = r;
481     compiledOfs++;
482 }
483 
Inst4(char * opname,int opcode,int destReg,int aReg,int bReg,int cReg)484 static void Inst4( char *opname, int opcode, int destReg, int aReg, int bReg, int cReg ) {
485     unsigned		r;
486 
487 	#if DEBUG_VM
488 	if(pass == 1)
489 		printf("\t\t\t%p %s\tr%d,r%d,r%d,r%d\n",&buf[compiledOfs],opname,destReg,aReg,bReg,cReg);
490 	#endif
491     r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) | ( cReg << 6 );
492     buf[ compiledOfs ] = r;
493     compiledOfs++;
494 }
495 
InstImm(char * opname,int opcode,int destReg,int aReg,int immediate)496 static void InstImm( char *opname, int opcode, int destReg, int aReg, int immediate ) {
497 	unsigned		r;
498 
499 	if ( immediate > 32767 || immediate < -32768 ) {
500 	    Com_Error( ERR_FATAL, "VM_Compile: immediate value %i out of range, opcode %x,%d,%d", immediate, opcode, destReg, aReg );
501 	}
502 	#if DEBUG_VM
503 	if(pass == 1)
504 		printf("\t\t\t%p %s\tr%d,r%d,0x%x\n",&buf[compiledOfs],opname,destReg,aReg,immediate);
505 	#endif
506 	r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( immediate & 0xffff );
507 	buf[ compiledOfs ] = r;
508 	compiledOfs++;
509 }
510 
InstImmU(char * opname,int opcode,int destReg,int aReg,int immediate)511 static void InstImmU( char *opname, int opcode, int destReg, int aReg, int immediate ) {
512 	unsigned		r;
513 
514 	if ( immediate > 0xffff || immediate < 0 ) {
515 		Com_Error( ERR_FATAL, "VM_Compile: immediate value %i out of range", immediate );
516 	}
517 	#if DEBUG_VM
518 	if(pass == 1)
519 		printf("\t\t\t%p %s\tr%d,r%d,0x%x\n",&buf[compiledOfs],opname,destReg,aReg,immediate);
520 	#endif
521     r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( immediate & 0xffff );
522 	buf[ compiledOfs ] = r;
523 	compiledOfs++;
524 }
525 
526 static int pop0, pop1, oc0, oc1;
527 static vm_t *tvm;
528 static int instruction;
529 static byte *jused;
530 
spillOpStack(int depth)531 static void spillOpStack(int depth)
532 {
533 	// Store out each register on the operand stack to it's correct location.
534 	int i;
535 
536 	for(i = 0; i < depth; i++)
537 	{
538 		assert(opStackRegType[i]);
539 		assert(opStackRegType[i] == 1);
540 		switch(opStackRegType[i])
541 		{
542 			case 1:	// Integer register
543 				InstImm( "stw", PPC_STW, opStackIntRegisters[i], R_OPSTACK, i*4+4);
544 				break;
545 			case 2: // Float register
546 				InstImm( "stfs", PPC_STFS, opStackFloatRegisters[i], R_OPSTACK, i*4+4);
547 				break;
548 		}
549 		opStackRegType[i] = 0;
550 	}
551 }
552 
loadOpStack(int depth)553 static void loadOpStack(int depth)
554 {
555 	// Back off operand stack pointer and reload all operands.
556 //	InstImm( "addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, -(depth)*4 );
557 
558 	int i;
559 
560 	for(i = 0; i < depth; i++)
561 	{
562 		assert(opStackRegType[i] == 0);
563 		// For now we're stuck reloading everything as an integer.
564 		opStackLoadInstructionAddr[i] = &buf[compiledOfs];
565 		InstImm( "lwz", PPC_LWZ, opStackIntRegisters[i], R_OPSTACK, i*4+4);
566 		opStackRegType[i] = 1;
567 	}
568 }
569 
makeFloat(int depth)570 static void makeFloat(int depth)
571 {
572 	//assert(opStackRegType[depth] == 1);
573 	if(opStackRegType[depth] == 1)
574 	{
575 		unsigned instruction;
576 		unsigned destReg, aReg, bReg, imm;
577 
578 		if(opStackLoadInstructionAddr[depth])
579 		{
580 			// Repatch load instruction to use LFS instead of LWZ
581 			instruction = *opStackLoadInstructionAddr[depth];
582 			// Figure out if it's LWZ or LWZX
583 			if((instruction & 0xfc000000) == PPC_LWZ)
584 			{
585 				//printf("patching LWZ at %p to LFS at depth %ld\n",opStackLoadInstructionAddr[depth],depth);
586 				//printf("old instruction: %08lx\n",instruction);
587 				// Extract registers
588 				destReg = (instruction >> 21) & 31;
589 				aReg    = (instruction >> 16) & 31;
590 				imm     = instruction & 0xffff;
591 
592 				// Calculate correct FP register to use.
593 				// THIS ASSUMES REGISTER USAGE FOR THE STACK IS n, n+1, n+2, etc!
594 				//printf("old dest: %ld\n",destReg);
595 				destReg = (destReg - opStackIntRegisters[0]) + opStackFloatRegisters[0];
596 				instruction = PPC_LFS | ( destReg << 21 ) | ( aReg << 16 ) | imm ;
597 				//printf("new dest: %ld\n",destReg);
598 				//printf("new instruction: %08lx\n",instruction);
599 			}
600 			else
601 			{
602 				//printf("patching LWZX at %p to LFSX at depth %ld\n",opStackLoadInstructionAddr[depth],depth);
603 				//printf("old instruction: %08lx\n",instruction);
604 				// Extract registers
605 				destReg = (instruction >> 21) & 31;
606 				aReg    = (instruction >> 16) & 31;
607 				bReg    = (instruction >> 11) & 31;
608 				// Calculate correct FP register to use.
609 				// THIS ASSUMES REGISTER USAGE FOR THE STACK IS n, n+1, n+2, etc!
610 				//printf("old dest: %ld\n",destReg);
611 				destReg = (destReg - opStackIntRegisters[0]) + opStackFloatRegisters[0];
612 				instruction = PPC_LFSX | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) ;
613 				//printf("new dest: %ld\n",destReg);
614 				//printf("new instruction: %08lx\n",instruction);
615 			}
616 			*opStackLoadInstructionAddr[depth] = instruction;
617 			opStackLoadInstructionAddr[depth] = 0;
618 		}
619 		else
620 		{
621 			//printf("doing float constant load at %p for depth %ld\n",&buf[compiledOfs],depth);
622 			// It was likely loaded as a constant so we have to save/load it.  A more
623 			// interesting implementation might be to generate code to do a "PC relative"
624 			// load from the VM code region.
625 			InstImm( "stw", PPC_STW, opStackIntRegisters[depth], R_OPSTACK, depth*4+4);
626 			// For XXX make sure we force enough NOPs to get the load into
627 			// another dispatch group to avoid pipeline flush.
628 			Inst( "ori", PPC_ORI,  0, 0, 0 );
629 			Inst( "ori", PPC_ORI,  0, 0, 0 );
630 			Inst( "ori", PPC_ORI,  0, 0, 0 );
631 			Inst( "ori", PPC_ORI,  0, 0, 0 );
632 			InstImm( "lfs", PPC_LFS, opStackFloatRegisters[depth], R_OPSTACK, depth*4+4);
633 		}
634 		opStackRegType[depth] = 2;
635 	}
636 }
637 
638 // TJW: Unused
639 #if 0
640 static void fltop() {
641     if (rtopped == qfalse) {
642 	InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 );		// get value from opstack
643     }
644 }
645 #endif
646 
647 #if 0
648 static void fltopandsecond() {
649 	InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 );		// get value from opstack
650 	InstImm( PPC_LFS, R_SECOND, R_OPSTACK, -4 );	// get value from opstack
651 	InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -8 );
652     rtopped = qfalse;
653 	return;
654 }
655 #endif
656 
657 #define assertInteger(depth)	assert(opStackRegType[depth] == 1)
658 
659 /*
660 =================
661 VM_Compile
662 =================
663 */
VM_Compile(vm_t * vm,vmHeader_t * header)664 void VM_Compile( vm_t *vm, vmHeader_t *header ) {
665 	int		op;
666 	int		maxLength;
667 	int		v;
668 	int		i;
669         int		opStackDepth;
670 
671 	int		mainFunction;
672 
673 	// set up the into-to-float variables
674    	((int *)itofConvert)[0] = 0x43300000;
675    	((int *)itofConvert)[1] = 0x80000000;
676    	((int *)itofConvert)[2] = 0x43300000;
677 
678 	// allocate a very large temp buffer, we will shrink it later
679 	maxLength = header->codeLength * 8;
680 	buf = Z_Malloc( maxLength );
681 	jused = Z_Malloc(header->instructionCount + 2);
682 	Com_Memset(jused, 0, header->instructionCount+2);
683 
684     // compile everything twice, so the second pass will have valid instruction
685     // pointers for branches
686     for ( pass = -1 ; pass < 2 ; pass++ ) {
687 
688         // translate all instructions
689         pc = 0;
690 	mainFunction = 0;
691 	opStackDepth = 0;
692 
693 	pop0 = 343545;
694 	pop1 = 2443545;
695 	oc0 = -2343535;
696 	oc1 = 24353454;
697 	tvm = vm;
698         code = (byte *)header + header->codeOffset;
699         compiledOfs = 0;
700 #ifndef __GNUC__
701 		// metrowerks seems to require this header in front of functions
702 		Emit4( (int)(buf+2) );
703 		Emit4( 0 );
704 #endif
705 
706 	for ( instruction = 0 ; instruction < header->instructionCount ; instruction++ ) {
707             if ( compiledOfs*4 > maxLength - 16 ) {
708                 Com_Error( ERR_DROP, "VM_Compile: maxLength exceeded" );
709             }
710 
711             op = code[ pc ];
712             if ( !pass ) {
713                 vm->instructionPointers[ instruction ] = compiledOfs * 4;
714             }
715             pc++;
716             switch ( op ) {
717             case 0:
718                 break;
719             case OP_BREAK:
720 		#if DEBUG_VM
721 		if(pass == 1)
722 			printf("%08lx BREAK\n",instruction);
723 		#endif
724                 InstImmU( "addi", PPC_ADDI, R_TOP, 0, 0 );
725                 InstImm( "lwz", PPC_LWZ, R_TOP, R_TOP, 0 );			// *(int *)0 to crash to debugger
726                 break;
727             case OP_ENTER:
728 		opStackDepth = 0;
729 		v = Constant4();
730 		#if DEBUG_VM
731 		if(pass == 1)
732 			printf("%08x ENTER\t%04x\n",instruction,v);
733 		#endif
734 		opStackRegType[opStackDepth] = 0;
735 		mainFunction++;
736 		if(mainFunction == 1)
737 		{
738 			// Main VM entry point is the first thing we compile, so save off operand stack
739 			// registers here.  This avoids issues with trying to trick the native compiler
740 			// into doing it, and properly matches the PowerPC ABI
741 			InstImm( "addi", PPC_ADDI, R_REAL_STACK, R_REAL_STACK, -OP_STACK_MAX_DEPTH*4 );	// sub R_STACK, R_STACK, imm
742 			for(i = 0; i < OP_STACK_MAX_DEPTH; i++)
743 				InstImm( "stw", PPC_STW, opStackIntRegisters[i], R_REAL_STACK, i*4);
744 		}
745                 InstImm( "addi", PPC_ADDI, R_STACK, R_STACK, -v );	// sub R_STACK, R_STACK, imm
746                 break;
747             case OP_CONST:
748                 v = Constant4();
749 		#if DEBUG_VM
750 		if(pass == 1)
751 			printf("%08x CONST\t%08x\n",instruction,v);
752 		#endif
753 		opStackLoadInstructionAddr[opStackDepth] = 0;
754                 if ( v < 32768 && v >= -32768 ) {
755                     InstImmU( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth], 0, v & 0xffff );
756                 } else {
757                     InstImmU( "addis", PPC_ADDIS, opStackIntRegisters[opStackDepth], 0, (v >> 16)&0xffff );
758                     if ( v & 0xffff ) {
759                         InstImmU( "ori", PPC_ORI, opStackIntRegisters[opStackDepth], opStackIntRegisters[opStackDepth], v & 0xffff );
760                     }
761                 }
762 		opStackRegType[opStackDepth] = 1;
763 		opStackDepth += 1;
764 		if (code[pc] == OP_JUMP) {
765 		    jused[v] = 1;
766 		}
767 		break;
768             case OP_LOCAL:
769 		oc1 = Constant4();
770 		#if DEBUG_VM
771 		if(pass == 1)
772 			printf("%08x LOCAL\t%08x\n",instruction,oc1);
773 		#endif
774 		if (code[pc] == OP_LOAD4 || code[pc] == OP_LOAD2 || code[pc] == OP_LOAD1) {
775 		    oc1 &= vm->dataMask;
776 		}
777                 InstImm( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth], R_STACK, oc1 );
778 		opStackRegType[opStackDepth] = 1;
779 		opStackLoadInstructionAddr[opStackDepth] = 0;
780 		opStackDepth += 1;
781                 break;
782             case OP_ARG:
783 		v = Constant1();
784 		#if DEBUG_VM
785 		if(pass == 1)
786 			printf("%08x ARG \t%08x\n",instruction,v);
787 		#endif
788                 InstImm( "addi", PPC_ADDI, R_EA, R_STACK, v );	// location to put it
789 		if(opStackRegType[opStackDepth-1] == 1)
790 			Inst( "stwx", PPC_STWX, opStackIntRegisters[opStackDepth-1], R_EA, R_MEMBASE );
791 		else
792 			Inst( "stfsx", PPC_STFSX, opStackFloatRegisters[opStackDepth-1], R_EA, R_MEMBASE );
793 		opStackRegType[opStackDepth-1] = 0;
794 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
795 		opStackDepth -= 1;
796 
797                 break;
798             case OP_CALL:
799 		#if DEBUG_VM
800 		if(pass == 1)
801 			printf("%08x CALL\n",instruction);
802 		#endif
803 		assertInteger(opStackDepth-1);
804 		assert(opStackDepth > 0);
805                 Inst( "mflr", PPC_MFSPR, R_SECOND, 8, 0 );			// move from link register
806                 InstImm( "stwu", PPC_STWU, R_SECOND, R_REAL_STACK, -16 );	// save off the old return address
807 
808 		// Spill operand stack registers.
809 		spillOpStack(opStackDepth);
810 
811 		// We need to leave R_OPSTACK pointing to the top entry on the stack, which is the call address.
812 		// It will be consumed (and R4 decremented) by the AsmCall code.
813 		InstImm( "addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, opStackDepth*4);
814 
815                 Inst( "mtctr", PPC_MTSPR, R_ASMCALL, 9, 0 );			// move to count register
816                 Inst( "bctrl", PPC_BCCTR | 1, 20, 0, 0 );			// jump and link to the count register
817 
818 		// R4 now points to the top of the operand stack, which has the return value in it.  We want to
819 		// back off the pointer to point to the base of our local operand stack and then reload the stack.
820 
821 		InstImm("addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, -opStackDepth*4);
822 
823 		// Reload operand stack.
824 		loadOpStack(opStackDepth);
825 
826                 InstImm( "lwz", PPC_LWZ, R_SECOND, R_REAL_STACK, 0 );		// fetch the old return address
827                 InstImm( "addi", PPC_ADDI, R_REAL_STACK, R_REAL_STACK, 16 );
828                 Inst( "mtlr", PPC_MTSPR, R_SECOND, 8, 0 );			// move to link register
829                 break;
830             case OP_PUSH:
831 		#if DEBUG_VM
832 		if(pass == 1)
833 			printf("%08x PUSH\n",instruction);
834 		#endif
835 		opStackRegType[opStackDepth] = 1; 	// Garbage int value.
836 		opStackDepth += 1;
837                 break;
838             case OP_POP:
839 		#if DEBUG_VM
840 		if(pass == 1)
841 			printf("%08x POP\n",instruction);
842 		#endif
843 		opStackDepth -= 1;
844 		opStackRegType[opStackDepth] = 0; 	// ??
845 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
846                 break;
847             case OP_LEAVE:
848 		#if DEBUG_VM
849 		if(pass == 1)
850 			printf("%08x LEAVE\n",instruction);
851 		#endif
852 		assert(opStackDepth == 1);
853 		assert(opStackRegType[0] != 0);
854 		// Save return value onto top of op stack.  We also have to increment R_OPSTACK
855 		switch(opStackRegType[0])
856 		{
857 			case 1:	// Integer register
858 				InstImm( "stw", PPC_STWU, opStackIntRegisters[0], R_OPSTACK, 4);
859 				break;
860 			case 2: // Float register
861 				InstImm( "stfs", PPC_STFSU, opStackFloatRegisters[0], R_OPSTACK, 4);
862 				break;
863 		}
864                 InstImm( "addi", PPC_ADDI, R_STACK, R_STACK, Constant4() );	// add R_STACK, R_STACK, imm
865 		if(mainFunction == 1)
866 		{
867 			for(i = 0; i < OP_STACK_MAX_DEPTH; i++)
868 				InstImm( "lwz", PPC_LWZ,  opStackIntRegisters[i], R_REAL_STACK, i*4);
869 			InstImm( "addi", PPC_ADDI, R_REAL_STACK, R_REAL_STACK, OP_STACK_MAX_DEPTH*4 );
870 		}
871 		opStackDepth--;
872 		opStackRegType[opStackDepth] = 0;
873 		opStackLoadInstructionAddr[opStackDepth] = 0;
874                 Inst( "blr", PPC_BCLR, 20, 0, 0 );							// branch unconditionally to link register
875                 break;
876             case OP_LOAD4:
877 		#if DEBUG_VM
878 		if(pass == 1)
879 			printf("%08x LOAD4\n",instruction);
880 		#endif
881 		// We should try to figure out whether to use LWZX or LFSX based
882 		// on some kind of code analysis after subsequent passes.  I think what
883 		// we could do is store the compiled load instruction address along with
884 		// the register type.  When we hit the first mismatched operator, we go back
885 		// and patch the load.  Since LCC's operand stack should be at 0 depth by the
886 		// time we hit a branch, this should work fairly well.  FIXME FIXME FIXME.
887 		assertInteger(opStackDepth-1);
888 		opStackLoadInstructionAddr[opStackDepth-1] = &buf[ compiledOfs ];
889                 Inst( "lwzx", PPC_LWZX, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_MEMBASE );// load from memory base
890 		opStackRegType[opStackDepth-1] = 1;
891                 break;
892             case OP_LOAD2:
893 		#if DEBUG_VM
894 		if(pass == 1)
895 			printf("%08x LOAD2\n",instruction);
896 		#endif
897 		assertInteger(opStackDepth-1);
898 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
899                 Inst( "lhzx", PPC_LHZX, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_MEMBASE );// load from memory base
900 		opStackRegType[opStackDepth-1] = 1;
901                 break;
902             case OP_LOAD1:
903 		#if DEBUG_VM
904 		if(pass == 1)
905 			printf("%08x LOAD1\n",instruction);
906 		#endif
907 		assertInteger(opStackDepth-1);
908 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
909                 Inst( "lbzx", PPC_LBZX, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_MEMBASE );// load from memory base
910 		opStackRegType[opStackDepth-1] = 1;
911                 break;
912             case OP_STORE4:
913 		#if DEBUG_VM
914 		if(pass == 1)
915 			printf("%08x STORE4\n",instruction);
916 		#endif
917 		assertInteger(opStackDepth-2);
918 		if(opStackRegType[opStackDepth-1] == 1)
919 			Inst( "stwx", PPC_STWX, opStackIntRegisters[opStackDepth-1],
920 					opStackIntRegisters[opStackDepth-2], R_MEMBASE );		// store from memory base
921 		else
922 			Inst( "stfsx", PPC_STFSX, opStackFloatRegisters[opStackDepth-1],
923 					opStackIntRegisters[opStackDepth-2], R_MEMBASE );		// store from memory base
924 		opStackRegType[opStackDepth-1] = 0;
925 		opStackRegType[opStackDepth-2] = 0;
926 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
927 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
928 		opStackDepth -= 2;
929                 break;
930             case OP_STORE2:
931 		#if DEBUG_VM
932 		if(pass == 1)
933 			printf("%08x STORE2\n",instruction);
934 		#endif
935 		assertInteger(opStackDepth-1);
936 		assertInteger(opStackDepth-2);
937                 Inst( "sthx", PPC_STHX, opStackIntRegisters[opStackDepth-1],
938 				opStackIntRegisters[opStackDepth-2], R_MEMBASE );		// store from memory base
939 		opStackRegType[opStackDepth-1] = 0;
940 		opStackRegType[opStackDepth-2] = 0;
941 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
942 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
943 		opStackDepth -= 2;
944                 break;
945             case OP_STORE1:
946 		#if DEBUG_VM
947 		if(pass == 1)
948 			printf("%08x STORE1\n",instruction);
949 		#endif
950 		assertInteger(opStackDepth-1);
951 		assertInteger(opStackDepth-2);
952                 Inst( "stbx", PPC_STBX, opStackIntRegisters[opStackDepth-1],
953 				opStackIntRegisters[opStackDepth-2], R_MEMBASE );		// store from memory base
954 		opStackRegType[opStackDepth-1] = 0;
955 		opStackRegType[opStackDepth-2] = 0;
956 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
957 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
958 		opStackDepth -= 2;
959                 break;
960 
961             case OP_EQ:
962 		#if DEBUG_VM
963 		if(pass == 1)
964 			printf("%08x EQ\n",instruction);
965 		#endif
966 		assertInteger(opStackDepth-1);
967 		assertInteger(opStackDepth-2);
968                 Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
969 		opStackRegType[opStackDepth-1] = 0;
970 		opStackRegType[opStackDepth-2] = 0;
971 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
972 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
973 		opStackDepth -= 2;
974                 i = Constant4();
975 				jused[i] = 1;
976                 InstImm( "bc", PPC_BC, 4, 2, 8 );
977                 if ( pass==1 ) {
978                     v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
979                 } else {
980                     v = 0;
981                 }
982                 Emit4("b", PPC_B | (v&0x3ffffff) );
983                 break;
984             case OP_NE:
985 		#if DEBUG_VM
986 		if(pass == 1)
987 			printf("%08x NE\n",instruction);
988 		#endif
989 		assertInteger(opStackDepth-1);
990 		assertInteger(opStackDepth-2);
991                 Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
992 		opStackRegType[opStackDepth-1] = 0;
993 		opStackRegType[opStackDepth-2] = 0;
994 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
995 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
996 		opStackDepth -= 2;
997                 i = Constant4();
998 				jused[i] = 1;
999                 InstImm( "bc", PPC_BC, 12, 2, 8 );
1000                 if ( pass==1 ) {
1001                     v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
1002                 } else {
1003                     v = 0;
1004                 }
1005                 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
1006 //                InstImm( "bc", PPC_BC, 4, 2, v );
1007 
1008                 break;
1009             case OP_LTI:
1010 		#if DEBUG_VM
1011 		if(pass == 1)
1012 		printf("%08x LTI\n",instruction);
1013 		#endif
1014 		assertInteger(opStackDepth-1);
1015 		assertInteger(opStackDepth-2);
1016                 Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1017 		opStackRegType[opStackDepth-1] = 0;
1018 		opStackRegType[opStackDepth-2] = 0;
1019 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1020 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
1021 		opStackDepth -= 2;
1022                 i = Constant4();
1023 				jused[i] = 1;
1024                 InstImm( "bc", PPC_BC, 4, 0, 8 );
1025                 if ( pass==1 ) {
1026                     v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
1027                 } else {
1028                     v = 0;
1029                 }
1030                 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
1031 //                InstImm( "bc", PPC_BC, 12, 0, v );
1032                 break;
1033             case OP_LEI:
1034 		#if DEBUG_VM
1035 		if(pass == 1)
1036 		printf("%08x LEI\n",instruction);
1037 		#endif
1038 		assertInteger(opStackDepth-1);
1039 		assertInteger(opStackDepth-2);
1040                 Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1041 		opStackRegType[opStackDepth-1] = 0;
1042 		opStackRegType[opStackDepth-2] = 0;
1043 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1044 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
1045 		opStackDepth -= 2;
1046                 i = Constant4();
1047 				jused[i] = 1;
1048                 InstImm( "bc", PPC_BC, 12, 1, 8 );
1049                 if ( pass==1 ) {
1050                     v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
1051                 } else {
1052                     v = 0;
1053                 }
1054                 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
1055 //                InstImm( "bc", PPC_BC, 4, 1, v );
1056                 break;
1057             case OP_GTI:
1058 		#if DEBUG_VM
1059 		if(pass == 1)
1060 		printf("%08x GTI\n",instruction);
1061 		#endif
1062 		assertInteger(opStackDepth-1);
1063 		assertInteger(opStackDepth-2);
1064                 Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1065 		opStackRegType[opStackDepth-1] = 0;
1066 		opStackRegType[opStackDepth-2] = 0;
1067 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1068 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
1069 		opStackDepth -= 2;
1070                 i = Constant4();
1071 				jused[i] = 1;
1072                 InstImm( "bc", PPC_BC, 4, 1, 8 );
1073                 if ( pass==1 ) {
1074                     v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
1075                 } else {
1076                     v = 0;
1077                 }
1078                 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
1079 //                InstImm( "bc", PPC_BC, 12, 1, v );
1080                 break;
1081             case OP_GEI:
1082 		#if DEBUG_VM
1083 		if(pass == 1)
1084 		printf("%08x GEI\n",instruction);
1085 		#endif
1086 		assertInteger(opStackDepth-1);
1087 		assertInteger(opStackDepth-2);
1088                 Inst( "cmp", PPC_CMP, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1089 		opStackRegType[opStackDepth-1] = 0;
1090 		opStackRegType[opStackDepth-2] = 0;
1091 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1092 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
1093 		opStackDepth -= 2;
1094                 i = Constant4();
1095 				jused[i] = 1;
1096                 InstImm( "bc", PPC_BC, 12, 0, 8 );
1097                 if ( pass==1 ) {
1098                     v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
1099                 } else {
1100                     v = 0;
1101                 }
1102                 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
1103 //                InstImm( "bc", PPC_BC, 4, 0, v );
1104                 break;
1105             case OP_LTU:
1106 		#if DEBUG_VM
1107 		if(pass == 1)
1108 		printf("%08x LTU\n",instruction);
1109 		#endif
1110 		assertInteger(opStackDepth-1);
1111 		assertInteger(opStackDepth-2);
1112                 Inst( "cmpl", PPC_CMPL, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1113 		opStackRegType[opStackDepth-1] = 0;
1114 		opStackRegType[opStackDepth-2] = 0;
1115 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1116 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
1117 		opStackDepth -= 2;
1118                 i = Constant4();
1119 		jused[i] = 1;
1120                 InstImm( "bc", PPC_BC, 4, 0, 8 );
1121                 if ( pass==1 ) {
1122                     v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
1123                 } else {
1124                     v = 0;
1125                 }
1126                 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
1127 //                InstImm( "bc", PPC_BC, 12, 0, v );
1128                 break;
1129             case OP_LEU:
1130 		#if DEBUG_VM
1131 		if(pass == 1)
1132 		printf("%08x LEU\n",instruction);
1133 		#endif
1134 		assertInteger(opStackDepth-1);
1135 		assertInteger(opStackDepth-2);
1136                 Inst( "cmpl", PPC_CMPL, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1137 		opStackRegType[opStackDepth-1] = 0;
1138 		opStackRegType[opStackDepth-2] = 0;
1139 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1140 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
1141 		opStackDepth -= 2;
1142                 i = Constant4();
1143 		jused[i] = 1;
1144                 InstImm( "bc", PPC_BC, 12, 1, 8 );
1145                 if ( pass==1 ) {
1146                     v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
1147                 } else {
1148                     v = 0;
1149                 }
1150                 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
1151 //                InstImm( "bc", PPC_BC, 4, 1, v );
1152                 break;
1153             case OP_GTU:
1154 		#if DEBUG_VM
1155 		if(pass == 1)
1156 		printf("%08x GTU\n",instruction);
1157 		#endif
1158 		assertInteger(opStackDepth-1);
1159 		assertInteger(opStackDepth-2);
1160                 Inst( "cmpl", PPC_CMPL, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1161 		opStackRegType[opStackDepth-1] = 0;
1162 		opStackRegType[opStackDepth-2] = 0;
1163 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1164 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
1165 		opStackDepth -= 2;
1166                 i = Constant4();
1167 		jused[i] = 1;
1168                 InstImm( "bc", PPC_BC, 4, 1, 8 );
1169                 if ( pass==1 ) {
1170                     v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
1171                 } else {
1172                     v = 0;
1173                 }
1174                 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
1175 //                InstImm( "bc", PPC_BC, 12, 1, v );
1176                 break;
1177             case OP_GEU:
1178 		#if DEBUG_VM
1179 		if(pass == 1)
1180 		printf("%08x GEU\n",instruction);
1181 		#endif
1182 		assertInteger(opStackDepth-1);
1183 		assertInteger(opStackDepth-2);
1184                 Inst( "cmpl", PPC_CMPL, 0, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1185 		opStackRegType[opStackDepth-1] = 0;
1186 		opStackRegType[opStackDepth-2] = 0;
1187 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1188 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
1189 		opStackDepth -= 2;
1190                 i = Constant4();
1191 		jused[i] = 1;
1192                 InstImm( "bc", PPC_BC, 12, 0, 8 );
1193                 if ( pass==1 ) {
1194                     v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
1195                 } else {
1196                     v = 0;
1197                 }
1198                 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
1199 //                InstImm( "bc", PPC_BC, 4, 0, v );
1200                 break;
1201 
1202             case OP_EQF:
1203 		#if DEBUG_VM
1204 		if(pass == 1)
1205 		printf("%08x EQF\n",instruction);
1206 		#endif
1207 		makeFloat(opStackDepth-1);
1208 		makeFloat(opStackDepth-2);
1209                 Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
1210 		opStackRegType[opStackDepth-1] = 0;
1211 		opStackRegType[opStackDepth-2] = 0;
1212 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1213 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
1214 		opStackDepth -= 2;
1215                 i = Constant4();
1216 		jused[i] = 1;
1217                 InstImm( "bc", PPC_BC, 4, 2, 8 );
1218                 if ( pass==1 ) {
1219                     v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
1220                 } else {
1221                     v = 0;
1222                 }
1223                 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
1224 //                InstImm( "bc", PPC_BC, 12, 2, v );
1225                 break;
1226             case OP_NEF:
1227 		#if DEBUG_VM
1228 		if(pass == 1)
1229 		printf("%08x NEF\n",instruction);
1230 		#endif
1231 		makeFloat(opStackDepth-1);
1232 		makeFloat(opStackDepth-2);
1233                 Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
1234 		opStackRegType[opStackDepth-1] = 0;
1235 		opStackRegType[opStackDepth-2] = 0;
1236 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1237 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
1238 		opStackDepth -= 2;
1239                 i = Constant4();
1240 		jused[i] = 1;
1241                 InstImm( "bc", PPC_BC, 12, 2, 8 );
1242                 if ( pass==1 ) {
1243                     v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
1244                 } else {
1245                     v = 0;
1246                 }
1247                 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
1248 //                InstImm( "bc", PPC_BC, 4, 2, v );
1249                 break;
1250             case OP_LTF:
1251 		#if DEBUG_VM
1252 		if(pass == 1)
1253 		printf("%08x LTF\n",instruction);
1254 		#endif
1255 		makeFloat(opStackDepth-1);
1256 		makeFloat(opStackDepth-2);
1257                 Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
1258 		opStackRegType[opStackDepth-1] = 0;
1259 		opStackRegType[opStackDepth-2] = 0;
1260 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1261 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
1262 		opStackDepth -= 2;
1263                 i = Constant4();
1264 		jused[i] = 1;
1265                 InstImm( "bc", PPC_BC, 4, 0, 8 );
1266                 if ( pass==1 ) {
1267                     v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
1268                 } else {
1269                     v = 0;
1270                 }
1271                 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
1272 //                InstImm( "bc", PPC_BC, 12, 0, v );
1273                 break;
1274             case OP_LEF:
1275 		#if DEBUG_VM
1276 		if(pass == 1)
1277 		printf("%08x LEF\n",instruction);
1278 		#endif
1279 		makeFloat(opStackDepth-1);
1280 		makeFloat(opStackDepth-2);
1281                 Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
1282 		opStackRegType[opStackDepth-1] = 0;
1283 		opStackRegType[opStackDepth-2] = 0;
1284 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1285 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
1286 		opStackDepth -= 2;
1287                 i = Constant4();
1288 		jused[i] = 1;
1289                 InstImm( "bc", PPC_BC, 12, 1, 8 );
1290                 if ( pass==1 ) {
1291                     v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
1292                 } else {
1293                     v = 0;
1294                 }
1295                 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
1296 //                InstImm( "bc", PPC_BC, 4, 1, v );
1297                 break;
1298             case OP_GTF:
1299 		#if DEBUG_VM
1300 		if(pass == 1)
1301 		printf("%08x GTF\n",instruction);
1302 		#endif
1303 		makeFloat(opStackDepth-1);
1304 		makeFloat(opStackDepth-2);
1305                 Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
1306 		opStackRegType[opStackDepth-1] = 0;
1307 		opStackRegType[opStackDepth-2] = 0;
1308 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1309 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
1310 		opStackDepth -= 2;
1311                 i = Constant4();
1312 		jused[i] = 1;
1313                 InstImm( "bc", PPC_BC, 4, 1, 8 );
1314                 if ( pass==1 ) {
1315                     v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
1316                 } else {
1317                     v = 0;
1318                 }
1319                 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
1320 //                InstImm( "bc", PPC_BC, 12, 1, v );
1321                 break;
1322             case OP_GEF:
1323 		#if DEBUG_VM
1324 		if(pass == 1)
1325 		printf("%08x GEF\n",instruction);
1326 		#endif
1327 		makeFloat(opStackDepth-1);
1328 		makeFloat(opStackDepth-2);
1329                 Inst( "fcmpu", PPC_FCMPU, 0, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
1330 		opStackRegType[opStackDepth-1] = 0;
1331 		opStackRegType[opStackDepth-2] = 0;
1332 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1333 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
1334 		opStackDepth -= 2;
1335                 i = Constant4();
1336 		jused[i] = 1;
1337                 InstImm( "bc", PPC_BC, 12, 0, 8 );
1338                 if ( pass==1 ) {
1339                     v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
1340                 } else {
1341                     v = 0;
1342                 }
1343                 Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
1344 //                InstImm( "bc", PPC_BC, 4, 0, v );
1345                 break;
1346 
1347             case OP_NEGI:
1348 		#if DEBUG_VM
1349 		if(pass == 1)
1350 		printf("%08x NEGI\n",instruction);
1351 		#endif
1352 		assertInteger(opStackDepth-1);
1353                 InstImm( "subfic", PPC_SUBFIC, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 0 );
1354 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1355                 break;
1356             case OP_ADD:
1357 		#if DEBUG_VM
1358 		if(pass == 1)
1359 		printf("%08x ADD\n",instruction);
1360 		#endif
1361 		assertInteger(opStackDepth-1);
1362 		assertInteger(opStackDepth-2);
1363                 Inst( "add", PPC_ADD, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-2] );
1364 		opStackRegType[opStackDepth-1] = 0;
1365 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1366 		opStackDepth -= 1;
1367                 break;
1368             case OP_SUB:
1369 		#if DEBUG_VM
1370 		if(pass == 1)
1371 		printf("%08x SUB\n",instruction);
1372 		#endif
1373 		assertInteger(opStackDepth-1);
1374 		assertInteger(opStackDepth-2);
1375                 Inst( "subf", PPC_SUBF, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-2] );
1376 		opStackRegType[opStackDepth-1] = 0;
1377 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1378 		opStackDepth -= 1;
1379                 break;
1380             case OP_DIVI:
1381 		#if DEBUG_VM
1382 		if(pass == 1)
1383 		printf("%08x DIVI\n",instruction);
1384 		#endif
1385 		assertInteger(opStackDepth-1);
1386 		assertInteger(opStackDepth-2);
1387                 Inst( "divw", PPC_DIVW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1388 		opStackRegType[opStackDepth-1] = 0;
1389 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1390 		opStackDepth -= 1;
1391                 break;
1392             case OP_DIVU:
1393 		#if DEBUG_VM
1394 		if(pass == 1)
1395 		printf("%08x DIVU\n",instruction);
1396 		#endif
1397 		assertInteger(opStackDepth-1);
1398 		assertInteger(opStackDepth-2);
1399                 Inst( "divwu", PPC_DIVWU, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1400 		opStackRegType[opStackDepth-1] = 0;
1401 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1402 		opStackDepth -= 1;
1403                 break;
1404             case OP_MODI:
1405 		#if DEBUG_VM
1406 		if(pass == 1)
1407 		printf("%08x MODI\n",instruction);
1408 		#endif
1409 		assertInteger(opStackDepth-1);
1410 		assertInteger(opStackDepth-2);
1411                 Inst( "divw", PPC_DIVW, R_EA, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1412                 Inst( "mullw", PPC_MULLW, R_EA, opStackIntRegisters[opStackDepth-1], R_EA );
1413                 Inst( "subf", PPC_SUBF, opStackIntRegisters[opStackDepth-2], R_EA, opStackIntRegisters[opStackDepth-2] );
1414 		opStackRegType[opStackDepth-1] = 0;
1415 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1416 		opStackDepth -= 1;
1417                 break;
1418             case OP_MODU:
1419 		#if DEBUG_VM
1420 		if(pass == 1)
1421 		printf("%08x MODU\n",instruction);
1422 		#endif
1423 		assertInteger(opStackDepth-1);
1424 		assertInteger(opStackDepth-2);
1425                 Inst( "divwu", PPC_DIVWU, R_EA, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1426                 Inst( "mullw", PPC_MULLW, R_EA, opStackIntRegisters[opStackDepth-1], R_EA );
1427                 Inst( "subf", PPC_SUBF, opStackIntRegisters[opStackDepth-2], R_EA, opStackIntRegisters[opStackDepth-2] );
1428 		opStackRegType[opStackDepth-1] = 0;
1429 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1430 		opStackDepth -= 1;
1431                 break;
1432             case OP_MULI:
1433             case OP_MULU:
1434 		#if DEBUG_VM
1435 		if(pass == 1)
1436 		printf("%08x MULI\n",instruction);
1437 		#endif
1438 		assertInteger(opStackDepth-1);
1439 		assertInteger(opStackDepth-2);
1440                 Inst( "mullw", PPC_MULLW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-2] );
1441 		opStackRegType[opStackDepth-1] = 0;
1442 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1443 		opStackDepth -= 1;
1444                 break;
1445             case OP_BAND:
1446 		#if DEBUG_VM
1447 		if(pass == 1)
1448 		printf("%08x BAND\n",instruction);
1449 		#endif
1450 		assertInteger(opStackDepth-1);
1451 		assertInteger(opStackDepth-2);
1452                 Inst( "and", PPC_AND, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1453 		opStackRegType[opStackDepth-1] = 0;
1454 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1455 		opStackDepth -= 1;
1456                 break;
1457             case OP_BOR:
1458 		#if DEBUG_VM
1459 		if(pass == 1)
1460 		printf("%08x BOR\n",instruction);
1461 		#endif
1462 		assertInteger(opStackDepth-1);
1463 		assertInteger(opStackDepth-2);
1464                 Inst( "or", PPC_OR, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1465 		opStackRegType[opStackDepth-1] = 0;
1466 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1467 		opStackDepth -= 1;
1468                 break;
1469             case OP_BXOR:
1470 		#if DEBUG_VM
1471 		if(pass == 1)
1472 		printf("%08x BXOR\n",instruction);
1473 		#endif
1474 		assertInteger(opStackDepth-1);
1475 		assertInteger(opStackDepth-2);
1476                 Inst( "xor", PPC_XOR, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1477 		opStackRegType[opStackDepth-1] = 0;
1478 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1479 		opStackDepth -= 1;
1480                 break;
1481             case OP_BCOM:
1482 		#if DEBUG_VM
1483 		if(pass == 1)
1484 		printf("%08x BCOM\n",instruction);
1485 		#endif
1486 		assertInteger(opStackDepth-1);
1487                 Inst( "nor", PPC_NOR, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1] );
1488 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1489                 break;
1490             case OP_LSH:
1491 		#if DEBUG_VM
1492 		if(pass == 1)
1493 		printf("%08x LSH\n",instruction);
1494 		#endif
1495 		assertInteger(opStackDepth-1);
1496 		assertInteger(opStackDepth-2);
1497                 Inst( "slw", PPC_SLW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1498 		opStackRegType[opStackDepth-1] = 0;
1499 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1500 		opStackDepth -= 1;
1501                 break;
1502             case OP_RSHI:
1503 		#if DEBUG_VM
1504 		if(pass == 1)
1505 		printf("%08x RSHI\n",instruction);
1506 		#endif
1507 		assertInteger(opStackDepth-1);
1508 		assertInteger(opStackDepth-2);
1509                 Inst( "sraw", PPC_SRAW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1510 		opStackRegType[opStackDepth-1] = 0;
1511 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1512 		opStackDepth -= 1;
1513                 break;
1514             case OP_RSHU:
1515 		#if DEBUG_VM
1516 		if(pass == 1)
1517 		printf("%08x RSHU\n",instruction);
1518 		#endif
1519 		assertInteger(opStackDepth-1);
1520 		assertInteger(opStackDepth-2);
1521                 Inst( "srw", PPC_SRW, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-1] );
1522 		opStackRegType[opStackDepth-1] = 0;
1523 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1524 		opStackDepth -= 1;
1525                 break;
1526 
1527             case OP_NEGF:
1528 		#if DEBUG_VM
1529 		if(pass == 1)
1530 		printf("%08x NEGF\n",instruction);
1531 		#endif
1532 		makeFloat(opStackDepth-1);
1533                 Inst( "fneg", PPC_FNEG, opStackFloatRegisters[opStackDepth-1], 0, opStackFloatRegisters[opStackDepth-1] );
1534 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1535                 break;
1536             case OP_ADDF:
1537 		#if DEBUG_VM
1538 		if(pass == 1)
1539 		printf("%08x ADDF\n",instruction);
1540 		#endif
1541 		makeFloat(opStackDepth-1);
1542 		makeFloat(opStackDepth-2);
1543                 Inst( "fadds", PPC_FADDS, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
1544 		opStackRegType[opStackDepth-1] = 0;
1545 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1546 		opStackDepth -= 1;
1547                 break;
1548             case OP_SUBF:
1549 		#if DEBUG_VM
1550 		if(pass == 1)
1551 		printf("%08x SUBF\n",instruction);
1552 		#endif
1553 		makeFloat(opStackDepth-1);
1554 		makeFloat(opStackDepth-2);
1555                 Inst( "fsubs", PPC_FSUBS, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
1556 		opStackRegType[opStackDepth-1] = 0;
1557 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1558 		opStackDepth -= 1;
1559                 break;
1560             case OP_DIVF:
1561 		#if DEBUG_VM
1562 		if(pass == 1)
1563 		printf("%08x DIVF\n",instruction);
1564 		#endif
1565 		makeFloat(opStackDepth-1);
1566 		makeFloat(opStackDepth-2);
1567                 Inst( "fdivs", PPC_FDIVS, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-1] );
1568 		opStackRegType[opStackDepth-1] = 0;
1569 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1570 		opStackDepth -= 1;
1571                 break;
1572             case OP_MULF:
1573 		#if DEBUG_VM
1574 		if(pass == 1)
1575 		printf("%08x MULF\n",instruction);
1576 		#endif
1577 		makeFloat(opStackDepth-1);
1578 		makeFloat(opStackDepth-2);
1579                 Inst4( "fmuls", PPC_FMULS, opStackFloatRegisters[opStackDepth-2], opStackFloatRegisters[opStackDepth-2], 0, opStackFloatRegisters[opStackDepth-1] );
1580 		opStackRegType[opStackDepth-1] = 0;
1581 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1582 		opStackDepth -= 1;
1583                 break;
1584 
1585             case OP_CVIF:
1586 		#if DEBUG_VM
1587 		if(pass == 1)
1588 		printf("%08x CVIF\n",instruction);
1589 		#endif
1590 		assertInteger(opStackDepth-1);
1591 		//makeInteger(opStackDepth-1);
1592                 v = (int)&itofConvert;
1593                 InstImmU( "addis", PPC_ADDIS, R_EA, 0, (v >> 16)&0xffff );
1594                 InstImmU( "ori", PPC_ORI, R_EA, R_EA, v & 0xffff );
1595                 InstImmU( "xoris", PPC_XORIS, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 0x8000 );
1596                 InstImm( "stw", PPC_STW, opStackIntRegisters[opStackDepth-1], R_EA, 12 );
1597                 InstImm( "lfd", PPC_LFD, opStackFloatRegisters[opStackDepth-1], R_EA, 0 );
1598 		Inst( "ori", PPC_ORI, 0, 0, 0);
1599 		Inst( "ori", PPC_ORI, 0, 0, 0);
1600 		Inst( "ori", PPC_ORI, 0, 0, 0);
1601                 InstImm( "lfd", PPC_LFD, 13, R_EA, 8 );
1602                 Inst( "fsub", PPC_FSUB, opStackFloatRegisters[opStackDepth-1], 13, opStackFloatRegisters[opStackDepth-1] );
1603 		opStackRegType[opStackDepth-1] = 2;
1604 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1605     //            Inst( PPC_FRSP, R_TOP, 0, R_TOP );
1606                 break;
1607             case OP_CVFI:
1608 		#if DEBUG_VM
1609 		if(pass == 1)
1610 		printf("%08x CVFI\n",instruction);
1611 		#endif
1612 		makeFloat(opStackDepth-1);
1613 
1614 		InstImm( "addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, opStackDepth*4);
1615 
1616                 Inst( "fctiwz", PPC_FCTIWZ, opStackFloatRegisters[opStackDepth-1], 0, opStackFloatRegisters[opStackDepth-1] );
1617                 Inst( "stfiwx", PPC_STFIWX, opStackFloatRegisters[opStackDepth-1], 0, R_OPSTACK );		// save value to opstack (dummy area now)
1618 		Inst( "ori", PPC_ORI, 0, 0, 0);
1619 		Inst( "ori", PPC_ORI, 0, 0, 0);
1620 		Inst( "ori", PPC_ORI, 0, 0, 0);
1621 		Inst( "ori", PPC_ORI, 0, 0, 0);
1622                 InstImm( "lwz", PPC_LWZ, opStackIntRegisters[opStackDepth-1], R_OPSTACK, 0 );
1623 
1624 		InstImm( "addi", PPC_ADDI, R_OPSTACK, R_OPSTACK, -opStackDepth*4);
1625 
1626 		opStackRegType[opStackDepth-1] = 1;
1627 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1628                 break;
1629             case OP_SEX8:
1630 		#if DEBUG_VM
1631 		if(pass == 1)
1632 		printf("%08x SEX8\n",instruction);
1633 		#endif
1634 		assertInteger(opStackDepth-1);
1635                 Inst( "extsb", PPC_EXTSB, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 0 );
1636 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1637                 break;
1638             case OP_SEX16:
1639 		#if DEBUG_VM
1640 		if(pass == 1)
1641 		printf("%08x SEX16\n",instruction);
1642 		#endif
1643 		assertInteger(opStackDepth-1);
1644                 Inst( "extsh", PPC_EXTSH, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 0 );
1645 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1646                 break;
1647 
1648             case OP_BLOCK_COPY:
1649                 v = Constant4() >> 2;
1650 		#if DEBUG_VM
1651 		if(pass == 1)
1652 		printf("%08x BLOCK_COPY\t%08lx\n",instruction,v<<2);
1653 		#endif
1654 		assert(opStackDepth >= 2);
1655 		assertInteger(opStackDepth-1);
1656 		assertInteger(opStackDepth-2);
1657                 InstImmU( "addi", PPC_ADDI, R_EA, 0, v );				// count
1658 				// FIXME: range check
1659               	Inst( "mtctr", PPC_MTSPR, R_EA, 9, 0 );					// move to count register
1660 
1661                 Inst( "add", PPC_ADD, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_MEMBASE );
1662                 InstImm( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], -4 );
1663                 Inst( "add", PPC_ADD, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], R_MEMBASE );
1664                 InstImm( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth-2], opStackIntRegisters[opStackDepth-2], -4 );
1665 
1666                 InstImm( "lwzu", PPC_LWZU, R_EA, opStackIntRegisters[opStackDepth-1], 4 );		// source
1667                 InstImm( "stwu", PPC_STWU, R_EA, opStackIntRegisters[opStackDepth-2], 4 );	// dest
1668                 Inst( "b", PPC_BC | 0xfff8 , 16, 0, 0 );					// loop
1669 		opStackRegType[opStackDepth-1] = 0;
1670 		opStackRegType[opStackDepth-2] = 0;
1671 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1672 		opStackLoadInstructionAddr[opStackDepth-2] = 0;
1673 		opStackDepth -= 2;
1674                 break;
1675 
1676             case OP_JUMP:
1677 		#if DEBUG_VM
1678 		if(pass == 1)
1679 		printf("%08x JUMP\n",instruction);
1680 		#endif
1681 		assert(opStackDepth == 1);
1682 		assertInteger(opStackDepth-1);
1683 
1684                 Inst( "rlwinm", PPC_RLWINM | ( 29 << 1 ), opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], 2 );
1685 		// FIXME: range check
1686 		Inst( "lwzx", PPC_LWZX, opStackIntRegisters[opStackDepth-1], opStackIntRegisters[opStackDepth-1], R_INSTRUCTIONS );
1687                 Inst( "mtctr", PPC_MTSPR, opStackIntRegisters[opStackDepth-1], 9, 0 );		// move to count register
1688                 Inst( "bctr", PPC_BCCTR, 20, 0, 0 );		// jump to the count register
1689 		opStackRegType[opStackDepth-1] = 0;
1690 		opStackLoadInstructionAddr[opStackDepth-1] = 0;
1691 		opStackDepth -= 1;
1692                 break;
1693             default:
1694                 Com_Error( ERR_DROP, "VM_CompilePPC: bad opcode %i at instruction %i, offset %i", op, instruction, pc );
1695             }
1696 	    pop0 = pop1;
1697 	    pop1 = op;
1698 		assert(opStackDepth >= 0);
1699 		assert(opStackDepth < OP_STACK_MAX_DEPTH);
1700 
1701 		//printf("%4d\t%s\n",opStackDepth,opnames[op]);
1702         }
1703 
1704 	Com_Printf( "VM file %s pass %d compiled to %i bytes of code\n", vm->name, (pass+1), compiledOfs*4 );
1705 
1706     	if ( pass == 0 ) {
1707 	    // copy to an exact size buffer on the hunk
1708 	    vm->codeLength = compiledOfs * 4;
1709 	    vm->codeBase = Hunk_Alloc( vm->codeLength, h_low );
1710 	    Com_Memcpy( vm->codeBase, buf, vm->codeLength );
1711 
1712 	    //printf("codeBase: %p\n",vm->codeBase);
1713 
1714 	    Z_Free( buf );
1715 
1716 	    // offset all the instruction pointers for the new location
1717 	    for ( i = 0 ; i < header->instructionCount ; i++ ) {
1718 		vm->instructionPointers[i] += (int)vm->codeBase;
1719 		//printf("%08x %08lx\n",i,vm->instructionPointers[i]);
1720 	    }
1721 
1722 	    // go back over it in place now to fixup reletive jump targets
1723 	    buf = (unsigned *)vm->codeBase;
1724 	} else if ( pass == 1 ) {
1725            // clear the instruction cache for generated code
1726            msync(vm->codeBase, vm->codeLength, MS_INVALIDATE);
1727        }
1728     }
1729     if(0)
1730     {
1731 	char buf[256];
1732 	printf("wait..\n");
1733 	gets(buf);
1734     }
1735     Z_Free( jused );
1736 }
1737 
1738 /*
1739 ==============
1740 VM_CallCompiled
1741 
1742 This function is called directly by the generated code
1743 ==============
1744 */
VM_CallCompiled(vm_t * vm,int * args)1745 int	VM_CallCompiled( vm_t *vm, int *args ) {
1746 	int		stack[1024];
1747 	int		programStack;
1748 	int		stackOnEntry;
1749 	byte	*image;
1750 
1751 	currentVM = vm;
1752 
1753 	//printf("VM_CallCompiled: %p   %08lx %08lx %08lx\n",
1754 	//	vm, args[0],args[1],args[2]);
1755 
1756 	// interpret the code
1757 	vm->currentlyInterpreting = qtrue;
1758 
1759 	// we might be called recursively, so this might not be the very top
1760 	programStack = vm->programStack;
1761 	stackOnEntry = programStack;
1762 	image = vm->dataBase;
1763 
1764 	// set up the stack frame
1765 	programStack -= 48;
1766 
1767 	*(int *)&image[ programStack + 44] = args[9];
1768 	*(int *)&image[ programStack + 40] = args[8];
1769 	*(int *)&image[ programStack + 36] = args[7];
1770 	*(int *)&image[ programStack + 32] = args[6];
1771 	*(int *)&image[ programStack + 28] = args[5];
1772 	*(int *)&image[ programStack + 24] = args[4];
1773 	*(int *)&image[ programStack + 20] = args[3];
1774 	*(int *)&image[ programStack + 16] = args[2];
1775 	*(int *)&image[ programStack + 12] = args[1];
1776 	*(int *)&image[ programStack + 8 ] = args[0];
1777 	*(int *)&image[ programStack + 4 ] = 0;	// return stack
1778 	*(int *)&image[ programStack ] = -1;	// will terminate the loop on return
1779 
1780 	// Cheesy... manually save registers used by VM call...
1781 	// off we go into generated code...
1782 	// the PPC calling standard says the parms will all go into R3 - R11, so
1783 	// no special asm code is needed here
1784 #ifdef __GNUC__
1785 	((void(*)(int, int, int, int, int, int, int, int))(vm->codeBase))(
1786 		programStack, (int)&stack,
1787 		(int)image, vm->dataMask, (int)&AsmCall,
1788 		(int)vm->instructionPointers, vm->instructionPointersLength,
1789         (int)vm );
1790 #else
1791 	((void(*)(int, int, int, int, int, int, int, int))(vm->codeBase))(
1792 		programStack, (int)&stack,
1793 		(int)image, vm->dataMask, *(int *)&AsmCall /* skip function pointer header */,
1794 		(int)vm->instructionPointers, vm->instructionPointersLength,
1795         (int)vm );
1796 #endif
1797 	vm->programStack = stackOnEntry;
1798 
1799     vm->currentlyInterpreting = qfalse;
1800 
1801 	return stack[1];
1802 }
1803 
1804 
1805 /*
1806 ==================
1807 AsmCall
1808 
1809 Put this at end of file because gcc messes up debug line numbers
1810 ==================
1811 */
1812 #ifdef __GNUC__
1813 
AsmCall(void)1814 void AsmCall( void ) {
1815 asm (
1816      // pop off the destination instruction
1817 "    lwz		12,0(4)	\n"	// RG_TOP, 0(RG_OPSTACK)
1818 "    addi	4,4,-4		\n"	// RG_OPSTACK, RG_OPSTACK, -4 \n"
1819 
1820     // see if it is a system trap
1821 "    cmpwi	12,0			\n"	// RG_TOP, 0 \n"
1822 "    bc		12,0, systemTrap	\n"
1823 
1824     // calling another VM function, so lookup in instructionPointers
1825 "    slwi	12,12,2		\n"	// RG_TOP,RG_TOP,2
1826                         // FIXME: range check
1827 "    lwzx	12, 8, 12		\n"	// RG_TOP, RG_INSTRUCTIONS(RG_TOP)
1828 "    mtctr	12			\n"	// RG_TOP
1829 );
1830 
1831 #if defined(MACOS_X) && defined(__OPTIMIZE__)
1832     // On Mac OS X, gcc doesn't push a frame when we are optimized, so trying to tear it down results in grave disorder.
1833 //#warning Mac OS X optimization on, not popping GCC AsmCall frame
1834 #else
1835     // Mac OS X Server and unoptimized compiles include a GCC AsmCall frame
1836     asm (
1837 "	lwz		1,0(1)	\n"	// pop off the GCC AsmCall frame
1838 "	lmw		30,-8(1)	\n"
1839 );
1840 #endif
1841 
1842 asm (
1843 "	    bcctr	20,0		\n" // when it hits a leave, it will branch to the current link register
1844 
1845     // calling a system trap
1846 "systemTrap:				\n"
1847 	// convert to positive system call number
1848 "	subfic	12,12,-1		\n"
1849 
1850     // save all our registers, including the current link register
1851 "    mflr	13			\n"	// RG_SECOND		// copy off our link register
1852 "	addi	1,1,-92		\n"	// required 24 byets of linkage, 32 bytes of parameter, plus our saves
1853 "    stw		3,56(1)	\n"	// RG_STACK, -36(REAL_STACK)
1854 "    stw		4,60(1)	\n"	// RG_OPSTACK, 4(RG_REAL_STACK)
1855 "    stw		5,64(1)	\n"	// RG_MEMBASE, 8(RG_REAL_STACK)
1856 "    stw		6,68(1)	\n"	// RG_MEMMASK, 12(RG_REAL_STACK)
1857 "    stw		7,72(1)	\n"	// RG_ASMCALL, 16(RG_REAL_STACK)
1858 "    stw		8,76(1)	\n"	// RG_INSTRUCTIONS, 20(RG_REAL_STACK)
1859 "    stw		9,80(1)	\n"	// RG_NUM_INSTRUCTIONS, 24(RG_REAL_STACK)
1860 "    stw		10,84(1)	\n"	// RG_VM, 28(RG_REAL_STACK)
1861 "    stw		13,88(1)	\n"	// RG_SECOND, 32(RG_REAL_STACK)	// link register
1862 
1863     // save the vm stack position to allow recursive VM entry
1864 "    addi	13,3,-4		\n"	// RG_TOP, RG_STACK, -4
1865 "    stw		13,0(10)	\n"	//RG_TOP, VM_OFFSET_PROGRAM_STACK(RG_VM)
1866 
1867     // save the system call number as the 0th parameter
1868 "    add		3,3,5	\n"	// r3,  RG_STACK, RG_MEMBASE		// r3 is the first parameter to vm->systemCalls
1869 "    stwu	12,4(3)		\n"	// RG_TOP, 4(r3)
1870 
1871     // make the system call with the address of all the VM parms as a parameter
1872     // vm->systemCalls( &parms )
1873 "    lwz		12,4(10)	\n"	// RG_TOP, VM_OFFSET_SYSTEM_CALL(RG_VM)
1874 "    mtctr	12			\n"	// RG_TOP
1875 "    bcctrl	20,0			\n"
1876 "    mr		12,3			\n"	// RG_TOP, r3
1877 
1878     // pop our saved registers
1879 "   	lwz		3,56(1)	\n"	// RG_STACK, 0(RG_REAL_STACK)
1880 "   	lwz		4,60(1)	\n"	// RG_OPSTACK, 4(RG_REAL_STACK)
1881 "   	lwz		5,64(1)	\n"	// RG_MEMBASE, 8(RG_REAL_STACK)
1882 "   	lwz		6,68(1)	\n"	// RG_MEMMASK, 12(RG_REAL_STACK)
1883 "   	lwz		7,72(1)	\n"	// RG_ASMCALL, 16(RG_REAL_STACK)
1884 "   	lwz		8,76(1)	\n"	// RG_INSTRUCTIONS, 20(RG_REAL_STACK)
1885 "   	lwz		9,80(1)	\n"	// RG_NUM_INSTRUCTIONS, 24(RG_REAL_STACK)
1886 "   	lwz		10,84(1)	\n"	// RG_VM, 28(RG_REAL_STACK)
1887 "   	lwz		13,88(1)	\n"	// RG_SECOND, 32(RG_REAL_STACK)
1888 "    addi	1,1,92		\n"	// RG_REAL_STACK, RG_REAL_STACK, 36
1889 
1890     // restore the old link register
1891 "    mtlr	13			\n"	// RG_SECOND
1892 
1893     // save off the return value
1894 "    stwu	12,4(4)		\n"	// RG_TOP, 0(RG_OPSTACK)
1895 
1896 	// GCC adds its own prolog / epliog code
1897  );
1898 }
1899 #else
1900 
1901 // codewarrior version
1902 
AsmCall(void)1903 void asm AsmCall( void ) {
1904 
1905     // pop off the destination instruction
1906 
1907     lwz		r12,0(r4)	// RG_TOP, 0(RG_OPSTACK)
1908 
1909     addi	r4,r4,-4	// RG_OPSTACK, RG_OPSTACK, -4
1910 
1911 
1912 
1913     // see if it is a system trap
1914 
1915     cmpwi	r12,0		// RG_TOP, 0
1916 
1917     bc		12,0, systemTrap
1918 
1919 
1920 
1921     // calling another VM function, so lookup in instructionPointers
1922 
1923     slwi	r12,r12,2		// RG_TOP,RG_TOP,2
1924 
1925                         // FIXME: range check
1926 
1927     lwzx	r12, r8, r12	// RG_TOP, RG_INSTRUCTIONS(RG_TOP)
1928 
1929     mtctr	r12			// RG_TOP
1930 
1931 
1932 
1933     bcctr	20,0		// when it hits a leave, it will branch to the current link register
1934 
1935 
1936 
1937     // calling a system trap
1938 
1939 systemTrap:
1940 
1941 	// convert to positive system call number
1942 
1943 	subfic	r12,r12,-1
1944 
1945 
1946 
1947     // save all our registers, including the current link register
1948 
1949     mflr	r13			// RG_SECOND		// copy off our link register
1950 
1951 	addi	r1,r1,-92	// required 24 byets of linkage, 32 bytes of parameter, plus our saves
1952 
1953     stw		r3,56(r1)	// RG_STACK, -36(REAL_STACK)
1954 
1955     stw		r4,60(r1)	// RG_OPSTACK, 4(RG_REAL_STACK)
1956 
1957     stw		r5,64(r1)	// RG_MEMBASE, 8(RG_REAL_STACK)
1958 
1959     stw		r6,68(r1)	// RG_MEMMASK, 12(RG_REAL_STACK)
1960 
1961     stw		r7,72(r1)	// RG_ASMCALL, 16(RG_REAL_STACK)
1962 
1963     stw		r8,76(r1)	// RG_INSTRUCTIONS, 20(RG_REAL_STACK)
1964 
1965     stw		r9,80(r1)	// RG_NUM_INSTRUCTIONS, 24(RG_REAL_STACK)
1966 
1967     stw		r10,84(r1)	// RG_VM, 28(RG_REAL_STACK)
1968 
1969     stw		r13,88(r1)	// RG_SECOND, 32(RG_REAL_STACK)	// link register
1970 
1971 
1972 
1973     // save the vm stack position to allow recursive VM entry
1974 
1975     addi	r13,r3,-4	// RG_TOP, RG_STACK, -4
1976 
1977     stw		r13,0(r10)	//RG_TOP, VM_OFFSET_PROGRAM_STACK(RG_VM)
1978 
1979 
1980 
1981     // save the system call number as the 0th parameter
1982 
1983     add		r3,r3,r5	// r3,  RG_STACK, RG_MEMBASE		// r3 is the first parameter to vm->systemCalls
1984 
1985     stwu	r12,4(r3)	// RG_TOP, 4(r3)
1986 
1987 
1988 
1989     // make the system call with the address of all the VM parms as a parameter
1990 
1991     // vm->systemCalls( &parms )
1992 
1993     lwz		r12,4(r10)	// RG_TOP, VM_OFFSET_SYSTEM_CALL(RG_VM)
1994 
1995 
1996 
1997     // perform macos cross fragment fixup crap
1998 
1999     lwz		r9,0(r12)
2000 
2001     stw		r2,52(r1)	// save old TOC
2002 
2003 	lwz		r2,4(r12)
2004 
2005 
2006 
2007     mtctr	r9			// RG_TOP
2008 
2009     bcctrl	20,0
2010 
2011 
2012 
2013     lwz		r2,52(r1)	// restore TOC
2014 
2015 
2016 
2017     mr		r12,r3		// RG_TOP, r3
2018 
2019 
2020 
2021     // pop our saved registers
2022 
2023    	lwz		r3,56(r1)	// RG_STACK, 0(RG_REAL_STACK)
2024 
2025    	lwz		r4,60(r1)	// RG_OPSTACK, 4(RG_REAL_STACK)
2026 
2027    	lwz		r5,64(r1)	// RG_MEMBASE, 8(RG_REAL_STACK)
2028 
2029    	lwz		r6,68(r1)	// RG_MEMMASK, 12(RG_REAL_STACK)
2030 
2031    	lwz		r7,72(r1)	// RG_ASMCALL, 16(RG_REAL_STACK)
2032 
2033    	lwz		r8,76(r1)	// RG_INSTRUCTIONS, 20(RG_REAL_STACK)
2034 
2035    	lwz		r9,80(r1)	// RG_NUM_INSTRUCTIONS, 24(RG_REAL_STACK)
2036 
2037    	lwz		r10,84(r1)	// RG_VM, 28(RG_REAL_STACK)
2038 
2039    	lwz		r13,88(r1)	// RG_SECOND, 32(RG_REAL_STACK)
2040 
2041     addi	r1,r1,92	// RG_REAL_STACK, RG_REAL_STACK, 36
2042 
2043 
2044 
2045     // restore the old link register
2046 
2047     mtlr	r13			// RG_SECOND
2048 
2049 
2050 
2051     // save off the return value
2052 
2053     stwu	r12,4(r4)	// RG_TOP, 0(RG_OPSTACK)
2054 
2055 
2056 
2057 	blr
2058 
2059 }
2060 
2061 
2062 
2063 
2064 #endif
2065