diff --git a/src/xenia/cpu/libjit/libjit_emit_alu.cc b/src/xenia/cpu/libjit/libjit_emit_alu.cc index b4b3aa58d..92c51421b 100644 --- a/src/xenia/cpu/libjit/libjit_emit_alu.cc +++ b/src/xenia/cpu/libjit/libjit_emit_alu.cc @@ -19,7 +19,7 @@ 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) @@ -125,7 +125,7 @@ XEEMITTER(addmex, 0x7C0001D4, XO )(LibjitEmitter& e, jit_function_t f, Ins // 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 ca = jit_insn_and(f, jit_insn_ushr(f, 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); @@ -175,7 +175,7 @@ XEEMITTER(divdux, 0x7C000392, XO )(LibjitEmitter& e, jit_function_t f, Ins // 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)), +// b.CreateCondBr(b.CreateICmpEQ(divisor, b.get_int32(0)), // i.XO.OE ? zero_bb : after_bb, nonzero_bb); // if (zero_bb) { @@ -228,7 +228,7 @@ XEEMITTER(divdux, 0x7C000392, XO )(LibjitEmitter& e, jit_function_t f, Ins // 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)), +// b.CreateCondBr(b.CreateICmpEQ(divisor, b.get_int32(0)), // i.XO.OE ? zero_bb : after_bb, nonzero_bb); // if (zero_bb) { @@ -421,7 +421,7 @@ XEEMITTER(subfcx, 0x7C000010, XO )(LibjitEmitter& e, jit_function_t f, Ins // // 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); +// jit_value_t ca = jit_insn_and(f, jit_insn_ushr(f, 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, @@ -491,157 +491,159 @@ XEEMITTER(cmp, 0x7C000000, X )(LibjitEmitter& e, jit_function_t f, Ins 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] +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; + 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 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); + jit_value_t rhs = e.get_int64(XEEXTS16(i.D.DS)); + e.update_cr_with_cond(BF, lhs, rhs, true); -// return 0; -// } + 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] +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; + 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); -// } + 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); + e.update_cr_with_cond(BF, lhs, rhs, false); -// return 0; -// } + 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] +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; + 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 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); + jit_value_t rhs = e.get_int64(i.D.DS); + e.update_cr_with_cond(BF, lhs, rhs, false); -// return 0; -// } + return 0; +} -// // Integer logical (A-5) +// Integer logical (A-5) -// XEEMITTER(andx, 0x7C000038, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RA <- (RS) & (RB) +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); + jit_value_t v = jit_insn_and(f, 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); -// } + if (i.X.Rc) { + // With cr0 update. + e.update_cr_with_cond(0, v, e.get_int64(0), true); + } -// return 0; -// } + return 0; +} -// XEEMITTER(andcx, 0x7C000078, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RA <- (RS) & ¬(RB) +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); + jit_value_t v = jit_insn_xor(f, e.gpr_value(i.X.RB), + e.get_int64(-1)); + v = jit_insn_and(f, 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); -// } + if (i.X.Rc) { + // With cr0 update. + e.update_cr_with_cond(0, v, e.get_int64(0), true); + } -// return 0; -// } + return 0; +} -// XEEMITTER(andix, 0x70000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RA <- (RS) & (i48.0 || UI) +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); + jit_value_t v = jit_insn_and(f, e.gpr_value(i.D.RT), e.get_uint64(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); + // With cr0 update. + e.update_cr_with_cond(0, v, e.get_int64(0), true); -// return 0; -// } + return 0; +} -// XEEMITTER(andisx, 0x74000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RA <- (RS) & (i32.0 || UI || i16.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); + jit_value_t v = jit_insn_and(f, e.gpr_value(i.D.RT), + e.get_uint64(((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); + // With cr0 update. + e.update_cr_with_cond(0, v, e.get_int64(0), true); -// return 1; -// } + return 1; +} -// XEEMITTER(cntlzdx, 0x7C000074, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// 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 @@ -670,411 +672,419 @@ XEEMITTER(cmp, 0x7C000000, X )(LibjitEmitter& e, jit_function_t f, Ins // return 0; // } -// XEEMITTER(eqvx, 0x7C000238, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +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 +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); + 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); -// } + if (i.X.Rc) { + // Update cr0. + e.update_cr_with_cond(0, v, e.get_int64(0), true); + } -// return 0; -// } + return 0; +} -// XEEMITTER(extshx, 0x7C000734, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +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(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(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)) +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); + jit_value_t v = jit_insn_or(f, e.gpr_value(i.X.RT), e.gpr_value(i.X.RB)); + v = jit_insn_xor(f, v, e.get_int64(-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); -// } + if (i.X.Rc) { + // With cr0 update. + e.update_cr_with_cond(0, v, e.get_int64(0), true); + } -// return 0; -// } + return 0; +} -// XEEMITTER(orx, 0x7C000378, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// // RA <- (RS) | (RB) +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); + jit_value_t v = jit_insn_or(f, 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); -// } + if (i.X.Rc) { + // With cr0 update. + e.update_cr_with_cond(0, v, e.get_int64(0), true); + } -// return 0; -// } + return 0; +} -// XEEMITTER(orcx, 0x7C000338, X )(LibjitEmitter& e, jit_function_t f, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +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) +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); + jit_value_t v = jit_insn_or(f, e.gpr_value(i.D.RT), + e.get_uint64((uint64_t)i.D.DS)); + e.update_gpr_value(i.D.RA, v); -// return 0; -// } + 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; -// } +XEEMITTER(oris, 0x64000000, D )(LibjitEmitter& e, jit_function_t f, InstrData& i) { + // RA <- (RS) | (i32.0 || UI || i16.0) + + jit_value_t v = jit_insn_or(f, e.gpr_value(i.D.RT), + e.get_uint64(((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 = jit_insn_xor(f, 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 = jit_insn_xor(f, e.gpr_value(i.D.RT), + e.get_uint64((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 = jit_insn_xor(f, e.gpr_value(i.D.RT), + e.get_uint64(((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 = jit_insn_and(f, e.gpr_value(i.M.RT), + e.get_uint64(UINT32_MAX)); + v = jit_insn_or(f, jit_insn_shl(f, v, e.get_uint32(32)), v); + // (v << shift) | (v >> (32 - shift)); + v = jit_insn_or(f, jit_insn_shl(f, v, e.get_uint32(i.M.SH)), + jit_insn_ushr(f, v, e.get_uint32(32 - i.M.SH))); + uint64_t m = XEMASK(i.M.MB + 32, i.M.ME + 32); + v = jit_insn_and(f, v, e.get_uint64(m)); + v = jit_insn_or(f, v, jit_insn_and(f, e.gpr_value(i.M.RA), + e.get_uint64(~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 = jit_insn_and(f, + e.trunc_to_int(e.gpr_value(i.M.RT)), + e.get_uint32((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 = jit_insn_and(f, e.gpr_value(i.M.RT), e.get_uint64(UINT32_MAX)); + v = jit_insn_or(f, jit_insn_shl(f, v, e.get_uint32(32)), v); + // (v << shift) | (v >> (32 - shift)); + v = jit_insn_or(f, jit_insn_shl(f, v, e.get_uint32(i.M.SH)), + jit_insn_ushr(f, v, e.get_uint32(32 - i.M.SH))); + v = jit_insn_and(f, v, e.get_uint64(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 = jit_insn_shl(f, e.gpr_value(i.X.RT), e.gpr_value(i.X.RB)); + v = jit_insn_and(f, v, e.get_uint64(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 = jit_insn_sshr(f, rs32, e.get_uint32(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 = jit_insn_and(f, jit_insn_lt(f, v, e.get_int32(0)), + jit_insn_lt(f, 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(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(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_emitter.cc b/src/xenia/cpu/libjit/libjit_emitter.cc index 743860947..34edf65c3 100644 --- a/src/xenia/cpu/libjit/libjit_emitter.cc +++ b/src/xenia/cpu/libjit/libjit_emitter.cc @@ -554,6 +554,14 @@ void LibjitEmitter::GenerateBasicBlock(FunctionBlock* block) { // TODO(benvanik): finish up BB } +jit_value_t LibjitEmitter::get_int32(int32_t value) { + return jit_value_create_nint_constant(fn_, jit_type_int, value); +} + +jit_value_t LibjitEmitter::get_uint32(uint32_t value) { + return jit_value_create_nint_constant(fn_, jit_type_uint, value); +} + jit_value_t LibjitEmitter::get_int64(int64_t value) { return jit_value_create_nint_constant(fn_, jit_type_nint, value); } @@ -766,7 +774,7 @@ int LibjitEmitter::branch_to_return_if_not(jit_value_t value) { // b.CreateStore(b.getInt64(cia), locals_.indirection_cia); // jit_value_t symbol_ge_cmp = b.CreateICmpUGE(target, b.getInt64(symbol_->start_address)); // jit_value_t symbol_l_cmp = b.CreateICmpULT(target, b.getInt64(symbol_->end_address)); -// jit_value_t symbol_target_cmp = b.CreateAnd(symbol_ge_cmp, symbol_l_cmp); +// jit_value_t symbol_target_cmp = jit_insn_and(fn_, symbol_ge_cmp, symbol_l_cmp); // b.CreateCondBr(symbol_target_cmp, // internal_indirection_block_, external_indirection_block_); // return 0; @@ -1027,55 +1035,50 @@ void LibjitEmitter::update_xer_value(jit_value_t value) { jit_insn_store(fn_, locals_.xer, value); } -//void LibjitEmitter::update_xer_with_overflow(jit_value_t value) { -// XEASSERTNOTNULL(locals_.xer); -// -// // Expects a i1 indicating overflow. -// // Trust the caller that if it's larger than that it's already truncated. -// if (!value->getType()->isIntegerTy(64)) { -// value = b.CreateZExt(value, jit_type_nuint); -// } -// -// jit_value_t xer = xer_value(); -// xer = b.CreateAnd(xer, 0xFFFFFFFFBFFFFFFF); // clear bit 30 -// xer = b.CreateOr(xer, b.CreateShl(value, 31)); -// xer = b.CreateOr(xer, b.CreateShl(value, 30)); -// jit_insn_store(fn_, locals_.xer, value); -//} -// -//void LibjitEmitter::update_xer_with_carry(jit_value_t value) { -// XEASSERTNOTNULL(locals_.xer); -// -// // Expects a i1 indicating carry. -// // Trust the caller that if it's larger than that it's already truncated. -// if (!value->getType()->isIntegerTy(64)) { -// value = b.CreateZExt(value, jit_type_nuint); -// } -// -// jit_value_t xer = xer_value(); -// xer = b.CreateAnd(xer, 0xFFFFFFFFDFFFFFFF); // clear bit 29 -// xer = b.CreateOr(xer, b.CreateShl(value, 29)); -// jit_insn_store(fn_, locals_.xer, value); -//} -// -//void LibjitEmitter::update_xer_with_overflow_and_carry(jit_value_t value) { -// XEASSERTNOTNULL(locals_.xer); -// -// // Expects a i1 indicating overflow. -// // Trust the caller that if it's larger than that it's already truncated. -// if (!value->getType()->isIntegerTy(64)) { -// value = b.CreateZExt(value, jit_type_nuint); -// } -// -// // This is effectively an update_xer_with_overflow followed by an -// // update_xer_with_carry, but since the logic is largely the same share it. -// jit_value_t xer = xer_value(); -// xer = b.CreateAnd(xer, 0xFFFFFFFF9FFFFFFF); // clear bit 30 & 29 -// xer = b.CreateOr(xer, b.CreateShl(value, 31)); -// xer = b.CreateOr(xer, b.CreateShl(value, 30)); -// xer = b.CreateOr(xer, b.CreateShl(value, 29)); -// jit_insn_store(fn_, locals_.xer, value); -//} +void LibjitEmitter::update_xer_with_overflow(jit_value_t value) { + XEASSERTNOTNULL(locals_.xer); + + // Expects a i1 indicating overflow. + // Trust the caller that if it's larger than that it's already truncated. + value = zero_extend(value, jit_type_nuint); + + jit_value_t xer = xer_value(); + xer = jit_insn_and(fn_, xer, get_uint64(0xFFFFFFFFBFFFFFFF)); // clear bit 30 + xer = jit_insn_or(fn_, xer, jit_insn_shl(fn_, value, get_uint32(31))); + xer = jit_insn_or(fn_, xer, jit_insn_shl(fn_, value, get_uint32(30))); + jit_insn_store(fn_, locals_.xer, value); +} + +void LibjitEmitter::update_xer_with_carry(jit_value_t value) { + XEASSERTNOTNULL(locals_.xer); + + // Expects a i1 indicating carry. + // Trust the caller that if it's larger than that it's already truncated. + value = zero_extend(value, jit_type_nuint); + + jit_value_t xer = xer_value(); + xer = jit_insn_and(fn_, xer, get_uint64(0xFFFFFFFFDFFFFFFF)); // clear bit 29 + xer = jit_insn_or(fn_, xer, jit_insn_shl(fn_, value, get_uint32(29))); + jit_insn_store(fn_, locals_.xer, value); +} + +void LibjitEmitter::update_xer_with_overflow_and_carry(jit_value_t value) { + XEASSERTNOTNULL(locals_.xer); + + // Expects a i1 indicating overflow. + // Trust the caller that if it's larger than that it's already truncated. + value = zero_extend(value, jit_type_nuint); + + // This is effectively an update_xer_with_overflow followed by an + // update_xer_with_carry, but since the logic is largely the same share it. + jit_value_t xer = xer_value(); + // clear bit 30 & 29 + xer = jit_insn_and(fn_, xer, get_uint64(0xFFFFFFFF9FFFFFFF)); + xer = jit_insn_or(fn_, xer, jit_insn_shl(fn_, value, get_uint32(31))); + xer = jit_insn_or(fn_, xer, jit_insn_shl(fn_, value, get_uint32(30))); + xer = jit_insn_or(fn_, xer, jit_insn_shl(fn_, value, get_uint32(29))); + jit_insn_store(fn_, locals_.xer, value); +} jit_value_t LibjitEmitter::lr_value() { XEASSERTNOTNULL(locals_.lr); diff --git a/src/xenia/cpu/libjit/libjit_emitter.h b/src/xenia/cpu/libjit/libjit_emitter.h index eb476c765..26fce1c9f 100644 --- a/src/xenia/cpu/libjit/libjit_emitter.h +++ b/src/xenia/cpu/libjit/libjit_emitter.h @@ -36,6 +36,8 @@ public: jit_function_t fn(); sdb::FunctionBlock* fn_block(); + jit_value_t get_int32(int32_t value); + jit_value_t get_uint32(uint32_t value); 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);