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