📄 vm_ppc.c
字号:
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// vm_ppc.c
// ppc dynamic compiler
#include "vm_local.h"
#pragma opt_pointer_analysis off
typedef enum {
R_REAL_STACK = 1,
// registers 3-11 are the parameter passing registers
// state
R_STACK = 3, // local
R_OPSTACK, // global
// constants
R_MEMBASE, // global
R_MEMMASK,
R_ASMCALL, // global
R_INSTRUCTIONS, // global
R_NUM_INSTRUCTIONS, // global
R_CVM, // currentVM
// temps
R_TOP = 11,
R_SECOND = 12,
R_EA = 2 // effective address calculation
} regNums_t;
#define RG_REAL_STACK r1
#define RG_STACK r3
#define RG_OPSTACK r4
#define RG_MEMBASE r5
#define RG_MEMMASK r6
#define RG_ASMCALL r7
#define RG_INSTRUCTIONS r8
#define RG_NUM_INSTRUCTIONS r9
#define RG_CVM r10
#define RG_TOP r12
#define RG_SECOND r13
#define RG_EA r14
// this doesn't have the low order bits set for instructions i'm not using...
typedef enum {
PPC_TDI = 0x08000000,
PPC_TWI = 0x0c000000,
PPC_MULLI = 0x1c000000,
PPC_SUBFIC = 0x20000000,
PPC_CMPI = 0x28000000,
PPC_CMPLI = 0x2c000000,
PPC_ADDIC = 0x30000000,
PPC_ADDIC_ = 0x34000000,
PPC_ADDI = 0x38000000,
PPC_ADDIS = 0x3c000000,
PPC_BC = 0x40000000,
PPC_SC = 0x44000000,
PPC_B = 0x48000000,
PPC_MCRF = 0x4c000000,
PPC_BCLR = 0x4c000020,
PPC_RFID = 0x4c000000,
PPC_CRNOR = 0x4c000000,
PPC_RFI = 0x4c000000,
PPC_CRANDC = 0x4c000000,
PPC_ISYNC = 0x4c000000,
PPC_CRXOR = 0x4c000000,
PPC_CRNAND = 0x4c000000,
PPC_CREQV = 0x4c000000,
PPC_CRORC = 0x4c000000,
PPC_CROR = 0x4c000000,
//------------
PPC_BCCTR = 0x4c000420,
PPC_RLWIMI = 0x50000000,
PPC_RLWINM = 0x54000000,
PPC_RLWNM = 0x5c000000,
PPC_ORI = 0x60000000,
PPC_ORIS = 0x64000000,
PPC_XORI = 0x68000000,
PPC_XORIS = 0x6c000000,
PPC_ANDI_ = 0x70000000,
PPC_ANDIS_ = 0x74000000,
PPC_RLDICL = 0x78000000,
PPC_RLDICR = 0x78000000,
PPC_RLDIC = 0x78000000,
PPC_RLDIMI = 0x78000000,
PPC_RLDCL = 0x78000000,
PPC_RLDCR = 0x78000000,
PPC_CMP = 0x7c000000,
PPC_TW = 0x7c000000,
PPC_SUBFC = 0x7c000010,
PPC_MULHDU = 0x7c000000,
PPC_ADDC = 0x7c000014,
PPC_MULHWU = 0x7c000000,
PPC_MFCR = 0x7c000000,
PPC_LWAR = 0x7c000000,
PPC_LDX = 0x7c000000,
PPC_LWZX = 0x7c00002e,
PPC_SLW = 0x7c000030,
PPC_CNTLZW = 0x7c000000,
PPC_SLD = 0x7c000000,
PPC_AND = 0x7c000038,
PPC_CMPL = 0x7c000040,
PPC_SUBF = 0x7c000050,
PPC_LDUX = 0x7c000000,
//------------
PPC_DCBST = 0x7c000000,
PPC_LWZUX = 0x7c00006c,
PPC_CNTLZD = 0x7c000000,
PPC_ANDC = 0x7c000000,
PPC_TD = 0x7c000000,
PPC_MULHD = 0x7c000000,
PPC_MULHW = 0x7c000000,
PPC_MTSRD = 0x7c000000,
PPC_MFMSR = 0x7c000000,
PPC_LDARX = 0x7c000000,
PPC_DCBF = 0x7c000000,
PPC_LBZX = 0x7c0000ae,
PPC_NEG = 0x7c000000,
PPC_MTSRDIN = 0x7c000000,
PPC_LBZUX = 0x7c000000,
PPC_NOR = 0x7c0000f8,
PPC_SUBFE = 0x7c000000,
PPC_ADDE = 0x7c000000,
PPC_MTCRF = 0x7c000000,
PPC_MTMSR = 0x7c000000,
PPC_STDX = 0x7c000000,
PPC_STWCX_ = 0x7c000000,
PPC_STWX = 0x7c00012e,
PPC_MTMSRD = 0x7c000000,
PPC_STDUX = 0x7c000000,
PPC_STWUX = 0x7c00016e,
PPC_SUBFZE = 0x7c000000,
PPC_ADDZE = 0x7c000000,
PPC_MTSR = 0x7c000000,
PPC_STDCX_ = 0x7c000000,
PPC_STBX = 0x7c0001ae,
PPC_SUBFME = 0x7c000000,
PPC_MULLD = 0x7c000000,
//------------
PPC_ADDME = 0x7c000000,
PPC_MULLW = 0x7c0001d6,
PPC_MTSRIN = 0x7c000000,
PPC_DCBTST = 0x7c000000,
PPC_STBUX = 0x7c000000,
PPC_ADD = 0x7c000214,
PPC_DCBT = 0x7c000000,
PPC_LHZX = 0x7c00022e,
PPC_EQV = 0x7c000000,
PPC_TLBIE = 0x7c000000,
PPC_ECIWX = 0x7c000000,
PPC_LHZUX = 0x7c000000,
PPC_XOR = 0x7c000278,
PPC_MFSPR = 0x7c0002a6,
PPC_LWAX = 0x7c000000,
PPC_LHAX = 0x7c000000,
PPC_TLBIA = 0x7c000000,
PPC_MFTB = 0x7c000000,
PPC_LWAUX = 0x7c000000,
PPC_LHAUX = 0x7c000000,
PPC_STHX = 0x7c00032e,
PPC_ORC = 0x7c000338,
PPC_SRADI = 0x7c000000,
PPC_SLBIE = 0x7c000000,
PPC_ECOWX = 0x7c000000,
PPC_STHUX = 0x7c000000,
PPC_OR = 0x7c000378,
PPC_DIVDU = 0x7c000000,
PPC_DIVWU = 0x7c000396,
PPC_MTSPR = 0x7c0003a6,
PPC_DCBI = 0x7c000000,
PPC_NAND = 0x7c000000,
PPC_DIVD = 0x7c000000,
//------------
PPC_DIVW = 0x7c0003d6,
PPC_SLBIA = 0x7c000000,
PPC_MCRXR = 0x7c000000,
PPC_LSWX = 0x7c000000,
PPC_LWBRX = 0x7c000000,
PPC_LFSX = 0x7c000000,
PPC_SRW = 0x7c000430,
PPC_SRD = 0x7c000000,
PPC_TLBSYNC = 0x7c000000,
PPC_LFSUX = 0x7c000000,
PPC_MFSR = 0x7c000000,
PPC_LSWI = 0x7c000000,
PPC_SYNC = 0x7c000000,
PPC_LFDX = 0x7c000000,
PPC_LFDUX = 0x7c000000,
PPC_MFSRIN = 0x7c000000,
PPC_STSWX = 0x7c000000,
PPC_STWBRX = 0x7c000000,
PPC_STFSX = 0x7c000000,
PPC_STFSUX = 0x7c000000,
PPC_STSWI = 0x7c000000,
PPC_STFDX = 0x7c000000,
PPC_DCBA = 0x7c000000,
PPC_STFDUX = 0x7c000000,
PPC_LHBRX = 0x7c000000,
PPC_SRAW = 0x7c000630,
PPC_SRAD = 0x7c000000,
PPC_SRAWI = 0x7c000000,
PPC_EIEIO = 0x7c000000,
PPC_STHBRX = 0x7c000000,
PPC_EXTSH = 0x7c000734,
PPC_EXTSB = 0x7c000774,
PPC_ICBI = 0x7c000000,
//------------
PPC_STFIWX = 0x7c0007ae,
PPC_EXTSW = 0x7c000000,
PPC_DCBZ = 0x7c000000,
PPC_LWZ = 0x80000000,
PPC_LWZU = 0x84000000,
PPC_LBZ = 0x88000000,
PPC_LBZU = 0x8c000000,
PPC_STW = 0x90000000,
PPC_STWU = 0x94000000,
PPC_STB = 0x98000000,
PPC_STBU = 0x9c000000,
PPC_LHZ = 0xa0000000,
PPC_LHZU = 0xa4000000,
PPC_LHA = 0xa8000000,
PPC_LHAU = 0xac000000,
PPC_STH = 0xb0000000,
PPC_STHU = 0xb4000000,
PPC_LMW = 0xb8000000,
PPC_STMW = 0xbc000000,
PPC_LFS = 0xc0000000,
PPC_LFSU = 0xc4000000,
PPC_LFD = 0xc8000000,
PPC_LFDU = 0xcc000000,
PPC_STFS = 0xd0000000,
PPC_STFSU = 0xd4000000,
PPC_STFD = 0xd8000000,
PPC_STFDU = 0xdc000000,
PPC_LD = 0xe8000000,
PPC_LDU = 0xe8000001,
PPC_LWA = 0xe8000002,
PPC_FDIVS = 0xec000024,
PPC_FSUBS = 0xec000028,
PPC_FADDS = 0xec00002a,
//------------
PPC_FSQRTS = 0xec000000,
PPC_FRES = 0xec000000,
PPC_FMULS = 0xec000032,
PPC_FMSUBS = 0xec000000,
PPC_FMADDS = 0xec000000,
PPC_FNMSUBS = 0xec000000,
PPC_FNMADDS = 0xec000000,
PPC_STD = 0xf8000000,
PPC_STDU = 0xf8000001,
PPC_FCMPU = 0xfc000000,
PPC_FRSP = 0xfc000018,
PPC_FCTIW = 0xfc000000,
PPC_FCTIWZ = 0xfc00001e,
PPC_FDIV = 0xfc000000,
PPC_FSUB = 0xfc000028,
PPC_FADD = 0xfc000000,
PPC_FSQRT = 0xfc000000,
PPC_FSEL = 0xfc000000,
PPC_FMUL = 0xfc000000,
PPC_FRSQRTE = 0xfc000000,
PPC_FMSUB = 0xfc000000,
PPC_FMADD = 0xfc000000,
PPC_FNMSUB = 0xfc000000,
PPC_FNMADD = 0xfc000000,
PPC_FCMPO = 0xfc000000,
PPC_MTFSB1 = 0xfc000000,
PPC_FNEG = 0xfc000050,
PPC_MCRFS = 0xfc000000,
PPC_MTFSB0 = 0xfc000000,
PPC_FMR = 0xfc000000,
PPC_MTFSFI = 0xfc000000,
PPC_FNABS = 0xfc000000,
PPC_FABS = 0xfc000000,
//------------
PPC_MFFS = 0xfc000000,
PPC_MTFSF = 0xfc000000,
PPC_FCTID = 0xfc000000,
PPC_FCTIDZ = 0xfc000000,
PPC_FCFID = 0xfc000000
} ppcOpcodes_t;
// the newly generated code
static unsigned *buf;
static int compiledOfs; // in dwords
// fromt the original bytecode
static byte *code;
static int pc;
void AsmCall( void );
double itofConvert[2];
static int Constant4( void ) {
int v;
v = code[pc] | (code[pc+1]<<8) | (code[pc+2]<<16) | (code[pc+3]<<24);
pc += 4;
return v;
}
static int Constant1( void ) {
int v;
v = code[pc];
pc += 1;
return v;
}
static void Emit4( int i ) {
buf[ compiledOfs ] = i;
compiledOfs++;
}
static void Inst( int opcode, int destReg, int aReg, int bReg ) {
unsigned r;
r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) ;
buf[ compiledOfs ] = r;
compiledOfs++;
}
static void Inst4( int opcode, int destReg, int aReg, int bReg, int cReg ) {
unsigned r;
r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( bReg << 11 ) | ( cReg << 6 );
buf[ compiledOfs ] = r;
compiledOfs++;
}
static void InstImm( int opcode, int destReg, int aReg, int immediate ) {
unsigned r;
if ( immediate > 32767 || immediate < -32768 ) {
Com_Error( ERR_FATAL, "VM_Compile: immediate value %i out of range, opcode %x,%d,%d", immediate, opcode, destReg, aReg );
}
r = opcode | ( destReg << 21 ) | ( aReg << 16 ) | ( immediate & 0xffff );
buf[ compiledOfs ] = r;
compiledOfs++;
}
static void InstImmU( int opcode, int destReg, int aReg, int immediate ) {
unsigned r;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -