From b8323c30550d8d130934c26ffd69f4fa5ef92d5c Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Fri, 24 May 2013 03:51:58 -0700 Subject: [PATCH] Preparing some control instructions for proper emitting. --- src/xenia/cpu/x64/x64_emit_control.cc | 718 +++++++++++++------------- src/xenia/cpu/x64/x64_emitter.cc | 23 +- 2 files changed, 369 insertions(+), 372 deletions(-) diff --git a/src/xenia/cpu/x64/x64_emit_control.cc b/src/xenia/cpu/x64/x64_emit_control.cc index d3e5b90d5..3b341ea30 100644 --- a/src/xenia/cpu/x64/x64_emit_control.cc +++ b/src/xenia/cpu/x64/x64_emit_control.cc @@ -75,6 +75,7 @@ int XeEmitBranchTo( XEASSERTALWAYS(); } else { //e.TraceBranch(cia); + //e.SpillRegisters(); //c.jmp(e.GetBlockLabel(fn_block->outgoing_address)); } return 0; @@ -184,404 +185,399 @@ XEEMITTER(bx, 0x48000000, I )(X64Emitter& e, X86Compiler& c, InstrDat return XeEmitBranchTo(e, c, "bx", i.address, i.I.LK); } -// XEEMITTER(bcx, 0x40000000, B )(X64Emitter& e, X86Compiler& c, InstrData& i) { -// // if ¬BO[2] then -// // CTR <- CTR - 1 -// // ctr_ok <- BO[2] | ((CTR[0:63] != 0) XOR BO[3]) -// // cond_ok <- BO[0] | (CR[BI+32] ≡ BO[1]) -// // if ctr_ok & cond_ok then -// // if AA then -// // NIA <- EXTS(BD || 0b00) -// // else -// // NIA <- CIA + EXTS(BD || 0b00) -// // if LK then -// // LR <- CIA + 4 +XEEMITTER(bcx, 0x40000000, B )(X64Emitter& e, X86Compiler& c, InstrData& i) { + // if ¬BO[2] then + // CTR <- CTR - 1 + // ctr_ok <- BO[2] | ((CTR[0:63] != 0) XOR BO[3]) + // cond_ok <- BO[0] | (CR[BI+32] ≡ BO[1]) + // if ctr_ok & cond_ok then + // if AA then + // NIA <- EXTS(BD || 0b00) + // else + // NIA <- CIA + EXTS(BD || 0b00) + // if LK then + // LR <- CIA + 4 -// // NOTE: the condition bits are reversed! -// // 01234 (docs) -// // 43210 (real) + // NOTE: the condition bits are reversed! + // 01234 (docs) + // 43210 (real) -// // TODO(benvanik): this may be wrong and overwrite LRs when not desired! -// // The docs say always, though... -// if (i.B.LK) { -// e.update_lr_value(e.get_uint64(i.address + 4)); -// } + // // TODO(benvanik): this may be wrong and overwrite LRs when not desired! + // // The docs say always, though... + // if (i.B.LK) { + // e.update_lr_value(e.get_uint64(i.address + 4)); + // } -// jit_value_t ctr_ok = NULL; -// if (XESELECTBITS(i.B.BO, 2, 2)) { -// // Ignore ctr. -// } else { -// // Decrement counter. -// jit_value_t ctr = e.ctr_value(); -// ctr = jit_insn_sub(f, ctr, e.get_int64(1)); -// e.update_ctr_value(ctr); + // jit_value_t ctr_ok = NULL; + // if (XESELECTBITS(i.B.BO, 2, 2)) { + // // Ignore ctr. + // } else { + // // Decrement counter. + // jit_value_t ctr = e.ctr_value(); + // ctr = jit_insn_sub(f, ctr, e.get_int64(1)); + // e.update_ctr_value(ctr); -// // Ctr check. -// if (XESELECTBITS(i.B.BO, 1, 1)) { -// ctr_ok = jit_insn_eq(f, ctr, e.get_int64(0)); -// } else { -// ctr_ok = jit_insn_ne(f, ctr, e.get_int64(0)); -// } -// } + // // Ctr check. + // if (XESELECTBITS(i.B.BO, 1, 1)) { + // ctr_ok = jit_insn_eq(f, ctr, e.get_int64(0)); + // } else { + // ctr_ok = jit_insn_ne(f, ctr, e.get_int64(0)); + // } + // } -// jit_value_t cond_ok = NULL; -// if (XESELECTBITS(i.B.BO, 4, 4)) { -// // Ignore cond. -// } else { -// jit_value_t cr = e.cr_value(i.B.BI >> 2); -// cr = jit_insn_and(f, cr, e.get_uint32(1 << (i.B.BI & 3))); -// if (XESELECTBITS(i.B.BO, 3, 3)) { -// cond_ok = jit_insn_ne(f, cr, e.get_int64(0)); -// } else { -// cond_ok = jit_insn_eq(f, cr, e.get_int64(0)); -// } -// } + // jit_value_t cond_ok = NULL; + // if (XESELECTBITS(i.B.BO, 4, 4)) { + // // Ignore cond. + // } else { + // jit_value_t cr = e.cr_value(i.B.BI >> 2); + // cr = jit_insn_and(f, cr, e.get_uint32(1 << (i.B.BI & 3))); + // if (XESELECTBITS(i.B.BO, 3, 3)) { + // cond_ok = jit_insn_ne(f, cr, e.get_int64(0)); + // } else { + // cond_ok = jit_insn_eq(f, cr, e.get_int64(0)); + // } + // } -// // We do a bit of optimization here to make the llvm assembly easier to read. -// jit_value_t ok = NULL; -// if (ctr_ok && cond_ok) { -// ok = jit_insn_and(f, ctr_ok, cond_ok); -// } else if (ctr_ok) { -// ok = ctr_ok; -// } else if (cond_ok) { -// ok = cond_ok; -// } + // // We do a bit of optimization here to make the llvm assembly easier to read. + // jit_value_t ok = NULL; + // if (ctr_ok && cond_ok) { + // ok = jit_insn_and(f, ctr_ok, cond_ok); + // } else if (ctr_ok) { + // ok = ctr_ok; + // } else if (cond_ok) { + // ok = cond_ok; + // } -// uint32_t nia; -// if (i.B.AA) { -// nia = XEEXTS26(i.B.BD << 2); -// } else { -// nia = i.address + XEEXTS26(i.B.BD << 2); -// } -// if (XeEmitBranchTo(e, c, "bcx", i.address, i.B.LK, ok)) { -// return 1; -// } + // uint32_t nia; + // if (i.B.AA) { + // nia = XEEXTS26(i.B.BD << 2); + // } else { + // nia = i.address + XEEXTS26(i.B.BD << 2); + // } + // if (XeEmitBranchTo(e, c, "bcx", i.address, i.B.LK, ok)) { + // return 1; + // } -// return 0; -// } + return 0; +} -// XEEMITTER(bcctrx, 0x4C000420, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { -// // cond_ok <- BO[0] | (CR[BI+32] ≡ BO[1]) -// // if cond_ok then -// // NIA <- CTR[0:61] || 0b00 -// // if LK then -// // LR <- CIA + 4 +XEEMITTER(bcctrx, 0x4C000420, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { + // cond_ok <- BO[0] | (CR[BI+32] ≡ BO[1]) + // if cond_ok then + // NIA <- CTR[0:61] || 0b00 + // if LK then + // LR <- CIA + 4 -// // NOTE: the condition bits are reversed! -// // 01234 (docs) -// // 43210 (real) + // NOTE: the condition bits are reversed! + // 01234 (docs) + // 43210 (real) -// // TODO(benvanik): this may be wrong and overwrite LRs when not desired! -// // The docs say always, though... -// if (i.XL.LK) { -// e.update_lr_value(e.get_uint64(i.address + 4)); -// } + // // TODO(benvanik): this may be wrong and overwrite LRs when not desired! + // // The docs say always, though... + // if (i.XL.LK) { + // e.update_lr_value(e.get_uint64(i.address + 4)); + // } -// jit_value_t cond_ok = NULL; -// if (XESELECTBITS(i.XL.BO, 4, 4)) { -// // Ignore cond. -// } else { -// jit_value_t cr = e.cr_value(i.XL.BI >> 2); -// cr = jit_insn_and(f, cr, e.get_uint64(1 << (i.XL.BI & 3))); -// if (XESELECTBITS(i.XL.BO, 3, 3)) { -// cond_ok = jit_insn_ne(f, cr, e.get_int64(0)); -// } else { -// cond_ok = jit_insn_eq(f, cr, e.get_int64(0)); -// } -// } + // jit_value_t cond_ok = NULL; + // if (XESELECTBITS(i.XL.BO, 4, 4)) { + // // Ignore cond. + // } else { + // jit_value_t cr = e.cr_value(i.XL.BI >> 2); + // cr = jit_insn_and(f, cr, e.get_uint64(1 << (i.XL.BI & 3))); + // if (XESELECTBITS(i.XL.BO, 3, 3)) { + // cond_ok = jit_insn_ne(f, cr, e.get_int64(0)); + // } else { + // cond_ok = jit_insn_eq(f, cr, e.get_int64(0)); + // } + // } -// // We do a bit of optimization here to make the llvm assembly easier to read. -// jit_value_t ok = NULL; -// if (cond_ok) { -// ok = cond_ok; -// } + // // We do a bit of optimization here to make the llvm assembly easier to read. + // jit_value_t ok = NULL; + // if (cond_ok) { + // ok = cond_ok; + // } -// if (XeEmitBranchTo(e, c, "bcctrx", i.address, i.XL.LK, ok)) { -// return 1; -// } + // if (XeEmitBranchTo(e, c, "bcctrx", i.address, i.XL.LK, ok)) { + // return 1; + // } -// return 0; -// } + return 0; +} -// XEEMITTER(bclrx, 0x4C000020, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { -// // if ¬BO[2] then -// // CTR <- CTR - 1 -// // ctr_ok <- BO[2] | ((CTR[0:63] != 0) XOR BO[3] -// // cond_ok <- BO[0] | (CR[BI+32] ≡ BO[1]) -// // if ctr_ok & cond_ok then -// // NIA <- LR[0:61] || 0b00 -// // if LK then -// // LR <- CIA + 4 +XEEMITTER(bclrx, 0x4C000020, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { + // if ¬BO[2] then + // CTR <- CTR - 1 + // ctr_ok <- BO[2] | ((CTR[0:63] != 0) XOR BO[3] + // cond_ok <- BO[0] | (CR[BI+32] ≡ BO[1]) + // if ctr_ok & cond_ok then + // NIA <- LR[0:61] || 0b00 + // if LK then + // LR <- CIA + 4 -// // NOTE: the condition bits are reversed! -// // 01234 (docs) -// // 43210 (real) + // NOTE: the condition bits are reversed! + // 01234 (docs) + // 43210 (real) -// // TODO(benvanik): this may be wrong and overwrite LRs when not desired! -// // The docs say always, though... -// if (i.XL.LK) { -// e.update_lr_value(e.get_uint64(i.address + 4)); -// } + // // TODO(benvanik): this may be wrong and overwrite LRs when not desired! + // // The docs say always, though... + // if (i.XL.LK) { + // e.update_lr_value(e.get_uint64(i.address + 4)); + // } -// jit_value_t ctr_ok = NULL; -// if (XESELECTBITS(i.XL.BO, 2, 2)) { -// // Ignore ctr. -// } else { -// // Decrement counter. -// jit_value_t ctr = e.ctr_value(); -// ctr = jit_insn_sub(f, ctr, e.get_int64(1)); + // jit_value_t ctr_ok = NULL; + // if (XESELECTBITS(i.XL.BO, 2, 2)) { + // // Ignore ctr. + // } else { + // // Decrement counter. + // jit_value_t ctr = e.ctr_value(); + // ctr = jit_insn_sub(f, ctr, e.get_int64(1)); -// // Ctr check. -// if (XESELECTBITS(i.XL.BO, 1, 1)) { -// ctr_ok = jit_insn_eq(f, ctr, e.get_int64(0)); -// } else { -// ctr_ok = jit_insn_ne(f, ctr, e.get_int64(0)); -// } -// } + // // Ctr check. + // if (XESELECTBITS(i.XL.BO, 1, 1)) { + // ctr_ok = jit_insn_eq(f, ctr, e.get_int64(0)); + // } else { + // ctr_ok = jit_insn_ne(f, ctr, e.get_int64(0)); + // } + // } -// jit_value_t cond_ok = NULL; -// if (XESELECTBITS(i.XL.BO, 4, 4)) { -// // Ignore cond. -// } else { -// jit_value_t cr = e.cr_value(i.XL.BI >> 2); -// cr = jit_insn_and(f, cr, e.get_uint32(1 << (i.XL.BI & 3))); -// if (XESELECTBITS(i.XL.BO, 3, 3)) { -// cond_ok = jit_insn_ne(f, cr, e.get_int64(0)); -// } else { -// cond_ok = jit_insn_eq(f, cr, e.get_int64(0)); -// } -// } + // jit_value_t cond_ok = NULL; + // if (XESELECTBITS(i.XL.BO, 4, 4)) { + // // Ignore cond. + // } else { + // jit_value_t cr = e.cr_value(i.XL.BI >> 2); + // cr = jit_insn_and(f, cr, e.get_uint32(1 << (i.XL.BI & 3))); + // if (XESELECTBITS(i.XL.BO, 3, 3)) { + // cond_ok = jit_insn_ne(f, cr, e.get_int64(0)); + // } else { + // cond_ok = jit_insn_eq(f, cr, e.get_int64(0)); + // } + // } -// // We do a bit of optimization here to make the llvm assembly easier to read. -// jit_value_t ok = NULL; -// if (ctr_ok && cond_ok) { -// ok = jit_insn_and(f, ctr_ok, cond_ok); -// } else if (ctr_ok) { -// ok = ctr_ok; -// } else if (cond_ok) { -// ok = cond_ok; -// } + // // We do a bit of optimization here to make the llvm assembly easier to read. + // jit_value_t ok = NULL; + // if (ctr_ok && cond_ok) { + // ok = jit_insn_and(f, ctr_ok, cond_ok); + // } else if (ctr_ok) { + // ok = ctr_ok; + // } else if (cond_ok) { + // ok = cond_ok; + // } -// if (XeEmitBranchTo(e, c, "bclrx", i.address, i.XL.LK, ok)) { -// return 1; -// } + // if (XeEmitBranchTo(e, c, "bclrx", i.address, i.XL.LK, ok)) { + // return 1; + // } -// return 0; -// } + return 0; +} -// // Condition register logical (A-23) +// Condition register logical (A-23) -// XEEMITTER(crand, 0x4C000202, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(crand, 0x4C000202, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} -// XEEMITTER(crandc, 0x4C000102, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(crandc, 0x4C000102, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} -// XEEMITTER(creqv, 0x4C000242, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(creqv, 0x4C000242, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} -// XEEMITTER(crnand, 0x4C0001C2, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(crnand, 0x4C0001C2, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} -// XEEMITTER(crnor, 0x4C000042, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(crnor, 0x4C000042, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} -// XEEMITTER(cror, 0x4C000382, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(cror, 0x4C000382, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} -// XEEMITTER(crorc, 0x4C000342, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(crorc, 0x4C000342, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} -// XEEMITTER(crxor, 0x4C000182, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(crxor, 0x4C000182, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} -// XEEMITTER(mcrf, 0x4C000000, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(mcrf, 0x4C000000, XL )(X64Emitter& e, X86Compiler& c, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} -// // System linkage (A-24) +// System linkage (A-24) -// XEEMITTER(sc, 0x44000002, SC )(X64Emitter& e, X86Compiler& c, InstrData& i) { -// XEINSTRNOTIMPLEMENTED(); -// return 1; -// } +XEEMITTER(sc, 0x44000002, SC )(X64Emitter& e, X86Compiler& c, InstrData& i) { + XEINSTRNOTIMPLEMENTED(); + return 1; +} -// // Trap (A-25) +// Trap (A-25) -// int XeEmitTrap(X64Emitter& e, X86Compiler& c, InstrData& i, -// jit_value_t va, jit_value_t vb, uint32_t TO) { -// // if (a < b) & TO[0] then TRAP -// // if (a > b) & TO[1] then TRAP -// // if (a = b) & TO[2] then TRAP -// // if (a u b) & TO[4] then TRAP -// // Bits swapped: -// // 01234 -// // 43210 +int XeEmitTrap(X64Emitter& e, X86Compiler& c, InstrData& i, + GpVar& va, GpVar& vb, uint32_t TO) { + // if (a < b) & TO[0] then TRAP + // if (a > b) & TO[1] then TRAP + // if (a = b) & TO[2] then TRAP + // if (a u b) & TO[4] then TRAP + // Bits swapped: + // 01234 + // 43210 -// if (!TO) { -// return 0; -// } + if (!TO) { + return 0; + } -// // TODO(benvanik): port from LLVM -// XEASSERTALWAYS(); + // TODO(benvanik): port from LLVM + XEASSERTALWAYS(); -// // BasicBlock* after_bb = BasicBlock::Create(*e.context(), "", e.fn(), -// // e.GetNextBasicBlock()); -// // BasicBlock* trap_bb = BasicBlock::Create(*e.context(), "", e.fn(), -// // after_bb); + // BasicBlock* after_bb = BasicBlock::Create(*e.context(), "", e.fn(), + // e.GetNextBasicBlock()); + // BasicBlock* trap_bb = BasicBlock::Create(*e.context(), "", e.fn(), + // after_bb); -// // // Create the basic blocks (so we can chain). -// // std::vector bbs; -// // if (TO & (1 << 4)) { -// // bbs.push_back(BasicBlock::Create(*e.context(), "", e.fn(), trap_bb)); -// // } -// // if (TO & (1 << 3)) { -// // bbs.push_back(BasicBlock::Create(*e.context(), "", e.fn(), trap_bb)); -// // } -// // if (TO & (1 << 2)) { -// // bbs.push_back(BasicBlock::Create(*e.context(), "", e.fn(), trap_bb)); -// // } -// // if (TO & (1 << 1)) { -// // bbs.push_back(BasicBlock::Create(*e.context(), "", e.fn(), trap_bb)); -// // } -// // if (TO & (1 << 0)) { -// // bbs.push_back(BasicBlock::Create(*e.context(), "", e.fn(), trap_bb)); -// // } -// // bbs.push_back(after_bb); + // // Create the basic blocks (so we can chain). + // std::vector bbs; + // if (TO & (1 << 4)) { + // bbs.push_back(BasicBlock::Create(*e.context(), "", e.fn(), trap_bb)); + // } + // if (TO & (1 << 3)) { + // bbs.push_back(BasicBlock::Create(*e.context(), "", e.fn(), trap_bb)); + // } + // if (TO & (1 << 2)) { + // bbs.push_back(BasicBlock::Create(*e.context(), "", e.fn(), trap_bb)); + // } + // if (TO & (1 << 1)) { + // bbs.push_back(BasicBlock::Create(*e.context(), "", e.fn(), trap_bb)); + // } + // if (TO & (1 << 0)) { + // bbs.push_back(BasicBlock::Create(*e.context(), "", e.fn(), trap_bb)); + // } + // bbs.push_back(after_bb); -// // // Jump to the first bb. -// // b.CreateBr(bbs.front()); + // // Jump to the first bb. + // b.CreateBr(bbs.front()); -// // // Setup each basic block. -// // std::vector::iterator it = bbs.begin(); -// // if (TO & (1 << 4)) { -// // // a < b -// // BasicBlock* bb = *(it++); -// // b.SetInsertPoint(bb); -// // jit_value_t cmp = b.CreateICmpSLT(va, vb); -// // b.CreateCondBr(cmp, trap_bb, *it); -// // } -// // if (TO & (1 << 3)) { -// // // a > b -// // BasicBlock* bb = *(it++); -// // b.SetInsertPoint(bb); -// // jit_value_t cmp = b.CreateICmpSGT(va, vb); -// // b.CreateCondBr(cmp, trap_bb, *it); -// // } -// // if (TO & (1 << 2)) { -// // // a = b -// // BasicBlock* bb = *(it++); -// // b.SetInsertPoint(bb); -// // jit_value_t cmp = b.CreateICmpEQ(va, vb); -// // b.CreateCondBr(cmp, trap_bb, *it); -// // } -// // if (TO & (1 << 1)) { -// // // a u b -// // BasicBlock* bb = *(it++); -// // b.SetInsertPoint(bb); -// // jit_value_t cmp = b.CreateICmpUGT(va, vb); -// // b.CreateCondBr(cmp, trap_bb, *it); -// // } + // // Setup each basic block. + // std::vector::iterator it = bbs.begin(); + // if (TO & (1 << 4)) { + // // a < b + // BasicBlock* bb = *(it++); + // b.SetInsertPoint(bb); + // jit_value_t cmp = b.CreateICmpSLT(va, vb); + // b.CreateCondBr(cmp, trap_bb, *it); + // } + // if (TO & (1 << 3)) { + // // a > b + // BasicBlock* bb = *(it++); + // b.SetInsertPoint(bb); + // jit_value_t cmp = b.CreateICmpSGT(va, vb); + // b.CreateCondBr(cmp, trap_bb, *it); + // } + // if (TO & (1 << 2)) { + // // a = b + // BasicBlock* bb = *(it++); + // b.SetInsertPoint(bb); + // jit_value_t cmp = b.CreateICmpEQ(va, vb); + // b.CreateCondBr(cmp, trap_bb, *it); + // } + // if (TO & (1 << 1)) { + // // a u b + // BasicBlock* bb = *(it++); + // b.SetInsertPoint(bb); + // jit_value_t cmp = b.CreateICmpUGT(va, vb); + // b.CreateCondBr(cmp, trap_bb, *it); + // } -// // // Create trap BB. -// // b.SetInsertPoint(trap_bb); -// // e.SpillRegisters(); -// // // TODO(benvanik): use @llvm.debugtrap? could make debugging better -// // b.CreateCall2(e.gen_module()->getFunction("XeTrap"), -// // e.fn()->arg_begin(), -// // e.get_uint64(i.address)); -// // b.CreateBr(after_bb); + // // Create trap BB. + // b.SetInsertPoint(trap_bb); + // e.SpillRegisters(); + // // TODO(benvanik): use @llvm.debugtrap? could make debugging better + // b.CreateCall2(e.gen_module()->getFunction("XeTrap"), + // e.fn()->arg_begin(), + // e.get_uint64(i.address)); + // b.CreateBr(after_bb); -// // // Resume. -// // b.SetInsertPoint(after_bb); + // // Resume. + // b.SetInsertPoint(after_bb); -// return 0; -// } + return 0; +} -// XEEMITTER(td, 0x7C000088, X )(X64Emitter& e, X86Compiler& c, InstrData& i) { -// // a <- (RA) -// // b <- (RB) -// // if (a < b) & TO[0] then TRAP -// // if (a > b) & TO[1] then TRAP -// // if (a = b) & TO[2] then TRAP -// // if (a u b) & TO[4] then TRAP -// return XeEmitTrap(e, f, i, -// e.gpr_value(i.X.RA), -// e.gpr_value(i.X.RB), -// i.X.RT); -// } +XEEMITTER(td, 0x7C000088, X )(X64Emitter& e, X86Compiler& c, InstrData& i) { + // a <- (RA) + // b <- (RB) + // if (a < b) & TO[0] then TRAP + // if (a > b) & TO[1] then TRAP + // if (a = b) & TO[2] then TRAP + // if (a u b) & TO[4] then TRAP + GpVar va = e.gpr_value(i.X.RA); + GpVar vb = e.gpr_value(i.X.RA); + return XeEmitTrap(e, c, i, va, vb, i.X.RT); +} -// XEEMITTER(tdi, 0x08000000, D )(X64Emitter& e, X86Compiler& c, InstrData& i) { -// // a <- (RA) -// // if (a < EXTS(SI)) & TO[0] then TRAP -// // if (a > EXTS(SI)) & TO[1] then TRAP -// // if (a = EXTS(SI)) & TO[2] then TRAP -// // if (a u EXTS(SI)) & TO[4] then TRAP -// return XeEmitTrap(e, f, i, -// e.gpr_value(i.D.RA), -// e.get_int64(XEEXTS16(i.D.DS)), -// i.D.RT); -// } +XEEMITTER(tdi, 0x08000000, D )(X64Emitter& e, X86Compiler& c, InstrData& i) { + // a <- (RA) + // if (a < EXTS(SI)) & TO[0] then TRAP + // if (a > EXTS(SI)) & TO[1] then TRAP + // if (a = EXTS(SI)) & TO[2] then TRAP + // if (a u EXTS(SI)) & TO[4] then TRAP + GpVar va = e.gpr_value(i.D.RA); + GpVar vb(c.newGpVar()); + c.mov(vb, imm(XEEXTS16(i.D.DS))); + return XeEmitTrap(e, c, i, va, vb, i.D.RT); +} -// XEEMITTER(tw, 0x7C000008, X )(X64Emitter& e, X86Compiler& c, InstrData& i) { -// // a <- EXTS((RA)[32:63]) -// // b <- EXTS((RB)[32:63]) -// // if (a < b) & TO[0] then TRAP -// // if (a > b) & TO[1] then TRAP -// // if (a = b) & TO[2] then TRAP -// // if (a u b) & TO[4] then TRAP -// return XeEmitTrap(e, f, i, -// e.sign_extend(e.trunc_to_int(e.gpr_value(i.X.RA)), -// jit_type_nint), -// e.sign_extend(e.trunc_to_int(e.gpr_value(i.X.RB)), -// jit_type_nint), -// i.X.RT); -// } +XEEMITTER(tw, 0x7C000008, X )(X64Emitter& e, X86Compiler& c, InstrData& i) { + // a <- EXTS((RA)[32:63]) + // b <- EXTS((RB)[32:63]) + // if (a < b) & TO[0] then TRAP + // if (a > b) & TO[1] then TRAP + // if (a = b) & TO[2] then TRAP + // if (a u b) & TO[4] then TRAP + GpVar va = e.sign_extend(e.trunc(e.gpr_value(i.X.RA), 4), 8); + GpVar vb = e.sign_extend(e.trunc(e.gpr_value(i.X.RA), 4), 8); + return XeEmitTrap(e, c, i, va, vb, i.X.RT); +} -// XEEMITTER(twi, 0x0C000000, D )(X64Emitter& e, X86Compiler& c, InstrData& i) { -// // a <- EXTS((RA)[32:63]) -// // if (a < EXTS(SI)) & TO[0] then TRAP -// // if (a > EXTS(SI)) & TO[1] then TRAP -// // if (a = EXTS(SI)) & TO[2] then TRAP -// // if (a u EXTS(SI)) & TO[4] then TRAP -// return XeEmitTrap(e, f, i, -// e.sign_extend(e.trunc_to_int(e.gpr_value(i.D.RA)), -// jit_type_nint), -// e.get_int64(XEEXTS16(i.D.DS)), -// i.D.RT); -// } +XEEMITTER(twi, 0x0C000000, D )(X64Emitter& e, X86Compiler& c, InstrData& i) { + // a <- EXTS((RA)[32:63]) + // if (a < EXTS(SI)) & TO[0] then TRAP + // if (a > EXTS(SI)) & TO[1] then TRAP + // if (a = EXTS(SI)) & TO[2] then TRAP + // if (a u EXTS(SI)) & TO[4] then TRAP + GpVar va = e.sign_extend(e.trunc(e.gpr_value(i.D.RA), 4), 8); + GpVar vb(c.newGpVar()); + c.mov(vb, imm(XEEXTS16(i.D.DS))); + return XeEmitTrap(e, c, i, va, vb, i.D.RT); +} // Processor control (A-26) @@ -667,23 +663,23 @@ XEEMITTER(mtspr, 0x7C0003A6, XFX)(X64Emitter& e, X86Compiler& c, InstrDat void X64RegisterEmitCategoryControl() { XEREGISTERINSTR(bx, 0x48000000); - // XEREGISTERINSTR(bcx, 0x40000000); - // XEREGISTERINSTR(bcctrx, 0x4C000420); - // XEREGISTERINSTR(bclrx, 0x4C000020); - // XEREGISTERINSTR(crand, 0x4C000202); - // XEREGISTERINSTR(crandc, 0x4C000102); - // XEREGISTERINSTR(creqv, 0x4C000242); - // XEREGISTERINSTR(crnand, 0x4C0001C2); - // XEREGISTERINSTR(crnor, 0x4C000042); - // XEREGISTERINSTR(cror, 0x4C000382); - // XEREGISTERINSTR(crorc, 0x4C000342); - // XEREGISTERINSTR(crxor, 0x4C000182); - // XEREGISTERINSTR(mcrf, 0x4C000000); - // XEREGISTERINSTR(sc, 0x44000002); - // XEREGISTERINSTR(td, 0x7C000088); - // XEREGISTERINSTR(tdi, 0x08000000); - // XEREGISTERINSTR(tw, 0x7C000008); - // XEREGISTERINSTR(twi, 0x0C000000); + XEREGISTERINSTR(bcx, 0x40000000); + XEREGISTERINSTR(bcctrx, 0x4C000420); + XEREGISTERINSTR(bclrx, 0x4C000020); + XEREGISTERINSTR(crand, 0x4C000202); + XEREGISTERINSTR(crandc, 0x4C000102); + XEREGISTERINSTR(creqv, 0x4C000242); + XEREGISTERINSTR(crnand, 0x4C0001C2); + XEREGISTERINSTR(crnor, 0x4C000042); + XEREGISTERINSTR(cror, 0x4C000382); + XEREGISTERINSTR(crorc, 0x4C000342); + XEREGISTERINSTR(crxor, 0x4C000182); + XEREGISTERINSTR(mcrf, 0x4C000000); + XEREGISTERINSTR(sc, 0x44000002); + XEREGISTERINSTR(td, 0x7C000088); + XEREGISTERINSTR(tdi, 0x08000000); + XEREGISTERINSTR(tw, 0x7C000008); + XEREGISTERINSTR(twi, 0x0C000000); XEREGISTERINSTR(mfcr, 0x7C000026); XEREGISTERINSTR(mfspr, 0x7C0002A6); XEREGISTERINSTR(mftb, 0x7C0002E6); diff --git a/src/xenia/cpu/x64/x64_emitter.cc b/src/xenia/cpu/x64/x64_emitter.cc index 01ce33836..0d45773c5 100644 --- a/src/xenia/cpu/x64/x64_emitter.cc +++ b/src/xenia/cpu/x64/x64_emitter.cc @@ -1471,7 +1471,6 @@ void X64Emitter::update_fpr_value(uint32_t n, GpVar& value) { // return jit_value_create_nint_constant(fn_, jit_type_nuint, value); // } -#if 0 GpVar X64Emitter::sign_extend(GpVar& value, int size) { X86Compiler& c = compiler_; @@ -1489,25 +1488,27 @@ GpVar X64Emitter::sign_extend(GpVar& value, int size) { GpVar tmp; switch (size) { case 1: - tmp = c.newGpVar(kX86VarTypeGpd); - return value.r8(); + XEASSERTALWAYS(); + return value; case 2: - tmp = c.newGpVar(kX86VarTypeGpd); - return value.r16(); + XEASSERTALWAYS(); + return value; case 4: - tmp = c.newGpVar(kX86VarTypeGpd); - return value.r32(); + XEASSERTALWAYS(); + return value; default: case 8: tmp = c.newGpVar(kX86VarTypeGpq); c.mov(tmp, value); - if (value.getSize() == 4) { - c.cdqe(value); + switch (value.getSize()) { + case 1: c.cbw(value); // b->w->d->q + case 2: c.cwde(value); // w->d->q + case 4: c.cdqe(value); // d->q + break; } - return value.r64(); + return value; } } -#endif GpVar X64Emitter::zero_extend(GpVar& value, int size) { X86Compiler& c = compiler_;