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(&registers_);
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