Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <dirent.h>
     18 #include <fstream>
     19 #include <sys/types.h>
     20 #include <map>
     21 
     22 #include "gtest/gtest.h"
     23 #include "utils/arm/assembler_thumb2.h"
     24 #include "base/hex_dump.h"
     25 #include "common_runtime_test.h"
     26 
     27 namespace art {
     28 namespace arm {
     29 
     30 // Include results file (generated manually)
     31 #include "assembler_thumb_test_expected.cc.inc"
     32 
     33 #ifndef HAVE_ANDROID_OS
     34 // This controls whether the results are printed to the
     35 // screen or compared against the expected output.
     36 // To generate new expected output, set this to true and
     37 // copy the output into the .cc.inc file in the form
     38 // of the other results.
     39 //
     40 // When this is false, the results are not printed to the
     41 // output, but are compared against the expected results
     42 // in the .cc.inc file.
     43 static constexpr bool kPrintResults = false;
     44 #endif
     45 
     46 void SetAndroidData() {
     47   const char* data = getenv("ANDROID_DATA");
     48   if (data == nullptr) {
     49     setenv("ANDROID_DATA", "/tmp", 1);
     50   }
     51 }
     52 
     53 int CompareIgnoringSpace(const char* s1, const char* s2) {
     54   while (*s1 != '\0') {
     55     while (isspace(*s1)) ++s1;
     56     while (isspace(*s2)) ++s2;
     57     if (*s1 == '\0' || *s1 != *s2) {
     58       break;
     59     }
     60     ++s1;
     61     ++s2;
     62   }
     63   return *s1 - *s2;
     64 }
     65 
     66 void dump(std::vector<uint8_t>& code, const char* testname) {
     67   // This will only work on the host.  There is no as, objcopy or objdump on the
     68   // device.
     69 #ifndef HAVE_ANDROID_OS
     70   static bool results_ok = false;
     71   static std::string toolsdir;
     72 
     73   if (!results_ok) {
     74     setup_results();
     75     toolsdir = CommonRuntimeTest::GetAndroidTargetToolsDir(kThumb2);
     76     SetAndroidData();
     77     results_ok = true;
     78   }
     79 
     80   ScratchFile file;
     81 
     82   const char* filename = file.GetFilename().c_str();
     83 
     84   std::ofstream out(filename);
     85   if (out) {
     86     out << ".section \".text\"\n";
     87     out << ".syntax unified\n";
     88     out << ".arch armv7-a\n";
     89     out << ".thumb\n";
     90     out << ".thumb_func\n";
     91     out << ".type " << testname << ", #function\n";
     92     out << ".global " << testname << "\n";
     93     out << testname << ":\n";
     94     out << ".fnstart\n";
     95 
     96     for (uint32_t i = 0 ; i < code.size(); ++i) {
     97       out << ".byte " << (static_cast<int>(code[i]) & 0xff) << "\n";
     98     }
     99     out << ".fnend\n";
    100     out << ".size " << testname << ", .-" << testname << "\n";
    101   }
    102   out.close();
    103 
    104   char cmd[1024];
    105 
    106   // Assemble the .S
    107   snprintf(cmd, sizeof(cmd), "%sas %s -o %s.o", toolsdir.c_str(), filename, filename);
    108   system(cmd);
    109 
    110   // Remove the $d symbols to prevent the disassembler dumping the instructions
    111   // as .word
    112   snprintf(cmd, sizeof(cmd), "%sobjcopy -N '$d' %s.o %s.oo", toolsdir.c_str(), filename, filename);
    113   system(cmd);
    114 
    115   // Disassemble.
    116 
    117   snprintf(cmd, sizeof(cmd), "%sobjdump -d %s.oo | grep '^  *[0-9a-f][0-9a-f]*:'",
    118     toolsdir.c_str(), filename);
    119   if (kPrintResults) {
    120     // Print the results only, don't check. This is used to generate new output for inserting
    121     // into the .inc file.
    122     system(cmd);
    123   } else {
    124     // Check the results match the appropriate results in the .inc file.
    125     FILE *fp = popen(cmd, "r");
    126     ASSERT_TRUE(fp != nullptr);
    127 
    128     std::map<std::string, const char**>::iterator results = test_results.find(testname);
    129     ASSERT_NE(results, test_results.end());
    130 
    131     uint32_t lineindex = 0;
    132 
    133     while (!feof(fp)) {
    134       char testline[256];
    135       char *s = fgets(testline, sizeof(testline), fp);
    136       if (s == nullptr) {
    137         break;
    138       }
    139       if (CompareIgnoringSpace(results->second[lineindex], testline) != 0) {
    140         LOG(FATAL) << "Output is not as expected at line: " << lineindex
    141           << results->second[lineindex] << "/" << testline;
    142       }
    143       ++lineindex;
    144     }
    145     // Check that we are at the end.
    146     ASSERT_TRUE(results->second[lineindex] == nullptr);
    147     fclose(fp);
    148   }
    149 
    150   char buf[FILENAME_MAX];
    151   snprintf(buf, sizeof(buf), "%s.o", filename);
    152   unlink(buf);
    153 
    154   snprintf(buf, sizeof(buf), "%s.oo", filename);
    155   unlink(buf);
    156 #endif
    157 }
    158 
    159 #define __ assembler->
    160 
    161 TEST(Thumb2AssemblerTest, SimpleMov) {
    162   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    163 
    164   __ mov(R0, ShifterOperand(R1));
    165   __ mov(R8, ShifterOperand(R9));
    166 
    167   __ mov(R0, ShifterOperand(1));
    168   __ mov(R8, ShifterOperand(9));
    169 
    170   size_t cs = __ CodeSize();
    171   std::vector<uint8_t> managed_code(cs);
    172   MemoryRegion code(&managed_code[0], managed_code.size());
    173   __ FinalizeInstructions(code);
    174   dump(managed_code, "SimpleMov");
    175   delete assembler;
    176 }
    177 
    178 TEST(Thumb2AssemblerTest, SimpleMov32) {
    179   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    180   assembler->Force32Bit();
    181 
    182   __ mov(R0, ShifterOperand(R1));
    183   __ mov(R8, ShifterOperand(R9));
    184 
    185   size_t cs = __ CodeSize();
    186   std::vector<uint8_t> managed_code(cs);
    187   MemoryRegion code(&managed_code[0], managed_code.size());
    188   __ FinalizeInstructions(code);
    189   dump(managed_code, "SimpleMov32");
    190   delete assembler;
    191 }
    192 
    193 TEST(Thumb2AssemblerTest, SimpleMovAdd) {
    194   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    195 
    196   __ mov(R0, ShifterOperand(R1));
    197   __ add(R0, R1, ShifterOperand(R2));
    198   __ add(R0, R1, ShifterOperand());
    199 
    200   size_t cs = __ CodeSize();
    201   std::vector<uint8_t> managed_code(cs);
    202   MemoryRegion code(&managed_code[0], managed_code.size());
    203   __ FinalizeInstructions(code);
    204   dump(managed_code, "SimpleMovAdd");
    205   delete assembler;
    206 }
    207 
    208 TEST(Thumb2AssemblerTest, DataProcessingRegister) {
    209   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    210 
    211   __ mov(R0, ShifterOperand(R1));
    212   __ mvn(R0, ShifterOperand(R1));
    213 
    214   // 32 bit variants.
    215   __ add(R0, R1, ShifterOperand(R2));
    216   __ sub(R0, R1, ShifterOperand(R2));
    217   __ and_(R0, R1, ShifterOperand(R2));
    218   __ orr(R0, R1, ShifterOperand(R2));
    219   __ eor(R0, R1, ShifterOperand(R2));
    220   __ bic(R0, R1, ShifterOperand(R2));
    221   __ adc(R0, R1, ShifterOperand(R2));
    222   __ sbc(R0, R1, ShifterOperand(R2));
    223   __ rsb(R0, R1, ShifterOperand(R2));
    224 
    225   // 16 bit variants.
    226   __ add(R0, R1, ShifterOperand());
    227   __ sub(R0, R1, ShifterOperand());
    228   __ and_(R0, R0, ShifterOperand(R1));
    229   __ orr(R0, R0, ShifterOperand(R1));
    230   __ eor(R0, R0, ShifterOperand(R1));
    231   __ bic(R0, R0, ShifterOperand(R1));
    232   __ adc(R0, R0, ShifterOperand(R1));
    233   __ sbc(R0, R0, ShifterOperand(R1));
    234   __ rsb(R0, R0, ShifterOperand(R1));
    235 
    236   __ tst(R0, ShifterOperand(R1));
    237   __ teq(R0, ShifterOperand(R1));
    238   __ cmp(R0, ShifterOperand(R1));
    239   __ cmn(R0, ShifterOperand(R1));
    240 
    241   __ movs(R0, ShifterOperand(R1));
    242   __ mvns(R0, ShifterOperand(R1));
    243 
    244   // 32 bit variants.
    245   __ add(R12, R1, ShifterOperand(R0));
    246 
    247   size_t cs = __ CodeSize();
    248   std::vector<uint8_t> managed_code(cs);
    249   MemoryRegion code(&managed_code[0], managed_code.size());
    250   __ FinalizeInstructions(code);
    251   dump(managed_code, "DataProcessingRegister");
    252   delete assembler;
    253 }
    254 
    255 TEST(Thumb2AssemblerTest, DataProcessingImmediate) {
    256   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    257 
    258   __ mov(R0, ShifterOperand(0x55));
    259   __ mvn(R0, ShifterOperand(0x55));
    260   __ add(R0, R1, ShifterOperand(0x55));
    261   __ sub(R0, R1, ShifterOperand(0x55));
    262   __ and_(R0, R1, ShifterOperand(0x55));
    263   __ orr(R0, R1, ShifterOperand(0x55));
    264   __ eor(R0, R1, ShifterOperand(0x55));
    265   __ bic(R0, R1, ShifterOperand(0x55));
    266   __ adc(R0, R1, ShifterOperand(0x55));
    267   __ sbc(R0, R1, ShifterOperand(0x55));
    268   __ rsb(R0, R1, ShifterOperand(0x55));
    269 
    270   __ tst(R0, ShifterOperand(0x55));
    271   __ teq(R0, ShifterOperand(0x55));
    272   __ cmp(R0, ShifterOperand(0x55));
    273   __ cmn(R0, ShifterOperand(0x55));
    274 
    275   __ add(R0, R1, ShifterOperand(5));
    276   __ sub(R0, R1, ShifterOperand(5));
    277 
    278   __ movs(R0, ShifterOperand(0x55));
    279   __ mvns(R0, ShifterOperand(0x55));
    280 
    281   size_t cs = __ CodeSize();
    282   std::vector<uint8_t> managed_code(cs);
    283   MemoryRegion code(&managed_code[0], managed_code.size());
    284   __ FinalizeInstructions(code);
    285   dump(managed_code, "DataProcessingImmediate");
    286   delete assembler;
    287 }
    288 
    289 TEST(Thumb2AssemblerTest, DataProcessingModifiedImmediate) {
    290   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    291 
    292   __ mov(R0, ShifterOperand(0x550055));
    293   __ mvn(R0, ShifterOperand(0x550055));
    294   __ add(R0, R1, ShifterOperand(0x550055));
    295   __ sub(R0, R1, ShifterOperand(0x550055));
    296   __ and_(R0, R1, ShifterOperand(0x550055));
    297   __ orr(R0, R1, ShifterOperand(0x550055));
    298   __ eor(R0, R1, ShifterOperand(0x550055));
    299   __ bic(R0, R1, ShifterOperand(0x550055));
    300   __ adc(R0, R1, ShifterOperand(0x550055));
    301   __ sbc(R0, R1, ShifterOperand(0x550055));
    302   __ rsb(R0, R1, ShifterOperand(0x550055));
    303 
    304   __ tst(R0, ShifterOperand(0x550055));
    305   __ teq(R0, ShifterOperand(0x550055));
    306   __ cmp(R0, ShifterOperand(0x550055));
    307   __ cmn(R0, ShifterOperand(0x550055));
    308 
    309   size_t cs = __ CodeSize();
    310   std::vector<uint8_t> managed_code(cs);
    311   MemoryRegion code(&managed_code[0], managed_code.size());
    312   __ FinalizeInstructions(code);
    313   dump(managed_code, "DataProcessingModifiedImmediate");
    314   delete assembler;
    315 }
    316 
    317 
    318 TEST(Thumb2AssemblerTest, DataProcessingModifiedImmediates) {
    319   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    320 
    321   __ mov(R0, ShifterOperand(0x550055));
    322   __ mov(R0, ShifterOperand(0x55005500));
    323   __ mov(R0, ShifterOperand(0x55555555));
    324   __ mov(R0, ShifterOperand(0xd5000000));       // rotated to first position
    325   __ mov(R0, ShifterOperand(0x6a000000));       // rotated to second position
    326   __ mov(R0, ShifterOperand(0x350));            // rotated to 2nd last position
    327   __ mov(R0, ShifterOperand(0x1a8));            // rotated to last position
    328 
    329   size_t cs = __ CodeSize();
    330   std::vector<uint8_t> managed_code(cs);
    331   MemoryRegion code(&managed_code[0], managed_code.size());
    332   __ FinalizeInstructions(code);
    333   dump(managed_code, "DataProcessingModifiedImmediates");
    334   delete assembler;
    335 }
    336 
    337 TEST(Thumb2AssemblerTest, DataProcessingShiftedRegister) {
    338   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    339 
    340   __ mov(R3, ShifterOperand(R4, LSL, 4));
    341   __ mov(R3, ShifterOperand(R4, LSR, 5));
    342   __ mov(R3, ShifterOperand(R4, ASR, 6));
    343   __ mov(R3, ShifterOperand(R4, ROR, 7));
    344   __ mov(R3, ShifterOperand(R4, ROR));
    345 
    346   // 32 bit variants.
    347   __ mov(R8, ShifterOperand(R4, LSL, 4));
    348   __ mov(R8, ShifterOperand(R4, LSR, 5));
    349   __ mov(R8, ShifterOperand(R4, ASR, 6));
    350   __ mov(R8, ShifterOperand(R4, ROR, 7));
    351   __ mov(R8, ShifterOperand(R4, RRX));
    352 
    353   size_t cs = __ CodeSize();
    354   std::vector<uint8_t> managed_code(cs);
    355   MemoryRegion code(&managed_code[0], managed_code.size());
    356   __ FinalizeInstructions(code);
    357   dump(managed_code, "DataProcessingShiftedRegister");
    358   delete assembler;
    359 }
    360 
    361 
    362 TEST(Thumb2AssemblerTest, BasicLoad) {
    363   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    364 
    365   __ ldr(R3, Address(R4, 24));
    366   __ ldrb(R3, Address(R4, 24));
    367   __ ldrh(R3, Address(R4, 24));
    368   __ ldrsb(R3, Address(R4, 24));
    369   __ ldrsh(R3, Address(R4, 24));
    370 
    371   __ ldr(R3, Address(SP, 24));
    372 
    373   // 32 bit variants
    374   __ ldr(R8, Address(R4, 24));
    375   __ ldrb(R8, Address(R4, 24));
    376   __ ldrh(R8, Address(R4, 24));
    377   __ ldrsb(R8, Address(R4, 24));
    378   __ ldrsh(R8, Address(R4, 24));
    379 
    380   size_t cs = __ CodeSize();
    381   std::vector<uint8_t> managed_code(cs);
    382   MemoryRegion code(&managed_code[0], managed_code.size());
    383   __ FinalizeInstructions(code);
    384   dump(managed_code, "BasicLoad");
    385   delete assembler;
    386 }
    387 
    388 
    389 TEST(Thumb2AssemblerTest, BasicStore) {
    390   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    391 
    392   __ str(R3, Address(R4, 24));
    393   __ strb(R3, Address(R4, 24));
    394   __ strh(R3, Address(R4, 24));
    395 
    396   __ str(R3, Address(SP, 24));
    397 
    398   // 32 bit variants.
    399   __ str(R8, Address(R4, 24));
    400   __ strb(R8, Address(R4, 24));
    401   __ strh(R8, Address(R4, 24));
    402 
    403   size_t cs = __ CodeSize();
    404   std::vector<uint8_t> managed_code(cs);
    405   MemoryRegion code(&managed_code[0], managed_code.size());
    406   __ FinalizeInstructions(code);
    407   dump(managed_code, "BasicStore");
    408   delete assembler;
    409 }
    410 
    411 TEST(Thumb2AssemblerTest, ComplexLoad) {
    412   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    413 
    414   __ ldr(R3, Address(R4, 24, Address::Mode::Offset));
    415   __ ldr(R3, Address(R4, 24, Address::Mode::PreIndex));
    416   __ ldr(R3, Address(R4, 24, Address::Mode::PostIndex));
    417   __ ldr(R3, Address(R4, 24, Address::Mode::NegOffset));
    418   __ ldr(R3, Address(R4, 24, Address::Mode::NegPreIndex));
    419   __ ldr(R3, Address(R4, 24, Address::Mode::NegPostIndex));
    420 
    421   __ ldrb(R3, Address(R4, 24, Address::Mode::Offset));
    422   __ ldrb(R3, Address(R4, 24, Address::Mode::PreIndex));
    423   __ ldrb(R3, Address(R4, 24, Address::Mode::PostIndex));
    424   __ ldrb(R3, Address(R4, 24, Address::Mode::NegOffset));
    425   __ ldrb(R3, Address(R4, 24, Address::Mode::NegPreIndex));
    426   __ ldrb(R3, Address(R4, 24, Address::Mode::NegPostIndex));
    427 
    428   __ ldrh(R3, Address(R4, 24, Address::Mode::Offset));
    429   __ ldrh(R3, Address(R4, 24, Address::Mode::PreIndex));
    430   __ ldrh(R3, Address(R4, 24, Address::Mode::PostIndex));
    431   __ ldrh(R3, Address(R4, 24, Address::Mode::NegOffset));
    432   __ ldrh(R3, Address(R4, 24, Address::Mode::NegPreIndex));
    433   __ ldrh(R3, Address(R4, 24, Address::Mode::NegPostIndex));
    434 
    435   __ ldrsb(R3, Address(R4, 24, Address::Mode::Offset));
    436   __ ldrsb(R3, Address(R4, 24, Address::Mode::PreIndex));
    437   __ ldrsb(R3, Address(R4, 24, Address::Mode::PostIndex));
    438   __ ldrsb(R3, Address(R4, 24, Address::Mode::NegOffset));
    439   __ ldrsb(R3, Address(R4, 24, Address::Mode::NegPreIndex));
    440   __ ldrsb(R3, Address(R4, 24, Address::Mode::NegPostIndex));
    441 
    442   __ ldrsh(R3, Address(R4, 24, Address::Mode::Offset));
    443   __ ldrsh(R3, Address(R4, 24, Address::Mode::PreIndex));
    444   __ ldrsh(R3, Address(R4, 24, Address::Mode::PostIndex));
    445   __ ldrsh(R3, Address(R4, 24, Address::Mode::NegOffset));
    446   __ ldrsh(R3, Address(R4, 24, Address::Mode::NegPreIndex));
    447   __ ldrsh(R3, Address(R4, 24, Address::Mode::NegPostIndex));
    448 
    449   size_t cs = __ CodeSize();
    450   std::vector<uint8_t> managed_code(cs);
    451   MemoryRegion code(&managed_code[0], managed_code.size());
    452   __ FinalizeInstructions(code);
    453   dump(managed_code, "ComplexLoad");
    454   delete assembler;
    455 }
    456 
    457 
    458 TEST(Thumb2AssemblerTest, ComplexStore) {
    459   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    460 
    461   __ str(R3, Address(R4, 24, Address::Mode::Offset));
    462   __ str(R3, Address(R4, 24, Address::Mode::PreIndex));
    463   __ str(R3, Address(R4, 24, Address::Mode::PostIndex));
    464   __ str(R3, Address(R4, 24, Address::Mode::NegOffset));
    465   __ str(R3, Address(R4, 24, Address::Mode::NegPreIndex));
    466   __ str(R3, Address(R4, 24, Address::Mode::NegPostIndex));
    467 
    468   __ strb(R3, Address(R4, 24, Address::Mode::Offset));
    469   __ strb(R3, Address(R4, 24, Address::Mode::PreIndex));
    470   __ strb(R3, Address(R4, 24, Address::Mode::PostIndex));
    471   __ strb(R3, Address(R4, 24, Address::Mode::NegOffset));
    472   __ strb(R3, Address(R4, 24, Address::Mode::NegPreIndex));
    473   __ strb(R3, Address(R4, 24, Address::Mode::NegPostIndex));
    474 
    475   __ strh(R3, Address(R4, 24, Address::Mode::Offset));
    476   __ strh(R3, Address(R4, 24, Address::Mode::PreIndex));
    477   __ strh(R3, Address(R4, 24, Address::Mode::PostIndex));
    478   __ strh(R3, Address(R4, 24, Address::Mode::NegOffset));
    479   __ strh(R3, Address(R4, 24, Address::Mode::NegPreIndex));
    480   __ strh(R3, Address(R4, 24, Address::Mode::NegPostIndex));
    481 
    482   size_t cs = __ CodeSize();
    483   std::vector<uint8_t> managed_code(cs);
    484   MemoryRegion code(&managed_code[0], managed_code.size());
    485   __ FinalizeInstructions(code);
    486   dump(managed_code, "ComplexStore");
    487   delete assembler;
    488 }
    489 
    490 TEST(Thumb2AssemblerTest, NegativeLoadStore) {
    491   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    492 
    493   __ ldr(R3, Address(R4, -24, Address::Mode::Offset));
    494   __ ldr(R3, Address(R4, -24, Address::Mode::PreIndex));
    495   __ ldr(R3, Address(R4, -24, Address::Mode::PostIndex));
    496   __ ldr(R3, Address(R4, -24, Address::Mode::NegOffset));
    497   __ ldr(R3, Address(R4, -24, Address::Mode::NegPreIndex));
    498   __ ldr(R3, Address(R4, -24, Address::Mode::NegPostIndex));
    499 
    500   __ ldrb(R3, Address(R4, -24, Address::Mode::Offset));
    501   __ ldrb(R3, Address(R4, -24, Address::Mode::PreIndex));
    502   __ ldrb(R3, Address(R4, -24, Address::Mode::PostIndex));
    503   __ ldrb(R3, Address(R4, -24, Address::Mode::NegOffset));
    504   __ ldrb(R3, Address(R4, -24, Address::Mode::NegPreIndex));
    505   __ ldrb(R3, Address(R4, -24, Address::Mode::NegPostIndex));
    506 
    507   __ ldrh(R3, Address(R4, -24, Address::Mode::Offset));
    508   __ ldrh(R3, Address(R4, -24, Address::Mode::PreIndex));
    509   __ ldrh(R3, Address(R4, -24, Address::Mode::PostIndex));
    510   __ ldrh(R3, Address(R4, -24, Address::Mode::NegOffset));
    511   __ ldrh(R3, Address(R4, -24, Address::Mode::NegPreIndex));
    512   __ ldrh(R3, Address(R4, -24, Address::Mode::NegPostIndex));
    513 
    514   __ ldrsb(R3, Address(R4, -24, Address::Mode::Offset));
    515   __ ldrsb(R3, Address(R4, -24, Address::Mode::PreIndex));
    516   __ ldrsb(R3, Address(R4, -24, Address::Mode::PostIndex));
    517   __ ldrsb(R3, Address(R4, -24, Address::Mode::NegOffset));
    518   __ ldrsb(R3, Address(R4, -24, Address::Mode::NegPreIndex));
    519   __ ldrsb(R3, Address(R4, -24, Address::Mode::NegPostIndex));
    520 
    521   __ ldrsh(R3, Address(R4, -24, Address::Mode::Offset));
    522   __ ldrsh(R3, Address(R4, -24, Address::Mode::PreIndex));
    523   __ ldrsh(R3, Address(R4, -24, Address::Mode::PostIndex));
    524   __ ldrsh(R3, Address(R4, -24, Address::Mode::NegOffset));
    525   __ ldrsh(R3, Address(R4, -24, Address::Mode::NegPreIndex));
    526   __ ldrsh(R3, Address(R4, -24, Address::Mode::NegPostIndex));
    527 
    528   __ str(R3, Address(R4, -24, Address::Mode::Offset));
    529   __ str(R3, Address(R4, -24, Address::Mode::PreIndex));
    530   __ str(R3, Address(R4, -24, Address::Mode::PostIndex));
    531   __ str(R3, Address(R4, -24, Address::Mode::NegOffset));
    532   __ str(R3, Address(R4, -24, Address::Mode::NegPreIndex));
    533   __ str(R3, Address(R4, -24, Address::Mode::NegPostIndex));
    534 
    535   __ strb(R3, Address(R4, -24, Address::Mode::Offset));
    536   __ strb(R3, Address(R4, -24, Address::Mode::PreIndex));
    537   __ strb(R3, Address(R4, -24, Address::Mode::PostIndex));
    538   __ strb(R3, Address(R4, -24, Address::Mode::NegOffset));
    539   __ strb(R3, Address(R4, -24, Address::Mode::NegPreIndex));
    540   __ strb(R3, Address(R4, -24, Address::Mode::NegPostIndex));
    541 
    542   __ strh(R3, Address(R4, -24, Address::Mode::Offset));
    543   __ strh(R3, Address(R4, -24, Address::Mode::PreIndex));
    544   __ strh(R3, Address(R4, -24, Address::Mode::PostIndex));
    545   __ strh(R3, Address(R4, -24, Address::Mode::NegOffset));
    546   __ strh(R3, Address(R4, -24, Address::Mode::NegPreIndex));
    547   __ strh(R3, Address(R4, -24, Address::Mode::NegPostIndex));
    548 
    549   size_t cs = __ CodeSize();
    550   std::vector<uint8_t> managed_code(cs);
    551   MemoryRegion code(&managed_code[0], managed_code.size());
    552   __ FinalizeInstructions(code);
    553   dump(managed_code, "NegativeLoadStore");
    554   delete assembler;
    555 }
    556 
    557 TEST(Thumb2AssemblerTest, SimpleLoadStoreDual) {
    558   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    559 
    560   __ strd(R2, Address(R0, 24, Address::Mode::Offset));
    561   __ ldrd(R2, Address(R0, 24, Address::Mode::Offset));
    562 
    563   size_t cs = __ CodeSize();
    564   std::vector<uint8_t> managed_code(cs);
    565   MemoryRegion code(&managed_code[0], managed_code.size());
    566   __ FinalizeInstructions(code);
    567   dump(managed_code, "SimpleLoadStoreDual");
    568   delete assembler;
    569 }
    570 
    571 TEST(Thumb2AssemblerTest, ComplexLoadStoreDual) {
    572   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    573 
    574   __ strd(R2, Address(R0, 24, Address::Mode::Offset));
    575   __ strd(R2, Address(R0, 24, Address::Mode::PreIndex));
    576   __ strd(R2, Address(R0, 24, Address::Mode::PostIndex));
    577   __ strd(R2, Address(R0, 24, Address::Mode::NegOffset));
    578   __ strd(R2, Address(R0, 24, Address::Mode::NegPreIndex));
    579   __ strd(R2, Address(R0, 24, Address::Mode::NegPostIndex));
    580 
    581   __ ldrd(R2, Address(R0, 24, Address::Mode::Offset));
    582   __ ldrd(R2, Address(R0, 24, Address::Mode::PreIndex));
    583   __ ldrd(R2, Address(R0, 24, Address::Mode::PostIndex));
    584   __ ldrd(R2, Address(R0, 24, Address::Mode::NegOffset));
    585   __ ldrd(R2, Address(R0, 24, Address::Mode::NegPreIndex));
    586   __ ldrd(R2, Address(R0, 24, Address::Mode::NegPostIndex));
    587 
    588   size_t cs = __ CodeSize();
    589   std::vector<uint8_t> managed_code(cs);
    590   MemoryRegion code(&managed_code[0], managed_code.size());
    591   __ FinalizeInstructions(code);
    592   dump(managed_code, "ComplexLoadStoreDual");
    593   delete assembler;
    594 }
    595 
    596 TEST(Thumb2AssemblerTest, NegativeLoadStoreDual) {
    597   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    598 
    599   __ strd(R2, Address(R0, -24, Address::Mode::Offset));
    600   __ strd(R2, Address(R0, -24, Address::Mode::PreIndex));
    601   __ strd(R2, Address(R0, -24, Address::Mode::PostIndex));
    602   __ strd(R2, Address(R0, -24, Address::Mode::NegOffset));
    603   __ strd(R2, Address(R0, -24, Address::Mode::NegPreIndex));
    604   __ strd(R2, Address(R0, -24, Address::Mode::NegPostIndex));
    605 
    606   __ ldrd(R2, Address(R0, -24, Address::Mode::Offset));
    607   __ ldrd(R2, Address(R0, -24, Address::Mode::PreIndex));
    608   __ ldrd(R2, Address(R0, -24, Address::Mode::PostIndex));
    609   __ ldrd(R2, Address(R0, -24, Address::Mode::NegOffset));
    610   __ ldrd(R2, Address(R0, -24, Address::Mode::NegPreIndex));
    611   __ ldrd(R2, Address(R0, -24, Address::Mode::NegPostIndex));
    612 
    613   size_t cs = __ CodeSize();
    614   std::vector<uint8_t> managed_code(cs);
    615   MemoryRegion code(&managed_code[0], managed_code.size());
    616   __ FinalizeInstructions(code);
    617   dump(managed_code, "NegativeLoadStoreDual");
    618   delete assembler;
    619 }
    620 
    621 TEST(Thumb2AssemblerTest, SimpleBranch) {
    622   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    623 
    624   Label l1;
    625   __ mov(R0, ShifterOperand(2));
    626   __ Bind(&l1);
    627   __ mov(R1, ShifterOperand(1));
    628   __ b(&l1);
    629   Label l2;
    630   __ b(&l2);
    631   __ mov(R1, ShifterOperand(2));
    632   __ Bind(&l2);
    633   __ mov(R0, ShifterOperand(3));
    634 
    635   Label l3;
    636   __ mov(R0, ShifterOperand(2));
    637   __ Bind(&l3);
    638   __ mov(R1, ShifterOperand(1));
    639   __ b(&l3, EQ);
    640 
    641   Label l4;
    642   __ b(&l4, EQ);
    643   __ mov(R1, ShifterOperand(2));
    644   __ Bind(&l4);
    645   __ mov(R0, ShifterOperand(3));
    646 
    647   // 2 linked labels.
    648   Label l5;
    649   __ b(&l5);
    650   __ mov(R1, ShifterOperand(4));
    651   __ b(&l5);
    652   __ mov(R1, ShifterOperand(5));
    653   __ Bind(&l5);
    654   __ mov(R0, ShifterOperand(6));
    655 
    656   size_t cs = __ CodeSize();
    657   std::vector<uint8_t> managed_code(cs);
    658   MemoryRegion code(&managed_code[0], managed_code.size());
    659   __ FinalizeInstructions(code);
    660   dump(managed_code, "SimpleBranch");
    661   delete assembler;
    662 }
    663 
    664 TEST(Thumb2AssemblerTest, LongBranch) {
    665   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    666   assembler->Force32Bit();
    667   // 32 bit branches.
    668   Label l1;
    669   __ mov(R0, ShifterOperand(2));
    670   __ Bind(&l1);
    671   __ mov(R1, ShifterOperand(1));
    672   __ b(&l1);
    673 
    674   Label l2;
    675   __ b(&l2);
    676   __ mov(R1, ShifterOperand(2));
    677   __ Bind(&l2);
    678   __ mov(R0, ShifterOperand(3));
    679 
    680   Label l3;
    681   __ mov(R0, ShifterOperand(2));
    682   __ Bind(&l3);
    683   __ mov(R1, ShifterOperand(1));
    684   __ b(&l3, EQ);
    685 
    686   Label l4;
    687   __ b(&l4, EQ);
    688   __ mov(R1, ShifterOperand(2));
    689   __ Bind(&l4);
    690   __ mov(R0, ShifterOperand(3));
    691 
    692   // 2 linked labels.
    693   Label l5;
    694   __ b(&l5);
    695   __ mov(R1, ShifterOperand(4));
    696   __ b(&l5);
    697   __ mov(R1, ShifterOperand(5));
    698   __ Bind(&l5);
    699   __ mov(R0, ShifterOperand(6));
    700 
    701   size_t cs = __ CodeSize();
    702   std::vector<uint8_t> managed_code(cs);
    703   MemoryRegion code(&managed_code[0], managed_code.size());
    704   __ FinalizeInstructions(code);
    705   dump(managed_code, "LongBranch");
    706   delete assembler;
    707 }
    708 
    709 TEST(Thumb2AssemblerTest, LoadMultiple) {
    710   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    711 
    712   // 16 bit.
    713   __ ldm(DB_W, R4, (1 << R0 | 1 << R3));
    714 
    715   // 32 bit.
    716   __ ldm(DB_W, R4, (1 << LR | 1 << R11));
    717   __ ldm(DB, R4, (1 << LR | 1 << R11));
    718 
    719   // Single reg is converted to ldr
    720   __ ldm(DB_W, R4, (1 << R5));
    721 
    722   size_t cs = __ CodeSize();
    723   std::vector<uint8_t> managed_code(cs);
    724   MemoryRegion code(&managed_code[0], managed_code.size());
    725   __ FinalizeInstructions(code);
    726   dump(managed_code, "LoadMultiple");
    727   delete assembler;
    728 }
    729 
    730 TEST(Thumb2AssemblerTest, StoreMultiple) {
    731   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    732 
    733   // 16 bit.
    734   __ stm(IA_W, R4, (1 << R0 | 1 << R3));
    735 
    736   // 32 bit.
    737   __ stm(IA_W, R4, (1 << LR | 1 << R11));
    738   __ stm(IA, R4, (1 << LR | 1 << R11));
    739 
    740   // Single reg is converted to str
    741   __ stm(IA_W, R4, (1 << R5));
    742   __ stm(IA, R4, (1 << R5));
    743 
    744   size_t cs = __ CodeSize();
    745   std::vector<uint8_t> managed_code(cs);
    746   MemoryRegion code(&managed_code[0], managed_code.size());
    747   __ FinalizeInstructions(code);
    748   dump(managed_code, "StoreMultiple");
    749   delete assembler;
    750 }
    751 
    752 TEST(Thumb2AssemblerTest, MovWMovT) {
    753   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    754 
    755   __ movw(R4, 0);         // 16 bit.
    756   __ movw(R4, 0x34);      // 16 bit.
    757   __ movw(R9, 0x34);      // 32 bit due to high register.
    758   __ movw(R3, 0x1234);    // 32 bit due to large value.
    759   __ movw(R9, 0xffff);    // 32 bit due to large value and high register.
    760 
    761   // Always 32 bit.
    762   __ movt(R0, 0);
    763   __ movt(R0, 0x1234);
    764   __ movt(R1, 0xffff);
    765 
    766   size_t cs = __ CodeSize();
    767   std::vector<uint8_t> managed_code(cs);
    768   MemoryRegion code(&managed_code[0], managed_code.size());
    769   __ FinalizeInstructions(code);
    770   dump(managed_code, "MovWMovT");
    771   delete assembler;
    772 }
    773 
    774 TEST(Thumb2AssemblerTest, SpecialAddSub) {
    775   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    776 
    777   __ add(R2, SP, ShifterOperand(0x50));   // 16 bit.
    778   __ add(SP, SP, ShifterOperand(0x50));   // 16 bit.
    779   __ add(R8, SP, ShifterOperand(0x50));   // 32 bit.
    780 
    781   __ add(R2, SP, ShifterOperand(0xf00));  // 32 bit due to imm size.
    782   __ add(SP, SP, ShifterOperand(0xf00));  // 32 bit due to imm size.
    783 
    784   __ sub(SP, SP, ShifterOperand(0x50));     // 16 bit
    785   __ sub(R0, SP, ShifterOperand(0x50));     // 32 bit
    786   __ sub(R8, SP, ShifterOperand(0x50));     // 32 bit.
    787 
    788   __ sub(SP, SP, ShifterOperand(0xf00));   // 32 bit due to imm size
    789 
    790   size_t cs = __ CodeSize();
    791   std::vector<uint8_t> managed_code(cs);
    792   MemoryRegion code(&managed_code[0], managed_code.size());
    793   __ FinalizeInstructions(code);
    794   dump(managed_code, "SpecialAddSub");
    795   delete assembler;
    796 }
    797 
    798 TEST(Thumb2AssemblerTest, StoreToOffset) {
    799   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    800 
    801   __ StoreToOffset(kStoreWord, R2, R4, 12);     // Simple
    802   __ StoreToOffset(kStoreWord, R2, R4, 0x2000);     // Offset too big.
    803   __ StoreToOffset(kStoreWord, R0, R12, 12);
    804   __ StoreToOffset(kStoreHalfword, R0, R12, 12);
    805   __ StoreToOffset(kStoreByte, R2, R12, 12);
    806 
    807   size_t cs = __ CodeSize();
    808   std::vector<uint8_t> managed_code(cs);
    809   MemoryRegion code(&managed_code[0], managed_code.size());
    810   __ FinalizeInstructions(code);
    811   dump(managed_code, "StoreToOffset");
    812   delete assembler;
    813 }
    814 
    815 
    816 TEST(Thumb2AssemblerTest, IfThen) {
    817   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    818 
    819   __ it(EQ);
    820   __ mov(R1, ShifterOperand(1), EQ);
    821 
    822   __ it(EQ, kItThen);
    823   __ mov(R1, ShifterOperand(1), EQ);
    824   __ mov(R2, ShifterOperand(2), EQ);
    825 
    826   __ it(EQ, kItElse);
    827   __ mov(R1, ShifterOperand(1), EQ);
    828   __ mov(R2, ShifterOperand(2), NE);
    829 
    830   __ it(EQ, kItThen, kItElse);
    831   __ mov(R1, ShifterOperand(1), EQ);
    832   __ mov(R2, ShifterOperand(2), EQ);
    833   __ mov(R3, ShifterOperand(3), NE);
    834 
    835   __ it(EQ, kItElse, kItElse);
    836   __ mov(R1, ShifterOperand(1), EQ);
    837   __ mov(R2, ShifterOperand(2), NE);
    838   __ mov(R3, ShifterOperand(3), NE);
    839 
    840   __ it(EQ, kItThen, kItThen, kItElse);
    841   __ mov(R1, ShifterOperand(1), EQ);
    842   __ mov(R2, ShifterOperand(2), EQ);
    843   __ mov(R3, ShifterOperand(3), EQ);
    844   __ mov(R4, ShifterOperand(4), NE);
    845 
    846   size_t cs = __ CodeSize();
    847   std::vector<uint8_t> managed_code(cs);
    848   MemoryRegion code(&managed_code[0], managed_code.size());
    849   __ FinalizeInstructions(code);
    850   dump(managed_code, "IfThen");
    851   delete assembler;
    852 }
    853 
    854 TEST(Thumb2AssemblerTest, CbzCbnz) {
    855   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    856 
    857   Label l1;
    858   __ cbz(R2, &l1);
    859   __ mov(R1, ShifterOperand(3));
    860   __ mov(R2, ShifterOperand(3));
    861   __ Bind(&l1);
    862   __ mov(R2, ShifterOperand(4));
    863 
    864   Label l2;
    865   __ cbnz(R2, &l2);
    866   __ mov(R8, ShifterOperand(3));
    867   __ mov(R2, ShifterOperand(3));
    868   __ Bind(&l2);
    869   __ mov(R2, ShifterOperand(4));
    870 
    871   size_t cs = __ CodeSize();
    872   std::vector<uint8_t> managed_code(cs);
    873   MemoryRegion code(&managed_code[0], managed_code.size());
    874   __ FinalizeInstructions(code);
    875   dump(managed_code, "CbzCbnz");
    876   delete assembler;
    877 }
    878 
    879 TEST(Thumb2AssemblerTest, Multiply) {
    880   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    881 
    882   __ mul(R0, R1, R0);
    883   __ mul(R0, R1, R2);
    884   __ mul(R8, R9, R8);
    885   __ mul(R8, R9, R10);
    886 
    887   __ mla(R0, R1, R2, R3);
    888   __ mla(R8, R9, R8, R9);
    889 
    890   __ mls(R0, R1, R2, R3);
    891   __ mls(R8, R9, R8, R9);
    892 
    893   __ umull(R0, R1, R2, R3);
    894   __ umull(R8, R9, R10, R11);
    895 
    896   size_t cs = __ CodeSize();
    897   std::vector<uint8_t> managed_code(cs);
    898   MemoryRegion code(&managed_code[0], managed_code.size());
    899   __ FinalizeInstructions(code);
    900   dump(managed_code, "Multiply");
    901   delete assembler;
    902 }
    903 
    904 TEST(Thumb2AssemblerTest, Divide) {
    905   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    906 
    907   __ sdiv(R0, R1, R2);
    908   __ sdiv(R8, R9, R10);
    909 
    910   __ udiv(R0, R1, R2);
    911   __ udiv(R8, R9, R10);
    912 
    913   size_t cs = __ CodeSize();
    914   std::vector<uint8_t> managed_code(cs);
    915   MemoryRegion code(&managed_code[0], managed_code.size());
    916   __ FinalizeInstructions(code);
    917   dump(managed_code, "Divide");
    918   delete assembler;
    919 }
    920 
    921 TEST(Thumb2AssemblerTest, VMov) {
    922   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    923 
    924   __ vmovs(S1, 1.0);
    925   __ vmovd(D1, 1.0);
    926 
    927   __ vmovs(S1, S2);
    928   __ vmovd(D1, D2);
    929 
    930   size_t cs = __ CodeSize();
    931   std::vector<uint8_t> managed_code(cs);
    932   MemoryRegion code(&managed_code[0], managed_code.size());
    933   __ FinalizeInstructions(code);
    934   dump(managed_code, "VMov");
    935   delete assembler;
    936 }
    937 
    938 
    939 TEST(Thumb2AssemblerTest, BasicFloatingPoint) {
    940   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    941 
    942   __ vadds(S0, S1, S2);
    943   __ vsubs(S0, S1, S2);
    944   __ vmuls(S0, S1, S2);
    945   __ vmlas(S0, S1, S2);
    946   __ vmlss(S0, S1, S2);
    947   __ vdivs(S0, S1, S2);
    948   __ vabss(S0, S1);
    949   __ vnegs(S0, S1);
    950   __ vsqrts(S0, S1);
    951 
    952   __ vaddd(D0, D1, D2);
    953   __ vsubd(D0, D1, D2);
    954   __ vmuld(D0, D1, D2);
    955   __ vmlad(D0, D1, D2);
    956   __ vmlsd(D0, D1, D2);
    957   __ vdivd(D0, D1, D2);
    958   __ vabsd(D0, D1);
    959   __ vnegd(D0, D1);
    960   __ vsqrtd(D0, D1);
    961 
    962   size_t cs = __ CodeSize();
    963   std::vector<uint8_t> managed_code(cs);
    964   MemoryRegion code(&managed_code[0], managed_code.size());
    965   __ FinalizeInstructions(code);
    966   dump(managed_code, "BasicFloatingPoint");
    967   delete assembler;
    968 }
    969 
    970 TEST(Thumb2AssemblerTest, FloatingPointConversions) {
    971   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    972 
    973   __ vcvtsd(S2, D2);
    974   __ vcvtds(D2, S2);
    975 
    976   __ vcvtis(S1, S2);
    977   __ vcvtsi(S1, S2);
    978 
    979   __ vcvtid(S1, D2);
    980   __ vcvtdi(D1, S2);
    981 
    982   __ vcvtus(S1, S2);
    983   __ vcvtsu(S1, S2);
    984 
    985   __ vcvtud(S1, D2);
    986   __ vcvtdu(D1, S2);
    987 
    988   size_t cs = __ CodeSize();
    989   std::vector<uint8_t> managed_code(cs);
    990   MemoryRegion code(&managed_code[0], managed_code.size());
    991   __ FinalizeInstructions(code);
    992   dump(managed_code, "FloatingPointConversions");
    993   delete assembler;
    994 }
    995 
    996 TEST(Thumb2AssemblerTest, FloatingPointComparisons) {
    997   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
    998 
    999   __ vcmps(S0, S1);
   1000   __ vcmpd(D0, D1);
   1001 
   1002   __ vcmpsz(S2);
   1003   __ vcmpdz(D2);
   1004 
   1005   size_t cs = __ CodeSize();
   1006   std::vector<uint8_t> managed_code(cs);
   1007   MemoryRegion code(&managed_code[0], managed_code.size());
   1008   __ FinalizeInstructions(code);
   1009   dump(managed_code, "FloatingPointComparisons");
   1010   delete assembler;
   1011 }
   1012 
   1013 TEST(Thumb2AssemblerTest, Calls) {
   1014   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
   1015 
   1016   __ blx(LR);
   1017   __ bx(LR);
   1018 
   1019   size_t cs = __ CodeSize();
   1020   std::vector<uint8_t> managed_code(cs);
   1021   MemoryRegion code(&managed_code[0], managed_code.size());
   1022   __ FinalizeInstructions(code);
   1023   dump(managed_code, "Calls");
   1024   delete assembler;
   1025 }
   1026 
   1027 TEST(Thumb2AssemblerTest, Breakpoint) {
   1028   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
   1029 
   1030   __ bkpt(0);
   1031 
   1032   size_t cs = __ CodeSize();
   1033   std::vector<uint8_t> managed_code(cs);
   1034   MemoryRegion code(&managed_code[0], managed_code.size());
   1035   __ FinalizeInstructions(code);
   1036   dump(managed_code, "Breakpoint");
   1037   delete assembler;
   1038 }
   1039 
   1040 TEST(Thumb2AssemblerTest, StrR1) {
   1041   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
   1042 
   1043   __ str(R1, Address(SP, 68));
   1044   __ str(R1, Address(SP, 1068));
   1045 
   1046   size_t cs = __ CodeSize();
   1047   std::vector<uint8_t> managed_code(cs);
   1048   MemoryRegion code(&managed_code[0], managed_code.size());
   1049   __ FinalizeInstructions(code);
   1050   dump(managed_code, "StrR1");
   1051   delete assembler;
   1052 }
   1053 
   1054 TEST(Thumb2AssemblerTest, VPushPop) {
   1055   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
   1056 
   1057   __ vpushs(S2, 4);
   1058   __ vpushd(D2, 4);
   1059 
   1060   __ vpops(S2, 4);
   1061   __ vpopd(D2, 4);
   1062 
   1063   size_t cs = __ CodeSize();
   1064   std::vector<uint8_t> managed_code(cs);
   1065   MemoryRegion code(&managed_code[0], managed_code.size());
   1066   __ FinalizeInstructions(code);
   1067   dump(managed_code, "VPushPop");
   1068   delete assembler;
   1069 }
   1070 
   1071 TEST(Thumb2AssemblerTest, Max16BitBranch) {
   1072   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
   1073 
   1074   Label l1;
   1075   __ b(&l1);
   1076   for (int i = 0 ; i < (1 << 11) ; i += 2) {
   1077     __ mov(R3, ShifterOperand(i & 0xff));
   1078   }
   1079   __ Bind(&l1);
   1080   __ mov(R1, ShifterOperand(R2));
   1081 
   1082   size_t cs = __ CodeSize();
   1083   std::vector<uint8_t> managed_code(cs);
   1084   MemoryRegion code(&managed_code[0], managed_code.size());
   1085   __ FinalizeInstructions(code);
   1086   dump(managed_code, "Max16BitBranch");
   1087   delete assembler;
   1088 }
   1089 
   1090 TEST(Thumb2AssemblerTest, Branch32) {
   1091   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
   1092 
   1093   Label l1;
   1094   __ b(&l1);
   1095   for (int i = 0 ; i < (1 << 11) + 2 ; i += 2) {
   1096     __ mov(R3, ShifterOperand(i & 0xff));
   1097   }
   1098   __ Bind(&l1);
   1099   __ mov(R1, ShifterOperand(R2));
   1100 
   1101   size_t cs = __ CodeSize();
   1102   std::vector<uint8_t> managed_code(cs);
   1103   MemoryRegion code(&managed_code[0], managed_code.size());
   1104   __ FinalizeInstructions(code);
   1105   dump(managed_code, "Branch32");
   1106   delete assembler;
   1107 }
   1108 
   1109 TEST(Thumb2AssemblerTest, CompareAndBranchMax) {
   1110   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
   1111 
   1112   Label l1;
   1113   __ cbz(R4, &l1);
   1114   for (int i = 0 ; i < (1 << 7) ; i += 2) {
   1115     __ mov(R3, ShifterOperand(i & 0xff));
   1116   }
   1117   __ Bind(&l1);
   1118   __ mov(R1, ShifterOperand(R2));
   1119 
   1120   size_t cs = __ CodeSize();
   1121   std::vector<uint8_t> managed_code(cs);
   1122   MemoryRegion code(&managed_code[0], managed_code.size());
   1123   __ FinalizeInstructions(code);
   1124   dump(managed_code, "CompareAndBranchMax");
   1125   delete assembler;
   1126 }
   1127 
   1128 TEST(Thumb2AssemblerTest, CompareAndBranchRelocation16) {
   1129   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
   1130 
   1131   Label l1;
   1132   __ cbz(R4, &l1);
   1133   for (int i = 0 ; i < (1 << 7) + 2 ; i += 2) {
   1134     __ mov(R3, ShifterOperand(i & 0xff));
   1135   }
   1136   __ Bind(&l1);
   1137   __ mov(R1, ShifterOperand(R2));
   1138 
   1139   size_t cs = __ CodeSize();
   1140   std::vector<uint8_t> managed_code(cs);
   1141   MemoryRegion code(&managed_code[0], managed_code.size());
   1142   __ FinalizeInstructions(code);
   1143   dump(managed_code, "CompareAndBranchRelocation16");
   1144   delete assembler;
   1145 }
   1146 
   1147 TEST(Thumb2AssemblerTest, CompareAndBranchRelocation32) {
   1148   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
   1149 
   1150   Label l1;
   1151   __ cbz(R4, &l1);
   1152   for (int i = 0 ; i < (1 << 11) + 2 ; i += 2) {
   1153     __ mov(R3, ShifterOperand(i & 0xff));
   1154   }
   1155   __ Bind(&l1);
   1156   __ mov(R1, ShifterOperand(R2));
   1157 
   1158   size_t cs = __ CodeSize();
   1159   std::vector<uint8_t> managed_code(cs);
   1160   MemoryRegion code(&managed_code[0], managed_code.size());
   1161   __ FinalizeInstructions(code);
   1162   dump(managed_code, "CompareAndBranchRelocation32");
   1163   delete assembler;
   1164 }
   1165 
   1166 TEST(Thumb2AssemblerTest, MixedBranch32) {
   1167   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
   1168 
   1169   Label l1;
   1170   Label l2;
   1171   __ b(&l1);      // Forwards.
   1172   __ Bind(&l2);
   1173 
   1174   // Space to force relocation.
   1175   for (int i = 0 ; i < (1 << 11) + 2 ; i += 2) {
   1176     __ mov(R3, ShifterOperand(i & 0xff));
   1177   }
   1178   __ b(&l2);      // Backwards.
   1179   __ Bind(&l1);
   1180   __ mov(R1, ShifterOperand(R2));
   1181 
   1182   size_t cs = __ CodeSize();
   1183   std::vector<uint8_t> managed_code(cs);
   1184   MemoryRegion code(&managed_code[0], managed_code.size());
   1185   __ FinalizeInstructions(code);
   1186   dump(managed_code, "MixedBranch32");
   1187   delete assembler;
   1188 }
   1189 
   1190 TEST(Thumb2AssemblerTest, Shifts) {
   1191   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
   1192 
   1193   // 16 bit
   1194   __ Lsl(R0, R1, 5);
   1195   __ Lsr(R0, R1, 5);
   1196   __ Asr(R0, R1, 5);
   1197 
   1198   __ Lsl(R0, R0, R1);
   1199   __ Lsr(R0, R0, R1);
   1200   __ Asr(R0, R0, R1);
   1201 
   1202   // 32 bit due to high registers.
   1203   __ Lsl(R8, R1, 5);
   1204   __ Lsr(R0, R8, 5);
   1205   __ Asr(R8, R1, 5);
   1206   __ Ror(R0, R8, 5);
   1207 
   1208   // 32 bit due to different Rd and Rn.
   1209   __ Lsl(R0, R1, R2);
   1210   __ Lsr(R0, R1, R2);
   1211   __ Asr(R0, R1, R2);
   1212   __ Ror(R0, R1, R2);
   1213 
   1214   // 32 bit due to use of high registers.
   1215   __ Lsl(R8, R1, R2);
   1216   __ Lsr(R0, R8, R2);
   1217   __ Asr(R0, R1, R8);
   1218 
   1219   // S bit (all 32 bit)
   1220 
   1221   // 32 bit due to high registers.
   1222   __ Lsl(R8, R1, 5, true);
   1223   __ Lsr(R0, R8, 5, true);
   1224   __ Asr(R8, R1, 5, true);
   1225   __ Ror(R0, R8, 5, true);
   1226 
   1227   // 32 bit due to different Rd and Rn.
   1228   __ Lsl(R0, R1, R2, true);
   1229   __ Lsr(R0, R1, R2, true);
   1230   __ Asr(R0, R1, R2, true);
   1231   __ Ror(R0, R1, R2, true);
   1232 
   1233   // 32 bit due to use of high registers.
   1234   __ Lsl(R8, R1, R2, true);
   1235   __ Lsr(R0, R8, R2, true);
   1236   __ Asr(R0, R1, R8, true);
   1237 
   1238   size_t cs = __ CodeSize();
   1239   std::vector<uint8_t> managed_code(cs);
   1240   MemoryRegion code(&managed_code[0], managed_code.size());
   1241   __ FinalizeInstructions(code);
   1242   dump(managed_code, "Shifts");
   1243   delete assembler;
   1244 }
   1245 
   1246 TEST(Thumb2AssemblerTest, LoadStoreRegOffset) {
   1247   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
   1248 
   1249   // 16 bit.
   1250   __ ldr(R0, Address(R1, R2));
   1251   __ str(R0, Address(R1, R2));
   1252 
   1253   // 32 bit due to shift.
   1254   __ ldr(R0, Address(R1, R2, LSL, 1));
   1255   __ str(R0, Address(R1, R2, LSL, 1));
   1256 
   1257   __ ldr(R0, Address(R1, R2, LSL, 3));
   1258   __ str(R0, Address(R1, R2, LSL, 3));
   1259 
   1260   // 32 bit due to high register use.
   1261   __ ldr(R8, Address(R1, R2));
   1262   __ str(R8, Address(R1, R2));
   1263 
   1264   __ ldr(R1, Address(R8, R2));
   1265   __ str(R2, Address(R8, R2));
   1266 
   1267   __ ldr(R0, Address(R1, R8));
   1268   __ str(R0, Address(R1, R8));
   1269 
   1270   size_t cs = __ CodeSize();
   1271   std::vector<uint8_t> managed_code(cs);
   1272   MemoryRegion code(&managed_code[0], managed_code.size());
   1273   __ FinalizeInstructions(code);
   1274   dump(managed_code, "LoadStoreRegOffset");
   1275   delete assembler;
   1276 }
   1277 
   1278 TEST(Thumb2AssemblerTest, LoadStoreLiteral) {
   1279   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
   1280 
   1281   __ ldr(R0, Address(4));
   1282   __ str(R0, Address(4));
   1283 
   1284   __ ldr(R0, Address(-8));
   1285   __ str(R0, Address(-8));
   1286 
   1287   // Limits.
   1288   __ ldr(R0, Address(0x3ff));       // 10 bits (16 bit).
   1289   __ ldr(R0, Address(0x7ff));       // 11 bits (32 bit).
   1290   __ str(R0, Address(0x3ff));       // 32 bit (no 16 bit str(literal)).
   1291   __ str(R0, Address(0x7ff));       // 11 bits (32 bit).
   1292 
   1293   size_t cs = __ CodeSize();
   1294   std::vector<uint8_t> managed_code(cs);
   1295   MemoryRegion code(&managed_code[0], managed_code.size());
   1296   __ FinalizeInstructions(code);
   1297   dump(managed_code, "LoadStoreLiteral");
   1298   delete assembler;
   1299 }
   1300 
   1301 TEST(Thumb2AssemblerTest, LoadStoreLimits) {
   1302   arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
   1303 
   1304   __ ldr(R0, Address(R4, 124));     // 16 bit.
   1305   __ ldr(R0, Address(R4, 128));     // 32 bit.
   1306 
   1307   __ ldrb(R0, Address(R4, 31));     // 16 bit.
   1308   __ ldrb(R0, Address(R4, 32));     // 32 bit.
   1309 
   1310   __ ldrh(R0, Address(R4, 62));     // 16 bit.
   1311   __ ldrh(R0, Address(R4, 64));     // 32 bit.
   1312 
   1313   __ ldrsb(R0, Address(R4, 31));     // 32 bit.
   1314   __ ldrsb(R0, Address(R4, 32));     // 32 bit.
   1315 
   1316   __ ldrsh(R0, Address(R4, 62));     // 32 bit.
   1317   __ ldrsh(R0, Address(R4, 64));     // 32 bit.
   1318 
   1319   __ str(R0, Address(R4, 124));     // 16 bit.
   1320   __ str(R0, Address(R4, 128));     // 32 bit.
   1321 
   1322   __ strb(R0, Address(R4, 31));     // 16 bit.
   1323   __ strb(R0, Address(R4, 32));     // 32 bit.
   1324 
   1325   __ strh(R0, Address(R4, 62));     // 16 bit.
   1326   __ strh(R0, Address(R4, 64));     // 32 bit.
   1327 
   1328   size_t cs = __ CodeSize();
   1329   std::vector<uint8_t> managed_code(cs);
   1330   MemoryRegion code(&managed_code[0], managed_code.size());
   1331   __ FinalizeInstructions(code);
   1332   dump(managed_code, "LoadStoreLimits");
   1333   delete assembler;
   1334 }
   1335 
   1336 #undef __
   1337 }  // namespace arm
   1338 }  // namespace art
   1339