summaryrefslogtreecommitdiff
path: root/Source/Core/Common/Arm64Emitter.cpp
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2023-12-17 17:51:46 +0100
committerJosJuice <josjuice@gmail.com>2023-12-17 18:13:32 +0100
commitdc60bc5f1ef19fc92b2dd9c92655bf5f282106dd (patch)
tree35f9106e43ff260fb381574d794312a6afbc3da3 /Source/Core/Common/Arm64Emitter.cpp
parenta8e1e1ae48d0c03f60c3fc7cd13856b92590efc8 (diff)
JitArm64: Improve codegen in ANDI2R and friends
The codegen for the functions themselves, not for the emitted code. This seems to save 32 bytes per function. We also get rid of the oddity we had before where ANDI2R would do masking for 32-bit operations but the other functions wouldn't.
Diffstat (limited to 'Source/Core/Common/Arm64Emitter.cpp')
-rw-r--r--Source/Core/Common/Arm64Emitter.cpp67
1 files changed, 58 insertions, 9 deletions
diff --git a/Source/Core/Common/Arm64Emitter.cpp b/Source/Core/Common/Arm64Emitter.cpp
index 7d7b9fc16f..6f4f42c027 100644
--- a/Source/Core/Common/Arm64Emitter.cpp
+++ b/Source/Core/Common/Arm64Emitter.cpp
@@ -4039,9 +4039,19 @@ void ARM64FloatEmitter::ABI_PopRegisters(BitSet32 registers, ARM64Reg tmp)
void ARM64XEmitter::ANDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
{
if (!Is64Bit(Rn))
- imm &= 0xFFFFFFFF;
+ {
+ // To handle 32-bit logical immediates, the very easiest thing is to repeat
+ // the input value twice to make a 64-bit word. The correct encoding of that
+ // as a logical immediate will also be the correct encoding of the 32-bit
+ // value.
+ //
+ // Doing this here instead of in the LogicalImm constructor makes it easier
+ // to check if the input is all ones.
+
+ imm = (imm << 32) | (imm & 0xFFFFFFFF);
+ }
- if (imm != (Is64Bit(Rn) ? 0xFFFF'FFFF'FFFF'FFFF : 0xFFFF'FFFF))
+ if ((~imm) == 0)
{
// Do nothing
}
@@ -4049,7 +4059,7 @@ void ARM64XEmitter::ANDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
{
MOVZ(Rd, 0);
}
- else if (const auto result = LogicalImm(imm, Is64Bit(Rn) ? GPRSize::B64 : GPRSize::B32))
+ else if (const auto result = LogicalImm(imm, GPRSize::B64))
{
AND(Rd, Rn, result);
}
@@ -4065,15 +4075,28 @@ void ARM64XEmitter::ANDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
void ARM64XEmitter::ORRI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
{
+ if (!Is64Bit(Rn))
+ {
+ // To handle 32-bit logical immediates, the very easiest thing is to repeat
+ // the input value twice to make a 64-bit word. The correct encoding of that
+ // as a logical immediate will also be the correct encoding of the 32-bit
+ // value.
+ //
+ // Doing this here instead of in the LogicalImm constructor makes it easier
+ // to check if the input is all ones.
+
+ imm = (imm << 32) | (imm & 0xFFFFFFFF);
+ }
+
if (imm == 0)
{
// Do nothing
}
- else if (imm == (Is64Bit(Rn) ? 0xFFFF'FFFF'FFFF'FFFF : 0xFFFF'FFFF))
+ else if ((~imm) == 0)
{
MOVN(Rd, 0);
}
- else if (const auto result = LogicalImm(imm, Is64Bit(Rn) ? GPRSize::B64 : GPRSize::B32))
+ else if (const auto result = LogicalImm(imm, GPRSize::B64))
{
ORR(Rd, Rn, result);
}
@@ -4089,15 +4112,28 @@ void ARM64XEmitter::ORRI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
void ARM64XEmitter::EORI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
{
+ if (!Is64Bit(Rn))
+ {
+ // To handle 32-bit logical immediates, the very easiest thing is to repeat
+ // the input value twice to make a 64-bit word. The correct encoding of that
+ // as a logical immediate will also be the correct encoding of the 32-bit
+ // value.
+ //
+ // Doing this here instead of in the LogicalImm constructor makes it easier
+ // to check if the input is all ones.
+
+ imm = (imm << 32) | (imm & 0xFFFFFFFF);
+ }
+
if (imm == 0)
{
// Do nothing
}
- else if (imm == (Is64Bit(Rn) ? 0xFFFF'FFFF'FFFF'FFFF : 0xFFFF'FFFF))
+ else if ((~imm) == 0)
{
MVN(Rd, Rn);
}
- else if (const auto result = LogicalImm(imm, Is64Bit(Rn) ? GPRSize::B64 : GPRSize::B32))
+ else if (const auto result = LogicalImm(imm, GPRSize::B64))
{
EOR(Rd, Rn, result);
}
@@ -4113,16 +4149,29 @@ void ARM64XEmitter::EORI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
void ARM64XEmitter::ANDSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
{
+ if (!Is64Bit(Rn))
+ {
+ // To handle 32-bit logical immediates, the very easiest thing is to repeat
+ // the input value twice to make a 64-bit word. The correct encoding of that
+ // as a logical immediate will also be the correct encoding of the 32-bit
+ // value.
+ //
+ // Doing this here instead of in the LogicalImm constructor makes it easier
+ // to check if the input is all ones.
+
+ imm = (imm << 32) | (imm & 0xFFFFFFFF);
+ }
+
if (imm == 0)
{
ANDS(Rd, Is64Bit(Rn) ? ARM64Reg::ZR : ARM64Reg::WZR,
Is64Bit(Rn) ? ARM64Reg::ZR : ARM64Reg::WZR);
}
- else if (imm == (Is64Bit(Rn) ? 0xFFFF'FFFF'FFFF'FFFF : 0xFFFF'FFFF))
+ else if ((~imm) == 0)
{
ANDS(Rd, Rn, Rn);
}
- else if (const auto result = LogicalImm(imm, Is64Bit(Rn) ? GPRSize::B64 : GPRSize::B32))
+ else if (const auto result = LogicalImm(imm, GPRSize::B64))
{
ANDS(Rd, Rn, result);
}