11a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain/* 21a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain * Copyright (C) 2014 The Android Open Source Project 31a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain * 41a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain * Licensed under the Apache License, Version 2.0 (the "License"); 51a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain * you may not use this file except in compliance with the License. 61a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain * You may obtain a copy of the License at 71a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain * 81a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain * http://www.apache.org/licenses/LICENSE-2.0 91a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain * 101a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain * Unless required by applicable law or agreed to in writing, software 111a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain * distributed under the License is distributed on an "AS IS" BASIS, 121a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain * See the License for the specific language governing permissions and 141a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain * limitations under the License. 151a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain */ 161a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 171a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain#include "assembler_thumb2.h" 181a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 191a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain#include "base/stl_util.h" 207cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe#include "base/stringprintf.h" 211a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain#include "utils/assembler_test.h" 221a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 231a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillainnamespace art { 241a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 251a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillainclass AssemblerThumb2Test : public AssemblerTest<arm::Thumb2Assembler, 26851df20225593b10e698a760ac3cd5243620700bAndreas Gampe arm::Register, arm::SRegister, 27851df20225593b10e698a760ac3cd5243620700bAndreas Gampe uint32_t> { 281a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain protected: 291a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain std::string GetArchitectureString() OVERRIDE { 301a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain return "arm"; 311a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain } 321a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 331a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain std::string GetAssemblerParameters() OVERRIDE { 34513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe return " -march=armv7-a -mcpu=cortex-a15 -mfpu=neon -mthumb"; 35513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe } 36513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe 37513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe const char* GetAssemblyHeader() OVERRIDE { 38513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe return kThumb2AssemblyHeader; 391a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain } 401a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 411a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain std::string GetDisassembleParameters() OVERRIDE { 42513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe return " -D -bbinary -marm --disassembler-options=force-thumb --no-show-raw-insn"; 431a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain } 441a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 451a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain void SetUpHelpers() OVERRIDE { 461a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain if (registers_.size() == 0) { 471a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain registers_.insert(end(registers_), 481a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain { // NOLINT(whitespace/braces) 491a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain new arm::Register(arm::R0), 501a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain new arm::Register(arm::R1), 511a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain new arm::Register(arm::R2), 521a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain new arm::Register(arm::R3), 531a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain new arm::Register(arm::R4), 541a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain new arm::Register(arm::R5), 551a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain new arm::Register(arm::R6), 561a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain new arm::Register(arm::R7), 571a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain new arm::Register(arm::R8), 581a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain new arm::Register(arm::R9), 591a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain new arm::Register(arm::R10), 601a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain new arm::Register(arm::R11), 611a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain new arm::Register(arm::R12), 621a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain new arm::Register(arm::R13), 631a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain new arm::Register(arm::R14), 641a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain new arm::Register(arm::R15) 651a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain }); 661a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain } 671a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain } 681a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 691a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain void TearDown() OVERRIDE { 701a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain AssemblerTest::TearDown(); 711a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain STLDeleteElements(®isters_); 721a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain } 731a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 741a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain std::vector<arm::Register*> GetRegisters() OVERRIDE { 751a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain return registers_; 761a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain } 771a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 781a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain uint32_t CreateImmediate(int64_t imm_value) OVERRIDE { 791a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain return imm_value; 801a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain } 811a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 82cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string RepeatInsn(size_t count, const std::string& insn) { 83cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string result; 84cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (; count != 0u; --count) { 85cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko result += insn; 86cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 87cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko return result; 88cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 89cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 901a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain private: 911a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain std::vector<arm::Register*> registers_; 92513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe 93513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe static constexpr const char* kThumb2AssemblyHeader = ".syntax unified\n.thumb\n"; 941a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain}; 951a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 961a28fc43ea7daa624ada9af40e30de64d4e946a8Roland LevillainTEST_F(AssemblerThumb2Test, Toolchain) { 971a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain EXPECT_TRUE(CheckTools()); 981a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain} 991a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 100c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu#define __ GetAssembler()-> 1011a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 1021a28fc43ea7daa624ada9af40e30de64d4e946a8Roland LevillainTEST_F(AssemblerThumb2Test, Sbfx) { 103c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ sbfx(arm::R0, arm::R1, 0, 1); 104c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ sbfx(arm::R0, arm::R1, 0, 8); 105c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ sbfx(arm::R0, arm::R1, 0, 16); 106c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ sbfx(arm::R0, arm::R1, 0, 32); 1071a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 108c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ sbfx(arm::R0, arm::R1, 8, 1); 109c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ sbfx(arm::R0, arm::R1, 8, 8); 110c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ sbfx(arm::R0, arm::R1, 8, 16); 111c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ sbfx(arm::R0, arm::R1, 8, 24); 1121a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 113c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ sbfx(arm::R0, arm::R1, 16, 1); 114c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ sbfx(arm::R0, arm::R1, 16, 8); 115c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ sbfx(arm::R0, arm::R1, 16, 16); 1161a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 117c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ sbfx(arm::R0, arm::R1, 31, 1); 1181a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 1191a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain const char* expected = 1201a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain "sbfx r0, r1, #0, #1\n" 1211a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain "sbfx r0, r1, #0, #8\n" 1221a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain "sbfx r0, r1, #0, #16\n" 1231a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain "sbfx r0, r1, #0, #32\n" 1241a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 1251a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain "sbfx r0, r1, #8, #1\n" 1261a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain "sbfx r0, r1, #8, #8\n" 1271a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain "sbfx r0, r1, #8, #16\n" 1281a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain "sbfx r0, r1, #8, #24\n" 1291a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 1301a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain "sbfx r0, r1, #16, #1\n" 1311a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain "sbfx r0, r1, #16, #8\n" 1321a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain "sbfx r0, r1, #16, #16\n" 1331a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 1341a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain "sbfx r0, r1, #31, #1\n"; 1351a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain DriverStr(expected, "sbfx"); 1361a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain} 1371a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain 138981e45424f52735b1c61ae0eac7e299ed313f8dbRoland LevillainTEST_F(AssemblerThumb2Test, Ubfx) { 139c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ubfx(arm::R0, arm::R1, 0, 1); 140c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ubfx(arm::R0, arm::R1, 0, 8); 141c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ubfx(arm::R0, arm::R1, 0, 16); 142c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ubfx(arm::R0, arm::R1, 0, 32); 143981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain 144c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ubfx(arm::R0, arm::R1, 8, 1); 145c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ubfx(arm::R0, arm::R1, 8, 8); 146c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ubfx(arm::R0, arm::R1, 8, 16); 147c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ubfx(arm::R0, arm::R1, 8, 24); 148981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain 149c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ubfx(arm::R0, arm::R1, 16, 1); 150c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ubfx(arm::R0, arm::R1, 16, 8); 151c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ubfx(arm::R0, arm::R1, 16, 16); 152981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain 153c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ubfx(arm::R0, arm::R1, 31, 1); 154981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain 155981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain const char* expected = 156981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain "ubfx r0, r1, #0, #1\n" 157981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain "ubfx r0, r1, #0, #8\n" 158981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain "ubfx r0, r1, #0, #16\n" 159981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain "ubfx r0, r1, #0, #32\n" 160981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain 161981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain "ubfx r0, r1, #8, #1\n" 162981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain "ubfx r0, r1, #8, #8\n" 163981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain "ubfx r0, r1, #8, #16\n" 164981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain "ubfx r0, r1, #8, #24\n" 165981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain 166981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain "ubfx r0, r1, #16, #1\n" 167981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain "ubfx r0, r1, #16, #8\n" 168981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain "ubfx r0, r1, #16, #16\n" 169981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain 170981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain "ubfx r0, r1, #31, #1\n"; 171981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain DriverStr(expected, "ubfx"); 172981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain} 173981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain 174ddb7df25af45d7cd19ed1138e537973735cc78a5Calin JuravleTEST_F(AssemblerThumb2Test, Vmstat) { 175c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ vmstat(); 176ddb7df25af45d7cd19ed1138e537973735cc78a5Calin Juravle 177ddb7df25af45d7cd19ed1138e537973735cc78a5Calin Juravle const char* expected = "vmrs APSR_nzcv, FPSCR\n"; 178ddb7df25af45d7cd19ed1138e537973735cc78a5Calin Juravle 179ddb7df25af45d7cd19ed1138e537973735cc78a5Calin Juravle DriverStr(expected, "vmrs"); 180ddb7df25af45d7cd19ed1138e537973735cc78a5Calin Juravle} 181ddb7df25af45d7cd19ed1138e537973735cc78a5Calin Juravle 18252c489645b6e9ae33623f1ec24143cde5444906eCalin JuravleTEST_F(AssemblerThumb2Test, ldrexd) { 183c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ldrexd(arm::R0, arm::R1, arm::R0); 184c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ldrexd(arm::R0, arm::R1, arm::R1); 185c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ldrexd(arm::R0, arm::R1, arm::R2); 186c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ldrexd(arm::R5, arm::R3, arm::R7); 18752c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle 18852c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle const char* expected = 18952c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle "ldrexd r0, r1, [r0]\n" 19052c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle "ldrexd r0, r1, [r1]\n" 19152c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle "ldrexd r0, r1, [r2]\n" 19252c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle "ldrexd r5, r3, [r7]\n"; 19352c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle DriverStr(expected, "ldrexd"); 19452c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle} 19552c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle 19652c489645b6e9ae33623f1ec24143cde5444906eCalin JuravleTEST_F(AssemblerThumb2Test, strexd) { 197c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ strexd(arm::R9, arm::R0, arm::R1, arm::R0); 198c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ strexd(arm::R9, arm::R0, arm::R1, arm::R1); 199c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ strexd(arm::R9, arm::R0, arm::R1, arm::R2); 200c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ strexd(arm::R9, arm::R5, arm::R3, arm::R7); 20152c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle 20252c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle const char* expected = 20352c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle "strexd r9, r0, r1, [r0]\n" 20452c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle "strexd r9, r0, r1, [r1]\n" 20552c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle "strexd r9, r0, r1, [r2]\n" 20652c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle "strexd r9, r5, r3, [r7]\n"; 20752c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle DriverStr(expected, "strexd"); 20852c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle} 20952c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle 2102bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeTEST_F(AssemblerThumb2Test, LdrdStrd) { 211c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ldrd(arm::R0, arm::Address(arm::R2, 8)); 212c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ ldrd(arm::R0, arm::Address(arm::R12)); 213c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ strd(arm::R0, arm::Address(arm::R2, 8)); 2142bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 2152bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe const char* expected = 2162bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe "ldrd r0, r1, [r2, #8]\n" 2172bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe "ldrd r0, r1, [r12]\n" 2182bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe "strd r0, r1, [r2, #8]\n"; 2192bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe DriverStr(expected, "ldrdstrd"); 2202bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe} 2212bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe 222513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas GampeTEST_F(AssemblerThumb2Test, eor) { 223513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe __ eor(arm::R1, arm::R1, arm::ShifterOperand(arm::R0)); 224513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe __ eor(arm::R1, arm::R0, arm::ShifterOperand(arm::R1)); 225513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe __ eor(arm::R1, arm::R8, arm::ShifterOperand(arm::R0)); 226513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe __ eor(arm::R8, arm::R1, arm::ShifterOperand(arm::R0)); 227513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe __ eor(arm::R1, arm::R0, arm::ShifterOperand(arm::R8)); 228513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe 229513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe const char* expected = 230513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe "eors r1, r0\n" 231513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe "eor r1, r0, r1\n" 232513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe "eor r1, r8, r0\n" 233513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe "eor r8, r1, r0\n" 234513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe "eor r1, r0, r8\n"; 235513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe DriverStr(expected, "abs"); 236513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe} 237513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe 238dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" SanchezTEST_F(AssemblerThumb2Test, sub) { 239dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez __ subs(arm::R1, arm::R0, arm::ShifterOperand(42)); 240dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez __ sub(arm::R1, arm::R0, arm::ShifterOperand(42)); 241c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ subs(arm::R1, arm::R0, arm::ShifterOperand(arm::R2, arm::ASR, 31)); 242c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ sub(arm::R1, arm::R0, arm::ShifterOperand(arm::R2, arm::ASR, 31)); 243dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez 244dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez const char* expected = 245dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez "subs r1, r0, #42\n" 2466fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko "sub.w r1, r0, #42\n" 247c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu "subs r1, r0, r2, asr #31\n" 248c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu "sub r1, r0, r2, asr #31\n"; 249dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez DriverStr(expected, "sub"); 250dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez} 251dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez 252dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" SanchezTEST_F(AssemblerThumb2Test, add) { 253dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez __ adds(arm::R1, arm::R0, arm::ShifterOperand(42)); 254dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez __ add(arm::R1, arm::R0, arm::ShifterOperand(42)); 255c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ adds(arm::R1, arm::R0, arm::ShifterOperand(arm::R2, arm::ASR, 31)); 256c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ add(arm::R1, arm::R0, arm::ShifterOperand(arm::R2, arm::ASR, 31)); 257dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez 258dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez const char* expected = 259dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez "adds r1, r0, #42\n" 2606fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko "add.w r1, r0, #42\n" 261c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu "adds r1, r0, r2, asr #31\n" 262c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu "add r1, r0, r2, asr #31\n"; 263dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez DriverStr(expected, "add"); 264dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez} 265dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez 266c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng XuTEST_F(AssemblerThumb2Test, umull) { 267c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ umull(arm::R0, arm::R1, arm::R2, arm::R3); 268c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu 269c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu const char* expected = 270c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu "umull r0, r1, r2, r3\n"; 271c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu DriverStr(expected, "umull"); 272c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu} 273c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu 274c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng XuTEST_F(AssemblerThumb2Test, smull) { 275c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu __ smull(arm::R0, arm::R1, arm::R2, arm::R3); 276c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu 277c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu const char* expected = 278c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu "smull r0, r1, r2, r3\n"; 279c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu DriverStr(expected, "smull"); 280c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu} 281c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu 282c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland LevillainTEST_F(AssemblerThumb2Test, StoreWordToThumbOffset) { 283c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain arm::StoreOperandType type = arm::kStoreWord; 284c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain int32_t offset = 4092; 285c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain ASSERT_TRUE(arm::Address::CanHoldStoreOffsetThumb(type, offset)); 286c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain 287c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain __ StoreToOffset(type, arm::R0, arm::SP, offset); 288c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain __ StoreToOffset(type, arm::IP, arm::SP, offset); 289c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain __ StoreToOffset(type, arm::IP, arm::R5, offset); 290c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain 291c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain const char* expected = 292c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain "str r0, [sp, #4092]\n" 293c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain "str ip, [sp, #4092]\n" 294c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain "str ip, [r5, #4092]\n"; 295c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain DriverStr(expected, "StoreWordToThumbOffset"); 296c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain} 297c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain 298c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland LevillainTEST_F(AssemblerThumb2Test, StoreWordToNonThumbOffset) { 299c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain arm::StoreOperandType type = arm::kStoreWord; 300c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain int32_t offset = 4096; 301c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain ASSERT_FALSE(arm::Address::CanHoldStoreOffsetThumb(type, offset)); 302c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain 303c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain __ StoreToOffset(type, arm::R0, arm::SP, offset); 304c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain __ StoreToOffset(type, arm::IP, arm::SP, offset); 305c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain __ StoreToOffset(type, arm::IP, arm::R5, offset); 306c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain 307c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain const char* expected = 3086fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko "add.w ip, sp, #4096\n" // AddConstant(ip, sp, 4096) 309c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain "str r0, [ip, #0]\n" 310c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain 3116fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko "str r5, [sp, #-4]!\n" // Push(r5) 3126fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko "add.w r5, sp, #4096\n" // AddConstant(r5, 4100 & ~0xfff) 3136fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko "str ip, [r5, #4]\n" // StoreToOffset(type, ip, r5, 4100 & 0xfff) 3146fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko "ldr r5, [sp], #4\n" // Pop(r5) 3156fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko 3166fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko "str r6, [sp, #-4]!\n" // Push(r6) 3176fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko "add.w r6, r5, #4096\n" // AddConstant(r6, r5, 4096 & ~0xfff) 3186fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko "str ip, [r6, #0]\n" // StoreToOffset(type, ip, r6, 4096 & 0xfff) 3196fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko "ldr r6, [sp], #4\n"; // Pop(r6) 320c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain DriverStr(expected, "StoreWordToNonThumbOffset"); 321c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain} 322c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain 3234af147eb3296a26eea566f53a7f687194638d46bRoland LevillainTEST_F(AssemblerThumb2Test, StoreWordPairToThumbOffset) { 3244af147eb3296a26eea566f53a7f687194638d46bRoland Levillain arm::StoreOperandType type = arm::kStoreWordPair; 3254af147eb3296a26eea566f53a7f687194638d46bRoland Levillain int32_t offset = 1020; 3264af147eb3296a26eea566f53a7f687194638d46bRoland Levillain ASSERT_TRUE(arm::Address::CanHoldStoreOffsetThumb(type, offset)); 3274af147eb3296a26eea566f53a7f687194638d46bRoland Levillain 3284af147eb3296a26eea566f53a7f687194638d46bRoland Levillain __ StoreToOffset(type, arm::R0, arm::SP, offset); 3294af147eb3296a26eea566f53a7f687194638d46bRoland Levillain // We cannot use IP (i.e. R12) as first source register, as it would 3304af147eb3296a26eea566f53a7f687194638d46bRoland Levillain // force us to use SP (i.e. R13) as second source register, which 3314af147eb3296a26eea566f53a7f687194638d46bRoland Levillain // would have an "unpredictable" effect according to the ARMv7 3324af147eb3296a26eea566f53a7f687194638d46bRoland Levillain // specification (the T1 encoding describes the result as 3334af147eb3296a26eea566f53a7f687194638d46bRoland Levillain // UNPREDICTABLE when of the source registers is R13). 3344af147eb3296a26eea566f53a7f687194638d46bRoland Levillain // 3354af147eb3296a26eea566f53a7f687194638d46bRoland Levillain // So we use (R11, IP) (e.g. (R11, R12)) as source registers in the 3364af147eb3296a26eea566f53a7f687194638d46bRoland Levillain // following instructions. 3374af147eb3296a26eea566f53a7f687194638d46bRoland Levillain __ StoreToOffset(type, arm::R11, arm::SP, offset); 3384af147eb3296a26eea566f53a7f687194638d46bRoland Levillain __ StoreToOffset(type, arm::R11, arm::R5, offset); 3394af147eb3296a26eea566f53a7f687194638d46bRoland Levillain 3404af147eb3296a26eea566f53a7f687194638d46bRoland Levillain const char* expected = 3414af147eb3296a26eea566f53a7f687194638d46bRoland Levillain "strd r0, r1, [sp, #1020]\n" 3424af147eb3296a26eea566f53a7f687194638d46bRoland Levillain "strd r11, ip, [sp, #1020]\n" 3434af147eb3296a26eea566f53a7f687194638d46bRoland Levillain "strd r11, ip, [r5, #1020]\n"; 3444af147eb3296a26eea566f53a7f687194638d46bRoland Levillain DriverStr(expected, "StoreWordPairToThumbOffset"); 3454af147eb3296a26eea566f53a7f687194638d46bRoland Levillain} 3464af147eb3296a26eea566f53a7f687194638d46bRoland Levillain 3474af147eb3296a26eea566f53a7f687194638d46bRoland LevillainTEST_F(AssemblerThumb2Test, StoreWordPairToNonThumbOffset) { 3484af147eb3296a26eea566f53a7f687194638d46bRoland Levillain arm::StoreOperandType type = arm::kStoreWordPair; 3494af147eb3296a26eea566f53a7f687194638d46bRoland Levillain int32_t offset = 1024; 3504af147eb3296a26eea566f53a7f687194638d46bRoland Levillain ASSERT_FALSE(arm::Address::CanHoldStoreOffsetThumb(type, offset)); 3514af147eb3296a26eea566f53a7f687194638d46bRoland Levillain 3524af147eb3296a26eea566f53a7f687194638d46bRoland Levillain __ StoreToOffset(type, arm::R0, arm::SP, offset); 3534af147eb3296a26eea566f53a7f687194638d46bRoland Levillain // Same comment as in AssemblerThumb2Test.StoreWordPairToThumbOffset 3544af147eb3296a26eea566f53a7f687194638d46bRoland Levillain // regarding the use of (R11, IP) (e.g. (R11, R12)) as source 3554af147eb3296a26eea566f53a7f687194638d46bRoland Levillain // registers in the following instructions. 3564af147eb3296a26eea566f53a7f687194638d46bRoland Levillain __ StoreToOffset(type, arm::R11, arm::SP, offset); 3574af147eb3296a26eea566f53a7f687194638d46bRoland Levillain __ StoreToOffset(type, arm::R11, arm::R5, offset); 3584af147eb3296a26eea566f53a7f687194638d46bRoland Levillain 3594af147eb3296a26eea566f53a7f687194638d46bRoland Levillain const char* expected = 3606fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko "add.w ip, sp, #1024\n" // AddConstant(ip, sp, 1024) 3614af147eb3296a26eea566f53a7f687194638d46bRoland Levillain "strd r0, r1, [ip, #0]\n" 3624af147eb3296a26eea566f53a7f687194638d46bRoland Levillain 3634af147eb3296a26eea566f53a7f687194638d46bRoland Levillain "str r5, [sp, #-4]!\n" // Push(r5) 3646fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko "add.w r5, sp, #1024\n" // AddConstant(r5, sp, (1024 + kRegisterSize) & ~0x3fc) 3656fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko "strd r11, ip, [r5, #4]\n" // StoreToOffset(type, r11, sp, (1024 + kRegisterSize) & 0x3fc) 3664af147eb3296a26eea566f53a7f687194638d46bRoland Levillain "ldr r5, [sp], #4\n" // Pop(r5) 3674af147eb3296a26eea566f53a7f687194638d46bRoland Levillain 3684af147eb3296a26eea566f53a7f687194638d46bRoland Levillain "str r6, [sp, #-4]!\n" // Push(r6) 3696fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko "add.w r6, r5, #1024\n" // AddConstant(r6, r5, 1024 & ~0x3fc) 3706fd0ffe8da212723a3ac0256ce350b5872cc61d4Vladimir Marko "strd r11, ip, [r6, #0]\n" // StoreToOffset(type, r11, r6, 1024 & 0x3fc) 3714af147eb3296a26eea566f53a7f687194638d46bRoland Levillain "ldr r6, [sp], #4\n"; // Pop(r6) 3724af147eb3296a26eea566f53a7f687194638d46bRoland Levillain DriverStr(expected, "StoreWordPairToNonThumbOffset"); 3734af147eb3296a26eea566f53a7f687194638d46bRoland Levillain} 3744af147eb3296a26eea566f53a7f687194638d46bRoland Levillain 375f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir MarkoTEST_F(AssemblerThumb2Test, DistantBackBranch) { 376f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko Label start, end; 377f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko __ Bind(&start); 378f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko constexpr size_t kLdrR0R0Count1 = 256; 379f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko for (size_t i = 0; i != kLdrR0R0Count1; ++i) { 380f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 381f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko } 382f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko __ b(&end, arm::EQ); 383f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko __ b(&start, arm::LT); 384f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko constexpr size_t kLdrR0R0Count2 = 256; 385f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko for (size_t i = 0; i != kLdrR0R0Count2; ++i) { 386f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 387f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko } 388f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko __ Bind(&end); 389f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko 390f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko std::string expected = 391f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko "0:\n" + 392f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko RepeatInsn(kLdrR0R0Count1, "ldr r0, [r0]\n") + 393f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko "beq 1f\n" 394f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko "blt 0b\n" + 395f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") + 396f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko "1:\n"; 397f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko DriverStr(expected, "DistantBackBranch"); 398f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko} 399f2bb04304ab545ecef67fc6b8708e3ad41a6005fVladimir Marko 400cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, TwoCbzMaxOffset) { 401cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label0, label1, label2; 402cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ cbz(arm::R0, &label1); 403cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count1 = 63; 404cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count1; ++i) { 405cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 406cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 407cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label0); 408cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ cbz(arm::R0, &label2); 409cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label1); 410cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count2 = 64; 411cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count2; ++i) { 412cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 413cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 414cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label2); 415cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 416cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 417cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "cbz r0, 1f\n" + // cbz r0, label1 418cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count1, "ldr r0, [r0]\n") + 419cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "0:\n" 420cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "cbz r0, 2f\n" // cbz r0, label2 421cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" + 422cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") + 423cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n"; 424cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "TwoCbzMaxOffset"); 425cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 426cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label0.Position()) + 0u, 427cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label0.Position())); 428cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label1.Position()) + 0u, 429cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label1.Position())); 430cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label2.Position()) + 0u, 431cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label2.Position())); 432cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 433cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 434cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, TwoCbzBeyondMaxOffset) { 435cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label0, label1, label2; 436cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ cbz(arm::R0, &label1); 437cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count1 = 63; 438cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count1; ++i) { 439cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 440cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 441cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label0); 442cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ cbz(arm::R0, &label2); 443cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label1); 444cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count2 = 65; 445cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count2; ++i) { 446cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 447cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 448cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label2); 449cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 450cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 451cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "cmp r0, #0\n" // cbz r0, label1 452cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "beq.n 1f\n" + 453cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count1, "ldr r0, [r0]\n") + 454cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "0:\n" 455cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "cmp r0, #0\n" // cbz r0, label2 456cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "beq.n 2f\n" 457cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" + 458cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") + 459cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n"; 460cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "TwoCbzBeyondMaxOffset"); 461cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 462cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label0.Position()) + 2u, 463cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label0.Position())); 464cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label1.Position()) + 4u, 465cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label1.Position())); 466cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label2.Position()) + 4u, 467cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label2.Position())); 468cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 469cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 470cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, TwoCbzSecondAtMaxB16Offset) { 471cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label0, label1, label2; 472cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ cbz(arm::R0, &label1); 473cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count1 = 62; 474cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count1; ++i) { 475cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 476cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 477cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label0); 478cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ cbz(arm::R0, &label2); 479cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label1); 480cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count2 = 128; 481cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count2; ++i) { 482cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 483cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 484cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label2); 485cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 486cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 487cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "cbz r0, 1f\n" + // cbz r0, label1 488cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count1, "ldr r0, [r0]\n") + 489cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "0:\n" 490cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "cmp r0, #0\n" // cbz r0, label2 491cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "beq.n 2f\n" 492cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" + 493cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") + 494cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n"; 495cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "TwoCbzSecondAtMaxB16Offset"); 496cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 497cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label0.Position()) + 0u, 498cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label0.Position())); 499cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label1.Position()) + 2u, 500cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label1.Position())); 501cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label2.Position()) + 2u, 502cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label2.Position())); 503cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 504cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 505cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, TwoCbzSecondBeyondMaxB16Offset) { 506cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label0, label1, label2; 507cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ cbz(arm::R0, &label1); 508cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count1 = 62; 509cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count1; ++i) { 510cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 511cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 512cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label0); 513cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ cbz(arm::R0, &label2); 514cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label1); 515cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count2 = 129; 516cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count2; ++i) { 517cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 518cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 519cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label2); 520cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 521cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 522cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "cmp r0, #0\n" // cbz r0, label1 523cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "beq.n 1f\n" + 524cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count1, "ldr r0, [r0]\n") + 525cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "0:\n" 526cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "cmp r0, #0\n" // cbz r0, label2 527cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "beq.w 2f\n" 528cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" + 529cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") + 530cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n"; 531cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "TwoCbzSecondBeyondMaxB16Offset"); 532cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 533cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label0.Position()) + 2u, 534cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label0.Position())); 535cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label1.Position()) + 6u, 536cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label1.Position())); 537cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label2.Position()) + 6u, 538cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label2.Position())); 539cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 540cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 541cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, TwoCbzFirstAtMaxB16Offset) { 542cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label0, label1, label2; 543cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ cbz(arm::R0, &label1); 544cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count1 = 127; 545cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count1; ++i) { 546cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 547cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 548cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label0); 549cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ cbz(arm::R0, &label2); 550cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label1); 551cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count2 = 64; 552cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count2; ++i) { 553cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 554cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 555cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label2); 556cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 557cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 558cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "cmp r0, #0\n" // cbz r0, label1 559cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "beq.n 1f\n" + 560cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count1, "ldr r0, [r0]\n") + 561cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "0:\n" 562cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "cbz r0, 2f\n" // cbz r0, label2 563cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" + 564cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") + 565cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n"; 566cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "TwoCbzFirstAtMaxB16Offset"); 567cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 568cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label0.Position()) + 2u, 569cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label0.Position())); 570cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label1.Position()) + 2u, 571cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label1.Position())); 572cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label2.Position()) + 2u, 573cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label2.Position())); 574cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 575cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 576cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, TwoCbzFirstBeyondMaxB16Offset) { 577cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label0, label1, label2; 578cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ cbz(arm::R0, &label1); 579cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count1 = 127; 580cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count1; ++i) { 581cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 582cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 583cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label0); 584cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ cbz(arm::R0, &label2); 585cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label1); 586cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count2 = 65; 587cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count2; ++i) { 588cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 589cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 590cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label2); 591cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 592cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 593cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "cmp r0, #0\n" // cbz r0, label1 594cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "beq.w 1f\n" + 595cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count1, "ldr r0, [r0]\n") + 596cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "0:\n" 597cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "cmp r0, #0\n" // cbz r0, label2 598cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "beq.n 2f\n" 599cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" + 600cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") + 601cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n"; 602cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "TwoCbzFirstBeyondMaxB16Offset"); 603cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 604cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label0.Position()) + 4u, 605cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label0.Position())); 606cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label1.Position()) + 6u, 607cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label1.Position())); 608cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label2.Position()) + 6u, 609cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label2.Position())); 610cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 611cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 612cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralMax1KiB) { 613cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678); 614cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ LoadLiteral(arm::R0, literal); 615cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label; 616cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label); 617cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count = 511; 618cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count; ++i) { 619cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 620cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 621cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 622cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 623cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" 624cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "ldr.n r0, [pc, #((2f - 1b - 2) & ~2)]\n" + 625cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 626cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".align 2, 0\n" 627cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n" 628cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x12345678\n"; 629cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "LoadLiteralMax1KiB"); 630cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 631cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 0u, 632cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label.Position())); 633cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 634cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 635cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralBeyondMax1KiB) { 636cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678); 637cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ LoadLiteral(arm::R0, literal); 638cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label; 639cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label); 640cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count = 512; 641cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count; ++i) { 642cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 643cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 644cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 645cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 646cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" 647cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "ldr.w r0, [pc, #((2f - 1b - 2) & ~2)]\n" + 648cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 649cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".align 2, 0\n" 650cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n" 651cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x12345678\n"; 652cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "LoadLiteralBeyondMax1KiB"); 653cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 654cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 2u, 655cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label.Position())); 656cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 657cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 658cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralMax4KiB) { 659cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678); 660cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ LoadLiteral(arm::R1, literal); 661cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label; 662cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label); 663cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count = 2046; 664cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count; ++i) { 665cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 666cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 667cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 668cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 669cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" 670cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "ldr.w r1, [pc, #((2f - 1b - 2) & ~2)]\n" + 671cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 672cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".align 2, 0\n" 673cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n" 674cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x12345678\n"; 675cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "LoadLiteralMax4KiB"); 676cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 677cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 2u, 678cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label.Position())); 679cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 680cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 681cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralBeyondMax4KiB) { 682cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678); 683cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ LoadLiteral(arm::R1, literal); 684cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label; 685cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label); 686cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count = 2047; 687cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count; ++i) { 688cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 689cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 690cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 691cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 692cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "movw r1, #4096\n" // "as" does not consider (2f - 1f - 4) a constant expression for movw. 693cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" 694cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "add r1, pc\n" 695cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "ldr r1, [r1, #0]\n" + 696cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 697cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".align 2, 0\n" 698cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n" 699cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x12345678\n"; 700cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "LoadLiteralBeyondMax4KiB"); 701cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 702cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 6u, 703cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label.Position())); 704cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 705cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 706cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralMax64KiB) { 707cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678); 708cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ LoadLiteral(arm::R1, literal); 709cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label; 710cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label); 711cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count = (1u << 15) - 2u; 712cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count; ++i) { 713cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 714cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 715cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 716cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 717cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "movw r1, #0xfffc\n" // "as" does not consider (2f - 1f - 4) a constant expression for movw. 718cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" 719cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "add r1, pc\n" 720cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "ldr r1, [r1, #0]\n" + 721cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 722cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".align 2, 0\n" 723cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n" 724cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x12345678\n"; 725cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "LoadLiteralMax64KiB"); 726cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 727cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 6u, 728cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label.Position())); 729cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 730cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 731cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralBeyondMax64KiB) { 732cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678); 733cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ LoadLiteral(arm::R1, literal); 734cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label; 735cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label); 736cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count = (1u << 15) - 1u; 737cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count; ++i) { 738cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 739cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 740cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 741cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 742cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "mov.w r1, #((2f - 1f - 4) & ~0xfff)\n" 743cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" 744cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "add r1, pc\n" 745cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "ldr r1, [r1, #((2f - 1b - 4) & 0xfff)]\n" + 746cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 747cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".align 2, 0\n" 748cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n" 749cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x12345678\n"; 750cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "LoadLiteralBeyondMax64KiB"); 751cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 752cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 8u, 753cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label.Position())); 754cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 755cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 756cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralMax1MiB) { 757cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678); 758cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ LoadLiteral(arm::R1, literal); 759cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label; 760cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label); 761cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count = (1u << 19) - 3u; 762cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count; ++i) { 763cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 764cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 765cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 766cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 767cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "mov.w r1, #((2f - 1f - 4) & ~0xfff)\n" 768cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" 769cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "add r1, pc\n" 770cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "ldr r1, [r1, #((2f - 1b - 4) & 0xfff)]\n" + 771cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 772cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".align 2, 0\n" 773cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n" 774cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x12345678\n"; 775cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "LoadLiteralMax1MiB"); 776cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 777cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 8u, 778cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label.Position())); 779cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 780cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 781cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralBeyondMax1MiB) { 782cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678); 783cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ LoadLiteral(arm::R1, literal); 784cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label; 785cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label); 786cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count = (1u << 19) - 2u; 787cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count; ++i) { 788cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 789cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 790cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 791cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 792cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // "as" does not consider ((2f - 1f - 4) & 0xffff) a constant expression for movw. 793cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "movw r1, #(0x100000 & 0xffff)\n" 794cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // "as" does not consider ((2f - 1f - 4) >> 16) a constant expression for movt. 795cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "movt r1, #(0x100000 >> 16)\n" 796cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" 797cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "add r1, pc\n" 798cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "ldr.w r1, [r1, #0]\n" + 799cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 800cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".align 2, 0\n" 801cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n" 802cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x12345678\n"; 803cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "LoadLiteralBeyondMax1MiB"); 804cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 805cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 12u, 806cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label.Position())); 807cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 808cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 809cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralFar) { 810cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678); 811cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ LoadLiteral(arm::R1, literal); 812cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label; 813cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label); 814cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count = (1u << 19) - 2u + 0x1234; 815cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count; ++i) { 816cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 817cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 818cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 819cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 820cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // "as" does not consider ((2f - 1f - 4) & 0xffff) a constant expression for movw. 821cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "movw r1, #((0x100000 + 2 * 0x1234) & 0xffff)\n" 822cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // "as" does not consider ((2f - 1f - 4) >> 16) a constant expression for movt. 823cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "movt r1, #((0x100000 + 2 * 0x1234) >> 16)\n" 824cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" 825cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "add r1, pc\n" 826cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "ldr.w r1, [r1, #0]\n" + 827cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 828cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".align 2, 0\n" 829cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n" 830cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x12345678\n"; 831cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "LoadLiteralFar"); 832cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 833cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 12u, 834cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label.Position())); 835cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 836cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 837cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralWideMax1KiB) { 838cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko arm::Literal* literal = __ NewLiteral<int64_t>(INT64_C(0x1234567887654321)); 839cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ LoadLiteral(arm::R1, arm::R3, literal); 840cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label; 841cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label); 842cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count = 510; 843cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count; ++i) { 844cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 845cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 846cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 847cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 848cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" 849cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "ldrd r1, r3, [pc, #((2f - 1b - 2) & ~2)]\n" + 850cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 851cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".align 2, 0\n" 852cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n" 853cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x87654321\n" 854cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x12345678\n"; 855cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "LoadLiteralWideMax1KiB"); 856cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 857cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 0u, 858cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label.Position())); 859cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 860cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 861cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralWideBeyondMax1KiB) { 862cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko arm::Literal* literal = __ NewLiteral<int64_t>(INT64_C(0x1234567887654321)); 863cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ LoadLiteral(arm::R1, arm::R3, literal); 864cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label; 865cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label); 866cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count = 511; 867cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count; ++i) { 868cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 869cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 870cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 871cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 872cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "mov.w ip, #((2f - 1f - 4) & ~0x3ff)\n" 873cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" 874cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "add ip, pc\n" 875cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "ldrd r1, r3, [ip, #((2f - 1b - 4) & 0x3ff)]\n" + 876cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 877cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".align 2, 0\n" 878cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n" 879cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x87654321\n" 880cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x12345678\n"; 881cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "LoadLiteralWideBeyondMax1KiB"); 882cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 883cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 6u, 884cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label.Position())); 885cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 886cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 887cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralSingleMax256KiB) { 888cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // The literal size must match but the type doesn't, so use an int32_t rather than float. 889cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678); 890cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ LoadLiteral(arm::S3, literal); 891cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label; 892cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label); 893cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count = (1 << 17) - 3u; 894cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count; ++i) { 895cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 896cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 897cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 898cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 899cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "mov.w ip, #((2f - 1f - 4) & ~0x3ff)\n" 900cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" 901cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "add ip, pc\n" 902cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "vldr s3, [ip, #((2f - 1b - 4) & 0x3ff)]\n" + 903cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 904cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".align 2, 0\n" 905cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n" 906cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x12345678\n"; 907cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "LoadLiteralSingleMax256KiB"); 908cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 909cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 6u, 910cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label.Position())); 911cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 912cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 913cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralDoubleBeyondMax256KiB) { 914cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // The literal size must match but the type doesn't, so use an int64_t rather than double. 915cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko arm::Literal* literal = __ NewLiteral<int64_t>(INT64_C(0x1234567887654321)); 916cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ LoadLiteral(arm::D3, literal); 917cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label; 918cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label); 919cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count = (1 << 17) - 2u; 920cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count; ++i) { 921cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 922cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 923cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 924cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 925cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // "as" does not consider ((2f - 1f - 4) & 0xffff) a constant expression for movw. 926cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "movw ip, #(0x40000 & 0xffff)\n" 927cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // "as" does not consider ((2f - 1f - 4) >> 16) a constant expression for movt. 928cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "movt ip, #(0x40000 >> 16)\n" 929cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" 930cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "add ip, pc\n" 931cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "vldr d3, [ip, #0]\n" + 932cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 933cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".align 2, 0\n" 934cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n" 935cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x87654321\n" 936cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x12345678\n"; 937cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "LoadLiteralDoubleBeyondMax256KiB"); 938cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 939cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 10u, 940cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label.Position())); 941cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 942cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 943cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralDoubleFar) { 944cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // The literal size must match but the type doesn't, so use an int64_t rather than double. 945cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko arm::Literal* literal = __ NewLiteral<int64_t>(INT64_C(0x1234567887654321)); 946cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ LoadLiteral(arm::D3, literal); 947cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko Label label; 948cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ Bind(&label); 949cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko constexpr size_t kLdrR0R0Count = (1 << 17) - 2u + 0x1234; 950cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko for (size_t i = 0; i != kLdrR0R0Count; ++i) { 951cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 952cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko } 953cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 954cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko std::string expected = 955cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // "as" does not consider ((2f - 1f - 4) & 0xffff) a constant expression for movw. 956cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "movw ip, #((0x40000 + 2 * 0x1234) & 0xffff)\n" 957cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // "as" does not consider ((2f - 1f - 4) >> 16) a constant expression for movt. 958cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "movt ip, #((0x40000 + 2 * 0x1234) >> 16)\n" 959cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "1:\n" 960cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "add ip, pc\n" 961cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "vldr d3, [ip, #0]\n" + 962cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 963cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".align 2, 0\n" 964cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko "2:\n" 965cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x87654321\n" 966cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko ".word 0x12345678\n"; 967cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko DriverStr(expected, "LoadLiteralDoubleFar"); 968cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 969cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 10u, 970cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko __ GetAdjustedPosition(label.Position())); 971cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko} 972cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 973663c93448e50599d411b2403585b90513dbf8e3aVladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralBeyondMax1KiBDueToAlignmentOnSecondPass) { 974663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko // First part: as TwoCbzBeyondMaxOffset but add one 16-bit instruction to the end, 975663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko // so that the size is not Aligned<4>(.). On the first pass, the assembler resizes 976663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko // the second CBZ because it's out of range, then it will resize the first CBZ 977663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko // which has been pushed out of range. Thus, after the first pass, the code size 978663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko // will appear Aligned<4>(.) but the final size will not be. 979663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko Label label0, label1, label2; 980663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko __ cbz(arm::R0, &label1); 981663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko constexpr size_t kLdrR0R0Count1 = 63; 982663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko for (size_t i = 0; i != kLdrR0R0Count1; ++i) { 983663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 984663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko } 985663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko __ Bind(&label0); 986663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko __ cbz(arm::R0, &label2); 987663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko __ Bind(&label1); 988663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko constexpr size_t kLdrR0R0Count2 = 65; 989663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko for (size_t i = 0; i != kLdrR0R0Count2; ++i) { 990663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 991663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko } 992663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko __ Bind(&label2); 993663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 994663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko 995663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko std::string expected_part1 = 996663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko "cmp r0, #0\n" // cbz r0, label1 997663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko "beq.n 1f\n" + 998663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko RepeatInsn(kLdrR0R0Count1, "ldr r0, [r0]\n") + 999663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko "0:\n" 1000663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko "cmp r0, #0\n" // cbz r0, label2 1001663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko "beq.n 2f\n" 1002663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko "1:\n" + 1003663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") + 1004663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko "2:\n" // Here the offset is Aligned<4>(.). 1005663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko "ldr r0, [r0]\n"; // Make the first part 1006663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko 1007663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko // Second part: as LoadLiteralMax1KiB with the caveat that the offset of the load 1008663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko // literal will not be Aligned<4>(.) but it will appear to be when we process the 1009663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko // instruction during the first pass, so the literal will need a padding and it 1010663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko // will push the literal out of range, so we shall end up with "ldr.w". 1011663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678); 1012663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko __ LoadLiteral(arm::R0, literal); 1013663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko Label label; 1014663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko __ Bind(&label); 1015663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko constexpr size_t kLdrR0R0Count = 511; 1016663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko for (size_t i = 0; i != kLdrR0R0Count; ++i) { 1017663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko __ ldr(arm::R0, arm::Address(arm::R0)); 1018663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko } 1019663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko 1020663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko std::string expected = 1021663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko expected_part1 + 1022663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko "1:\n" 1023663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko "ldr.w r0, [pc, #((2f - 1b - 2) & ~2)]\n" + 1024663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 1025663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko ".align 2, 0\n" 1026663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko "2:\n" 1027663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko ".word 0x12345678\n"; 1028663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko DriverStr(expected, "LoadLiteralMax1KiB"); 1029663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko 1030663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 6u, 1031663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko __ GetAdjustedPosition(label.Position())); 1032663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko} 1033663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko 10347cffc3b0004d32faffc552c0a59286f369b21504Andreas GampeTEST_F(AssemblerThumb2Test, BindTrackedLabel) { 10357cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe Label non_tracked, tracked, branch_target; 10367cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 10377cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // A few dummy loads on entry. 10387cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe constexpr size_t kLdrR0R0Count = 5; 10397cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 10407cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 10417cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 10427cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 10437cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // A branch that will need to be fixed up. 10447cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ cbz(arm::R0, &branch_target); 10457cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 10467cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Some more dummy loads. 10477cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 10487cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 10497cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 10507cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 10517cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Now insert tracked and untracked label. 10527cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ Bind(&non_tracked); 10537cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ BindTrackedLabel(&tracked); 10547cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 10557cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // A lot of dummy loads, to ensure the branch needs resizing. 10567cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe constexpr size_t kLdrR0R0CountLong = 60; 10577cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0CountLong; ++i) { 10587cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 10597cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 10607cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 10617cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Bind the branch target. 10627cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ Bind(&branch_target); 10637cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 10647cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // One more load. 10657cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 10667cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 10677cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe std::string expected = 10687cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 10697cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "cmp r0, #0\n" // cbz r0, 1f 10707cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "beq.n 1f\n" + 10717cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count + kLdrR0R0CountLong, "ldr r0, [r0]\n") + 10727cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "1:\n" 10737cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "ldr r0, [r0]\n"; 10747cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe DriverStr(expected, "BindTrackedLabel"); 10757cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 10767cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Expectation is that the tracked label should have moved. 10777cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe EXPECT_LT(non_tracked.Position(), tracked.Position()); 10787cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe} 10797cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 10807cffc3b0004d32faffc552c0a59286f369b21504Andreas GampeTEST_F(AssemblerThumb2Test, JumpTable) { 10817cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // The jump table. Use three labels. 10827cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe Label label1, label2, label3; 10837cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe std::vector<Label*> labels({ &label1, &label2, &label3 }); 10847cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 10857cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // A few dummy loads on entry, interspersed with 2 labels. 10867cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe constexpr size_t kLdrR0R0Count = 5; 10877cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 10887cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 10897cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 10907cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ BindTrackedLabel(&label1); 10917cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 10927cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 10937cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 10947cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ BindTrackedLabel(&label2); 10957cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 10967cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 10977cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 10987cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 10997cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Create the jump table, emit the base load. 11007cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe arm::JumpTable* jump_table = __ CreateJumpTable(std::move(labels), arm::R1); 11017cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 11027cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Dummy computation, stand-in for the address. We're only testing the jump table here, not how 11037cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // it's being used. 11047cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 11057cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 11067cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Emit the jump 11077cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ EmitJumpTableDispatch(jump_table, arm::R1); 11087cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 11097cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Some more dummy instructions. 11107cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 11117cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 11127cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 11137cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ BindTrackedLabel(&label3); 11147cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { // Note: odd so there's no alignment 11157cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); // necessary, as gcc as emits nops, 11167cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } // whereas we emit 0 != nop. 11177cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 11187cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe static_assert((kLdrR0R0Count + 3) * 2 < 1 * KB, "Too much offset"); 11197cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 11207cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe std::string expected = 11217cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 11227cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".L1:\n" + 11237cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 11247cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".L2:\n" + 11257cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 11267cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "adr r1, .Ljump_table\n" 11277cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "ldr r0, [r0]\n" 11287cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".Lbase:\n" 11297cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "add pc, r1\n" + 11307cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 11317cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".L3:\n" + 11327cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 11337cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".align 2\n" 11347cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".Ljump_table:\n" 11357cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".4byte (.L1 - .Lbase - 4)\n" 11367cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".4byte (.L2 - .Lbase - 4)\n" 11377cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".4byte (.L3 - .Lbase - 4)\n"; 11387cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe DriverStr(expected, "JumpTable"); 11397cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe} 11407cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 11417cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe// Test for >1K fixup. 11427cffc3b0004d32faffc552c0a59286f369b21504Andreas GampeTEST_F(AssemblerThumb2Test, JumpTable4K) { 11437cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // The jump table. Use three labels. 11447cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe Label label1, label2, label3; 11457cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe std::vector<Label*> labels({ &label1, &label2, &label3 }); 11467cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 11477cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // A few dummy loads on entry, interspersed with 2 labels. 11487cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe constexpr size_t kLdrR0R0Count = 5; 11497cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 11507cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 11517cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 11527cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ BindTrackedLabel(&label1); 11537cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 11547cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 11557cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 11567cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ BindTrackedLabel(&label2); 11577cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 11587cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 11597cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 11607cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 11617cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Create the jump table, emit the base load. 11627cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe arm::JumpTable* jump_table = __ CreateJumpTable(std::move(labels), arm::R1); 11637cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 11647cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Dummy computation, stand-in for the address. We're only testing the jump table here, not how 11657cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // it's being used. 11667cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 11677cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 11687cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Emit the jump 11697cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ EmitJumpTableDispatch(jump_table, arm::R1); 11707cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 11717cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Some more dummy instructions. 11727cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 11737cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 11747cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 11757cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ BindTrackedLabel(&label3); 11767cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe constexpr size_t kLdrR0R0Count2 = 600; // Note: even so there's no alignment 11777cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count2; ++i) { // necessary, as gcc as emits nops, 11787cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); // whereas we emit 0 != nop. 11797cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 11807cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 11817cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe static_assert((kLdrR0R0Count + kLdrR0R0Count2 + 3) * 2 > 1 * KB, "Not enough offset"); 11827cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe static_assert((kLdrR0R0Count + kLdrR0R0Count2 + 3) * 2 < 4 * KB, "Too much offset"); 11837cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 11847cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe std::string expected = 11857cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 11867cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".L1:\n" + 11877cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 11887cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".L2:\n" + 11897cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 11907cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "adr r1, .Ljump_table\n" 11917cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "ldr r0, [r0]\n" 11927cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".Lbase:\n" 11937cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "add pc, r1\n" + 11947cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 11957cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".L3:\n" + 11967cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") + 11977cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".align 2\n" 11987cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".Ljump_table:\n" 11997cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".4byte (.L1 - .Lbase - 4)\n" 12007cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".4byte (.L2 - .Lbase - 4)\n" 12017cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".4byte (.L3 - .Lbase - 4)\n"; 12027cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe DriverStr(expected, "JumpTable4K"); 12037cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe} 12047cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 12057cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe// Test for >4K fixup. 12067cffc3b0004d32faffc552c0a59286f369b21504Andreas GampeTEST_F(AssemblerThumb2Test, JumpTable64K) { 12077cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // The jump table. Use three labels. 12087cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe Label label1, label2, label3; 12097cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe std::vector<Label*> labels({ &label1, &label2, &label3 }); 12107cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 12117cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // A few dummy loads on entry, interspersed with 2 labels. 12127cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe constexpr size_t kLdrR0R0Count = 5; 12137cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 12147cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 12157cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 12167cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ BindTrackedLabel(&label1); 12177cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 12187cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 12197cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 12207cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ BindTrackedLabel(&label2); 12217cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 12227cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 12237cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 12247cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 12257cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Create the jump table, emit the base load. 12267cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe arm::JumpTable* jump_table = __ CreateJumpTable(std::move(labels), arm::R1); 12277cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 12287cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Dummy computation, stand-in for the address. We're only testing the jump table here, not how 12297cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // it's being used. 12307cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 12317cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 12327cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Emit the jump 12337cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ EmitJumpTableDispatch(jump_table, arm::R1); 12347cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 12357cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Some more dummy instructions. 12367cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 12377cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 12387cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 12397cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ BindTrackedLabel(&label3); 12407cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe constexpr size_t kLdrR0R0Count2 = 2601; // Note: odd so there's no alignment 12417cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count2; ++i) { // necessary, as gcc as emits nops, 12427cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); // whereas we emit 0 != nop. 12437cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 12447cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 12457cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe static_assert((kLdrR0R0Count + kLdrR0R0Count2 + 3) * 2 > 4 * KB, "Not enough offset"); 12467cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe static_assert((kLdrR0R0Count + kLdrR0R0Count2 + 3) * 2 < 64 * KB, "Too much offset"); 12477cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 12487cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe std::string expected = 12497cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 12507cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".L1:\n" + 12517cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 12527cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".L2:\n" + 12537cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 12547cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // ~ adr r1, .Ljump_table, gcc as can't seem to fix up a large offset itself. 12557cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // (Note: have to use constants, as labels aren't accepted. 12567cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "movw r1, #(((3 + " + StringPrintf("%zu", kLdrR0R0Count + kLdrR0R0Count2) + 12577cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ") * 2 - 4) & 0xFFFF)\n" 12587cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "add r1, pc\n" 12597cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "ldr r0, [r0]\n" 12607cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".Lbase:\n" 12617cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "add pc, r1\n" + 12627cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 12637cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".L3:\n" + 12647cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") + 12657cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".align 2\n" 12667cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".Ljump_table:\n" 12677cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".4byte (.L1 - .Lbase - 4)\n" 12687cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".4byte (.L2 - .Lbase - 4)\n" 12697cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".4byte (.L3 - .Lbase - 4)\n"; 12707cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe DriverStr(expected, "JumpTable64K"); 12717cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe} 12727cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 12737cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe// Test for >64K fixup. 12747cffc3b0004d32faffc552c0a59286f369b21504Andreas GampeTEST_F(AssemblerThumb2Test, JumpTableFar) { 12757cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // The jump table. Use three labels. 12767cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe Label label1, label2, label3; 12777cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe std::vector<Label*> labels({ &label1, &label2, &label3 }); 12787cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 12797cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // A few dummy loads on entry, interspersed with 2 labels. 12807cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe constexpr size_t kLdrR0R0Count = 5; 12817cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 12827cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 12837cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 12847cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ BindTrackedLabel(&label1); 12857cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 12867cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 12877cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 12887cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ BindTrackedLabel(&label2); 12897cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 12907cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 12917cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 12927cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 12937cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Create the jump table, emit the base load. 12947cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe arm::JumpTable* jump_table = __ CreateJumpTable(std::move(labels), arm::R1); 12957cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 12967cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Dummy computation, stand-in for the address. We're only testing the jump table here, not how 12977cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // it's being used. 12987cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 12997cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 13007cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Emit the jump 13017cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ EmitJumpTableDispatch(jump_table, arm::R1); 13027cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 13037cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // Some more dummy instructions. 13047cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count; ++i) { 13057cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); 13067cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 13077cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ BindTrackedLabel(&label3); 13087cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe constexpr size_t kLdrR0R0Count2 = 70001; // Note: odd so there's no alignment 13097cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe for (size_t i = 0; i != kLdrR0R0Count2; ++i) { // necessary, as gcc as emits nops, 13107cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe __ ldr(arm::R0, arm::Address(arm::R0)); // whereas we emit 0 != nop. 13117cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe } 13127cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 13137cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe static_assert((kLdrR0R0Count + kLdrR0R0Count2 + 3) * 2 > 64 * KB, "Not enough offset"); 13147cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 13157cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe std::string expected = 13167cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 13177cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".L1:\n" + 13187cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 13197cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".L2:\n" + 13207cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 13217cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // ~ adr r1, .Ljump_table, gcc as can't seem to fix up a large offset itself. 13227cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe // (Note: have to use constants, as labels aren't accepted. 13237cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "movw r1, #(((3 + " + StringPrintf("%zu", kLdrR0R0Count + kLdrR0R0Count2) + 13247cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ") * 2 - 4) & 0xFFFF)\n" 13257cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "movt r1, #(((3 + " + StringPrintf("%zu", kLdrR0R0Count + kLdrR0R0Count2) + 13267cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ") * 2 - 4) >> 16)\n" 13277cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".Lhelp:" 13287cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "add r1, pc\n" 13297cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "ldr r0, [r0]\n" 13307cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".Lbase:\n" 13317cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe "add pc, r1\n" + 13327cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") + 13337cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".L3:\n" + 13347cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") + 13357cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".align 2\n" 13367cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".Ljump_table:\n" 13377cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".4byte (.L1 - .Lbase - 4)\n" 13387cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".4byte (.L2 - .Lbase - 4)\n" 13397cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe ".4byte (.L3 - .Lbase - 4)\n"; 13407cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe DriverStr(expected, "JumpTableFar"); 13417cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe} 13427cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe 1343611d3395e9efc0ab8dbfa4a197fa022fbd8c7204Scott WakelingTEST_F(AssemblerThumb2Test, Clz) { 1344611d3395e9efc0ab8dbfa4a197fa022fbd8c7204Scott Wakeling __ clz(arm::R0, arm::R1); 1345611d3395e9efc0ab8dbfa4a197fa022fbd8c7204Scott Wakeling 1346611d3395e9efc0ab8dbfa4a197fa022fbd8c7204Scott Wakeling const char* expected = "clz r0, r1\n"; 1347611d3395e9efc0ab8dbfa4a197fa022fbd8c7204Scott Wakeling 1348611d3395e9efc0ab8dbfa4a197fa022fbd8c7204Scott Wakeling DriverStr(expected, "clz"); 1349611d3395e9efc0ab8dbfa4a197fa022fbd8c7204Scott Wakeling} 1350611d3395e9efc0ab8dbfa4a197fa022fbd8c7204Scott Wakeling 13519ee23f4273efed8d6378f6ad8e63c65e30a17139Scott WakelingTEST_F(AssemblerThumb2Test, rbit) { 13529ee23f4273efed8d6378f6ad8e63c65e30a17139Scott Wakeling __ rbit(arm::R1, arm::R0); 13539ee23f4273efed8d6378f6ad8e63c65e30a17139Scott Wakeling 13549ee23f4273efed8d6378f6ad8e63c65e30a17139Scott Wakeling const char* expected = "rbit r1, r0\n"; 13559ee23f4273efed8d6378f6ad8e63c65e30a17139Scott Wakeling 13569ee23f4273efed8d6378f6ad8e63c65e30a17139Scott Wakeling DriverStr(expected, "rbit"); 13579ee23f4273efed8d6378f6ad8e63c65e30a17139Scott Wakeling} 13589ee23f4273efed8d6378f6ad8e63c65e30a17139Scott Wakeling 1359c257da7b0fb6737f65aba426add8831e45404755Artem SerovTEST_F(AssemblerThumb2Test, rev) { 1360c257da7b0fb6737f65aba426add8831e45404755Artem Serov __ rev(arm::R1, arm::R0); 1361c257da7b0fb6737f65aba426add8831e45404755Artem Serov 1362c257da7b0fb6737f65aba426add8831e45404755Artem Serov const char* expected = "rev r1, r0\n"; 1363c257da7b0fb6737f65aba426add8831e45404755Artem Serov 1364c257da7b0fb6737f65aba426add8831e45404755Artem Serov DriverStr(expected, "rev"); 1365c257da7b0fb6737f65aba426add8831e45404755Artem Serov} 1366c257da7b0fb6737f65aba426add8831e45404755Artem Serov 1367c257da7b0fb6737f65aba426add8831e45404755Artem SerovTEST_F(AssemblerThumb2Test, rev16) { 1368c257da7b0fb6737f65aba426add8831e45404755Artem Serov __ rev16(arm::R1, arm::R0); 1369c257da7b0fb6737f65aba426add8831e45404755Artem Serov 1370c257da7b0fb6737f65aba426add8831e45404755Artem Serov const char* expected = "rev16 r1, r0\n"; 1371c257da7b0fb6737f65aba426add8831e45404755Artem Serov 1372c257da7b0fb6737f65aba426add8831e45404755Artem Serov DriverStr(expected, "rev16"); 1373c257da7b0fb6737f65aba426add8831e45404755Artem Serov} 1374c257da7b0fb6737f65aba426add8831e45404755Artem Serov 1375c257da7b0fb6737f65aba426add8831e45404755Artem SerovTEST_F(AssemblerThumb2Test, revsh) { 1376c257da7b0fb6737f65aba426add8831e45404755Artem Serov __ revsh(arm::R1, arm::R0); 1377c257da7b0fb6737f65aba426add8831e45404755Artem Serov 1378c257da7b0fb6737f65aba426add8831e45404755Artem Serov const char* expected = "revsh r1, r0\n"; 1379c257da7b0fb6737f65aba426add8831e45404755Artem Serov 1380c257da7b0fb6737f65aba426add8831e45404755Artem Serov DriverStr(expected, "revsh"); 1381c257da7b0fb6737f65aba426add8831e45404755Artem Serov} 1382c257da7b0fb6737f65aba426add8831e45404755Artem Serov 13831a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain} // namespace art 1384