diff options
| author | 2015-08-12 00:00:44 -0400 | |
|---|---|---|
| committer | 2015-08-15 18:03:25 -0400 | |
| commit | bd7e691f78d916ed6ae5396b2d646d9b3a053dd7 (patch) | |
| tree | a20367004f684afeca83e795ce66e62115e8e79d /src/common | |
| parent | JIT: Support negative address offsets. (diff) | |
| download | yuzu-bd7e691f78d916ed6ae5396b2d646d9b3a053dd7.tar.gz yuzu-bd7e691f78d916ed6ae5396b2d646d9b3a053dd7.tar.xz yuzu-bd7e691f78d916ed6ae5396b2d646d9b3a053dd7.zip | |
x64: Refactor to remove fake interfaces and general cleanups.
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/CMakeLists.txt | 18 | ||||
| -rw-r--r-- | src/common/common_funcs.h | 2 | ||||
| -rw-r--r-- | src/common/cpu_detect.cpp (renamed from src/common/cpu_detect_x86.cpp) | 2 | ||||
| -rw-r--r-- | src/common/cpu_detect_generic.cpp | 19 | ||||
| -rw-r--r-- | src/common/fake_emitter.h | 465 | ||||
| -rw-r--r-- | src/common/platform.h | 2 | ||||
| -rw-r--r-- | src/common/x64/abi.cpp (renamed from src/common/abi.cpp) | 6 | ||||
| -rw-r--r-- | src/common/x64/abi.h (renamed from src/common/abi.h) | 4 | ||||
| -rw-r--r-- | src/common/x64/emitter.cpp (renamed from src/common/x64_emitter.cpp) | 16 | ||||
| -rw-r--r-- | src/common/x64/emitter.h (renamed from src/common/x64_emitter.h) | 8 |
10 files changed, 26 insertions, 516 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index af387c6c8..fe82f71e8 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -2,8 +2,8 @@ | |||
| 2 | configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in" "${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp" @ONLY) | 2 | configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in" "${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp" @ONLY) |
| 3 | 3 | ||
| 4 | set(SRCS | 4 | set(SRCS |
| 5 | abi.cpp | ||
| 6 | break_points.cpp | 5 | break_points.cpp |
| 6 | cpu_detect.cpp | ||
| 7 | emu_window.cpp | 7 | emu_window.cpp |
| 8 | file_util.cpp | 8 | file_util.cpp |
| 9 | hash.cpp | 9 | hash.cpp |
| @@ -22,7 +22,6 @@ set(SRCS | |||
| 22 | ) | 22 | ) |
| 23 | 23 | ||
| 24 | set(HEADERS | 24 | set(HEADERS |
| 25 | abi.h | ||
| 26 | assert.h | 25 | assert.h |
| 27 | bit_field.h | 26 | bit_field.h |
| 28 | break_points.h | 27 | break_points.h |
| @@ -61,19 +60,14 @@ set(HEADERS | |||
| 61 | vector_math.h | 60 | vector_math.h |
| 62 | ) | 61 | ) |
| 63 | 62 | ||
| 64 | if(_M_X86_64) | 63 | if(ARCHITECTURE_X64) |
| 65 | set(SRCS ${SRCS} | 64 | set(SRCS ${SRCS} |
| 66 | cpu_detect_x86.cpp | 65 | x64/abi.cpp |
| 67 | x64_emitter.cpp) | 66 | x64/emitter.cpp) |
| 68 | 67 | ||
| 69 | set(HEADERS ${HEADERS} | 68 | set(HEADERS ${HEADERS} |
| 70 | x64_emitter.h) | 69 | x64/abi.h |
| 71 | else() | 70 | x64/emitter.h) |
| 72 | set(SRCS ${SRCS} | ||
| 73 | cpu_detect_generic.cpp) | ||
| 74 | |||
| 75 | set(HEADERS ${HEADERS} | ||
| 76 | fake_emitter.h) | ||
| 77 | endif() | 71 | endif() |
| 78 | 72 | ||
| 79 | create_directory_groups(${SRCS} ${HEADERS}) | 73 | create_directory_groups(${SRCS} ${HEADERS}) |
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index 6fd2b06b2..948070e62 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h | |||
| @@ -35,7 +35,7 @@ | |||
| 35 | 35 | ||
| 36 | #ifndef _MSC_VER | 36 | #ifndef _MSC_VER |
| 37 | 37 | ||
| 38 | #if defined(__x86_64__) || defined(_M_X86_64) | 38 | #if defined(__x86_64__) || defined(ARCHITECTURE_X64) |
| 39 | #define Crash() __asm__ __volatile__("int $3") | 39 | #define Crash() __asm__ __volatile__("int $3") |
| 40 | #elif defined(_M_ARM) | 40 | #elif defined(_M_ARM) |
| 41 | #define Crash() __asm__ __volatile__("trap") | 41 | #define Crash() __asm__ __volatile__("trap") |
diff --git a/src/common/cpu_detect_x86.cpp b/src/common/cpu_detect.cpp index 0bcff726d..1d612829e 100644 --- a/src/common/cpu_detect_x86.cpp +++ b/src/common/cpu_detect.cpp | |||
| @@ -62,7 +62,7 @@ CPUInfo::CPUInfo() { | |||
| 62 | // Detects the various CPU features | 62 | // Detects the various CPU features |
| 63 | void CPUInfo::Detect() { | 63 | void CPUInfo::Detect() { |
| 64 | memset(this, 0, sizeof(*this)); | 64 | memset(this, 0, sizeof(*this)); |
| 65 | #ifdef _M_X86_64 | 65 | #ifdef ARCHITECTURE_X64 |
| 66 | Mode64bit = true; | 66 | Mode64bit = true; |
| 67 | OS64bit = true; | 67 | OS64bit = true; |
| 68 | #endif | 68 | #endif |
diff --git a/src/common/cpu_detect_generic.cpp b/src/common/cpu_detect_generic.cpp deleted file mode 100644 index ccec324d9..000000000 --- a/src/common/cpu_detect_generic.cpp +++ /dev/null | |||
| @@ -1,19 +0,0 @@ | |||
| 1 | // Copyright 2014 Dolphin Emulator Project | ||
| 2 | // Licensed under GPLv2+ | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "cpu_detect.h" | ||
| 6 | #include "hash.h" | ||
| 7 | |||
| 8 | namespace Common { | ||
| 9 | |||
| 10 | CPUInfo cpu_info; | ||
| 11 | |||
| 12 | CPUInfo::CPUInfo() { | ||
| 13 | } | ||
| 14 | |||
| 15 | std::string CPUInfo::Summarize() { | ||
| 16 | return "Generic"; | ||
| 17 | } | ||
| 18 | |||
| 19 | } // namespace Common | ||
diff --git a/src/common/fake_emitter.h b/src/common/fake_emitter.h deleted file mode 100644 index d6d96a51e..000000000 --- a/src/common/fake_emitter.h +++ /dev/null | |||
| @@ -1,465 +0,0 @@ | |||
| 1 | // Copyright (C) 2003 Dolphin Project. | ||
| 2 | |||
| 3 | // This program is free software: you can redistribute it and/or modify | ||
| 4 | // it under the terms of the GNU General Public License as published by | ||
| 5 | // the Free Software Foundation, version 2.0. | ||
| 6 | |||
| 7 | // This program is distributed in the hope that it will be useful, | ||
| 8 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 9 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 10 | // GNU General Public License 2.0 for more details. | ||
| 11 | |||
| 12 | // A copy of the GPL 2.0 should have been included with the program. | ||
| 13 | // If not, see http://www.gnu.org/licenses/ | ||
| 14 | |||
| 15 | // Official SVN repository and contact information can be found at | ||
| 16 | // http://code.google.com/p/dolphin-emu/ | ||
| 17 | |||
| 18 | // WARNING - THIS LIBRARY IS NOT THREAD SAFE!!! | ||
| 19 | |||
| 20 | #pragma once | ||
| 21 | |||
| 22 | #include <vector> | ||
| 23 | #include <stdint.h> | ||
| 24 | |||
| 25 | #include "assert.h" | ||
| 26 | #include "common_types.h" | ||
| 27 | |||
| 28 | // TODO: Check if Pandora still needs signal.h/kill here. Symbian doesn't. | ||
| 29 | |||
| 30 | // VCVT flags | ||
| 31 | #define TO_FLOAT 0 | ||
| 32 | #define TO_INT 1 << 0 | ||
| 33 | #define IS_SIGNED 1 << 1 | ||
| 34 | #define ROUND_TO_ZERO 1 << 2 | ||
| 35 | |||
| 36 | namespace FakeGen | ||
| 37 | { | ||
| 38 | enum FakeReg | ||
| 39 | { | ||
| 40 | // GPRs | ||
| 41 | R0 = 0, R1, R2, R3, R4, R5, | ||
| 42 | R6, R7, R8, R9, R10, R11, | ||
| 43 | |||
| 44 | // SPRs | ||
| 45 | // R13 - R15 are SP, LR, and PC. | ||
| 46 | // Almost always referred to by name instead of register number | ||
| 47 | R12 = 12, R13 = 13, R14 = 14, R15 = 15, | ||
| 48 | R_IP = 12, R_SP = 13, R_LR = 14, R_PC = 15, | ||
| 49 | |||
| 50 | |||
| 51 | // VFP single precision registers | ||
| 52 | S0, S1, S2, S3, S4, S5, S6, | ||
| 53 | S7, S8, S9, S10, S11, S12, S13, | ||
| 54 | S14, S15, S16, S17, S18, S19, S20, | ||
| 55 | S21, S22, S23, S24, S25, S26, S27, | ||
| 56 | S28, S29, S30, S31, | ||
| 57 | |||
| 58 | // VFP Double Precision registers | ||
| 59 | D0, D1, D2, D3, D4, D5, D6, D7, | ||
| 60 | D8, D9, D10, D11, D12, D13, D14, D15, | ||
| 61 | D16, D17, D18, D19, D20, D21, D22, D23, | ||
| 62 | D24, D25, D26, D27, D28, D29, D30, D31, | ||
| 63 | |||
| 64 | // ASIMD Quad-Word registers | ||
| 65 | Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, | ||
| 66 | Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15, | ||
| 67 | |||
| 68 | // for NEON VLD/VST instructions | ||
| 69 | REG_UPDATE = R13, | ||
| 70 | INVALID_REG = 0xFFFFFFFF | ||
| 71 | }; | ||
| 72 | |||
| 73 | enum CCFlags | ||
| 74 | { | ||
| 75 | CC_EQ = 0, // Equal | ||
| 76 | CC_NEQ, // Not equal | ||
| 77 | CC_CS, // Carry Set | ||
| 78 | CC_CC, // Carry Clear | ||
| 79 | CC_MI, // Minus (Negative) | ||
| 80 | CC_PL, // Plus | ||
| 81 | CC_VS, // Overflow | ||
| 82 | CC_VC, // No Overflow | ||
| 83 | CC_HI, // Unsigned higher | ||
| 84 | CC_LS, // Unsigned lower or same | ||
| 85 | CC_GE, // Signed greater than or equal | ||
| 86 | CC_LT, // Signed less than | ||
| 87 | CC_GT, // Signed greater than | ||
| 88 | CC_LE, // Signed less than or equal | ||
| 89 | CC_AL, // Always (unconditional) 14 | ||
| 90 | CC_HS = CC_CS, // Alias of CC_CS Unsigned higher or same | ||
| 91 | CC_LO = CC_CC, // Alias of CC_CC Unsigned lower | ||
| 92 | }; | ||
| 93 | const u32 NO_COND = 0xE0000000; | ||
| 94 | |||
| 95 | enum ShiftType | ||
| 96 | { | ||
| 97 | ST_LSL = 0, | ||
| 98 | ST_ASL = 0, | ||
| 99 | ST_LSR = 1, | ||
| 100 | ST_ASR = 2, | ||
| 101 | ST_ROR = 3, | ||
| 102 | ST_RRX = 4 | ||
| 103 | }; | ||
| 104 | enum IntegerSize | ||
| 105 | { | ||
| 106 | I_I8 = 0, | ||
| 107 | I_I16, | ||
| 108 | I_I32, | ||
| 109 | I_I64 | ||
| 110 | }; | ||
| 111 | |||
| 112 | enum | ||
| 113 | { | ||
| 114 | NUMGPRs = 13, | ||
| 115 | }; | ||
| 116 | |||
| 117 | class FakeXEmitter; | ||
| 118 | |||
| 119 | enum OpType | ||
| 120 | { | ||
| 121 | TYPE_IMM = 0, | ||
| 122 | TYPE_REG, | ||
| 123 | TYPE_IMMSREG, | ||
| 124 | TYPE_RSR, | ||
| 125 | TYPE_MEM | ||
| 126 | }; | ||
| 127 | |||
| 128 | // This is no longer a proper operand2 class. Need to split up. | ||
| 129 | class Operand2 | ||
| 130 | { | ||
| 131 | friend class FakeXEmitter; | ||
| 132 | protected: | ||
| 133 | u32 Value; | ||
| 134 | |||
| 135 | private: | ||
| 136 | OpType Type; | ||
| 137 | |||
| 138 | // IMM types | ||
| 139 | u8 Rotation; // Only for u8 values | ||
| 140 | |||
| 141 | // Register types | ||
| 142 | u8 IndexOrShift; | ||
| 143 | ShiftType Shift; | ||
| 144 | public: | ||
| 145 | OpType GetType() | ||
| 146 | { | ||
| 147 | return Type; | ||
| 148 | } | ||
| 149 | Operand2() {} | ||
| 150 | Operand2(u32 imm, OpType type = TYPE_IMM) | ||
| 151 | { | ||
| 152 | Type = type; | ||
| 153 | Value = imm; | ||
| 154 | Rotation = 0; | ||
| 155 | } | ||
| 156 | |||
| 157 | Operand2(FakeReg Reg) | ||
| 158 | { | ||
| 159 | Type = TYPE_REG; | ||
| 160 | Value = Reg; | ||
| 161 | Rotation = 0; | ||
| 162 | } | ||
| 163 | Operand2(u8 imm, u8 rotation) | ||
| 164 | { | ||
| 165 | Type = TYPE_IMM; | ||
| 166 | Value = imm; | ||
| 167 | Rotation = rotation; | ||
| 168 | } | ||
| 169 | Operand2(FakeReg base, ShiftType type, FakeReg shift) // RSR | ||
| 170 | { | ||
| 171 | Type = TYPE_RSR; | ||
| 172 | ASSERT_MSG(type != ST_RRX, "Invalid Operand2: RRX does not take a register shift amount"); | ||
| 173 | IndexOrShift = shift; | ||
| 174 | Shift = type; | ||
| 175 | Value = base; | ||
| 176 | } | ||
| 177 | |||
| 178 | Operand2(FakeReg base, ShiftType type, u8 shift)// For IMM shifted register | ||
| 179 | { | ||
| 180 | if(shift == 32) shift = 0; | ||
| 181 | switch (type) | ||
| 182 | { | ||
| 183 | case ST_LSL: | ||
| 184 | ASSERT_MSG(shift < 32, "Invalid Operand2: LSL %u", shift); | ||
| 185 | break; | ||
| 186 | case ST_LSR: | ||
| 187 | ASSERT_MSG(shift <= 32, "Invalid Operand2: LSR %u", shift); | ||
| 188 | if (!shift) | ||
| 189 | type = ST_LSL; | ||
| 190 | if (shift == 32) | ||
| 191 | shift = 0; | ||
| 192 | break; | ||
| 193 | case ST_ASR: | ||
| 194 | ASSERT_MSG(shift < 32, "Invalid Operand2: ASR %u", shift); | ||
| 195 | if (!shift) | ||
| 196 | type = ST_LSL; | ||
| 197 | if (shift == 32) | ||
| 198 | shift = 0; | ||
| 199 | break; | ||
| 200 | case ST_ROR: | ||
| 201 | ASSERT_MSG(shift < 32, "Invalid Operand2: ROR %u", shift); | ||
| 202 | if (!shift) | ||
| 203 | type = ST_LSL; | ||
| 204 | break; | ||
| 205 | case ST_RRX: | ||
| 206 | ASSERT_MSG(shift == 0, "Invalid Operand2: RRX does not take an immediate shift amount"); | ||
| 207 | type = ST_ROR; | ||
| 208 | break; | ||
| 209 | } | ||
| 210 | IndexOrShift = shift; | ||
| 211 | Shift = type; | ||
| 212 | Value = base; | ||
| 213 | Type = TYPE_IMMSREG; | ||
| 214 | } | ||
| 215 | u32 GetData() | ||
| 216 | { | ||
| 217 | switch(Type) | ||
| 218 | { | ||
| 219 | case TYPE_IMM: | ||
| 220 | return Imm12Mod(); // This'll need to be changed later | ||
| 221 | case TYPE_REG: | ||
| 222 | return Rm(); | ||
| 223 | case TYPE_IMMSREG: | ||
| 224 | return IMMSR(); | ||
| 225 | case TYPE_RSR: | ||
| 226 | return RSR(); | ||
| 227 | default: | ||
| 228 | ASSERT_MSG(false, "GetData with Invalid Type"); | ||
| 229 | return 0; | ||
| 230 | } | ||
| 231 | } | ||
| 232 | u32 IMMSR() // IMM shifted register | ||
| 233 | { | ||
| 234 | ASSERT_MSG(Type == TYPE_IMMSREG, "IMMSR must be imm shifted register"); | ||
| 235 | return ((IndexOrShift & 0x1f) << 7 | (Shift << 5) | Value); | ||
| 236 | } | ||
| 237 | u32 RSR() // Register shifted register | ||
| 238 | { | ||
| 239 | ASSERT_MSG(Type == TYPE_RSR, "RSR must be RSR Of Course"); | ||
| 240 | return (IndexOrShift << 8) | (Shift << 5) | 0x10 | Value; | ||
| 241 | } | ||
| 242 | u32 Rm() | ||
| 243 | { | ||
| 244 | ASSERT_MSG(Type == TYPE_REG, "Rm must be with Reg"); | ||
| 245 | return Value; | ||
| 246 | } | ||
| 247 | |||
| 248 | u32 Imm5() | ||
| 249 | { | ||
| 250 | ASSERT_MSG((Type == TYPE_IMM), "Imm5 not IMM value"); | ||
| 251 | return ((Value & 0x0000001F) << 7); | ||
| 252 | } | ||
| 253 | u32 Imm8() | ||
| 254 | { | ||
| 255 | ASSERT_MSG((Type == TYPE_IMM), "Imm8Rot not IMM value"); | ||
| 256 | return Value & 0xFF; | ||
| 257 | } | ||
| 258 | u32 Imm8Rot() // IMM8 with Rotation | ||
| 259 | { | ||
| 260 | ASSERT_MSG((Type == TYPE_IMM), "Imm8Rot not IMM value"); | ||
| 261 | ASSERT_MSG((Rotation & 0xE1) != 0, "Invalid Operand2: immediate rotation %u", Rotation); | ||
| 262 | return (1 << 25) | (Rotation << 7) | (Value & 0x000000FF); | ||
| 263 | } | ||
| 264 | u32 Imm12() | ||
| 265 | { | ||
| 266 | ASSERT_MSG((Type == TYPE_IMM), "Imm12 not IMM"); | ||
| 267 | return (Value & 0x00000FFF); | ||
| 268 | } | ||
| 269 | |||
| 270 | u32 Imm12Mod() | ||
| 271 | { | ||
| 272 | // This is an IMM12 with the top four bits being rotation and the | ||
| 273 | // bottom eight being an IMM. This is for instructions that need to | ||
| 274 | // expand a 8bit IMM to a 32bit value and gives you some rotation as | ||
| 275 | // well. | ||
| 276 | // Each rotation rotates to the right by 2 bits | ||
| 277 | ASSERT_MSG((Type == TYPE_IMM), "Imm12Mod not IMM"); | ||
| 278 | return ((Rotation & 0xF) << 8) | (Value & 0xFF); | ||
| 279 | } | ||
| 280 | u32 Imm16() | ||
| 281 | { | ||
| 282 | ASSERT_MSG((Type == TYPE_IMM), "Imm16 not IMM"); | ||
| 283 | return ( (Value & 0xF000) << 4) | (Value & 0x0FFF); | ||
| 284 | } | ||
| 285 | u32 Imm16Low() | ||
| 286 | { | ||
| 287 | return Imm16(); | ||
| 288 | } | ||
| 289 | u32 Imm16High() // Returns high 16bits | ||
| 290 | { | ||
| 291 | ASSERT_MSG((Type == TYPE_IMM), "Imm16 not IMM"); | ||
| 292 | return ( ((Value >> 16) & 0xF000) << 4) | ((Value >> 16) & 0x0FFF); | ||
| 293 | } | ||
| 294 | u32 Imm24() | ||
| 295 | { | ||
| 296 | ASSERT_MSG((Type == TYPE_IMM), "Imm16 not IMM"); | ||
| 297 | return (Value & 0x0FFFFFFF); | ||
| 298 | } | ||
| 299 | }; | ||
| 300 | |||
| 301 | // Use these when you don't know if an imm can be represented as an operand2. | ||
| 302 | // This lets you generate both an optimal and a fallback solution by checking | ||
| 303 | // the return value, which will be false if these fail to find a Operand2 that | ||
| 304 | // represents your 32-bit imm value. | ||
| 305 | bool TryMakeOperand2(u32 imm, Operand2 &op2); | ||
| 306 | bool TryMakeOperand2_AllowInverse(u32 imm, Operand2 &op2, bool *inverse); | ||
| 307 | bool TryMakeOperand2_AllowNegation(s32 imm, Operand2 &op2, bool *negated); | ||
| 308 | |||
| 309 | // Use this only when you know imm can be made into an Operand2. | ||
| 310 | Operand2 AssumeMakeOperand2(u32 imm); | ||
| 311 | |||
| 312 | inline Operand2 R(FakeReg Reg) { return Operand2(Reg, TYPE_REG); } | ||
| 313 | inline Operand2 IMM(u32 Imm) { return Operand2(Imm, TYPE_IMM); } | ||
| 314 | inline Operand2 Mem(void *ptr) { return Operand2((u32)(uintptr_t)ptr, TYPE_IMM); } | ||
| 315 | //usage: struct {int e;} s; STRUCT_OFFSET(s,e) | ||
| 316 | #define STRUCT_OFF(str,elem) ((u32)((u32)&(str).elem-(u32)&(str))) | ||
| 317 | |||
| 318 | |||
| 319 | struct FixupBranch | ||
| 320 | { | ||
| 321 | u8 *ptr; | ||
| 322 | u32 condition; // Remembers our codition at the time | ||
| 323 | int type; //0 = B 1 = BL | ||
| 324 | }; | ||
| 325 | |||
| 326 | typedef const u8* JumpTarget; | ||
| 327 | |||
| 328 | // XXX: Stop polluting the global namespace | ||
| 329 | const u32 I_8 = (1 << 0); | ||
| 330 | const u32 I_16 = (1 << 1); | ||
| 331 | const u32 I_32 = (1 << 2); | ||
| 332 | const u32 I_64 = (1 << 3); | ||
| 333 | const u32 I_SIGNED = (1 << 4); | ||
| 334 | const u32 I_UNSIGNED = (1 << 5); | ||
| 335 | const u32 F_32 = (1 << 6); | ||
| 336 | const u32 I_POLYNOMIAL = (1 << 7); // Only used in VMUL/VMULL | ||
| 337 | |||
| 338 | u32 EncodeVd(FakeReg Vd); | ||
| 339 | u32 EncodeVn(FakeReg Vn); | ||
| 340 | u32 EncodeVm(FakeReg Vm); | ||
| 341 | |||
| 342 | u32 encodedSize(u32 value); | ||
| 343 | |||
| 344 | // Subtracts the base from the register to give us the real one | ||
| 345 | FakeReg SubBase(FakeReg Reg); | ||
| 346 | |||
| 347 | // See A.7.1 in the Fakev7-A | ||
| 348 | // VMUL F32 scalars can only be up to D15[0], D15[1] - higher scalars cannot be individually addressed | ||
| 349 | FakeReg DScalar(FakeReg dreg, int subScalar); | ||
| 350 | FakeReg QScalar(FakeReg qreg, int subScalar); | ||
| 351 | |||
| 352 | enum NEONAlignment { | ||
| 353 | ALIGN_NONE = 0, | ||
| 354 | ALIGN_64 = 1, | ||
| 355 | ALIGN_128 = 2, | ||
| 356 | ALIGN_256 = 3 | ||
| 357 | }; | ||
| 358 | |||
| 359 | |||
| 360 | class NEONXEmitter; | ||
| 361 | |||
| 362 | class FakeXEmitter | ||
| 363 | { | ||
| 364 | friend struct OpArg; // for Write8 etc | ||
| 365 | private: | ||
| 366 | u8 *code, *startcode; | ||
| 367 | u8 *lastCacheFlushEnd; | ||
| 368 | u32 condition; | ||
| 369 | |||
| 370 | protected: | ||
| 371 | inline void Write32(u32 value) {*(u32*)code = value; code+=4;} | ||
| 372 | |||
| 373 | public: | ||
| 374 | FakeXEmitter() : code(0), startcode(0), lastCacheFlushEnd(0) { | ||
| 375 | condition = CC_AL << 28; | ||
| 376 | } | ||
| 377 | FakeXEmitter(u8 *code_ptr) { | ||
| 378 | code = code_ptr; | ||
| 379 | lastCacheFlushEnd = code_ptr; | ||
| 380 | startcode = code_ptr; | ||
| 381 | condition = CC_AL << 28; | ||
| 382 | } | ||
| 383 | virtual ~FakeXEmitter() {} | ||
| 384 | |||
| 385 | void SetCodePtr(u8 *ptr) {} | ||
| 386 | void ReserveCodeSpace(u32 bytes) {} | ||
| 387 | const u8 *AlignCode16() { return nullptr; } | ||
| 388 | const u8 *AlignCodePage() { return nullptr; } | ||
| 389 | const u8 *GetCodePtr() const { return nullptr; } | ||
| 390 | void FlushIcache() {} | ||
| 391 | void FlushIcacheSection(u8 *start, u8 *end) {} | ||
| 392 | u8 *GetWritableCodePtr() { return nullptr; } | ||
| 393 | |||
| 394 | CCFlags GetCC() { return CCFlags(condition >> 28); } | ||
| 395 | void SetCC(CCFlags cond = CC_AL) {} | ||
| 396 | |||
| 397 | // Special purpose instructions | ||
| 398 | |||
| 399 | // Do nothing | ||
| 400 | void NOP(int count = 1) {} //nop padding - TODO: fast nop slides, for amd and intel (check their manuals) | ||
| 401 | |||
| 402 | #ifdef CALL | ||
| 403 | #undef CALL | ||
| 404 | #endif | ||
| 405 | |||
| 406 | void QuickCallFunction(FakeReg scratchreg, const void *func); | ||
| 407 | template <typename T> void QuickCallFunction(FakeReg scratchreg, T func) { | ||
| 408 | QuickCallFunction(scratchreg, (const void *)func); | ||
| 409 | } | ||
| 410 | }; // class FakeXEmitter | ||
| 411 | |||
| 412 | |||
| 413 | // Everything that needs to generate machine code should inherit from this. | ||
| 414 | // You get memory management for free, plus, you can use all the MOV etc functions without | ||
| 415 | // having to prefix them with gen-> or something similar. | ||
| 416 | class FakeXCodeBlock : public FakeXEmitter | ||
| 417 | { | ||
| 418 | protected: | ||
| 419 | u8 *region; | ||
| 420 | size_t region_size; | ||
| 421 | |||
| 422 | public: | ||
| 423 | FakeXCodeBlock() : region(NULL), region_size(0) {} | ||
| 424 | virtual ~FakeXCodeBlock() { if (region) FreeCodeSpace(); } | ||
| 425 | |||
| 426 | // Call this before you generate any code. | ||
| 427 | void AllocCodeSpace(int size) { } | ||
| 428 | |||
| 429 | // Always clear code space with breakpoints, so that if someone accidentally executes | ||
| 430 | // uninitialized, it just breaks into the debugger. | ||
| 431 | void ClearCodeSpace() { } | ||
| 432 | |||
| 433 | // Call this when shutting down. Don't rely on the destructor, even though it'll do the job. | ||
| 434 | void FreeCodeSpace() { } | ||
| 435 | |||
| 436 | bool IsInSpace(const u8 *ptr) const | ||
| 437 | { | ||
| 438 | return ptr >= region && ptr < region + region_size; | ||
| 439 | } | ||
| 440 | |||
| 441 | // Cannot currently be undone. Will write protect the entire code region. | ||
| 442 | // Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()). | ||
| 443 | void WriteProtect() { } | ||
| 444 | void UnWriteProtect() { } | ||
| 445 | |||
| 446 | void ResetCodePtr() | ||
| 447 | { | ||
| 448 | SetCodePtr(region); | ||
| 449 | } | ||
| 450 | |||
| 451 | size_t GetSpaceLeft() const | ||
| 452 | { | ||
| 453 | return region_size - (GetCodePtr() - region); | ||
| 454 | } | ||
| 455 | |||
| 456 | u8 *GetBasePtr() { | ||
| 457 | return region; | ||
| 458 | } | ||
| 459 | |||
| 460 | size_t GetOffset(const u8 *ptr) const { | ||
| 461 | return ptr - region; | ||
| 462 | } | ||
| 463 | }; | ||
| 464 | |||
| 465 | } // namespace | ||
diff --git a/src/common/platform.h b/src/common/platform.h index 08aaa03a4..118a9ed3b 100644 --- a/src/common/platform.h +++ b/src/common/platform.h | |||
| @@ -27,7 +27,7 @@ | |||
| 27 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 27 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 28 | // Platform detection | 28 | // Platform detection |
| 29 | 29 | ||
| 30 | #if defined(__x86_64__) || defined(_M_X86_64) || defined(__aarch64__) | 30 | #if defined(__x86_64__) || defined(ARCHITECTURE_X64) || defined(__aarch64__) |
| 31 | #define EMU_ARCH_BITS 64 | 31 | #define EMU_ARCH_BITS 64 |
| 32 | #elif defined(__i386) || defined(_M_IX86) || defined(__arm__) || defined(_M_ARM) | 32 | #elif defined(__i386) || defined(_M_IX86) || defined(__arm__) || defined(_M_ARM) |
| 33 | #define EMU_ARCH_BITS 32 | 33 | #define EMU_ARCH_BITS 32 |
diff --git a/src/common/abi.cpp b/src/common/x64/abi.cpp index d1892ad48..598e7f335 100644 --- a/src/common/abi.cpp +++ b/src/common/x64/abi.cpp | |||
| @@ -15,8 +15,8 @@ | |||
| 15 | // Official SVN repository and contact information can be found at | 15 | // Official SVN repository and contact information can be found at |
| 16 | // http://code.google.com/p/dolphin-emu/ | 16 | // http://code.google.com/p/dolphin-emu/ |
| 17 | 17 | ||
| 18 | #include "x64_emitter.h" | ||
| 19 | #include "abi.h" | 18 | #include "abi.h" |
| 19 | #include "emitter.h" | ||
| 20 | 20 | ||
| 21 | using namespace Gen; | 21 | using namespace Gen; |
| 22 | 22 | ||
| @@ -27,7 +27,7 @@ void XEmitter::ABI_EmitPrologue(int maxCallParams) | |||
| 27 | { | 27 | { |
| 28 | #ifdef _M_IX86 | 28 | #ifdef _M_IX86 |
| 29 | // Don't really need to do anything | 29 | // Don't really need to do anything |
| 30 | #elif defined(_M_X86_64) | 30 | #elif defined(ARCHITECTURE_X64) |
| 31 | #if _WIN32 | 31 | #if _WIN32 |
| 32 | int stacksize = ((maxCallParams + 1) & ~1) * 8 + 8; | 32 | int stacksize = ((maxCallParams + 1) & ~1) * 8 + 8; |
| 33 | // Set up a stack frame so that we can call functions | 33 | // Set up a stack frame so that we can call functions |
| @@ -43,7 +43,7 @@ void XEmitter::ABI_EmitEpilogue(int maxCallParams) | |||
| 43 | { | 43 | { |
| 44 | #ifdef _M_IX86 | 44 | #ifdef _M_IX86 |
| 45 | RET(); | 45 | RET(); |
| 46 | #elif defined(_M_X86_64) | 46 | #elif defined(ARCHITECTURE_X64) |
| 47 | #ifdef _WIN32 | 47 | #ifdef _WIN32 |
| 48 | int stacksize = ((maxCallParams+1)&~1)*8 + 8; | 48 | int stacksize = ((maxCallParams+1)&~1)*8 + 8; |
| 49 | ADD(64, R(RSP), Imm8(stacksize)); | 49 | ADD(64, R(RSP), Imm8(stacksize)); |
diff --git a/src/common/abi.h b/src/common/x64/abi.h index bb9f7c95f..0ee189d45 100644 --- a/src/common/abi.h +++ b/src/common/x64/abi.h | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | #pragma once | 18 | #pragma once |
| 19 | 19 | ||
| 20 | #include "common_types.h" | 20 | #include "common/common_types.h" |
| 21 | 21 | ||
| 22 | // x86/x64 ABI:s, and helpers to help follow them when JIT-ing code. | 22 | // x86/x64 ABI:s, and helpers to help follow them when JIT-ing code. |
| 23 | // All convensions return values in EAX (+ possibly EDX). | 23 | // All convensions return values in EAX (+ possibly EDX). |
| @@ -55,7 +55,7 @@ | |||
| 55 | // 32-bit bog standard cdecl, shared between linux and windows | 55 | // 32-bit bog standard cdecl, shared between linux and windows |
| 56 | // MacOSX 32-bit is same as System V with a few exceptions that we probably don't care much about. | 56 | // MacOSX 32-bit is same as System V with a few exceptions that we probably don't care much about. |
| 57 | 57 | ||
| 58 | #elif _M_X86_64 // 64 bit calling convention | 58 | #elif ARCHITECTURE_X64 // 64 bit calling convention |
| 59 | 59 | ||
| 60 | #ifdef _WIN32 // 64-bit Windows - the really exotic calling convention | 60 | #ifdef _WIN32 // 64-bit Windows - the really exotic calling convention |
| 61 | 61 | ||
diff --git a/src/common/x64_emitter.cpp b/src/common/x64/emitter.cpp index 19db2e484..4e1c43d6c 100644 --- a/src/common/x64_emitter.cpp +++ b/src/common/x64/emitter.cpp | |||
| @@ -17,13 +17,13 @@ | |||
| 17 | 17 | ||
| 18 | #include <cstring> | 18 | #include <cstring> |
| 19 | 19 | ||
| 20 | #include "logging/log.h" | 20 | #include "common/assert.h" |
| 21 | #include "common/cpu_detect.h" | ||
| 22 | #include "common/logging/log.h" | ||
| 23 | #include "common/memory_util.h" | ||
| 21 | 24 | ||
| 22 | #include "assert.h" | ||
| 23 | #include "x64_emitter.h" | ||
| 24 | #include "abi.h" | 25 | #include "abi.h" |
| 25 | #include "cpu_detect.h" | 26 | #include "emitter.h" |
| 26 | #include "memory_util.h" | ||
| 27 | 27 | ||
| 28 | #define PRIx64 "llx" | 28 | #define PRIx64 "llx" |
| 29 | 29 | ||
| @@ -164,7 +164,7 @@ void XEmitter::WriteSIB(int scale, int index, int base) | |||
| 164 | void OpArg::WriteRex(XEmitter *emit, int opBits, int bits, int customOp) const | 164 | void OpArg::WriteRex(XEmitter *emit, int opBits, int bits, int customOp) const |
| 165 | { | 165 | { |
| 166 | if (customOp == -1) customOp = operandReg; | 166 | if (customOp == -1) customOp = operandReg; |
| 167 | #ifdef _M_X86_64 | 167 | #ifdef ARCHITECTURE_X64 |
| 168 | u8 op = 0x40; | 168 | u8 op = 0x40; |
| 169 | // REX.W (whether operation is a 64-bit operation) | 169 | // REX.W (whether operation is a 64-bit operation) |
| 170 | if (opBits == 64) op |= 8; | 170 | if (opBits == 64) op |= 8; |
| @@ -236,7 +236,7 @@ void OpArg::WriteRest(XEmitter *emit, int extraBytes, X64Reg _operandReg, | |||
| 236 | _offsetOrBaseReg = 5; | 236 | _offsetOrBaseReg = 5; |
| 237 | emit->WriteModRM(0, _operandReg, _offsetOrBaseReg); | 237 | emit->WriteModRM(0, _operandReg, _offsetOrBaseReg); |
| 238 | //TODO : add some checks | 238 | //TODO : add some checks |
| 239 | #ifdef _M_X86_64 | 239 | #ifdef ARCHITECTURE_X64 |
| 240 | u64 ripAddr = (u64)emit->GetCodePtr() + 4 + extraBytes; | 240 | u64 ripAddr = (u64)emit->GetCodePtr() + 4 + extraBytes; |
| 241 | s64 distance = (s64)offset - (s64)ripAddr; | 241 | s64 distance = (s64)offset - (s64)ripAddr; |
| 242 | ASSERT_MSG( | 242 | ASSERT_MSG( |
| @@ -1463,7 +1463,7 @@ void XEmitter::MOVD_xmm(const OpArg &arg, X64Reg src) {WriteSSEOp(0x66, 0x7E, sr | |||
| 1463 | 1463 | ||
| 1464 | void XEmitter::MOVQ_xmm(X64Reg dest, OpArg arg) | 1464 | void XEmitter::MOVQ_xmm(X64Reg dest, OpArg arg) |
| 1465 | { | 1465 | { |
| 1466 | #ifdef _M_X86_64 | 1466 | #ifdef ARCHITECTURE_X64 |
| 1467 | // Alternate encoding | 1467 | // Alternate encoding |
| 1468 | // This does not display correctly in MSVC's debugger, it thinks it's a MOVD | 1468 | // This does not display correctly in MSVC's debugger, it thinks it's a MOVD |
| 1469 | arg.operandReg = dest; | 1469 | arg.operandReg = dest; |
diff --git a/src/common/x64_emitter.h b/src/common/x64/emitter.h index 369bfaa08..312e9dc19 100644 --- a/src/common/x64_emitter.h +++ b/src/common/x64/emitter.h | |||
| @@ -17,11 +17,11 @@ | |||
| 17 | 17 | ||
| 18 | #pragma once | 18 | #pragma once |
| 19 | 19 | ||
| 20 | #include "assert.h" | 20 | #include "common/assert.h" |
| 21 | #include "common_types.h" | 21 | #include "common/common_types.h" |
| 22 | #include "code_block.h" | 22 | #include "common/code_block.h" |
| 23 | 23 | ||
| 24 | #if defined(_M_X86_64) && !defined(_ARCH_64) | 24 | #if defined(ARCHITECTURE_X64) && !defined(_ARCH_64) |
| 25 | #define _ARCH_64 | 25 | #define _ARCH_64 |
| 26 | #endif | 26 | #endif |
| 27 | 27 | ||