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