Bug 1202757 - disassemble more instructions. r=sstangl
authorLars T Hansen <lhansen@mozilla.com>
Mon, 14 Sep 2015 11:37:42 +0200
changeset 294902 839bd50e595038bf5b445c88e256f520ee3ffe32
parent 294901 61ab9f5612e481f32b6bb579b4784fe4c82b98e6
child 294903 fa0a54cadfd0313e8b66334f7e31aa5ed661881f
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssstangl
bugs1202757
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1202757 - disassemble more instructions. r=sstangl
js/src/jit/arm/Simulator-arm.cpp
js/src/jit/arm/disasm/Constants-arm.h
js/src/jit/arm/disasm/Disasm-arm.cpp
--- a/js/src/jit/arm/Simulator-arm.cpp
+++ b/js/src/jit/arm/Simulator-arm.cpp
@@ -32,16 +32,17 @@
 #include "mozilla/DebugOnly.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/Likely.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/SizePrintfMacros.h"
 
 #include "asmjs/AsmJSValidate.h"
 #include "jit/arm/Assembler-arm.h"
+#include "jit/arm/disasm/Constants-arm.h"
 #include "vm/Runtime.h"
 
 extern "C" {
 
 int64_t
 __aeabi_idivmod(int x, int y)
 {
     uint32_t lo = uint32_t(x / y);
@@ -2511,69 +2512,67 @@ Simulator::decodeType01(SimInstruction* 
                         lo_res = static_cast<int32_t>(result & 0xffffffff);
                     }
                     set_register(rd_lo, lo_res);
                     set_register(rd_hi, hi_res);
                     if (instr->hasS())
                         MOZ_CRASH();
                 }
             } else {
-                if (instr->bit(23)) {
+                if (instr->bits(disasm::ExclusiveOpHi, disasm::ExclusiveOpLo) == disasm::ExclusiveOpcode) {
                     // Load-exclusive / store-exclusive.
                     //
                     // Bare-bones simulation: the store always succeeds, and we
                     // do not execute any fences.  Also, we allow readDW and
                     // writeDW to split the memory transaction.
                     //
                     // The next step up would involve remembering the value
                     // that was read with load-exclusive so that we could use
                     // compareExchange for the store-exclusive, and to
                     // implement atomic doubleword read and write.
                     //
                     // Also see DMB/DSB/ISB below.
-                    if (instr->bit(20)) {
-                        // Load-exclusive.
+                    if (instr->bit(disasm::ExclusiveLoad)) {
                         int rn = instr->rnValue();
                         int rt = instr->rtValue();
                         int32_t address = get_register(rn);
-                        switch (instr->bits(22,21)) {
-                          case 0:
+                        switch (instr->bits(disasm::ExclusiveSizeHi, disasm::ExclusiveSizeLo)) {
+                          case disasm::ExclusiveWord:
                             set_register(rt, readW(address, instr));
                             break;
-                          case 1:
+                          case disasm::ExclusiveDouble:
                             set_dw_register(rt, readDW(address));
                             break;
-                          case 2:
+                          case disasm::ExclusiveByte:
                             set_register(rt, readBU(address));
                             break;
-                          case 3:
+                          case disasm::ExclusiveHalf:
                             set_register(rt, readHU(address, instr));
                             break;
                         }
                     } else {
-                        // Store-exclusive.
                         int rn = instr->rnValue();
                         int rd = instr->rdValue();
                         int rt = instr->bits(3,0);
                         int32_t address = get_register(rn);
                         int32_t value = get_register(rt);
-                        switch (instr->bits(22,21)) {
-                          case 0:
+                        switch (instr->bits(disasm::ExclusiveSizeHi, disasm::ExclusiveSizeLo)) {
+                          case disasm::ExclusiveWord:
                             writeW(address, value, instr);
                             break;
-                          case 1: {
+                          case disasm::ExclusiveDouble: {
                               MOZ_ASSERT((rt % 2) == 0);
                               int32_t value2 = get_register(rt+1);
                               writeDW(address, value, value2);
                               break;
                           }
-                          case 2:
+                          case disasm::ExclusiveByte:
                             writeB(address, (uint8_t)value);
                             break;
-                          case 3:
+                          case disasm::ExclusiveHalf:
                             writeH(address, (uint16_t)value, instr);
                             break;
                         }
                         set_register(rd, 0);
                     }
                 } else {
                     MOZ_CRASH(); // Not used atm
                 }
--- a/js/src/jit/arm/disasm/Constants-arm.h
+++ b/js/src/jit/arm/disasm/Constants-arm.h
@@ -164,16 +164,39 @@ enum MiscInstructionsBits74 {
     BXJ  =  2 << 4,
     BLX  =  3 << 4,
     BKPT =  7 << 4,
 
     // With bits 22-21 11.
     CLZ  =  1 << 4
 };
 
+// Load and store exclusive instructions.
+
+// Bit positions.
+enum {
+    ExclusiveOpHi = 24,         // Hi bit of opcode field
+    ExclusiveOpLo = 23,         // Lo bit of opcode field
+    ExclusiveSizeHi = 22,       // Hi bit of operand size field
+    ExclusiveSizeLo = 21,       // Lo bit of operand size field
+    ExclusiveLoad = 20          // Bit indicating load
+};
+
+// Opcode bits for exclusive instructions.
+enum {
+    ExclusiveOpcode = 3
+};
+
+// Operand size, Bits(ExclusiveSizeHi,ExclusiveSizeLo).
+enum {
+    ExclusiveWord = 0,
+    ExclusiveDouble = 1,
+    ExclusiveByte = 2,
+    ExclusiveHalf = 3
+};
 
 // Instruction encoding bits and masks.
 enum {
     H = 1 << 5,   // Halfword (or byte).
     S6 = 1 << 6,  // Signed (or unsigned).
     L = 1 << 20,  // Load (or store).
     S = 1 << 20,  // Set condition code (or leave unchanged).
     W = 1 << 21,  // Writeback base register (or leave unchanged).
--- a/js/src/jit/arm/disasm/Disasm-arm.cpp
+++ b/js/src/jit/arm/disasm/Disasm-arm.cpp
@@ -793,17 +793,54 @@ Decoder::DecodeType01(Instruction* instr
                     // when referring to the target registers. They are mapped to the Rn
                     // and Rd fields as follows:
                     // RdLo == Rd field
                     // RdHi == Rn field
                     // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs>
                     Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs");
                 }
             } else {
-                Unknown(instr);  // not used by V8
+                if (instr->Bits(ExclusiveOpHi, ExclusiveOpLo) == ExclusiveOpcode) {
+                    if (instr->Bit(ExclusiveLoad) == 1) {
+                        switch (instr->Bits(ExclusiveSizeHi, ExclusiveSizeLo)) {
+                          case ExclusiveWord:
+                            Format(instr, "ldrex'cond 'rt, ['rn]");
+                            break;
+                          case ExclusiveDouble:
+                            Format(instr, "ldrexd'cond 'rt, ['rn]");
+                            break;
+                          case ExclusiveByte:
+                            Format(instr, "ldrexb'cond 'rt, ['rn]");
+                            break;
+                          case ExclusiveHalf:
+                            Format(instr, "ldrexh'cond 'rt, ['rn]");
+                            break;
+                        }
+                    } else {
+                        // The documentation names the low four bits of the
+                        // store-exclusive instructions "Rt" but canonically
+                        // for disassembly they are really "Rm".
+                        switch (instr->Bits(ExclusiveSizeHi, ExclusiveSizeLo)) {
+                          case ExclusiveWord:
+                            Format(instr, "strex'cond 'rd, 'rm, ['rn]");
+                            break;
+                          case ExclusiveDouble:
+                            Format(instr, "strexd'cond 'rd, 'rm, ['rn]");
+                            break;
+                          case ExclusiveByte:
+                            Format(instr, "strexb'cond 'rd, 'rm, ['rn]");
+                            break;
+                          case ExclusiveHalf:
+                            Format(instr, "strexh'cond 'rd, 'rm, ['rn]");
+                            break;
+                        }
+                    }
+                } else {
+                    Unknown(instr);
+                }
             }
         } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xd) == 0xd)) {
             // ldrd, strd
             switch (instr->PUField()) {
               case da_x: {
                 if (instr->Bit(22) == 0) {
                     Format(instr, "'memop'cond's 'rd, ['rn], -'rm");
                 } else {
@@ -1835,16 +1872,43 @@ Decoder::DecodeSpecialCondition(Instruct
             FormatNeonList(Vd, type);
             Print(", ");
             FormatNeonMemory(Rn, align, Rm);
         } else {
             Unknown(instr);
         }
         break;
       case 0xA:
+        if (instr->Bits(22, 20) == 7) {
+            const char* option = "?";
+            switch (instr->Bits(3, 0)) {
+              case  2: option = "oshst"; break;
+              case  3: option = "osh";   break;
+              case  6: option = "nshst"; break;
+              case  7: option = "nsh";   break;
+              case 10: option = "ishst"; break;
+              case 11: option = "ish";   break;
+              case 14: option = "st";    break;
+              case 15: option = "sy";    break;
+            }
+            switch (instr->Bits(7, 4)) {
+              case 4:
+                out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                            "dsb %s", option);
+                break;
+              case 5:
+                out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+                                            "dmb %s", option);
+                break;
+              default:
+                Unknown(instr);
+            }
+            break;
+        }
+        // else fall through
       case 0xB:
         if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) {
             int Rn = instr->Bits(19, 16);
             int offset = instr->Bits(11, 0);
             if (offset == 0) {
                 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
                                             "pld [r%d]", Rn);
             } else if (instr->Bit(23) == 0) {