From afc3d30f5ce270d64cdc4c7a9151b9fb1590b818 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Mon, 29 Jun 2015 19:00:22 -0500 Subject: [PATCH] [AArch64] Implement BFI & UBFIZ in the emitter. Also fixes a bug in the UBFX instruction emitter. Naughty Naughty PPSSPP, not testing emitter functions you add. --- Source/Core/Common/Arm64Emitter.cpp | 15 +++++++++++++++ Source/Core/Common/Arm64Emitter.h | 4 +++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Source/Core/Common/Arm64Emitter.cpp b/Source/Core/Common/Arm64Emitter.cpp index 600b424d51..c31583e5fc 100644 --- a/Source/Core/Common/Arm64Emitter.cpp +++ b/Source/Core/Common/Arm64Emitter.cpp @@ -1523,6 +1523,21 @@ void ARM64XEmitter::UBFM(ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms) { EncodeBitfieldMOVInst(2, Rd, Rn, immr, imms); } + +void ARM64XEmitter::BFI(ARM64Reg Rd, ARM64Reg Rn, u32 lsb, u32 width) +{ + u32 size = Is64Bit(Rn) ? 64 : 32; + _assert_msg_(DYNA_REC, (lsb + width) <= size, "%s passed lsb %d and width %d which is greater than the register size!", + __FUNCTION__, lsb, width); + EncodeBitfieldMOVInst(1, Rd, Rn, (size - lsb) % size, width - 1); +} +void ARM64XEmitter::UBFIZ(ARM64Reg Rd, ARM64Reg Rn, u32 lsb, u32 width) +{ + u32 size = Is64Bit(Rn) ? 64 : 32; + _assert_msg_(DYNA_REC, (lsb + width) <= size, "%s passed lsb %d and width %d which is greater than the register size!", + __FUNCTION__, lsb, width); + EncodeBitfieldMOVInst(2, Rd, Rn, (size - lsb) % size, width - 1); +} void ARM64XEmitter::EXTR(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u32 shift) { bool sf = Is64Bit(Rd); diff --git a/Source/Core/Common/Arm64Emitter.h b/Source/Core/Common/Arm64Emitter.h index d4d95ba78d..6db19dc890 100644 --- a/Source/Core/Common/Arm64Emitter.h +++ b/Source/Core/Common/Arm64Emitter.h @@ -578,6 +578,8 @@ public: void BFM(ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms); void SBFM(ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms); void UBFM(ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms); + void BFI(ARM64Reg Rd, ARM64Reg Rn, u32 lsb, u32 width); + void UBFIZ(ARM64Reg Rd, ARM64Reg Rn, u32 lsb, u32 width); // Extract register (ROR with two inputs, if same then faster on A67) void EXTR(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u32 shift); @@ -591,7 +593,7 @@ public: void UBFX(ARM64Reg Rd, ARM64Reg Rn, int lsb, int width) { - UBFM(Rd, Rn, lsb, lsb + width <= (Is64Bit(Rn) ? 64 : 32)); + UBFM(Rd, Rn, lsb, lsb + width - 1); } // Load Register (Literal)