From 64b619023d30ea2a4c056266c390b068141c2820 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Wed, 22 May 2013 18:03:43 -0700 Subject: [PATCH] Adding back in quite a few instructions. --- src/xenia/cpu/libjit/libjit_emit_alu.cc | 2094 ++++++++++--------- src/xenia/cpu/libjit/libjit_emit_control.cc | 30 +- src/xenia/cpu/libjit/libjit_emit_memory.cc | 1570 +++++++------- src/xenia/cpu/libjit/libjit_emitter.cc | 321 ++- src/xenia/cpu/libjit/libjit_emitter.h | 11 + third_party/libjit | 2 +- 6 files changed, 2079 insertions(+), 1949 deletions(-) diff --git a/src/xenia/cpu/libjit/libjit_emit_alu.cc b/src/xenia/cpu/libjit/libjit_emit_alu.cc index 08c2a6e26..b4b3aa58d 100644 --- a/src/xenia/cpu/libjit/libjit_emit_alu.cc +++ b/src/xenia/cpu/libjit/libjit_emit_alu.cc @@ -19,1060 +19,1062 @@ namespace cpu { namespace libjit { -// Integer arithmetic (A-3) +// // Integer arithmetic (A-3) -XEEMITTER(addx, 0x7C000214, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { - // RD <- (RA) + (RB) +// XEEMITTER(addx, 0x7C000214, XO )(LibjitEmitter& e, jit_function_t f, 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, jit_type_nint); +// jit_value_t v = b.CreateCall2(sadd_with_overflow, +// e.gpr_value(i.XO.RA), e.gpr_value(i.XO.RB)); +// jit_value_t 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, e.get_int64(0), true); +// } + +// return 0; +// } else { +// // No OE bit setting. +// jit_value_t 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, e.get_int64(0), true); +// } + +// return 0; +// } +// return 0; +// } + +XEEMITTER(addcx, 0x7C000014, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(addex, 0x7C000114, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(addi, 0x38000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // RT <- EXTS(SI) + // else + // RT <- (RA) + EXTS(SI) + + jit_value_t v = e.get_int64(XEEXTS16(i.D.DS)); + if (i.D.RA) { + v = jit_insn_add(f, e.gpr_value(i.D.RA), v); + } + e.update_gpr_value(i.D.RT, v); -// 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, jit_type_nint); -// jit_value_t v = b.CreateCall2(sadd_with_overflow, -// e.gpr_value(i.XO.RA), e.gpr_value(i.XO.RB)); -// jit_value_t 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. -// jit_value_t 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; -// } return 0; } -//XEEMITTER(addcx, 0x7C000014, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(addex, 0x7C000114, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(addi, 0x38000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // RT <- EXTS(SI) -// // else -// // RT <- (RA) + EXTS(SI) -// -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RT <- (RA) + EXTS(SI) -// -// Function* sadd_with_overflow = Intrinsic::getDeclaration( -// e.gen_module(), Intrinsic::sadd_with_overflow, jit_type_nint); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(addis, 0x3C000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // RT <- EXTS(SI) || i16.0 -// // else -// // RT <- (RA) + EXTS(SI) || i16.0 -// -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(addzex, 0x7C000194, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RT <- (RA) + CA -// -// Function* sadd_with_overflow = Intrinsic::getDeclaration( -// e.gen_module(), Intrinsic::sadd_with_overflow, jit_type_nint); -// jit_value_t ca = b.CreateAnd(b.CreateLShr(e.xer_value(), 29), 0x1); -// jit_value_t v = b.CreateCall2(sadd_with_overflow, -// e.gpr_value(i.XO.RA), ca); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(divdux, 0x7C000392, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(divwx, 0x7C0003D6, XO )(LibjitEmitter& e, jit_function_t f, 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 -// -// jit_value_t dividend = b.CreateTrunc(e.gpr_value(i.XO.RA), b.getInt32Ty()); -// jit_value_t 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.fn()) : NULL; -// BasicBlock* nonzero_bb = BasicBlock::Create(*e.context(), "", e.fn()); -// BasicBlock* after_bb = BasicBlock::Create(*e.context(), "", e.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); -// jit_value_t v = b.CreateSDiv(dividend, divisor); -// v = b.CreateSExt(v, jit_type_nint); -// 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 )(LibjitEmitter& e, jit_function_t f, 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 -// -// jit_value_t dividend = b.CreateTrunc(e.gpr_value(i.XO.RA), b.getInt32Ty()); -// jit_value_t 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.fn()) : NULL; -// BasicBlock* nonzero_bb = BasicBlock::Create(*e.context(), "", e.fn()); -// BasicBlock* after_bb = BasicBlock::Create(*e.context(), "", e.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); -// jit_value_t v = b.CreateUDiv(dividend, divisor); -// v = b.CreateZExt(v, jit_type_nint); -// 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(mulhdux, 0x7C000012, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(mulhwx, 0x7C000096, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(mulhwux, 0x7C000016, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(mulldx, 0x7C0001D2, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(mulli, 0x1C000000, D )(LibjitEmitter& e, jit_function_t f, 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. -// -// jit_value_t 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, jit_type_nint)); -// -// return 0; -//} -// -//XEEMITTER(mullwx, 0x7C0001D6, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RT <- (RA)[32:63] × (RB)[32:63] -// -// if (i.XO.OE) { -// // With XER update. -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } -// -// jit_value_t v = b.CreateMul(b.CreateSExt(e.gpr_value(i.XO.RA), jit_type_nint), -// b.CreateSExt(e.gpr_value(i.XO.RB), jit_type_nint)); -// 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 )(LibjitEmitter& e, jit_function_t f, 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, jit_type_nint); -// jit_value_t v = b.CreateCall2(ssub_with_overflow, -// b.getInt64(0), e.gpr_value(i.XO.RA)); -// jit_value_t 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. -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, 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, jit_type_nint); -// jit_value_t v = b.CreateCall2(ssub_with_overflow, -// e.gpr_value(i.XO.RB), e.gpr_value(i.XO.RA)); -// jit_value_t 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. -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(subficx, 0x20000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RT <- ¬(RA) + EXTS(SI) + 1 -// -// Function* ssub_with_overflow = Intrinsic::getDeclaration( -// e.gen_module(), Intrinsic::ssub_with_overflow, jit_type_nint); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RT <- ¬(RA) + (RB) + CA -// -// // TODO(benvanik): possible that the add of rb+ca needs to also check for -// // overflow! -// -// jit_value_t ca = b.CreateAnd(b.CreateLShr(e.xer_value(), 29), 0x1); -// Function* uadd_with_overflow = Intrinsic::getDeclaration( -// e.gen_module(), Intrinsic::uadd_with_overflow, jit_type_nint); -// jit_value_t v = b.CreateCall2(uadd_with_overflow, -// b.CreateNeg(e.gpr_value(i.XO.RA)), -// b.CreateAdd(e.gpr_value(i.XO.RB), ca)); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(subfzex, 0x7C000190, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -// -//// Integer compare (A-4) -// -//XEEMITTER(cmp, 0x7C000000, X )(LibjitEmitter& e, jit_function_t f, 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; -// -// jit_value_t lhs = e.gpr_value(i.X.RA); -// jit_value_t 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, jit_type_nint); -// rhs = b.CreateTrunc(rhs, b.getInt32Ty()); -// rhs = b.CreateSExt(rhs, jit_type_nint); -// } -// -// e.update_cr_with_cond(BF, lhs, rhs, true); -// -// return 0; -//} -// -//XEEMITTER(cmpi, 0x2C000000, D )(LibjitEmitter& e, jit_function_t f, 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; -// -// jit_value_t 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, jit_type_nint); -// } -// -// jit_value_t rhs = b.getInt64(XEEXTS16(i.D.DS)); -// e.update_cr_with_cond(BF, lhs, rhs, true); -// -// return 0; -//} -// -//XEEMITTER(cmpl, 0x7C000040, X )(LibjitEmitter& e, jit_function_t f, 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; -// -// jit_value_t lhs = e.gpr_value(i.X.RA); -// jit_value_t 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, jit_type_nint); -// rhs = b.CreateTrunc(rhs, b.getInt32Ty()); -// rhs = b.CreateZExt(rhs, jit_type_nint); -// } -// -// e.update_cr_with_cond(BF, lhs, rhs, false); -// -// return 0; -//} -// -//XEEMITTER(cmpli, 0x28000000, D )(LibjitEmitter& e, jit_function_t f, 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; -// -// jit_value_t 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, jit_type_nint); -// } -// -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RA <- (RS) & (RB) -// -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RA <- (RS) & ¬(RB) -// -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RA <- (RS) & (i48.0 || UI) -// -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RA <- (RS) & (i32.0 || UI || i16.0) -// -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(cntlzwx, 0x7C000034, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // n <- 32 -// // do while n < 64 -// // if (RS) = 1 then leave n -// // n <- n + 1 -// // RA <- n - 32 -// -// jit_value_t 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.fn()->getParent(), Intrinsic::ctlz, arg_types); -// jit_value_t count = b.CreateCall2(ctlz, v, b.getInt1(1)); -// -// count = b.CreateZExt(count, jit_type_nint); -// 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(extsbx, 0x7C000774, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // s <- (RS)[56] -// // RA[56:63] <- (RS)[56:63] -// // RA[0:55] <- i56.s -// -// jit_value_t v = e.gpr_value(i.X.RT); -// v = b.CreateTrunc(v, jit_type_ubyte); -// v = b.CreateSExt(v, jit_type_nint); -// 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(extswx, 0x7C0007B4, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(nandx, 0x7C0003B8, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(norx, 0x7C0000F8, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RA <- ¬((RS) | (RB)) -// -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RA <- (RS) | (RB) -// -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(ori, 0x60000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RA <- (RS) | (i48.0 || UI) -// -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RA <- (RS) | (i32.0 || UI || i16.0) -// -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RA <- (RS) XOR (RB) -// -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RA <- (RS) XOR (i48.0 || UI) -// -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RA <- (RS) XOR (i32.0 || UI || i16.0) -// -// jit_value_t 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)(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(rldcrx, 0x78000012, MDS)(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(rldicx, 0x78000008, MD )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(rldiclx, 0x78000000, MD )(LibjitEmitter& e, jit_function_t f, 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; -// -// // jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(rldimix, 0x7800000C, MD )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(rlwimix, 0x50000000, M )(LibjitEmitter& e, jit_function_t f, 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) -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, 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) { -// jit_value_t 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, jit_type_nint); -// 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) -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -// -//// Integer shift (A-7) -// -//XEEMITTER(sldx, 0x7C000036, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(slwx, 0x7C000030, X )(LibjitEmitter& e, jit_function_t f, 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 -// -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(sradix, 0x7C000674, XS )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(srawx, 0x7C000630, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(srawix, 0x7C000670, X )(LibjitEmitter& e, jit_function_t f, 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) -// -// jit_value_t rs64 = e.gpr_value(i.X.RT); -// jit_value_t rs32 = b.CreateTrunc(rs64, b.getInt32Ty()); -// -// jit_value_t v; -// jit_value_t 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, jit_type_nint); -// 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} -// -//XEEMITTER(srwx, 0x7C000430, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -//} +// XEEMITTER(addic, 0x30000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// // RT <- (RA) + EXTS(SI) + +// Function* sadd_with_overflow = Intrinsic::getDeclaration( +// e.gen_module(), Intrinsic::sadd_with_overflow, jit_type_nint); +// jit_value_t v = b.CreateCall2(sadd_with_overflow, +// e.gpr_value(i.D.RA), e.get_int64(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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(addis, 0x3C000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // RT <- EXTS(SI) || i16.0 + // else + // RT <- (RA) + EXTS(SI) || i16.0 + + jit_value_t v = e.get_int64(XEEXTS16(i.D.DS) << 16); + if (i.D.RA) { + v = jit_insn_add(f, e.gpr_value(i.D.RA), v); + } + e.update_gpr_value(i.D.RT, v); + + return 0; +} + +XEEMITTER(addmex, 0x7C0001D4, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +// XEEMITTER(addzex, 0x7C000194, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// // RT <- (RA) + CA + +// Function* sadd_with_overflow = Intrinsic::getDeclaration( +// e.gen_module(), Intrinsic::sadd_with_overflow, jit_type_nint); +// jit_value_t ca = b.CreateAnd(b.CreateLShr(e.xer_value(), 29), 0x1); +// jit_value_t v = b.CreateCall2(sadd_with_overflow, +// e.gpr_value(i.XO.RA), ca); +// jit_value_t 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, e.get_int64(0), true); +// } + +// return 0; +// } + +XEEMITTER(divdx, 0x7C0003D2, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(divdux, 0x7C000392, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +// XEEMITTER(divwx, 0x7C0003D6, XO )(LibjitEmitter& e, jit_function_t f, 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 + +// jit_value_t dividend = e.trunc_to_int(e.gpr_value(i.XO.RA)); +// jit_value_t divisor = e.trunc_to_int(e.gpr_value(i.XO.RB)); + +// // 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.fn()) : NULL; +// BasicBlock* nonzero_bb = BasicBlock::Create(*e.context(), "", e.fn()); +// BasicBlock* after_bb = BasicBlock::Create(*e.context(), "", e.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); +// jit_value_t v = b.CreateSDiv(dividend, divisor); +// v = e.sign_extend(v, jit_type_nint); +// 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, e.get_int64(0), true); +// } + +// b.CreateBr(after_bb); + +// // Resume. +// b.SetInsertPoint(after_bb); + +// return 0; +// } + +// XEEMITTER(divwux, 0x7C000396, XO )(LibjitEmitter& e, jit_function_t f, 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 + +// jit_value_t dividend = e.trunc_to_int(e.gpr_value(i.XO.RA)); +// jit_value_t divisor = e.trunc_to_int(e.gpr_value(i.XO.RB)); + +// // 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.fn()) : NULL; +// BasicBlock* nonzero_bb = BasicBlock::Create(*e.context(), "", e.fn()); +// BasicBlock* after_bb = BasicBlock::Create(*e.context(), "", e.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); +// jit_value_t v = b.CreateUDiv(dividend, divisor); +// v = e.zero_extend(v, jit_type_nint); +// 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, e.get_int64(0), true); +// } + +// b.CreateBr(after_bb); + +// // Resume. +// b.SetInsertPoint(after_bb); + +// return 0; +// } + +XEEMITTER(mulhdx, 0x7C000092, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(mulhdux, 0x7C000012, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(mulhwx, 0x7C000096, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(mulhwux, 0x7C000016, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(mulldx, 0x7C0001D2, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(mulli, 0x1C000000, D )(LibjitEmitter& e, jit_function_t f, 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. + + jit_value_t v = jit_insn_mul(f, e.gpr_value(i.D.RA), + e.get_int64(XEEXTS16(i.D.DS))); + e.update_gpr_value(i.D.RT, v); + + return 0; +} + +XEEMITTER(mullwx, 0x7C0001D6, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // RT <- (RA)[32:63] × (RB)[32:63] + + if (i.XO.OE) { + // With XER update. + XEINSTRNOTIMPLEMENTED(); + return 1; + } + + jit_value_t v = jit_insn_mul( + f, e.sign_extend(e.gpr_value(i.XO.RA), jit_type_nint), + e.sign_extend(e.gpr_value(i.XO.RB), jit_type_nint)); + e.update_gpr_value(i.XO.RT, v); + + if (i.XO.Rc) { + // With cr0 update. + e.update_cr_with_cond(0, v, e.get_int64(0), true); + } + + return 0; +} + +// XEEMITTER(negx, 0x7C0000D0, XO )(LibjitEmitter& e, jit_function_t f, 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, jit_type_nint); +// jit_value_t v = b.CreateCall2(ssub_with_overflow, +// e.get_int64(0), e.gpr_value(i.XO.RA)); +// jit_value_t 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, e.get_int64(0), true); +// } + +// return 0; +// } else { +// // No OE bit setting. +// jit_value_t v = b.CreateSub(e.get_int64(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, e.get_int64(0), true); +// } + +// return 0; +// } +// } + +// XEEMITTER(subfx, 0x7C000050, XO )(LibjitEmitter& e, jit_function_t f, 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, jit_type_nint); +// jit_value_t v = b.CreateCall2(ssub_with_overflow, +// e.gpr_value(i.XO.RB), e.gpr_value(i.XO.RA)); +// jit_value_t 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, e.get_int64(0), true); +// } + +// return 0; +// } else { +// // No OE bit setting. +// jit_value_t 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, e.get_int64(0), true); +// } + +// return 0; +// } +// } + +XEEMITTER(subfcx, 0x7C000010, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +// XEEMITTER(subficx, 0x20000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// // RT <- ¬(RA) + EXTS(SI) + 1 + +// Function* ssub_with_overflow = Intrinsic::getDeclaration( +// e.gen_module(), Intrinsic::ssub_with_overflow, jit_type_nint); +// jit_value_t v = b.CreateCall2(ssub_with_overflow, +// e.get_int64(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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// // RT <- ¬(RA) + (RB) + CA + +// // TODO(benvanik): possible that the add of rb+ca needs to also check for +// // overflow! + +// jit_value_t ca = b.CreateAnd(b.CreateLShr(e.xer_value(), 29), 0x1); +// Function* uadd_with_overflow = Intrinsic::getDeclaration( +// e.gen_module(), Intrinsic::uadd_with_overflow, jit_type_nint); +// jit_value_t v = b.CreateCall2(uadd_with_overflow, +// b.CreateNeg(e.gpr_value(i.XO.RA)), +// b.CreateAdd(e.gpr_value(i.XO.RB), ca)); +// jit_value_t 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, e.get_int64(0), true); +// } + +// return 0; +// } + +XEEMITTER(subfmex, 0x7C0001D0, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(subfzex, 0x7C000190, XO )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + + +// Integer compare (A-4) + +XEEMITTER(cmp, 0x7C000000, X )(LibjitEmitter& e, jit_function_t f, 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; + + jit_value_t lhs = e.gpr_value(i.X.RA); + jit_value_t rhs = e.gpr_value(i.X.RB); + if (!L) { + // 32-bit - truncate and sign extend. + lhs = e.trunc_to_int(lhs); + lhs = e.sign_extend(lhs, jit_type_nint); + rhs = e.trunc_to_int(rhs); + rhs = e.sign_extend(rhs, jit_type_nint); + } + + e.update_cr_with_cond(BF, lhs, rhs, true); + + return 0; +} + +// XEEMITTER(cmpi, 0x2C000000, D )(LibjitEmitter& e, jit_function_t f, 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; + +// jit_value_t lhs = e.gpr_value(i.D.RA); +// if (!L) { +// // 32-bit - truncate and sign extend. +// lhs = e.trunc_to_int(lhs); +// lhs = e.sign_extend(lhs, jit_type_nint); +// } + +// jit_value_t rhs = e.get_int64(XEEXTS16(i.D.DS)); +// e.update_cr_with_cond(BF, lhs, rhs, true); + +// return 0; +// } + +// XEEMITTER(cmpl, 0x7C000040, X )(LibjitEmitter& e, jit_function_t f, 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; + +// jit_value_t lhs = e.gpr_value(i.X.RA); +// jit_value_t rhs = e.gpr_value(i.X.RB); +// if (!L) { +// // 32-bit - truncate and zero extend. +// lhs = e.trunc_to_int(lhs); +// lhs = e.zero_extend(lhs, jit_type_nint); +// rhs = e.trunc_to_int(rhs); +// rhs = e.zero_extend(rhs, jit_type_nint); +// } + +// e.update_cr_with_cond(BF, lhs, rhs, false); + +// return 0; +// } + +// XEEMITTER(cmpli, 0x28000000, D )(LibjitEmitter& e, jit_function_t f, 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; + +// jit_value_t lhs = e.gpr_value(i.D.RA); +// if (!L) { +// // 32-bit - truncate and zero extend. +// lhs = e.trunc_to_int(lhs); +// lhs = e.zero_extend(lhs, jit_type_nint); +// } + +// jit_value_t rhs = e.get_int64(i.D.DS); +// e.update_cr_with_cond(BF, lhs, rhs, false); + +// return 0; +// } + + +// // Integer logical (A-5) + +// XEEMITTER(andx, 0x7C000038, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// // RA <- (RS) & (RB) + +// jit_value_t 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, e.get_int64(0), true); +// } + +// return 0; +// } + +// XEEMITTER(andcx, 0x7C000078, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// // RA <- (RS) & ¬(RB) + +// jit_value_t 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, e.get_int64(0), true); +// } + +// return 0; +// } + +// XEEMITTER(andix, 0x70000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// // RA <- (RS) & (i48.0 || UI) + +// jit_value_t 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, e.get_int64(0), true); + +// return 0; +// } + +// XEEMITTER(andisx, 0x74000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// // RA <- (RS) & (i32.0 || UI || i16.0) + +// jit_value_t 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, e.get_int64(0), true); + +// return 1; +// } + +// XEEMITTER(cntlzdx, 0x7C000074, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + +// XEEMITTER(cntlzwx, 0x7C000034, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// // n <- 32 +// // do while n < 64 +// // if (RS) = 1 then leave n +// // n <- n + 1 +// // RA <- n - 32 + +// jit_value_t v = e.gpr_value(i.X.RT); +// v = e.trunc_to_int(v); + +// std::vector arg_types; +// arg_types.push_back(b.getInt32Ty()); +// Function* ctlz = Intrinsic::getDeclaration( +// e.fn()->getParent(), Intrinsic::ctlz, arg_types); +// jit_value_t count = b.CreateCall2(ctlz, v, b.getInt1(1)); + +// count = e.zero_extend(count, jit_type_nint); +// e.update_gpr_value(i.X.RA, count); + +// if (i.X.Rc) { +// // With cr0 update. +// e.update_cr_with_cond(0, count, e.get_int64(0), true); +// } + +// return 0; +// } + +// XEEMITTER(eqvx, 0x7C000238, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + +// XEEMITTER(extsbx, 0x7C000774, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// // s <- (RS)[56] +// // RA[56:63] <- (RS)[56:63] +// // RA[0:55] <- i56.s + +// jit_value_t v = e.gpr_value(i.X.RT); +// v = e.trunc_to_ubyte(v); +// v = e.sign_extend(v, jit_type_nint); +// e.update_gpr_value(i.X.RA, v); + +// if (i.X.Rc) { +// // Update cr0. +// e.update_cr_with_cond(0, v, e.get_int64(0), true); +// } + +// return 0; +// } + +// XEEMITTER(extshx, 0x7C000734, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + +// XEEMITTER(extswx, 0x7C0007B4, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + +// XEEMITTER(nandx, 0x7C0003B8, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + +// XEEMITTER(norx, 0x7C0000F8, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// // RA <- ¬((RS) | (RB)) + +// jit_value_t 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, e.get_int64(0), true); +// } + +// return 0; +// } + +// XEEMITTER(orx, 0x7C000378, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// // RA <- (RS) | (RB) + +// jit_value_t 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, e.get_int64(0), true); +// } + +// return 0; +// } + +// XEEMITTER(orcx, 0x7C000338, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + +// XEEMITTER(ori, 0x60000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// // RA <- (RS) | (i48.0 || UI) + +// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// // RA <- (RS) | (i32.0 || UI || i16.0) + +// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// // RA <- (RS) XOR (RB) + +// jit_value_t 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, e.get_int64(0), true); +// } + +// return 0; +// } + +// XEEMITTER(xori, 0x68000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// // RA <- (RS) XOR (i48.0 || UI) + +// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// // RA <- (RS) XOR (i32.0 || UI || i16.0) + +// jit_value_t 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)(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + +// XEEMITTER(rldcrx, 0x78000012, MDS)(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + +// XEEMITTER(rldicx, 0x78000008, MD )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + +// XEEMITTER(rldiclx, 0x78000000, MD )(LibjitEmitter& e, jit_function_t f, 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; + +// // jit_value_t 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, e.get_int64(0), true); +// // } + +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + +// XEEMITTER(rldicrx, 0x78000004, MD )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + +// XEEMITTER(rldimix, 0x7800000C, MD )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + +// XEEMITTER(rlwimix, 0x50000000, M )(LibjitEmitter& e, jit_function_t f, 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) +// jit_value_t 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, e.get_int64(0), true); +// } + +// return 0; +// } + +// XEEMITTER(rlwinmx, 0x54000000, M )(LibjitEmitter& e, jit_function_t f, 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) { +// jit_value_t v = b.CreateAnd( +// e.trunc_to_int(e.gpr_value(i.M.RT)), +// b.getInt32((uint32_t)XEMASK(i.M.MB + 32, i.M.ME + 32))); +// v = e.zero_extend(v, jit_type_nint); +// e.update_gpr_value(i.M.RA, v); +// if (i.M.Rc) { +// // With cr0 update. +// e.update_cr_with_cond(0, v, e.get_int64(0), true); +// } +// return 0; +// } + +// // ROTL32(x, y) = rotl(i64.(x||x), y) +// jit_value_t 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, e.get_int64(0), true); +// } + +// return 0; +// } + +// XEEMITTER(rlwnmx, 0x5C000000, M )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + + +// // Integer shift (A-7) + +// XEEMITTER(sldx, 0x7C000036, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + +// XEEMITTER(slwx, 0x7C000030, X )(LibjitEmitter& e, jit_function_t f, 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 + +// jit_value_t 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, e.get_int64(0), true); +// } + +// return 0; +// } + +// XEEMITTER(sradx, 0x7C000634, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + +// XEEMITTER(sradix, 0x7C000674, XS )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + +// XEEMITTER(srawx, 0x7C000630, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + +// XEEMITTER(srawix, 0x7C000670, X )(LibjitEmitter& e, jit_function_t f, 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) + +// jit_value_t rs64 = e.gpr_value(i.X.RT); +// jit_value_t rs32 = e.trunc_to_int(rs64); + +// jit_value_t v; +// jit_value_t ca; +// if (!i.X.RB) { +// // No shift, just a fancy sign extend and CA clearer. +// v = rs32; +// ca = e.get_int64(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, e.get_int64(0))); +// } +// v = e.sign_extend(v, jit_type_nint); +// 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, e.get_int64(0), true); +// } + +// return 0; +// } + +// XEEMITTER(srdx, 0x7C000436, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } + +// XEEMITTER(srwx, 0x7C000430, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { +// XEINSTRNOTIMPLEMENTED(); +// return 1; +// } void LibjitRegisterEmitCategoryALU() { - 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); + // 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); } diff --git a/src/xenia/cpu/libjit/libjit_emit_control.cc b/src/xenia/cpu/libjit/libjit_emit_control.cc index be5bc767a..8cd1f12e9 100644 --- a/src/xenia/cpu/libjit/libjit_emit_control.cc +++ b/src/xenia/cpu/libjit/libjit_emit_control.cc @@ -98,7 +98,7 @@ namespace libjit { // } else { // // Will return here eventually. // // Refill registers from state. -// b.CreateCall2(target_fn, state_ptr, b.getInt64(cia + 4)); +// b.CreateCall2(target_fn, state_ptr, e.get_int64(cia + 4)); // e.FillRegisters(); // b.CreateBr(next_bb); // } @@ -175,14 +175,14 @@ namespace libjit { // } else { // // Decrement counter. // jit_value_t ctr = e.ctr_value(); -// ctr = b.CreateSub(ctr, b.getInt64(1)); +// ctr = b.CreateSub(ctr, e.get_int64(1)); // e.update_ctr_value(ctr); // // Ctr check. // if (XESELECTBITS(i.B.BO, 1, 1)) { -// ctr_ok = b.CreateICmpEQ(ctr, b.getInt64(0)); +// ctr_ok = b.CreateICmpEQ(ctr, e.get_int64(0)); // } else { -// ctr_ok = b.CreateICmpNE(ctr, b.getInt64(0)); +// ctr_ok = b.CreateICmpNE(ctr, e.get_int64(0)); // } // } @@ -193,9 +193,9 @@ namespace libjit { // jit_value_t 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)); +// cond_ok = b.CreateICmpNE(cr, e.get_int64(0)); // } else { -// cond_ok = b.CreateICmpEQ(cr, b.getInt64(0)); +// cond_ok = b.CreateICmpEQ(cr, e.get_int64(0)); // } // } @@ -262,9 +262,9 @@ namespace libjit { // jit_value_t 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)); +// cond_ok = b.CreateICmpNE(cr, e.get_int64(0)); // } else { -// cond_ok = b.CreateICmpEQ(cr, b.getInt64(0)); +// cond_ok = b.CreateICmpEQ(cr, e.get_int64(0)); // } // } @@ -324,13 +324,13 @@ namespace libjit { // } else { // // Decrement counter. // jit_value_t ctr = e.ctr_value(); -// ctr = b.CreateSub(ctr, b.getInt64(1)); +// ctr = b.CreateSub(ctr, e.get_int64(1)); // // Ctr check. // if (XESELECTBITS(i.XL.BO, 1, 1)) { -// ctr_ok = b.CreateICmpEQ(ctr, b.getInt64(0)); +// ctr_ok = b.CreateICmpEQ(ctr, e.get_int64(0)); // } else { -// ctr_ok = b.CreateICmpNE(ctr, b.getInt64(0)); +// ctr_ok = b.CreateICmpNE(ctr, e.get_int64(0)); // } // } @@ -341,9 +341,9 @@ namespace libjit { // jit_value_t 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)); +// cond_ok = b.CreateICmpNE(cr, e.get_int64(0)); // } else { -// cond_ok = b.CreateICmpEQ(cr, b.getInt64(0)); +// cond_ok = b.CreateICmpEQ(cr, e.get_int64(0)); // } // } @@ -558,7 +558,7 @@ namespace libjit { // // 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)), +// e.get_int64(XEEXTS16(i.D.DS)), // i.D.RT); // } @@ -591,7 +591,7 @@ namespace libjit { // b.CreateSExt(b.CreateTrunc(e.gpr_value(i.D.RA), // b.getInt32Ty()), // jit_type_nint), -// b.getInt64(XEEXTS16(i.D.DS)), +// e.get_int64(XEEXTS16(i.D.DS)), // i.D.RT); // } diff --git a/src/xenia/cpu/libjit/libjit_emit_memory.cc b/src/xenia/cpu/libjit/libjit_emit_memory.cc index d624694da..9a1b50119 100644 --- a/src/xenia/cpu/libjit/libjit_emit_memory.cc +++ b/src/xenia/cpu/libjit/libjit_emit_memory.cc @@ -21,674 +21,678 @@ namespace libjit { // Integer load (A-13) -// XEEMITTER(lbz, 0x88000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + EXTS(D) -// // RT <- i56.0 || MEM(EA, 1) - -// jit_value_t ea = b.getInt64(XEEXTS16(i.D.DS)); -// if (i.D.RA) { -// ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); -// } -// jit_value_t v = e.ReadMemory(i.address, ea, 1, false); -// e.update_gpr_value(i.D.RT, v); - -// return 0; -// } - -// XEEMITTER(lbzu, 0x8C000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // EA <- (RA) + EXTS(D) -// // RT <- i56.0 || MEM(EA, 1) -// // RA <- EA - -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // EA <- (RA) + (RB) -// // RT <- i56.0 || MEM(EA, 1) -// // RA <- EA - -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + (RB) -// // RT <- i56.0 || MEM(EA, 1) - -// jit_value_t ea = e.gpr_value(i.X.RB); -// if (i.X.RA) { -// ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); -// } -// jit_value_t v = e.ReadMemory(i.address, ea, 1, false); -// e.update_gpr_value(i.X.RT, v); - -// return 0; -// } - -// XEEMITTER(ld, 0xE8000000, DS )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + EXTS(DS || 0b00) -// // RT <- MEM(EA, 8) - -// jit_value_t ea = b.getInt64(XEEXTS16(i.DS.DS << 2)); -// if (i.DS.RA) { -// ea = b.CreateAdd(e.gpr_value(i.DS.RA), ea); -// } -// jit_value_t v = e.ReadMemory(i.address, ea, 8, false); -// e.update_gpr_value(i.DS.RT, v); - -// return 0; -// } - -// XEEMITTER(ldu, 0xE8000001, DS )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // EA <- (RA) + EXTS(DS || 0b00) -// // RT <- MEM(EA, 8) -// // RA <- EA - -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.DS.RA), -// b.getInt64(XEEXTS16(i.DS.DS << 2))); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } - -// XEEMITTER(ldx, 0x7C00002A, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } - -// XEEMITTER(lha, 0xA8000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + EXTS(D) -// // RT <- EXTS(MEM(EA, 2)) - -// jit_value_t ea = b.getInt64(XEEXTS16(i.D.DS)); -// if (i.D.RA) { -// ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); -// } -// jit_value_t v = b.CreateSExt(e.ReadMemory(i.address, ea, 2, false), -// jit_type_nint); -// e.update_gpr_value(i.D.RT, v); - -// return 0; -// } - -// XEEMITTER(lhau, 0xAC000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } - -// XEEMITTER(lhaux, 0x7C0002EE, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } - -// XEEMITTER(lhax, 0x7C0002AE, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + (RB) -// // RT <- EXTS(MEM(EA, 2)) - -// jit_value_t ea = e.gpr_value(i.X.RB); -// if (i.X.RA) { -// ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); -// } -// jit_value_t v = b.CreateSExt(e.ReadMemory(i.address, ea, 2, false), -// jit_type_nint); -// e.update_gpr_value(i.X.RT, v); - -// return 0; -// } - -// XEEMITTER(lhz, 0xA0000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + EXTS(D) -// // RT <- i48.0 || MEM(EA, 2) - -// jit_value_t ea = b.getInt64(XEEXTS16(i.D.DS)); -// if (i.D.RA) { -// ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); -// } -// jit_value_t v = e.ReadMemory(i.address, ea, 2, false); -// e.update_gpr_value(i.D.RT, v); - -// return 0; -// } - -// XEEMITTER(lhzu, 0xA4000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // EA <- (RA) + EXTS(D) -// // RT <- i48.0 || MEM(EA, 2) -// // RA <- EA - -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // EA <- (RA) + (RB) -// // RT <- i48.0 || MEM(EA, 2) -// // RA <- EA - -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + (RB) -// // RT <- i48.0 || MEM(EA, 2) - -// jit_value_t ea = e.gpr_value(i.X.RB); -// if (i.X.RA) { -// ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); -// } -// jit_value_t v = e.ReadMemory(i.address, ea, 2, false); -// e.update_gpr_value(i.X.RT, v); - -// return 0; -// } - -// XEEMITTER(lwa, 0xE8000002, DS )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + EXTS(D || 00) -// // RT <- EXTS(MEM(EA, 4)) - -// jit_value_t ea = b.getInt64(XEEXTS16(i.DS.DS << 2)); -// if (i.DS.RA) { -// ea = b.CreateAdd(e.gpr_value(i.DS.RA), ea); -// } -// jit_value_t v = b.CreateSExt(e.ReadMemory(i.address, ea, 4, false), -// jit_type_nint); -// e.update_gpr_value(i.DS.RT, v); - -// return 0; -// } - -// XEEMITTER(lwaux, 0x7C0002EA, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // EA <- (RA) + (RB) -// // RT <- EXTS(MEM(EA, 4)) -// // RA <- EA - -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); -// jit_value_t v = b.CreateSExt(e.ReadMemory(i.address, ea, 4, false), -// jit_type_nint); -// e.update_gpr_value(i.X.RT, v); -// e.update_gpr_value(i.X.RA, ea); - -// return 0; -// } - -// XEEMITTER(lwax, 0x7C0002AA, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + (RB) -// // RT <- EXTS(MEM(EA, 4)) - -// jit_value_t ea = e.gpr_value(i.X.RB); -// if (i.X.RA) { -// ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); -// } -// jit_value_t v = b.CreateSExt(e.ReadMemory(i.address, ea, 4, false), -// jit_type_nint); -// e.update_gpr_value(i.X.RT, v); - -// return 0; -// } - -// XEEMITTER(lwz, 0x80000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + EXTS(D) -// // RT <- i32.0 || MEM(EA, 4) - -// jit_value_t ea = b.getInt64(XEEXTS16(i.D.DS)); -// if (i.D.RA) { -// ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); -// } -// jit_value_t v = e.ReadMemory(i.address, ea, 4, false); -// e.update_gpr_value(i.D.RT, v); - -// return 0; -// } - -// XEEMITTER(lwzu, 0x84000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // EA <- (RA) + EXTS(D) -// // RT <- i32.0 || MEM(EA, 4) -// // RA <- EA - -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // EA <- (RA) + (RB) -// // RT <- i32.0 || MEM(EA, 4) -// // RA <- EA - -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + (RB) -// // RT <- i32.0 || MEM(EA, 4) - -// jit_value_t ea = e.gpr_value(i.X.RB); -// if (i.X.RA) { -// ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); -// } -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + EXTS(D) -// // MEM(EA, 1) <- (RS)[56:63] - -// jit_value_t ea = b.getInt64(XEEXTS16(i.D.DS)); -// if (i.D.RA) { -// ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); -// } -// jit_value_t v = e.gpr_value(i.D.RT); -// e.WriteMemory(i.address, ea, 1, v); - -// return 0; -// } - -// XEEMITTER(stbu, 0x9C000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // EA <- (RA) + EXTS(D) -// // MEM(EA, 1) <- (RS)[56:63] -// // RA <- EA - -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // EA <- (RA) + (RB) -// // MEM(EA, 1) <- (RS)[56:63] -// // RA <- EA - -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + (RB) -// // MEM(EA, 1) <- (RS)[56:63] - -// jit_value_t ea = e.gpr_value(i.X.RB); -// if (i.D.RA) { -// ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); -// } -// jit_value_t v = e.gpr_value(i.X.RT); -// e.WriteMemory(i.address, ea, 1, v); - -// return 0; -// } - -// XEEMITTER(std, 0xF8000000, DS )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + EXTS(DS || 0b00) -// // MEM(EA, 8) <- (RS) - -// jit_value_t ea = b.getInt64(XEEXTS16(i.DS.DS << 2)); -// if (i.DS.RA) { -// ea = b.CreateAdd(e.gpr_value(i.DS.RA), ea); -// } -// jit_value_t v = e.gpr_value(i.DS.RT); -// e.WriteMemory(i.address, ea, 8, v); - -// return 0; -// } - -// XEEMITTER(stdu, 0xF8000001, DS )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // EA <- (RA) + EXTS(DS || 0b00) -// // MEM(EA, 8) <- (RS) -// // RA <- EA - -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.DS.RA), -// b.getInt64(XEEXTS16(i.DS.DS << 2))); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + (RB) -// // MEM(EA, 8) <- (RS) - -// jit_value_t ea = e.gpr_value(i.X.RB); -// if (i.X.RA) { -// ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); -// } -// jit_value_t v = e.gpr_value(i.X.RT); -// e.WriteMemory(i.address, ea, 8, v); - -// return 0; -// } - -// XEEMITTER(stdx, 0x7C00012A, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // EA <- (RA) + (RB) -// // MEM(EA, 8) <- (RS) -// // RA <- EA - -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + EXTS(D) -// // MEM(EA, 2) <- (RS)[48:63] - -// jit_value_t ea = b.getInt64(XEEXTS16(i.D.DS)); -// if (i.D.RA) { -// ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); -// } -// jit_value_t v = e.gpr_value(i.D.RT); -// e.WriteMemory(i.address, ea, 2, v); - -// return 0; -// } - -// XEEMITTER(sthu, 0xB4000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // EA <- (RA) + EXTS(D) -// // MEM(EA, 2) <- (RS)[48:63] -// // RA <- EA - -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.D.RA), -// b.getInt64(XEEXTS16(i.D.DS))); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // EA <- (RA) + (RB) -// // MEM(EA, 2) <- (RS)[48:63] -// // RA <- EA - -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + (RB) -// // MEM(EA, 2) <- (RS)[48:63] - -// jit_value_t ea = e.gpr_value(i.X.RB); -// if (i.D.RA) { -// ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); -// } -// jit_value_t v = e.gpr_value(i.X.RT); -// e.WriteMemory(i.address, ea, 2, v); - -// return 0; -// } - -// XEEMITTER(stw, 0x90000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + EXTS(D) -// // MEM(EA, 4) <- (RS)[32:63] - -// jit_value_t ea = b.getInt64(XEEXTS16(i.D.DS)); -// if (i.D.RA) { -// ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); -// } -// jit_value_t v = e.gpr_value(i.D.RT); -// e.WriteMemory(i.address, ea, 4, v); - -// return 0; -// } - -// XEEMITTER(stwu, 0x94000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // EA <- (RA) + EXTS(D) -// // MEM(EA, 4) <- (RS)[32:63] -// // RA <- EA - -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.D.RA), -// b.getInt64(XEEXTS16(i.D.DS))); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // EA <- (RA) + (RB) -// // MEM(EA, 4) <- (RS)[32:63] -// // RA <- EA - -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // if RA = 0 then -// // b <- 0 -// // else -// // b <- (RA) -// // EA <- b + (RB) -// // MEM(EA, 4) <- (RS)[32:63] - -// jit_value_t ea = e.gpr_value(i.X.RB); -// if (i.X.RA) { -// ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); -// } -// jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } - -// XEEMITTER(lwbrx, 0x7C00042C, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } - -// XEEMITTER(ldbrx, 0x7C000428, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } - -// XEEMITTER(sthbrx, 0x7C00072C, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } - -// XEEMITTER(stwbrx, 0x7C00052C, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } - -// XEEMITTER(stdbrx, 0x7C000528, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } - - -// // Integer load and store multiple (A-16) - -// XEEMITTER(lmw, 0xB8000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } - -// XEEMITTER(stmw, 0xBC000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } - - -// // Integer load and store string (A-17) - -// XEEMITTER(lswi, 0x7C0004AA, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } - -// XEEMITTER(lswx, 0x7C00042A, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } - -// XEEMITTER(stswi, 0x7C0005AA, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(lbz, 0x88000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + EXTS(D) + // RT <- i56.0 || MEM(EA, 1) + + jit_value_t ea = e.get_int64(XEEXTS16(i.D.DS)); + if (i.D.RA) { + ea = jit_insn_add(f, e.gpr_value(i.D.RA), ea); + } + jit_value_t v = e.ReadMemory(i.address, ea, 1, false); + e.update_gpr_value(i.D.RT, v); + + return 0; +} + +XEEMITTER(lbzu, 0x8C000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // EA <- (RA) + EXTS(D) + // RT <- i56.0 || MEM(EA, 1) + // RA <- EA + + jit_value_t ea = jit_insn_add(f, e.gpr_value(i.D.RA), + e.get_int64(XEEXTS16(i.D.DS))); + jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // EA <- (RA) + (RB) + // RT <- i56.0 || MEM(EA, 1) + // RA <- EA + + jit_value_t ea = jit_insn_add(f, e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); + jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // RT <- i56.0 || MEM(EA, 1) + + jit_value_t ea = e.gpr_value(i.X.RB); + if (i.X.RA) { + ea = jit_insn_add(f, e.gpr_value(i.X.RA), ea); + } + jit_value_t v = e.ReadMemory(i.address, ea, 1, false); + e.update_gpr_value(i.X.RT, v); + + return 0; +} + +XEEMITTER(ld, 0xE8000000, DS )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + EXTS(DS || 0b00) + // RT <- MEM(EA, 8) + + jit_value_t ea = e.get_int64(XEEXTS16(i.DS.DS << 2)); + if (i.DS.RA) { + ea = jit_insn_add(f, e.gpr_value(i.DS.RA), ea); + } + jit_value_t v = e.ReadMemory(i.address, ea, 8, false); + e.update_gpr_value(i.DS.RT, v); + + return 0; +} + +XEEMITTER(ldu, 0xE8000001, DS )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // EA <- (RA) + EXTS(DS || 0b00) + // RT <- MEM(EA, 8) + // RA <- EA + + jit_value_t ea = jit_insn_add(f, e.gpr_value(i.DS.RA), + e.get_int64(XEEXTS16(i.DS.DS << 2))); + jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(ldx, 0x7C00002A, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(lha, 0xA8000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + EXTS(D) + // RT <- EXTS(MEM(EA, 2)) + + jit_value_t ea = e.get_int64(XEEXTS16(i.D.DS)); + if (i.D.RA) { + ea = jit_insn_add(f, e.gpr_value(i.D.RA), ea); + } + jit_value_t v = e.sign_extend(e.ReadMemory(i.address, ea, 2, false), + jit_type_nuint); + e.update_gpr_value(i.D.RT, v); + + return 0; +} + +XEEMITTER(lhau, 0xAC000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(lhaux, 0x7C0002EE, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(lhax, 0x7C0002AE, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // RT <- EXTS(MEM(EA, 2)) + + jit_value_t ea = e.gpr_value(i.X.RB); + if (i.X.RA) { + ea = jit_insn_add(f, e.gpr_value(i.X.RA), ea); + } + jit_value_t v = e.sign_extend(e.ReadMemory(i.address, ea, 2, false), + jit_type_nuint); + e.update_gpr_value(i.X.RT, v); + + return 0; +} + +XEEMITTER(lhz, 0xA0000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + EXTS(D) + // RT <- i48.0 || MEM(EA, 2) + + jit_value_t ea = e.get_int64(XEEXTS16(i.D.DS)); + if (i.D.RA) { + ea = jit_insn_add(f, e.gpr_value(i.D.RA), ea); + } + jit_value_t v = e.ReadMemory(i.address, ea, 2, false); + e.update_gpr_value(i.D.RT, v); + + return 0; +} + +XEEMITTER(lhzu, 0xA4000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // EA <- (RA) + EXTS(D) + // RT <- i48.0 || MEM(EA, 2) + // RA <- EA + + jit_value_t ea = jit_insn_add(f, e.gpr_value(i.D.RA), + e.get_int64(XEEXTS16(i.D.DS))); + jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // EA <- (RA) + (RB) + // RT <- i48.0 || MEM(EA, 2) + // RA <- EA + + jit_value_t ea = jit_insn_add(f, e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); + jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // RT <- i48.0 || MEM(EA, 2) + + jit_value_t ea = e.gpr_value(i.X.RB); + if (i.X.RA) { + ea = jit_insn_add(f, e.gpr_value(i.X.RA), ea); + } + jit_value_t v = e.ReadMemory(i.address, ea, 2, false); + e.update_gpr_value(i.X.RT, v); + + return 0; +} + +XEEMITTER(lwa, 0xE8000002, DS )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + EXTS(D || 00) + // RT <- EXTS(MEM(EA, 4)) + + jit_value_t ea = e.get_int64(XEEXTS16(i.DS.DS << 2)); + if (i.DS.RA) { + ea = jit_insn_add(f, e.gpr_value(i.DS.RA), ea); + } + jit_value_t v = e.sign_extend(e.ReadMemory(i.address, ea, 4, false), + jit_type_nuint); + e.update_gpr_value(i.DS.RT, v); + + return 0; +} + +XEEMITTER(lwaux, 0x7C0002EA, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // EA <- (RA) + (RB) + // RT <- EXTS(MEM(EA, 4)) + // RA <- EA + + jit_value_t ea = jit_insn_add(f, e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); + jit_value_t v = e.sign_extend(e.ReadMemory(i.address, ea, 4, false), + jit_type_nuint); + e.update_gpr_value(i.X.RT, v); + e.update_gpr_value(i.X.RA, ea); + + return 0; +} + +XEEMITTER(lwax, 0x7C0002AA, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // RT <- EXTS(MEM(EA, 4)) + + jit_value_t ea = e.gpr_value(i.X.RB); + if (i.X.RA) { + ea = jit_insn_add(f, e.gpr_value(i.X.RA), ea); + } + jit_value_t v = e.sign_extend(e.ReadMemory(i.address, ea, 4, false), + jit_type_nuint); + e.update_gpr_value(i.X.RT, v); + + return 0; +} + +XEEMITTER(lwz, 0x80000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + EXTS(D) + // RT <- i32.0 || MEM(EA, 4) + + jit_value_t ea = e.get_int64(XEEXTS16(i.D.DS)); + if (i.D.RA) { + ea = jit_insn_add(f, e.gpr_value(i.D.RA), ea); + } + jit_value_t v = e.ReadMemory(i.address, ea, 4, false); + e.update_gpr_value(i.D.RT, v); + + return 0; +} + +XEEMITTER(lwzu, 0x84000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // EA <- (RA) + EXTS(D) + // RT <- i32.0 || MEM(EA, 4) + // RA <- EA + + jit_value_t ea = jit_insn_add(f, e.gpr_value(i.D.RA), + e.get_int64(XEEXTS16(i.D.DS))); + jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // EA <- (RA) + (RB) + // RT <- i32.0 || MEM(EA, 4) + // RA <- EA + + jit_value_t ea = jit_insn_add(f, e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); + jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // RT <- i32.0 || MEM(EA, 4) + + jit_value_t ea = e.gpr_value(i.X.RB); + if (i.X.RA) { + ea = jit_insn_add(f, e.gpr_value(i.X.RA), ea); + } + jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + EXTS(D) + // MEM(EA, 1) <- (RS)[56:63] + + jit_value_t ea = e.get_int64(XEEXTS16(i.D.DS)); + if (i.D.RA) { + ea = jit_insn_add(f, e.gpr_value(i.D.RA), ea); + } + jit_value_t v = e.gpr_value(i.D.RT); + e.WriteMemory(i.address, ea, 1, v); + + return 0; +} + +XEEMITTER(stbu, 0x9C000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // EA <- (RA) + EXTS(D) + // MEM(EA, 1) <- (RS)[56:63] + // RA <- EA + + jit_value_t ea = jit_insn_add(f, e.gpr_value(i.D.RA), + e.get_int64(XEEXTS16(i.D.DS))); + jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // EA <- (RA) + (RB) + // MEM(EA, 1) <- (RS)[56:63] + // RA <- EA + + jit_value_t ea = jit_insn_add(f, e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); + jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // MEM(EA, 1) <- (RS)[56:63] + + jit_value_t ea = e.gpr_value(i.X.RB); + if (i.D.RA) { + ea = jit_insn_add(f, e.gpr_value(i.X.RA), ea); + } + jit_value_t v = e.gpr_value(i.X.RT); + e.WriteMemory(i.address, ea, 1, v); + + return 0; +} + +XEEMITTER(std, 0xF8000000, DS )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + EXTS(DS || 0b00) + // MEM(EA, 8) <- (RS) + + jit_value_t ea = e.get_int64(XEEXTS16(i.DS.DS << 2)); + if (i.DS.RA) { + ea = jit_insn_add(f, e.gpr_value(i.DS.RA), ea); + } + jit_value_t v = e.gpr_value(i.DS.RT); + e.WriteMemory(i.address, ea, 8, v); + + return 0; +} + +XEEMITTER(stdu, 0xF8000001, DS )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // EA <- (RA) + EXTS(DS || 0b00) + // MEM(EA, 8) <- (RS) + // RA <- EA + + jit_value_t ea = jit_insn_add(f, e.gpr_value(i.DS.RA), + e.get_int64(XEEXTS16(i.DS.DS << 2))); + jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // MEM(EA, 8) <- (RS) + + jit_value_t ea = e.gpr_value(i.X.RB); + if (i.X.RA) { + ea = jit_insn_add(f, e.gpr_value(i.X.RA), ea); + } + jit_value_t v = e.gpr_value(i.X.RT); + e.WriteMemory(i.address, ea, 8, v); + + return 0; +} + +XEEMITTER(stdx, 0x7C00012A, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // EA <- (RA) + (RB) + // MEM(EA, 8) <- (RS) + // RA <- EA + + jit_value_t ea = jit_insn_add(f, e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); + jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + EXTS(D) + // MEM(EA, 2) <- (RS)[48:63] + + jit_value_t ea = e.get_int64(XEEXTS16(i.D.DS)); + if (i.D.RA) { + ea = jit_insn_add(f, e.gpr_value(i.D.RA), ea); + } + jit_value_t v = e.gpr_value(i.D.RT); + e.WriteMemory(i.address, ea, 2, v); + + return 0; +} + +XEEMITTER(sthu, 0xB4000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // EA <- (RA) + EXTS(D) + // MEM(EA, 2) <- (RS)[48:63] + // RA <- EA + + jit_value_t ea = jit_insn_add(f, e.gpr_value(i.D.RA), + e.get_int64(XEEXTS16(i.D.DS))); + jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // EA <- (RA) + (RB) + // MEM(EA, 2) <- (RS)[48:63] + // RA <- EA + + jit_value_t ea = jit_insn_add(f, e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); + jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // MEM(EA, 2) <- (RS)[48:63] + + jit_value_t ea = e.gpr_value(i.X.RB); + if (i.D.RA) { + ea = jit_insn_add(f, e.gpr_value(i.X.RA), ea); + } + jit_value_t v = e.gpr_value(i.X.RT); + e.WriteMemory(i.address, ea, 2, v); + + return 0; +} + +XEEMITTER(stw, 0x90000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + EXTS(D) + // MEM(EA, 4) <- (RS)[32:63] + + jit_value_t ea = e.get_int64(XEEXTS16(i.D.DS)); + if (i.D.RA) { + ea = jit_insn_add(f, e.gpr_value(i.D.RA), ea); + } + jit_value_t v = e.gpr_value(i.D.RT); + e.WriteMemory(i.address, ea, 4, v); + + return 0; +} + +XEEMITTER(stwu, 0x94000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // EA <- (RA) + EXTS(D) + // MEM(EA, 4) <- (RS)[32:63] + // RA <- EA + + jit_value_t ea = jit_insn_add(f, e.gpr_value(i.D.RA), + e.get_int64(XEEXTS16(i.D.DS))); + jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // EA <- (RA) + (RB) + // MEM(EA, 4) <- (RS)[32:63] + // RA <- EA + + jit_value_t ea = jit_insn_add(f, e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); + jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // MEM(EA, 4) <- (RS)[32:63] + + jit_value_t ea = e.gpr_value(i.X.RB); + if (i.X.RA) { + ea = jit_insn_add(f, e.gpr_value(i.X.RA), ea); + } + jit_value_t 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 )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(lwbrx, 0x7C00042C, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(ldbrx, 0x7C000428, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(sthbrx, 0x7C00072C, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(stwbrx, 0x7C00052C, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(stdbrx, 0x7C000528, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + + +// Integer load and store multiple (A-16) + +XEEMITTER(lmw, 0xB8000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(stmw, 0xBC000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + + +// Integer load and store string (A-17) + +XEEMITTER(lswi, 0x7C0004AA, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(lswx, 0x7C00042A, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} + +XEEMITTER(stswi, 0x7C0005AA, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} -// XEEMITTER(stswx, 0x7C00052A, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(stswx, 0x7C00052A, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} -// // Memory synchronization (A-18) - -// XEEMITTER(eieio, 0x7C0006AC, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +// Memory synchronization (A-18) + +XEEMITTER(eieio, 0x7C0006AC, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} -// XEEMITTER(isync, 0x4C00012C, XL )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(isync, 0x4C00012C, XL )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} -// XEEMITTER(ldarx, 0x7C0000A8, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(ldarx, 0x7C0000A8, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} // XEEMITTER(lwarx, 0x7C000028, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { // // if RA = 0 then @@ -705,7 +709,7 @@ namespace libjit { // jit_value_t ea = e.gpr_value(i.X.RB); // if (i.X.RA) { -// ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); +// ea = jit_insn_add(f, e.gpr_value(i.X.RA), ea); // } // jit_value_t v = e.ReadMemory(i.address, ea, 4, /* acquire */ true); // e.update_gpr_value(i.X.RT, v); @@ -731,23 +735,23 @@ namespace libjit { // // TODO(benvanik): make this right -// jit_value_t ea = b.getInt64(XEEXTS16(i.D.DS)); +// jit_value_t ea = e.get_int64(XEEXTS16(i.D.DS)); // if (i.D.RA) { -// ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); +// ea = jit_insn_add(f, e.gpr_value(i.D.RA), ea); // } // jit_value_t 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)); +// e.update_cr_value(0, e.get_int64(1 << 2)); // return 0; // } -// XEEMITTER(sync, 0x7C0004AC, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(sync, 0x7C0004AC, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} // // Floating-point load (A-19) @@ -760,9 +764,9 @@ namespace libjit { // // EA <- b + EXTS(D) // // FRT <- MEM(EA, 8) -// jit_value_t ea = b.getInt64(XEEXTS16(i.D.DS)); +// jit_value_t ea = e.get_int64(XEEXTS16(i.D.DS)); // if (i.D.RA) { -// ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); +// ea = jit_insn_add(f, e.gpr_value(i.D.RA), ea); // } // jit_value_t v = e.ReadMemory(i.address, ea, 8, false); // v = b.CreateBitCast(v, jit_type_float64); @@ -776,7 +780,7 @@ namespace libjit { // // FRT <- MEM(EA, 8) // // RA <- EA -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); +// jit_value_t ea = jit_insn_add(f, e.gpr_value(i.D.RA), e.get_int64(XEEXTS16(i.D.DS))); // jit_value_t v = e.ReadMemory(i.address, ea, 8, false); // v = b.CreateBitCast(v, jit_type_float64); // e.update_fpr_value(i.D.RT, v); @@ -790,7 +794,7 @@ namespace libjit { // // FRT <- MEM(EA, 8) // // RA <- EA -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); +// jit_value_t ea = jit_insn_add(f, e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); // jit_value_t v = e.ReadMemory(i.address, ea, 8, false); // v = b.CreateBitCast(v, jit_type_float64); // e.update_fpr_value(i.X.RT, v); @@ -809,7 +813,7 @@ namespace libjit { // jit_value_t ea = e.gpr_value(i.X.RB); // if (i.X.RA) { -// ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); +// ea = jit_insn_add(f, e.gpr_value(i.X.RA), ea); // } // jit_value_t v = e.ReadMemory(i.address, ea, 8, false); // v = b.CreateBitCast(v, jit_type_float64); @@ -826,9 +830,9 @@ namespace libjit { // // EA <- b + EXTS(D) // // FRT <- DOUBLE(MEM(EA, 4)) -// jit_value_t ea = b.getInt64(XEEXTS16(i.D.DS)); +// jit_value_t ea = e.get_int64(XEEXTS16(i.D.DS)); // if (i.D.RA) { -// ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); +// ea = jit_insn_add(f, e.gpr_value(i.D.RA), ea); // } // jit_value_t v = e.ReadMemory(i.address, ea, 4, false); // v = b.CreateFPExt(b.CreateBitCast(v, b.getFloatTy()), jit_type_float64); @@ -842,7 +846,7 @@ namespace libjit { // // FRT <- DOUBLE(MEM(EA, 4)) // // RA <- EA -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); +// jit_value_t ea = jit_insn_add(f, e.gpr_value(i.D.RA), e.get_int64(XEEXTS16(i.D.DS))); // jit_value_t v = e.ReadMemory(i.address, ea, 4, false); // v = b.CreateFPExt(b.CreateBitCast(v, b.getFloatTy()), jit_type_float64); // e.update_fpr_value(i.D.RT, v); @@ -856,7 +860,7 @@ namespace libjit { // // FRT <- DOUBLE(MEM(EA, 4)) // // RA <- EA -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); +// jit_value_t ea = jit_insn_add(f, e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); // jit_value_t v = e.ReadMemory(i.address, ea, 4, false); // v = b.CreateFPExt(b.CreateBitCast(v, b.getFloatTy()), jit_type_float64); // e.update_fpr_value(i.X.RT, v); @@ -875,7 +879,7 @@ namespace libjit { // jit_value_t ea = e.gpr_value(i.X.RB); // if (i.X.RA) { -// ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); +// ea = jit_insn_add(f, e.gpr_value(i.X.RA), ea); // } // jit_value_t v = e.ReadMemory(i.address, ea, 4, false); // v = b.CreateFPExt(b.CreateBitCast(v, b.getFloatTy()), jit_type_float64); @@ -895,9 +899,9 @@ namespace libjit { // // EA <- b + EXTS(D) // // MEM(EA, 8) <- (FRS) -// jit_value_t ea = b.getInt64(XEEXTS16(i.D.DS)); +// jit_value_t ea = e.get_int64(XEEXTS16(i.D.DS)); // if (i.D.RA) { -// ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); +// ea = jit_insn_add(f, e.gpr_value(i.D.RA), ea); // } // jit_value_t v = e.fpr_value(i.D.RT); // v = b.CreateBitCast(v, jit_type_nint); @@ -911,8 +915,8 @@ namespace libjit { // // MEM(EA, 8) <- (FRS) // // RA <- EA -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.D.RA), -// b.getInt64(XEEXTS16(i.D.DS))); +// jit_value_t ea = jit_insn_add(f, e.gpr_value(i.D.RA), +// e.get_int64(XEEXTS16(i.D.DS))); // jit_value_t v = e.fpr_value(i.D.RT); // v = b.CreateBitCast(v, jit_type_nint); // e.WriteMemory(i.address, ea, 8, v); @@ -926,7 +930,7 @@ namespace libjit { // // MEM(EA, 8) <- (FRS) // // RA <- EA -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); +// jit_value_t ea = jit_insn_add(f, e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); // jit_value_t v = e.fpr_value(i.X.RT); // v = b.CreateBitCast(v, jit_type_nint); // e.WriteMemory(i.address, ea, 8, v); @@ -945,7 +949,7 @@ namespace libjit { // jit_value_t ea = e.gpr_value(i.X.RB); // if (i.X.RA) { -// ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); +// ea = jit_insn_add(f, e.gpr_value(i.X.RA), ea); // } // jit_value_t v = e.fpr_value(i.X.RT); // v = b.CreateBitCast(v, jit_type_nint); @@ -964,7 +968,7 @@ namespace libjit { // jit_value_t ea = e.gpr_value(i.X.RB); // if (i.X.RA) { -// ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); +// ea = jit_insn_add(f, e.gpr_value(i.D.RA), ea); // } // jit_value_t v = e.fpr_value(i.X.RT); // v = b.CreateBitCast(v, jit_type_nint); @@ -981,9 +985,9 @@ namespace libjit { // // EA <- b + EXTS(D) // // MEM(EA, 4) <- SINGLE(FRS) -// jit_value_t ea = b.getInt64(XEEXTS16(i.D.DS)); +// jit_value_t ea = e.get_int64(XEEXTS16(i.D.DS)); // if (i.D.RA) { -// ea = b.CreateAdd(e.gpr_value(i.D.RA), ea); +// ea = jit_insn_add(f, e.gpr_value(i.D.RA), ea); // } // jit_value_t v = e.fpr_value(i.D.RT); // v = b.CreateBitCast(b.CreateFPTrunc(v, b.getFloatTy()), b.getInt32Ty()); @@ -997,8 +1001,8 @@ namespace libjit { // // MEM(EA, 4) <- SINGLE(FRS) // // RA <- EA -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.D.RA), -// b.getInt64(XEEXTS16(i.D.DS))); +// jit_value_t ea = jit_insn_add(f, e.gpr_value(i.D.RA), +// e.get_int64(XEEXTS16(i.D.DS))); // jit_value_t v = e.fpr_value(i.D.RT); // v = b.CreateBitCast(b.CreateFPTrunc(v, b.getFloatTy()), b.getInt32Ty()); // e.WriteMemory(i.address, ea, 4, v); @@ -1012,7 +1016,7 @@ namespace libjit { // // MEM(EA, 4) <- SINGLE(FRS) // // RA <- EA -// jit_value_t ea = b.CreateAdd(e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); +// jit_value_t ea = jit_insn_add(f, e.gpr_value(i.X.RA), e.gpr_value(i.X.RB)); // jit_value_t v = e.fpr_value(i.X.RT); // v = b.CreateBitCast(b.CreateFPTrunc(v, b.getFloatTy()), b.getInt32Ty()); // e.WriteMemory(i.address, ea, 4, v); @@ -1031,7 +1035,7 @@ namespace libjit { // jit_value_t ea = e.gpr_value(i.X.RB); // if (i.X.RA) { -// ea = b.CreateAdd(e.gpr_value(i.X.RA), ea); +// ea = jit_insn_add(f, e.gpr_value(i.X.RA), ea); // } // jit_value_t v = e.fpr_value(i.X.RT); // v = b.CreateBitCast(b.CreateFPTrunc(v, b.getFloatTy()), b.getInt32Ty()); @@ -1041,101 +1045,101 @@ namespace libjit { // } -// // Cache management (A-27) +// Cache management (A-27) -// XEEMITTER(dcbf, 0x7C0000AC, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(dcbf, 0x7C0000AC, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} -// XEEMITTER(dcbst, 0x7C00006C, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(dcbst, 0x7C00006C, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} -// XEEMITTER(dcbt, 0x7C00022C, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // No-op for now. -// // TODO(benvanik): use @llvm.prefetch -// return 0; -// } +XEEMITTER(dcbt, 0x7C00022C, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // No-op for now. + // TODO(benvanik): use @llvm.prefetch + return 0; +} -// XEEMITTER(dcbtst, 0x7C0001EC, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // No-op for now. -// // TODO(benvanik): use @llvm.prefetch -// return 0; -// } +XEEMITTER(dcbtst, 0x7C0001EC, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // No-op for now. + // TODO(benvanik): use @llvm.prefetch + return 0; +} -// XEEMITTER(dcbz, 0x7C0007EC, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // or dcbz128 0x7C2007EC -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(dcbz, 0x7C0007EC, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // or dcbz128 0x7C2007EC + XEINSTRNOTIMPLEMENTED(); + return 1; +} -// XEEMITTER(icbi, 0x7C0007AC, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(icbi, 0x7C0007AC, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} void LibjitRegisterEmitCategoryMemory() { - // 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(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(sync, 0x7C0004AC); // XEREGISTERINSTR(lfd, 0xC8000000); // XEREGISTERINSTR(lfdu, 0xCC000000); // XEREGISTERINSTR(lfdux, 0x7C0004EE); @@ -1153,12 +1157,12 @@ void LibjitRegisterEmitCategoryMemory() { // 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); + XEREGISTERINSTR(dcbf, 0x7C0000AC); + XEREGISTERINSTR(dcbst, 0x7C00006C); + XEREGISTERINSTR(dcbt, 0x7C00022C); + XEREGISTERINSTR(dcbtst, 0x7C0001EC); + XEREGISTERINSTR(dcbz, 0x7C0007EC); + XEREGISTERINSTR(icbi, 0x7C0007AC); } diff --git a/src/xenia/cpu/libjit/libjit_emitter.cc b/src/xenia/cpu/libjit/libjit_emitter.cc index 572f8e9b5..743860947 100644 --- a/src/xenia/cpu/libjit/libjit_emitter.cc +++ b/src/xenia/cpu/libjit/libjit_emitter.cc @@ -146,8 +146,8 @@ int LibjitEmitter::PrepareFunction(FunctionSymbol* symbol) { // Set optimization options. // TODO(benvanik): add gflags - uint32_t opt_level = 0; uint32_t max_level = jit_function_get_max_optimization_level(); + uint32_t opt_level = max_level; // 0 opt_level = MIN(max_level, MAX(0, opt_level)); jit_function_set_optimization_level(fn, opt_level); @@ -480,29 +480,29 @@ void LibjitEmitter::GenerateBasicBlock(FunctionBlock* block) { // Add debugging tag. // TODO(benvanik): mark type. - jit_insn_mark_breakpoint(fn_, 1, ia); + //jit_insn_mark_breakpoint(fn_, 1, ia); if (FLAGS_trace_instructions) { - SpillRegisters(); - jit_insn_call_native( - fn_, - "XeTraceInstruction", - global_exports_.XeTraceInstruction, - global_export_signature_3_, - trace_args, XECOUNT(trace_args), - 0); + // SpillRegisters(); + // jit_insn_call_native( + // fn_, + // "XeTraceInstruction", + // global_exports_.XeTraceInstruction, + // global_export_signature_3_, + // trace_args, XECOUNT(trace_args), + // 0); } if (!i.type) { XELOGCPU("Invalid instruction %.8X %.8X", ia, i.code); - SpillRegisters(); - jit_insn_call_native( - fn_, - "XeInvalidInstruction", - global_exports_.XeInvalidInstruction, - global_export_signature_3_, - trace_args, XECOUNT(trace_args), - 0); + // SpillRegisters(); + // jit_insn_call_native( + // fn_, + // "XeInvalidInstruction", + // global_exports_.XeInvalidInstruction, + // global_export_signature_3_, + // trace_args, XECOUNT(trace_args), + // 0); continue; } @@ -527,14 +527,14 @@ void LibjitEmitter::GenerateBasicBlock(FunctionBlock* block) { XELOGCPU("Unimplemented instr %.8X %.8X %s", ia, i.code, i.type->name); - SpillRegisters(); - jit_insn_call_native( - fn_, - "XeInvalidInstruction", - global_exports_.XeInvalidInstruction, - global_export_signature_3_, - trace_args, XECOUNT(trace_args), - 0); + // SpillRegisters(); + // jit_insn_call_native( + // fn_, + // "XeInvalidInstruction", + // global_exports_.XeInvalidInstruction, + // global_export_signature_3_, + // trace_args, XECOUNT(trace_args), + // 0); } } @@ -554,6 +554,134 @@ void LibjitEmitter::GenerateBasicBlock(FunctionBlock* block) { // TODO(benvanik): finish up BB } +jit_value_t LibjitEmitter::get_int64(int64_t value) { + return jit_value_create_nint_constant(fn_, jit_type_nint, value); +} + +jit_value_t LibjitEmitter::get_uint64(uint64_t value) { + return jit_value_create_nint_constant(fn_, jit_type_nuint, value); +} + +jit_value_t LibjitEmitter::make_signed(jit_value_t value) { + jit_type_t source_type = jit_value_get_type(value); + source_type = jit_type_normalize(source_type); + jit_type_t signed_source_type = source_type; + switch (jit_type_get_kind(source_type)) { + case JIT_TYPE_UBYTE: signed_source_type = jit_type_sbyte; break; + case JIT_TYPE_USHORT: signed_source_type = jit_type_short; break; + case JIT_TYPE_UINT: signed_source_type = jit_type_int; break; + case JIT_TYPE_NUINT: signed_source_type = jit_type_nint; break; + case JIT_TYPE_ULONG: signed_source_type = jit_type_long; break; + } + if (signed_source_type != source_type) { + value = jit_insn_convert(fn_, value, signed_source_type, 0); + } + return value; +} + +jit_value_t LibjitEmitter::make_unsigned(jit_value_t value) { + jit_type_t source_type = jit_value_get_type(value); + source_type = jit_type_normalize(source_type); + jit_type_t unsigned_source_type = source_type; + switch (jit_type_get_kind(source_type)) { + case JIT_TYPE_SBYTE: unsigned_source_type = jit_type_ubyte; break; + case JIT_TYPE_SHORT: unsigned_source_type = jit_type_ushort; break; + case JIT_TYPE_INT: unsigned_source_type = jit_type_uint; break; + case JIT_TYPE_NINT: unsigned_source_type = jit_type_nuint; break; + case JIT_TYPE_LONG: unsigned_source_type = jit_type_ulong; break; + } + if (unsigned_source_type != source_type) { + value = jit_insn_convert(fn_, value, unsigned_source_type, 0); + } + return value; +} + +jit_value_t LibjitEmitter::sign_extend(jit_value_t value, + jit_type_t target_type) { + // TODO(benvanik): better conversion checking. + // Libjit follows the C rules, which is that the source type indicates whether + // sign extension occurs. + // For example, int -> ulong is sign extended, + // uint -> ulong is zero extended. + // We convert to the same type with the expected sign and then use the built + // in convert, only if needed. + + // No-op if the same types. + jit_type_t source_type = jit_value_get_type(value); + source_type = jit_type_normalize(source_type); + target_type = jit_type_normalize(target_type); + if (source_type == target_type) { + return value; + } + + // If just a sign change, simple conversion. + if (jit_type_get_size(source_type) == jit_type_get_size(target_type)) { + return jit_insn_convert(fn_, value, target_type, 0); + } + + // Otherwise, need to convert to signed of the current type then extend. + value = make_signed(value); + return jit_insn_convert(fn_, value, target_type, 0); +} + +jit_value_t LibjitEmitter::zero_extend(jit_value_t value, + jit_type_t target_type) { + // See the comment in ::sign_extend for more information. + + // No-op if the same types. + jit_type_t source_type = jit_value_get_type(value); + source_type = jit_type_normalize(source_type); + target_type = jit_type_normalize(target_type); + if (source_type == target_type) { + return value; + } + + // If just a sign change, simple conversion. + if (jit_type_get_size(source_type) == jit_type_get_size(target_type)) { + return jit_insn_convert(fn_, value, target_type, 0); + } + + // Otherwise, need to convert to signed of the current type then extend. + value = make_unsigned(value); + return jit_insn_convert(fn_, value, target_type, 0); +} + +jit_value_t LibjitEmitter::trunc_to_sbyte(jit_value_t value) { + jit_type_t source_type = jit_value_get_type(value); + source_type = jit_type_normalize(source_type); + if (source_type == jit_type_sbyte) { + return value; + } + return jit_insn_convert(fn_, value, jit_type_sbyte, 0); +} + +jit_value_t LibjitEmitter::trunc_to_ubyte(jit_value_t value) { + jit_type_t source_type = jit_value_get_type(value); + source_type = jit_type_normalize(source_type); + if (source_type == jit_type_ubyte) { + return value; + } + return jit_insn_convert(fn_, value, jit_type_ubyte, 0); +} + +jit_value_t LibjitEmitter::trunc_to_short(jit_value_t value) { + jit_type_t source_type = jit_value_get_type(value); + source_type = jit_type_normalize(source_type); + if (source_type == jit_type_sbyte) { + return value; + } + return jit_insn_convert(fn_, value, jit_type_short, 0); +} + +jit_value_t LibjitEmitter::trunc_to_int(jit_value_t value) { + jit_type_t source_type = jit_value_get_type(value); + source_type = jit_type_normalize(source_type); + if (source_type == jit_type_sbyte) { + return value; + } + return jit_insn_convert(fn_, value, jit_type_int, 0); +} + int LibjitEmitter::branch_to_block(uint32_t address) { std::map::iterator it = bbs_.find(address); return jit_insn_branch(fn_, &it->second); @@ -895,10 +1023,7 @@ void LibjitEmitter::update_xer_value(jit_value_t value) { XEASSERTNOTNULL(locals_.xer); // Extend to 64bits if needed. - // TODO(benvanik): extend? - /*if (!value->getType()->isIntegerTy(64)) { - value = b.CreateZExt(value, jit_type_nuint); - }*/ + value = zero_extend(value, jit_type_nuint); jit_insn_store(fn_, locals_.xer, value); } @@ -961,10 +1086,7 @@ void LibjitEmitter::update_lr_value(jit_value_t value) { XEASSERTNOTNULL(locals_.lr); // Extend to 64bits if needed. - // TODO(benvanik): extend? - /*if (!value->getType()->isIntegerTy(64)) { - value = b.CreateZExt(value, jit_type_nuint); - }*/ + value = zero_extend(value, jit_type_nuint); jit_insn_store(fn_, locals_.lr, value); } @@ -977,65 +1099,64 @@ void LibjitEmitter::update_ctr_value(jit_value_t value) { XEASSERTNOTNULL(locals_.ctr); // Extend to 64bits if needed. - // TODO(benvanik): extend? - /*if (!value->getType()->isIntegerTy(64)) { - value = b.CreateZExt(value, jit_type_nuint); - }*/ + value = zero_extend(value, jit_type_nuint); jit_insn_store(fn_, locals_.ctr, value); } -//jit_value_t LibjitEmitter::cr_value(uint32_t n) { -// XEASSERT(n >= 0 && n < 8); -// XEASSERTNOTNULL(locals_.cr[n]); -// -// jit_value_t v = jit_insn_load(fn_, locals_.cr[n]); -// v = b.CreateZExt(v, jit_type_nuint); -// return v; -//} -// -//void LibjitEmitter::update_cr_value(uint32_t n, jit_value_t value) { -// XEASSERT(n >= 0 && n < 8); -// XEASSERTNOTNULL(locals_.cr[n]); -// -// // 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 LibjitEmitter::update_cr_with_cond( -// uint32_t n, jit_value_t lhs, jit_value_t rhs, bool is_signed) { -// -// // 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. -// // jit_value_t cmp = InlineAsm::get( -// // FunctionType::get(), -// // "cmp $0, $1 \n" -// // "mov from compare registers \n", -// // "r,r", ?? -// // true); -// -// jit_value_t is_lt = is_signed ? -// b.CreateICmpSLT(lhs, rhs) : b.CreateICmpULT(lhs, rhs); -// jit_value_t is_gt = is_signed ? -// b.CreateICmpSGT(lhs, rhs) : b.CreateICmpUGT(lhs, rhs); -// jit_value_t cp = b.CreateSelect(is_gt, b.getInt8(1 << 1), b.getInt8(1 << 2)); -// jit_value_t 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); -//} +jit_value_t LibjitEmitter::cr_value(uint32_t n) { + XEASSERT(n >= 0 && n < 8); + XEASSERTNOTNULL(locals_.cr[n]); + + jit_value_t value = jit_insn_load(fn_, locals_.cr[n]); + value = zero_extend(value, jit_type_nuint); + return value; +} + +void LibjitEmitter::update_cr_value(uint32_t n, jit_value_t value) { + XEASSERT(n >= 0 && n < 8); + XEASSERTNOTNULL(locals_.cr[n]); + + // Truncate to 8 bits if needed. + // TODO(benvanik): also widen? + value = trunc_to_ubyte(value); + + jit_insn_store(fn_, locals_.cr[n], value); +} + +void LibjitEmitter::update_cr_with_cond( + uint32_t n, jit_value_t lhs, jit_value_t rhs, bool is_signed) { + // 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. + // jit_value_t cmp = InlineAsm::get( + // FunctionType::get(), + // "cmp $0, $1 \n" + // "mov from compare registers \n", + // "r,r", ?? + // true); + + // Convert input signs, if needed. + if (is_signed) { + lhs = make_signed(lhs); + rhs = make_signed(rhs); + } else { + lhs = make_unsigned(lhs); + rhs = make_unsigned(rhs); + } + jit_value_t c = jit_insn_lt(fn_, lhs, rhs); + c = jit_insn_or(fn_, jit_insn_gt(fn_, lhs, rhs), c); + c = jit_insn_or(fn_, jit_insn_eq(fn_, lhs, rhs), c); + + // TODO(benvanik): set bit 4 to XER[SO] + + // Insert the 4 bits into their location in the CR. + update_cr_value(n, c); +} jit_value_t LibjitEmitter::gpr_value(uint32_t n) { XEASSERT(n >= 0 && n < 32); @@ -1044,7 +1165,7 @@ jit_value_t LibjitEmitter::gpr_value(uint32_t n) { // Actually r0 is writable, even though nobody should ever do that. // Perhaps we can check usage and enable this if safe? // if (n == 0) { - // return jit_value_create_nuint_constant(fn_, jit_type_nint, 0); + // return get_uint64(0); // } return jit_insn_load(fn_, locals_.gpr[n]); @@ -1061,11 +1182,7 @@ void LibjitEmitter::update_gpr_value(uint32_t n, jit_value_t value) { // } // Extend to 64bits if needed. - // TODO(benvanik): extend? - //jit_insn_convert(fn_, value, jit_type_nuint, 0); - /*if (!value->getType()->isIntegerTy(64)) { - value = b.CreateZExt(value, jit_type_nuint); - }*/ + value = zero_extend(value, jit_type_nuint); jit_insn_store(fn_, locals_.gpr[n], value); } @@ -1113,8 +1230,8 @@ jit_value_t LibjitEmitter::GetMemoryAddress(uint32_t cia, jit_value_t addr) { // Rebase off of memory base pointer. // We could store the memory base as a global value (or indirection off of // state) if we wanted to avoid embedding runtime values into the code. - jit_nuint membase = (jit_nuint)xe_memory_addr(memory_, 0); - return jit_insn_add_relative(fn_, addr, membase); + jit_value_t membase = get_uint64((uint64_t)xe_memory_addr(memory_, 0)); + return jit_insn_add(fn_, addr, membase); } jit_value_t LibjitEmitter::ReadMemory( @@ -1155,9 +1272,7 @@ jit_value_t LibjitEmitter::ReadMemory( // Swap after loading. // TODO(benvanik): find a way to avoid this! if (needs_swap) { - // Function* bswap = Intrinsic::getDeclaration( - // gen_module_, Intrinsic::bswap, data_type); - // value = b.CreateCall(bswap, value); + value = jit_insn_bswap(fn_, value); } return value; @@ -1199,9 +1314,7 @@ void LibjitEmitter::WriteMemory( // Swap before storing. // TODO(benvanik): find a way to avoid this! if (needs_swap) { - // Function* bswap = Intrinsic::getDeclaration( - // gen_module_, Intrinsic::bswap, data_type); - // value = b.CreateCall(bswap, value); + value = jit_insn_bswap(fn_, value); } // TODO(benvanik): release semantics diff --git a/src/xenia/cpu/libjit/libjit_emitter.h b/src/xenia/cpu/libjit/libjit_emitter.h index d996a2a6d..eb476c765 100644 --- a/src/xenia/cpu/libjit/libjit_emitter.h +++ b/src/xenia/cpu/libjit/libjit_emitter.h @@ -36,6 +36,17 @@ public: jit_function_t fn(); sdb::FunctionBlock* fn_block(); + jit_value_t get_int64(int64_t value); + jit_value_t get_uint64(uint64_t value); + jit_value_t make_signed(jit_value_t value); + jit_value_t make_unsigned(jit_value_t value); + jit_value_t sign_extend(jit_value_t value, jit_type_t target_type); + jit_value_t zero_extend(jit_value_t value, jit_type_t target_type); + jit_value_t trunc_to_sbyte(jit_value_t value); + jit_value_t trunc_to_ubyte(jit_value_t value); + jit_value_t trunc_to_short(jit_value_t value); + jit_value_t trunc_to_int(jit_value_t value); + int branch_to_block(uint32_t address); int branch_to_block_if(uint32_t address, jit_value_t value); int branch_to_block_if_not(uint32_t address, jit_value_t value); diff --git a/third_party/libjit b/third_party/libjit index 61b04ce23..b73375e72 160000 --- a/third_party/libjit +++ b/third_party/libjit @@ -1 +1 @@ -Subproject commit 61b04ce23f04165c6d3041927a4bc62b53e8b032 +Subproject commit b73375e72ef395800b8290bd02a3a0104b52a92c