From 53f8b03acc022e724b3a5797a1249aedcfeb2009 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 12 Feb 2018 19:35:04 +0300 Subject: [PATCH] CPUTranslator: implement ICmp ops Added operators ==, !=, >, <, >=, <= --- rpcs3/Emu/CPU/CPUTranslator.h | 112 ++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/rpcs3/Emu/CPU/CPUTranslator.h b/rpcs3/Emu/CPU/CPUTranslator.h index 64e348bbf5..828197fb46 100644 --- a/rpcs3/Emu/CPU/CPUTranslator.h +++ b/rpcs3/Emu/CPU/CPUTranslator.h @@ -32,6 +32,7 @@ struct llvm_value_t static_assert(std::is_same::value, "llvm_value_t<> error: unknown type"); using type = void; + using base = llvm_value_t; static constexpr uint esize = 0; static constexpr bool is_int = false; static constexpr bool is_sint = false; @@ -669,6 +670,117 @@ inline llvm_not_t operator ~(T1 a1) return {a1}; } +template +struct llvm_icmp_t +{ + using type = std::conditional_t::is_vector, bool[llvm_value_t::is_vector], bool>; + + A1 a1; + A2 a2; + + static_assert(llvm_value_t::is_int, "llvm_eq_t<>: invalid type"); + + // Convert unsigned comparison predicate to signed if necessary + static constexpr llvm::CmpInst::Predicate pred = llvm_value_t::is_uint ? UPred : + UPred == llvm::ICmpInst::ICMP_UGT ? llvm::ICmpInst::ICMP_SGT : + UPred == llvm::ICmpInst::ICMP_UGE ? llvm::ICmpInst::ICMP_SGE : + UPred == llvm::ICmpInst::ICMP_ULT ? llvm::ICmpInst::ICMP_SLT : + UPred == llvm::ICmpInst::ICMP_ULE ? llvm::ICmpInst::ICMP_SLE : UPred; + + static inline llvm::Value* icmp(llvm::IRBuilder<>* ir, llvm::Value* lhs, llvm::Value* rhs) + { + return ir->CreateICmp(pred, lhs, rhs); + } + + static inline llvm::Value* icmp(llvm::IRBuilder<>* ir, llvm::Value* lhs, u64 value) + { + return ir->CreateICmp(pred, lhs, llvm::ConstantInt::get(llvm_value_t::get_type(ir->getContext()), value, llvm_value_t::is_sint)); + } + + llvm::Value* eval(llvm::IRBuilder<>* ir) const + { + const auto v1 = a1.eval(ir); + const auto v2 = a2.eval(ir); + + if (llvm_value_t::is_int) + { + return icmp(ir, v1, v2); + } + } +}; + +template ().eval(0)), typename = std::enable_if_t::value>> +inline llvm_icmp_t operator ==(T1 a1, T2 a2) +{ + return {a1, a2}; +} + +template ().eval(0)), typename = std::enable_if_t::is_int>> +inline llvm_icmp_t operator ==(T1 a1, u64 a2) +{ + return {a1, llvm_int_t{a2}}; +} + +template ().eval(0)), typename = std::enable_if_t::value>> +inline llvm_icmp_t operator !=(T1 a1, T2 a2) +{ + return {a1, a2}; +} + +template ().eval(0)), typename = std::enable_if_t::is_int>> +inline llvm_icmp_t operator !=(T1 a1, u64 a2) +{ + return {a1, llvm_int_t{a2}}; +} + +template ().eval(0)), typename = std::enable_if_t::value>> +inline llvm_icmp_t operator >(T1 a1, T2 a2) +{ + return {a1, a2}; +} + +template ().eval(0)), typename = std::enable_if_t::is_int>> +inline llvm_icmp_t operator >(T1 a1, u64 a2) +{ + return {a1, llvm_int_t{a2}}; +} + +template ().eval(0)), typename = std::enable_if_t::value>> +inline llvm_icmp_t operator >=(T1 a1, T2 a2) +{ + return {a1, a2}; +} + +template ().eval(0)), typename = std::enable_if_t::is_int>> +inline llvm_icmp_t operator >=(T1 a1, u64 a2) +{ + return {a1, llvm_int_t{a2}}; +} + +template ().eval(0)), typename = std::enable_if_t::value>> +inline llvm_icmp_t operator <(T1 a1, T2 a2) +{ + return {a1, a2}; +} + +template ().eval(0)), typename = std::enable_if_t::is_int>> +inline llvm_icmp_t operator <(T1 a1, u64 a2) +{ + return {a1, llvm_int_t{a2}}; +} + +template ().eval(0)), typename = std::enable_if_t::value>> +inline llvm_icmp_t operator <=(T1 a1, T2 a2) +{ + return {a1, a2}; +} + +template ().eval(0)), typename = std::enable_if_t::is_int>> +inline llvm_icmp_t operator <=(T1 a1, u64 a2) +{ + return {a1, llvm_int_t{a2}}; +} + class cpu_translator { protected: