ARM: Fix STREX/LDREX reecoding
authorAmaury de la Vieuville <amaury.dlv@gmail.com>
Tue, 11 Jun 2013 08:03:20 +0000 (08:03 +0000)
committerAmaury de la Vieuville <amaury.dlv@gmail.com>
Tue, 11 Jun 2013 08:03:20 +0000 (08:03 +0000)
The decoded MCInst wasn't reencoded as the same instruction

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@183729 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/Disassembler/ARMDisassembler.cpp
test/MC/Disassembler/ARM/arm-LDREXD-reencoding.txt [new file with mode: 0644]
test/MC/Disassembler/ARM/arm-STREXD-reencoding.txt [new file with mode: 0644]

index 4d25e15fcc97e728ec08514d46b23971bffd49fc..b1a12306f5370ac7481ce2ba719660fefea094ca 100644 (file)
@@ -165,6 +165,8 @@ static DecodeStatus DecodetcGPRRegisterClass(MCInst &Inst, unsigned RegNo,
                                    uint64_t Address, const void *Decoder);
 static DecodeStatus DecoderGPRRegisterClass(MCInst &Inst, unsigned RegNo,
                                    uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeGPRPairRegisterClass(MCInst &Inst, unsigned RegNo,
+                                   uint64_t Address, const void *Decoder);
 static DecodeStatus DecodeSPRRegisterClass(MCInst &Inst, unsigned RegNo,
                                    uint64_t Address, const void *Decoder);
 static DecodeStatus DecodeDPRRegisterClass(MCInst &Inst, unsigned RegNo,
@@ -854,6 +856,26 @@ static DecodeStatus DecodetGPRRegisterClass(MCInst &Inst, unsigned RegNo,
   return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
 }
 
+static const uint16_t GPRPairDecoderTable[] = {
+  ARM::R0_R1, ARM::R2_R3,   ARM::R4_R5,  ARM::R6_R7,
+  ARM::R8_R9, ARM::R10_R11, ARM::R12_SP
+};
+
+static DecodeStatus DecodeGPRPairRegisterClass(MCInst &Inst, unsigned RegNo,
+                                   uint64_t Address, const void *Decoder) {
+  DecodeStatus S = MCDisassembler::Success;
+
+  if (RegNo > 13)
+    return MCDisassembler::Fail;
+
+  if ((RegNo & 1) || RegNo == 0xe)
+     S = MCDisassembler::SoftFail;
+
+  unsigned RegisterPair = GPRPairDecoderTable[RegNo/2];
+  Inst.addOperand(MCOperand::CreateReg(RegisterPair));
+  return S;
+}
+
 static DecodeStatus DecodetcGPRRegisterClass(MCInst &Inst, unsigned RegNo,
                                    uint64_t Address, const void *Decoder) {
   unsigned Register = 0;
@@ -3579,11 +3601,10 @@ static DecodeStatus DecodeDoubleRegLoad(MCInst &Inst, unsigned Insn,
   unsigned Rn = fieldFromInstruction(Insn, 16, 4);
   unsigned pred = fieldFromInstruction(Insn, 28, 4);
 
-  if ((Rt & 1) || Rt == 0xE || Rn == 0xF) return MCDisassembler::Fail;
+  if (Rn == 0xF)
+    S = MCDisassembler::SoftFail;
 
-  if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
-    return MCDisassembler::Fail;
-  if (!Check(S, DecodeGPRRegisterClass(Inst, Rt+1, Address, Decoder)))
+  if (!Check(S, DecodeGPRPairRegisterClass(Inst, Rt, Address, Decoder)))
     return MCDisassembler::Fail;
   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
     return MCDisassembler::Fail;
@@ -3593,7 +3614,6 @@ static DecodeStatus DecodeDoubleRegLoad(MCInst &Inst, unsigned Insn,
   return S;
 }
 
-
 static DecodeStatus DecodeDoubleRegStore(MCInst &Inst, unsigned Insn,
                                          uint64_t Address, const void *Decoder){
   DecodeStatus S = MCDisassembler::Success;
@@ -3606,12 +3626,10 @@ static DecodeStatus DecodeDoubleRegStore(MCInst &Inst, unsigned Insn,
   if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rd, Address, Decoder)))
     return MCDisassembler::Fail;
 
-  if ((Rt & 1) || Rt == 0xE || Rn == 0xF) return MCDisassembler::Fail;
-  if (Rd == Rn || Rd == Rt || Rd == Rt+1) return MCDisassembler::Fail;
+  if (Rn == 0xF || Rd == Rn || Rd == Rt || Rd == Rt+1)
+    S = MCDisassembler::SoftFail;
 
-  if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
-    return MCDisassembler::Fail;
-  if (!Check(S, DecodeGPRRegisterClass(Inst, Rt+1, Address, Decoder)))
+  if (!Check(S, DecodeGPRPairRegisterClass(Inst, Rt, Address, Decoder)))
     return MCDisassembler::Fail;
   if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
     return MCDisassembler::Fail;
diff --git a/test/MC/Disassembler/ARM/arm-LDREXD-reencoding.txt b/test/MC/Disassembler/ARM/arm-LDREXD-reencoding.txt
new file mode 100644 (file)
index 0000000..e73d4ce
--- /dev/null
@@ -0,0 +1,14 @@
+# RUN: llvm-mc -triple armv7 -show-encoding -disassemble < %s | FileCheck %s
+
+0x9f 0x0f 0xb0 0xe1
+0x9f 0xcf 0xb1 0xe1
+0x9f 0xcf 0xb3 0xe1
+0x9f 0x8f 0xbd 0xe1
+0x9f 0xcf 0xbe 0xe1
+
+# CHECK: ldrexd        r0, r1, [r0]            @ encoding: [0x9f,0x0f,0xb0,0xe1]
+# CHECK: ldrexd        r12, sp, [r1]           @ encoding: [0x9f,0xcf,0xb1,0xe1]
+# CHECK: ldrexd        r12, sp, [r3]           @ encoding: [0x9f,0xcf,0xb3,0xe1]
+# CHECK: ldrexd        r8, r9, [sp]            @ encoding: [0x9f,0x8f,0xbd,0xe1]
+# CHECK: ldrexd        r12, sp, [lr]           @ encoding: [0x9f,0xcf,0xbe,0xe1]
+
diff --git a/test/MC/Disassembler/ARM/arm-STREXD-reencoding.txt b/test/MC/Disassembler/ARM/arm-STREXD-reencoding.txt
new file mode 100644 (file)
index 0000000..27944ac
--- /dev/null
@@ -0,0 +1,14 @@
+# RUN: llvm-mc -triple armv7 -show-encoding -disassemble < %s | FileCheck %s
+
+0x92 0x1f 0xa0 0xe1
+0x90 0x4f 0xa3 0xe1
+0x92 0xdf 0xa4 0xe1
+0x90 0xaf 0xa6 0xe1
+0x9c 0x5f 0xa8 0xe1
+
+# CHECK: strexd        r1, r2, r3, [r0]        @ encoding: [0x92,0x1f,0xa0,0xe1]
+# CHECK: strexd        r4, r0, r1, [r3]        @ encoding: [0x90,0x4f,0xa3,0xe1]
+# CHECK: strexd        sp, r2, r3, [r4]        @ encoding: [0x92,0xdf,0xa4,0xe1]
+# CHECK: strexd        r10, r0, r1, [r6]       @ encoding: [0x90,0xaf,0xa6,0xe1]
+# CHECK: strexd        r5, r12, sp, [r8]       @ encoding: [0x9c,0x5f,0xa8,0xe1]
+