mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-06 20:32:19 +00:00
Replace r101053 with a fix for getSOImmValRotate() so that it will correctly
recognize all the valid rotated immediates. This fixes the disassembler issue and will also help codegen for some unusual constant values. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@101114 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a590b79ee2
commit
b123b8bee0
@ -151,22 +151,13 @@ namespace ARM_AM {
|
||||
if ((rotr32(Imm, RotAmt) & ~255U) == 0)
|
||||
return (32-RotAmt)&31; // HW rotates right, not left.
|
||||
|
||||
// For values like 0xF000000F, we should skip the first run of ones, then
|
||||
// For values like 0xF000000F, we should ignore the low 7 bits, then
|
||||
// retry the hunt.
|
||||
if (Imm & 1) {
|
||||
unsigned TrailingOnes = CountTrailingZeros_32(~Imm);
|
||||
if (TrailingOnes != 32) { // Avoid overflow on 0xFFFFFFFF
|
||||
// Restart the search for a high-order bit after the initial seconds of
|
||||
// ones.
|
||||
unsigned TZ2 = CountTrailingZeros_32(Imm & ~((1 << TrailingOnes)-1));
|
||||
|
||||
// Rotate amount must be even.
|
||||
unsigned RotAmt2 = TZ2 & ~1;
|
||||
|
||||
// If this fits, use it.
|
||||
if (RotAmt2 != 32 && (rotr32(Imm, RotAmt2) & ~255U) == 0)
|
||||
return (32-RotAmt2)&31; // HW rotates right, not left.
|
||||
}
|
||||
if (Imm & 127U) {
|
||||
unsigned TZ2 = CountTrailingZeros_32(Imm & ~127U);
|
||||
unsigned RotAmt2 = TZ2 & ~1;
|
||||
if ((rotr32(Imm, RotAmt2) & ~255U) == 0)
|
||||
return (32-RotAmt2)&31; // HW rotates right, not left.
|
||||
}
|
||||
|
||||
// Otherwise, we have no way to cover this span of bits with a single
|
||||
@ -193,43 +184,6 @@ namespace ARM_AM {
|
||||
return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8);
|
||||
}
|
||||
|
||||
/// getSOImmValOneRotate - Try to handle Imm with an immediate shifter
|
||||
/// operand, computing the rotate amount to use. If this immediate value
|
||||
/// cannot be handled with a single shifter-op, return 0.
|
||||
static unsigned getSOImmValOneRotate(unsigned Imm) {
|
||||
// A5.2.4 Constants with multiple encodings
|
||||
// The lowest unsigned value of rotation wins!
|
||||
for (unsigned R = 1; R <= 15; ++R)
|
||||
if ((Imm & rotr32(~255U, 2*R)) == 0)
|
||||
return 2*R;
|
||||
|
||||
// Failed to find a suitable rotate amount.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getSOImmValOneOrNoRotate - Given a 32-bit immediate, if it is something
|
||||
/// that can fit into a shifter_operand immediate operand, return the 12-bit
|
||||
/// encoding for it. If not, return -1. This is different from getSOImmVal()
|
||||
/// in that getSOImmVal() is used during codegen, for example,
|
||||
/// rewriteARMFrameIndex() where return value of -1 is not considered fatal.
|
||||
///
|
||||
/// The current consumer of this API is printSOImm() within ARMInstPrinter.cpp
|
||||
/// where return value of -1 indicates that the Arg is not a valid so_imm val!
|
||||
static inline int getSOImmValOneOrNoRotate(unsigned Arg) {
|
||||
// 8-bit (or less) immediates are trivially shifter_operands with a rotate
|
||||
// of zero.
|
||||
if ((Arg & ~255U) == 0) return Arg;
|
||||
|
||||
unsigned RotAmt = getSOImmValOneRotate(Arg);
|
||||
|
||||
// If this cannot be handled with a single shifter_op, bail out.
|
||||
if (rotr32(~255U, RotAmt) & Arg)
|
||||
return -1;
|
||||
|
||||
// Encode this correctly.
|
||||
return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8);
|
||||
}
|
||||
|
||||
/// isSOImmTwoPartVal - Return true if the specified value can be obtained by
|
||||
/// or'ing together two SOImmVal's.
|
||||
static inline bool isSOImmTwoPartVal(unsigned V) {
|
||||
|
@ -225,7 +225,7 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm,
|
||||
const MCAsmInfo *MAI) {
|
||||
// Break it up into two parts that make up a shifter immediate.
|
||||
V = ARM_AM::getSOImmValOneOrNoRotate(V);
|
||||
V = ARM_AM::getSOImmVal(V);
|
||||
assert(V != -1 && "Not a valid so_imm value!");
|
||||
|
||||
unsigned Imm = ARM_AM::getSOImmValImm(V);
|
||||
|
Loading…
Reference in New Issue
Block a user