| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 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 |  | 
| Nicolas Geoffray | 96f89a2 | 2014-07-11 10:57:49 +0100 | [diff] [blame] | 17 | #include <dirent.h> | 
| Andreas Gampe | fd11470 | 2015-05-13 17:00:41 -0700 | [diff] [blame] | 18 | #include <errno.h> | 
| Andreas Gampe | fd11470 | 2015-05-13 17:00:41 -0700 | [diff] [blame] | 19 | #include <string.h> | 
 | 20 | #include <sys/types.h> | 
| Andreas Gampe | 8cf9cb3 | 2017-07-19 09:28:38 -0700 | [diff] [blame] | 21 | #include <fstream> | 
 | 22 | #include <map> | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 23 |  | 
 | 24 | #include "gtest/gtest.h" | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 25 |  | 
 | 26 | #include "jni/quick/calling_convention.h" | 
 | 27 | #include "utils/arm/jni_macro_assembler_arm_vixl.h" | 
 | 28 |  | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 29 | #include "base/hex_dump.h" | 
| David Sehr | 3215fff | 2018-04-03 17:10:12 -0700 | [diff] [blame] | 30 | #include "base/malloc_arena_pool.h" | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 31 | #include "common_runtime_test.h" | 
 | 32 |  | 
 | 33 | namespace art { | 
 | 34 | namespace arm { | 
 | 35 |  | 
 | 36 | // Include results file (generated manually) | 
 | 37 | #include "assembler_thumb_test_expected.cc.inc" | 
 | 38 |  | 
| Bilyan Borisov | bb661c0 | 2016-04-04 16:27:32 +0100 | [diff] [blame] | 39 | #ifndef ART_TARGET_ANDROID | 
| Dave Allison | 45fdb93 | 2014-06-25 12:37:10 -0700 | [diff] [blame] | 40 | // This controls whether the results are printed to the | 
 | 41 | // screen or compared against the expected output. | 
 | 42 | // To generate new expected output, set this to true and | 
 | 43 | // copy the output into the .cc.inc file in the form | 
 | 44 | // of the other results. | 
 | 45 | // | 
 | 46 | // When this is false, the results are not printed to the | 
 | 47 | // output, but are compared against the expected results | 
 | 48 | // in the .cc.inc file. | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 49 | static constexpr bool kPrintResults = false; | 
| Dave Allison | d20ddb2 | 2014-06-05 14:16:30 -0700 | [diff] [blame] | 50 | #endif | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 51 |  | 
 | 52 | void SetAndroidData() { | 
 | 53 |   const char* data = getenv("ANDROID_DATA"); | 
 | 54 |   if (data == nullptr) { | 
 | 55 |     setenv("ANDROID_DATA", "/tmp", 1); | 
 | 56 |   } | 
 | 57 | } | 
 | 58 |  | 
| Dave Allison | 45fdb93 | 2014-06-25 12:37:10 -0700 | [diff] [blame] | 59 | int CompareIgnoringSpace(const char* s1, const char* s2) { | 
 | 60 |   while (*s1 != '\0') { | 
 | 61 |     while (isspace(*s1)) ++s1; | 
 | 62 |     while (isspace(*s2)) ++s2; | 
 | 63 |     if (*s1 == '\0' || *s1 != *s2) { | 
 | 64 |       break; | 
 | 65 |     } | 
 | 66 |     ++s1; | 
 | 67 |     ++s2; | 
 | 68 |   } | 
 | 69 |   return *s1 - *s2; | 
 | 70 | } | 
 | 71 |  | 
| Vladimir Marko | cf93a5c | 2015-06-16 11:33:24 +0000 | [diff] [blame] | 72 | void InitResults() { | 
 | 73 |   if (test_results.empty()) { | 
 | 74 |     setup_results(); | 
 | 75 |   } | 
 | 76 | } | 
 | 77 |  | 
 | 78 | std::string GetToolsDir() { | 
| Bilyan Borisov | bb661c0 | 2016-04-04 16:27:32 +0100 | [diff] [blame] | 79 | #ifndef ART_TARGET_ANDROID | 
| Vladimir Marko | cf93a5c | 2015-06-16 11:33:24 +0000 | [diff] [blame] | 80 |   // This will only work on the host.  There is no as, objcopy or objdump on the device. | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 81 |   static std::string toolsdir; | 
 | 82 |  | 
| Vladimir Marko | cf93a5c | 2015-06-16 11:33:24 +0000 | [diff] [blame] | 83 |   if (toolsdir.empty()) { | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 84 |     setup_results(); | 
| Vladimir Marko | 33bff25 | 2017-11-01 14:35:42 +0000 | [diff] [blame] | 85 |     toolsdir = CommonRuntimeTest::GetAndroidTargetToolsDir(InstructionSet::kThumb2); | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 86 |     SetAndroidData(); | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 87 |   } | 
 | 88 |  | 
| Vladimir Marko | cf93a5c | 2015-06-16 11:33:24 +0000 | [diff] [blame] | 89 |   return toolsdir; | 
 | 90 | #else | 
 | 91 |   return std::string(); | 
 | 92 | #endif | 
 | 93 | } | 
 | 94 |  | 
 | 95 | void DumpAndCheck(std::vector<uint8_t>& code, const char* testname, const char* const* results) { | 
| Bilyan Borisov | bb661c0 | 2016-04-04 16:27:32 +0100 | [diff] [blame] | 96 | #ifndef ART_TARGET_ANDROID | 
| Vladimir Marko | cf93a5c | 2015-06-16 11:33:24 +0000 | [diff] [blame] | 97 |   static std::string toolsdir = GetToolsDir(); | 
 | 98 |  | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 99 |   ScratchFile file; | 
 | 100 |  | 
 | 101 |   const char* filename = file.GetFilename().c_str(); | 
 | 102 |  | 
 | 103 |   std::ofstream out(filename); | 
 | 104 |   if (out) { | 
 | 105 |     out << ".section \".text\"\n"; | 
 | 106 |     out << ".syntax unified\n"; | 
 | 107 |     out << ".arch armv7-a\n"; | 
 | 108 |     out << ".thumb\n"; | 
 | 109 |     out << ".thumb_func\n"; | 
 | 110 |     out << ".type " << testname << ", #function\n"; | 
 | 111 |     out << ".global " << testname << "\n"; | 
 | 112 |     out << testname << ":\n"; | 
 | 113 |     out << ".fnstart\n"; | 
 | 114 |  | 
 | 115 |     for (uint32_t i = 0 ; i < code.size(); ++i) { | 
 | 116 |       out << ".byte " << (static_cast<int>(code[i]) & 0xff) << "\n"; | 
 | 117 |     } | 
 | 118 |     out << ".fnend\n"; | 
 | 119 |     out << ".size " << testname << ", .-" << testname << "\n"; | 
 | 120 |   } | 
 | 121 |   out.close(); | 
 | 122 |  | 
| Andreas Gampe | 4470c1d | 2014-07-21 18:32:59 -0700 | [diff] [blame] | 123 |   char cmd[1024]; | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 124 |  | 
 | 125 |   // Assemble the .S | 
| David Srbecky | 3e52aa4 | 2015-04-12 07:45:18 +0100 | [diff] [blame] | 126 |   snprintf(cmd, sizeof(cmd), "%sas %s -o %s.o", toolsdir.c_str(), filename, filename); | 
| Andreas Gampe | fd11470 | 2015-05-13 17:00:41 -0700 | [diff] [blame] | 127 |   int cmd_result = system(cmd); | 
 | 128 |   ASSERT_EQ(cmd_result, 0) << strerror(errno); | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 129 |  | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 130 |   // Disassemble. | 
| Rahul Chaudhry | 956dac2 | 2017-09-27 16:33:40 -0700 | [diff] [blame] | 131 |   snprintf(cmd, sizeof(cmd), "%sobjdump -D -M force-thumb --section=.text %s.o  | grep '^  *[0-9a-f][0-9a-f]*:'", | 
| David Srbecky | 3e52aa4 | 2015-04-12 07:45:18 +0100 | [diff] [blame] | 132 |     toolsdir.c_str(), filename); | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 133 |   if (kPrintResults) { | 
 | 134 |     // Print the results only, don't check. This is used to generate new output for inserting | 
| Vladimir Marko | f5c09c3 | 2015-12-17 12:08:08 +0000 | [diff] [blame] | 135 |     // into the .inc file, so let's add the appropriate prefix/suffix needed in the C++ code. | 
 | 136 |     strcat(cmd, " | sed '-es/^/  \"/' | sed '-es/$/\\\\n\",/'"); | 
| Andreas Gampe | fd11470 | 2015-05-13 17:00:41 -0700 | [diff] [blame] | 137 |     int cmd_result3 = system(cmd); | 
 | 138 |     ASSERT_EQ(cmd_result3, 0) << strerror(errno); | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 139 |   } else { | 
 | 140 |     // Check the results match the appropriate results in the .inc file. | 
 | 141 |     FILE *fp = popen(cmd, "r"); | 
 | 142 |     ASSERT_TRUE(fp != nullptr); | 
 | 143 |  | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 144 |     uint32_t lineindex = 0; | 
 | 145 |  | 
 | 146 |     while (!feof(fp)) { | 
 | 147 |       char testline[256]; | 
 | 148 |       char *s = fgets(testline, sizeof(testline), fp); | 
 | 149 |       if (s == nullptr) { | 
 | 150 |         break; | 
 | 151 |       } | 
| Vladimir Marko | cf93a5c | 2015-06-16 11:33:24 +0000 | [diff] [blame] | 152 |       if (CompareIgnoringSpace(results[lineindex], testline) != 0) { | 
| Dave Allison | 45fdb93 | 2014-06-25 12:37:10 -0700 | [diff] [blame] | 153 |         LOG(FATAL) << "Output is not as expected at line: " << lineindex | 
| Igor Murashkin | af1e299 | 2016-10-12 17:44:50 -0700 | [diff] [blame] | 154 |           << results[lineindex] << "/" << testline << ", test name: " << testname; | 
| Dave Allison | 45fdb93 | 2014-06-25 12:37:10 -0700 | [diff] [blame] | 155 |       } | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 156 |       ++lineindex; | 
 | 157 |     } | 
 | 158 |     // Check that we are at the end. | 
| Vladimir Marko | cf93a5c | 2015-06-16 11:33:24 +0000 | [diff] [blame] | 159 |     ASSERT_TRUE(results[lineindex] == nullptr); | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 160 |     fclose(fp); | 
 | 161 |   } | 
 | 162 |  | 
 | 163 |   char buf[FILENAME_MAX]; | 
 | 164 |   snprintf(buf, sizeof(buf), "%s.o", filename); | 
 | 165 |   unlink(buf); | 
| Bilyan Borisov | bb661c0 | 2016-04-04 16:27:32 +0100 | [diff] [blame] | 166 | #endif  // ART_TARGET_ANDROID | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 167 | } | 
 | 168 |  | 
| Vladimir Marko | 0e851e2 | 2016-08-25 18:17:56 +0100 | [diff] [blame] | 169 | class ArmVIXLAssemblerTest : public ::testing::Test { | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 170 |  public: | 
| Vladimir Marko | 69d310e | 2017-10-09 14:12:23 +0100 | [diff] [blame] | 171 |   ArmVIXLAssemblerTest() : pool(), allocator(&pool), assembler(&allocator) { } | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 172 |  | 
| David Sehr | 3215fff | 2018-04-03 17:10:12 -0700 | [diff] [blame] | 173 |   MallocArenaPool pool; | 
| Vladimir Marko | 69d310e | 2017-10-09 14:12:23 +0100 | [diff] [blame] | 174 |   ArenaAllocator allocator; | 
| Roland Levillain | c043d00 | 2017-07-14 16:39:16 +0100 | [diff] [blame] | 175 |   ArmVIXLJNIMacroAssembler assembler; | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 176 | }; | 
 | 177 |  | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 178 | #define __ assembler-> | 
 | 179 |  | 
| Roland Levillain | c043d00 | 2017-07-14 16:39:16 +0100 | [diff] [blame] | 180 | void EmitAndCheck(ArmVIXLJNIMacroAssembler* assembler, const char* testname, | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 181 |                   const char* const* results) { | 
 | 182 |   __ FinalizeCode(); | 
 | 183 |   size_t cs = __ CodeSize(); | 
 | 184 |   std::vector<uint8_t> managed_code(cs); | 
 | 185 |   MemoryRegion code(&managed_code[0], managed_code.size()); | 
 | 186 |   __ FinalizeInstructions(code); | 
 | 187 |  | 
 | 188 |   DumpAndCheck(managed_code, testname, results); | 
 | 189 | } | 
 | 190 |  | 
| Roland Levillain | c043d00 | 2017-07-14 16:39:16 +0100 | [diff] [blame] | 191 | void EmitAndCheck(ArmVIXLJNIMacroAssembler* assembler, const char* testname) { | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 192 |   InitResults(); | 
 | 193 |   std::map<std::string, const char* const*>::iterator results = test_results.find(testname); | 
 | 194 |   ASSERT_NE(results, test_results.end()); | 
 | 195 |  | 
 | 196 |   EmitAndCheck(assembler, testname, results->second); | 
 | 197 | } | 
 | 198 |  | 
 | 199 | #undef __ | 
| Roland Levillain | c043d00 | 2017-07-14 16:39:16 +0100 | [diff] [blame] | 200 |  | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 201 | #define __ assembler. | 
 | 202 |  | 
| Vladimir Marko | 0e851e2 | 2016-08-25 18:17:56 +0100 | [diff] [blame] | 203 | TEST_F(ArmVIXLAssemblerTest, VixlJniHelpers) { | 
| Roland Levillain | 6d729a7 | 2017-06-30 18:34:01 +0100 | [diff] [blame] | 204 |   // Run the test only with Baker read barriers, as the expected | 
 | 205 |   // generated code contains a Marking Register refresh instruction. | 
 | 206 |   TEST_DISABLED_WITHOUT_BAKER_READ_BARRIERS(); | 
 | 207 |  | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 208 |   const bool is_static = true; | 
 | 209 |   const bool is_synchronized = false; | 
| Igor Murashkin | 367f3dd | 2016-09-01 17:00:24 -0700 | [diff] [blame] | 210 |   const bool is_critical_native = false; | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 211 |   const char* shorty = "IIFII"; | 
 | 212 |  | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 213 |   std::unique_ptr<JniCallingConvention> jni_conv( | 
| Vladimir Marko | 69d310e | 2017-10-09 14:12:23 +0100 | [diff] [blame] | 214 |       JniCallingConvention::Create(&allocator, | 
| Igor Murashkin | 367f3dd | 2016-09-01 17:00:24 -0700 | [diff] [blame] | 215 |                                    is_static, | 
 | 216 |                                    is_synchronized, | 
 | 217 |                                    is_critical_native, | 
 | 218 |                                    shorty, | 
| Vladimir Marko | 33bff25 | 2017-11-01 14:35:42 +0000 | [diff] [blame] | 219 |                                    InstructionSet::kThumb2)); | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 220 |   std::unique_ptr<ManagedRuntimeCallingConvention> mr_conv( | 
| Vladimir Marko | 69d310e | 2017-10-09 14:12:23 +0100 | [diff] [blame] | 221 |       ManagedRuntimeCallingConvention::Create( | 
| Vladimir Marko | 33bff25 | 2017-11-01 14:35:42 +0000 | [diff] [blame] | 222 |           &allocator, is_static, is_synchronized, shorty, InstructionSet::kThumb2)); | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 223 |   const int frame_size(jni_conv->FrameSize()); | 
 | 224 |   ArrayRef<const ManagedRegister> callee_save_regs = jni_conv->CalleeSaveRegisters(); | 
 | 225 |  | 
 | 226 |   const ManagedRegister method_register = ArmManagedRegister::FromCoreRegister(R0); | 
 | 227 |   const ManagedRegister scratch_register = ArmManagedRegister::FromCoreRegister(R12); | 
 | 228 |  | 
 | 229 |   __ BuildFrame(frame_size, mr_conv->MethodRegister(), callee_save_regs, mr_conv->EntrySpills()); | 
 | 230 |   __ IncreaseFrameSize(32); | 
 | 231 |  | 
 | 232 |   // Loads | 
 | 233 |   __ IncreaseFrameSize(4096); | 
 | 234 |   __ Load(method_register, FrameOffset(32), 4); | 
 | 235 |   __ Load(method_register, FrameOffset(124), 4); | 
 | 236 |   __ Load(method_register, FrameOffset(132), 4); | 
 | 237 |   __ Load(method_register, FrameOffset(1020), 4); | 
 | 238 |   __ Load(method_register, FrameOffset(1024), 4); | 
 | 239 |   __ Load(scratch_register, FrameOffset(4092), 4); | 
 | 240 |   __ Load(scratch_register, FrameOffset(4096), 4); | 
 | 241 |   __ LoadRawPtrFromThread(scratch_register, ThreadOffset32(512)); | 
| Vladimir Marko | 0e851e2 | 2016-08-25 18:17:56 +0100 | [diff] [blame] | 242 |   __ LoadRef(method_register, scratch_register, MemberOffset(128), /* unpoison_reference */ false); | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 243 |  | 
 | 244 |   // Stores | 
 | 245 |   __ Store(FrameOffset(32), method_register, 4); | 
 | 246 |   __ Store(FrameOffset(124), method_register, 4); | 
 | 247 |   __ Store(FrameOffset(132), method_register, 4); | 
 | 248 |   __ Store(FrameOffset(1020), method_register, 4); | 
 | 249 |   __ Store(FrameOffset(1024), method_register, 4); | 
 | 250 |   __ Store(FrameOffset(4092), scratch_register, 4); | 
 | 251 |   __ Store(FrameOffset(4096), scratch_register, 4); | 
 | 252 |   __ StoreImmediateToFrame(FrameOffset(48), 0xFF, scratch_register); | 
 | 253 |   __ StoreImmediateToFrame(FrameOffset(48), 0xFFFFFF, scratch_register); | 
 | 254 |   __ StoreRawPtr(FrameOffset(48), scratch_register); | 
 | 255 |   __ StoreRef(FrameOffset(48), scratch_register); | 
 | 256 |   __ StoreSpanning(FrameOffset(48), method_register, FrameOffset(48), scratch_register); | 
 | 257 |   __ StoreStackOffsetToThread(ThreadOffset32(512), FrameOffset(4096), scratch_register); | 
 | 258 |   __ StoreStackPointerToThread(ThreadOffset32(512)); | 
 | 259 |  | 
 | 260 |   // Other | 
 | 261 |   __ Call(method_register, FrameOffset(48), scratch_register); | 
 | 262 |   __ Copy(FrameOffset(48), FrameOffset(44), scratch_register, 4); | 
 | 263 |   __ CopyRawPtrFromThread(FrameOffset(44), ThreadOffset32(512), scratch_register); | 
 | 264 |   __ CopyRef(FrameOffset(48), FrameOffset(44), scratch_register); | 
 | 265 |   __ GetCurrentThread(method_register); | 
 | 266 |   __ GetCurrentThread(FrameOffset(48), scratch_register); | 
 | 267 |   __ Move(scratch_register, method_register, 4); | 
 | 268 |   __ VerifyObject(scratch_register, false); | 
 | 269 |  | 
 | 270 |   __ CreateHandleScopeEntry(scratch_register, FrameOffset(48), scratch_register, true); | 
 | 271 |   __ CreateHandleScopeEntry(scratch_register, FrameOffset(48), scratch_register, false); | 
 | 272 |   __ CreateHandleScopeEntry(method_register, FrameOffset(48), scratch_register, true); | 
 | 273 |   __ CreateHandleScopeEntry(FrameOffset(48), FrameOffset(64), scratch_register, true); | 
 | 274 |   __ CreateHandleScopeEntry(method_register, FrameOffset(0), scratch_register, true); | 
 | 275 |   __ CreateHandleScopeEntry(method_register, FrameOffset(1025), scratch_register, true); | 
 | 276 |   __ CreateHandleScopeEntry(scratch_register, FrameOffset(1025), scratch_register, true); | 
 | 277 |  | 
 | 278 |   __ ExceptionPoll(scratch_register, 0); | 
 | 279 |  | 
| Artem Serov | 8f840f8 | 2016-12-15 17:56:27 +0000 | [diff] [blame] | 280 |   // Push the target out of range of branch emitted by ExceptionPoll. | 
 | 281 |   for (int i = 0; i < 64; i++) { | 
 | 282 |     __ Store(FrameOffset(2047), scratch_register, 4); | 
 | 283 |   } | 
 | 284 |  | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 285 |   __ DecreaseFrameSize(4096); | 
 | 286 |   __ DecreaseFrameSize(32); | 
| Roland Levillain | 0d127e1 | 2017-07-05 17:01:11 +0100 | [diff] [blame] | 287 |   __ RemoveFrame(frame_size, callee_save_regs, /* may_suspend */ true); | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 288 |  | 
 | 289 |   EmitAndCheck(&assembler, "VixlJniHelpers"); | 
 | 290 | } | 
 | 291 |  | 
| Roland Levillain | c043d00 | 2017-07-14 16:39:16 +0100 | [diff] [blame] | 292 | #undef __ | 
 | 293 |  | 
 | 294 | // TODO: Avoid these macros. | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 295 | #define R0 vixl::aarch32::r0 | 
 | 296 | #define R2 vixl::aarch32::r2 | 
 | 297 | #define R4 vixl::aarch32::r4 | 
 | 298 | #define R12 vixl::aarch32::r12 | 
| Roland Levillain | c043d00 | 2017-07-14 16:39:16 +0100 | [diff] [blame] | 299 |  | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 300 | #define __ assembler.asm_. | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 301 |  | 
| Vladimir Marko | 0e851e2 | 2016-08-25 18:17:56 +0100 | [diff] [blame] | 302 | TEST_F(ArmVIXLAssemblerTest, VixlLoadFromOffset) { | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 303 |   __ LoadFromOffset(kLoadWord, R2, R4, 12); | 
 | 304 |   __ LoadFromOffset(kLoadWord, R2, R4, 0xfff); | 
 | 305 |   __ LoadFromOffset(kLoadWord, R2, R4, 0x1000); | 
 | 306 |   __ LoadFromOffset(kLoadWord, R2, R4, 0x1000a4); | 
 | 307 |   __ LoadFromOffset(kLoadWord, R2, R4, 0x101000); | 
 | 308 |   __ LoadFromOffset(kLoadWord, R4, R4, 0x101000); | 
 | 309 |   __ LoadFromOffset(kLoadUnsignedHalfword, R2, R4, 12); | 
 | 310 |   __ LoadFromOffset(kLoadUnsignedHalfword, R2, R4, 0xfff); | 
 | 311 |   __ LoadFromOffset(kLoadUnsignedHalfword, R2, R4, 0x1000); | 
 | 312 |   __ LoadFromOffset(kLoadUnsignedHalfword, R2, R4, 0x1000a4); | 
 | 313 |   __ LoadFromOffset(kLoadUnsignedHalfword, R2, R4, 0x101000); | 
 | 314 |   __ LoadFromOffset(kLoadUnsignedHalfword, R4, R4, 0x101000); | 
 | 315 |   __ LoadFromOffset(kLoadWordPair, R2, R4, 12); | 
 | 316 |   __ LoadFromOffset(kLoadWordPair, R2, R4, 0x3fc); | 
 | 317 |   __ LoadFromOffset(kLoadWordPair, R2, R4, 0x400); | 
 | 318 |   __ LoadFromOffset(kLoadWordPair, R2, R4, 0x400a4); | 
 | 319 |   __ LoadFromOffset(kLoadWordPair, R2, R4, 0x40400); | 
 | 320 |   __ LoadFromOffset(kLoadWordPair, R4, R4, 0x40400); | 
 | 321 |  | 
| Scott Wakeling | b77051e | 2016-11-21 19:46:00 +0000 | [diff] [blame] | 322 |   vixl::aarch32::UseScratchRegisterScope temps(assembler.asm_.GetVIXLAssembler()); | 
 | 323 |   temps.Exclude(R12); | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 324 |   __ LoadFromOffset(kLoadWord, R0, R12, 12);  // 32-bit because of R12. | 
| Scott Wakeling | b77051e | 2016-11-21 19:46:00 +0000 | [diff] [blame] | 325 |   temps.Include(R12); | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 326 |   __ LoadFromOffset(kLoadWord, R2, R4, 0xa4 - 0x100000); | 
 | 327 |  | 
 | 328 |   __ LoadFromOffset(kLoadSignedByte, R2, R4, 12); | 
 | 329 |   __ LoadFromOffset(kLoadUnsignedByte, R2, R4, 12); | 
 | 330 |   __ LoadFromOffset(kLoadSignedHalfword, R2, R4, 12); | 
 | 331 |  | 
 | 332 |   EmitAndCheck(&assembler, "VixlLoadFromOffset"); | 
 | 333 | } | 
 | 334 |  | 
| Vladimir Marko | 0e851e2 | 2016-08-25 18:17:56 +0100 | [diff] [blame] | 335 | TEST_F(ArmVIXLAssemblerTest, VixlStoreToOffset) { | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 336 |   __ StoreToOffset(kStoreWord, R2, R4, 12); | 
 | 337 |   __ StoreToOffset(kStoreWord, R2, R4, 0xfff); | 
 | 338 |   __ StoreToOffset(kStoreWord, R2, R4, 0x1000); | 
 | 339 |   __ StoreToOffset(kStoreWord, R2, R4, 0x1000a4); | 
 | 340 |   __ StoreToOffset(kStoreWord, R2, R4, 0x101000); | 
 | 341 |   __ StoreToOffset(kStoreWord, R4, R4, 0x101000); | 
 | 342 |   __ StoreToOffset(kStoreHalfword, R2, R4, 12); | 
 | 343 |   __ StoreToOffset(kStoreHalfword, R2, R4, 0xfff); | 
 | 344 |   __ StoreToOffset(kStoreHalfword, R2, R4, 0x1000); | 
 | 345 |   __ StoreToOffset(kStoreHalfword, R2, R4, 0x1000a4); | 
 | 346 |   __ StoreToOffset(kStoreHalfword, R2, R4, 0x101000); | 
 | 347 |   __ StoreToOffset(kStoreHalfword, R4, R4, 0x101000); | 
 | 348 |   __ StoreToOffset(kStoreWordPair, R2, R4, 12); | 
 | 349 |   __ StoreToOffset(kStoreWordPair, R2, R4, 0x3fc); | 
 | 350 |   __ StoreToOffset(kStoreWordPair, R2, R4, 0x400); | 
 | 351 |   __ StoreToOffset(kStoreWordPair, R2, R4, 0x400a4); | 
 | 352 |   __ StoreToOffset(kStoreWordPair, R2, R4, 0x40400); | 
 | 353 |   __ StoreToOffset(kStoreWordPair, R4, R4, 0x40400); | 
 | 354 |  | 
| Scott Wakeling | b77051e | 2016-11-21 19:46:00 +0000 | [diff] [blame] | 355 |   vixl::aarch32::UseScratchRegisterScope temps(assembler.asm_.GetVIXLAssembler()); | 
 | 356 |   temps.Exclude(R12); | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 357 |   __ StoreToOffset(kStoreWord, R0, R12, 12);  // 32-bit because of R12. | 
| Scott Wakeling | b77051e | 2016-11-21 19:46:00 +0000 | [diff] [blame] | 358 |   temps.Include(R12); | 
| Artem Serov | 12e097c | 2016-08-08 15:13:26 +0100 | [diff] [blame] | 359 |   __ StoreToOffset(kStoreWord, R2, R4, 0xa4 - 0x100000); | 
 | 360 |  | 
 | 361 |   __ StoreToOffset(kStoreByte, R2, R4, 12); | 
 | 362 |  | 
 | 363 |   EmitAndCheck(&assembler, "VixlStoreToOffset"); | 
 | 364 | } | 
 | 365 |  | 
 | 366 | #undef __ | 
| Dave Allison | 65fcc2c | 2014-04-28 13:45:27 -0700 | [diff] [blame] | 367 | }  // namespace arm | 
 | 368 | }  // namespace art |