forked from eden-emu/eden
		
	x64: Refactor to remove fake interfaces and general cleanups.
This commit is contained in:
		
							parent
							
								
									fe33a705de
								
							
						
					
					
						commit
						f9e3228caa
					
				
					 16 changed files with 52 additions and 666 deletions
				
			
		|  | @ -2,8 +2,8 @@ | ||||||
| configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in" "${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp" @ONLY) | configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in" "${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp" @ONLY) | ||||||
| 
 | 
 | ||||||
| set(SRCS | set(SRCS | ||||||
|             abi.cpp |  | ||||||
|             break_points.cpp |             break_points.cpp | ||||||
|  |             cpu_detect.cpp | ||||||
|             emu_window.cpp |             emu_window.cpp | ||||||
|             file_util.cpp |             file_util.cpp | ||||||
|             hash.cpp |             hash.cpp | ||||||
|  | @ -22,7 +22,6 @@ set(SRCS | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
| set(HEADERS | set(HEADERS | ||||||
|             abi.h |  | ||||||
|             assert.h |             assert.h | ||||||
|             bit_field.h |             bit_field.h | ||||||
|             break_points.h |             break_points.h | ||||||
|  | @ -61,19 +60,14 @@ set(HEADERS | ||||||
|             vector_math.h |             vector_math.h | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
| if(_M_X86_64) | if(ARCHITECTURE_X64) | ||||||
|     set(SRCS ${SRCS} |     set(SRCS ${SRCS} | ||||||
|             cpu_detect_x86.cpp |             x64/abi.cpp | ||||||
|             x64_emitter.cpp) |             x64/emitter.cpp) | ||||||
| 
 | 
 | ||||||
|     set(HEADERS ${HEADERS} |     set(HEADERS ${HEADERS} | ||||||
|             x64_emitter.h) |             x64/abi.h | ||||||
| else() |             x64/emitter.h) | ||||||
|     set(SRCS ${SRCS} |  | ||||||
|             cpu_detect_generic.cpp) |  | ||||||
| 
 |  | ||||||
|     set(HEADERS ${HEADERS} |  | ||||||
|             fake_emitter.h) |  | ||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
| create_directory_groups(${SRCS} ${HEADERS}) | create_directory_groups(${SRCS} ${HEADERS}) | ||||||
|  |  | ||||||
|  | @ -35,7 +35,7 @@ | ||||||
| 
 | 
 | ||||||
| #ifndef _MSC_VER | #ifndef _MSC_VER | ||||||
| 
 | 
 | ||||||
| #if defined(__x86_64__) || defined(_M_X86_64) | #if defined(__x86_64__) || defined(ARCHITECTURE_X64) | ||||||
| #define Crash() __asm__ __volatile__("int $3") | #define Crash() __asm__ __volatile__("int $3") | ||||||
| #elif defined(_M_ARM) | #elif defined(_M_ARM) | ||||||
| #define Crash() __asm__ __volatile__("trap") | #define Crash() __asm__ __volatile__("trap") | ||||||
|  |  | ||||||
|  | @ -62,7 +62,7 @@ CPUInfo::CPUInfo() { | ||||||
| // Detects the various CPU features
 | // Detects the various CPU features
 | ||||||
| void CPUInfo::Detect() { | void CPUInfo::Detect() { | ||||||
|     memset(this, 0, sizeof(*this)); |     memset(this, 0, sizeof(*this)); | ||||||
| #ifdef _M_X86_64 | #ifdef ARCHITECTURE_X64 | ||||||
|     Mode64bit = true; |     Mode64bit = true; | ||||||
|     OS64bit = true; |     OS64bit = true; | ||||||
| #endif | #endif | ||||||
|  | @ -1,19 +0,0 @@ | ||||||
| // Copyright 2014 Dolphin Emulator Project
 |  | ||||||
| // Licensed under GPLv2+
 |  | ||||||
| // Refer to the license.txt file included.
 |  | ||||||
| 
 |  | ||||||
| #include "cpu_detect.h" |  | ||||||
| #include "hash.h" |  | ||||||
| 
 |  | ||||||
| namespace Common { |  | ||||||
| 
 |  | ||||||
| CPUInfo cpu_info; |  | ||||||
| 
 |  | ||||||
| CPUInfo::CPUInfo() { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| std::string CPUInfo::Summarize() { |  | ||||||
|     return "Generic"; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } // namespace Common
 |  | ||||||
|  | @ -1,465 +0,0 @@ | ||||||
| // Copyright (C) 2003 Dolphin Project.
 |  | ||||||
| 
 |  | ||||||
| // This program 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, version 2.0.
 |  | ||||||
| 
 |  | ||||||
| // This program 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 2.0 for more details.
 |  | ||||||
| 
 |  | ||||||
| // A copy of the GPL 2.0 should have been included with the program.
 |  | ||||||
| // If not, see http://www.gnu.org/licenses/
 |  | ||||||
| 
 |  | ||||||
| // Official SVN repository and contact information can be found at
 |  | ||||||
| // http://code.google.com/p/dolphin-emu/
 |  | ||||||
| 
 |  | ||||||
| // WARNING - THIS LIBRARY IS NOT THREAD SAFE!!!
 |  | ||||||
| 
 |  | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <vector> |  | ||||||
| #include <stdint.h> |  | ||||||
| 
 |  | ||||||
| #include "assert.h" |  | ||||||
| #include "common_types.h" |  | ||||||
| 
 |  | ||||||
| // TODO: Check if Pandora still needs signal.h/kill here. Symbian doesn't.
 |  | ||||||
| 
 |  | ||||||
| // VCVT flags
 |  | ||||||
| #define TO_FLOAT      0 |  | ||||||
| #define TO_INT        1 << 0 |  | ||||||
| #define IS_SIGNED     1 << 1 |  | ||||||
| #define ROUND_TO_ZERO 1 << 2 |  | ||||||
| 
 |  | ||||||
| namespace FakeGen |  | ||||||
| { |  | ||||||
| enum FakeReg |  | ||||||
| { |  | ||||||
|     // GPRs
 |  | ||||||
|     R0 = 0, R1, R2, R3, R4, R5, |  | ||||||
|     R6, R7, R8, R9, R10, R11, |  | ||||||
| 
 |  | ||||||
|     // SPRs
 |  | ||||||
|     // R13 - R15 are SP, LR, and PC.
 |  | ||||||
|     // Almost always referred to by name instead of register number
 |  | ||||||
|     R12 = 12, R13 = 13, R14 = 14, R15 = 15, |  | ||||||
|     R_IP = 12, R_SP = 13, R_LR = 14, R_PC = 15, |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     // VFP single precision registers
 |  | ||||||
|     S0, S1, S2, S3, S4, S5, S6, |  | ||||||
|     S7, S8, S9, S10, S11, S12, S13, |  | ||||||
|     S14, S15, S16, S17, S18, S19, S20, |  | ||||||
|     S21, S22, S23, S24, S25, S26, S27, |  | ||||||
|     S28, S29, S30, S31, |  | ||||||
| 
 |  | ||||||
|     // VFP Double Precision registers
 |  | ||||||
|     D0, D1, D2, D3, D4, D5, D6, D7, |  | ||||||
|     D8, D9, D10, D11, D12, D13, D14, D15, |  | ||||||
|     D16, D17, D18, D19, D20, D21, D22, D23, |  | ||||||
|     D24, D25, D26, D27, D28, D29, D30, D31, |  | ||||||
| 
 |  | ||||||
|     // ASIMD Quad-Word registers
 |  | ||||||
|     Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, |  | ||||||
|     Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15, |  | ||||||
| 
 |  | ||||||
|     // for NEON VLD/VST instructions
 |  | ||||||
|     REG_UPDATE = R13, |  | ||||||
|     INVALID_REG = 0xFFFFFFFF |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| enum CCFlags |  | ||||||
| { |  | ||||||
|     CC_EQ = 0, // Equal
 |  | ||||||
|     CC_NEQ, // Not equal
 |  | ||||||
|     CC_CS, // Carry Set
 |  | ||||||
|     CC_CC, // Carry Clear
 |  | ||||||
|     CC_MI, // Minus (Negative)
 |  | ||||||
|     CC_PL, // Plus
 |  | ||||||
|     CC_VS, // Overflow
 |  | ||||||
|     CC_VC, // No Overflow
 |  | ||||||
|     CC_HI, // Unsigned higher
 |  | ||||||
|     CC_LS, // Unsigned lower or same
 |  | ||||||
|     CC_GE, // Signed greater than or equal
 |  | ||||||
|     CC_LT, // Signed less than
 |  | ||||||
|     CC_GT, // Signed greater than
 |  | ||||||
|     CC_LE, // Signed less than or equal
 |  | ||||||
|     CC_AL, // Always (unconditional) 14
 |  | ||||||
|     CC_HS = CC_CS, // Alias of CC_CS  Unsigned higher or same
 |  | ||||||
|     CC_LO = CC_CC, // Alias of CC_CC  Unsigned lower
 |  | ||||||
| }; |  | ||||||
| const u32 NO_COND = 0xE0000000; |  | ||||||
| 
 |  | ||||||
| enum ShiftType |  | ||||||
| { |  | ||||||
|     ST_LSL = 0, |  | ||||||
|     ST_ASL = 0, |  | ||||||
|     ST_LSR = 1, |  | ||||||
|     ST_ASR = 2, |  | ||||||
|     ST_ROR = 3, |  | ||||||
|     ST_RRX = 4 |  | ||||||
| }; |  | ||||||
| enum IntegerSize |  | ||||||
| { |  | ||||||
|     I_I8 = 0, |  | ||||||
|     I_I16, |  | ||||||
|     I_I32, |  | ||||||
|     I_I64 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| enum |  | ||||||
| { |  | ||||||
|     NUMGPRs = 13, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| class FakeXEmitter; |  | ||||||
| 
 |  | ||||||
| enum OpType |  | ||||||
| { |  | ||||||
|     TYPE_IMM = 0, |  | ||||||
|     TYPE_REG, |  | ||||||
|     TYPE_IMMSREG, |  | ||||||
|     TYPE_RSR, |  | ||||||
|     TYPE_MEM |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // This is no longer a proper operand2 class. Need to split up.
 |  | ||||||
| class Operand2 |  | ||||||
| { |  | ||||||
|     friend class FakeXEmitter; |  | ||||||
| protected: |  | ||||||
|     u32 Value; |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     OpType Type; |  | ||||||
| 
 |  | ||||||
|     // IMM types
 |  | ||||||
|     u8    Rotation; // Only for u8 values
 |  | ||||||
| 
 |  | ||||||
|     // Register types
 |  | ||||||
|     u8 IndexOrShift; |  | ||||||
|     ShiftType Shift; |  | ||||||
| public: |  | ||||||
|     OpType GetType() |  | ||||||
|     { |  | ||||||
|         return Type; |  | ||||||
|     } |  | ||||||
|     Operand2() {} |  | ||||||
|     Operand2(u32 imm, OpType type = TYPE_IMM) |  | ||||||
|     { |  | ||||||
|         Type = type; |  | ||||||
|         Value = imm; |  | ||||||
|         Rotation = 0; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     Operand2(FakeReg Reg) |  | ||||||
|     { |  | ||||||
|         Type = TYPE_REG; |  | ||||||
|         Value = Reg; |  | ||||||
|         Rotation = 0; |  | ||||||
|     } |  | ||||||
|     Operand2(u8 imm, u8 rotation) |  | ||||||
|     { |  | ||||||
|         Type = TYPE_IMM; |  | ||||||
|         Value = imm; |  | ||||||
|         Rotation = rotation; |  | ||||||
|     } |  | ||||||
|     Operand2(FakeReg base, ShiftType type, FakeReg shift) // RSR
 |  | ||||||
|     { |  | ||||||
|         Type = TYPE_RSR; |  | ||||||
|         ASSERT_MSG(type != ST_RRX, "Invalid Operand2: RRX does not take a register shift amount"); |  | ||||||
|         IndexOrShift = shift; |  | ||||||
|         Shift = type; |  | ||||||
|         Value = base; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     Operand2(FakeReg base, ShiftType type, u8 shift)// For IMM shifted register
 |  | ||||||
|     { |  | ||||||
|         if(shift == 32) shift = 0; |  | ||||||
|         switch (type) |  | ||||||
|         { |  | ||||||
|         case ST_LSL: |  | ||||||
|             ASSERT_MSG(shift < 32, "Invalid Operand2: LSL %u", shift); |  | ||||||
|             break; |  | ||||||
|         case ST_LSR: |  | ||||||
|             ASSERT_MSG(shift <= 32, "Invalid Operand2: LSR %u", shift); |  | ||||||
|             if (!shift) |  | ||||||
|                 type = ST_LSL; |  | ||||||
|             if (shift == 32) |  | ||||||
|                 shift = 0; |  | ||||||
|             break; |  | ||||||
|         case ST_ASR: |  | ||||||
|             ASSERT_MSG(shift < 32, "Invalid Operand2: ASR %u", shift); |  | ||||||
|             if (!shift) |  | ||||||
|                 type = ST_LSL; |  | ||||||
|             if (shift == 32) |  | ||||||
|                 shift = 0; |  | ||||||
|             break; |  | ||||||
|         case ST_ROR: |  | ||||||
|             ASSERT_MSG(shift < 32, "Invalid Operand2: ROR %u", shift); |  | ||||||
|             if (!shift) |  | ||||||
|                 type = ST_LSL; |  | ||||||
|             break; |  | ||||||
|         case ST_RRX: |  | ||||||
|             ASSERT_MSG(shift == 0, "Invalid Operand2: RRX does not take an immediate shift amount"); |  | ||||||
|             type = ST_ROR; |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|         IndexOrShift = shift; |  | ||||||
|         Shift = type; |  | ||||||
|         Value = base; |  | ||||||
|         Type = TYPE_IMMSREG; |  | ||||||
|     } |  | ||||||
|     u32 GetData() |  | ||||||
|     { |  | ||||||
|         switch(Type) |  | ||||||
|         { |  | ||||||
|         case TYPE_IMM: |  | ||||||
|             return Imm12Mod(); // This'll need to be changed later
 |  | ||||||
|         case TYPE_REG: |  | ||||||
|             return Rm(); |  | ||||||
|         case TYPE_IMMSREG: |  | ||||||
|             return IMMSR(); |  | ||||||
|         case TYPE_RSR: |  | ||||||
|             return RSR(); |  | ||||||
|         default: |  | ||||||
|             ASSERT_MSG(false, "GetData with Invalid Type"); |  | ||||||
|             return 0; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     u32 IMMSR() // IMM shifted register
 |  | ||||||
|     { |  | ||||||
|         ASSERT_MSG(Type == TYPE_IMMSREG, "IMMSR must be imm shifted register"); |  | ||||||
|         return ((IndexOrShift & 0x1f) << 7 | (Shift << 5) | Value); |  | ||||||
|     } |  | ||||||
|     u32 RSR() // Register shifted register
 |  | ||||||
|     { |  | ||||||
|         ASSERT_MSG(Type == TYPE_RSR, "RSR must be RSR Of Course"); |  | ||||||
|         return (IndexOrShift << 8) | (Shift << 5) | 0x10 | Value; |  | ||||||
|     } |  | ||||||
|     u32 Rm() |  | ||||||
|     { |  | ||||||
|         ASSERT_MSG(Type == TYPE_REG, "Rm must be with Reg"); |  | ||||||
|         return Value; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     u32 Imm5() |  | ||||||
|     { |  | ||||||
|         ASSERT_MSG((Type == TYPE_IMM), "Imm5 not IMM value"); |  | ||||||
|         return ((Value & 0x0000001F) << 7); |  | ||||||
|     } |  | ||||||
|     u32 Imm8() |  | ||||||
|     { |  | ||||||
|         ASSERT_MSG((Type == TYPE_IMM), "Imm8Rot not IMM value"); |  | ||||||
|         return Value & 0xFF; |  | ||||||
|     } |  | ||||||
|     u32 Imm8Rot() // IMM8 with Rotation
 |  | ||||||
|     { |  | ||||||
|         ASSERT_MSG((Type == TYPE_IMM), "Imm8Rot not IMM value"); |  | ||||||
|         ASSERT_MSG((Rotation & 0xE1) != 0, "Invalid Operand2: immediate rotation %u", Rotation); |  | ||||||
|         return (1 << 25) | (Rotation << 7) | (Value & 0x000000FF); |  | ||||||
|     } |  | ||||||
|     u32 Imm12() |  | ||||||
|     { |  | ||||||
|         ASSERT_MSG((Type == TYPE_IMM), "Imm12 not IMM"); |  | ||||||
|         return (Value & 0x00000FFF); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     u32 Imm12Mod() |  | ||||||
|     { |  | ||||||
|         // This is an IMM12 with the top four bits being rotation and the
 |  | ||||||
|         // bottom eight being an IMM. This is for instructions that need to
 |  | ||||||
|         // expand a 8bit IMM to a 32bit value and gives you some rotation as
 |  | ||||||
|         // well.
 |  | ||||||
|         // Each rotation rotates to the right by 2 bits
 |  | ||||||
|         ASSERT_MSG((Type == TYPE_IMM), "Imm12Mod not IMM"); |  | ||||||
|         return ((Rotation & 0xF) << 8) | (Value & 0xFF); |  | ||||||
|     } |  | ||||||
|     u32 Imm16() |  | ||||||
|     { |  | ||||||
|         ASSERT_MSG((Type == TYPE_IMM), "Imm16 not IMM"); |  | ||||||
|         return ( (Value & 0xF000) << 4) | (Value & 0x0FFF); |  | ||||||
|     } |  | ||||||
|     u32 Imm16Low() |  | ||||||
|     { |  | ||||||
|         return Imm16(); |  | ||||||
|     } |  | ||||||
|     u32 Imm16High() // Returns high 16bits
 |  | ||||||
|     { |  | ||||||
|         ASSERT_MSG((Type == TYPE_IMM), "Imm16 not IMM"); |  | ||||||
|         return ( ((Value >> 16) & 0xF000) << 4) | ((Value >> 16) & 0x0FFF); |  | ||||||
|     } |  | ||||||
|     u32 Imm24() |  | ||||||
|     { |  | ||||||
|         ASSERT_MSG((Type == TYPE_IMM), "Imm16 not IMM"); |  | ||||||
|         return (Value & 0x0FFFFFFF); |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // Use these when you don't know if an imm can be represented as an operand2.
 |  | ||||||
| // This lets you generate both an optimal and a fallback solution by checking
 |  | ||||||
| // the return value, which will be false if these fail to find a Operand2 that
 |  | ||||||
| // represents your 32-bit imm value.
 |  | ||||||
| bool TryMakeOperand2(u32 imm, Operand2 &op2); |  | ||||||
| bool TryMakeOperand2_AllowInverse(u32 imm, Operand2 &op2, bool *inverse); |  | ||||||
| bool TryMakeOperand2_AllowNegation(s32 imm, Operand2 &op2, bool *negated); |  | ||||||
| 
 |  | ||||||
| // Use this only when you know imm can be made into an Operand2.
 |  | ||||||
| Operand2 AssumeMakeOperand2(u32 imm); |  | ||||||
| 
 |  | ||||||
| inline Operand2 R(FakeReg Reg)    { return Operand2(Reg, TYPE_REG); } |  | ||||||
| inline Operand2 IMM(u32 Imm)    { return Operand2(Imm, TYPE_IMM); } |  | ||||||
| inline Operand2 Mem(void *ptr)    { return Operand2((u32)(uintptr_t)ptr, TYPE_IMM); } |  | ||||||
| //usage: struct {int e;} s; STRUCT_OFFSET(s,e)
 |  | ||||||
| #define STRUCT_OFF(str,elem) ((u32)((u32)&(str).elem-(u32)&(str))) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| struct FixupBranch |  | ||||||
| { |  | ||||||
|     u8 *ptr; |  | ||||||
|     u32 condition; // Remembers our codition at the time
 |  | ||||||
|     int type; //0 = B 1 = BL
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| typedef const u8* JumpTarget; |  | ||||||
| 
 |  | ||||||
| // XXX: Stop polluting the global namespace
 |  | ||||||
| const u32 I_8 = (1 << 0); |  | ||||||
| const u32 I_16 = (1 << 1); |  | ||||||
| const u32 I_32 = (1 << 2); |  | ||||||
| const u32 I_64 = (1 << 3); |  | ||||||
| const u32 I_SIGNED = (1 << 4); |  | ||||||
| const u32 I_UNSIGNED = (1 << 5); |  | ||||||
| const u32 F_32 = (1 << 6); |  | ||||||
| const u32 I_POLYNOMIAL = (1 << 7); // Only used in VMUL/VMULL
 |  | ||||||
| 
 |  | ||||||
| u32 EncodeVd(FakeReg Vd); |  | ||||||
| u32 EncodeVn(FakeReg Vn); |  | ||||||
| u32 EncodeVm(FakeReg Vm); |  | ||||||
| 
 |  | ||||||
| u32 encodedSize(u32 value); |  | ||||||
| 
 |  | ||||||
| // Subtracts the base from the register to give us the real one
 |  | ||||||
| FakeReg SubBase(FakeReg Reg); |  | ||||||
| 
 |  | ||||||
| // See A.7.1 in the Fakev7-A
 |  | ||||||
| // VMUL F32 scalars can only be up to D15[0], D15[1] - higher scalars cannot be individually addressed
 |  | ||||||
| FakeReg DScalar(FakeReg dreg, int subScalar); |  | ||||||
| FakeReg QScalar(FakeReg qreg, int subScalar); |  | ||||||
| 
 |  | ||||||
| enum NEONAlignment { |  | ||||||
|     ALIGN_NONE = 0, |  | ||||||
|     ALIGN_64 = 1, |  | ||||||
|     ALIGN_128 = 2, |  | ||||||
|     ALIGN_256 = 3 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class NEONXEmitter; |  | ||||||
| 
 |  | ||||||
| class FakeXEmitter |  | ||||||
| { |  | ||||||
|     friend struct OpArg;  // for Write8 etc
 |  | ||||||
| private: |  | ||||||
|     u8 *code, *startcode; |  | ||||||
|     u8 *lastCacheFlushEnd; |  | ||||||
|     u32 condition; |  | ||||||
| 
 |  | ||||||
| protected: |  | ||||||
|     inline void Write32(u32 value) {*(u32*)code = value; code+=4;} |  | ||||||
| 
 |  | ||||||
| public: |  | ||||||
|     FakeXEmitter() : code(0), startcode(0), lastCacheFlushEnd(0) { |  | ||||||
|         condition = CC_AL << 28; |  | ||||||
|     } |  | ||||||
|     FakeXEmitter(u8 *code_ptr) { |  | ||||||
|         code = code_ptr; |  | ||||||
|         lastCacheFlushEnd = code_ptr; |  | ||||||
|         startcode = code_ptr; |  | ||||||
|         condition = CC_AL << 28; |  | ||||||
|     } |  | ||||||
|     virtual ~FakeXEmitter() {} |  | ||||||
| 
 |  | ||||||
|     void SetCodePtr(u8 *ptr) {} |  | ||||||
|     void ReserveCodeSpace(u32 bytes) {} |  | ||||||
|     const u8 *AlignCode16() { return nullptr; } |  | ||||||
|     const u8 *AlignCodePage() { return nullptr; } |  | ||||||
|     const u8 *GetCodePtr() const { return nullptr; } |  | ||||||
|     void FlushIcache() {} |  | ||||||
|     void FlushIcacheSection(u8 *start, u8 *end) {} |  | ||||||
|     u8 *GetWritableCodePtr() { return nullptr; } |  | ||||||
| 
 |  | ||||||
|     CCFlags GetCC() { return CCFlags(condition >> 28); } |  | ||||||
|     void SetCC(CCFlags cond = CC_AL) {} |  | ||||||
| 
 |  | ||||||
|     // Special purpose instructions
 |  | ||||||
| 
 |  | ||||||
|     // Do nothing
 |  | ||||||
|     void NOP(int count = 1) {} //nop padding - TODO: fast nop slides, for amd and intel (check their manuals)
 |  | ||||||
| 
 |  | ||||||
| #ifdef CALL |  | ||||||
| #undef CALL |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|     void QuickCallFunction(FakeReg scratchreg, const void *func); |  | ||||||
|     template <typename T> void QuickCallFunction(FakeReg scratchreg, T func) { |  | ||||||
|         QuickCallFunction(scratchreg, (const void *)func); |  | ||||||
|     } |  | ||||||
| };  // class FakeXEmitter
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| // Everything that needs to generate machine code should inherit from this.
 |  | ||||||
| // You get memory management for free, plus, you can use all the MOV etc functions without
 |  | ||||||
| // having to prefix them with gen-> or something similar.
 |  | ||||||
| class FakeXCodeBlock : public FakeXEmitter |  | ||||||
| { |  | ||||||
| protected: |  | ||||||
|     u8 *region; |  | ||||||
|     size_t region_size; |  | ||||||
| 
 |  | ||||||
| public: |  | ||||||
|     FakeXCodeBlock() : region(NULL), region_size(0) {} |  | ||||||
|     virtual ~FakeXCodeBlock() { if (region) FreeCodeSpace(); } |  | ||||||
| 
 |  | ||||||
|     // Call this before you generate any code.
 |  | ||||||
|     void AllocCodeSpace(int size) { } |  | ||||||
| 
 |  | ||||||
|     // Always clear code space with breakpoints, so that if someone accidentally executes
 |  | ||||||
|     // uninitialized, it just breaks into the debugger.
 |  | ||||||
|     void ClearCodeSpace() { } |  | ||||||
| 
 |  | ||||||
|     // Call this when shutting down. Don't rely on the destructor, even though it'll do the job.
 |  | ||||||
|     void FreeCodeSpace() { } |  | ||||||
| 
 |  | ||||||
|     bool IsInSpace(const u8 *ptr) const |  | ||||||
|     { |  | ||||||
|         return ptr >= region && ptr < region + region_size; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Cannot currently be undone. Will write protect the entire code region.
 |  | ||||||
|     // Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()).
 |  | ||||||
|     void WriteProtect() { } |  | ||||||
|     void UnWriteProtect() { } |  | ||||||
| 
 |  | ||||||
|     void ResetCodePtr() |  | ||||||
|     { |  | ||||||
|         SetCodePtr(region); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     size_t GetSpaceLeft() const |  | ||||||
|     { |  | ||||||
|         return region_size - (GetCodePtr() - region); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     u8 *GetBasePtr() { |  | ||||||
|         return region; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     size_t GetOffset(const u8 *ptr) const { |  | ||||||
|         return ptr - region; |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| }  // namespace
 |  | ||||||
|  | @ -27,7 +27,7 @@ | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // Platform detection
 | // Platform detection
 | ||||||
| 
 | 
 | ||||||
| #if defined(__x86_64__) || defined(_M_X86_64) || defined(__aarch64__) | #if defined(__x86_64__) || defined(ARCHITECTURE_X64) || defined(__aarch64__) | ||||||
|     #define EMU_ARCH_BITS 64 |     #define EMU_ARCH_BITS 64 | ||||||
| #elif defined(__i386) || defined(_M_IX86) || defined(__arm__) || defined(_M_ARM) | #elif defined(__i386) || defined(_M_IX86) || defined(__arm__) || defined(_M_ARM) | ||||||
|     #define EMU_ARCH_BITS 32 |     #define EMU_ARCH_BITS 32 | ||||||
|  |  | ||||||
|  | @ -15,8 +15,8 @@ | ||||||
| // Official SVN repository and contact information can be found at
 | // Official SVN repository and contact information can be found at
 | ||||||
| // http://code.google.com/p/dolphin-emu/
 | // http://code.google.com/p/dolphin-emu/
 | ||||||
| 
 | 
 | ||||||
| #include "x64_emitter.h" |  | ||||||
| #include "abi.h" | #include "abi.h" | ||||||
|  | #include "emitter.h" | ||||||
| 
 | 
 | ||||||
| using namespace Gen; | using namespace Gen; | ||||||
| 
 | 
 | ||||||
|  | @ -27,7 +27,7 @@ void XEmitter::ABI_EmitPrologue(int maxCallParams) | ||||||
| { | { | ||||||
| #ifdef _M_IX86 | #ifdef _M_IX86 | ||||||
|     // Don't really need to do anything
 |     // Don't really need to do anything
 | ||||||
| #elif defined(_M_X86_64) | #elif defined(ARCHITECTURE_X64) | ||||||
| #if _WIN32 | #if _WIN32 | ||||||
|     int stacksize = ((maxCallParams + 1) & ~1) * 8 + 8; |     int stacksize = ((maxCallParams + 1) & ~1) * 8 + 8; | ||||||
|     // Set up a stack frame so that we can call functions
 |     // Set up a stack frame so that we can call functions
 | ||||||
|  | @ -43,7 +43,7 @@ void XEmitter::ABI_EmitEpilogue(int maxCallParams) | ||||||
| { | { | ||||||
| #ifdef _M_IX86 | #ifdef _M_IX86 | ||||||
|     RET(); |     RET(); | ||||||
| #elif defined(_M_X86_64) | #elif defined(ARCHITECTURE_X64) | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
|     int stacksize = ((maxCallParams+1)&~1)*8 + 8; |     int stacksize = ((maxCallParams+1)&~1)*8 + 8; | ||||||
|     ADD(64, R(RSP), Imm8(stacksize)); |     ADD(64, R(RSP), Imm8(stacksize)); | ||||||
|  | @ -17,7 +17,7 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| // x86/x64 ABI:s, and helpers to help follow them when JIT-ing code.
 | // x86/x64 ABI:s, and helpers to help follow them when JIT-ing code.
 | ||||||
| // All convensions return values in EAX (+ possibly EDX).
 | // All convensions return values in EAX (+ possibly EDX).
 | ||||||
|  | @ -55,7 +55,7 @@ | ||||||
| // 32-bit bog standard cdecl, shared between linux and windows
 | // 32-bit bog standard cdecl, shared between linux and windows
 | ||||||
| // MacOSX 32-bit is same as System V with a few exceptions that we probably don't care much about.
 | // MacOSX 32-bit is same as System V with a few exceptions that we probably don't care much about.
 | ||||||
| 
 | 
 | ||||||
| #elif _M_X86_64 // 64 bit calling convention
 | #elif ARCHITECTURE_X64 // 64 bit calling convention
 | ||||||
| 
 | 
 | ||||||
| #ifdef _WIN32 // 64-bit Windows - the really exotic calling convention
 | #ifdef _WIN32 // 64-bit Windows - the really exotic calling convention
 | ||||||
| 
 | 
 | ||||||
|  | @ -17,13 +17,13 @@ | ||||||
| 
 | 
 | ||||||
| #include <cstring> | #include <cstring> | ||||||
| 
 | 
 | ||||||
| #include "logging/log.h" | #include "common/assert.h" | ||||||
|  | #include "common/cpu_detect.h" | ||||||
|  | #include "common/logging/log.h" | ||||||
|  | #include "common/memory_util.h" | ||||||
| 
 | 
 | ||||||
| #include "assert.h" |  | ||||||
| #include "x64_emitter.h" |  | ||||||
| #include "abi.h" | #include "abi.h" | ||||||
| #include "cpu_detect.h" | #include "emitter.h" | ||||||
| #include "memory_util.h" |  | ||||||
| 
 | 
 | ||||||
| #define PRIx64 "llx" | #define PRIx64 "llx" | ||||||
| 
 | 
 | ||||||
|  | @ -164,7 +164,7 @@ void XEmitter::WriteSIB(int scale, int index, int base) | ||||||
| void OpArg::WriteRex(XEmitter *emit, int opBits, int bits, int customOp) const | void OpArg::WriteRex(XEmitter *emit, int opBits, int bits, int customOp) const | ||||||
| { | { | ||||||
|     if (customOp == -1)       customOp = operandReg; |     if (customOp == -1)       customOp = operandReg; | ||||||
| #ifdef _M_X86_64 | #ifdef ARCHITECTURE_X64 | ||||||
|     u8 op = 0x40; |     u8 op = 0x40; | ||||||
|     // REX.W (whether operation is a 64-bit operation)
 |     // REX.W (whether operation is a 64-bit operation)
 | ||||||
|     if (opBits == 64)         op |= 8; |     if (opBits == 64)         op |= 8; | ||||||
|  | @ -236,7 +236,7 @@ void OpArg::WriteRest(XEmitter *emit, int extraBytes, X64Reg _operandReg, | ||||||
|         _offsetOrBaseReg = 5; |         _offsetOrBaseReg = 5; | ||||||
|         emit->WriteModRM(0, _operandReg, _offsetOrBaseReg); |         emit->WriteModRM(0, _operandReg, _offsetOrBaseReg); | ||||||
|         //TODO : add some checks
 |         //TODO : add some checks
 | ||||||
| #ifdef _M_X86_64 | #ifdef ARCHITECTURE_X64 | ||||||
|         u64 ripAddr = (u64)emit->GetCodePtr() + 4 + extraBytes; |         u64 ripAddr = (u64)emit->GetCodePtr() + 4 + extraBytes; | ||||||
|         s64 distance = (s64)offset - (s64)ripAddr; |         s64 distance = (s64)offset - (s64)ripAddr; | ||||||
|         ASSERT_MSG( |         ASSERT_MSG( | ||||||
|  | @ -1463,7 +1463,7 @@ void XEmitter::MOVD_xmm(const OpArg &arg, X64Reg src) {WriteSSEOp(0x66, 0x7E, sr | ||||||
| 
 | 
 | ||||||
| void XEmitter::MOVQ_xmm(X64Reg dest, OpArg arg) | void XEmitter::MOVQ_xmm(X64Reg dest, OpArg arg) | ||||||
| { | { | ||||||
| #ifdef _M_X86_64 | #ifdef ARCHITECTURE_X64 | ||||||
|         // Alternate encoding
 |         // Alternate encoding
 | ||||||
|         // This does not display correctly in MSVC's debugger, it thinks it's a MOVD
 |         // This does not display correctly in MSVC's debugger, it thinks it's a MOVD
 | ||||||
|         arg.operandReg = dest; |         arg.operandReg = dest; | ||||||
|  | @ -17,11 +17,11 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "assert.h" | #include "common/assert.h" | ||||||
| #include "common_types.h" | #include "common/common_types.h" | ||||||
| #include "code_block.h" | #include "common/code_block.h" | ||||||
| 
 | 
 | ||||||
| #if defined(_M_X86_64) && !defined(_ARCH_64) | #if defined(ARCHITECTURE_X64) && !defined(_ARCH_64) | ||||||
| #define _ARCH_64 | #define _ARCH_64 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | @ -13,7 +13,6 @@ set(SRCS | ||||||
|             rasterizer.cpp |             rasterizer.cpp | ||||||
|             shader/shader.cpp |             shader/shader.cpp | ||||||
|             shader/shader_interpreter.cpp |             shader/shader_interpreter.cpp | ||||||
|             shader/shader_jit.cpp |  | ||||||
|             utils.cpp |             utils.cpp | ||||||
|             video_core.cpp |             video_core.cpp | ||||||
|             ) |             ) | ||||||
|  | @ -39,17 +38,16 @@ set(HEADERS | ||||||
|             renderer_base.h |             renderer_base.h | ||||||
|             shader/shader.h |             shader/shader.h | ||||||
|             shader/shader_interpreter.h |             shader/shader_interpreter.h | ||||||
|             shader/shader_jit.h |  | ||||||
|             utils.h |             utils.h | ||||||
|             video_core.h |             video_core.h | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
| if(_M_X86_64) | if(ARCHITECTURE_X64) | ||||||
|     set(SRCS ${SRCS} |     set(SRCS ${SRCS} | ||||||
|             shader/shader_jit_x64.cpp) |             shader/shader_jit_x64.cpp) | ||||||
| else() | 
 | ||||||
|     set(SRCS ${SRCS} |     set(HEADERS ${HEADERS} | ||||||
|             shader/shader_jit_fake.cpp) |             shader/shader_jit_x64.h) | ||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
| create_directory_groups(${SRCS} ${HEADERS}) | create_directory_groups(${SRCS} ${HEADERS}) | ||||||
|  |  | ||||||
|  | @ -15,7 +15,10 @@ | ||||||
| 
 | 
 | ||||||
| #include "shader.h" | #include "shader.h" | ||||||
| #include "shader_interpreter.h" | #include "shader_interpreter.h" | ||||||
| #include "shader_jit.h" | 
 | ||||||
|  | #ifdef ARCHITECTURE_X64 | ||||||
|  | #include "shader_jit_x64.h" | ||||||
|  | #endif // ARCHITECTURE_X64
 | ||||||
| 
 | 
 | ||||||
| namespace Pica { | namespace Pica { | ||||||
| 
 | 
 | ||||||
|  | @ -43,7 +46,7 @@ void Setup(UnitState& state) { | ||||||
|             jit_shader = jit.Compile(); |             jit_shader = jit.Compile(); | ||||||
|             shader_map.emplace(cache_key, jit_shader); |             shader_map.emplace(cache_key, jit_shader); | ||||||
|         } |         } | ||||||
|     } | #endif // ARCHITECTURE_X64
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Shutdown() { | void Shutdown() { | ||||||
|  | @ -92,7 +95,7 @@ OutputVertex Run(UnitState& state, const InputVertex& input, int num_attributes) | ||||||
|         RunInterpreter(state); |         RunInterpreter(state); | ||||||
| #else | #else | ||||||
|     RunInterpreter(state); |     RunInterpreter(state); | ||||||
| #endif | #endif // ARCHITECTURE_X64
 | ||||||
| 
 | 
 | ||||||
| #if PICA_DUMP_SHADERS | #if PICA_DUMP_SHADERS | ||||||
|     DebugUtils::DumpShader(setup.program_code.data(), state.debug.max_offset, setup.swizzle_data.data(), |     DebugUtils::DumpShader(setup.program_code.data(), state.debug.max_offset, setup.swizzle_data.data(), | ||||||
|  |  | ||||||
|  | @ -1,36 +0,0 @@ | ||||||
| // Copyright 2015 Citra Emulator Project
 |  | ||||||
| // Licensed under GPLv2 or any later version
 |  | ||||||
| // Refer to the license.txt file included.
 |  | ||||||
| 
 |  | ||||||
| #include "video_core/pica.h" |  | ||||||
| 
 |  | ||||||
| #include "shader.h" |  | ||||||
| #include "shader_jit.h" |  | ||||||
| 
 |  | ||||||
| namespace Pica { |  | ||||||
| 
 |  | ||||||
| namespace Shader { |  | ||||||
| 
 |  | ||||||
| JitShader::JitShader() : jitted(nullptr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void JitShader::DoJit(JitCompiler& jit) { |  | ||||||
|     jitted = jit.Compile(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void JitShader::Run(UnitState& state) { |  | ||||||
|     if (jitted) |  | ||||||
|         jitted(&state); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| JitCompiler::JitCompiler() { |  | ||||||
|     AllocCodeSpace(1024 * 1024 * 4); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void JitCompiler::Clear() { |  | ||||||
|     ClearCodeSpace(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } // namespace Shader
 |  | ||||||
| 
 |  | ||||||
| } // namespace Pica
 |  | ||||||
|  | @ -1,91 +0,0 @@ | ||||||
| // Copyright 2015 Citra Emulator Project
 |  | ||||||
| // Licensed under GPLv2 or any later version
 |  | ||||||
| // Refer to the license.txt file included.
 |  | ||||||
| 
 |  | ||||||
| #include "common/fake_emitter.h" |  | ||||||
| 
 |  | ||||||
| #include "video_core/shader/shader.h" |  | ||||||
| #include "video_core/shader/shader_jit.h" |  | ||||||
| 
 |  | ||||||
| namespace Pica { |  | ||||||
| 
 |  | ||||||
| namespace Shader { |  | ||||||
| 
 |  | ||||||
| using namespace FakeGen; |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_ADD(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_DP3(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_DP4(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_MUL(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_FLR(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_MAX(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_MIN(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_MOVA(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_MOV(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_SLTI(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_RCP(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_RSQ(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_NOP(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_END(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_CALL(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_CALLC(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_CALLU(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_CMP(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_MAD(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_IF(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_LOOP(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_JMP(Instruction instr) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Jit::Comp_NextInstr(unsigned* offset) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| CompiledShader Jit::Compile() { |  | ||||||
|     return nullptr; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } // namespace Shader
 |  | ||||||
| 
 |  | ||||||
| } // namespace Pica
 |  | ||||||
|  | @ -4,12 +4,13 @@ | ||||||
| 
 | 
 | ||||||
| #include <smmintrin.h> | #include <smmintrin.h> | ||||||
| 
 | 
 | ||||||
| #include "common/abi.h" |  | ||||||
| #include "common/cpu_detect.h" | #include "common/cpu_detect.h" | ||||||
| #include "common/x64_emitter.h" | 
 | ||||||
|  | #include "common/x64/abi.h" | ||||||
|  | #include "common/x64/emitter.h" | ||||||
| 
 | 
 | ||||||
| #include "shader.h" | #include "shader.h" | ||||||
| #include "shader_jit.h" | #include "shader_jit_x64.h" | ||||||
| 
 | 
 | ||||||
| namespace Pica { | namespace Pica { | ||||||
| 
 | 
 | ||||||
|  | @ -134,7 +135,7 @@ static const u8 NO_DEST_REG_MASK = 0xf; | ||||||
|  */ |  */ | ||||||
| void JitCompiler::Compile_SwizzleSrc(Instruction instr, unsigned src_num, SourceRegister src_reg, X64Reg dest) { | void JitCompiler::Compile_SwizzleSrc(Instruction instr, unsigned src_num, SourceRegister src_reg, X64Reg dest) { | ||||||
|     X64Reg src_ptr; |     X64Reg src_ptr; | ||||||
|     std::size_t src_offset; |     int src_offset; | ||||||
| 
 | 
 | ||||||
|     if (src_reg.GetRegisterType() == RegisterType::FloatUniform) { |     if (src_reg.GetRegisterType() == RegisterType::FloatUniform) { | ||||||
|         src_ptr = UNIFORMS; |         src_ptr = UNIFORMS; | ||||||
|  | @ -451,7 +452,6 @@ void JitCompiler::Compile_NOP(Instruction instr) { | ||||||
| void JitCompiler::Compile_END(Instruction instr) { | void JitCompiler::Compile_END(Instruction instr) { | ||||||
|     ABI_PopAllCalleeSavedRegsAndAdjustStack(); |     ABI_PopAllCalleeSavedRegsAndAdjustStack(); | ||||||
|     RET(); |     RET(); | ||||||
|     done = true; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void JitCompiler::Compile_CALL(Instruction instr) { | void JitCompiler::Compile_CALL(Instruction instr) { | ||||||
|  | @ -655,7 +655,7 @@ CompiledShader* JitCompiler::Compile() { | ||||||
|     MOVAPS(NEGBIT, MDisp(RAX, 0)); |     MOVAPS(NEGBIT, MDisp(RAX, 0)); | ||||||
| 
 | 
 | ||||||
|     looping = false; |     looping = false; | ||||||
|     done = false; | 
 | ||||||
|     while (offset < g_state.vs.program_code.size()) { |     while (offset < g_state.vs.program_code.size()) { | ||||||
|         Compile_NextInstr(&offset); |         Compile_NextInstr(&offset); | ||||||
|     } |     } | ||||||
|  | @ -663,6 +663,14 @@ CompiledShader* JitCompiler::Compile() { | ||||||
|     return (CompiledShader*)start; |     return (CompiledShader*)start; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | JitCompiler::JitCompiler() { | ||||||
|  |     AllocCodeSpace(1024 * 1024 * 4); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void JitCompiler::Clear() { | ||||||
|  |     ClearCodeSpace(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace Shader
 | } // namespace Shader
 | ||||||
| 
 | 
 | ||||||
| } // namespace Pica
 | } // namespace Pica
 | ||||||
|  |  | ||||||
|  | @ -6,11 +6,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <nihstro/shader_bytecode.h> | #include <nihstro/shader_bytecode.h> | ||||||
| 
 | 
 | ||||||
| #if defined(_M_X86_64) | #include "common/x64/emitter.h" | ||||||
| #include "common/x64_emitter.h" |  | ||||||
| #else |  | ||||||
| #include "common/fake_emitter.h" |  | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| #include "video_core/pica.h" | #include "video_core/pica.h" | ||||||
| 
 | 
 | ||||||
|  | @ -65,18 +61,16 @@ private: | ||||||
|     void Compile_Block(unsigned stop); |     void Compile_Block(unsigned stop); | ||||||
|     void Compile_NextInstr(unsigned* offset); |     void Compile_NextInstr(unsigned* offset); | ||||||
| 
 | 
 | ||||||
| #if defined(_M_X86_64) |  | ||||||
|     void Compile_SwizzleSrc(Instruction instr, unsigned src_num, SourceRegister src_reg, Gen::X64Reg dest); |     void Compile_SwizzleSrc(Instruction instr, unsigned src_num, SourceRegister src_reg, Gen::X64Reg dest); | ||||||
|     void Compile_DestEnable(Instruction instr, Gen::X64Reg dest); |     void Compile_DestEnable(Instruction instr, Gen::X64Reg dest); | ||||||
| 
 | 
 | ||||||
|     void Compile_EvaluateCondition(Instruction instr); |     void Compile_EvaluateCondition(Instruction instr); | ||||||
|     void Compile_UniformCondition(Instruction instr); |     void Compile_UniformCondition(Instruction instr); | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
|     /// Pointer to the variable that stores the current Pica code offset. Used to handle nested code blocks.
 |     /// Pointer to the variable that stores the current Pica code offset. Used to handle nested code blocks.
 | ||||||
|     unsigned* offset_ptr = nullptr; |     unsigned* offset_ptr = nullptr; | ||||||
| 
 | 
 | ||||||
|     bool done = false; |     /// Set to true if currently in a loop, used to check for the existence of nested loops
 | ||||||
|     bool looping = false; |     bool looping = false; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bunnei
						bunnei