A64: Implement EXTR

This commit is contained in:
Lioncash 2018-01-26 11:49:08 -05:00 committed by MerryMage
parent e1fd6038a2
commit 7734cf1050
6 changed files with 61 additions and 1 deletions

View file

@ -176,6 +176,26 @@ void EmitX64::EmitConditionalSelect64(EmitContext& ctx, IR::Inst* inst) {
EmitConditionalSelect(code, ctx, inst, 64);
}
static void EmitExtractRegister(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit_size) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Reg result = ctx.reg_alloc.UseScratchGpr(args[0]).changeBit(bit_size);
const Xbyak::Reg operand = ctx.reg_alloc.UseScratchGpr(args[1]).changeBit(bit_size);
const u8 lsb = args[2].GetImmediateU8();
code.shrd(result, operand, lsb);
ctx.reg_alloc.DefineValue(inst, result);
}
void EmitX64::EmitExtractRegister32(Dynarmic::BackendX64::EmitContext& ctx, IR::Inst* inst) {
EmitExtractRegister(*code, ctx, inst, 32);
}
void EmitX64::EmitExtractRegister64(Dynarmic::BackendX64::EmitContext& ctx, IR::Inst* inst) {
EmitExtractRegister(*code, ctx, inst, 64);
}
void EmitX64::EmitLogicalShiftLeft32(EmitContext& ctx, IR::Inst* inst) {
auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);

View file

@ -25,7 +25,7 @@ INST(BFM, "BFM", "z0110
INST(UBFM, "UBFM", "z10100110Nrrrrrrssssssnnnnnddddd")
// Data processing - Immediate - Extract
//INST(EXTR, "EXTR", "z00100111N0mmmmmssssssnnnnnddddd")
INST(EXTR, "EXTR", "z00100111N0mmmmmssssssnnnnnddddd")
// Conditional branch
INST(B_cond, "B.cond", "01010100iiiiiiiiiiiiiiiiiii0cccc")

View file

@ -76,4 +76,23 @@ bool TranslatorVisitor::UBFM(bool sf, bool N, Imm<6> immr, Imm<6> imms, Reg Rn,
return true;
}
bool TranslatorVisitor::EXTR(bool sf, bool N, Reg Rm, Imm<6> imms, Reg Rn, Reg Rd) {
if (N != sf) {
return UnallocatedEncoding();
}
if (!sf && imms.Bit<5>()) {
return ReservedValue();
}
const size_t datasize = sf ? 64 : 32;
const IR::U32U64 m = X(datasize, Rm);
const IR::U32U64 n = X(datasize, Rn);
const IR::U32U64 result = ir.ExtractRegister(m, n, ir.Imm8(imms.ZeroExtend<u8>()));
X(datasize, Rd, result);
return true;
}
} // namespace Dynarmic::A64

View file

@ -481,6 +481,22 @@ U32U64 IREmitter::CountLeadingZeros(const U32U64& a) {
return Inst<U64>(Opcode::CountLeadingZeros64, a);
}
U32 IREmitter::ExtractRegister(const U32& a, const U32& b, const U8& lsb) {
return Inst<U32>(Opcode::ExtractRegister32, a, b, lsb);
}
U64 IREmitter::ExtractRegister(const U64& a, const U64& b, const U8& lsb) {
return Inst<U64>(Opcode::ExtractRegister64, a, b, lsb);
}
U32U64 IREmitter::ExtractRegister(const U32U64& a, const U32U64& b, const U8& lsb) {
if (a.GetType() == IR::Type::U32) {
return Inst<U32>(Opcode::ExtractRegister32, a, b, lsb);
}
return Inst<U64>(Opcode::ExtractRegister64, a, b, lsb);
}
ResultAndOverflow<U32> IREmitter::SignedSaturatedAdd(const U32& a, const U32& b) {
auto result = Inst<U32>(Opcode::SignedSaturatedAdd, a, b);
auto overflow = Inst<U1>(Opcode::GetOverflowFromOp, result);

View file

@ -142,6 +142,9 @@ public:
U32 CountLeadingZeros(const U32& a);
U64 CountLeadingZeros(const U64& a);
U32U64 CountLeadingZeros(const U32U64& a);
U32 ExtractRegister(const U32& a, const U32& b, const U8& lsb);
U64 ExtractRegister(const U64& a, const U64& b, const U8& lsb);
U32U64 ExtractRegister(const U32U64& a, const U32U64& b, const U8& lsb);
ResultAndOverflow<U32> SignedSaturatedAdd(const U32& a, const U32& b);
ResultAndOverflow<U32> SignedSaturatedSub(const U32& a, const U32& b);

View file

@ -122,6 +122,8 @@ OPCODE(ByteReverseHalf, T::U16, T::U16
OPCODE(ByteReverseDual, T::U64, T::U64 )
OPCODE(CountLeadingZeros32, T::U32, T::U32 )
OPCODE(CountLeadingZeros64, T::U64, T::U64 )
OPCODE(ExtractRegister32, T::U32, T::U32, T::U32, T::U8 )
OPCODE(ExtractRegister64, T::U64, T::U64, T::U64, T::U8 )
// Saturated instructions
OPCODE(SignedSaturatedAdd, T::U32, T::U32, T::U32 )