summaryrefslogtreecommitdiffstats
path: root/disassembler/disassembler_arm.cc
diff options
context:
space:
mode:
authorVladimir Marko <vmarko@google.com>2013-11-21 15:01:20 +0000
committerVladimir Marko <vmarko@google.com>2013-11-26 17:50:59 +0000
commit3e5af82ae1a2cd69b7b045ac008ac3b394d17f41 (patch)
treede4cb3a63320db48bc942de670552167e1d7bea3 /disassembler/disassembler_arm.cc
parent5da3778746375b73e7e77c5f1371f29684674776 (diff)
downloadart-3e5af82ae1a2cd69b7b045ac008ac3b394d17f41.zip
art-3e5af82ae1a2cd69b7b045ac008ac3b394d17f41.tar.gz
art-3e5af82ae1a2cd69b7b045ac008ac3b394d17f41.tar.bz2
Intrinsic Unsafe.CompareAndSwapLong() for ARM.
(cherry picked from cb53fcd79b1a5ce608208ec454b5c19f64aaba37) Change-Id: Iadd3cc8b4ed390670463b80f8efd579ce6ece226
Diffstat (limited to 'disassembler/disassembler_arm.cc')
-rw-r--r--disassembler/disassembler_arm.cc47
1 files changed, 32 insertions, 15 deletions
diff --git a/disassembler/disassembler_arm.cc b/disassembler/disassembler_arm.cc
index 936fb07..90d84d5 100644
--- a/disassembler/disassembler_arm.cc
+++ b/disassembler/disassembler_arm.cc
@@ -440,18 +440,34 @@ size_t DisassemblerArm::DumpThumb32(std::ostream& os, const uint8_t* instr_ptr)
if (op3 == 0) { // op3 is 00, op4 is 00
opcode << "strex";
args << Rd << ", " << Rt << ", [" << Rn << ", #" << (imm8 << 2) << "]";
+ if (Rd.r == 13 || Rd.r == 15 || Rt.r == 13 || Rt.r == 15 || Rn.r == 15 ||
+ Rd.r == Rn.r || Rd.r == Rt.r) {
+ args << " (UNPREDICTABLE)";
+ }
} else { // op3 is 01, op4 is 00
// this is one of strexb, strexh or strexd
int op5 = (instr >> 4) & 0xf;
switch (op5) {
case 4:
- opcode << "strexb";
- break;
case 5:
- opcode << "strexh";
+ opcode << ((op5 == 4) ? "strexb" : "strexh");
+ Rd = ArmRegister(instr, 0);
+ args << Rd << ", " << Rt << ", [" << Rn << "]";
+ if (Rd.r == 13 || Rd.r == 15 || Rt.r == 13 || Rt.r == 15 || Rn.r == 15 ||
+ Rd.r == Rn.r || Rd.r == Rt.r || (instr & 0xf00) != 0xf00) {
+ args << " (UNPREDICTABLE)";
+ }
break;
case 7:
opcode << "strexd";
+ ArmRegister Rt2 = Rd;
+ Rd = ArmRegister(instr, 0);
+ args << Rd << ", " << Rt << ", " << Rt2 << ", [" << Rn << "]";
+ if (Rd.r == 13 || Rd.r == 15 || Rt.r == 13 || Rt.r == 15 ||
+ Rt2.r == 13 || Rt2.r == 15 || Rn.r == 15 ||
+ Rd.r == Rn.r || Rd.r == Rt.r || Rd.r == Rt2.r) {
+ args << " (UNPREDICTABLE)";
+ }
break;
}
}
@@ -460,6 +476,9 @@ size_t DisassemblerArm::DumpThumb32(std::ostream& os, const uint8_t* instr_ptr)
if (op3 == 0) { // op3 is 00, op4 is 01
opcode << "ldrex";
args << Rt << ", [" << Rn << ", #" << (imm8 << 2) << "]";
+ if (Rt.r == 13 || Rt.r == 15 || Rn.r == 15 || (instr & 0xf00) != 0xf00) {
+ args << " (UNPREDICTABLE)";
+ }
} else { // op3 is 01, op4 is 01
// this is one of strexb, strexh or strexd
int op5 = (instr >> 4) & 0xf;
@@ -471,13 +490,20 @@ size_t DisassemblerArm::DumpThumb32(std::ostream& os, const uint8_t* instr_ptr)
opcode << "tbh";
break;
case 4:
- opcode << "ldrexb";
- break;
case 5:
- opcode << "ldrexh";
+ opcode << ((op5 == 4) ? "ldrexb" : "ldrexh");
+ args << Rt << ", [" << Rn << "]";
+ if (Rt.r == 13 || Rt.r == 15 || Rn.r == 15 || (instr & 0xf0f) != 0xf0f) {
+ args << " (UNPREDICTABLE)";
+ }
break;
case 7:
opcode << "ldrexd";
+ args << Rt << ", " << Rd /* Rt2 */ << ", [" << Rn << "]";
+ if (Rt.r == 13 || Rt.r == 15 || Rd.r == 13 /* Rt2 */ || Rd.r == 15 /* Rt2 */ ||
+ Rn.r == 15 || (instr & 0x00f) != 0x00f) {
+ args << " (UNPREDICTABLE)";
+ }
break;
}
}
@@ -507,15 +533,6 @@ size_t DisassemblerArm::DumpThumb32(std::ostream& os, const uint8_t* instr_ptr)
}
}
-
- if (op3 == 0 && op4 == 0) { // STREX
- ArmRegister Rd(instr, 8);
- opcode << "strex";
- args << Rd << ", " << Rt << ", [" << Rn << ", #" << (imm8 << 2) << "]";
- } else if (op3 == 0 && op4 == 1) { // LDREX
- opcode << "ldrex";
- args << Rt << ", [" << Rn << ", #" << (imm8 << 2) << "]";
- }
} else if ((op2 & 0x60) == 0x20) { // 01x xxxx
// Data-processing (shifted register)
// |111|1110|0000|0|0000|1111|1100|00|00|0000|