mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
[ARM] Rewrite .save/.vsave emission with bit math
Hopefully makes it a bit easier to understand what's going on. No functional change intended. llvm-svn: 233191
This commit is contained in:
parent
05bbd7484f
commit
6c5bd093e6
@ -72,14 +72,10 @@ void UnwindOpcodeAssembler::EmitRegSave(uint32_t RegSave) {
|
|||||||
// opcode when r4 is not in .save directive.
|
// opcode when r4 is not in .save directive.
|
||||||
|
|
||||||
// Compute the consecutive registers from r4 to r11.
|
// Compute the consecutive registers from r4 to r11.
|
||||||
uint32_t Range = 0;
|
uint32_t Mask = RegSave & 0xff0u;
|
||||||
uint32_t Mask = (1u << 4);
|
uint32_t Range = countTrailingOnes(Mask >> 5); // Exclude r4.
|
||||||
for (uint32_t Bit = (1u << 5); Bit < (1u << 12); Bit <<= 1) {
|
// Mask off non-consecutive registers. Keep r4.
|
||||||
if ((RegSave & Bit) == 0u)
|
Mask &= ~(0xffffffe0u << Range);
|
||||||
break;
|
|
||||||
++Range;
|
|
||||||
Mask |= Bit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit this opcode when the mask covers every registers.
|
// Emit this opcode when the mask covers every registers.
|
||||||
uint32_t UnmaskedReg = RegSave & 0xfff0u & (~Mask);
|
uint32_t UnmaskedReg = RegSave & 0xfff0u & (~Mask);
|
||||||
@ -105,50 +101,24 @@ void UnwindOpcodeAssembler::EmitRegSave(uint32_t RegSave) {
|
|||||||
|
|
||||||
/// Emit unwind opcodes for .vsave directives
|
/// Emit unwind opcodes for .vsave directives
|
||||||
void UnwindOpcodeAssembler::EmitVFPRegSave(uint32_t VFPRegSave) {
|
void UnwindOpcodeAssembler::EmitVFPRegSave(uint32_t VFPRegSave) {
|
||||||
size_t i = 32;
|
// We only have 4 bits to save the offset in the opcode so look at the lower
|
||||||
|
// and upper 16 bits separately.
|
||||||
|
for (uint32_t Regs : {VFPRegSave & 0xffff0000u, VFPRegSave & 0x0000ffffu}) {
|
||||||
|
while (Regs) {
|
||||||
|
// Now look for a run of set bits. Remember the MSB and LSB of the run.
|
||||||
|
auto RangeMSB = 32 - countLeadingZeros(Regs);
|
||||||
|
auto RangeLen = countLeadingOnes(Regs << (32 - RangeMSB));
|
||||||
|
auto RangeLSB = RangeMSB - RangeLen;
|
||||||
|
|
||||||
while (i > 16) {
|
int Opcode = RangeLSB >= 16
|
||||||
uint32_t Bit = 1u << (i - 1);
|
? ARM::EHABI::UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD_D16
|
||||||
if ((VFPRegSave & Bit) == 0u) {
|
: ARM::EHABI::UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD;
|
||||||
--i;
|
|
||||||
continue;
|
EmitInt16(Opcode | ((RangeLSB % 16) << 4) | (RangeLen - 1));
|
||||||
|
|
||||||
|
// Zero out bits we're done with.
|
||||||
|
Regs &= ~(-1u << RangeLSB);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Range = 0;
|
|
||||||
|
|
||||||
--i;
|
|
||||||
Bit >>= 1;
|
|
||||||
|
|
||||||
while (i > 16 && (VFPRegSave & Bit)) {
|
|
||||||
--i;
|
|
||||||
++Range;
|
|
||||||
Bit >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
EmitInt16(ARM::EHABI::UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD_D16 |
|
|
||||||
((i - 16) << 4) | Range);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (i > 0) {
|
|
||||||
uint32_t Bit = 1u << (i - 1);
|
|
||||||
if ((VFPRegSave & Bit) == 0u) {
|
|
||||||
--i;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t Range = 0;
|
|
||||||
|
|
||||||
--i;
|
|
||||||
Bit >>= 1;
|
|
||||||
|
|
||||||
while (i > 0 && (VFPRegSave & Bit)) {
|
|
||||||
--i;
|
|
||||||
++Range;
|
|
||||||
Bit >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
EmitInt16(ARM::EHABI::UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD | (i << 4) |
|
|
||||||
Range);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user