mirror of
https://github.com/google0101-ryan/Emotional.git
synced 2024-06-23 14:43:20 -04:00
Added first instruction
This commit is contained in:
parent
1bbe22910c
commit
cb5ecc4b2a
|
@ -19,7 +19,9 @@ set(SOURCES src/main.cpp
|
|||
src/app/Application.cpp
|
||||
src/emu/memory/Bus.cpp
|
||||
src/emu/System.cpp
|
||||
src/emu/cpu/ee/EmotionEngine.cpp)
|
||||
src/emu/cpu/ee/EmotionEngine.cpp
|
||||
src/emu/cpu/ee/x64/reg_alloc.cpp
|
||||
src/emu/cpu/ee/x64/emit.cpp)
|
||||
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
|
||||
|
|
2951
src/3rdparty/xbyak/xbyak.h
vendored
Normal file
2951
src/3rdparty/xbyak/xbyak.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
258
src/3rdparty/xbyak/xbyak_bin2hex.h
vendored
Normal file
258
src/3rdparty/xbyak/xbyak_bin2hex.h
vendored
Normal file
|
@ -0,0 +1,258 @@
|
|||
enum {
|
||||
B00000000= 0,
|
||||
B00000001= 1,
|
||||
B00000010= 2,
|
||||
B00000011= 3,
|
||||
B00000100= 4,
|
||||
B00000101= 5,
|
||||
B00000110= 6,
|
||||
B00000111= 7,
|
||||
B00001000= 8,
|
||||
B00001001= 9,
|
||||
B00001010= 10,
|
||||
B00001011= 11,
|
||||
B00001100= 12,
|
||||
B00001101= 13,
|
||||
B00001110= 14,
|
||||
B00001111= 15,
|
||||
B00010000= 16,
|
||||
B00010001= 17,
|
||||
B00010010= 18,
|
||||
B00010011= 19,
|
||||
B00010100= 20,
|
||||
B00010101= 21,
|
||||
B00010110= 22,
|
||||
B00010111= 23,
|
||||
B00011000= 24,
|
||||
B00011001= 25,
|
||||
B00011010= 26,
|
||||
B00011011= 27,
|
||||
B00011100= 28,
|
||||
B00011101= 29,
|
||||
B00011110= 30,
|
||||
B00011111= 31,
|
||||
B00100000= 32,
|
||||
B00100001= 33,
|
||||
B00100010= 34,
|
||||
B00100011= 35,
|
||||
B00100100= 36,
|
||||
B00100101= 37,
|
||||
B00100110= 38,
|
||||
B00100111= 39,
|
||||
B00101000= 40,
|
||||
B00101001= 41,
|
||||
B00101010= 42,
|
||||
B00101011= 43,
|
||||
B00101100= 44,
|
||||
B00101101= 45,
|
||||
B00101110= 46,
|
||||
B00101111= 47,
|
||||
B00110000= 48,
|
||||
B00110001= 49,
|
||||
B00110010= 50,
|
||||
B00110011= 51,
|
||||
B00110100= 52,
|
||||
B00110101= 53,
|
||||
B00110110= 54,
|
||||
B00110111= 55,
|
||||
B00111000= 56,
|
||||
B00111001= 57,
|
||||
B00111010= 58,
|
||||
B00111011= 59,
|
||||
B00111100= 60,
|
||||
B00111101= 61,
|
||||
B00111110= 62,
|
||||
B00111111= 63,
|
||||
B01000000= 64,
|
||||
B01000001= 65,
|
||||
B01000010= 66,
|
||||
B01000011= 67,
|
||||
B01000100= 68,
|
||||
B01000101= 69,
|
||||
B01000110= 70,
|
||||
B01000111= 71,
|
||||
B01001000= 72,
|
||||
B01001001= 73,
|
||||
B01001010= 74,
|
||||
B01001011= 75,
|
||||
B01001100= 76,
|
||||
B01001101= 77,
|
||||
B01001110= 78,
|
||||
B01001111= 79,
|
||||
B01010000= 80,
|
||||
B01010001= 81,
|
||||
B01010010= 82,
|
||||
B01010011= 83,
|
||||
B01010100= 84,
|
||||
B01010101= 85,
|
||||
B01010110= 86,
|
||||
B01010111= 87,
|
||||
B01011000= 88,
|
||||
B01011001= 89,
|
||||
B01011010= 90,
|
||||
B01011011= 91,
|
||||
B01011100= 92,
|
||||
B01011101= 93,
|
||||
B01011110= 94,
|
||||
B01011111= 95,
|
||||
B01100000= 96,
|
||||
B01100001= 97,
|
||||
B01100010= 98,
|
||||
B01100011= 99,
|
||||
B01100100= 100,
|
||||
B01100101= 101,
|
||||
B01100110= 102,
|
||||
B01100111= 103,
|
||||
B01101000= 104,
|
||||
B01101001= 105,
|
||||
B01101010= 106,
|
||||
B01101011= 107,
|
||||
B01101100= 108,
|
||||
B01101101= 109,
|
||||
B01101110= 110,
|
||||
B01101111= 111,
|
||||
B01110000= 112,
|
||||
B01110001= 113,
|
||||
B01110010= 114,
|
||||
B01110011= 115,
|
||||
B01110100= 116,
|
||||
B01110101= 117,
|
||||
B01110110= 118,
|
||||
B01110111= 119,
|
||||
B01111000= 120,
|
||||
B01111001= 121,
|
||||
B01111010= 122,
|
||||
B01111011= 123,
|
||||
B01111100= 124,
|
||||
B01111101= 125,
|
||||
B01111110= 126,
|
||||
B01111111= 127,
|
||||
B10000000= 128,
|
||||
B10000001= 129,
|
||||
B10000010= 130,
|
||||
B10000011= 131,
|
||||
B10000100= 132,
|
||||
B10000101= 133,
|
||||
B10000110= 134,
|
||||
B10000111= 135,
|
||||
B10001000= 136,
|
||||
B10001001= 137,
|
||||
B10001010= 138,
|
||||
B10001011= 139,
|
||||
B10001100= 140,
|
||||
B10001101= 141,
|
||||
B10001110= 142,
|
||||
B10001111= 143,
|
||||
B10010000= 144,
|
||||
B10010001= 145,
|
||||
B10010010= 146,
|
||||
B10010011= 147,
|
||||
B10010100= 148,
|
||||
B10010101= 149,
|
||||
B10010110= 150,
|
||||
B10010111= 151,
|
||||
B10011000= 152,
|
||||
B10011001= 153,
|
||||
B10011010= 154,
|
||||
B10011011= 155,
|
||||
B10011100= 156,
|
||||
B10011101= 157,
|
||||
B10011110= 158,
|
||||
B10011111= 159,
|
||||
B10100000= 160,
|
||||
B10100001= 161,
|
||||
B10100010= 162,
|
||||
B10100011= 163,
|
||||
B10100100= 164,
|
||||
B10100101= 165,
|
||||
B10100110= 166,
|
||||
B10100111= 167,
|
||||
B10101000= 168,
|
||||
B10101001= 169,
|
||||
B10101010= 170,
|
||||
B10101011= 171,
|
||||
B10101100= 172,
|
||||
B10101101= 173,
|
||||
B10101110= 174,
|
||||
B10101111= 175,
|
||||
B10110000= 176,
|
||||
B10110001= 177,
|
||||
B10110010= 178,
|
||||
B10110011= 179,
|
||||
B10110100= 180,
|
||||
B10110101= 181,
|
||||
B10110110= 182,
|
||||
B10110111= 183,
|
||||
B10111000= 184,
|
||||
B10111001= 185,
|
||||
B10111010= 186,
|
||||
B10111011= 187,
|
||||
B10111100= 188,
|
||||
B10111101= 189,
|
||||
B10111110= 190,
|
||||
B10111111= 191,
|
||||
B11000000= 192,
|
||||
B11000001= 193,
|
||||
B11000010= 194,
|
||||
B11000011= 195,
|
||||
B11000100= 196,
|
||||
B11000101= 197,
|
||||
B11000110= 198,
|
||||
B11000111= 199,
|
||||
B11001000= 200,
|
||||
B11001001= 201,
|
||||
B11001010= 202,
|
||||
B11001011= 203,
|
||||
B11001100= 204,
|
||||
B11001101= 205,
|
||||
B11001110= 206,
|
||||
B11001111= 207,
|
||||
B11010000= 208,
|
||||
B11010001= 209,
|
||||
B11010010= 210,
|
||||
B11010011= 211,
|
||||
B11010100= 212,
|
||||
B11010101= 213,
|
||||
B11010110= 214,
|
||||
B11010111= 215,
|
||||
B11011000= 216,
|
||||
B11011001= 217,
|
||||
B11011010= 218,
|
||||
B11011011= 219,
|
||||
B11011100= 220,
|
||||
B11011101= 221,
|
||||
B11011110= 222,
|
||||
B11011111= 223,
|
||||
B11100000= 224,
|
||||
B11100001= 225,
|
||||
B11100010= 226,
|
||||
B11100011= 227,
|
||||
B11100100= 228,
|
||||
B11100101= 229,
|
||||
B11100110= 230,
|
||||
B11100111= 231,
|
||||
B11101000= 232,
|
||||
B11101001= 233,
|
||||
B11101010= 234,
|
||||
B11101011= 235,
|
||||
B11101100= 236,
|
||||
B11101101= 237,
|
||||
B11101110= 238,
|
||||
B11101111= 239,
|
||||
B11110000= 240,
|
||||
B11110001= 241,
|
||||
B11110010= 242,
|
||||
B11110011= 243,
|
||||
B11110100= 244,
|
||||
B11110101= 245,
|
||||
B11110110= 246,
|
||||
B11110111= 247,
|
||||
B11111000= 248,
|
||||
B11111001= 249,
|
||||
B11111010= 250,
|
||||
B11111011= 251,
|
||||
B11111100= 252,
|
||||
B11111101= 253,
|
||||
B11111110= 254,
|
||||
B11111111= 255
|
||||
};
|
2331
src/3rdparty/xbyak/xbyak_mnemonic.h
vendored
Normal file
2331
src/3rdparty/xbyak/xbyak_mnemonic.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
1000
src/3rdparty/xbyak/xbyak_util.h
vendored
Normal file
1000
src/3rdparty/xbyak/xbyak_util.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
|
@ -48,4 +48,6 @@ void Application::Exit(int code)
|
|||
}
|
||||
|
||||
void Application::Exit()
|
||||
{}
|
||||
{
|
||||
System::Dump();
|
||||
}
|
|
@ -35,4 +35,9 @@ void System::Run()
|
|||
{
|
||||
while (1)
|
||||
EmotionEngine::Clock();
|
||||
}
|
||||
}
|
||||
|
||||
void System::Dump()
|
||||
{
|
||||
EmotionEngine::Dump();
|
||||
}
|
||||
|
|
|
@ -11,5 +11,6 @@ void LoadBios(std::string biosName);
|
|||
|
||||
void Reset();
|
||||
void Run();
|
||||
void Dump();
|
||||
|
||||
}
|
|
@ -1,55 +1,34 @@
|
|||
#include "EmotionEngine.h"
|
||||
#include <emu/memory/Bus.h>
|
||||
#include <emu/cpu/ee/x64/emit.h>
|
||||
|
||||
namespace EE_JIT
|
||||
{
|
||||
|
||||
enum IRInstrs
|
||||
void JIT::EmitBNE(uint32_t instr, EE_JIT::IRInstruction &i)
|
||||
{
|
||||
MOV = 0,
|
||||
NOP = 0,
|
||||
SLTI = 0,
|
||||
};
|
||||
printf("bne\n");
|
||||
|
||||
struct IRValue
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
Imm,
|
||||
Reg,
|
||||
Cop0Reg,
|
||||
FP
|
||||
};
|
||||
private:
|
||||
union
|
||||
{
|
||||
uint32_t imm;
|
||||
int register_num;
|
||||
float fp_value;
|
||||
int cop_regnum;
|
||||
} value;
|
||||
int rt = (instr >> 16) & 0x1F;
|
||||
int rs = (instr >> 21) & 0x1F;
|
||||
|
||||
Type type;
|
||||
public:
|
||||
IRValue(Type type)
|
||||
: type(type) {}
|
||||
IRValue dest = IRValue(IRValue::Reg);
|
||||
IRValue source = IRValue(IRValue::Reg);
|
||||
IRValue imm = IRValue(IRValue::Imm);
|
||||
|
||||
bool IsImm() {return type == Imm;}
|
||||
// Can be used for guest and COP0 registers
|
||||
void SetReg(uint32_t reg) {value.register_num = reg;}
|
||||
void SetImm(uint16_t imm) {value.imm = (int32_t)(int16_t)imm;}
|
||||
};
|
||||
source.SetReg(rs);
|
||||
dest.SetReg(rt);
|
||||
imm.SetImm(instr & 0xffff);
|
||||
|
||||
struct IRInstruction
|
||||
{
|
||||
uint8_t instr;
|
||||
// Arguments are right -> left
|
||||
std::vector<IRValue> args;
|
||||
};
|
||||
i = IRInstruction::Build({dest, source, imm}, IRInstrs::BranchConditional);
|
||||
i.b_type = IRInstruction::BranchType::NE;
|
||||
cur_block->ir.push_back(i);
|
||||
}
|
||||
|
||||
void JIT::EmitSLTI(uint32_t instr, EE_JIT::IRInstruction &i)
|
||||
{
|
||||
printf("slti\n");
|
||||
|
||||
int rt = (instr >> 16) & 0x1F;
|
||||
int rs = (instr >> 21) & 0x1F;
|
||||
|
||||
|
@ -60,10 +39,7 @@ void JIT::EmitSLTI(uint32_t instr, EE_JIT::IRInstruction &i)
|
|||
dest.SetReg(rt);
|
||||
imm.SetImm(instr & 0xffff);
|
||||
|
||||
i.instr = IRInstrs::SLTI;
|
||||
i.args.push_back(imm);
|
||||
i.args.push_back(source);
|
||||
i.args.push_back(dest);
|
||||
i = IRInstruction::Build({dest, source, imm}, IRInstrs::SLTI);
|
||||
|
||||
cur_block->ir.push_back(i);
|
||||
}
|
||||
|
@ -87,6 +63,8 @@ void JIT::EmitCOP0(uint32_t instr, EE_JIT::IRInstruction &i)
|
|||
|
||||
void JIT::EmitMFC0(uint32_t instr, EE_JIT::IRInstruction& i)
|
||||
{
|
||||
printf("mfc0\n");
|
||||
|
||||
int rd = (instr >> 11) & 0x1F;
|
||||
int rt = (instr >> 16) & 0x1F;
|
||||
|
||||
|
@ -95,25 +73,19 @@ void JIT::EmitMFC0(uint32_t instr, EE_JIT::IRInstruction& i)
|
|||
|
||||
dest.SetReg(rd);
|
||||
src.SetReg(rt);
|
||||
|
||||
i.instr = IRInstrs::MOV;
|
||||
i.args.push_back(src);
|
||||
i.args.push_back(dest);
|
||||
|
||||
i = IRInstruction::Build({dest, src}, IRInstrs::MOV);
|
||||
|
||||
cur_block->ir.push_back(i);
|
||||
}
|
||||
|
||||
void JIT::EmitIR(uint32_t instr)
|
||||
{
|
||||
if (!cur_block)
|
||||
{
|
||||
cur_block = new Block;
|
||||
}
|
||||
|
||||
EE_JIT::IRInstruction current_instruction;
|
||||
|
||||
if (instr == 0)
|
||||
{
|
||||
printf("nop\n");
|
||||
current_instruction.instr = NOP;
|
||||
cur_block->ir.push_back(current_instruction);
|
||||
return;
|
||||
|
@ -123,6 +95,9 @@ void JIT::EmitIR(uint32_t instr)
|
|||
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x05:
|
||||
EmitBNE(instr, current_instruction);
|
||||
break;
|
||||
case 0x0A:
|
||||
EmitSLTI(instr, current_instruction);
|
||||
break;
|
||||
|
@ -135,6 +110,26 @@ void JIT::EmitIR(uint32_t instr)
|
|||
}
|
||||
}
|
||||
|
||||
void JIT::EmitPrequel()
|
||||
{
|
||||
if (!cur_block)
|
||||
{
|
||||
cur_block = new Block;
|
||||
}
|
||||
|
||||
auto i = IRInstruction::Build({}, IRInstrs::SaveHostRegs);
|
||||
cur_block->ir.push_back(i);
|
||||
}
|
||||
|
||||
void JIT::EmitDone()
|
||||
{
|
||||
auto i = IRInstruction::Build({}, IRInstrs::RestoreHostRegs);
|
||||
cur_block->ir.push_back(i);
|
||||
|
||||
blockCache.push_back(cur_block);
|
||||
EE_JIT::emit->TranslateBlock(cur_block);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
EE_JIT::JIT jit;
|
||||
|
@ -149,15 +144,53 @@ void Reset()
|
|||
|
||||
state.pc = 0xBFC00000;
|
||||
state.next_pc = 0xBFC00004;
|
||||
|
||||
EE_JIT::emit = new EE_JIT::Emitter();
|
||||
}
|
||||
|
||||
bool IsBranch(uint32_t instr)
|
||||
{
|
||||
uint8_t opcode = (instr >> 26) & 0x3F;
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x05:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Clock()
|
||||
{
|
||||
uint32_t instr = Bus::Read32(state.pc);
|
||||
state.pc = state.next_pc;
|
||||
state.next_pc += 4;
|
||||
jit.EmitPrequel();
|
||||
|
||||
jit.EmitIR(instr);
|
||||
bool isBranch = false;
|
||||
bool isBranchDelayed = false;
|
||||
|
||||
do
|
||||
{
|
||||
uint32_t instr = Bus::Read32(state.pc);
|
||||
state.pc = state.next_pc;
|
||||
state.next_pc += 4;
|
||||
|
||||
jit.EmitIR(instr);
|
||||
|
||||
isBranch = isBranchDelayed;
|
||||
isBranchDelayed = IsBranch(instr);
|
||||
} while (!isBranch);
|
||||
|
||||
jit.EmitDone();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void Dump()
|
||||
{
|
||||
EE_JIT::emit->Dump();
|
||||
}
|
||||
|
||||
ProcessorState* GetState()
|
||||
{
|
||||
return &state;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,26 +7,95 @@
|
|||
namespace EE_JIT
|
||||
{
|
||||
|
||||
struct IRInstruction;
|
||||
enum IRInstrs
|
||||
{
|
||||
MOV = 0,
|
||||
NOP = 1,
|
||||
SLTI = 2,
|
||||
SaveHostRegs = 3,
|
||||
RestoreHostRegs = 4,
|
||||
BranchConditional = 5,
|
||||
};
|
||||
|
||||
struct IRValue
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
Imm,
|
||||
Reg,
|
||||
Cop0Reg,
|
||||
FP
|
||||
};
|
||||
private:
|
||||
union
|
||||
{
|
||||
uint32_t imm;
|
||||
int register_num;
|
||||
float fp_value;
|
||||
int cop_regnum;
|
||||
} value;
|
||||
|
||||
Type type;
|
||||
public:
|
||||
IRValue(Type type)
|
||||
: type(type) {}
|
||||
|
||||
bool IsImm() {return type == Imm;}
|
||||
bool IsCop0() {return type == Cop0Reg;}
|
||||
// Can be used for guest and COP0 registers
|
||||
void SetReg(uint32_t reg) {value.register_num = reg;}
|
||||
void SetImm(uint16_t imm) {value.imm = (int32_t)(int16_t)imm;}
|
||||
|
||||
uint32_t GetImm() {return value.imm;}
|
||||
uint32_t GetReg() {return value.register_num;}
|
||||
};
|
||||
|
||||
struct IRInstruction
|
||||
{
|
||||
uint8_t instr;
|
||||
// Arguments are right -> left
|
||||
std::vector<IRValue> args;
|
||||
|
||||
enum BranchType
|
||||
{
|
||||
NE = 0,
|
||||
} b_type;
|
||||
|
||||
static IRInstruction Build(std::vector<IRValue> args, uint8_t i_type)
|
||||
{
|
||||
IRInstruction i;
|
||||
i.instr = i_type;
|
||||
i.args = args;
|
||||
|
||||
return i;
|
||||
}
|
||||
};
|
||||
|
||||
struct Block
|
||||
{
|
||||
uint32_t guest_start;
|
||||
std::vector<IRInstruction> ir;
|
||||
};
|
||||
|
||||
class JIT
|
||||
{
|
||||
private:
|
||||
struct Block
|
||||
{
|
||||
uint32_t guest_start;
|
||||
std::vector<IRInstruction> ir;
|
||||
};
|
||||
|
||||
Block* cur_block;
|
||||
std::vector<Block*> blockCache;
|
||||
|
||||
void EmitSLTI(uint32_t instr, EE_JIT::IRInstruction& i);
|
||||
void EmitCOP0(uint32_t instr, EE_JIT::IRInstruction& i);
|
||||
void EmitBNE(uint32_t instr, EE_JIT::IRInstruction& i); // 0x05
|
||||
void EmitSLTI(uint32_t instr, EE_JIT::IRInstruction& i); // 0x0A
|
||||
void EmitCOP0(uint32_t instr, EE_JIT::IRInstruction& i); // 0x10
|
||||
|
||||
|
||||
void EmitMFC0(uint32_t instr, EE_JIT::IRInstruction& i);
|
||||
public:
|
||||
void EmitIR(uint32_t instr);
|
||||
|
||||
void EmitPrequel();
|
||||
void EmitDone();
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -37,10 +106,13 @@ namespace EmotionEngine
|
|||
struct ProcessorState
|
||||
{
|
||||
uint128_t regs[32];
|
||||
uint32_t cop0_regs[32];
|
||||
uint32_t pc, next_pc;
|
||||
};
|
||||
|
||||
void Reset();
|
||||
void Clock();
|
||||
void Dump();
|
||||
ProcessorState* GetState();
|
||||
|
||||
}
|
98
src/emu/cpu/ee/x64/emit.cpp
Normal file
98
src/emu/cpu/ee/x64/emit.cpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include "emit.h"
|
||||
#include <sys/mman.h>
|
||||
#include <emu/cpu/ee/EmotionEngine.h>
|
||||
#include <fstream>
|
||||
|
||||
EE_JIT::Emitter* EE_JIT::emit;
|
||||
|
||||
void EE_JIT::Emitter::EmitMov(IRInstruction i)
|
||||
{
|
||||
if (i.args[1].IsImm()) // Lui
|
||||
{
|
||||
Xbyak::Reg64 reg_ptr = Xbyak::Reg64(reg_alloc->AllocHostRegister());
|
||||
auto offset = ((offsetof(EmotionEngine::ProcessorState, regs)) + (i.args[1].GetReg() * sizeof(uint128_t) + offsetof(uint128_t, u32)));
|
||||
cg->lea(reg_ptr, cg->ptr[cg->rax + offset]);
|
||||
cg->mov(cg->dword[reg_ptr], i.args[0].GetImm());
|
||||
}
|
||||
else if (i.args[1].IsCop0()) // Mfc0
|
||||
{
|
||||
Xbyak::Reg64 ee_reg_ptr = Xbyak::Reg64(reg_alloc->AllocHostRegister());
|
||||
Xbyak::Reg64 cop_reg_ptr = Xbyak::Reg64(reg_alloc->AllocHostRegister());
|
||||
Xbyak::Reg64 ee_reg_value = Xbyak::Reg64(reg_alloc->AllocHostRegister());
|
||||
auto dest_offset = ((offsetof(EmotionEngine::ProcessorState, regs)) + (i.args[0].GetReg() * sizeof(uint128_t) + offsetof(uint128_t, u32)));
|
||||
auto src_offset = ((offsetof(EmotionEngine::ProcessorState, cop0_regs)) + (i.args[1].GetReg() * sizeof(uint32_t)));
|
||||
cg->lea(cop_reg_ptr, cg->ptr[cg->rax + src_offset]);
|
||||
cg->mov(ee_reg_value, cg->dword[cop_reg_ptr]);
|
||||
cg->lea(ee_reg_ptr, cg->ptr[cg->rax + dest_offset]);
|
||||
cg->mov(cg->dword[ee_reg_ptr], ee_reg_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[emu/JIT]: Unknown MOV format\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void EE_JIT::Emitter::EmitSaveHostRegs()
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
if (i != 4)
|
||||
cg->push(Xbyak::Reg64(i));
|
||||
|
||||
cg->mov(cg->rbp, reinterpret_cast<uint64_t>(EmotionEngine::GetState()));
|
||||
}
|
||||
|
||||
void EE_JIT::Emitter::EmitIR(IRInstruction i)
|
||||
{
|
||||
reg_alloc->Reset();
|
||||
|
||||
switch (i.instr)
|
||||
{
|
||||
case SaveHostRegs:
|
||||
EmitSaveHostRegs();
|
||||
break;
|
||||
case MOV:
|
||||
EmitMov(i);
|
||||
break;
|
||||
default:
|
||||
printf("[JIT/Emit]: Unknown IR instruction 0x%02x\n", i.instr);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
EE_JIT::Emitter::Emitter()
|
||||
{
|
||||
base = (uint8_t*)mmap(nullptr, 0xffffffff, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
if (base == MAP_FAILED)
|
||||
{
|
||||
printf("[JIT/Emit]: Failed to map base! %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cg = new Xbyak::CodeGenerator(0xffffff, (void*)base);
|
||||
reg_alloc = new RegisterAllocator();
|
||||
reg_alloc->Reset();
|
||||
}
|
||||
|
||||
void EE_JIT::Emitter::Dump()
|
||||
{
|
||||
std::ofstream dump("out.bin");
|
||||
for (size_t i = 0; i < cg->getSize(); i++)
|
||||
{
|
||||
dump << cg->getCode()[i];
|
||||
}
|
||||
|
||||
dump.flush();
|
||||
dump.close();
|
||||
|
||||
munmap(base, 0xffffffff);
|
||||
}
|
||||
|
||||
void EE_JIT::Emitter::TranslateBlock(Block *block)
|
||||
{
|
||||
for (auto& i : block->ir)
|
||||
{
|
||||
EmitIR(i);
|
||||
}
|
||||
}
|
31
src/emu/cpu/ee/x64/emit.h
Normal file
31
src/emu/cpu/ee/x64/emit.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <emu/cpu/ee/x64/reg_alloc.h>
|
||||
#include <3rdparty/xbyak/xbyak.h>
|
||||
|
||||
namespace EE_JIT
|
||||
{
|
||||
|
||||
struct Block;
|
||||
struct IRInstruction;
|
||||
|
||||
class Emitter
|
||||
{
|
||||
private:
|
||||
Xbyak::CodeGenerator* cg;
|
||||
uint8_t* base;
|
||||
RegisterAllocator* reg_alloc;
|
||||
|
||||
void EmitSaveHostRegs();
|
||||
void EmitMov(IRInstruction i);
|
||||
void EmitIR(IRInstruction i);
|
||||
public:
|
||||
Emitter();
|
||||
void Dump();
|
||||
void TranslateBlock(Block* block);
|
||||
};
|
||||
|
||||
extern Emitter* emit;
|
||||
|
||||
}
|
31
src/emu/cpu/ee/x64/reg_alloc.cpp
Normal file
31
src/emu/cpu/ee/x64/reg_alloc.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include "reg_alloc.h"
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
RegisterAllocator::RegisterAllocator()
|
||||
{
|
||||
Reset();
|
||||
// Here just in case I have to do any initialization in the future
|
||||
}
|
||||
|
||||
void RegisterAllocator::Reset()
|
||||
{
|
||||
used_registers.fill(false);
|
||||
used_registers_8.fill(false);
|
||||
used_registers[RBP] = true;
|
||||
}
|
||||
|
||||
int RegisterAllocator::AllocHostRegister()
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (!used_registers[i])
|
||||
{
|
||||
used_registers[i] = true;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
printf("[JIT/RegAlloc]: Ran out of host registers!\n");
|
||||
exit(1);
|
||||
}
|
29
src/emu/cpu/ee/x64/reg_alloc.h
Normal file
29
src/emu/cpu/ee/x64/reg_alloc.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
|
||||
class RegisterAllocator
|
||||
{
|
||||
private:
|
||||
std::array<bool, 8> used_registers;
|
||||
// Due to how 8-bit registers map, we have a seperate array
|
||||
std::array<bool, 8> used_registers_8;
|
||||
|
||||
enum HostRegisters64
|
||||
{
|
||||
RAX,
|
||||
RCX,
|
||||
RDX,
|
||||
RBX,
|
||||
RSP,
|
||||
RBP,
|
||||
RSI,
|
||||
RDI
|
||||
};
|
||||
public:
|
||||
RegisterAllocator();
|
||||
void Reset();
|
||||
|
||||
int AllocHostRegister();
|
||||
};
|
Loading…
Reference in a new issue