From edb3aabdd4c3c2bcb1626f5041f25feaaf2e61dd Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Sat, 25 May 2013 04:28:21 -0700 Subject: [PATCH] Removing llvm backend. --- src/xenia/cpu/llvmbe/emit.h | 41 - src/xenia/cpu/llvmbe/emit_alu.cc | 1085 --------------- src/xenia/cpu/llvmbe/emit_control.cc | 713 ---------- src/xenia/cpu/llvmbe/emit_fpu.cc | 296 ----- src/xenia/cpu/llvmbe/emit_memory.cc | 1170 ----------------- src/xenia/cpu/llvmbe/emitter_context.cc | 1103 ---------------- src/xenia/cpu/llvmbe/emitter_context.h | 146 -- src/xenia/cpu/llvmbe/llvm_backend.cc | 78 -- src/xenia/cpu/llvmbe/llvm_backend.h | 43 - .../cpu/llvmbe/llvm_code_unit_builder.cc | 264 ---- src/xenia/cpu/llvmbe/llvm_code_unit_builder.h | 77 -- src/xenia/cpu/llvmbe/llvm_exports.cc | 96 -- src/xenia/cpu/llvmbe/llvm_exports.h | 42 - src/xenia/cpu/llvmbe/llvm_jit.cc | 211 --- src/xenia/cpu/llvmbe/llvm_jit.h | 64 - src/xenia/cpu/llvmbe/llvm_library_linker.cc | 24 - src/xenia/cpu/llvmbe/llvm_library_linker.h | 37 - src/xenia/cpu/llvmbe/llvm_library_loader.cc | 24 - src/xenia/cpu/llvmbe/llvm_library_loader.h | 37 - src/xenia/cpu/llvmbe/sources.gypi | 24 - 20 files changed, 5575 deletions(-) delete mode 100644 src/xenia/cpu/llvmbe/emit.h delete mode 100644 src/xenia/cpu/llvmbe/emit_alu.cc delete mode 100644 src/xenia/cpu/llvmbe/emit_control.cc delete mode 100644 src/xenia/cpu/llvmbe/emit_fpu.cc delete mode 100644 src/xenia/cpu/llvmbe/emit_memory.cc delete mode 100644 src/xenia/cpu/llvmbe/emitter_context.cc delete mode 100644 src/xenia/cpu/llvmbe/emitter_context.h delete mode 100644 src/xenia/cpu/llvmbe/llvm_backend.cc delete mode 100644 src/xenia/cpu/llvmbe/llvm_backend.h delete mode 100644 src/xenia/cpu/llvmbe/llvm_code_unit_builder.cc delete mode 100644 src/xenia/cpu/llvmbe/llvm_code_unit_builder.h delete mode 100644 src/xenia/cpu/llvmbe/llvm_exports.cc delete mode 100644 src/xenia/cpu/llvmbe/llvm_exports.h delete mode 100644 src/xenia/cpu/llvmbe/llvm_jit.cc delete mode 100644 src/xenia/cpu/llvmbe/llvm_jit.h delete mode 100644 src/xenia/cpu/llvmbe/llvm_library_linker.cc delete mode 100644 src/xenia/cpu/llvmbe/llvm_library_linker.h delete mode 100644 src/xenia/cpu/llvmbe/llvm_library_loader.cc delete mode 100644 src/xenia/cpu/llvmbe/llvm_library_loader.h delete mode 100644 src/xenia/cpu/llvmbe/sources.gypi diff --git a/src/xenia/cpu/llvmbe/emit.h b/src/xenia/cpu/llvmbe/emit.h deleted file mode 100644 index f1b8a322e..000000000 --- a/src/xenia/cpu/llvmbe/emit.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_CPU_LLVMBE_EMIT_H_ -#define XENIA_CPU_LLVMBE_EMIT_H_ - -#include - - -namespace xe { -namespace cpu { -namespace llvmbe { - - -void RegisterEmitCategoryALU(); -void RegisterEmitCategoryControl(); -void RegisterEmitCategoryFPU(); -void RegisterEmitCategoryMemory(); - - -#define XEEMITTER(name, opcode, format) int InstrEmit_##name - -#define XEREGISTERINSTR(name, opcode) \ - RegisterInstrEmit(opcode, (InstrEmitFn)InstrEmit_##name); - -#define XEINSTRNOTIMPLEMENTED() -//#define XEINSTRNOTIMPLEMENTED XEASSERTALWAYS - - -} // namespace llvmbe -} // namespace cpu -} // namespace xe - - -#endif // XENIA_CPU_LLVMBE_EMIT_H_ diff --git a/src/xenia/cpu/llvmbe/emit_alu.cc b/src/xenia/cpu/llvmbe/emit_alu.cc deleted file mode 100644 index a6fb39293..000000000 --- a/src/xenia/cpu/llvmbe/emit_alu.cc +++ /dev/null @@ -1,1085 +0,0 @@ -/* - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - -#include - -#include - - -using namespace llvm; -using namespace xe::cpu; -using namespace xe::cpu::ppc; - - -namespace xe { -namespace cpu { -namespace llvmbe { - - -// Integer arithmetic (A-3) - -XEEMITTER(addx, 0x7C000214, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RD <- (RA) + (RB) - - if (i.XO.OE) { - // With XER update. - // This is a different codepath as we need to use llvm.sadd.with.overflow. - - Function* sadd_with_overflow = Intrinsic::getDeclaration( - e.gen_module(), Intrinsic::sadd_with_overflow, b.getInt64Ty()); - Value* v = b.CreateCall2(sadd_with_overflow, - e.gpr_value(i.XO.RA), e.gpr_value(i.XO.RB)); - Value* v0 = b.CreateExtractValue(v, 0); - e.update_gpr_value(i.XO.RT, v0); - e.update_xer_with_overflow(b.CreateExtractValue(v, 1)); - - if (i.XO.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v0, b.getInt64(0), true); - } - - return 0; - } else { - // No OE bit setting. - Value* v = b.CreateAdd(e.gpr_value(i.XO.RA), e.gpr_value(i.XO.RB)); - e.update_gpr_value(i.XO.RT, v); - - if (i.XO.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - } - - return 0; - } -} - -XEEMITTER(addcx, 0x7C000014, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(addex, 0x7C000114, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(addi, 0x38000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // RT <- EXTS(SI) - // else - // RT <- (RA) + EXTS(SI) - - Value* v = b.getInt64(XEEXTS16(i.D.DS)); - if (i.D.RA) { - v = b.CreateAdd(e.gpr_value(i.D.RA), v); - } - e.update_gpr_value(i.D.RT, v); - - return 0; -} - -XEEMITTER(addic, 0x30000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RT <- (RA) + EXTS(SI) - - Function* sadd_with_overflow = Intrinsic::getDeclaration( - e.gen_module(), Intrinsic::sadd_with_overflow, b.getInt64Ty()); - Value* v = b.CreateCall2(sadd_with_overflow, - e.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); - e.update_gpr_value(i.D.RT, b.CreateExtractValue(v, 0)); - e.update_xer_with_carry(b.CreateExtractValue(v, 1)); - - return 0; -} - -XEEMITTER(addicx, 0x34000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(addis, 0x3C000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // RT <- EXTS(SI) || i16.0 - // else - // RT <- (RA) + EXTS(SI) || i16.0 - - Value* v = b.getInt64(XEEXTS16(i.D.DS) << 16); - if (i.D.RA) { - v = b.CreateAdd(e.gpr_value(i.D.RA), v); - } - e.update_gpr_value(i.D.RT, v); - - return 0; -} - -XEEMITTER(addmex, 0x7C0001D4, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(addzex, 0x7C000194, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RT <- (RA) + CA - - Function* sadd_with_overflow = Intrinsic::getDeclaration( - e.gen_module(), Intrinsic::sadd_with_overflow, b.getInt64Ty()); - Value* ca = b.CreateAnd(b.CreateLShr(e.xer_value(), 29), 0x1); - Value* v = b.CreateCall2(sadd_with_overflow, - e.gpr_value(i.XO.RA), ca); - Value* add_value = b.CreateExtractValue(v, 0); - e.update_gpr_value(i.XO.RT, add_value); - if (i.XO.OE) { - // With XER[SO] update too. - e.update_xer_with_overflow_and_carry(b.CreateExtractValue(v, 1)); - } else { - // Just CA update. - e.update_xer_with_carry(b.CreateExtractValue(v, 1)); - } - - if (i.XO.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, add_value, b.getInt64(0), true); - } - - return 0; -} - -XEEMITTER(divdx, 0x7C0003D2, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(divdux, 0x7C000392, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(divwx, 0x7C0003D6, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // dividend[0:31] <- (RA)[32:63] - // divisor[0:31] <- (RB)[32:63] - // if divisor = 0 then - // if OE = 1 then - // XER[OV] <- 1 - // return - // RT[32:63] <- dividend ÷ divisor - // RT[0:31] <- undefined - - Value* dividend = b.CreateTrunc(e.gpr_value(i.XO.RA), b.getInt32Ty()); - Value* divisor = b.CreateTrunc(e.gpr_value(i.XO.RB), b.getInt32Ty()); - - // Note that we skip the zero handling block and just avoid the divide if - // we are OE=0. - BasicBlock* zero_bb = i.XO.OE ? - BasicBlock::Create(*e.context(), "", e.gen_fn()) : NULL; - BasicBlock* nonzero_bb = BasicBlock::Create(*e.context(), "", e.gen_fn()); - BasicBlock* after_bb = BasicBlock::Create(*e.context(), "", e.gen_fn()); - b.CreateCondBr(b.CreateICmpEQ(divisor, b.getInt32(0)), - i.XO.OE ? zero_bb : after_bb, nonzero_bb); - - if (zero_bb) { - // Divisor was zero - do XER update. - b.SetInsertPoint(zero_bb); - e.update_xer_with_overflow(b.getInt1(1)); - b.CreateBr(after_bb); - } - - // Divide. - b.SetInsertPoint(nonzero_bb); - Value* v = b.CreateSDiv(dividend, divisor); - v = b.CreateSExt(v, b.getInt64Ty()); - e.update_gpr_value(i.XO.RT, v); - - // If we are OE=1 we need to clear the overflow bit. - if (i.XO.OE) { - e.update_xer_with_overflow(b.getInt1(0)); - } - - if (i.XO.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - } - - b.CreateBr(after_bb); - - // Resume. - b.SetInsertPoint(after_bb); - - return 0; -} - -XEEMITTER(divwux, 0x7C000396, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // dividend[0:31] <- (RA)[32:63] - // divisor[0:31] <- (RB)[32:63] - // if divisor = 0 then - // if OE = 1 then - // XER[OV] <- 1 - // return - // RT[32:63] <- dividend ÷ divisor - // RT[0:31] <- undefined - - Value* dividend = b.CreateTrunc(e.gpr_value(i.XO.RA), b.getInt32Ty()); - Value* divisor = b.CreateTrunc(e.gpr_value(i.XO.RB), b.getInt32Ty()); - - // Note that we skip the zero handling block and just avoid the divide if - // we are OE=0. - BasicBlock* zero_bb = i.XO.OE ? - BasicBlock::Create(*e.context(), "", e.gen_fn()) : NULL; - BasicBlock* nonzero_bb = BasicBlock::Create(*e.context(), "", e.gen_fn()); - BasicBlock* after_bb = BasicBlock::Create(*e.context(), "", e.gen_fn()); - b.CreateCondBr(b.CreateICmpEQ(divisor, b.getInt32(0)), - i.XO.OE ? zero_bb : after_bb, nonzero_bb); - - if (zero_bb) { - // Divisor was zero - do XER update. - b.SetInsertPoint(zero_bb); - e.update_xer_with_overflow(b.getInt1(1)); - b.CreateBr(after_bb); - } - - // Divide. - b.SetInsertPoint(nonzero_bb); - Value* v = b.CreateUDiv(dividend, divisor); - v = b.CreateZExt(v, b.getInt64Ty()); - e.update_gpr_value(i.XO.RT, v); - - // If we are OE=1 we need to clear the overflow bit. - if (i.XO.OE) { - e.update_xer_with_overflow(b.getInt1(0)); - } - - if (i.XO.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - } - - b.CreateBr(after_bb); - - // Resume. - b.SetInsertPoint(after_bb); - - return 0; -} - -XEEMITTER(mulhdx, 0x7C000092, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(mulhdux, 0x7C000012, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(mulhwx, 0x7C000096, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(mulhwux, 0x7C000016, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(mulldx, 0x7C0001D2, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(mulli, 0x1C000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // prod[0:127] <- (RA) × EXTS(SI) - // RT <- prod[64:127] - - // TODO(benvanik): ensure this has the right behavior when the value - // overflows. It should be truncating the result, but I'm not sure what LLVM - // does. - - Value* v = b.CreateMul(e.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); - e.update_gpr_value(i.D.RT, b.CreateTrunc(v, b.getInt64Ty())); - - return 0; -} - -XEEMITTER(mullwx, 0x7C0001D6, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RT <- (RA)[32:63] × (RB)[32:63] - - if (i.XO.OE) { - // With XER update. - XEINSTRNOTIMPLEMENTED(); - return 1; - } - - Value* v = b.CreateMul(b.CreateSExt(e.gpr_value(i.XO.RA), b.getInt64Ty()), - b.CreateSExt(e.gpr_value(i.XO.RB), b.getInt64Ty())); - e.update_gpr_value(i.XO.RT, v); - - if (i.XO.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - } - - return 0; -} - -XEEMITTER(negx, 0x7C0000D0, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RT <- ¬(RA) + 1 - - if (i.XO.OE) { - // With XER update. - // This is a different codepath as we need to use llvm.ssub.with.overflow. - - // if RA == 0x8000000000000000 then no-op and set OV=1 - // This may just magically do that... - - Function* ssub_with_overflow = Intrinsic::getDeclaration( - e.gen_module(), Intrinsic::ssub_with_overflow, b.getInt64Ty()); - Value* v = b.CreateCall2(ssub_with_overflow, - b.getInt64(0), e.gpr_value(i.XO.RA)); - Value* v0 = b.CreateExtractValue(v, 0); - e.update_gpr_value(i.XO.RT, v0); - e.update_xer_with_overflow(b.CreateExtractValue(v, 1)); - - if (i.XO.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v0, b.getInt64(0), true); - } - - return 0; - } else { - // No OE bit setting. - Value* v = b.CreateSub(b.getInt64(0), e.gpr_value(i.XO.RA)); - e.update_gpr_value(i.XO.RT, v); - - if (i.XO.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - } - - return 0; - } -} - -XEEMITTER(subfx, 0x7C000050, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RT <- ¬(RA) + (RB) + 1 - - if (i.XO.OE) { - // With XER update. - // This is a different codepath as we need to use llvm.ssub.with.overflow. - - Function* ssub_with_overflow = Intrinsic::getDeclaration( - e.gen_module(), Intrinsic::ssub_with_overflow, b.getInt64Ty()); - Value* v = b.CreateCall2(ssub_with_overflow, - e.gpr_value(i.XO.RB), e.gpr_value(i.XO.RA)); - Value* v0 = b.CreateExtractValue(v, 0); - e.update_gpr_value(i.XO.RT, v0); - e.update_xer_with_overflow(b.CreateExtractValue(v, 1)); - - if (i.XO.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v0, b.getInt64(0), true); - } - - return 0; - } else { - // No OE bit setting. - Value* v = b.CreateSub(e.gpr_value(i.XO.RB), e.gpr_value(i.XO.RA)); - e.update_gpr_value(i.XO.RT, v); - - if (i.XO.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - } - - return 0; - } -} - -XEEMITTER(subfcx, 0x7C000010, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(subficx, 0x20000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RT <- ¬(RA) + EXTS(SI) + 1 - - Function* ssub_with_overflow = Intrinsic::getDeclaration( - e.gen_module(), Intrinsic::ssub_with_overflow, b.getInt64Ty()); - Value* v = b.CreateCall2(ssub_with_overflow, - b.getInt64(XEEXTS16(i.D.DS)), e.gpr_value(i.D.RA)); - e.update_gpr_value(i.D.RT, b.CreateExtractValue(v, 0)); - e.update_xer_with_carry(b.CreateExtractValue(v, 1)); - - return 0; -} - -XEEMITTER(subfex, 0x7C000110, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RT <- ¬(RA) + (RB) + CA - - // TODO(benvanik): possible that the add of rb+ca needs to also check for - // overflow! - - Value* ca = b.CreateAnd(b.CreateLShr(e.xer_value(), 29), 0x1); - Function* uadd_with_overflow = Intrinsic::getDeclaration( - e.gen_module(), Intrinsic::uadd_with_overflow, b.getInt64Ty()); - Value* v = b.CreateCall2(uadd_with_overflow, - b.CreateNeg(e.gpr_value(i.XO.RA)), - b.CreateAdd(e.gpr_value(i.XO.RB), ca)); - Value* v0 = b.CreateExtractValue(v, 0); - e.update_gpr_value(i.XO.RT, v0); - - if (i.XO.OE) { - // With XER update. - e.update_xer_with_overflow_and_carry(b.CreateExtractValue(v, 1)); - } else { - e.update_xer_with_carry(b.CreateExtractValue(v, 1)); - } - - if (i.XO.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v0, b.getInt64(0), true); - } - - return 0; -} - -XEEMITTER(subfmex, 0x7C0001D0, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(subfzex, 0x7C000190, XO )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - - -// Integer compare (A-4) - -XEEMITTER(cmp, 0x7C000000, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if L = 0 then - // a <- EXTS((RA)[32:63]) - // b <- EXTS((RB)[32:63]) - // else - // a <- (RA) - // b <- (RB) - // if a < b then - // c <- 0b100 - // else if a > b then - // c <- 0b010 - // else - // c <- 0b001 - // CR[4×BF+32:4×BF+35] <- c || XER[SO] - - uint32_t BF = i.X.RT >> 2; - uint32_t L = i.X.RT & 1; - - Value* lhs = e.gpr_value(i.X.RA); - Value* rhs = e.gpr_value(i.X.RB); - if (!L) { - // 32-bit - truncate and sign extend. - lhs = b.CreateTrunc(lhs, b.getInt32Ty()); - lhs = b.CreateSExt(lhs, b.getInt64Ty()); - rhs = b.CreateTrunc(rhs, b.getInt32Ty()); - rhs = b.CreateSExt(rhs, b.getInt64Ty()); - } - - e.update_cr_with_cond(BF, lhs, rhs, true); - - return 0; -} - -XEEMITTER(cmpi, 0x2C000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if L = 0 then - // a <- EXTS((RA)[32:63]) - // else - // a <- (RA) - // if a < EXTS(SI) then - // c <- 0b100 - // else if a > EXTS(SI) then - // c <- 0b010 - // else - // c <- 0b001 - // CR[4×BF+32:4×BF+35] <- c || XER[SO] - - uint32_t BF = i.D.RT >> 2; - uint32_t L = i.D.RT & 1; - - Value* lhs = e.gpr_value(i.D.RA); - if (!L) { - // 32-bit - truncate and sign extend. - lhs = b.CreateTrunc(lhs, b.getInt32Ty()); - lhs = b.CreateSExt(lhs, b.getInt64Ty()); - } - - Value* rhs = b.getInt64(XEEXTS16(i.D.DS)); - e.update_cr_with_cond(BF, lhs, rhs, true); - - return 0; -} - -XEEMITTER(cmpl, 0x7C000040, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if L = 0 then - // a <- i32.0 || (RA)[32:63] - // b <- i32.0 || (RB)[32:63] - // else - // a <- (RA) - // b <- (RB) - // if a u b then - // c <- 0b010 - // else - // c <- 0b001 - // CR[4×BF+32:4×BF+35] <- c || XER[SO] - - uint32_t BF = i.X.RT >> 2; - uint32_t L = i.X.RT & 1; - - Value* lhs = e.gpr_value(i.X.RA); - Value* rhs = e.gpr_value(i.X.RB); - if (!L) { - // 32-bit - truncate and zero extend. - lhs = b.CreateTrunc(lhs, b.getInt32Ty()); - lhs = b.CreateZExt(lhs, b.getInt64Ty()); - rhs = b.CreateTrunc(rhs, b.getInt32Ty()); - rhs = b.CreateZExt(rhs, b.getInt64Ty()); - } - - e.update_cr_with_cond(BF, lhs, rhs, false); - - return 0; -} - -XEEMITTER(cmpli, 0x28000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if L = 0 then - // a <- i32.0 || (RA)[32:63] - // else - // a <- (RA) - // if a u i48.0 || SI then - // c <- 0b010 - // else - // c <- 0b001 - // CR[4×BF+32:4×BF+35] <- c || XER[SO] - - uint32_t BF = i.D.RT >> 2; - uint32_t L = i.D.RT & 1; - - Value* lhs = e.gpr_value(i.D.RA); - if (!L) { - // 32-bit - truncate and zero extend. - lhs = b.CreateTrunc(lhs, b.getInt32Ty()); - lhs = b.CreateZExt(lhs, b.getInt64Ty()); - } - - Value* rhs = b.getInt64(i.D.DS); - e.update_cr_with_cond(BF, lhs, rhs, false); - - return 0; -} - - -// Integer logical (A-5) - -XEEMITTER(andx, 0x7C000038, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RA <- (RS) & (RB) - - Value* v = b.CreateAnd(e.gpr_value(i.X.RT), e.gpr_value(i.X.RB)); - e.update_gpr_value(i.X.RA, v); - - if (i.X.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - } - - return 0; -} - -XEEMITTER(andcx, 0x7C000078, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RA <- (RS) & ¬(RB) - - Value* v = b.CreateXor(e.gpr_value(i.X.RB), -1); - v = b.CreateAnd(e.gpr_value(i.X.RT), v); - e.update_gpr_value(i.X.RA, v); - - if (i.X.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - } - - return 0; -} - -XEEMITTER(andix, 0x70000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RA <- (RS) & (i48.0 || UI) - - Value* v = b.CreateAnd(e.gpr_value(i.D.RT), (uint64_t)i.D.DS); - e.update_gpr_value(i.D.RA, v); - - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - - return 0; -} - -XEEMITTER(andisx, 0x74000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RA <- (RS) & (i32.0 || UI || i16.0) - - Value* v = b.CreateAnd(e.gpr_value(i.D.RT), ((uint64_t)i.D.DS) << 16); - e.update_gpr_value(i.D.RA, v); - - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - - return 1; -} - -XEEMITTER(cntlzdx, 0x7C000074, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(cntlzwx, 0x7C000034, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // n <- 32 - // do while n < 64 - // if (RS) = 1 then leave n - // n <- n + 1 - // RA <- n - 32 - - Value* v = e.gpr_value(i.X.RT); - v = b.CreateTrunc(v, b.getInt32Ty()); - - std::vector arg_types; - arg_types.push_back(b.getInt32Ty()); - Function* ctlz = Intrinsic::getDeclaration( - e.gen_fn()->getParent(), Intrinsic::ctlz, arg_types); - Value* count = b.CreateCall2(ctlz, v, b.getInt1(1)); - - count = b.CreateZExt(count, b.getInt64Ty()); - e.update_gpr_value(i.X.RA, count); - - if (i.X.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, count, b.getInt64(0), true); - } - - return 0; -} - -XEEMITTER(eqvx, 0x7C000238, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(extsbx, 0x7C000774, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // s <- (RS)[56] - // RA[56:63] <- (RS)[56:63] - // RA[0:55] <- i56.s - - Value* v = e.gpr_value(i.X.RT); - v = b.CreateTrunc(v, b.getInt8Ty()); - v = b.CreateSExt(v, b.getInt64Ty()); - e.update_gpr_value(i.X.RA, v); - - if (i.X.Rc) { - // Update cr0. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - } - - return 0; -} - -XEEMITTER(extshx, 0x7C000734, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(extswx, 0x7C0007B4, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(nandx, 0x7C0003B8, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(norx, 0x7C0000F8, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RA <- ¬((RS) | (RB)) - - Value* v = b.CreateOr(e.gpr_value(i.X.RT), e.gpr_value(i.X.RB)); - v = b.CreateXor(v, -1); - e.update_gpr_value(i.X.RA, v); - - if (i.X.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - } - - return 0; -} - -XEEMITTER(orx, 0x7C000378, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RA <- (RS) | (RB) - - Value* v = b.CreateOr(e.gpr_value(i.X.RT), e.gpr_value(i.X.RB)); - e.update_gpr_value(i.X.RA, v); - - if (i.X.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - } - - return 0; -} - -XEEMITTER(orcx, 0x7C000338, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(ori, 0x60000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RA <- (RS) | (i48.0 || UI) - - Value* v = b.CreateOr(e.gpr_value(i.D.RT), (uint64_t)i.D.DS); - e.update_gpr_value(i.D.RA, v); - - return 0; -} - -XEEMITTER(oris, 0x64000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RA <- (RS) | (i32.0 || UI || i16.0) - - Value* v = b.CreateOr(e.gpr_value(i.D.RT), ((uint64_t)i.D.DS) << 16); - e.update_gpr_value(i.D.RA, v); - - return 0; -} - -XEEMITTER(xorx, 0x7C000278, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RA <- (RS) XOR (RB) - - Value* v = b.CreateXor(e.gpr_value(i.X.RT), e.gpr_value(i.X.RB)); - e.update_gpr_value(i.X.RA, v); - - if (i.X.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - } - - return 0; -} - -XEEMITTER(xori, 0x68000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RA <- (RS) XOR (i48.0 || UI) - - Value* v = b.CreateXor(e.gpr_value(i.D.RT), (uint64_t)i.D.DS); - e.update_gpr_value(i.D.RA, v); - - return 0; -} - -XEEMITTER(xoris, 0x6C000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // RA <- (RS) XOR (i32.0 || UI || i16.0) - - Value* v = b.CreateXor(e.gpr_value(i.D.RT), ((uint64_t)i.D.DS) << 16); - e.update_gpr_value(i.D.RA, v); - - return 0; -} - - -// Integer rotate (A-6) - -XEEMITTER(rldclx, 0x78000010, MDS)(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(rldcrx, 0x78000012, MDS)(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(rldicx, 0x78000008, MD )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(rldiclx, 0x78000000, MD )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // n <- sh[5] || sh[0:4] - // r <- ROTL64((RS), n) - // b <- mb[5] || mb[0:4] - // m <- MASK(b, 63) - // RA <- r & m - - // uint32_t sh = (i.MD.SH5 << 5) | i.MD.SH; - // uint32_t mb = (i.MD.MB5 << 5) | i.MD.MB; - - // Value* v = e.gpr_value(i.MD.RS); - // if (sh) { - // v = // rotate by sh - // } - // if (mb) { - // v = // mask b mb->63 - // } - // e.update_gpr_value(i.MD.RA, v); - - // if (i.MD.Rc) { - // // With cr0 update. - // e.update_cr_with_cond(0, v, b.getInt64(0), true); - // } - - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(rldicrx, 0x78000004, MD )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(rldimix, 0x7800000C, MD )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(rlwimix, 0x50000000, M )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // n <- SH - // r <- ROTL32((RS)[32:63], n) - // m <- MASK(MB+32, ME+32) - // RA <- r&m | (RA)&¬m - - // ROTL32(x, y) = rotl(i64.(x||x), y) - Value* v = b.CreateAnd(e.gpr_value(i.M.RT), UINT32_MAX); - v = b.CreateOr(b.CreateShl(v, 32), v); - // (v << shift) | (v >> (32 - shift)); - v = b.CreateOr(b.CreateShl(v, i.M.SH), b.CreateLShr(v, 32 - i.M.SH)); - uint64_t m = XEMASK(i.M.MB + 32, i.M.ME + 32); - v = b.CreateAnd(v, m); - v = b.CreateOr(v, b.CreateAnd(e.gpr_value(i.M.RA), ~m)); - e.update_gpr_value(i.M.RA, v); - - if (i.M.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - } - - return 0; -} - -XEEMITTER(rlwinmx, 0x54000000, M )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // n <- SH - // r <- ROTL32((RS)[32:63], n) - // m <- MASK(MB+32, ME+32) - // RA <- r & m - - // The compiler will generate a bunch of these for the special case of SH=0. - // Which seems to just select some bits and set cr0 for use with a branch. - // We can detect this and do less work. - if (!i.M.SH) { - Value* v = b.CreateAnd( - b.CreateTrunc(e.gpr_value(i.M.RT), b.getInt32Ty()), - b.getInt32((uint32_t)XEMASK(i.M.MB + 32, i.M.ME + 32))); - v = b.CreateZExt(v, b.getInt64Ty()); - e.update_gpr_value(i.M.RA, v); - if (i.M.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - } - return 0; - } - - // ROTL32(x, y) = rotl(i64.(x||x), y) - Value* v = b.CreateAnd(e.gpr_value(i.M.RT), UINT32_MAX); - v = b.CreateOr(b.CreateShl(v, 32), v); - // (v << shift) | (v >> (32 - shift)); - v = b.CreateOr(b.CreateShl(v, i.M.SH), b.CreateLShr(v, 32 - i.M.SH)); - v = b.CreateAnd(v, XEMASK(i.M.MB + 32, i.M.ME + 32)); - e.update_gpr_value(i.M.RA, v); - - if (i.M.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - } - - return 0; -} - -XEEMITTER(rlwnmx, 0x5C000000, M )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - - -// Integer shift (A-7) - -XEEMITTER(sldx, 0x7C000036, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(slwx, 0x7C000030, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // n <- (RB)[59:63] - // r <- ROTL32((RS)[32:63], n) - // if (RB)[58] = 0 then - // m <- MASK(32, 63-n) - // else - // m <- i64.0 - // RA <- r & m - - Value* v = b.CreateShl(e.gpr_value(i.X.RT), e.gpr_value(i.X.RB)); - v = b.CreateAnd(v, UINT32_MAX); - e.update_gpr_value(i.X.RA, v); - - if (i.X.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - } - - return 0; -} - -XEEMITTER(sradx, 0x7C000634, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(sradix, 0x7C000674, XS )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(srawx, 0x7C000630, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(srawix, 0x7C000670, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // n <- SH - // r <- ROTL32((RS)[32:63], 64-n) - // m <- MASK(n+32, 63) - // s <- (RS)[32] - // RA <- r&m | (i64.s)&¬m - // CA <- s & ((r&¬m)[32:63]≠0) - - Value* rs64 = e.gpr_value(i.X.RT); - Value* rs32 = b.CreateTrunc(rs64, b.getInt32Ty()); - - Value* v; - Value* ca; - if (!i.X.RB) { - // No shift, just a fancy sign extend and CA clearer. - v = rs32; - ca = b.getInt64(0); - } else { - v = b.CreateAShr(rs32, i.X.RB); - - // CA is set to 1 if the low-order 32 bits of (RS) contain a negative number - // and any 1-bits are shifted out of position 63; otherwise CA is set to 0. - ca = b.CreateAnd(b.CreateICmpSLT(v, b.getInt32(0)), - b.CreateICmpSLT(rs64, b.getInt64(0))); - } - v = b.CreateSExt(v, b.getInt64Ty()); - e.update_gpr_value(i.X.RA, v); - e.update_xer_with_carry(ca); - - if (i.X.Rc) { - // With cr0 update. - e.update_cr_with_cond(0, v, b.getInt64(0), true); - } - - return 0; -} - -XEEMITTER(srdx, 0x7C000436, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(srwx, 0x7C000430, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - - -void RegisterEmitCategoryALU() { - XEREGISTERINSTR(addx, 0x7C000214); - XEREGISTERINSTR(addcx, 0X7C000014); - XEREGISTERINSTR(addex, 0x7C000114); - XEREGISTERINSTR(addi, 0x38000000); - XEREGISTERINSTR(addic, 0x30000000); - XEREGISTERINSTR(addicx, 0x34000000); - XEREGISTERINSTR(addis, 0x3C000000); - XEREGISTERINSTR(addmex, 0x7C0001D4); - XEREGISTERINSTR(addzex, 0x7C000194); - XEREGISTERINSTR(divdx, 0x7C0003D2); - XEREGISTERINSTR(divdux, 0x7C000392); - XEREGISTERINSTR(divwx, 0x7C0003D6); - XEREGISTERINSTR(divwux, 0x7C000396); - XEREGISTERINSTR(mulhdx, 0x7C000092); - XEREGISTERINSTR(mulhdux, 0x7C000012); - XEREGISTERINSTR(mulhwx, 0x7C000096); - XEREGISTERINSTR(mulhwux, 0x7C000016); - XEREGISTERINSTR(mulldx, 0x7C0001D2); - XEREGISTERINSTR(mulli, 0x1C000000); - XEREGISTERINSTR(mullwx, 0x7C0001D6); - XEREGISTERINSTR(negx, 0x7C0000D0); - XEREGISTERINSTR(subfx, 0x7C000050); - XEREGISTERINSTR(subfcx, 0x7C000010); - XEREGISTERINSTR(subficx, 0x20000000); - XEREGISTERINSTR(subfex, 0x7C000110); - XEREGISTERINSTR(subfmex, 0x7C0001D0); - XEREGISTERINSTR(subfzex, 0x7C000190); - XEREGISTERINSTR(cmp, 0x7C000000); - XEREGISTERINSTR(cmpi, 0x2C000000); - XEREGISTERINSTR(cmpl, 0x7C000040); - XEREGISTERINSTR(cmpli, 0x28000000); - XEREGISTERINSTR(andx, 0x7C000038); - XEREGISTERINSTR(andcx, 0x7C000078); - XEREGISTERINSTR(andix, 0x70000000); - XEREGISTERINSTR(andisx, 0x74000000); - XEREGISTERINSTR(cntlzdx, 0x7C000074); - XEREGISTERINSTR(cntlzwx, 0x7C000034); - XEREGISTERINSTR(eqvx, 0x7C000238); - XEREGISTERINSTR(extsbx, 0x7C000774); - XEREGISTERINSTR(extshx, 0x7C000734); - XEREGISTERINSTR(extswx, 0x7C0007B4); - XEREGISTERINSTR(nandx, 0x7C0003B8); - XEREGISTERINSTR(norx, 0x7C0000F8); - XEREGISTERINSTR(orx, 0x7C000378); - XEREGISTERINSTR(orcx, 0x7C000338); - XEREGISTERINSTR(ori, 0x60000000); - XEREGISTERINSTR(oris, 0x64000000); - XEREGISTERINSTR(xorx, 0x7C000278); - XEREGISTERINSTR(xori, 0x68000000); - XEREGISTERINSTR(xoris, 0x6C000000); - XEREGISTERINSTR(rldclx, 0x78000010); - XEREGISTERINSTR(rldcrx, 0x78000012); - XEREGISTERINSTR(rldicx, 0x78000008); - XEREGISTERINSTR(rldiclx, 0x78000000); - XEREGISTERINSTR(rldicrx, 0x78000004); - XEREGISTERINSTR(rldimix, 0x7800000C); - XEREGISTERINSTR(rlwimix, 0x50000000); - XEREGISTERINSTR(rlwinmx, 0x54000000); - XEREGISTERINSTR(rlwnmx, 0x5C000000); - XEREGISTERINSTR(sldx, 0x7C000036); - XEREGISTERINSTR(slwx, 0x7C000030); - XEREGISTERINSTR(sradx, 0x7C000634); - XEREGISTERINSTR(sradix, 0x7C000674); - XEREGISTERINSTR(srawx, 0x7C000630); - XEREGISTERINSTR(srawix, 0x7C000670); - XEREGISTERINSTR(srdx, 0x7C000436); - XEREGISTERINSTR(srwx, 0x7C000430); -} - - -} // namespace llvmbe -} // namespace cpu -} // namespace xe diff --git a/src/xenia/cpu/llvmbe/emit_control.cc b/src/xenia/cpu/llvmbe/emit_control.cc deleted file mode 100644 index b26575430..000000000 --- a/src/xenia/cpu/llvmbe/emit_control.cc +++ /dev/null @@ -1,713 +0,0 @@ -/* - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - -#include -#include - - -using namespace llvm; -using namespace xe::cpu; -using namespace xe::cpu::ppc; -using namespace xe::cpu::sdb; - - -namespace xe { -namespace cpu { -namespace llvmbe { - - -int XeEmitIndirectBranchTo( - EmitterContext& e, IRBuilder<>& b, const char* src, uint32_t cia, - bool lk, uint32_t reg) { - // TODO(benvanik): run a DFA pass to see if we can detect whether this is - // a normal function return that is pulling the LR from the stack that - // it set in the prolog. If so, we can omit the dynamic check! - - // NOTE: we avoid spilling registers until we know that the target is not - // a basic block within this function. - - Value* target; - switch (reg) { - case kXEPPCRegLR: - target = e.lr_value(); - break; - case kXEPPCRegCTR: - target = e.ctr_value(); - break; - default: - XEASSERTALWAYS(); - return 1; - } - - // Dynamic test when branching to LR, which is usually used for the return. - // We only do this if LK=0 as returns wouldn't set LR. - // Ideally it's a return and we can just do a simple ret and be done. - // If it's not, we fall through to the full indirection logic. - if (!lk && reg == kXEPPCRegLR) { - BasicBlock* next_block = e.GetNextBasicBlock(); - BasicBlock* mismatch_bb = BasicBlock::Create(*e.context(), "lr_mismatch", - e.gen_fn(), next_block); - Value* lr_cmp = b.CreateICmpEQ(target, ++(e.gen_fn()->arg_begin())); - // The return block will spill registers for us. - b.CreateCondBr(lr_cmp, e.GetReturnBasicBlock(), mismatch_bb); - b.SetInsertPoint(mismatch_bb); - } - - // Defer to the generator, which will do fancy things. - bool likely_local = !lk && reg == kXEPPCRegCTR; - return e.GenerateIndirectionBranch(cia, target, lk, likely_local); -} - -int XeEmitBranchTo( - EmitterContext& e, IRBuilder<>& b, const char* src, uint32_t cia, - bool lk) { - // Get the basic block and switch behavior based on outgoing type. - FunctionBlock* fn_block = e.fn_block(); - switch (fn_block->outgoing_type) { - case FunctionBlock::kTargetBlock: - { - BasicBlock* target_bb = e.GetBasicBlock(fn_block->outgoing_address); - XEASSERTNOTNULL(target_bb); - b.CreateBr(target_bb); - break; - } - case FunctionBlock::kTargetFunction: - { - // Spill all registers to memory. - // TODO(benvanik): only spill ones used by the target function? Use - // calling convention flags on the function to not spill temp - // registers? - e.SpillRegisters(); - - XEASSERTNOTNULL(fn_block->outgoing_function); - Function* target_fn = e.GetFunction(fn_block->outgoing_function); - Function::arg_iterator args = e.gen_fn()->arg_begin(); - Value* state_ptr = args; - BasicBlock* next_bb = e.GetNextBasicBlock(); - if (!lk || !next_bb) { - // Tail. No need to refill the local register values, just return. - // We optimize this by passing in the LR from our parent instead of the - // next instruction. This allows the return from our callee to pop - // all the way up. - b.CreateCall2(target_fn, state_ptr, ++args); - b.CreateRetVoid(); - } else { - // Will return here eventually. - // Refill registers from state. - b.CreateCall2(target_fn, state_ptr, b.getInt64(cia + 4)); - e.FillRegisters(); - b.CreateBr(next_bb); - } - break; - } - case FunctionBlock::kTargetLR: - { - // An indirect jump. - printf("INDIRECT JUMP VIA LR: %.8X\n", cia); - return XeEmitIndirectBranchTo(e, b, src, cia, lk, kXEPPCRegLR); - } - case FunctionBlock::kTargetCTR: - { - // An indirect jump. - printf("INDIRECT JUMP VIA CTR: %.8X\n", cia); - return XeEmitIndirectBranchTo(e, b, src, cia, lk, kXEPPCRegCTR); - } - default: - case FunctionBlock::kTargetNone: - XEASSERTALWAYS(); - return 1; - } - return 0; -} - - -XEEMITTER(bx, 0x48000000, I )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if AA then - // NIA <- EXTS(LI || 0b00) - // else - // NIA <- CIA + EXTS(LI || 0b00) - // if LK then - // LR <- CIA + 4 - - uint32_t nia; - if (i.I.AA) { - nia = XEEXTS26(i.I.LI << 2); - } else { - nia = i.address + XEEXTS26(i.I.LI << 2); - } - if (i.I.LK) { - e.update_lr_value(b.getInt32(i.address + 4)); - } - - return XeEmitBranchTo(e, b, "bx", i.address, i.I.LK); -} - -XEEMITTER(bcx, 0x40000000, B )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if ¬BO[2] then - // CTR <- CTR - 1 - // ctr_ok <- BO[2] | ((CTR[0:63] != 0) XOR BO[3]) - // cond_ok <- BO[0] | (CR[BI+32] ≡ BO[1]) - // if ctr_ok & cond_ok then - // if AA then - // NIA <- EXTS(BD || 0b00) - // else - // NIA <- CIA + EXTS(BD || 0b00) - // if LK then - // LR <- CIA + 4 - - // NOTE: the condition bits are reversed! - // 01234 (docs) - // 43210 (real) - - // TODO(benvanik): this may be wrong and overwrite LRs when not desired! - // The docs say always, though... - if (i.B.LK) { - e.update_lr_value(b.getInt32(i.address + 4)); - } - - Value* ctr_ok = NULL; - if (XESELECTBITS(i.B.BO, 2, 2)) { - // Ignore ctr. - } else { - // Decrement counter. - Value* ctr = e.ctr_value(); - ctr = b.CreateSub(ctr, b.getInt64(1)); - e.update_ctr_value(ctr); - - // Ctr check. - if (XESELECTBITS(i.B.BO, 1, 1)) { - ctr_ok = b.CreateICmpEQ(ctr, b.getInt64(0)); - } else { - ctr_ok = b.CreateICmpNE(ctr, b.getInt64(0)); - } - } - - Value* cond_ok = NULL; - if (XESELECTBITS(i.B.BO, 4, 4)) { - // Ignore cond. - } else { - Value* cr = e.cr_value(i.B.BI >> 2); - cr = b.CreateAnd(cr, 1 << (i.B.BI & 3)); - if (XESELECTBITS(i.B.BO, 3, 3)) { - cond_ok = b.CreateICmpNE(cr, b.getInt64(0)); - } else { - cond_ok = b.CreateICmpEQ(cr, b.getInt64(0)); - } - } - - // We do a bit of optimization here to make the llvm assembly easier to read. - Value* ok = NULL; - if (ctr_ok && cond_ok) { - ok = b.CreateAnd(ctr_ok, cond_ok); - } else if (ctr_ok) { - ok = ctr_ok; - } else if (cond_ok) { - ok = cond_ok; - } - - // Handle unconditional branches without extra fluff. - BasicBlock* original_bb = b.GetInsertBlock(); - if (ok) { - char name[32]; - xesnprintfa(name, XECOUNT(name), "loc_%.8X_bcx", i.address); - BasicBlock* next_block = e.GetNextBasicBlock(); - BasicBlock* branch_bb = BasicBlock::Create(*e.context(), name, e.gen_fn(), - next_block); - - b.CreateCondBr(ok, branch_bb, next_block); - b.SetInsertPoint(branch_bb); - } - - // Note that this occurs entirely within the branch true block. - uint32_t nia; - if (i.B.AA) { - nia = XEEXTS26(i.B.BD << 2); - } else { - nia = i.address + XEEXTS26(i.B.BD << 2); - } - if (XeEmitBranchTo(e, b, "bcx", i.address, i.B.LK)) { - return 1; - } - - b.SetInsertPoint(original_bb); - - return 0; -} - -XEEMITTER(bcctrx, 0x4C000420, XL )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // cond_ok <- BO[0] | (CR[BI+32] ≡ BO[1]) - // if cond_ok then - // NIA <- CTR[0:61] || 0b00 - // if LK then - // LR <- CIA + 4 - - // NOTE: the condition bits are reversed! - // 01234 (docs) - // 43210 (real) - - // TODO(benvanik): this may be wrong and overwrite LRs when not desired! - // The docs say always, though... - if (i.XL.LK) { - e.update_lr_value(b.getInt32(i.address + 4)); - } - - Value* cond_ok = NULL; - if (XESELECTBITS(i.XL.BO, 4, 4)) { - // Ignore cond. - } else { - Value* cr = e.cr_value(i.XL.BI >> 2); - cr = b.CreateAnd(cr, 1 << (i.XL.BI & 3)); - if (XESELECTBITS(i.XL.BO, 3, 3)) { - cond_ok = b.CreateICmpNE(cr, b.getInt64(0)); - } else { - cond_ok = b.CreateICmpEQ(cr, b.getInt64(0)); - } - } - - // We do a bit of optimization here to make the llvm assembly easier to read. - Value* ok = NULL; - if (cond_ok) { - ok = cond_ok; - } - - // Handle unconditional branches without extra fluff. - BasicBlock* original_bb = b.GetInsertBlock(); - if (ok) { - char name[32]; - xesnprintfa(name, XECOUNT(name), "loc_%.8X_bcctrx", i.address); - BasicBlock* next_block = e.GetNextBasicBlock(); - XEASSERTNOTNULL(next_block); - BasicBlock* branch_bb = BasicBlock::Create(*e.context(), name, e.gen_fn(), - next_block); - - b.CreateCondBr(ok, branch_bb, next_block); - b.SetInsertPoint(branch_bb); - } - - // Note that this occurs entirely within the branch true block. - if (XeEmitBranchTo(e, b, "bcctrx", i.address, i.XL.LK)) { - return 1; - } - - b.SetInsertPoint(original_bb); - - return 0; -} - -XEEMITTER(bclrx, 0x4C000020, XL )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if ¬BO[2] then - // CTR <- CTR - 1 - // ctr_ok <- BO[2] | ((CTR[0:63] != 0) XOR BO[3] - // cond_ok <- BO[0] | (CR[BI+32] ≡ BO[1]) - // if ctr_ok & cond_ok then - // NIA <- LR[0:61] || 0b00 - // if LK then - // LR <- CIA + 4 - - // NOTE: the condition bits are reversed! - // 01234 (docs) - // 43210 (real) - - // TODO(benvanik): this may be wrong and overwrite LRs when not desired! - // The docs say always, though... - if (i.XL.LK) { - e.update_lr_value(b.getInt32(i.address + 4)); - } - - Value* ctr_ok = NULL; - if (XESELECTBITS(i.XL.BO, 2, 2)) { - // Ignore ctr. - } else { - // Decrement counter. - Value* ctr = e.ctr_value(); - ctr = b.CreateSub(ctr, b.getInt64(1)); - - // Ctr check. - if (XESELECTBITS(i.XL.BO, 1, 1)) { - ctr_ok = b.CreateICmpEQ(ctr, b.getInt64(0)); - } else { - ctr_ok = b.CreateICmpNE(ctr, b.getInt64(0)); - } - } - - Value* cond_ok = NULL; - if (XESELECTBITS(i.XL.BO, 4, 4)) { - // Ignore cond. - } else { - Value* cr = e.cr_value(i.XL.BI >> 2); - cr = b.CreateAnd(cr, 1 << (i.XL.BI & 3)); - if (XESELECTBITS(i.XL.BO, 3, 3)) { - cond_ok = b.CreateICmpNE(cr, b.getInt64(0)); - } else { - cond_ok = b.CreateICmpEQ(cr, b.getInt64(0)); - } - } - - // We do a bit of optimization here to make the llvm assembly easier to read. - Value* ok = NULL; - if (ctr_ok && cond_ok) { - ok = b.CreateAnd(ctr_ok, cond_ok); - } else if (ctr_ok) { - ok = ctr_ok; - } else if (cond_ok) { - ok = cond_ok; - } - - // Handle unconditional branches without extra fluff. - BasicBlock* original_bb = b.GetInsertBlock(); - if (ok) { - char name[32]; - xesnprintfa(name, XECOUNT(name), "loc_%.8X_bclrx", i.address); - BasicBlock* next_block = e.GetNextBasicBlock(); - XEASSERTNOTNULL(next_block); - BasicBlock* branch_bb = BasicBlock::Create(*e.context(), name, e.gen_fn(), - next_block); - - b.CreateCondBr(ok, branch_bb, next_block); - b.SetInsertPoint(branch_bb); - } - - // Note that this occurs entirely within the branch true block. - if (XeEmitBranchTo(e, b, "bclrx", i.address, i.XL.LK)) { - return 1; - } - - b.SetInsertPoint(original_bb); - - return 0; -} - - -// Condition register logical (A-23) - -XEEMITTER(crand, 0x4C000202, XL )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(crandc, 0x4C000102, XL )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(creqv, 0x4C000242, XL )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(crnand, 0x4C0001C2, XL )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(crnor, 0x4C000042, XL )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(cror, 0x4C000382, XL )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(crorc, 0x4C000342, XL )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(crxor, 0x4C000182, XL )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(mcrf, 0x4C000000, XL )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - - -// System linkage (A-24) - -XEEMITTER(sc, 0x44000002, SC )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - - -// Trap (A-25) - -int XeEmitTrap(EmitterContext& e, IRBuilder<>& b, InstrData& i, - Value* va, Value* vb, uint32_t TO) { - // if (a < b) & TO[0] then TRAP - // if (a > b) & TO[1] then TRAP - // if (a = b) & TO[2] then TRAP - // if (a u b) & TO[4] then TRAP - // Bits swapped: - // 01234 - // 43210 - - if (!TO) { - return 0; - } - - BasicBlock* after_bb = BasicBlock::Create(*e.context(), "", e.gen_fn(), - e.GetNextBasicBlock()); - BasicBlock* trap_bb = BasicBlock::Create(*e.context(), "", e.gen_fn(), - after_bb); - - // Create the basic blocks (so we can chain). - std::vector bbs; - if (TO & (1 << 4)) { - bbs.push_back(BasicBlock::Create(*e.context(), "", e.gen_fn(), trap_bb)); - } - if (TO & (1 << 3)) { - bbs.push_back(BasicBlock::Create(*e.context(), "", e.gen_fn(), trap_bb)); - } - if (TO & (1 << 2)) { - bbs.push_back(BasicBlock::Create(*e.context(), "", e.gen_fn(), trap_bb)); - } - if (TO & (1 << 1)) { - bbs.push_back(BasicBlock::Create(*e.context(), "", e.gen_fn(), trap_bb)); - } - if (TO & (1 << 0)) { - bbs.push_back(BasicBlock::Create(*e.context(), "", e.gen_fn(), trap_bb)); - } - bbs.push_back(after_bb); - - // Jump to the first bb. - b.CreateBr(bbs.front()); - - // Setup each basic block. - std::vector::iterator it = bbs.begin(); - if (TO & (1 << 4)) { - // a < b - BasicBlock* bb = *(it++); - b.SetInsertPoint(bb); - Value* cmp = b.CreateICmpSLT(va, vb); - b.CreateCondBr(cmp, trap_bb, *it); - } - if (TO & (1 << 3)) { - // a > b - BasicBlock* bb = *(it++); - b.SetInsertPoint(bb); - Value* cmp = b.CreateICmpSGT(va, vb); - b.CreateCondBr(cmp, trap_bb, *it); - } - if (TO & (1 << 2)) { - // a = b - BasicBlock* bb = *(it++); - b.SetInsertPoint(bb); - Value* cmp = b.CreateICmpEQ(va, vb); - b.CreateCondBr(cmp, trap_bb, *it); - } - if (TO & (1 << 1)) { - // a u b - BasicBlock* bb = *(it++); - b.SetInsertPoint(bb); - Value* cmp = b.CreateICmpUGT(va, vb); - b.CreateCondBr(cmp, trap_bb, *it); - } - - // Create trap BB. - b.SetInsertPoint(trap_bb); - e.SpillRegisters(); - // TODO(benvanik): use @llvm.debugtrap? could make debugging better - b.CreateCall2(e.gen_module()->getFunction("XeTrap"), - e.gen_fn()->arg_begin(), - b.getInt32(i.address)); - b.CreateBr(after_bb); - - // Resume. - b.SetInsertPoint(after_bb); - - return 0; -} - -XEEMITTER(td, 0x7C000088, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // a <- (RA) - // b <- (RB) - // if (a < b) & TO[0] then TRAP - // if (a > b) & TO[1] then TRAP - // if (a = b) & TO[2] then TRAP - // if (a u b) & TO[4] then TRAP - return XeEmitTrap(e, b, i, - e.gpr_value(i.X.RA), - e.gpr_value(i.X.RB), - i.X.RT); -} - -XEEMITTER(tdi, 0x08000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // a <- (RA) - // if (a < EXTS(SI)) & TO[0] then TRAP - // if (a > EXTS(SI)) & TO[1] then TRAP - // if (a = EXTS(SI)) & TO[2] then TRAP - // if (a u EXTS(SI)) & TO[4] then TRAP - return XeEmitTrap(e, b, i, - e.gpr_value(i.D.RA), - b.getInt64(XEEXTS16(i.D.DS)), - i.D.RT); -} - -XEEMITTER(tw, 0x7C000008, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // a <- EXTS((RA)[32:63]) - // b <- EXTS((RB)[32:63]) - // if (a < b) & TO[0] then TRAP - // if (a > b) & TO[1] then TRAP - // if (a = b) & TO[2] then TRAP - // if (a u b) & TO[4] then TRAP - return XeEmitTrap(e, b, i, - b.CreateSExt(b.CreateTrunc(e.gpr_value(i.X.RA), - b.getInt32Ty()), - b.getInt64Ty()), - b.CreateSExt(b.CreateTrunc(e.gpr_value(i.X.RB), - b.getInt32Ty()), - b.getInt64Ty()), - i.X.RT); -} - -XEEMITTER(twi, 0x0C000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // a <- EXTS((RA)[32:63]) - // if (a < EXTS(SI)) & TO[0] then TRAP - // if (a > EXTS(SI)) & TO[1] then TRAP - // if (a = EXTS(SI)) & TO[2] then TRAP - // if (a u EXTS(SI)) & TO[4] then TRAP - return XeEmitTrap(e, b, i, - b.CreateSExt(b.CreateTrunc(e.gpr_value(i.D.RA), - b.getInt32Ty()), - b.getInt64Ty()), - b.getInt64(XEEXTS16(i.D.DS)), - i.D.RT); -} - - -// Processor control (A-26) - -XEEMITTER(mfcr, 0x7C000026, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(mfspr, 0x7C0002A6, XFX)(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // n <- spr[5:9] || spr[0:4] - // if length(SPR(n)) = 64 then - // RT <- SPR(n) - // else - // RT <- i32.0 || SPR(n) - - const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F); - Value* v = NULL; - switch (n) { - case 1: - // XER - v = e.xer_value(); - break; - case 8: - // LR - v = e.lr_value(); - break; - case 9: - // CTR - v = e.ctr_value(); - break; - default: - XEINSTRNOTIMPLEMENTED(); - return 1; - } - - e.update_gpr_value(i.XFX.RT, v); - - return 0; -} - -XEEMITTER(mftb, 0x7C0002E6, XFX)(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(mtcrf, 0x7C000120, XFX)(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(mtspr, 0x7C0003A6, XFX)(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // n <- spr[5:9] || spr[0:4] - // if length(SPR(n)) = 64 then - // SPR(n) <- (RS) - // else - // SPR(n) <- (RS)[32:63] - - Value* v = e.gpr_value(i.XFX.RT); - - const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F); - switch (n) { - case 1: - // XER - e.update_xer_value(v); - break; - case 8: - // LR - e.update_lr_value(v); - break; - case 9: - // CTR - e.update_ctr_value(v); - break; - default: - XEINSTRNOTIMPLEMENTED(); - return 1; - } - - return 0; -} - - -void RegisterEmitCategoryControl() { - XEREGISTERINSTR(bx, 0x48000000); - XEREGISTERINSTR(bcx, 0x40000000); - XEREGISTERINSTR(bcctrx, 0x4C000420); - XEREGISTERINSTR(bclrx, 0x4C000020); - XEREGISTERINSTR(crand, 0x4C000202); - XEREGISTERINSTR(crandc, 0x4C000102); - XEREGISTERINSTR(creqv, 0x4C000242); - XEREGISTERINSTR(crnand, 0x4C0001C2); - XEREGISTERINSTR(crnor, 0x4C000042); - XEREGISTERINSTR(cror, 0x4C000382); - XEREGISTERINSTR(crorc, 0x4C000342); - XEREGISTERINSTR(crxor, 0x4C000182); - XEREGISTERINSTR(mcrf, 0x4C000000); - XEREGISTERINSTR(sc, 0x44000002); - XEREGISTERINSTR(td, 0x7C000088); - XEREGISTERINSTR(tdi, 0x08000000); - XEREGISTERINSTR(tw, 0x7C000008); - XEREGISTERINSTR(twi, 0x0C000000); - XEREGISTERINSTR(mfcr, 0x7C000026); - XEREGISTERINSTR(mfspr, 0x7C0002A6); - XEREGISTERINSTR(mftb, 0x7C0002E6); - XEREGISTERINSTR(mtcrf, 0x7C000120); - XEREGISTERINSTR(mtspr, 0x7C0003A6); -} - - -} // namespace llvmbe -} // namespace cpu -} // namespace xe diff --git a/src/xenia/cpu/llvmbe/emit_fpu.cc b/src/xenia/cpu/llvmbe/emit_fpu.cc deleted file mode 100644 index 3c0afd1e6..000000000 --- a/src/xenia/cpu/llvmbe/emit_fpu.cc +++ /dev/null @@ -1,296 +0,0 @@ -/* - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - -#include - - -using namespace llvm; -using namespace xe::cpu; -using namespace xe::cpu::ppc; - - -namespace xe { -namespace cpu { -namespace llvmbe { - - -// Floating-point arithmetic (A-8) - -XEEMITTER(faddx, 0xFC00002A, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(faddsx, 0xEC00002A, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fdivx, 0xFC000024, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fdivsx, 0xEC000024, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fmulx, 0xFC000032, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fmulsx, 0xEC000032, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fresx, 0xEC000030, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(frsqrtex, 0xFC000034, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fsubx, 0xFC000028, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fsubsx, 0xEC000028, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fselx, 0xFC00002E, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fsqrtx, 0xFC00002C, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fsqrtsx, 0xEC00002C, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - - -// Floating-point multiply-add (A-9) - -XEEMITTER(fmaddx, 0xFC00003A, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fmaddsx, 0xEC00003A, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fmsubx, 0xFC000038, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fmsubsx, 0xEC000038, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fnmaddx, 0xFC00003E, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fnmaddsx, 0xEC00003E, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fnmsubx, 0xFC00003C, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fnmsubsx, 0xEC00003C, A )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - - -// Floating-point rounding and conversion (A-10) - -XEEMITTER(fcfidx, 0xFC00069C, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fctidx, 0xFC00065C, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fctidzx, 0xFC00065E, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fctiwx, 0xFC00001C, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fctiwzx, 0xFC00001E, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(frspx, 0xFC000018, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - - -// Floating-point compare (A-11) - -XEEMITTER(fcmpo, 0xFC000040, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fcmpu, 0xFC000000, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if (FRA) is a NaN or (FRB) is a NaN then - // c <- 0b0001 - // else if (FRA) < (FRB) then - // c <- 0b1000 - // else if (FRA) > (FRB) then - // c <- 0b0100 - // else { - // c <- 0b0010 - // } - // FPCC <- c - // CR[4*BF:4*BF+3] <- c - // if (FRA) is an SNaN or (FRB) is an SNaN then - // VXSNAN <- 1 - XEINSTRNOTIMPLEMENTED(); - return 1; -} - - -// Floating-point status and control register (A - -XEEMITTER(mcrfs, 0xFC000080, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(mffsx, 0xFC00048E, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(mtfsb0x, 0xFC00008C, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(mtfsb1x, 0xFC00004C, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(mtfsfx, 0xFC00058E, XFL)(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(mtfsfix, 0xFC00010C, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - - -// Floating-point move (A-21) - -XEEMITTER(fabsx, 0xFC000210, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fmrx, 0xFC000090, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fnabsx, 0xFC000110, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(fnegx, 0xFC000050, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - - -void RegisterEmitCategoryFPU() { - XEREGISTERINSTR(faddx, 0xFC00002A); - XEREGISTERINSTR(faddsx, 0xEC00002A); - XEREGISTERINSTR(fdivx, 0xFC000024); - XEREGISTERINSTR(fdivsx, 0xEC000024); - XEREGISTERINSTR(fmulx, 0xFC000032); - XEREGISTERINSTR(fmulsx, 0xEC000032); - XEREGISTERINSTR(fresx, 0xEC000030); - XEREGISTERINSTR(frsqrtex, 0xFC000034); - XEREGISTERINSTR(fsubx, 0xFC000028); - XEREGISTERINSTR(fsubsx, 0xEC000028); - XEREGISTERINSTR(fselx, 0xFC00002E); - XEREGISTERINSTR(fsqrtx, 0xFC00002C); - XEREGISTERINSTR(fsqrtsx, 0xEC00002C); - XEREGISTERINSTR(fmaddx, 0xFC00003A); - XEREGISTERINSTR(fmaddsx, 0xEC00003A); - XEREGISTERINSTR(fmsubx, 0xFC000038); - XEREGISTERINSTR(fmsubsx, 0xEC000038); - XEREGISTERINSTR(fnmaddx, 0xFC00003E); - XEREGISTERINSTR(fnmaddsx, 0xEC00003E); - XEREGISTERINSTR(fnmsubx, 0xFC00003C); - XEREGISTERINSTR(fnmsubsx, 0xEC00003C); - XEREGISTERINSTR(fcfidx, 0xFC00069C); - XEREGISTERINSTR(fctidx, 0xFC00065C); - XEREGISTERINSTR(fctidzx, 0xFC00065E); - XEREGISTERINSTR(fctiwx, 0xFC00001C); - XEREGISTERINSTR(fctiwzx, 0xFC00001E); - XEREGISTERINSTR(frspx, 0xFC000018); - XEREGISTERINSTR(fcmpo, 0xFC000040); - XEREGISTERINSTR(fcmpu, 0xFC000000); - XEREGISTERINSTR(mcrfs, 0xFC000080); - XEREGISTERINSTR(mffsx, 0xFC00048E); - XEREGISTERINSTR(mtfsb0x, 0xFC00008C); - XEREGISTERINSTR(mtfsb1x, 0xFC00004C); - XEREGISTERINSTR(mtfsfx, 0xFC00058E); - XEREGISTERINSTR(mtfsfix, 0xFC00010C); - XEREGISTERINSTR(fabsx, 0xFC000210); - XEREGISTERINSTR(fmrx, 0xFC000090); - XEREGISTERINSTR(fnabsx, 0xFC000110); - XEREGISTERINSTR(fnegx, 0xFC000050); -} - - -} // namespace llvmbe -} // namespace cpu -} // namespace xe diff --git a/src/xenia/cpu/llvmbe/emit_memory.cc b/src/xenia/cpu/llvmbe/emit_memory.cc deleted file mode 100644 index 0d7e0170b..000000000 --- a/src/xenia/cpu/llvmbe/emit_memory.cc +++ /dev/null @@ -1,1170 +0,0 @@ -/* - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - -#include - - -using namespace llvm; -using namespace xe::cpu; -using namespace xe::cpu::ppc; - - -namespace xe { -namespace cpu { -namespace llvmbe { - - -// Integer load (A-13) - -XEEMITTER(lbz, 0x88000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + EXTS(D) - // RT <- i56.0 || MEM(EA, 1) - - Value* ea = b.getInt64(XEEXTS16(i.D.DS)); - if (i.D.RA) { - ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); - } - Value* v = e.ReadMemory(i.address, ea, 1, false); - e.update_gpr_value(i.D.RT, v); - - return 0; -} - -XEEMITTER(lbzu, 0x8C000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + EXTS(D) - // RT <- i56.0 || MEM(EA, 1) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); - Value* v = e.ReadMemory(i.address, ea, 1, false); - e.update_gpr_value(i.D.RT, v); - e.update_gpr_value(i.D.RA, ea); - - return 0; -} - -XEEMITTER(lbzux, 0x7C0000EE, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + (RB) - // RT <- i56.0 || MEM(EA, 1) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); - Value* v = e.ReadMemory(i.address, ea, 1, false); - e.update_gpr_value(i.X.RT, v); - e.update_gpr_value(i.X.RA, ea); - - return 0; -} - -XEEMITTER(lbzx, 0x7C0000AE, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + (RB) - // RT <- i56.0 || MEM(EA, 1) - - Value* ea = e.gpr_value(i.X.RB); - if (i.X.RA) { - ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); - } - Value* v = e.ReadMemory(i.address, ea, 1, false); - e.update_gpr_value(i.X.RT, v); - - return 0; -} - -XEEMITTER(ld, 0xE8000000, DS )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + EXTS(DS || 0b00) - // RT <- MEM(EA, 8) - - Value* ea = b.getInt64(XEEXTS16(i.DS.DS << 2)); - if (i.DS.RA) { - ea = b.CreateAdd(e.gpr_value(i.DS.RA), ea); - } - Value* v = e.ReadMemory(i.address, ea, 8, false); - e.update_gpr_value(i.DS.RT, v); - - return 0; -} - -XEEMITTER(ldu, 0xE8000001, DS )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + EXTS(DS || 0b00) - // RT <- MEM(EA, 8) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.DS.RA), - b.getInt64(XEEXTS16(i.DS.DS << 2))); - Value* v = e.ReadMemory(i.address, ea, 8, false); - e.update_gpr_value(i.DS.RT, v); - e.update_gpr_value(i.DS.RA, ea); - - return 0; -} - -XEEMITTER(ldux, 0x7C00006A, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(ldx, 0x7C00002A, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(lha, 0xA8000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + EXTS(D) - // RT <- EXTS(MEM(EA, 2)) - - Value* ea = b.getInt64(XEEXTS16(i.D.DS)); - if (i.D.RA) { - ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); - } - Value* v = b.CreateSExt(e.ReadMemory(i.address, ea, 2, false), - b.getInt64Ty()); - e.update_gpr_value(i.D.RT, v); - - return 0; -} - -XEEMITTER(lhau, 0xAC000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(lhaux, 0x7C0002EE, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(lhax, 0x7C0002AE, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + (RB) - // RT <- EXTS(MEM(EA, 2)) - - Value* ea = e.gpr_value(i.X.RB); - if (i.X.RA) { - ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); - } - Value* v = b.CreateSExt(e.ReadMemory(i.address, ea, 2, false), - b.getInt64Ty()); - e.update_gpr_value(i.X.RT, v); - - return 0; -} - -XEEMITTER(lhz, 0xA0000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + EXTS(D) - // RT <- i48.0 || MEM(EA, 2) - - Value* ea = b.getInt64(XEEXTS16(i.D.DS)); - if (i.D.RA) { - ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); - } - Value* v = e.ReadMemory(i.address, ea, 2, false); - e.update_gpr_value(i.D.RT, v); - - return 0; -} - -XEEMITTER(lhzu, 0xA4000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + EXTS(D) - // RT <- i48.0 || MEM(EA, 2) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); - Value* v = e.ReadMemory(i.address, ea, 2, false); - e.update_gpr_value(i.D.RT, v); - e.update_gpr_value(i.D.RA, ea); - - return 0; -} - -XEEMITTER(lhzux, 0x7C00026E, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + (RB) - // RT <- i48.0 || MEM(EA, 2) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); - Value* v = e.ReadMemory(i.address, ea, 2, false); - e.update_gpr_value(i.X.RT, v); - e.update_gpr_value(i.X.RA, ea); - - return 0; -} - -XEEMITTER(lhzx, 0x7C00022E, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + (RB) - // RT <- i48.0 || MEM(EA, 2) - - Value* ea = e.gpr_value(i.X.RB); - if (i.X.RA) { - ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); - } - Value* v = e.ReadMemory(i.address, ea, 2, false); - e.update_gpr_value(i.X.RT, v); - - return 0; -} - -XEEMITTER(lwa, 0xE8000002, DS )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + EXTS(D || 00) - // RT <- EXTS(MEM(EA, 4)) - - Value* ea = b.getInt64(XEEXTS16(i.DS.DS << 2)); - if (i.DS.RA) { - ea = b.CreateAdd(e.gpr_value(i.DS.RA), ea); - } - Value* v = b.CreateSExt(e.ReadMemory(i.address, ea, 4, false), - b.getInt64Ty()); - e.update_gpr_value(i.DS.RT, v); - - return 0; -} - -XEEMITTER(lwaux, 0x7C0002EA, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + (RB) - // RT <- EXTS(MEM(EA, 4)) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); - Value* v = b.CreateSExt(e.ReadMemory(i.address, ea, 4, false), - b.getInt64Ty()); - e.update_gpr_value(i.X.RT, v); - e.update_gpr_value(i.X.RA, ea); - - return 0; -} - -XEEMITTER(lwax, 0x7C0002AA, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + (RB) - // RT <- EXTS(MEM(EA, 4)) - - Value* ea = e.gpr_value(i.X.RB); - if (i.X.RA) { - ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); - } - Value* v = b.CreateSExt(e.ReadMemory(i.address, ea, 4, false), - b.getInt64Ty()); - e.update_gpr_value(i.X.RT, v); - - return 0; -} - -XEEMITTER(lwz, 0x80000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + EXTS(D) - // RT <- i32.0 || MEM(EA, 4) - - Value* ea = b.getInt64(XEEXTS16(i.D.DS)); - if (i.D.RA) { - ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); - } - Value* v = e.ReadMemory(i.address, ea, 4, false); - e.update_gpr_value(i.D.RT, v); - - return 0; -} - -XEEMITTER(lwzu, 0x84000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + EXTS(D) - // RT <- i32.0 || MEM(EA, 4) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); - Value* v = e.ReadMemory(i.address, ea, 4, false); - e.update_gpr_value(i.D.RT, v); - e.update_gpr_value(i.D.RA, ea); - - return 0; -} - -XEEMITTER(lwzux, 0x7C00006E, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + (RB) - // RT <- i32.0 || MEM(EA, 4) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); - Value* v = e.ReadMemory(i.address, ea, 4, false); - e.update_gpr_value(i.X.RT, v); - e.update_gpr_value(i.X.RA, ea); - - return 0; -} - -XEEMITTER(lwzx, 0x7C00002E, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + (RB) - // RT <- i32.0 || MEM(EA, 4) - - Value* ea = e.gpr_value(i.X.RB); - if (i.X.RA) { - ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); - } - Value* v = e.ReadMemory(i.address, ea, 4, false); - e.update_gpr_value(i.X.RT, v); - - return 0; -} - - -// Integer store (A-14) - -XEEMITTER(stb, 0x98000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + EXTS(D) - // MEM(EA, 1) <- (RS)[56:63] - - Value* ea = b.getInt64(XEEXTS16(i.D.DS)); - if (i.D.RA) { - ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); - } - Value* v = e.gpr_value(i.D.RT); - e.WriteMemory(i.address, ea, 1, v); - - return 0; -} - -XEEMITTER(stbu, 0x9C000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + EXTS(D) - // MEM(EA, 1) <- (RS)[56:63] - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); - Value* v = e.gpr_value(i.D.RT); - e.WriteMemory(i.address, ea, 1, v); - e.update_gpr_value(i.D.RA, ea); - - return 0; -} - -XEEMITTER(stbux, 0x7C0001EE, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + (RB) - // MEM(EA, 1) <- (RS)[56:63] - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); - Value* v = e.gpr_value(i.X.RT); - e.WriteMemory(i.address, ea, 1, v); - e.update_gpr_value(i.X.RA, ea); - - return 0; -} - -XEEMITTER(stbx, 0x7C0001AE, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + (RB) - // MEM(EA, 1) <- (RS)[56:63] - - Value* ea = e.gpr_value(i.X.RB); - if (i.D.RA) { - ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); - } - Value* v = e.gpr_value(i.X.RT); - e.WriteMemory(i.address, ea, 1, v); - - return 0; -} - -XEEMITTER(std, 0xF8000000, DS )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + EXTS(DS || 0b00) - // MEM(EA, 8) <- (RS) - - Value* ea = b.getInt64(XEEXTS16(i.DS.DS << 2)); - if (i.DS.RA) { - ea = b.CreateAdd(e.gpr_value(i.DS.RA), ea); - } - Value* v = e.gpr_value(i.DS.RT); - e.WriteMemory(i.address, ea, 8, v); - - return 0; -} - -XEEMITTER(stdu, 0xF8000001, DS )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + EXTS(DS || 0b00) - // MEM(EA, 8) <- (RS) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.DS.RA), - b.getInt64(XEEXTS16(i.DS.DS << 2))); - Value* v = e.gpr_value(i.DS.RT); - e.WriteMemory(i.address, ea, 8, v); - e.update_gpr_value(i.DS.RA, ea); - - return 0; -} - -XEEMITTER(stdux, 0x7C00016A, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + (RB) - // MEM(EA, 8) <- (RS) - - Value* ea = e.gpr_value(i.X.RB); - if (i.X.RA) { - ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); - } - Value* v = e.gpr_value(i.X.RT); - e.WriteMemory(i.address, ea, 8, v); - - return 0; -} - -XEEMITTER(stdx, 0x7C00012A, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + (RB) - // MEM(EA, 8) <- (RS) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); - Value* v = e.gpr_value(i.X.RT); - e.WriteMemory(i.address, ea, 8, v); - e.update_gpr_value(i.X.RA, ea); - - return 0; -} - -XEEMITTER(sth, 0xB0000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + EXTS(D) - // MEM(EA, 2) <- (RS)[48:63] - - Value* ea = b.getInt64(XEEXTS16(i.D.DS)); - if (i.D.RA) { - ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); - } - Value* v = e.gpr_value(i.D.RT); - e.WriteMemory(i.address, ea, 2, v); - - return 0; -} - -XEEMITTER(sthu, 0xB4000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + EXTS(D) - // MEM(EA, 2) <- (RS)[48:63] - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.D.RA), - b.getInt64(XEEXTS16(i.D.DS))); - Value* v = e.gpr_value(i.D.RT); - e.WriteMemory(i.address, ea, 2, v); - e.update_gpr_value(i.D.RA, ea); - - return 0; -} - -XEEMITTER(sthux, 0x7C00036E, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + (RB) - // MEM(EA, 2) <- (RS)[48:63] - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); - Value* v = e.gpr_value(i.X.RT); - e.WriteMemory(i.address, ea, 2, v); - e.update_gpr_value(i.X.RA, ea); - - return 0; -} - -XEEMITTER(sthx, 0x7C00032E, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + (RB) - // MEM(EA, 2) <- (RS)[48:63] - - Value* ea = e.gpr_value(i.X.RB); - if (i.D.RA) { - ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); - } - Value* v = e.gpr_value(i.X.RT); - e.WriteMemory(i.address, ea, 2, v); - - return 0; -} - -XEEMITTER(stw, 0x90000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + EXTS(D) - // MEM(EA, 4) <- (RS)[32:63] - - Value* ea = b.getInt64(XEEXTS16(i.D.DS)); - if (i.D.RA) { - ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); - } - Value* v = e.gpr_value(i.D.RT); - e.WriteMemory(i.address, ea, 4, v); - - return 0; -} - -XEEMITTER(stwu, 0x94000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + EXTS(D) - // MEM(EA, 4) <- (RS)[32:63] - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.D.RA), - b.getInt64(XEEXTS16(i.D.DS))); - Value* v = e.gpr_value(i.D.RT); - e.WriteMemory(i.address, ea, 4, v); - e.update_gpr_value(i.D.RA, ea); - - return 0; -} - -XEEMITTER(stwux, 0x7C00016E, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + (RB) - // MEM(EA, 4) <- (RS)[32:63] - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); - Value* v = e.gpr_value(i.X.RT); - e.WriteMemory(i.address, ea, 4, v); - e.update_gpr_value(i.X.RA, ea); - - return 0; -} - -XEEMITTER(stwx, 0x7C00012E, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + (RB) - // MEM(EA, 4) <- (RS)[32:63] - - Value* ea = e.gpr_value(i.X.RB); - if (i.X.RA) { - ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); - } - Value* v = e.gpr_value(i.X.RT); - e.WriteMemory(i.address, ea, 4, v); - - return 0; -} - - -// Integer load and store with byte reverse (A-1 - -XEEMITTER(lhbrx, 0x7C00062C, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(lwbrx, 0x7C00042C, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(ldbrx, 0x7C000428, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(sthbrx, 0x7C00072C, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(stwbrx, 0x7C00052C, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(stdbrx, 0x7C000528, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - - -// Integer load and store multiple (A-16) - -XEEMITTER(lmw, 0xB8000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(stmw, 0xBC000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - - -// Integer load and store string (A-17) - -XEEMITTER(lswi, 0x7C0004AA, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(lswx, 0x7C00042A, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(stswi, 0x7C0005AA, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(stswx, 0x7C00052A, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - - -// Memory synchronization (A-18) - -XEEMITTER(eieio, 0x7C0006AC, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(isync, 0x4C00012C, XL )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(ldarx, 0x7C0000A8, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(lwarx, 0x7C000028, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + (RB) - // RESERVE <- 1 - // RESERVE_LENGTH <- 4 - // RESERVE_ADDR <- real_addr(EA) - // RT <- i32.0 || MEM(EA, 4) - - // TODO(benvanik): make this right - - Value* ea = e.gpr_value(i.X.RB); - if (i.X.RA) { - ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); - } - Value* v = e.ReadMemory(i.address, ea, 4, /* acquire */ true); - e.update_gpr_value(i.X.RT, v); - - return 0; -} - -XEEMITTER(stdcx, 0x7C0001AD, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(stwcx, 0x7C00012D, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + (RB) - // RESERVE stuff... - // MEM(EA, 4) <- (RS)[32:63] - // n <- 1 if store performed - // CR0[LT GT EQ SO] = 0b00 || n || XER[SO] - - // TODO(benvanik): make this right - - Value* ea = b.getInt64(XEEXTS16(i.D.DS)); - if (i.D.RA) { - ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); - } - Value* v = e.gpr_value(i.D.RT); - e.WriteMemory(i.address, ea, 4, v, /* release */ true); - - // We always succeed. - e.update_cr_value(0, b.getInt64(1 << 2)); - - return 0; -} - -XEEMITTER(sync, 0x7C0004AC, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - - -// Floating-point load (A-19) - -XEEMITTER(lfd, 0xC8000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + EXTS(D) - // FRT <- MEM(EA, 8) - - Value* ea = b.getInt64(XEEXTS16(i.D.DS)); - if (i.D.RA) { - ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); - } - Value* v = e.ReadMemory(i.address, ea, 8, false); - v = b.CreateBitCast(v, b.getDoubleTy()); - e.update_fpr_value(i.D.RT, v); - - return 0; -} - -XEEMITTER(lfdu, 0xCC000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + EXTS(D) - // FRT <- MEM(EA, 8) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); - Value* v = e.ReadMemory(i.address, ea, 8, false); - v = b.CreateBitCast(v, b.getDoubleTy()); - e.update_fpr_value(i.D.RT, v); - e.update_gpr_value(i.D.RA, ea); - - return 0; -} - -XEEMITTER(lfdux, 0x7C0004EE, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + (RB) - // FRT <- MEM(EA, 8) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); - Value* v = e.ReadMemory(i.address, ea, 8, false); - v = b.CreateBitCast(v, b.getDoubleTy()); - e.update_fpr_value(i.X.RT, v); - e.update_gpr_value(i.X.RA, ea); - - return 0; -} - -XEEMITTER(lfdx, 0x7C0004AE, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + (RB) - // FRT <- MEM(EA, 8) - - Value* ea = e.gpr_value(i.X.RB); - if (i.X.RA) { - ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); - } - Value* v = e.ReadMemory(i.address, ea, 8, false); - v = b.CreateBitCast(v, b.getDoubleTy()); - e.update_fpr_value(i.X.RT, v); - - return 0; -} - -XEEMITTER(lfs, 0xC0000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + EXTS(D) - // FRT <- DOUBLE(MEM(EA, 4)) - - Value* ea = b.getInt64(XEEXTS16(i.D.DS)); - if (i.D.RA) { - ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); - } - Value* v = e.ReadMemory(i.address, ea, 4, false); - v = b.CreateFPExt(b.CreateBitCast(v, b.getFloatTy()), b.getDoubleTy()); - e.update_fpr_value(i.D.RT, v); - - return 0; -} - -XEEMITTER(lfsu, 0xC4000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + EXTS(D) - // FRT <- DOUBLE(MEM(EA, 4)) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); - Value* v = e.ReadMemory(i.address, ea, 4, false); - v = b.CreateFPExt(b.CreateBitCast(v, b.getFloatTy()), b.getDoubleTy()); - e.update_fpr_value(i.D.RT, v); - e.update_gpr_value(i.D.RA, ea); - - return 0; -} - -XEEMITTER(lfsux, 0x7C00046E, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + (RB) - // FRT <- DOUBLE(MEM(EA, 4)) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); - Value* v = e.ReadMemory(i.address, ea, 4, false); - v = b.CreateFPExt(b.CreateBitCast(v, b.getFloatTy()), b.getDoubleTy()); - e.update_fpr_value(i.X.RT, v); - e.update_gpr_value(i.X.RA, ea); - - return 0; -} - -XEEMITTER(lfsx, 0x7C00042E, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + (RB) - // FRT <- DOUBLE(MEM(EA, 4)) - - Value* ea = e.gpr_value(i.X.RB); - if (i.X.RA) { - ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); - } - Value* v = e.ReadMemory(i.address, ea, 4, false); - v = b.CreateFPExt(b.CreateBitCast(v, b.getFloatTy()), b.getDoubleTy()); - e.update_fpr_value(i.X.RT, v); - - return 0; -} - - -// Floating-point store (A-20) - -XEEMITTER(stfd, 0xD8000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + EXTS(D) - // MEM(EA, 8) <- (FRS) - - Value* ea = b.getInt64(XEEXTS16(i.D.DS)); - if (i.D.RA) { - ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); - } - Value* v = e.fpr_value(i.D.RT); - v = b.CreateBitCast(v, b.getInt64Ty()); - e.WriteMemory(i.address, ea, 8, v); - - return 0; -} - -XEEMITTER(stfdu, 0xDC000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + EXTS(D) - // MEM(EA, 8) <- (FRS) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.D.RA), - b.getInt64(XEEXTS16(i.D.DS))); - Value* v = e.fpr_value(i.D.RT); - v = b.CreateBitCast(v, b.getInt64Ty()); - e.WriteMemory(i.address, ea, 8, v); - e.update_gpr_value(i.D.RA, ea); - - return 0; -} - -XEEMITTER(stfdux, 0x7C0005EE, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + (RB) - // MEM(EA, 8) <- (FRS) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); - Value* v = e.fpr_value(i.X.RT); - v = b.CreateBitCast(v, b.getInt64Ty()); - e.WriteMemory(i.address, ea, 8, v); - e.update_gpr_value(i.X.RA, ea); - - return 0; -} - -XEEMITTER(stfdx, 0x7C0005AE, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + (RB) - // MEM(EA, 8) <- (FRS) - - Value* ea = e.gpr_value(i.X.RB); - if (i.X.RA) { - ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); - } - Value* v = e.fpr_value(i.X.RT); - v = b.CreateBitCast(v, b.getInt64Ty()); - e.WriteMemory(i.address, ea, 8, v); - - return 0; -} - -XEEMITTER(stfiwx, 0x7C0007AE, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + (RB) - // MEM(EA, 4) <- (FRS)[32:63] - - Value* ea = e.gpr_value(i.X.RB); - if (i.X.RA) { - ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); - } - Value* v = e.fpr_value(i.X.RT); - v = b.CreateBitCast(v, b.getInt64Ty()); - e.WriteMemory(i.address, ea, 4, v); - - return 0; -} - -XEEMITTER(stfs, 0xD0000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + EXTS(D) - // MEM(EA, 4) <- SINGLE(FRS) - - Value* ea = b.getInt64(XEEXTS16(i.D.DS)); - if (i.D.RA) { - ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); - } - Value* v = e.fpr_value(i.D.RT); - v = b.CreateBitCast(b.CreateFPTrunc(v, b.getFloatTy()), b.getInt32Ty()); - e.WriteMemory(i.address, ea, 4, v); - - return 0; -} - -XEEMITTER(stfsu, 0xD4000000, D )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + EXTS(D) - // MEM(EA, 4) <- SINGLE(FRS) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.D.RA), - b.getInt64(XEEXTS16(i.D.DS))); - Value* v = e.fpr_value(i.D.RT); - v = b.CreateBitCast(b.CreateFPTrunc(v, b.getFloatTy()), b.getInt32Ty()); - e.WriteMemory(i.address, ea, 4, v); - e.update_gpr_value(i.D.RA, ea); - - return 0; -} - -XEEMITTER(stfsux, 0x7C00056E, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // EA <- (RA) + (RB) - // MEM(EA, 4) <- SINGLE(FRS) - // RA <- EA - - Value* ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); - Value* v = e.fpr_value(i.X.RT); - v = b.CreateBitCast(b.CreateFPTrunc(v, b.getFloatTy()), b.getInt32Ty()); - e.WriteMemory(i.address, ea, 4, v); - e.update_gpr_value(i.X.RA, ea); - - return 0; -} - -XEEMITTER(stfsx, 0x7C00052E, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // if RA = 0 then - // b <- 0 - // else - // b <- (RA) - // EA <- b + (RB) - // MEM(EA, 4) <- SINGLE(FRS) - - Value* ea = e.gpr_value(i.X.RB); - if (i.X.RA) { - ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); - } - Value* v = e.fpr_value(i.X.RT); - v = b.CreateBitCast(b.CreateFPTrunc(v, b.getFloatTy()), b.getInt32Ty()); - e.WriteMemory(i.address, ea, 4, v); - - return 0; -} - - -// Cache management (A-27) - -XEEMITTER(dcbf, 0x7C0000AC, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(dcbst, 0x7C00006C, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(dcbt, 0x7C00022C, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // No-op for now. - // TODO(benvanik): use @llvm.prefetch - return 0; -} - -XEEMITTER(dcbtst, 0x7C0001EC, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // No-op for now. - // TODO(benvanik): use @llvm.prefetch - return 0; -} - -XEEMITTER(dcbz, 0x7C0007EC, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - // or dcbz128 0x7C2007EC - XEINSTRNOTIMPLEMENTED(); - return 1; -} - -XEEMITTER(icbi, 0x7C0007AC, X )(EmitterContext& e, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; -} - - -void RegisterEmitCategoryMemory() { - XEREGISTERINSTR(lbz, 0x88000000); - XEREGISTERINSTR(lbzu, 0x8C000000); - XEREGISTERINSTR(lbzux, 0x7C0000EE); - XEREGISTERINSTR(lbzx, 0x7C0000AE); - XEREGISTERINSTR(ld, 0xE8000000); - XEREGISTERINSTR(ldu, 0xE8000001); - XEREGISTERINSTR(ldux, 0x7C00006A); - XEREGISTERINSTR(ldx, 0x7C00002A); - XEREGISTERINSTR(lha, 0xA8000000); - XEREGISTERINSTR(lhau, 0xAC000000); - XEREGISTERINSTR(lhaux, 0x7C0002EE); - XEREGISTERINSTR(lhax, 0x7C0002AE); - XEREGISTERINSTR(lhz, 0xA0000000); - XEREGISTERINSTR(lhzu, 0xA4000000); - XEREGISTERINSTR(lhzux, 0x7C00026E); - XEREGISTERINSTR(lhzx, 0x7C00022E); - XEREGISTERINSTR(lwa, 0xE8000002); - XEREGISTERINSTR(lwaux, 0x7C0002EA); - XEREGISTERINSTR(lwax, 0x7C0002AA); - XEREGISTERINSTR(lwz, 0x80000000); - XEREGISTERINSTR(lwzu, 0x84000000); - XEREGISTERINSTR(lwzux, 0x7C00006E); - XEREGISTERINSTR(lwzx, 0x7C00002E); - XEREGISTERINSTR(stb, 0x98000000); - XEREGISTERINSTR(stbu, 0x9C000000); - XEREGISTERINSTR(stbux, 0x7C0001EE); - XEREGISTERINSTR(stbx, 0x7C0001AE); - XEREGISTERINSTR(std, 0xF8000000); - XEREGISTERINSTR(stdu, 0xF8000001); - XEREGISTERINSTR(stdux, 0x7C00016A); - XEREGISTERINSTR(stdx, 0x7C00012A); - XEREGISTERINSTR(sth, 0xB0000000); - XEREGISTERINSTR(sthu, 0xB4000000); - XEREGISTERINSTR(sthux, 0x7C00036E); - XEREGISTERINSTR(sthx, 0x7C00032E); - XEREGISTERINSTR(stw, 0x90000000); - XEREGISTERINSTR(stwu, 0x94000000); - XEREGISTERINSTR(stwux, 0x7C00016E); - XEREGISTERINSTR(stwx, 0x7C00012E); - XEREGISTERINSTR(lhbrx, 0x7C00062C); - XEREGISTERINSTR(lwbrx, 0x7C00042C); - XEREGISTERINSTR(ldbrx, 0x7C000428); - XEREGISTERINSTR(sthbrx, 0x7C00072C); - XEREGISTERINSTR(stwbrx, 0x7C00052C); - XEREGISTERINSTR(stdbrx, 0x7C000528); - XEREGISTERINSTR(lmw, 0xB8000000); - XEREGISTERINSTR(stmw, 0xBC000000); - XEREGISTERINSTR(lswi, 0x7C0004AA); - XEREGISTERINSTR(lswx, 0x7C00042A); - XEREGISTERINSTR(stswi, 0x7C0005AA); - XEREGISTERINSTR(stswx, 0x7C00052A); - XEREGISTERINSTR(eieio, 0x7C0006AC); - XEREGISTERINSTR(isync, 0x4C00012C); - XEREGISTERINSTR(ldarx, 0x7C0000A8); - XEREGISTERINSTR(lwarx, 0x7C000028); - XEREGISTERINSTR(stdcx, 0x7C0001AD); - XEREGISTERINSTR(stwcx, 0x7C00012D); - XEREGISTERINSTR(sync, 0x7C0004AC); - XEREGISTERINSTR(lfd, 0xC8000000); - XEREGISTERINSTR(lfdu, 0xCC000000); - XEREGISTERINSTR(lfdux, 0x7C0004EE); - XEREGISTERINSTR(lfdx, 0x7C0004AE); - XEREGISTERINSTR(lfs, 0xC0000000); - XEREGISTERINSTR(lfsu, 0xC4000000); - XEREGISTERINSTR(lfsux, 0x7C00046E); - XEREGISTERINSTR(lfsx, 0x7C00042E); - XEREGISTERINSTR(stfd, 0xD8000000); - XEREGISTERINSTR(stfdu, 0xDC000000); - XEREGISTERINSTR(stfdux, 0x7C0005EE); - XEREGISTERINSTR(stfdx, 0x7C0005AE); - XEREGISTERINSTR(stfiwx, 0x7C0007AE); - XEREGISTERINSTR(stfs, 0xD0000000); - XEREGISTERINSTR(stfsu, 0xD4000000); - XEREGISTERINSTR(stfsux, 0x7C00056E); - XEREGISTERINSTR(stfsx, 0x7C00052E); - XEREGISTERINSTR(dcbf, 0x7C0000AC); - XEREGISTERINSTR(dcbst, 0x7C00006C); - XEREGISTERINSTR(dcbt, 0x7C00022C); - XEREGISTERINSTR(dcbtst, 0x7C0001EC); - XEREGISTERINSTR(dcbz, 0x7C0007EC); - XEREGISTERINSTR(icbi, 0x7C0007AC); -} - - -} // namespace llvmbe -} // namespace cpu -} // namespace xe diff --git a/src/xenia/cpu/llvmbe/emitter_context.cc b/src/xenia/cpu/llvmbe/emitter_context.cc deleted file mode 100644 index 52f11470e..000000000 --- a/src/xenia/cpu/llvmbe/emitter_context.cc +++ /dev/null @@ -1,1103 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - -#include - -#include -#include - - -using namespace llvm; -using namespace xe::cpu::llvmbe; -using namespace xe::cpu::ppc; -using namespace xe::cpu::sdb; - - -DEFINE_bool(memory_address_verification, false, - "Whether to add additional checks to generated memory load/stores."); -DEFINE_bool(log_codegen, false, - "Log codegen to stdout."); - - -/** - * This generates function code. - * One context is created and shared for each function to generate. - * Each basic block in the function is created and stashed in one pass, then - * filled in the next. - * - * This context object is a stateful representation of the current machine state - * and all accessors to registers should occur through it. By doing so it's - * possible to exploit the SSA nature of LLVM to reuse register values within - * a function without needing to flush to memory. - * - * Function calls (any branch outside of the function) will result in an - * expensive flush of registers. - * - * TODO(benvanik): track arguments by looking for register reads without writes - * TODO(benvanik): avoid flushing registers for leaf nodes - * TODO(benvnaik): pass return value in LLVM return, not by memory - */ - - -EmitterContext::EmitterContext( - xe_memory_ref memory, - LLVMContext* context, Module* gen_module) { - memory_ = memory; - context_ = context; - gen_module_ = gen_module; - builder_ = new IRBuilder<>(*context_); - - // Function type for all functions. - std::vector args; - args.push_back(PointerType::getUnqual(Type::getInt8Ty(*context))); - args.push_back(Type::getInt64Ty(*context)); - Type* return_type = Type::getVoidTy(*context); - fn_type_ = FunctionType::get( - return_type, ArrayRef(args), false); -} - -EmitterContext::~EmitterContext() { - delete builder_; -} - -int EmitterContext::Init(FunctionSymbol* fn, Function* gen_fn) { - builder_->ClearInsertionPoint(); - - fn_ = fn; - gen_fn_ = gen_fn; - - fn_block_ = NULL; - return_block_ = NULL; - internal_indirection_block_ = NULL; - external_indirection_block_ = NULL; - bb_ = NULL; - - insert_points_.clear(); - bbs_.clear(); - - cia_ = 0; - - access_bits_.Clear(); - - locals_.indirection_target = NULL; - locals_.indirection_cia = NULL; - - locals_.xer = NULL; - locals_.lr = NULL; - locals_.ctr = NULL; - for (size_t n = 0; n < XECOUNT(locals_.cr); n++) { - locals_.cr[n] = NULL; - } - for (size_t n = 0; n < XECOUNT(locals_.gpr); n++) { - locals_.gpr[n] = NULL; - } - for (size_t n = 0; n < XECOUNT(locals_.fpr); n++) { - locals_.fpr[n] = NULL; - } - - if (fn) { - if (FLAGS_log_codegen) { - printf("%s:\n", fn->name()); - } - } - - return 0; -} - -llvm::LLVMContext* EmitterContext::context() { - return context_; -} - -llvm::Module* EmitterContext::gen_module() { - return gen_module_; -} - -FunctionSymbol* EmitterContext::fn() { - return fn_; -} - -llvm::Function* EmitterContext::gen_fn() { - return gen_fn_; -} - -FunctionBlock* EmitterContext::fn_block() { - return fn_block_; -} - -void EmitterContext::PushInsertPoint() { - IRBuilder<>& b = *builder_; - insert_points_.push_back(std::pair( - b.GetInsertBlock(), b.GetInsertPoint())); -} - -void EmitterContext::PopInsertPoint() { - IRBuilder<>& b = *builder_; - std::pair back = insert_points_.back(); - b.SetInsertPoint(back.first, back.second); - insert_points_.pop_back(); -} - -void EmitterContext::GenerateBasicBlocks() { - IRBuilder<>& b = *builder_; - - // Always add an entry block. - BasicBlock* entry = BasicBlock::Create(*context_, "entry", gen_fn_); - b.SetInsertPoint(entry); - - if (FLAGS_trace_user_calls) { - SpillRegisters(); - Value* traceUserCall = gen_module_->getFunction("XeTraceUserCall"); - b.CreateCall4( - traceUserCall, - gen_fn_->arg_begin(), - b.getInt64(fn_->start_address), - ++gen_fn_->arg_begin(), - b.getInt64((uint64_t)fn_)); - } - - // If this function is empty, abort! - if (!fn_->blocks.size()) { - b.CreateRetVoid(); - return; - } - - // Create a return block. - // This spills registers and returns. All non-tail returns should branch - // here to do the return and ensure registers are spilled. - return_block_ = BasicBlock::Create(*context_, "return", gen_fn_); - - // Pass 1 creates all of the blocks - this way we can branch to them. - // We also track registers used so that when know which ones to fill/spill. - for (std::map::iterator it = fn_->blocks.begin(); - it != fn_->blocks.end(); ++it) { - FunctionBlock* block = it->second; - XEIGNORE(PrepareBasicBlock(block)); - } - - // Setup all local variables now that we know what we need. - SetupLocals(); - - // Pass 2 fills in instructions. - for (std::map::iterator it = fn_->blocks.begin(); - it != fn_->blocks.end(); ++it) { - FunctionBlock* block = it->second; - GenerateBasicBlock(block); - } - - // Setup the shared return/indirection/etc blocks now that we know all the - // blocks we need and all the registers used. - GenerateSharedBlocks(); -} - -void EmitterContext::GenerateSharedBlocks() { - IRBuilder<>& b = *builder_; - - Value* indirect_branch = gen_module_->getFunction("XeIndirectBranch"); - - // Setup initial register fill in the entry block. - // We can only do this once all the locals have been created. - b.SetInsertPoint(&gen_fn_->getEntryBlock()); - FillRegisters(); - // Entry always falls through to the second block. - b.CreateBr(bbs_.begin()->second); - - // Setup the spill block in return. - b.SetInsertPoint(return_block_); - SpillRegisters(); - b.CreateRetVoid(); - - // Build indirection block on demand. - // We have already prepped all basic blocks, so we can build these tables now. - if (external_indirection_block_) { - // This will spill registers and call the external function. - // It is only meant for LK=0. - b.SetInsertPoint(external_indirection_block_); - SpillRegisters(); - b.CreateCall3(indirect_branch, - gen_fn_->arg_begin(), - b.CreateLoad(locals_.indirection_target), - b.CreateLoad(locals_.indirection_cia)); - b.CreateRetVoid(); - } - - if (internal_indirection_block_) { - // This will not spill registers and instead try to switch on local blocks. - // If it fails then the external indirection path is taken. - // NOTE: we only generate this if a likely local branch is taken. - b.SetInsertPoint(internal_indirection_block_); - SwitchInst* switch_i = b.CreateSwitch( - b.CreateLoad(locals_.indirection_target), - external_indirection_block_, - static_cast(bbs_.size())); - for (std::map::iterator it = bbs_.begin(); - it != bbs_.end(); ++it) { - switch_i->addCase(b.getInt64(it->first), it->second); - } - } -} - -int EmitterContext::PrepareBasicBlock(FunctionBlock* block) { - // Create the basic block that will end up getting filled during - // generation. - char name[32]; - xesnprintfa(name, XECOUNT(name), "loc_%.8X", block->start_address); - BasicBlock* bb = BasicBlock::Create(*context_, name, gen_fn_); - bbs_.insert(std::pair(block->start_address, bb)); - - // Scan and disassemble each instruction in the block to get accurate - // register access bits. In the future we could do other optimization checks - // in this pass. - // TODO(benvanik): perhaps we want to stash this for each basic block? - // We could use this for faster checking of cr/ca checks/etc. - InstrAccessBits access_bits; - uint8_t* p = xe_memory_addr(memory_, 0); - for (uint32_t ia = block->start_address; ia <= block->end_address; ia += 4) { - InstrData i; - i.address = ia; - i.code = XEGETUINT32BE(p + ia); - i.type = ppc::GetInstrType(i.code); - - // Ignore unknown or ones with no disassembler fn. - if (!i.type || !i.type->disassemble) { - continue; - } - - // We really need to know the registers modified, so die if we've been lazy - // and haven't implemented the disassemble method yet. - ppc::InstrDisasm d; - XEASSERTNOTNULL(i.type->disassemble); - int result_code = i.type->disassemble(i, d); - XEASSERTZERO(result_code); - if (result_code) { - return result_code; - } - - // Accumulate access bits. - access_bits.Extend(d.access_bits); - } - - // Add in access bits to function access bits. - access_bits_.Extend(access_bits); - - return 0; -} - -void EmitterContext::GenerateBasicBlock(FunctionBlock* block) { - IRBuilder<>& b = *builder_; - - BasicBlock* bb = GetBasicBlock(block->start_address); - XEASSERTNOTNULL(bb); - - if (FLAGS_log_codegen) { - printf(" bb %.8X-%.8X:\n", block->start_address, block->end_address); - } - - fn_block_ = block; - bb_ = bb; - - // Move the builder to this block and setup. - b.SetInsertPoint(bb); - //i->setMetadata("some.name", MDNode::get(context, MDString::get(context, pname))); - - Value* invalidInstruction = - gen_module_->getFunction("XeInvalidInstruction"); - Value* traceInstruction = - gen_module_->getFunction("XeTraceInstruction"); - - // Walk instructions in block. - uint8_t* p = xe_memory_addr(memory_, 0); - for (uint32_t ia = block->start_address; ia <= block->end_address; ia += 4) { - InstrData i; - i.address = ia; - i.code = XEGETUINT32BE(p + ia); - i.type = ppc::GetInstrType(i.code); - - if (FLAGS_trace_instructions) { - SpillRegisters(); - b.CreateCall3( - traceInstruction, - gen_fn_->arg_begin(), - b.getInt32(i.address), - b.getInt32(i.code)); - } - - if (!i.type) { - XELOGCPU("Invalid instruction %.8X %.8X", ia, i.code); - SpillRegisters(); - b.CreateCall3( - invalidInstruction, - gen_fn_->arg_begin(), - b.getInt32(i.address), - b.getInt32(i.code)); - continue; - } - - if (FLAGS_log_codegen) { - if (i.type->disassemble) { - ppc::InstrDisasm d; - i.type->disassemble(i, d); - std::string disasm; - d.Dump(disasm); - printf(" %.8X: %.8X %s\n", ia, i.code, disasm.c_str()); - } else { - printf(" %.8X: %.8X %s ???\n", ia, i.code, i.type->name); - } - } - - // TODO(benvanik): debugging information? source/etc? - // builder_>SetCurrentDebugLocation(DebugLoc::get( - // ia >> 8, ia & 0xFF, ctx->cu)); - - typedef int (*InstrEmitter)(EmitterContext& g, IRBuilder<>& b, - InstrData& i); - InstrEmitter emit = (InstrEmitter)i.type->emit; - if (!i.type->emit || emit(*this, *builder_, i)) { - // This printf is handy for sort/uniquify to find instructions. - //printf("unimplinstr %s\n", i.type->name); - - XELOGCPU("Unimplemented instr %.8X %.8X %s", - ia, i.code, i.type->name); - SpillRegisters(); - b.CreateCall3( - invalidInstruction, - gen_fn_->arg_begin(), - b.getInt32(i.address), - b.getInt32(i.code)); - } - } - - // If we fall through, create the branch. - if (block->outgoing_type == FunctionBlock::kTargetNone) { - BasicBlock* next_bb = GetNextBasicBlock(); - XEASSERTNOTNULL(next_bb); - b.CreateBr(next_bb); - } else if (block->outgoing_type == FunctionBlock::kTargetUnknown) { - // Hrm. - // TODO(benvanik): assert this doesn't occur - means a bad sdb run! - XELOGCPU("SDB function scan error in %.8X: bb %.8X has unknown exit", - fn_->start_address, block->start_address); - b.CreateRetVoid(); - } - - // TODO(benvanik): finish up BB -} - -BasicBlock* EmitterContext::GetBasicBlock(uint32_t address) { - std::map::iterator it = bbs_.find(address); - if (it != bbs_.end()) { - return it->second; - } - return NULL; -} - -BasicBlock* EmitterContext::GetNextBasicBlock() { - std::map::iterator it = bbs_.find( - fn_block_->start_address); - ++it; - if (it != bbs_.end()) { - return it->second; - } - return NULL; -} - -BasicBlock* EmitterContext::GetReturnBasicBlock() { - return return_block_; -} - -Function* EmitterContext::GetFunction(FunctionSymbol* symbol) { - StringRef fn_name(symbol->name()); - Function* fn = gen_module_->getFunction(fn_name); - if (fn) { - return fn; - } - - fn = cast(gen_module_->getOrInsertFunction(fn_name, fn_type_)); - fn->setVisibility(GlobalValue::DefaultVisibility); - - // Indicate that the function will never be unwound with an exception. - // If we ever support native exception handling we may need to remove this. - fn->doesNotThrow(); - - // May be worth trying the X86_FastCall, as we only need state in a register. - //f->setCallingConv(CallingConv::Fast); - fn->setCallingConv(CallingConv::C); - - Function::arg_iterator fn_args = fn->arg_begin(); - - // 'state' - Value* fn_arg = fn_args++; - fn_arg->setName("state"); - fn->setDoesNotAlias(1); - fn->setDoesNotCapture(1); - // 'state' should try to be in a register, if possible. - // TODO(benvanik): verify that's a good idea. - // fn->getArgumentList().begin()->addAttr( - // Attribute::get(context, AttrBuilder().addAttribute(Attribute::InReg))); - - // 'lr' - fn_arg = fn_args++; - fn_arg->setName("lr"); - - return fn; -} - -int EmitterContext::GenerateIndirectionBranch(uint32_t cia, Value* target, - bool lk, bool likely_local) { - // This function is called by the control emitters when they know that an - // indirect branch is required. - // It first tries to see if the branch is to an address within the function - // and, if so, uses a local switch table. If that fails because we don't know - // the block the function is regenerated (ACK!). If the target is external - // then an external call occurs. - - IRBuilder<>& b = *builder_; - BasicBlock* next_block = GetNextBasicBlock(); - - PushInsertPoint(); - - // Request builds of the indirection blocks on demand. - // We can't build here because we don't know what registers will be needed - // yet, so we just create the blocks and let GenerateSharedBlocks handle it - // after we are done with all user instructions. - if (!external_indirection_block_) { - // Setup locals in the entry block. - b.SetInsertPoint(&gen_fn_->getEntryBlock()); - locals_.indirection_target = b.CreateAlloca( - b.getInt64Ty(), 0, "indirection_target"); - locals_.indirection_cia = b.CreateAlloca( - b.getInt64Ty(), 0, "indirection_cia"); - - external_indirection_block_ = BasicBlock::Create( - *context_, "external_indirection_block", gen_fn_, return_block_); - } - if (likely_local && !internal_indirection_block_) { - internal_indirection_block_ = BasicBlock::Create( - *context_, "internal_indirection_block", gen_fn_, return_block_); - } - - PopInsertPoint(); - - // Check to see if the target address is within the function. - // If it is jump to that basic block. If the basic block is not found it means - // we have a jump inside the function that wasn't identified via static - // analysis. These are bad as they require function regeneration. - if (likely_local) { - // Note that we only support LK=0, as we are using shared tables. - XEASSERT(!lk); - b.CreateStore(target, locals_.indirection_target); - b.CreateStore(b.getInt64(cia), locals_.indirection_cia); - Value* fn_ge_cmp = b.CreateICmpUGE(target, b.getInt64(fn_->start_address)); - Value* fn_l_cmp = b.CreateICmpULT(target, b.getInt64(fn_->end_address)); - Value* fn_target_cmp = b.CreateAnd(fn_ge_cmp, fn_l_cmp); - b.CreateCondBr(fn_target_cmp, - internal_indirection_block_, external_indirection_block_); - return 0; - } - - // If we are LK=0 jump to the shared indirection block. This prevents us - // from needing to fill the registers again after the call and shares more - // code. - if (!lk) { - b.CreateStore(target, locals_.indirection_target); - b.CreateStore(b.getInt64(cia), locals_.indirection_cia); - b.CreateBr(external_indirection_block_); - } else { - // Slowest path - spill, call the external function, and fill. - // We should avoid this at all costs. - - // Spill registers. We could probably share this. - SpillRegisters(); - - // TODO(benvanik): keep function pointer lookup local. - Value* indirect_branch = gen_module_->getFunction("XeIndirectBranch"); - b.CreateCall3(indirect_branch, - gen_fn_->arg_begin(), - target, - b.getInt64(cia)); - - if (next_block) { - // Only refill if not a tail call. - FillRegisters(); - b.CreateBr(next_block); - } else { - b.CreateRetVoid(); - } - } - - return 0; -} - -Value* EmitterContext::LoadStateValue(uint32_t offset, Type* type, - const char* name) { - IRBuilder<>& b = *builder_; - PointerType* pointerTy = PointerType::getUnqual(type); - Function::arg_iterator args = gen_fn_->arg_begin(); - Value* state_ptr = args; - Value* address = b.CreateInBoundsGEP(state_ptr, b.getInt32(offset)); - Value* ptr = b.CreatePointerCast(address, pointerTy); - return b.CreateLoad(ptr, name); -} - -void EmitterContext::StoreStateValue(uint32_t offset, Type* type, - Value* value) { - IRBuilder<>& b = *builder_; - PointerType* pointerTy = PointerType::getUnqual(type); - Function::arg_iterator args = gen_fn_->arg_begin(); - Value* state_ptr = args; - Value* address = b.CreateInBoundsGEP(state_ptr, b.getInt32(offset)); - Value* ptr = b.CreatePointerCast(address, pointerTy); - b.CreateStore(value, ptr); -} - -void EmitterContext::SetupLocals() { - IRBuilder<>& b = *builder_; - - uint64_t spr_t = access_bits_.spr; - if (spr_t & 0x3) { - locals_.xer = SetupLocal(b.getInt64Ty(), "xer"); - } - spr_t >>= 2; - if (spr_t & 0x3) { - locals_.lr = SetupLocal(b.getInt64Ty(), "lr"); - } - spr_t >>= 2; - if (spr_t & 0x3) { - locals_.ctr = SetupLocal(b.getInt64Ty(), "ctr"); - } - spr_t >>= 2; - // TODO: FPCSR - - char name[32]; - - uint64_t cr_t = access_bits_.cr; - for (int n = 0; n < 8; n++) { - if (cr_t & 3) { - xesnprintfa(name, XECOUNT(name), "cr%d", n); - locals_.cr[n] = SetupLocal(b.getInt8Ty(), name); - } - cr_t >>= 2; - } - - uint64_t gpr_t = access_bits_.gpr; - for (int n = 0; n < 32; n++) { - if (gpr_t & 3) { - xesnprintfa(name, XECOUNT(name), "r%d", n); - locals_.gpr[n] = SetupLocal(b.getInt64Ty(), name); - } - gpr_t >>= 2; - } - - uint64_t fpr_t = access_bits_.fpr; - for (int n = 0; n < 32; n++) { - if (fpr_t & 3) { - xesnprintfa(name, XECOUNT(name), "f%d", n); - locals_.fpr[n] = SetupLocal(b.getDoubleTy(), name); - } - fpr_t >>= 2; - } -} - -Value* EmitterContext::SetupLocal(llvm::Type* type, const char* name) { - IRBuilder<>& b = *builder_; - // Insert into the entry block. - PushInsertPoint(); - b.SetInsertPoint(&gen_fn_->getEntryBlock()); - Value* v = b.CreateAlloca(type, 0, name); - PopInsertPoint(); - return v; -} - -Value* EmitterContext::cia_value() { - return builder_->getInt32(cia_); -} - -void EmitterContext::FillRegisters() { - // This updates all of the local register values from the state memory. - // It should be called on function entry for initial setup and after any - // calls that may modify the registers. - - // TODO(benvanik): use access flags to see if we need to do reads/writes. - // Though LLVM may do a better job than we can, except across calls. - - IRBuilder<>& b = *builder_; - - if (locals_.xer) { - b.CreateStore(LoadStateValue( - offsetof(xe_ppc_state_t, xer), - b.getInt64Ty()), locals_.xer); - } - - if (locals_.lr) { - b.CreateStore(LoadStateValue( - offsetof(xe_ppc_state_t, lr), - b.getInt64Ty()), locals_.lr); - } - - if (locals_.ctr) { - b.CreateStore(LoadStateValue( - offsetof(xe_ppc_state_t, ctr), - b.getInt64Ty()), locals_.ctr); - } - - // Fill the split CR values by extracting each one from the CR. - // This could probably be done faster via an extractvalues or something. - // Perhaps we could also change it to be a vector<8*i8>. - Value* cr = NULL; - for (size_t n = 0; n < XECOUNT(locals_.cr); n++) { - Value* cr_n = locals_.cr[n]; - if (!cr_n) { - continue; - } - if (!cr) { - cr = LoadStateValue( - offsetof(xe_ppc_state_t, cr), - b.getInt64Ty()); - } - b.CreateStore( - b.CreateTrunc(b.CreateAnd(b.CreateLShr(cr, (28 - n * 4)), 0xF), - b.getInt8Ty()), cr_n); - } - - for (size_t n = 0; n < XECOUNT(locals_.gpr); n++) { - if (locals_.gpr[n]) { - b.CreateStore(LoadStateValue( - (uint32_t)offsetof(xe_ppc_state_t, r) + 8 * n, - b.getInt64Ty()), locals_.gpr[n]); - } - } - - for (size_t n = 0; n < XECOUNT(locals_.fpr); n++) { - if (locals_.fpr[n]) { - b.CreateStore(LoadStateValue( - (uint32_t)offsetof(xe_ppc_state_t, f) + 8 * n, - b.getDoubleTy()), locals_.fpr[n]); - } - } -} - -void EmitterContext::SpillRegisters() { - // This flushes all local registers (if written) to the register bank and - // resets their values. - // - // TODO(benvanik): only flush if actually required, or selective flushes. - - IRBuilder<>& b = *builder_; - - if (locals_.xer) { - StoreStateValue( - offsetof(xe_ppc_state_t, xer), - b.getInt64Ty(), - b.CreateLoad(locals_.xer)); - } - - if (locals_.lr) { - StoreStateValue( - offsetof(xe_ppc_state_t, lr), - b.getInt64Ty(), - b.CreateLoad(locals_.lr)); - } - - if (locals_.ctr) { - StoreStateValue( - offsetof(xe_ppc_state_t, ctr), - b.getInt64Ty(), - b.CreateLoad(locals_.ctr)); - } - - // Stitch together all split CR values. - // TODO(benvanik): don't flush across calls? - Value* cr = NULL; - for (size_t n = 0; n < XECOUNT(locals_.cr); n++) { - Value* cr_n = locals_.cr[n]; - if (!cr_n) { - continue; - } - cr_n = b.CreateZExt(b.CreateLoad(cr_n), b.getInt64Ty()); - if (!cr) { - cr = b.CreateShl(cr_n, n * 4); - } else { - cr = b.CreateOr(cr, b.CreateShl(cr_n, n * 4)); - } - } - if (cr) { - StoreStateValue( - offsetof(xe_ppc_state_t, cr), - b.getInt64Ty(), - cr); - } - - for (uint32_t n = 0; n < XECOUNT(locals_.gpr); n++) { - Value* v = locals_.gpr[n]; - if (v) { - StoreStateValue( - offsetof(xe_ppc_state_t, r) + 8 * n, - b.getInt64Ty(), - b.CreateLoad(locals_.gpr[n])); - } - } - - for (uint32_t n = 0; n < XECOUNT(locals_.fpr); n++) { - Value* v = locals_.fpr[n]; - if (v) { - StoreStateValue( - offsetof(xe_ppc_state_t, f) + 8 * n, - b.getDoubleTy(), - b.CreateLoad(locals_.fpr[n])); - } - } -} - -Value* EmitterContext::xer_value() { - XEASSERTNOTNULL(locals_.xer); - IRBuilder<>& b = *builder_; - return b.CreateLoad(locals_.xer); -} - -void EmitterContext::update_xer_value(Value* value) { - XEASSERTNOTNULL(locals_.xer); - IRBuilder<>& b = *builder_; - - // Extend to 64bits if needed. - if (!value->getType()->isIntegerTy(64)) { - value = b.CreateZExt(value, b.getInt64Ty()); - } - b.CreateStore(value, locals_.xer); -} - -void EmitterContext::update_xer_with_overflow(Value* value) { - XEASSERTNOTNULL(locals_.xer); - IRBuilder<>& b = *builder_; - - // Expects a i1 indicating overflow. - // Trust the caller that if it's larger than that it's already truncated. - if (!value->getType()->isIntegerTy(64)) { - value = b.CreateZExt(value, b.getInt64Ty()); - } - - Value* xer = xer_value(); - xer = b.CreateAnd(xer, 0xFFFFFFFFBFFFFFFF); // clear bit 30 - xer = b.CreateOr(xer, b.CreateShl(value, 31)); - xer = b.CreateOr(xer, b.CreateShl(value, 30)); - b.CreateStore(xer, locals_.xer); -} - -void EmitterContext::update_xer_with_carry(Value* value) { - XEASSERTNOTNULL(locals_.xer); - IRBuilder<>& b = *builder_; - - // Expects a i1 indicating carry. - // Trust the caller that if it's larger than that it's already truncated. - if (!value->getType()->isIntegerTy(64)) { - value = b.CreateZExt(value, b.getInt64Ty()); - } - - Value* xer = xer_value(); - xer = b.CreateAnd(xer, 0xFFFFFFFFDFFFFFFF); // clear bit 29 - xer = b.CreateOr(xer, b.CreateShl(value, 29)); - b.CreateStore(xer, locals_.xer); -} - -void EmitterContext::update_xer_with_overflow_and_carry(Value* value) { - XEASSERTNOTNULL(locals_.xer); - IRBuilder<>& b = *builder_; - - // Expects a i1 indicating overflow. - // Trust the caller that if it's larger than that it's already truncated. - if (!value->getType()->isIntegerTy(64)) { - value = b.CreateZExt(value, b.getInt64Ty()); - } - - // This is effectively an update_xer_with_overflow followed by an - // update_xer_with_carry, but since the logic is largely the same share it. - Value* xer = xer_value(); - xer = b.CreateAnd(xer, 0xFFFFFFFF9FFFFFFF); // clear bit 30 & 29 - xer = b.CreateOr(xer, b.CreateShl(value, 31)); - xer = b.CreateOr(xer, b.CreateShl(value, 30)); - xer = b.CreateOr(xer, b.CreateShl(value, 29)); - b.CreateStore(xer, locals_.xer); -} - -Value* EmitterContext::lr_value() { - XEASSERTNOTNULL(locals_.lr); - IRBuilder<>& b = *builder_; - return b.CreateLoad(locals_.lr); -} - -void EmitterContext::update_lr_value(Value* value) { - XEASSERTNOTNULL(locals_.lr); - IRBuilder<>& b = *builder_; - - // Extend to 64bits if needed. - if (!value->getType()->isIntegerTy(64)) { - value = b.CreateZExt(value, b.getInt64Ty()); - } - b.CreateStore(value, locals_.lr); -} - -Value* EmitterContext::ctr_value() { - XEASSERTNOTNULL(locals_.ctr); - IRBuilder<>& b = *builder_; - - return b.CreateLoad(locals_.ctr); -} - -void EmitterContext::update_ctr_value(Value* value) { - XEASSERTNOTNULL(locals_.ctr); - IRBuilder<>& b = *builder_; - - // Extend to 64bits if needed. - if (!value->getType()->isIntegerTy(64)) { - value = b.CreateZExt(value, b.getInt64Ty()); - } - b.CreateStore(value, locals_.ctr); -} - -Value* EmitterContext::cr_value(uint32_t n) { - XEASSERT(n >= 0 && n < 8); - XEASSERTNOTNULL(locals_.cr[n]); - IRBuilder<>& b = *builder_; - - Value* v = b.CreateLoad(locals_.cr[n]); - v = b.CreateZExt(v, b.getInt64Ty()); - return v; -} - -void EmitterContext::update_cr_value(uint32_t n, Value* value) { - XEASSERT(n >= 0 && n < 8); - XEASSERTNOTNULL(locals_.cr[n]); - IRBuilder<>& b = *builder_; - - // Truncate to 8 bits if needed. - // TODO(benvanik): also widen? - if (!value->getType()->isIntegerTy(8)) { - value = b.CreateTrunc(value, b.getInt8Ty()); - } - - b.CreateStore(value, locals_.cr[n]); -} - -void EmitterContext::update_cr_with_cond( - uint32_t n, Value* lhs, Value* rhs, bool is_signed) { - IRBuilder<>& b = *builder_; - - // bit0 = RA < RB - // bit1 = RA > RB - // bit2 = RA = RB - // bit3 = XER[SO] - - // TODO(benvanik): inline this using the x86 cmp instruction - this prevents - // the need for a lot of the compares and ensures we lower to the best - // possible x86. - // Value* cmp = InlineAsm::get( - // FunctionType::get(), - // "cmp $0, $1 \n" - // "mov from compare registers \n", - // "r,r", ?? - // true); - - Value* is_lt = is_signed ? - b.CreateICmpSLT(lhs, rhs) : b.CreateICmpULT(lhs, rhs); - Value* is_gt = is_signed ? - b.CreateICmpSGT(lhs, rhs) : b.CreateICmpUGT(lhs, rhs); - Value* cp = b.CreateSelect(is_gt, b.getInt8(1 << 1), b.getInt8(1 << 2)); - Value* c = b.CreateSelect(is_lt, b.getInt8(1 << 0), cp); - - // TODO(benvanik): set bit 4 to XER[SO] - - // Insert the 4 bits into their location in the CR. - update_cr_value(n, c); -} - -Value* EmitterContext::gpr_value(uint32_t n) { - XEASSERT(n >= 0 && n < 32); - XEASSERTNOTNULL(locals_.gpr[n]); - IRBuilder<>& b = *builder_; - - // Actually r0 is writable, even though nobody should ever do that. - // Perhaps we can check usage and enable this if safe? - // if (n == 0) { - // // Always force zero to a constant - this should help LLVM. - // return b.getInt64(0); - // } - - return b.CreateLoad(locals_.gpr[n]); -} - -void EmitterContext::update_gpr_value(uint32_t n, Value* value) { - XEASSERT(n >= 0 && n < 32); - XEASSERTNOTNULL(locals_.gpr[n]); - IRBuilder<>& b = *builder_; - - // See above - r0 can be written. - // if (n == 0) { - // // Ignore writes to zero. - // return; - // } - - // Extend to 64bits if needed. - if (!value->getType()->isIntegerTy(64)) { - value = b.CreateZExt(value, b.getInt64Ty()); - } - - b.CreateStore(value, locals_.gpr[n]); -} - -Value* EmitterContext::fpr_value(uint32_t n) { - XEASSERT(n >= 0 && n < 32); - XEASSERTNOTNULL(locals_.fpr[n]); - IRBuilder<>& b = *builder_; - return b.CreateLoad(locals_.fpr[n]); -} - -void EmitterContext::update_fpr_value(uint32_t n, Value* value) { - XEASSERT(n >= 0 && n < 32); - XEASSERTNOTNULL(locals_.fpr[n]); - IRBuilder<>& b = *builder_; - value = b.CreateFPExtOrFPTrunc(value, b.getDoubleTy()); - b.CreateStore(value, locals_.fpr[n]); -} - -Value* EmitterContext::GetMembase() { - Value* v = gen_module_->getGlobalVariable("xe_memory_base"); - return builder_->CreateLoad(v); -} - -Value* EmitterContext::GetMemoryAddress(uint32_t cia, Value* addr) { - IRBuilder<>& b = *builder_; - - // Input address is always in 32-bit space. - addr = b.CreateAnd(addr, UINT_MAX); - - // Add runtime memory address checks, if needed. - if (FLAGS_memory_address_verification) { - BasicBlock* invalid_bb = BasicBlock::Create(*context_, "", gen_fn_); - BasicBlock* valid_bb = BasicBlock::Create(*context_, "", gen_fn_); - - // The heap starts at 0x1000 - if we write below that we're boned. - Value* gt = b.CreateICmpUGE(addr, b.getInt64(0x00001000)); - b.CreateCondBr(gt, valid_bb, invalid_bb); - - b.SetInsertPoint(invalid_bb); - Value* access_violation = gen_module_->getFunction("XeAccessViolation"); - SpillRegisters(); - b.CreateCall3(access_violation, - gen_fn_->arg_begin(), - b.getInt32(cia), - addr); - b.CreateBr(valid_bb); - - b.SetInsertPoint(valid_bb); - } - - // Rebase off of memory base pointer. - return b.CreateInBoundsGEP(GetMembase(), addr); -} - -Value* EmitterContext::ReadMemory( - uint32_t cia, Value* addr, uint32_t size, bool acquire) { - IRBuilder<>& b = *builder_; - - Type* dataTy = NULL; - bool needs_swap = false; - switch (size) { - case 1: - dataTy = b.getInt8Ty(); - break; - case 2: - dataTy = b.getInt16Ty(); - needs_swap = true; - break; - case 4: - dataTy = b.getInt32Ty(); - needs_swap = true; - break; - case 8: - dataTy = b.getInt64Ty(); - needs_swap = true; - break; - default: - XEASSERTALWAYS(); - return NULL; - } - PointerType* pointerTy = PointerType::getUnqual(dataTy); - - Value* address = GetMemoryAddress(cia, addr); - Value* ptr = b.CreatePointerCast(address, pointerTy); - LoadInst* load_value = b.CreateLoad(ptr); - if (acquire) { - load_value->setAlignment(size); - load_value->setVolatile(true); - load_value->setAtomic(Acquire); - } - Value* value = load_value; - - // Swap after loading. - // TODO(benvanik): find a way to avoid this! - if (needs_swap) { - Function* bswap = Intrinsic::getDeclaration( - gen_module_, Intrinsic::bswap, dataTy); - value = b.CreateCall(bswap, value); - } - - return value; -} - -void EmitterContext::WriteMemory( - uint32_t cia, Value* addr, uint32_t size, Value* value, bool release) { - IRBuilder<>& b = *builder_; - - Type* dataTy = NULL; - bool needs_swap = false; - switch (size) { - case 1: - dataTy = b.getInt8Ty(); - break; - case 2: - dataTy = b.getInt16Ty(); - needs_swap = true; - break; - case 4: - dataTy = b.getInt32Ty(); - needs_swap = true; - break; - case 8: - dataTy = b.getInt64Ty(); - needs_swap = true; - break; - default: - XEASSERTALWAYS(); - return; - } - PointerType* pointerTy = PointerType::getUnqual(dataTy); - - Value* address = GetMemoryAddress(cia, addr); - Value* ptr = b.CreatePointerCast(address, pointerTy); - - // Truncate, if required. - if (value->getType() != dataTy) { - value = b.CreateTrunc(value, dataTy); - } - - // Swap before storing. - // TODO(benvanik): find a way to avoid this! - if (needs_swap) { - Function* bswap = Intrinsic::getDeclaration( - gen_module_, Intrinsic::bswap, dataTy); - value = b.CreateCall(bswap, value); - } - - StoreInst* store_value = b.CreateStore(value, ptr); - if (release) { - store_value->setAlignment(size); - store_value->setVolatile(true); - store_value->setAtomic(Release); - } -} diff --git a/src/xenia/cpu/llvmbe/emitter_context.h b/src/xenia/cpu/llvmbe/emitter_context.h deleted file mode 100644 index d8bf22e84..000000000 --- a/src/xenia/cpu/llvmbe/emitter_context.h +++ /dev/null @@ -1,146 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_CPU_LLVMBE_EMITTER_CONTEXT_H_ -#define XENIA_CPU_LLVMBE_EMITTER_CONTEXT_H_ - -#include -#include -#include -#include -#include -#include - -#include -#include - - -namespace xe { -namespace cpu { -namespace llvmbe { - - -class EmitterContext { -public: - EmitterContext( - xe_memory_ref memory, - llvm::LLVMContext* context, llvm::Module* gen_module); - ~EmitterContext(); - - int Init(sdb::FunctionSymbol* fn, llvm::Function* gen_fn); - - llvm::LLVMContext* context(); - llvm::Module* gen_module(); - - sdb::FunctionSymbol* fn(); - llvm::Function* gen_fn(); - sdb::FunctionBlock* fn_block(); - - void PushInsertPoint(); - void PopInsertPoint(); - - void GenerateBasicBlocks(); - llvm::BasicBlock* GetBasicBlock(uint32_t address); - llvm::BasicBlock* GetNextBasicBlock(); - llvm::BasicBlock* GetReturnBasicBlock(); - - llvm::Function* GetFunction(sdb::FunctionSymbol* symbol); - - int GenerateIndirectionBranch(uint32_t cia, llvm::Value* target, - bool lk, bool likely_local); - - llvm::Value* LoadStateValue(uint32_t offset, llvm::Type* type, - const char* name = ""); - void StoreStateValue(uint32_t offset, llvm::Type* type, llvm::Value* value); - - llvm::Value* cia_value(); - - llvm::Value* SetupLocal(llvm::Type* type, const char* name); - void FillRegisters(); - void SpillRegisters(); - - llvm::Value* xer_value(); - void update_xer_value(llvm::Value* value); - void update_xer_with_overflow(llvm::Value* value); - void update_xer_with_carry(llvm::Value* value); - void update_xer_with_overflow_and_carry(llvm::Value* value); - - llvm::Value* lr_value(); - void update_lr_value(llvm::Value* value); - - llvm::Value* ctr_value(); - void update_ctr_value(llvm::Value* value); - - llvm::Value* cr_value(uint32_t n); - void update_cr_value(uint32_t n, llvm::Value* value); - void update_cr_with_cond(uint32_t n, llvm::Value* lhs, llvm::Value* rhs, - bool is_signed); - - llvm::Value* gpr_value(uint32_t n); - void update_gpr_value(uint32_t n, llvm::Value* value); - llvm::Value* fpr_value(uint32_t n); - void update_fpr_value(uint32_t n, llvm::Value* value); - - llvm::Value* GetMembase(); - llvm::Value* GetMemoryAddress(uint32_t cia, llvm::Value* addr); - llvm::Value* ReadMemory( - uint32_t cia, llvm::Value* addr, uint32_t size, bool acquire = false); - void WriteMemory( - uint32_t cia, llvm::Value* addr, uint32_t size, llvm::Value* value, - bool release = false); - -private: - void GenerateSharedBlocks(); - int PrepareBasicBlock(sdb::FunctionBlock* block); - void GenerateBasicBlock(sdb::FunctionBlock* block); - void SetupLocals(); - - xe_memory_ref memory_; - llvm::LLVMContext* context_; - llvm::Module* gen_module_; - llvm::IRBuilder<>* builder_; - llvm::FunctionType* fn_type_; - - sdb::FunctionSymbol* fn_; - llvm::Function* gen_fn_; - sdb::FunctionBlock* fn_block_; - llvm::BasicBlock* return_block_; - llvm::BasicBlock* internal_indirection_block_; - llvm::BasicBlock* external_indirection_block_; - llvm::BasicBlock* bb_; - - std::vector > - insert_points_; - - std::map bbs_; - - // Address of the instruction being generated. - uint32_t cia_; - - ppc::InstrAccessBits access_bits_; - struct { - llvm::Value* indirection_target; - llvm::Value* indirection_cia; - - llvm::Value* xer; - llvm::Value* lr; - llvm::Value* ctr; - llvm::Value* cr[8]; - llvm::Value* gpr[32]; - llvm::Value* fpr[32]; - } locals_; -}; - - -} // namespace llvmbe -} // namespace cpu -} // namespace xe - - -#endif // XENIA_CPU_LLVMBE_EMITTER_CONTEXT_H_ diff --git a/src/xenia/cpu/llvmbe/llvm_backend.cc b/src/xenia/cpu/llvmbe/llvm_backend.cc deleted file mode 100644 index f429db4c5..000000000 --- a/src/xenia/cpu/llvmbe/llvm_backend.cc +++ /dev/null @@ -1,78 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - - -using namespace llvm; -using namespace xe; -using namespace xe::cpu; -using namespace xe::cpu::llvmbe; - - -namespace { - void InitializeIfNeeded(); - void CleanupOnShutdown(); - - void InitializeIfNeeded() { - static bool has_initialized = false; - if (has_initialized) { - return; - } - has_initialized = true; - - LLVMLinkInInterpreter(); - LLVMLinkInJIT(); - InitializeNativeTarget(); - - llvm_start_multithreaded(); - - llvmbe::RegisterEmitCategoryALU(); - llvmbe::RegisterEmitCategoryControl(); - llvmbe::RegisterEmitCategoryFPU(); - llvmbe::RegisterEmitCategoryMemory(); - - atexit(CleanupOnShutdown); - } - - void CleanupOnShutdown() { - llvm_shutdown(); - } -} - - -LLVMBackend::LLVMBackend() : - Backend() { - InitializeIfNeeded(); -} - -LLVMBackend::~LLVMBackend() { -} - -CodeUnitBuilder* LLVMBackend::CreateCodeUnitBuilder() { - return NULL; -} - -LibraryLoader* LLVMBackend::CreateLibraryLoader() { - return NULL; -} - -JIT* LLVMBackend::CreateJIT(xe_memory_ref memory, FunctionTable* fn_table) { - return new LLVMJIT(memory, fn_table); -} diff --git a/src/xenia/cpu/llvmbe/llvm_backend.h b/src/xenia/cpu/llvmbe/llvm_backend.h deleted file mode 100644 index 90c3f8269..000000000 --- a/src/xenia/cpu/llvmbe/llvm_backend.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_CPU_LLVMBE_LLVM_BACKEND_H_ -#define XENIA_CPU_LLVMBE_LLVM_BACKEND_H_ - -#include - -#include - - -namespace xe { -namespace cpu { -namespace llvmbe { - - -class LLVMBackend : public Backend { -public: - LLVMBackend(); - virtual ~LLVMBackend(); - - virtual CodeUnitBuilder* CreateCodeUnitBuilder(); - virtual LibraryLinker* CreateLibraryLinker(); - virtual LibraryLoader* CreateLibraryLoader(); - - virtual JIT* CreateJIT(xe_memory_ref memory, FunctionTable* fn_table); - -protected: -}; - - -} // namespace llvmbe -} // namespace cpu -} // namespace xe - - -#endif // XENIA_CPU_LLVMBE_LLVM_BACKEND_H_ diff --git a/src/xenia/cpu/llvmbe/llvm_code_unit_builder.cc b/src/xenia/cpu/llvmbe/llvm_code_unit_builder.cc deleted file mode 100644 index 18e1db947..000000000 --- a/src/xenia/cpu/llvmbe/llvm_code_unit_builder.cc +++ /dev/null @@ -1,264 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - -using namespace llvm; -using namespace xe; -using namespace xe::cpu; -using namespace xe::cpu::llvmbe; -using namespace xe::cpu::sdb; - - -LLVMCodeUnitBuilder::LLVMCodeUnitBuilder( - xe_memory_ref memory, LLVMContext* context) : - CodeUnitBuilder(memory), - context_(context) { -} - -LLVMCodeUnitBuilder::~LLVMCodeUnitBuilder() { - Reset(); -} - -Module* LLVMCodeUnitBuilder::module() { - return module_; -} - -int LLVMCodeUnitBuilder::Init(const char* module_name, - const char* module_path) { - Reset(); - - // Create LLVM module. - module_ = new Module(module_name, *context_); - - // Create the emitter used to generate functions. - emitter_ = new EmitterContext(memory_, context_, module_); - - // Setup optimization pass. - fpm_ = new FunctionPassManager(module_); - if (FLAGS_optimize_ir_functions) { - PassManagerBuilder pmb; - pmb.OptLevel = 3; - pmb.SizeLevel = 0; - pmb.Inliner = createFunctionInliningPass(); - pmb.Vectorize = true; - pmb.LoopVectorize = true; - pmb.populateFunctionPassManager(*fpm_); - } - // TODO(benvanik): disable verifier in release builds? - fpm_->add(createVerifierPass()); - - // Setup a debug info builder. - // This is used when creating any debug info. We may want to go more - // fine grained than this, but for now it's something. - char dir[XE_MAX_PATH]; - XEIGNORE(xestrcpya(dir, XECOUNT(dir), module_path)); - char* slash = xestrrchra(dir, '/'); - if (slash) { - *(slash + 1) = 0; - } - di_builder_ = new DIBuilder(*module_); - di_builder_->createCompileUnit( - dwarf::DW_LANG_C99, //0x8010, - StringRef(module_name), - StringRef(dir), - StringRef("xenia"), - true, - StringRef(""), - 0); - cu_ = (MDNode*)di_builder_->getCU(); - - return 0; -} - -int LLVMCodeUnitBuilder::MakeFunction(FunctionSymbol* symbol) { - return MakeFunction(symbol, NULL); -} - -int LLVMCodeUnitBuilder::MakeFunction(FunctionSymbol* symbol, - Function** out_fn) { - int result_code = 0; - - // Create the function (and setup args/attributes/etc). - Function* fn = emitter_->GetFunction(symbol); - - // If already defined, ignore. - if (!fn->isDeclaration()) { - if (out_fn) { - *out_fn = fn; - } - return 0; - } - - switch (symbol->type) { - case FunctionSymbol::User: - result_code = MakeUserFunction(symbol, fn); - break; - case FunctionSymbol::Kernel: - if (symbol->kernel_export && symbol->kernel_export->is_implemented) { - result_code = MakePresentImportFunction(symbol, fn); - } else { - result_code = MakeMissingImportFunction(symbol, fn); - } - break; - default: - XEASSERTALWAYS(); - return 1; - } - if (result_code) { - return result_code; - } - - // Run the optimizer on the function. - // Doing this here keeps the size of the IR small and speeds up the later - // passes. - OptimizeFunction(fn); - - // Add to map for processing later. - functions_.insert(std::pair(symbol->start_address, fn)); - - if (out_fn) { - *out_fn = fn; - } - - return 0; -} - -int LLVMCodeUnitBuilder::MakeUserFunction(FunctionSymbol* symbol, - Function* fn) { - // Setup emitter. - emitter_->Init(symbol, fn); - - // Emit. - emitter_->GenerateBasicBlocks(); - - return 0; -} - -int LLVMCodeUnitBuilder::MakePresentImportFunction(FunctionSymbol* symbol, - Function* fn) { - LLVMContext& context = *context_; - - // Pick names. - // We have both the shim function pointer and the shim data pointer. - char shim_name[256]; - xesnprintfa(shim_name, XECOUNT(shim_name), - "__shim_%s", symbol->kernel_export->name); - char shim_data_name[256]; - xesnprintfa(shim_data_name, XECOUNT(shim_data_name), - "__shim_data_%s", symbol->kernel_export->name); - - // Hardcoded to 64bits. - Type* intPtrTy = IntegerType::get(context, 64); - Type* int8PtrTy = PointerType::getUnqual(Type::getInt8Ty(context)); - - // Declare shim function. - std::vector shimArgs; - shimArgs.push_back(int8PtrTy); - shimArgs.push_back(int8PtrTy); - FunctionType* shimTy = FunctionType::get( - Type::getVoidTy(context), shimArgs, false); - Function* shim = Function::Create( - shimTy, Function::ExternalLinkage, shim_name, module_); - - GlobalVariable* shim_data = new GlobalVariable( - *module_, int8PtrTy, false, GlobalValue::ExternalLinkage, 0, - shim_data_name); - shim_data->setInitializer(ConstantExpr::getIntToPtr( - ConstantInt::get(intPtrTy, 0), int8PtrTy)); - - BasicBlock* block = BasicBlock::Create(context, "entry", fn); - IRBuilder<> b(block); - - if (FLAGS_trace_kernel_calls) { - Value* traceKernelCall = module_->getFunction("XeTraceKernelCall"); - b.CreateCall4( - traceKernelCall, - fn->arg_begin(), - b.getInt64(symbol->start_address), - ++fn->arg_begin(), - b.getInt64((uint64_t)symbol->kernel_export)); - } - - b.CreateCall2( - shim, - fn->arg_begin(), - b.CreateLoad(shim_data)); - - b.CreateRetVoid(); - - return 0; -} - -int LLVMCodeUnitBuilder::MakeMissingImportFunction(FunctionSymbol* symbol, - Function* fn) { - BasicBlock* block = BasicBlock::Create(*context_, "entry", fn); - IRBuilder<> b(block); - - if (FLAGS_trace_kernel_calls) { - Value* traceKernelCall = module_->getFunction("XeTraceKernelCall"); - b.CreateCall4( - traceKernelCall, - fn->arg_begin(), - b.getInt64(symbol->start_address), - ++fn->arg_begin(), - b.getInt64((uint64_t)symbol->kernel_export)); - } - - b.CreateRetVoid(); - - return 0; -} - -void LLVMCodeUnitBuilder::OptimizeFunction(Function* fn) { - //fn->dump(); - fpm_->run(*fn); - fn->dump(); -} - -int LLVMCodeUnitBuilder::Finalize() { - // Finalize debug info. - di_builder_->finalize(); - - // TODO(benvanik): run module optimizations, if enabled. - - return 0; -} - -void LLVMCodeUnitBuilder::Reset() { - functions_.clear(); - - delete emitter_; - emitter_ = NULL; - delete di_builder_; - di_builder_ = NULL; - delete fpm_; - fpm_ = NULL; - delete module_; - module_ = NULL; -} diff --git a/src/xenia/cpu/llvmbe/llvm_code_unit_builder.h b/src/xenia/cpu/llvmbe/llvm_code_unit_builder.h deleted file mode 100644 index 4557cc4b1..000000000 --- a/src/xenia/cpu/llvmbe/llvm_code_unit_builder.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_CPU_LLVMBE_LLVM_CODE_UNIT_BUILDER_H_ -#define XENIA_CPU_LLVMBE_LLVM_CODE_UNIT_BUILDER_H_ - -#include -#include - -#include -#include - - -namespace llvm { - class DIBuilder; - class Function; - class FunctionPassManager; - class LLVMContext; - class Module; - class MDNode; -} - - -namespace xe { -namespace cpu { -namespace llvmbe { - - -class EmitterContext; - - -class LLVMCodeUnitBuilder : public CodeUnitBuilder { -public: - LLVMCodeUnitBuilder(xe_memory_ref memory, llvm::LLVMContext* context); - virtual ~LLVMCodeUnitBuilder(); - - llvm::Module* module(); - - virtual int Init(const char* module_name, const char* module_path); - virtual int MakeFunction(sdb::FunctionSymbol* symbol); - int MakeFunction(sdb::FunctionSymbol* symbol, llvm::Function** out_fn); - virtual int Finalize(); - virtual void Reset(); - -private: - llvm::Function* CreateFunctionDeclaration(const char* name); - int MakeUserFunction(sdb::FunctionSymbol* symbol, - llvm::Function* f); - int MakePresentImportFunction(sdb::FunctionSymbol* symbol, - llvm::Function* f); - int MakeMissingImportFunction(sdb::FunctionSymbol* symbol, - llvm::Function* f); - void OptimizeFunction(llvm::Function* f); - - llvm::LLVMContext* context_; - llvm::Module* module_; - llvm::FunctionPassManager* fpm_; - llvm::DIBuilder* di_builder_; - llvm::MDNode* cu_; - EmitterContext* emitter_; - - std::map functions_; -}; - - -} // namespace llvmbe -} // namespace cpu -} // namespace xe - - -#endif // XENIA_CPU_LLVMBE_LLVM_CODE_UNIT_BUILDER_H_ diff --git a/src/xenia/cpu/llvmbe/llvm_exports.cc b/src/xenia/cpu/llvmbe/llvm_exports.cc deleted file mode 100644 index 389e424cf..000000000 --- a/src/xenia/cpu/llvmbe/llvm_exports.cc +++ /dev/null @@ -1,96 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - -#include -#include -#include -#include -#include -#include - - -using namespace llvm; -using namespace xe; -using namespace xe::cpu; - - -void xe::cpu::llvmbe::SetupLlvmExports( - GlobalExports* global_exports, - Module* module, const DataLayout* dl, ExecutionEngine* engine) { - LLVMContext& context = module->getContext(); - Type* int8PtrTy = PointerType::getUnqual(Type::getInt8Ty(context)); - - // Control methods: - std::vector trapArgs; - trapArgs.push_back(int8PtrTy); - trapArgs.push_back(Type::getInt32Ty(context)); - FunctionType* trapTy = FunctionType::get( - Type::getVoidTy(context), trapArgs, false); - engine->addGlobalMapping(Function::Create( - trapTy, Function::ExternalLinkage, "XeTrap", - module), (void*)(global_exports->XeTrap)); - - std::vector indirectBranchArgs; - indirectBranchArgs.push_back(int8PtrTy); - indirectBranchArgs.push_back(Type::getInt64Ty(context)); - indirectBranchArgs.push_back(Type::getInt64Ty(context)); - FunctionType* indirectBranchTy = FunctionType::get( - Type::getVoidTy(context), indirectBranchArgs, false); - engine->addGlobalMapping(Function::Create( - indirectBranchTy, Function::ExternalLinkage, "XeIndirectBranch", - module), (void*)(global_exports->XeIndirectBranch)); - - // Debugging methods: - std::vector invalidInstructionArgs; - invalidInstructionArgs.push_back(int8PtrTy); - invalidInstructionArgs.push_back(Type::getInt32Ty(context)); - invalidInstructionArgs.push_back(Type::getInt32Ty(context)); - FunctionType* invalidInstructionTy = FunctionType::get( - Type::getVoidTy(context), invalidInstructionArgs, false); - engine->addGlobalMapping(Function::Create( - invalidInstructionTy, Function::ExternalLinkage, "XeInvalidInstruction", - module), (void*)(global_exports->XeInvalidInstruction)); - - std::vector accessViolationArgs; - accessViolationArgs.push_back(int8PtrTy); - accessViolationArgs.push_back(Type::getInt32Ty(context)); - accessViolationArgs.push_back(Type::getInt64Ty(context)); - FunctionType* accessViolationTy = FunctionType::get( - Type::getVoidTy(context), accessViolationArgs, false); - engine->addGlobalMapping(Function::Create( - accessViolationTy, Function::ExternalLinkage, "XeAccessViolation", - module), (void*)(global_exports->XeAccessViolation)); - - // Tracing methods: - std::vector traceCallArgs; - traceCallArgs.push_back(int8PtrTy); - traceCallArgs.push_back(Type::getInt64Ty(context)); - traceCallArgs.push_back(Type::getInt64Ty(context)); - traceCallArgs.push_back(Type::getInt64Ty(context)); - FunctionType* traceCallTy = FunctionType::get( - Type::getVoidTy(context), traceCallArgs, false); - std::vector traceInstructionArgs; - traceInstructionArgs.push_back(int8PtrTy); - traceInstructionArgs.push_back(Type::getInt32Ty(context)); - traceInstructionArgs.push_back(Type::getInt32Ty(context)); - FunctionType* traceInstructionTy = FunctionType::get( - Type::getVoidTy(context), traceInstructionArgs, false); - - engine->addGlobalMapping(Function::Create( - traceCallTy, Function::ExternalLinkage, "XeTraceKernelCall", - module), (void*)(global_exports->XeTraceKernelCall)); - engine->addGlobalMapping(Function::Create( - traceCallTy, Function::ExternalLinkage, "XeTraceUserCall", - module), (void*)(global_exports->XeTraceUserCall)); - engine->addGlobalMapping(Function::Create( - traceInstructionTy, Function::ExternalLinkage, "XeTraceInstruction", - module), (void*)(global_exports->XeTraceInstruction)); -} diff --git a/src/xenia/cpu/llvmbe/llvm_exports.h b/src/xenia/cpu/llvmbe/llvm_exports.h deleted file mode 100644 index 48a6a28fa..000000000 --- a/src/xenia/cpu/llvmbe/llvm_exports.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_CPU_LLVMBE_LLVM_EXPORTS_H_ -#define XENIA_CPU_LLVMBE_LLVM_EXPORTS_H_ - -#include -#include - -#include - - -namespace llvm { - class ExecutionEngine; - class Module; - class DataLayout; -} - - -namespace xe { -namespace cpu { -namespace llvmbe { - - -void SetupLlvmExports( - GlobalExports* global_exports, - llvm::Module* module, const llvm::DataLayout* dl, - llvm::ExecutionEngine* engine); - - -} // llvmbe -} // cpu -} // xe - - -#endif // XENIA_CPU_LLVMBE_LLVM_EXPORTS_H_ diff --git a/src/xenia/cpu/llvmbe/llvm_jit.cc b/src/xenia/cpu/llvmbe/llvm_jit.cc deleted file mode 100644 index 87c7f5102..000000000 --- a/src/xenia/cpu/llvmbe/llvm_jit.cc +++ /dev/null @@ -1,211 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -using namespace llvm; -using namespace xe; -using namespace xe::cpu; -using namespace xe::cpu::llvmbe; -using namespace xe::cpu::sdb; - - -LLVMJIT::LLVMJIT(xe_memory_ref memory, FunctionTable* fn_table) : - JIT(memory, fn_table), - context_(NULL), engine_(NULL), module_(NULL), cub_(NULL) { -} - -LLVMJIT::~LLVMJIT() { - delete cub_; - if (engine_) { - engine_->removeModule(module_); - } - delete engine_; - delete context_; -} - -//namespace { -//void* LazyFunctionCreator(const std::string& name) { -// printf("lazy: %s", name.c_str()); -// return NULL; -//} -//} - -int LLVMJIT::Setup() { - int result_code = 1; - std::string error_message; - - context_ = new LLVMContext(); - - // Create a shared code unit builder used while JITing. - // Since there's only one we'll need to lock when generating code. - // In the future we could try to generate new code in separate CUBs and then - // link into the main module under the lock. - cub_ = new LLVMCodeUnitBuilder(memory_, context_); - result_code = cub_->Init("jit", ""); - if (result_code) { - return result_code; - } - module_ = cub_->module(); - - EngineBuilder builder(module_); - builder.setEngineKind(EngineKind::JIT); - builder.setErrorStr(&error_message); - builder.setOptLevel(CodeGenOpt::None); - //builder.setOptLevel(CodeGenOpt::Aggressive); - //builder.setJITMemoryManager(jmm); - //builder.setTargetOptions(); - builder.setAllocateGVsWithCode(false); - //builder.setUseMCJIT(true); - - engine_ = builder.create(); - XEEXPECTNOTNULL(engine_); - //engine_->DisableSymbolSearching(); - //engine_->InstallLazyFunctionCreator(LazyFunctionCreator); - - XEEXPECTZERO(InjectGlobals()); - - result_code = 0; -XECLEANUP: - return result_code; -} - -int LLVMJIT::InjectGlobals() { - LLVMContext& context = *context_; - const DataLayout* dl = engine_->getDataLayout(); - Type* intPtrTy = dl->getIntPtrType(context); - Type* int8PtrTy = PointerType::getUnqual(Type::getInt8Ty(context)); - GlobalVariable* gv; - - // xe_memory_base - // This is the base void* pointer to the memory space. - gv = new GlobalVariable( - *module_, - int8PtrTy, - true, - GlobalValue::ExternalLinkage, - 0, - "xe_memory_base"); - // Align to 64b - this makes SSE faster. - gv->setAlignment(64); - gv->setInitializer(ConstantExpr::getIntToPtr( - ConstantInt::get(intPtrTy, (uintptr_t)xe_memory_addr(memory_, 0)), - int8PtrTy)); - - // Setup global exports (the Xe* functions called by generated code). - GlobalExports global_exports; - cpu::GetGlobalExports(&global_exports); - SetupLlvmExports(&global_exports, module_, dl, engine_); - - return 0; -} - -int LLVMJIT::InitModule(ExecModule* module) { - SymbolDatabase* sdb = module->sdb(); - Module* cub_module = cub_->module(); - - // Setup all imports (as needed). - std::vector functions; - if (sdb->GetAllFunctions(functions)) { - return 1; - } - int result_code = 0; - for (std::vector::iterator it = functions.begin(); - it != functions.end(); ++it) { - FunctionSymbol* symbol = *it; - if (symbol->type == FunctionSymbol::Kernel) { - // Generate the function. - Function* fn = NULL; - result_code = cub_->MakeFunction(symbol, &fn); - if (result_code) { - XELOGE("Unable to generate import %s", symbol->name()); - return result_code; - } - - // Set global mappings for shim and data. - char shim_name[256]; - xesnprintfa(shim_name, XECOUNT(shim_name), - "__shim_%s", symbol->kernel_export->name); - Function* shim = cub_module->getFunction(shim_name); - if (shim) { - engine_->updateGlobalMapping( - shim, (void*)symbol->kernel_export->function_data.shim); - } - char shim_data_name[256]; - xesnprintfa(shim_data_name, XECOUNT(shim_data_name), - "__shim_data_%s", symbol->kernel_export->name); - GlobalVariable* shim_data = cub_module->getGlobalVariable(shim_data_name); - if (shim_data) { - engine_->updateGlobalMapping( - shim_data, (void*)symbol->kernel_export->function_data.shim_data); - } - } - } - - return 0; -} - -int LLVMJIT::UninitModule(ExecModule* module) { - return 0; -} - -FunctionPointer LLVMJIT::GenerateFunction(FunctionSymbol* symbol) { - // In theory this is only called when required, so just assume we need to - // generate it. - - // Lock the function for adding. - // If this fails it means the function exists and we don't need to generate - // it. - FunctionPointer ptr = fn_table_->BeginAddFunction(symbol->start_address); - if (ptr) { - return ptr; - } - - printf("generating %s...\n", symbol->name()); - - Function* fn = NULL; - int result_code = cub_->MakeFunction(symbol, &fn); - if (result_code) { - XELOGE("Unable to generate function %s", symbol->name()); - return NULL; - } - - // LLVM requires all functions called to be defined at the time of - // getPointerToFunction, so this does a recursive depth-first walk - // to generate them. - for (std::vector::iterator it = symbol->outgoing_calls.begin(); - it != symbol->outgoing_calls.end(); ++it) { - FunctionSymbol* target = it->target; - printf("needs dep fn %s\n", target->name()); - GenerateFunction(target); - } - - // Generate the machine code. - ptr = (FunctionPointer)engine_->getPointerToFunction(fn); - - // Add to the function table. - fn_table_->AddFunction(symbol->start_address, ptr); - - return ptr; -} diff --git a/src/xenia/cpu/llvmbe/llvm_jit.h b/src/xenia/cpu/llvmbe/llvm_jit.h deleted file mode 100644 index f88c5481e..000000000 --- a/src/xenia/cpu/llvmbe/llvm_jit.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_CPU_LLVMBE_LLVM_JIT_H_ -#define XENIA_CPU_LLVMBE_LLVM_JIT_H_ - -#include - -#include -#include -#include -#include - - -namespace llvm { - class ExecutionEngine; - class LLVMContext; - class Module; -} - - -namespace xe { -namespace cpu { -namespace llvmbe { - - -class LLVMCodeUnitBuilder; - - -class LLVMJIT : public JIT { -public: - LLVMJIT(xe_memory_ref memory, FunctionTable* fn_table); - virtual ~LLVMJIT(); - - virtual int Setup(); - - virtual int InitModule(ExecModule* module); - virtual int UninitModule(ExecModule* module); - - virtual FunctionPointer GenerateFunction(sdb::FunctionSymbol* symbol); - -protected: - int InjectGlobals(); - - llvm::LLVMContext* context_; - llvm::ExecutionEngine* engine_; - llvm::Module* module_; - - LLVMCodeUnitBuilder* cub_; -}; - - -} // namespace llvmbe -} // namespace cpu -} // namespace xe - - -#endif // XENIA_CPU_LLVMBE_LLVM_JIT_H_ diff --git a/src/xenia/cpu/llvmbe/llvm_library_linker.cc b/src/xenia/cpu/llvmbe/llvm_library_linker.cc deleted file mode 100644 index 8b8d18d38..000000000 --- a/src/xenia/cpu/llvmbe/llvm_library_linker.cc +++ /dev/null @@ -1,24 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - - -using namespace xe; -using namespace xe::cpu; -using namespace xe::cpu::llvmbe; - - -LLVMLibraryLinker::LLVMLibraryLinker( - xe_memory_ref memory, kernel::ExportResolver* export_resolver) : - LibraryLinker(memory, export_resolver) { -} - -LLVMLibraryLinker::~LLVMLibraryLinker() { -} diff --git a/src/xenia/cpu/llvmbe/llvm_library_linker.h b/src/xenia/cpu/llvmbe/llvm_library_linker.h deleted file mode 100644 index bf7beb0ab..000000000 --- a/src/xenia/cpu/llvmbe/llvm_library_linker.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_CPU_LLVMBE_LLVM_LIBRARY_LINKER_H_ -#define XENIA_CPU_LLVMBE_LLVM_LIBRARY_LINKER_H_ - -#include -#include - -#include - - -namespace xe { -namespace cpu { -namespace llvmbe { - - -class LLVMLibraryLinker : public LibraryLinker { -public: - LLVMLibraryLinker(xe_memory_ref memory, - kernel::ExportResolver* export_resolver); - virtual ~LLVMLibraryLinker(); -}; - - -} // namespace llvmbe -} // namespace cpu -} // namespace xe - - -#endif // XENIA_CPU_LLVMBE_LLVM_LIBRARY_LINKER_H_ diff --git a/src/xenia/cpu/llvmbe/llvm_library_loader.cc b/src/xenia/cpu/llvmbe/llvm_library_loader.cc deleted file mode 100644 index 07a0bc781..000000000 --- a/src/xenia/cpu/llvmbe/llvm_library_loader.cc +++ /dev/null @@ -1,24 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include - - -using namespace xe; -using namespace xe::cpu; -using namespace xe::cpu::llvmbe; - - -LLVMLibraryLoader::LLVMLibraryLoader( - xe_memory_ref memory, kernel::ExportResolver* export_resolver) : - LibraryLoader(memory, export_resolver) { -} - -LLVMLibraryLoader::~LLVMLibraryLoader() { -} diff --git a/src/xenia/cpu/llvmbe/llvm_library_loader.h b/src/xenia/cpu/llvmbe/llvm_library_loader.h deleted file mode 100644 index dc4fe5f2b..000000000 --- a/src/xenia/cpu/llvmbe/llvm_library_loader.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2013 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_CPU_LLVMBE_LLVM_LIBRARY_LOADER_H_ -#define XENIA_CPU_LLVMBE_LLVM_LIBRARY_LOADER_H_ - -#include -#include - -#include - - -namespace xe { -namespace cpu { -namespace llvmbe { - - -class LLVMLibraryLoader : public LibraryLoader { -public: - LLVMLibraryLoader(xe_memory_ref memory, - kernel::ExportResolver* export_resolver); - virtual ~LLVMLibraryLoader(); -}; - - -} // namespace llvmbe -} // namespace cpu -} // namespace xe - - -#endif // XENIA_CPU_LLVMBE_LLVM_LIBRARY_LOADER_H_ diff --git a/src/xenia/cpu/llvmbe/sources.gypi b/src/xenia/cpu/llvmbe/sources.gypi deleted file mode 100644 index c45929b45..000000000 --- a/src/xenia/cpu/llvmbe/sources.gypi +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2013 Ben Vanik. All Rights Reserved. -{ - 'sources': [ - 'emit.h', - 'emit_alu.cc', - 'emit_control.cc', - 'emit_fpu.cc', - 'emit_memory.cc', - 'emitter_context.cc', - 'emitter_context.h', - 'llvm_backend.cc', - 'llvm_backend.h', - 'llvm_code_unit_builder.cc', - 'llvm_code_unit_builder.h', - 'llvm_exports.cc', - 'llvm_exports.h', - 'llvm_jit.cc', - 'llvm_jit.h', - 'llvm_library_linker.cc', - 'llvm_library_linker.h', - 'llvm_library_loader.cc', - 'llvm_library_loader.h', - ], -}