~ubuntu-branches/ubuntu/precise/openarena/precise

« back to all changes in this revision

Viewing changes to code/qcommon/vm_ppc.c

  • Committer: Bazaar Package Importer
  • Author(s): Ansgar Burchardt
  • Date: 2008-09-05 21:14:51 UTC
  • mfrom: (1.2.1 upstream) (2.1.5 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080905211451-243bmbl6l6gdav7l
* Remove non-free code/tools/lcc (Closes: #496346)
  + Remove hunk from patch 10_fix_build_and_binary_on_alpha
  + debian/rules: Add BUILD_GAME_QVM=0 to $(MAKE) call
    (thanks to Peter De Wachter)
* Remove code/libs containing binary libraries for Mac OS X and Win32
* debian/copyright: Explain which parts of upstream's sources were removed
* debian/rules: replace ${source:Upstream-Version} by 0.7.7
  because the variable also contains the `+dfsg1' part
* Add -fsigned-char to compiler options (Closes: #487970)
  (thanks to Peter De Wachter)
* Add myself to Uploaders
* debian/control: Remove article from beginning of short description,
  don't start short description with a capital letter
* debian/openarena.6: Escape minus signs
  + fixes lintian warnings: hyphen-used-as-minus-sign

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
// ppc dynamic compiler
24
24
 
25
25
#include "vm_local.h"
26
 
 
27
 
#pragma opt_pointer_analysis off
28
 
 
 
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
29
119
 
30
120
typedef enum {
31
121
    R_REAL_STACK = 1,
63
153
#define RG_SECOND                       r13
64
154
#define RG_EA                           r14
65
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
 
66
192
// this doesn't have the low order bits set for instructions i'm not using...
67
193
typedef enum {
68
194
        PPC_TDI         = 0x08000000,
199
325
        PPC_MCRXR       = 0x7c000000,
200
326
        PPC_LSWX        = 0x7c000000,
201
327
        PPC_LWBRX       = 0x7c000000,
202
 
        PPC_LFSX        = 0x7c000000,
 
328
        PPC_LFSX        = 0x7c00042e,
203
329
        PPC_SRW         = 0x7c000430,
204
330
        PPC_SRD         = 0x7c000000,
205
331
        PPC_TLBSYNC     = 0x7c000000,
212
338
        PPC_MFSRIN      = 0x7c000000,
213
339
        PPC_STSWX       = 0x7c000000,
214
340
        PPC_STWBRX      = 0x7c000000,
215
 
        PPC_STFSX       = 0x7c000000,
 
341
        PPC_STFSX       = 0x7c00052e,
216
342
        PPC_STFSUX      = 0x7c000000,
217
343
        PPC_STSWI       = 0x7c000000,
218
344
        PPC_STFDX       = 0x7c000000,
308
434
// the newly generated code
309
435
static  unsigned        *buf;
310
436
static  int             compiledOfs;    // in dwords
 
437
static int pass;
311
438
 
312
439
// fromt the original bytecode
313
440
static  byte    *code;
333
460
        return v;
334
461
}
335
462
 
336
 
static void Emit4( 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
337
468
        buf[ compiledOfs ] = i;
338
469
        compiledOfs++;
339
470
}
340
471
 
341
 
static void Inst( int opcode, int destReg, int aReg, int bReg ) {
 
472
static void Inst( char *opname, int opcode, int destReg, int aReg, int bReg ) {
342
473
    unsigned            r;
343
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
344
479
    r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) ;
345
480
    buf[ compiledOfs ] = r;
346
481
    compiledOfs++;
347
482
}
348
483
 
349
 
static void Inst4( 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 ) {
350
485
    unsigned            r;
351
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
352
491
    r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) | ( cReg << 6 );
353
492
    buf[ compiledOfs ] = r;
354
493
    compiledOfs++;
355
494
}
356
495
 
357
 
static void InstImm( int opcode, int destReg, int aReg, int immediate ) {
 
496
static void InstImm( char *opname, int opcode, int destReg, int aReg, int immediate ) {
358
497
        unsigned                r;
359
498
        
360
499
        if ( immediate > 32767 || immediate < -32768 ) {
361
500
            Com_Error( ERR_FATAL, "VM_Compile: immediate value %i out of range, opcode %x,%d,%d", immediate, opcode, destReg, aReg );
362
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
363
506
        r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( immediate & 0xffff );
364
507
        buf[ compiledOfs ] = r;
365
508
        compiledOfs++;
366
509
}
367
510
 
368
 
static void InstImmU( int opcode, int destReg, int aReg, int immediate ) {
 
511
static void InstImmU( char *opname, int opcode, int destReg, int aReg, int immediate ) {
369
512
        unsigned                r;
370
513
        
371
514
        if ( immediate > 0xffff || immediate < 0 ) {
372
515
                Com_Error( ERR_FATAL, "VM_Compile: immediate value %i out of range", immediate );
373
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
374
521
    r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( immediate & 0xffff );
375
522
        buf[ compiledOfs ] = r;
376
523
        compiledOfs++;
377
524
}
378
525
 
379
 
static qboolean rtopped;
380
526
static int pop0, pop1, oc0, oc1;
381
527
static vm_t *tvm;
382
528
static int instruction;
383
529
static byte *jused;
384
 
static int pass;
385
 
 
386
 
static void ltop() {
387
 
    if (rtopped == qfalse) {
388
 
        InstImm( PPC_LWZ, R_TOP, R_OPSTACK, 0 );                // get value from opstack
389
 
    }
390
 
}
391
 
 
392
 
static void ltopandsecond() {
393
 
    if (pass>=0 && buf[compiledOfs-1] == (PPC_STWU |  R_TOP<<21 | R_OPSTACK<<16 | 4 ) && jused[instruction]==0 ) {
394
 
        compiledOfs--;
395
 
        if (!pass) {
396
 
            tvm->instructionPointers[instruction] = compiledOfs * 4;
397
 
        }
398
 
        InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 );     // get value from opstack
399
 
        InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
400
 
    } else if (pass>=0 && buf[compiledOfs-1] == (PPC_STW |  R_TOP<<21 | R_OPSTACK<<16 | 0 )  && jused[instruction]==0 ) {
401
 
        compiledOfs--;
402
 
        if (!pass) {
403
 
            tvm->instructionPointers[instruction] = compiledOfs * 4;
404
 
        }
405
 
        InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, -4 );    // get value from opstack
406
 
        InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -8 );
407
 
    } else {
408
 
        ltop();         // get value from opstack
409
 
        InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, -4 );    // get value from opstack
410
 
        InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -8 );
411
 
    }
412
 
    rtopped = qfalse;
 
530
 
 
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
 
 
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
 
 
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
        }
413
636
}
414
637
 
415
638
// TJW: Unused
421
644
}
422
645
#endif
423
646
 
 
647
#if 0
424
648
static void fltopandsecond() {
425
649
        InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 );                // get value from opstack
426
650
        InstImm( PPC_LFS, R_SECOND, R_OPSTACK, -4 );    // get value from opstack
428
652
    rtopped = qfalse;
429
653
        return;
430
654
}
 
655
#endif
 
656
 
 
657
#define assertInteger(depth)    assert(opStackRegType[depth] == 1)
431
658
 
432
659
/*
433
660
=================
439
666
        int             maxLength;
440
667
        int             v;
441
668
        int             i;
442
 
        
 
669
        int             opStackDepth;
 
670
        
 
671
        int             mainFunction;
 
672
        
443
673
        // set up the into-to-float variables
444
674
        ((int *)itofConvert)[0] = 0x43300000;
445
675
        ((int *)itofConvert)[1] = 0x80000000;
455
685
    // pointers for branches
456
686
    for ( pass = -1 ; pass < 2 ; pass++ ) {
457
687
 
458
 
        rtopped = qfalse;
459
688
        // translate all instructions
460
689
        pc = 0;
 
690
        mainFunction = 0;
 
691
        opStackDepth = 0;
461
692
        
462
693
        pop0 = 343545;
463
694
        pop1 = 2443545;
472
703
                Emit4( 0 );
473
704
#endif
474
705
 
475
 
                for ( instruction = 0 ; instruction < header->instructionCount ; instruction++ ) {
 
706
        for ( instruction = 0 ; instruction < header->instructionCount ; instruction++ ) {
476
707
            if ( compiledOfs*4 > maxLength - 16 ) {
477
708
                Com_Error( ERR_DROP, "VM_Compile: maxLength exceeded" );
478
709
            }
486
717
            case 0:
487
718
                break;
488
719
            case OP_BREAK:
489
 
                InstImmU( PPC_ADDI, R_TOP, 0, 0 );
490
 
                InstImm( PPC_LWZ, R_TOP, R_TOP, 0 );                    // *(int *)0 to crash to debugger
491
 
                rtopped = qfalse;
 
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
492
726
                break;
493
727
            case OP_ENTER:
494
 
                InstImm( PPC_ADDI, R_STACK, R_STACK, -Constant4() );    // sub R_STACK, R_STACK, imm
495
 
                rtopped = qfalse;
 
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
496
746
                break;
497
747
            case OP_CONST:
498
748
                v = Constant4();
499
 
                if (code[pc] == OP_LOAD4 || code[pc] == OP_LOAD2 || code[pc] == OP_LOAD1) {
500
 
                    v &= vm->dataMask;
501
 
                }
 
749
                #if DEBUG_VM
 
750
                if(pass == 1)
 
751
                        printf("%08x CONST\t%08x\n",instruction,v);
 
752
                #endif
 
753
                opStackLoadInstructionAddr[opStackDepth] = 0;
502
754
                if ( v < 32768 && v >= -32768 ) {
503
 
                    InstImmU( PPC_ADDI, R_TOP, 0, v & 0xffff );
 
755
                    InstImmU( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth], 0, v & 0xffff );
504
756
                } else {
505
 
                    InstImmU( PPC_ADDIS, R_TOP, 0, (v >> 16)&0xffff );
 
757
                    InstImmU( "addis", PPC_ADDIS, opStackIntRegisters[opStackDepth], 0, (v >> 16)&0xffff );
506
758
                    if ( v & 0xffff ) {
507
 
                        InstImmU( PPC_ORI, R_TOP, R_TOP, v & 0xffff );
 
759
                        InstImmU( "ori", PPC_ORI, opStackIntRegisters[opStackDepth], opStackIntRegisters[opStackDepth], v & 0xffff );
508
760
                    }
509
761
                }
510
 
                if (code[pc] == OP_LOAD4) {
511
 
                    Inst( PPC_LWZX, R_TOP, R_TOP, R_MEMBASE );          // load from memory base
512
 
                    pc++;
513
 
                    instruction++;
514
 
                } else if (code[pc] == OP_LOAD2) {
515
 
                    Inst( PPC_LHZX, R_TOP, R_TOP, R_MEMBASE );          // load from memory base
516
 
                    pc++;
517
 
                    instruction++;
518
 
                } else if (code[pc] == OP_LOAD1) {
519
 
                    Inst( PPC_LBZX, R_TOP, R_TOP, R_MEMBASE );          // load from memory base
520
 
                    pc++;
521
 
                    instruction++;
522
 
                }
523
 
                if (code[pc] == OP_STORE4) {
524
 
                    InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 ); // get value from opstack
525
 
                    InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
526
 
                    //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND );   // mask it
527
 
                    Inst( PPC_STWX, R_TOP, R_SECOND, R_MEMBASE );       // store from memory base
528
 
                    pc++;
529
 
                    instruction++;
530
 
                    rtopped = qfalse;
531
 
                    break;
532
 
                } else if (code[pc] == OP_STORE2) {
533
 
                    InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 ); // get value from opstack
534
 
                    InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
535
 
                    //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND );   // mask it
536
 
                    Inst( PPC_STHX, R_TOP, R_SECOND, R_MEMBASE );       // store from memory base
537
 
                    pc++;
538
 
                    instruction++;
539
 
                    rtopped = qfalse;
540
 
                    break;
541
 
                } else if (code[pc] == OP_STORE1) {
542
 
                    InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 ); // get value from opstack
543
 
                    InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
544
 
                    //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND );   // mask it
545
 
                    Inst( PPC_STBX, R_TOP, R_SECOND, R_MEMBASE );       // store from memory base
546
 
                    pc++;
547
 
                    instruction++;
548
 
                    rtopped = qfalse;
549
 
                    break;
550
 
                }
 
762
                opStackRegType[opStackDepth] = 1;
 
763
                opStackDepth += 1;
551
764
                if (code[pc] == OP_JUMP) {
552
765
                    jused[v] = 1;
553
766
                }
554
 
                InstImm( PPC_STWU, R_TOP, R_OPSTACK, 4 );
555
 
                rtopped = qtrue;
556
767
                break;
557
768
            case OP_LOCAL:
558
 
                oc0 = oc1;
559
769
                oc1 = Constant4();
 
770
                #if DEBUG_VM
 
771
                if(pass == 1)
 
772
                        printf("%08x LOCAL\t%08x\n",instruction,oc1);
 
773
                #endif
560
774
                if (code[pc] == OP_LOAD4 || code[pc] == OP_LOAD2 || code[pc] == OP_LOAD1) {
561
775
                    oc1 &= vm->dataMask;
562
776
                }
563
 
                InstImm( PPC_ADDI, R_TOP, R_STACK, oc1 );
564
 
                if (code[pc] == OP_LOAD4) {
565
 
                    Inst( PPC_LWZX, R_TOP, R_TOP, R_MEMBASE );          // load from memory base
566
 
                    pc++;
567
 
                    instruction++;
568
 
                } else if (code[pc] == OP_LOAD2) {
569
 
                    Inst( PPC_LHZX, R_TOP, R_TOP, R_MEMBASE );          // load from memory base
570
 
                    pc++;
571
 
                    instruction++;
572
 
                } else if (code[pc] == OP_LOAD1) {
573
 
                    Inst( PPC_LBZX, R_TOP, R_TOP, R_MEMBASE );          // load from memory base
574
 
                    pc++;
575
 
                    instruction++;
576
 
                }
577
 
                if (code[pc] == OP_STORE4) {
578
 
                    InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 );         // get value from opstack
579
 
                    InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
580
 
                    //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND );   // mask it
581
 
                    Inst( PPC_STWX, R_TOP, R_SECOND, R_MEMBASE );       // store from memory base
582
 
                    pc++;
583
 
                    instruction++;
584
 
                    rtopped = qfalse;
585
 
                    break;
586
 
                } else if (code[pc] == OP_STORE2) {
587
 
                    InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 );         // get value from opstack
588
 
                    InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
589
 
                    //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND );   // mask it
590
 
                    Inst( PPC_STHX, R_TOP, R_SECOND, R_MEMBASE );       // store from memory base
591
 
                    pc++;
592
 
                    instruction++;
593
 
                    rtopped = qfalse;
594
 
                    break;
595
 
                } else if (code[pc] == OP_STORE1) {
596
 
                    InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, 0 );         // get value from opstack
597
 
                    InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
598
 
                    //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND );   // mask it
599
 
                    Inst( PPC_STBX, R_TOP, R_SECOND, R_MEMBASE );       // store from memory base
600
 
                    pc++;
601
 
                    instruction++;
602
 
                    rtopped = qfalse;
603
 
                    break;
604
 
                }
605
 
                InstImm( PPC_STWU, R_TOP, R_OPSTACK, 4 );
606
 
                rtopped = qtrue;
 
777
                InstImm( "addi", PPC_ADDI, opStackIntRegisters[opStackDepth], R_STACK, oc1 );
 
778
                opStackRegType[opStackDepth] = 1;
 
779
                opStackLoadInstructionAddr[opStackDepth] = 0;
 
780
                opStackDepth += 1;
607
781
                break;
608
782
            case OP_ARG:
609
 
                ltop();                                                 // get value from opstack
610
 
                InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
611
 
                InstImm( PPC_ADDI, R_EA, R_STACK, Constant1() );        // location to put it
612
 
                Inst( PPC_STWX, R_TOP, R_EA, R_MEMBASE );
613
 
                rtopped = qfalse;
 
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
                
614
797
                break;
615
798
            case OP_CALL:
616
 
                Inst( PPC_MFSPR, R_SECOND, 8, 0 );                      // move from link register
617
 
                InstImm( PPC_STWU, R_SECOND, R_REAL_STACK, -16 );       // save off the old return address
618
 
 
619
 
                Inst( PPC_MTSPR, R_ASMCALL, 9, 0 );                     // move to count register
620
 
                Inst( PPC_BCCTR | 1, 20, 0, 0 );                        // jump and link to the count register
621
 
 
622
 
                InstImm( PPC_LWZ, R_SECOND, R_REAL_STACK, 0 );          // fetch the old return address
623
 
                InstImm( PPC_ADDI, R_REAL_STACK, R_REAL_STACK, 16 );
624
 
                Inst( PPC_MTSPR, R_SECOND, 8, 0 );                      // move to link register
625
 
                rtopped = qfalse;
 
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
626
829
                break;
627
830
            case OP_PUSH:
628
 
                InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, 4 );
629
 
                rtopped = qfalse;
 
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;
630
837
                break;
631
838
            case OP_POP:
632
 
                InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
633
 
                rtopped = qfalse;
 
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;
634
846
                break;
635
847
            case OP_LEAVE:
636
 
                InstImm( PPC_ADDI, R_STACK, R_STACK, Constant4() );     // add R_STACK, R_STACK, imm
637
 
                Inst( PPC_BCLR, 20, 0, 0 );                                                     // branch unconditionally to link register
638
 
                rtopped = qfalse;
 
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
639
875
                break;
640
876
            case OP_LOAD4:
641
 
                ltop();                                                 // get value from opstack
642
 
                //Inst( PPC_AND, R_MEMMASK, R_TOP, R_TOP );             // mask it
643
 
                Inst( PPC_LWZX, R_TOP, R_TOP, R_MEMBASE );              // load from memory base
644
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
645
 
                rtopped = qtrue;
 
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;
646
891
                break;
647
892
            case OP_LOAD2:
648
 
                ltop();                                                 // get value from opstack
649
 
                //Inst( PPC_AND, R_MEMMASK, R_TOP, R_TOP );             // mask it
650
 
                Inst( PPC_LHZX, R_TOP, R_TOP, R_MEMBASE );              // load from memory base
651
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
652
 
                rtopped = qtrue;
 
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;
653
901
                break;
654
902
            case OP_LOAD1:
655
 
                ltop();                                                 // get value from opstack
656
 
                //Inst( PPC_AND, R_MEMMASK, R_TOP, R_TOP );             // mask it
657
 
                Inst( PPC_LBZX, R_TOP, R_TOP, R_MEMBASE );              // load from memory base
658
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
659
 
                rtopped = qtrue;
 
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;
660
911
                break;
661
912
            case OP_STORE4:
662
 
                ltopandsecond();                                        // get value from opstack
663
 
                //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND );               // mask it
664
 
                Inst( PPC_STWX, R_TOP, R_SECOND, R_MEMBASE );           // store from memory base
665
 
                rtopped = qfalse;
 
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;
666
929
                break;
667
930
            case OP_STORE2:
668
 
                ltopandsecond();                                        // get value from opstack
669
 
                //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND );               // mask it
670
 
                Inst( PPC_STHX, R_TOP, R_SECOND, R_MEMBASE );           // store from memory base
671
 
                rtopped = qfalse;
 
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;
672
944
                break;
673
945
            case OP_STORE1:
674
 
                ltopandsecond();                                        // get value from opstack
675
 
                //Inst( PPC_AND, R_MEMMASK, R_SECOND, R_SECOND );               // mask it
676
 
                Inst( PPC_STBX, R_TOP, R_SECOND, R_MEMBASE );           // store from memory base
677
 
                rtopped = qfalse;
 
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;
678
959
                break;
679
960
 
680
961
            case OP_EQ:
681
 
                ltopandsecond();                                        // get value from opstack
682
 
                Inst( PPC_CMP, 0, R_SECOND, R_TOP );
 
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;
683
974
                i = Constant4();
684
975
                                jused[i] = 1;
685
 
                InstImm( PPC_BC, 4, 2, 8 );
 
976
                InstImm( "bc", PPC_BC, 4, 2, 8 );
686
977
                if ( pass==1 ) {
687
978
                    v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];                    
688
979
                } else {
689
980
                    v = 0;             
690
981
                }
691
 
                Emit4(PPC_B | (v&0x3ffffff) );
692
 
                                rtopped = qfalse;
 
982
                Emit4("b", PPC_B | (v&0x3ffffff) );
693
983
                break;
694
984
            case OP_NE:
695
 
                ltopandsecond();                                        // get value from opstack
696
 
                Inst( PPC_CMP, 0, R_SECOND, R_TOP );
 
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;
697
997
                i = Constant4();
698
998
                                jused[i] = 1;
699
 
                InstImm( PPC_BC, 12, 2, 8 );
 
999
                InstImm( "bc", PPC_BC, 12, 2, 8 );
700
1000
                if ( pass==1 ) {
701
1001
                    v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];                    
702
1002
                } else {
703
1003
                    v = 0;
704
1004
                }
705
 
                Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
706
 
//                InstImm( PPC_BC, 4, 2, v );
 
1005
                Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
 
1006
//                InstImm( "bc", PPC_BC, 4, 2, v );
707
1007
 
708
 
                                rtopped = qfalse;
709
1008
                break;
710
1009
            case OP_LTI:
711
 
                ltopandsecond();                                        // get value from opstack
712
 
                Inst( PPC_CMP, 0, R_SECOND, R_TOP );
 
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;
713
1022
                i = Constant4();
714
1023
                                jused[i] = 1;
715
 
                InstImm( PPC_BC, 4, 0, 8 );
 
1024
                InstImm( "bc", PPC_BC, 4, 0, 8 );
716
1025
                if ( pass==1 ) {
717
1026
                    v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
718
1027
                } else {
719
1028
                    v = 0;
720
1029
                }
721
 
                Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
722
 
//                InstImm( PPC_BC, 12, 0, v );
723
 
                                rtopped = qfalse;
 
1030
                Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
 
1031
//                InstImm( "bc", PPC_BC, 12, 0, v );
724
1032
                break;
725
1033
            case OP_LEI:
726
 
                ltopandsecond();                                        // get value from opstack
727
 
                Inst( PPC_CMP, 0, R_SECOND, R_TOP );
 
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;
728
1046
                i = Constant4();
729
1047
                                jused[i] = 1;
730
 
                InstImm( PPC_BC, 12, 1, 8 );
 
1048
                InstImm( "bc", PPC_BC, 12, 1, 8 );
731
1049
                if ( pass==1 ) {
732
1050
                    v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
733
1051
                } else {
734
1052
                    v = 0;
735
1053
                }
736
 
                Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
737
 
//                InstImm( PPC_BC, 4, 1, v );
738
 
                                rtopped = qfalse;
 
1054
                Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
 
1055
//                InstImm( "bc", PPC_BC, 4, 1, v );
739
1056
                break;
740
1057
            case OP_GTI:
741
 
                ltopandsecond();                // get value from opstack
742
 
                Inst( PPC_CMP, 0, R_SECOND, R_TOP );
 
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;
743
1070
                i = Constant4();
744
1071
                                jused[i] = 1;
745
 
                InstImm( PPC_BC, 4, 1, 8 );
 
1072
                InstImm( "bc", PPC_BC, 4, 1, 8 );
746
1073
                if ( pass==1 ) {
747
1074
                    v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
748
1075
                } else {
749
1076
                    v = 0;
750
1077
                }
751
 
                Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
752
 
//                InstImm( PPC_BC, 12, 1, v );
753
 
                                rtopped = qfalse;
 
1078
                Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
 
1079
//                InstImm( "bc", PPC_BC, 12, 1, v );
754
1080
                break;
755
1081
            case OP_GEI:
756
 
                ltopandsecond();                // get value from opstack
757
 
                Inst( PPC_CMP, 0, R_SECOND, R_TOP );
 
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;
758
1094
                i = Constant4();
759
1095
                                jused[i] = 1;
760
 
                InstImm( PPC_BC, 12, 0, 8 );
 
1096
                InstImm( "bc", PPC_BC, 12, 0, 8 );
761
1097
                if ( pass==1 ) {
762
1098
                    v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
763
1099
                } else {
764
1100
                    v = 0;
765
1101
                }
766
 
                Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
767
 
//                InstImm( PPC_BC, 4, 0, v );
768
 
                                rtopped = qfalse;
 
1102
                Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
 
1103
//                InstImm( "bc", PPC_BC, 4, 0, v );
769
1104
                break;
770
1105
            case OP_LTU:
771
 
                ltopandsecond();                // get value from opstack
772
 
                Inst( PPC_CMPL, 0, R_SECOND, R_TOP );
 
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;
773
1118
                i = Constant4();
774
1119
                jused[i] = 1;
775
 
                InstImm( PPC_BC, 4, 0, 8 );
 
1120
                InstImm( "bc", PPC_BC, 4, 0, 8 );
776
1121
                if ( pass==1 ) {
777
1122
                    v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
778
1123
                } else {
779
1124
                    v = 0;
780
1125
                }
781
 
                Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
782
 
//                InstImm( PPC_BC, 12, 0, v );
783
 
                rtopped = qfalse;
 
1126
                Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
 
1127
//                InstImm( "bc", PPC_BC, 12, 0, v );
784
1128
                break;
785
1129
            case OP_LEU:
786
 
                ltopandsecond();                // get value from opstack
787
 
                Inst( PPC_CMPL, 0, R_SECOND, R_TOP );
 
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;
788
1142
                i = Constant4();
789
1143
                jused[i] = 1;
790
 
                InstImm( PPC_BC, 12, 1, 8 );
 
1144
                InstImm( "bc", PPC_BC, 12, 1, 8 );
791
1145
                if ( pass==1 ) {
792
1146
                    v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
793
1147
                } else {
794
1148
                    v = 0;
795
1149
                }
796
 
                Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
797
 
//                InstImm( PPC_BC, 4, 1, v );
798
 
                rtopped = qfalse;
 
1150
                Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
 
1151
//                InstImm( "bc", PPC_BC, 4, 1, v );
799
1152
                break;
800
1153
            case OP_GTU:
801
 
                ltopandsecond();                // get value from opstack
802
 
                Inst( PPC_CMPL, 0, R_SECOND, R_TOP );
 
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;
803
1166
                i = Constant4();
804
1167
                jused[i] = 1;
805
 
                InstImm( PPC_BC, 4, 1, 8 );
 
1168
                InstImm( "bc", PPC_BC, 4, 1, 8 );
806
1169
                if ( pass==1 ) {
807
1170
                    v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
808
1171
                } else {
809
1172
                    v = 0;
810
1173
                }
811
 
                Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
812
 
//                InstImm( PPC_BC, 12, 1, v );
813
 
                rtopped = qfalse;
 
1174
                Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
 
1175
//                InstImm( "bc", PPC_BC, 12, 1, v );
814
1176
                break;
815
1177
            case OP_GEU:
816
 
                ltopandsecond();                // get value from opstack
817
 
                Inst( PPC_CMPL, 0, R_SECOND, R_TOP );
 
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;
818
1190
                i = Constant4();
819
1191
                jused[i] = 1;
820
 
                InstImm( PPC_BC, 12, 0, 8 );
 
1192
                InstImm( "bc", PPC_BC, 12, 0, 8 );
821
1193
                if ( pass==1 ) {
822
1194
                    v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
823
1195
                } else {
824
1196
                    v = 0;
825
1197
                }
826
 
                Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
827
 
//                InstImm( PPC_BC, 4, 0, v );
828
 
                rtopped = qfalse;
 
1198
                Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
 
1199
//                InstImm( "bc", PPC_BC, 4, 0, v );
829
1200
                break;
830
1201
                
831
1202
            case OP_EQF:
832
 
                fltopandsecond();               // get value from opstack
833
 
                Inst( PPC_FCMPU, 0, R_TOP, R_SECOND );
 
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;
834
1215
                i = Constant4();
835
1216
                jused[i] = 1;
836
 
                InstImm( PPC_BC, 4, 2, 8 );
 
1217
                InstImm( "bc", PPC_BC, 4, 2, 8 );
837
1218
                if ( pass==1 ) {
838
1219
                    v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
839
1220
                } else {
840
1221
                    v = 0;
841
1222
                }
842
 
                Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
843
 
//                InstImm( PPC_BC, 12, 2, v );
844
 
                rtopped = qfalse;
 
1223
                Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
 
1224
//                InstImm( "bc", PPC_BC, 12, 2, v );
845
1225
                break;                  
846
1226
            case OP_NEF:
847
 
                fltopandsecond();               // get value from opstack
848
 
                Inst( PPC_FCMPU, 0, R_TOP, R_SECOND );
 
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;
849
1239
                i = Constant4();
850
1240
                jused[i] = 1;
851
 
                InstImm( PPC_BC, 12, 2, 8 );
 
1241
                InstImm( "bc", PPC_BC, 12, 2, 8 );
852
1242
                if ( pass==1 ) {
853
1243
                    v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
854
1244
                } else {
855
1245
                    v = 0;
856
1246
                }
857
 
                Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
858
 
//                InstImm( PPC_BC, 4, 2, v );
859
 
                rtopped = qfalse;
 
1247
                Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
 
1248
//                InstImm( "bc", PPC_BC, 4, 2, v );
860
1249
                break;                  
861
1250
            case OP_LTF:
862
 
                fltopandsecond();               // get value from opstack
863
 
                Inst( PPC_FCMPU, 0, R_SECOND, R_TOP );
 
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;
864
1263
                i = Constant4();
865
1264
                jused[i] = 1;
866
 
                InstImm( PPC_BC, 4, 0, 8 );
 
1265
                InstImm( "bc", PPC_BC, 4, 0, 8 );
867
1266
                if ( pass==1 ) {
868
1267
                    v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
869
1268
                } else {
870
1269
                    v = 0;
871
1270
                }
872
 
                Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
873
 
//                InstImm( PPC_BC, 12, 0, v );
874
 
                rtopped = qfalse;
 
1271
                Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
 
1272
//                InstImm( "bc", PPC_BC, 12, 0, v );
875
1273
                break;                  
876
1274
            case OP_LEF:
877
 
                fltopandsecond();               // get value from opstack
878
 
                Inst( PPC_FCMPU, 0, R_SECOND, R_TOP );
 
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;
879
1287
                i = Constant4();
880
1288
                jused[i] = 1;
881
 
                InstImm( PPC_BC, 12, 1, 8 );
 
1289
                InstImm( "bc", PPC_BC, 12, 1, 8 );
882
1290
                if ( pass==1 ) {
883
1291
                    v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
884
1292
                } else {
885
1293
                    v = 0;
886
1294
                }
887
 
                Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
888
 
//                InstImm( PPC_BC, 4, 1, v );
889
 
                rtopped = qfalse;
 
1295
                Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
 
1296
//                InstImm( "bc", PPC_BC, 4, 1, v );
890
1297
                break;                  
891
1298
            case OP_GTF:
892
 
                fltopandsecond();               // get value from opstack
893
 
                Inst( PPC_FCMPU, 0, R_SECOND, R_TOP );
 
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;
894
1311
                i = Constant4();
895
1312
                jused[i] = 1;
896
 
                InstImm( PPC_BC, 4, 1, 8 );
 
1313
                InstImm( "bc", PPC_BC, 4, 1, 8 );
897
1314
                if ( pass==1 ) {
898
1315
                    v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
899
1316
                } else {
900
1317
                    v = 0;
901
1318
                }
902
 
                Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
903
 
//                InstImm( PPC_BC, 12, 1, v );
904
 
                rtopped = qfalse;
 
1319
                Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
 
1320
//                InstImm( "bc", PPC_BC, 12, 1, v );
905
1321
                break;                  
906
1322
            case OP_GEF:
907
 
                fltopandsecond();               // get value from opstack
908
 
                Inst( PPC_FCMPU, 0, R_SECOND, R_TOP );
 
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;
909
1335
                i = Constant4();
910
1336
                jused[i] = 1;
911
 
                InstImm( PPC_BC, 12, 0, 8 );
 
1337
                InstImm( "bc", PPC_BC, 12, 0, 8 );
912
1338
                if ( pass==1 ) {
913
1339
                    v = vm->instructionPointers[ i ] - (int)&buf[compiledOfs];
914
1340
                } else {
915
1341
                    v = 0;
916
1342
                }
917
 
                Emit4(PPC_B | (unsigned int)(v&0x3ffffff) );
918
 
//                InstImm( PPC_BC, 4, 0, v );
919
 
                rtopped = qfalse;
 
1343
                Emit4("b", PPC_B | (unsigned int)(v&0x3ffffff) );
 
1344
//                InstImm( "bc", PPC_BC, 4, 0, v );
920
1345
                break;
921
1346
 
922
1347
            case OP_NEGI:
923
 
                ltop();         // get value from opstack
924
 
                InstImm( PPC_SUBFIC, R_TOP, R_TOP, 0 );
925
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );                // save value to opstack
926
 
                rtopped = qtrue;
 
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;
927
1355
                break;
928
1356
            case OP_ADD:
929
 
                ltop();         // get value from opstack
930
 
                InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );           // get value from opstack
931
 
                Inst( PPC_ADD, R_TOP, R_TOP, R_SECOND );
932
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );                // save value to opstack
933
 
                rtopped = qtrue;
 
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;
934
1367
                break;
935
1368
            case OP_SUB:
936
 
                ltop();         // get value from opstack
937
 
                InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );           // get value from opstack
938
 
                Inst( PPC_SUBF, R_TOP, R_TOP, R_SECOND );
939
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );                // save value to opstack
940
 
                rtopped = qtrue;
 
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;
941
1379
                break;
942
1380
            case OP_DIVI:
943
 
                ltop();         // get value from opstack
944
 
                InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );           // get value from opstack
945
 
                Inst( PPC_DIVW, R_TOP, R_SECOND, R_TOP );
946
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );                // save value to opstack
947
 
                rtopped = qtrue;
 
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;
948
1391
                break;
949
1392
            case OP_DIVU:
950
 
                ltop();         // get value from opstack
951
 
                InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );           // get value from opstack
952
 
                Inst( PPC_DIVWU, R_TOP, R_SECOND, R_TOP );
953
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );                // save value to opstack
954
 
                rtopped = qtrue;
 
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;
955
1403
                break;
956
1404
            case OP_MODI:
957
 
                ltop();         // get value from opstack
958
 
                InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );           // get value from opstack
959
 
                Inst( PPC_DIVW, R_EA, R_SECOND, R_TOP );
960
 
                Inst( PPC_MULLW, R_EA, R_TOP, R_EA );
961
 
                Inst( PPC_SUBF, R_TOP, R_EA, R_SECOND );
962
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );                // save value to opstack
963
 
                rtopped = qtrue;
 
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;
964
1417
                break;
965
1418
            case OP_MODU:
966
 
                ltop();         // get value from opstack
967
 
                InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );           // get value from opstack
968
 
                Inst( PPC_DIVWU, R_EA, R_SECOND, R_TOP );
969
 
                Inst( PPC_MULLW, R_EA, R_TOP, R_EA );
970
 
                Inst( PPC_SUBF, R_TOP, R_EA, R_SECOND );
971
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );                // save value to opstack
972
 
                rtopped = qtrue;
 
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;
973
1431
                break;
974
1432
            case OP_MULI:
975
1433
            case OP_MULU:
976
 
                ltop();         // get value from opstack
977
 
                InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );           // get value from opstack
978
 
                Inst( PPC_MULLW, R_TOP, R_SECOND, R_TOP );
979
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );                // save value to opstack
980
 
                rtopped = qtrue;
 
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;
981
1444
                break;
982
1445
            case OP_BAND:
983
 
                ltop();         // get value from opstack
984
 
                InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );           // get value from opstack
985
 
                Inst( PPC_AND, R_SECOND, R_TOP, R_TOP );
986
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );                // save value to opstack
987
 
                rtopped = qtrue;
 
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;
988
1456
                break;
989
1457
            case OP_BOR:
990
 
                ltop();         // get value from opstack
991
 
                InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );           // get value from opstack
992
 
                Inst( PPC_OR, R_SECOND, R_TOP, R_TOP );
993
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );                // save value to opstack
994
 
                rtopped = qtrue;
 
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;
995
1468
                break;
996
1469
            case OP_BXOR:
997
 
                ltop();         // get value from opstack
998
 
                InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );           // get value from opstack
999
 
                Inst( PPC_XOR, R_SECOND, R_TOP, R_TOP );
1000
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );                // save value to opstack
1001
 
                rtopped = qtrue;
 
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;
1002
1480
                break;
1003
1481
            case OP_BCOM:
1004
 
                ltop();         // get value from opstack
1005
 
                Inst( PPC_NOR, R_TOP, R_TOP, R_TOP );
1006
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );                // save value to opstack
1007
 
                rtopped = qtrue;
 
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;
1008
1489
                break;
1009
1490
            case OP_LSH:
1010
 
                ltop();         // get value from opstack
1011
 
                InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );           // get value from opstack
1012
 
                Inst( PPC_SLW, R_SECOND, R_TOP, R_TOP );
1013
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );                // save value to opstack
1014
 
                rtopped = qtrue;
 
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;
1015
1501
                break;
1016
1502
            case OP_RSHI:
1017
 
                ltop();         // get value from opstack
1018
 
                InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );           // get value from opstack
1019
 
                Inst( PPC_SRAW, R_SECOND, R_TOP, R_TOP );
1020
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );                // save value to opstack
1021
 
                rtopped = qtrue;
 
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;
1022
1513
                break;
1023
1514
            case OP_RSHU:
1024
 
                ltop();         // get value from opstack
1025
 
                InstImm( PPC_LWZU, R_SECOND, R_OPSTACK, -4 );           // get value from opstack
1026
 
                Inst( PPC_SRW, R_SECOND, R_TOP, R_TOP );
1027
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );                // save value to opstack
1028
 
                rtopped = qtrue;
 
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;
1029
1525
                break;
1030
1526
 
1031
1527
            case OP_NEGF:
1032
 
                InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 );                // get value from opstack
1033
 
                Inst( PPC_FNEG, R_TOP, 0, R_TOP );
1034
 
                InstImm( PPC_STFS, R_TOP, R_OPSTACK, 0 );               // save value to opstack
1035
 
                rtopped = qfalse;
 
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;
1036
1535
                break;
1037
1536
            case OP_ADDF:
1038
 
                InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 );                // get value from opstack
1039
 
                InstImm( PPC_LFSU, R_SECOND, R_OPSTACK, -4 );           // get value from opstack
1040
 
                Inst( PPC_FADDS, R_TOP, R_SECOND, R_TOP );
1041
 
                InstImm( PPC_STFS, R_TOP, R_OPSTACK, 0 );               // save value to opstack
1042
 
                rtopped = qfalse;
 
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;
1043
1547
                break;
1044
1548
            case OP_SUBF:
1045
 
                InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 );                // get value from opstack
1046
 
                InstImm( PPC_LFSU, R_SECOND, R_OPSTACK, -4 );           // get value from opstack
1047
 
                Inst( PPC_FSUBS, R_TOP, R_SECOND, R_TOP );
1048
 
                InstImm( PPC_STFS, R_TOP, R_OPSTACK, 0 );               // save value to opstack
1049
 
                rtopped = qfalse;
 
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;
1050
1559
                break;
1051
1560
            case OP_DIVF:
1052
 
                InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 );                // get value from opstack
1053
 
                InstImm( PPC_LFSU, R_SECOND, R_OPSTACK, -4 );           // get value from opstack
1054
 
                Inst( PPC_FDIVS, R_TOP, R_SECOND, R_TOP );
1055
 
                InstImm( PPC_STFS, R_TOP, R_OPSTACK, 0 );               // save value to opstack
1056
 
                rtopped = qfalse;
 
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;
1057
1571
                break;
1058
1572
            case OP_MULF:
1059
 
                InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 );                // get value from opstack
1060
 
                InstImm( PPC_LFSU, R_SECOND, R_OPSTACK, -4 );           // get value from opstack
1061
 
                Inst4( PPC_FMULS, R_TOP, R_SECOND, 0, R_TOP );
1062
 
                InstImm( PPC_STFS, R_TOP, R_OPSTACK, 0 );               // save value to opstack
1063
 
                rtopped = qfalse;
 
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;
1064
1583
                break;
1065
1584
 
1066
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);
1067
1592
                v = (int)&itofConvert;
1068
 
                InstImmU( PPC_ADDIS, R_EA, 0, (v >> 16)&0xffff );
1069
 
                InstImmU( PPC_ORI, R_EA, R_EA, v & 0xffff );
1070
 
                InstImm( PPC_LWZ, R_TOP, R_OPSTACK, 0 );                // get value from opstack
1071
 
                InstImmU( PPC_XORIS, R_TOP, R_TOP, 0x8000 );
1072
 
                InstImm( PPC_STW, R_TOP, R_EA, 12 );
1073
 
                InstImm( PPC_LFD, R_TOP, R_EA, 0 );
1074
 
                InstImm( PPC_LFD, R_SECOND, R_EA, 8 );
1075
 
                Inst( PPC_FSUB, R_TOP, R_SECOND, R_TOP );
 
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;
1076
1605
    //            Inst( PPC_FRSP, R_TOP, 0, R_TOP );
1077
 
                InstImm( PPC_STFS, R_TOP, R_OPSTACK, 0 );               // save value to opstack
1078
 
                rtopped = qfalse;
1079
1606
                break;
1080
1607
            case OP_CVFI:
1081
 
                InstImm( PPC_LFS, R_TOP, R_OPSTACK, 0 );                // get value from opstack
1082
 
                Inst( PPC_FCTIWZ, R_TOP, 0, R_TOP );
1083
 
                Inst( PPC_STFIWX, R_TOP, 0, R_OPSTACK );                // save value to opstack
1084
 
                rtopped = qfalse;
 
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;
1085
1628
                break;
1086
1629
            case OP_SEX8:
1087
 
                ltop(); // get value from opstack
1088
 
                Inst( PPC_EXTSB, R_TOP, R_TOP, 0 );
1089
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
1090
 
                rtopped = qtrue;
 
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;
1091
1637
                break;
1092
1638
            case OP_SEX16:
1093
 
                ltop(); // get value from opstack
1094
 
                Inst( PPC_EXTSH, R_TOP, R_TOP, 0 );
1095
 
                InstImm( PPC_STW, R_TOP, R_OPSTACK, 0 );
1096
 
                rtopped = qtrue;
 
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;
1097
1646
                break;
1098
1647
 
1099
1648
            case OP_BLOCK_COPY:
1100
1649
                v = Constant4() >> 2;
1101
 
                ltop();         // source
1102
 
                InstImm( PPC_LWZ, R_SECOND, R_OPSTACK, -4 );    // dest
1103
 
                InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -8 );
1104
 
                InstImmU( PPC_ADDI, R_EA, 0, v );                               // count
 
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
1105
1658
                                // FIXME: range check
1106
 
                Inst( PPC_MTSPR, R_EA, 9, 0 );                                  // move to count register
1107
 
 
1108
 
                Inst( PPC_ADD, R_TOP, R_TOP, R_MEMBASE );
1109
 
                InstImm( PPC_ADDI, R_TOP, R_TOP, -4 );
1110
 
                Inst( PPC_ADD, R_SECOND, R_SECOND, R_MEMBASE );
1111
 
                InstImm( PPC_ADDI, R_SECOND, R_SECOND, -4 );
1112
 
 
1113
 
                InstImm( PPC_LWZU, R_EA, R_TOP, 4 );            // source
1114
 
                InstImm( PPC_STWU, R_EA, R_SECOND, 4 ); // dest
1115
 
                Inst( PPC_BC | 0xfff8 , 16, 0, 0 );                                     // loop
1116
 
                rtopped = qfalse;
 
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;
1117
1674
                break;
1118
1675
 
1119
1676
            case OP_JUMP:
1120
 
                ltop(); // get value from opstack
1121
 
                InstImm( PPC_ADDI, R_OPSTACK, R_OPSTACK, -4 );
1122
 
                Inst( PPC_RLWINM | ( 29 << 1 ), R_TOP, R_TOP, 2 );
 
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 );
1123
1685
                // FIXME: range check
1124
 
                Inst( PPC_LWZX, R_TOP, R_TOP, R_INSTRUCTIONS );
1125
 
                Inst( PPC_MTSPR, R_TOP, 9, 0 );         // move to count register
1126
 
                Inst( PPC_BCCTR, 20, 0, 0 );            // jump to the count register
1127
 
                rtopped = qfalse;
 
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;
1128
1692
                break;
1129
1693
            default:
1130
1694
                Com_Error( ERR_DROP, "VM_CompilePPC: bad opcode %i at instruction %i, offset %i", op, instruction, pc );
1131
1695
            }
1132
1696
            pop0 = pop1;
1133
1697
            pop1 = op;
 
1698
                assert(opStackDepth >= 0);
 
1699
                assert(opStackDepth < OP_STACK_MAX_DEPTH);
 
1700
                
 
1701
                //printf("%4d\t%s\n",opStackDepth,opnames[op]);
1134
1702
        }
1135
1703
 
1136
1704
        Com_Printf( "VM file %s pass %d compiled to %i bytes of code\n", vm->name, (pass+1), compiledOfs*4 );
1140
1708
            vm->codeLength = compiledOfs * 4;
1141
1709
            vm->codeBase = Hunk_Alloc( vm->codeLength, h_low );
1142
1710
            Com_Memcpy( vm->codeBase, buf, vm->codeLength );
 
1711
            
 
1712
            //printf("codeBase: %p\n",vm->codeBase);
 
1713
            
1143
1714
            Z_Free( buf );
1144
1715
        
1145
1716
            // offset all the instruction pointers for the new location
1146
1717
            for ( i = 0 ; i < header->instructionCount ; i++ ) {
1147
1718
                vm->instructionPointers[i] += (int)vm->codeBase;
 
1719
                //printf("%08x %08lx\n",i,vm->instructionPointers[i]);
1148
1720
            }
1149
1721
 
1150
1722
            // go back over it in place now to fixup reletive jump targets
1151
1723
            buf = (unsigned *)vm->codeBase;
1152
 
        }
 
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);
1153
1734
    }
1154
1735
    Z_Free( jused );
1155
1736
}
1169
1750
 
1170
1751
        currentVM = vm;
1171
1752
 
 
1753
        //printf("VM_CallCompiled: %p   %08lx %08lx %08lx\n",
 
1754
        //      vm, args[0],args[1],args[2]);
 
1755
                
1172
1756
        // interpret the code
1173
1757
        vm->currentlyInterpreting = qtrue;
1174
1758
 
1193
1777
        *(int *)&image[ programStack + 4 ] = 0; // return stack
1194
1778
        *(int *)&image[ programStack ] = -1;    // will terminate the loop on return
1195
1779
 
 
1780
        // Cheesy... manually save registers used by VM call...
1196
1781
        // off we go into generated code...
1197
1782
        // the PPC calling standard says the parms will all go into R3 - R11, so 
1198
1783
        // no special asm code is needed here
1245
1830
 
1246
1831
#if defined(MACOS_X) && defined(__OPTIMIZE__)
1247
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.
1248
 
#warning Mac OS X optimization on, not popping GCC AsmCall frame
 
1833
//#warning Mac OS X optimization on, not popping GCC AsmCall frame
1249
1834
#else
1250
1835
    // Mac OS X Server and unoptimized compiles include a GCC AsmCall frame
1251
1836
    asm (
1308
1893
    // save off the return value
1309
1894
"    stwu       r12,4(r4)               \n"     // RG_TOP, 0(RG_OPSTACK)
1310
1895
 
1311
 
        // GCC adds its own prolog / epilog code
 
1896
        // GCC adds its own prolog / epliog code
1312
1897
 );
1313
1898
}
1314
1899
#else