assembler_thumb2_test.cc revision 611d3395e9efc0ab8dbfa4a197fa022fbd8c7204
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"
201a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain#include "utils/assembler_test.h"
211a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
221a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillainnamespace art {
231a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
241a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillainclass AssemblerThumb2Test : public AssemblerTest<arm::Thumb2Assembler,
25851df20225593b10e698a760ac3cd5243620700bAndreas Gampe                                                 arm::Register, arm::SRegister,
26851df20225593b10e698a760ac3cd5243620700bAndreas Gampe                                                 uint32_t> {
271a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain protected:
281a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  std::string GetArchitectureString() OVERRIDE {
291a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain    return "arm";
301a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  }
311a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
321a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  std::string GetAssemblerParameters() OVERRIDE {
33513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe    return " -march=armv7-a -mcpu=cortex-a15 -mfpu=neon -mthumb";
34513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe  }
35513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe
36513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe  const char* GetAssemblyHeader() OVERRIDE {
37513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe    return kThumb2AssemblyHeader;
381a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  }
391a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
401a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  std::string GetDisassembleParameters() OVERRIDE {
41513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe    return " -D -bbinary -marm --disassembler-options=force-thumb --no-show-raw-insn";
421a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  }
431a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
441a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  void SetUpHelpers() OVERRIDE {
451a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain    if (registers_.size() == 0) {
461a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain      registers_.insert(end(registers_),
471a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                        {  // NOLINT(whitespace/braces)
481a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                          new arm::Register(arm::R0),
491a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                          new arm::Register(arm::R1),
501a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                          new arm::Register(arm::R2),
511a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                          new arm::Register(arm::R3),
521a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                          new arm::Register(arm::R4),
531a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                          new arm::Register(arm::R5),
541a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                          new arm::Register(arm::R6),
551a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                          new arm::Register(arm::R7),
561a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                          new arm::Register(arm::R8),
571a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                          new arm::Register(arm::R9),
581a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                          new arm::Register(arm::R10),
591a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                          new arm::Register(arm::R11),
601a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                          new arm::Register(arm::R12),
611a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                          new arm::Register(arm::R13),
621a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                          new arm::Register(arm::R14),
631a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                          new arm::Register(arm::R15)
641a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain                        });
651a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain    }
661a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  }
671a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
681a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  void TearDown() OVERRIDE {
691a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain    AssemblerTest::TearDown();
701a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain    STLDeleteElements(&registers_);
711a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  }
721a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
731a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  std::vector<arm::Register*> GetRegisters() OVERRIDE {
741a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain    return registers_;
751a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  }
761a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
771a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  uint32_t CreateImmediate(int64_t imm_value) OVERRIDE {
781a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain    return imm_value;
791a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  }
801a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
81cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string RepeatInsn(size_t count, const std::string& insn) {
82cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    std::string result;
83cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    for (; count != 0u; --count) {
84cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      result += insn;
85cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
86cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    return result;
87cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
88cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
891a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain private:
901a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  std::vector<arm::Register*> registers_;
91513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe
92513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe  static constexpr const char* kThumb2AssemblyHeader = ".syntax unified\n.thumb\n";
931a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain};
941a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
951a28fc43ea7daa624ada9af40e30de64d4e946a8Roland LevillainTEST_F(AssemblerThumb2Test, Toolchain) {
961a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  EXPECT_TRUE(CheckTools());
971a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain}
981a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
99c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu#define __ GetAssembler()->
1001a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
1011a28fc43ea7daa624ada9af40e30de64d4e946a8Roland LevillainTEST_F(AssemblerThumb2Test, Sbfx) {
102c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ sbfx(arm::R0, arm::R1, 0, 1);
103c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ sbfx(arm::R0, arm::R1, 0, 8);
104c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ sbfx(arm::R0, arm::R1, 0, 16);
105c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ sbfx(arm::R0, arm::R1, 0, 32);
1061a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
107c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ sbfx(arm::R0, arm::R1, 8, 1);
108c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ sbfx(arm::R0, arm::R1, 8, 8);
109c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ sbfx(arm::R0, arm::R1, 8, 16);
110c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ sbfx(arm::R0, arm::R1, 8, 24);
1111a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
112c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ sbfx(arm::R0, arm::R1, 16, 1);
113c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ sbfx(arm::R0, arm::R1, 16, 8);
114c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ sbfx(arm::R0, arm::R1, 16, 16);
1151a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
116c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ sbfx(arm::R0, arm::R1, 31, 1);
1171a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
1181a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  const char* expected =
1191a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain      "sbfx r0, r1, #0, #1\n"
1201a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain      "sbfx r0, r1, #0, #8\n"
1211a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain      "sbfx r0, r1, #0, #16\n"
1221a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain      "sbfx r0, r1, #0, #32\n"
1231a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
1241a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain      "sbfx r0, r1, #8, #1\n"
1251a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain      "sbfx r0, r1, #8, #8\n"
1261a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain      "sbfx r0, r1, #8, #16\n"
1271a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain      "sbfx r0, r1, #8, #24\n"
1281a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
1291a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain      "sbfx r0, r1, #16, #1\n"
1301a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain      "sbfx r0, r1, #16, #8\n"
1311a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain      "sbfx r0, r1, #16, #16\n"
1321a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
1331a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain      "sbfx r0, r1, #31, #1\n";
1341a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain  DriverStr(expected, "sbfx");
1351a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain}
1361a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain
137981e45424f52735b1c61ae0eac7e299ed313f8dbRoland LevillainTEST_F(AssemblerThumb2Test, Ubfx) {
138c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ubfx(arm::R0, arm::R1, 0, 1);
139c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ubfx(arm::R0, arm::R1, 0, 8);
140c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ubfx(arm::R0, arm::R1, 0, 16);
141c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ubfx(arm::R0, arm::R1, 0, 32);
142981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain
143c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ubfx(arm::R0, arm::R1, 8, 1);
144c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ubfx(arm::R0, arm::R1, 8, 8);
145c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ubfx(arm::R0, arm::R1, 8, 16);
146c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ubfx(arm::R0, arm::R1, 8, 24);
147981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain
148c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ubfx(arm::R0, arm::R1, 16, 1);
149c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ubfx(arm::R0, arm::R1, 16, 8);
150c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ubfx(arm::R0, arm::R1, 16, 16);
151981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain
152c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ubfx(arm::R0, arm::R1, 31, 1);
153981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain
154981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain  const char* expected =
155981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain      "ubfx r0, r1, #0, #1\n"
156981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain      "ubfx r0, r1, #0, #8\n"
157981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain      "ubfx r0, r1, #0, #16\n"
158981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain      "ubfx r0, r1, #0, #32\n"
159981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain
160981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain      "ubfx r0, r1, #8, #1\n"
161981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain      "ubfx r0, r1, #8, #8\n"
162981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain      "ubfx r0, r1, #8, #16\n"
163981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain      "ubfx r0, r1, #8, #24\n"
164981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain
165981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain      "ubfx r0, r1, #16, #1\n"
166981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain      "ubfx r0, r1, #16, #8\n"
167981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain      "ubfx r0, r1, #16, #16\n"
168981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain
169981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain      "ubfx r0, r1, #31, #1\n";
170981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain  DriverStr(expected, "ubfx");
171981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain}
172981e45424f52735b1c61ae0eac7e299ed313f8dbRoland Levillain
173ddb7df25af45d7cd19ed1138e537973735cc78a5Calin JuravleTEST_F(AssemblerThumb2Test, Vmstat) {
174c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ vmstat();
175ddb7df25af45d7cd19ed1138e537973735cc78a5Calin Juravle
176ddb7df25af45d7cd19ed1138e537973735cc78a5Calin Juravle  const char* expected = "vmrs APSR_nzcv, FPSCR\n";
177ddb7df25af45d7cd19ed1138e537973735cc78a5Calin Juravle
178ddb7df25af45d7cd19ed1138e537973735cc78a5Calin Juravle  DriverStr(expected, "vmrs");
179ddb7df25af45d7cd19ed1138e537973735cc78a5Calin Juravle}
180ddb7df25af45d7cd19ed1138e537973735cc78a5Calin Juravle
18152c489645b6e9ae33623f1ec24143cde5444906eCalin JuravleTEST_F(AssemblerThumb2Test, ldrexd) {
182c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ldrexd(arm::R0, arm::R1, arm::R0);
183c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ldrexd(arm::R0, arm::R1, arm::R1);
184c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ldrexd(arm::R0, arm::R1, arm::R2);
185c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ldrexd(arm::R5, arm::R3, arm::R7);
18652c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle
18752c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle  const char* expected =
18852c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle      "ldrexd r0, r1, [r0]\n"
18952c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle      "ldrexd r0, r1, [r1]\n"
19052c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle      "ldrexd r0, r1, [r2]\n"
19152c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle      "ldrexd r5, r3, [r7]\n";
19252c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle  DriverStr(expected, "ldrexd");
19352c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle}
19452c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle
19552c489645b6e9ae33623f1ec24143cde5444906eCalin JuravleTEST_F(AssemblerThumb2Test, strexd) {
196c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ strexd(arm::R9, arm::R0, arm::R1, arm::R0);
197c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ strexd(arm::R9, arm::R0, arm::R1, arm::R1);
198c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ strexd(arm::R9, arm::R0, arm::R1, arm::R2);
199c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ strexd(arm::R9, arm::R5, arm::R3, arm::R7);
20052c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle
20152c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle  const char* expected =
20252c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle      "strexd r9, r0, r1, [r0]\n"
20352c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle      "strexd r9, r0, r1, [r1]\n"
20452c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle      "strexd r9, r0, r1, [r2]\n"
20552c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle      "strexd r9, r5, r3, [r7]\n";
20652c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle  DriverStr(expected, "strexd");
20752c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle}
20852c489645b6e9ae33623f1ec24143cde5444906eCalin Juravle
2092bcf9bf784a0021630d8fe63d7230d46d6891780Andreas GampeTEST_F(AssemblerThumb2Test, LdrdStrd) {
210c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ldrd(arm::R0, arm::Address(arm::R2, 8));
211c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ ldrd(arm::R0, arm::Address(arm::R12));
212c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ strd(arm::R0, arm::Address(arm::R2, 8));
2132bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe
2142bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe  const char* expected =
2152bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe      "ldrd r0, r1, [r2, #8]\n"
2162bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe      "ldrd r0, r1, [r12]\n"
2172bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe      "strd r0, r1, [r2, #8]\n";
2182bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe  DriverStr(expected, "ldrdstrd");
2192bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe}
2202bcf9bf784a0021630d8fe63d7230d46d6891780Andreas Gampe
221513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas GampeTEST_F(AssemblerThumb2Test, eor) {
222513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe  __ eor(arm::R1, arm::R1, arm::ShifterOperand(arm::R0));
223513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe  __ eor(arm::R1, arm::R0, arm::ShifterOperand(arm::R1));
224513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe  __ eor(arm::R1, arm::R8, arm::ShifterOperand(arm::R0));
225513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe  __ eor(arm::R8, arm::R1, arm::ShifterOperand(arm::R0));
226513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe  __ eor(arm::R1, arm::R0, arm::ShifterOperand(arm::R8));
227513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe
228513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe  const char* expected =
229513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe      "eors r1, r0\n"
230513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe      "eor r1, r0, r1\n"
231513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe      "eor r1, r8, r0\n"
232513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe      "eor r8, r1, r0\n"
233513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe      "eor r1, r0, r8\n";
234513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe  DriverStr(expected, "abs");
235513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe}
236513ea0c203a86e9d81a8630b56cb62704e126cc2Andreas Gampe
237dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" SanchezTEST_F(AssemblerThumb2Test, sub) {
238dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez  __ subs(arm::R1, arm::R0, arm::ShifterOperand(42));
239dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez  __ sub(arm::R1, arm::R0, arm::ShifterOperand(42));
240c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ subs(arm::R1, arm::R0, arm::ShifterOperand(arm::R2, arm::ASR, 31));
241c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ sub(arm::R1, arm::R0, arm::ShifterOperand(arm::R2, arm::ASR, 31));
242dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez
243dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez  const char* expected =
244dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez      "subs r1, r0, #42\n"
245c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu      "subw r1, r0, #42\n"
246c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu      "subs r1, r0, r2, asr #31\n"
247c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu      "sub r1, r0, r2, asr #31\n";
248dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez  DriverStr(expected, "sub");
249dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez}
250dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez
251dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" SanchezTEST_F(AssemblerThumb2Test, add) {
252dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez  __ adds(arm::R1, arm::R0, arm::ShifterOperand(42));
253dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez  __ add(arm::R1, arm::R0, arm::ShifterOperand(42));
254c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ adds(arm::R1, arm::R0, arm::ShifterOperand(arm::R2, arm::ASR, 31));
255c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ add(arm::R1, arm::R0, arm::ShifterOperand(arm::R2, arm::ASR, 31));
256dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez
257dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez  const char* expected =
258dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez      "adds r1, r0, #42\n"
259c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu      "addw r1, r0, #42\n"
260c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu      "adds r1, r0, r2, asr #31\n"
261c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu      "add r1, r0, r2, asr #31\n";
262dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez  DriverStr(expected, "add");
263dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez}
264dc62c48937a6476ed9c0d739f6b3b5c26f758371Guillaume "Vermeille" Sanchez
265c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng XuTEST_F(AssemblerThumb2Test, umull) {
266c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ umull(arm::R0, arm::R1, arm::R2, arm::R3);
267c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu
268c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  const char* expected =
269c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu      "umull r0, r1, r2, r3\n";
270c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  DriverStr(expected, "umull");
271c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu}
272c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu
273c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng XuTEST_F(AssemblerThumb2Test, smull) {
274c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  __ smull(arm::R0, arm::R1, arm::R2, arm::R3);
275c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu
276c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  const char* expected =
277c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu      "smull r0, r1, r2, r3\n";
278c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  DriverStr(expected, "smull");
279c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu}
280c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu
281c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland LevillainTEST_F(AssemblerThumb2Test, StoreWordToThumbOffset) {
282c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain  arm::StoreOperandType type = arm::kStoreWord;
283c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain  int32_t offset = 4092;
284c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain  ASSERT_TRUE(arm::Address::CanHoldStoreOffsetThumb(type, offset));
285c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain
286c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain  __ StoreToOffset(type, arm::R0, arm::SP, offset);
287c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain  __ StoreToOffset(type, arm::IP, arm::SP, offset);
288c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain  __ StoreToOffset(type, arm::IP, arm::R5, offset);
289c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain
290c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain  const char* expected =
291c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain      "str r0, [sp, #4092]\n"
292c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain      "str ip, [sp, #4092]\n"
293c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain      "str ip, [r5, #4092]\n";
294c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain  DriverStr(expected, "StoreWordToThumbOffset");
295c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain}
296c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain
297c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland LevillainTEST_F(AssemblerThumb2Test, StoreWordToNonThumbOffset) {
298c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain  arm::StoreOperandType type = arm::kStoreWord;
299c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain  int32_t offset = 4096;
300c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain  ASSERT_FALSE(arm::Address::CanHoldStoreOffsetThumb(type, offset));
301c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain
302c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain  __ StoreToOffset(type, arm::R0, arm::SP, offset);
303c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain  __ StoreToOffset(type, arm::IP, arm::SP, offset);
304c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain  __ StoreToOffset(type, arm::IP, arm::R5, offset);
305c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain
306c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain  const char* expected =
307c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain      "mov ip, #4096\n"       // LoadImmediate(ip, 4096)
308c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain      "add ip, ip, sp\n"
309c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain      "str r0, [ip, #0]\n"
310c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain
311c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain      "str r5, [sp, #-4]!\n"  // Push(r5)
312c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain      "movw r5, #4100\n"      // LoadImmediate(r5, 4096 + kRegisterSize)
313c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain      "add r5, r5, sp\n"
314c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain      "str ip, [r5, #0]\n"
315c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain      "ldr r5, [sp], #4\n"    // Pop(r5)
316c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain
317c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain      "str r6, [sp, #-4]!\n"  // Push(r6)
318c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain      "mov r6, #4096\n"       // LoadImmediate(r6, 4096)
319c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain      "add r6, r6, r5\n"
320c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain      "str ip, [r6, #0]\n"
321c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain      "ldr r6, [sp], #4\n";   // Pop(r6)
322c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain  DriverStr(expected, "StoreWordToNonThumbOffset");
323c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain}
324c5a5ac641eb4b32fa6737c390813ce78c66a12d3Roland Levillain
3254af147eb3296a26eea566f53a7f687194638d46bRoland LevillainTEST_F(AssemblerThumb2Test, StoreWordPairToThumbOffset) {
3264af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  arm::StoreOperandType type = arm::kStoreWordPair;
3274af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  int32_t offset = 1020;
3284af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  ASSERT_TRUE(arm::Address::CanHoldStoreOffsetThumb(type, offset));
3294af147eb3296a26eea566f53a7f687194638d46bRoland Levillain
3304af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  __ StoreToOffset(type, arm::R0, arm::SP, offset);
3314af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  // We cannot use IP (i.e. R12) as first source register, as it would
3324af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  // force us to use SP (i.e. R13) as second source register, which
3334af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  // would have an "unpredictable" effect according to the ARMv7
3344af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  // specification (the T1 encoding describes the result as
3354af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  // UNPREDICTABLE when of the source registers is R13).
3364af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  //
3374af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  // So we use (R11, IP) (e.g. (R11, R12)) as source registers in the
3384af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  // following instructions.
3394af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  __ StoreToOffset(type, arm::R11, arm::SP, offset);
3404af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  __ StoreToOffset(type, arm::R11, arm::R5, offset);
3414af147eb3296a26eea566f53a7f687194638d46bRoland Levillain
3424af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  const char* expected =
3434af147eb3296a26eea566f53a7f687194638d46bRoland Levillain      "strd r0, r1, [sp, #1020]\n"
3444af147eb3296a26eea566f53a7f687194638d46bRoland Levillain      "strd r11, ip, [sp, #1020]\n"
3454af147eb3296a26eea566f53a7f687194638d46bRoland Levillain      "strd r11, ip, [r5, #1020]\n";
3464af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  DriverStr(expected, "StoreWordPairToThumbOffset");
3474af147eb3296a26eea566f53a7f687194638d46bRoland Levillain}
3484af147eb3296a26eea566f53a7f687194638d46bRoland Levillain
3494af147eb3296a26eea566f53a7f687194638d46bRoland LevillainTEST_F(AssemblerThumb2Test, StoreWordPairToNonThumbOffset) {
3504af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  arm::StoreOperandType type = arm::kStoreWordPair;
3514af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  int32_t offset = 1024;
3524af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  ASSERT_FALSE(arm::Address::CanHoldStoreOffsetThumb(type, offset));
3534af147eb3296a26eea566f53a7f687194638d46bRoland Levillain
3544af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  __ StoreToOffset(type, arm::R0, arm::SP, offset);
3554af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  // Same comment as in AssemblerThumb2Test.StoreWordPairToThumbOffset
3564af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  // regarding the use of (R11, IP) (e.g. (R11, R12)) as source
3574af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  // registers in the following instructions.
3584af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  __ StoreToOffset(type, arm::R11, arm::SP, offset);
3594af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  __ StoreToOffset(type, arm::R11, arm::R5, offset);
3604af147eb3296a26eea566f53a7f687194638d46bRoland Levillain
3614af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  const char* expected =
3624af147eb3296a26eea566f53a7f687194638d46bRoland Levillain      "mov ip, #1024\n"           // LoadImmediate(ip, 1024)
3634af147eb3296a26eea566f53a7f687194638d46bRoland Levillain      "add ip, ip, sp\n"
3644af147eb3296a26eea566f53a7f687194638d46bRoland Levillain      "strd r0, r1, [ip, #0]\n"
3654af147eb3296a26eea566f53a7f687194638d46bRoland Levillain
3664af147eb3296a26eea566f53a7f687194638d46bRoland Levillain      "str r5, [sp, #-4]!\n"      // Push(r5)
3674af147eb3296a26eea566f53a7f687194638d46bRoland Levillain      "movw r5, #1028\n"          // LoadImmediate(r5, 1024 + kRegisterSize)
3684af147eb3296a26eea566f53a7f687194638d46bRoland Levillain      "add r5, r5, sp\n"
3694af147eb3296a26eea566f53a7f687194638d46bRoland Levillain      "strd r11, ip, [r5, #0]\n"
3704af147eb3296a26eea566f53a7f687194638d46bRoland Levillain      "ldr r5, [sp], #4\n"        // Pop(r5)
3714af147eb3296a26eea566f53a7f687194638d46bRoland Levillain
3724af147eb3296a26eea566f53a7f687194638d46bRoland Levillain      "str r6, [sp, #-4]!\n"      // Push(r6)
3734af147eb3296a26eea566f53a7f687194638d46bRoland Levillain      "mov r6, #1024\n"           // LoadImmediate(r6, 1024)
3744af147eb3296a26eea566f53a7f687194638d46bRoland Levillain      "add r6, r6, r5\n"
3754af147eb3296a26eea566f53a7f687194638d46bRoland Levillain      "strd r11, ip, [r6, #0]\n"
3764af147eb3296a26eea566f53a7f687194638d46bRoland Levillain      "ldr r6, [sp], #4\n";       // Pop(r6)
3774af147eb3296a26eea566f53a7f687194638d46bRoland Levillain  DriverStr(expected, "StoreWordPairToNonThumbOffset");
3784af147eb3296a26eea566f53a7f687194638d46bRoland Levillain}
3794af147eb3296a26eea566f53a7f687194638d46bRoland Levillain
380cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, TwoCbzMaxOffset) {
381cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label0, label1, label2;
382cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ cbz(arm::R0, &label1);
383cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count1 = 63;
384cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count1; ++i) {
385cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
386cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
387cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label0);
388cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ cbz(arm::R0, &label2);
389cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label1);
390cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count2 = 64;
391cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count2; ++i) {
392cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
393cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
394cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label2);
395cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
396cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
397cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "cbz r0, 1f\n" +            // cbz r0, label1
398cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count1, "ldr r0, [r0]\n") +
399cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "0:\n"
400cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "cbz r0, 2f\n"              // cbz r0, label2
401cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n" +
402cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") +
403cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n";
404cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "TwoCbzMaxOffset");
405cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
406cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label0.Position()) + 0u,
407cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label0.Position()));
408cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label1.Position()) + 0u,
409cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label1.Position()));
410cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label2.Position()) + 0u,
411cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label2.Position()));
412cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
413cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
414cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, TwoCbzBeyondMaxOffset) {
415cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label0, label1, label2;
416cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ cbz(arm::R0, &label1);
417cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count1 = 63;
418cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count1; ++i) {
419cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
420cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
421cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label0);
422cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ cbz(arm::R0, &label2);
423cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label1);
424cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count2 = 65;
425cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count2; ++i) {
426cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
427cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
428cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label2);
429cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
430cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
431cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "cmp r0, #0\n"              // cbz r0, label1
432cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "beq.n 1f\n" +
433cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count1, "ldr r0, [r0]\n") +
434cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "0:\n"
435cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "cmp r0, #0\n"              // cbz r0, label2
436cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "beq.n 2f\n"
437cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n" +
438cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") +
439cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n";
440cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "TwoCbzBeyondMaxOffset");
441cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
442cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label0.Position()) + 2u,
443cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label0.Position()));
444cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label1.Position()) + 4u,
445cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label1.Position()));
446cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label2.Position()) + 4u,
447cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label2.Position()));
448cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
449cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
450cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, TwoCbzSecondAtMaxB16Offset) {
451cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label0, label1, label2;
452cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ cbz(arm::R0, &label1);
453cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count1 = 62;
454cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count1; ++i) {
455cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
456cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
457cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label0);
458cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ cbz(arm::R0, &label2);
459cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label1);
460cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count2 = 128;
461cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count2; ++i) {
462cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
463cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
464cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label2);
465cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
466cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
467cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "cbz r0, 1f\n" +            // cbz r0, label1
468cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count1, "ldr r0, [r0]\n") +
469cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "0:\n"
470cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "cmp r0, #0\n"              // cbz r0, label2
471cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "beq.n 2f\n"
472cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n" +
473cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") +
474cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n";
475cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "TwoCbzSecondAtMaxB16Offset");
476cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
477cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label0.Position()) + 0u,
478cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label0.Position()));
479cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label1.Position()) + 2u,
480cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label1.Position()));
481cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label2.Position()) + 2u,
482cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label2.Position()));
483cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
484cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
485cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, TwoCbzSecondBeyondMaxB16Offset) {
486cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label0, label1, label2;
487cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ cbz(arm::R0, &label1);
488cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count1 = 62;
489cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count1; ++i) {
490cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
491cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
492cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label0);
493cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ cbz(arm::R0, &label2);
494cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label1);
495cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count2 = 129;
496cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count2; ++i) {
497cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
498cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
499cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label2);
500cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
501cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
502cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "cmp r0, #0\n"              // cbz r0, label1
503cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "beq.n 1f\n" +
504cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count1, "ldr r0, [r0]\n") +
505cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "0:\n"
506cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "cmp r0, #0\n"              // cbz r0, label2
507cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "beq.w 2f\n"
508cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n" +
509cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") +
510cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n";
511cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "TwoCbzSecondBeyondMaxB16Offset");
512cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
513cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label0.Position()) + 2u,
514cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label0.Position()));
515cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label1.Position()) + 6u,
516cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label1.Position()));
517cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label2.Position()) + 6u,
518cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label2.Position()));
519cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
520cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
521cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, TwoCbzFirstAtMaxB16Offset) {
522cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label0, label1, label2;
523cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ cbz(arm::R0, &label1);
524cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count1 = 127;
525cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count1; ++i) {
526cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
527cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
528cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label0);
529cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ cbz(arm::R0, &label2);
530cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label1);
531cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count2 = 64;
532cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count2; ++i) {
533cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
534cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
535cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label2);
536cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
537cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
538cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "cmp r0, #0\n"              // cbz r0, label1
539cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "beq.n 1f\n" +
540cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count1, "ldr r0, [r0]\n") +
541cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "0:\n"
542cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "cbz r0, 2f\n"              // cbz r0, label2
543cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n" +
544cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") +
545cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n";
546cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "TwoCbzFirstAtMaxB16Offset");
547cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
548cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label0.Position()) + 2u,
549cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label0.Position()));
550cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label1.Position()) + 2u,
551cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label1.Position()));
552cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label2.Position()) + 2u,
553cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label2.Position()));
554cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
555cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
556cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, TwoCbzFirstBeyondMaxB16Offset) {
557cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label0, label1, label2;
558cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ cbz(arm::R0, &label1);
559cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count1 = 127;
560cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count1; ++i) {
561cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
562cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
563cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label0);
564cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ cbz(arm::R0, &label2);
565cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label1);
566cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count2 = 65;
567cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count2; ++i) {
568cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
569cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
570cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label2);
571cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
572cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
573cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "cmp r0, #0\n"              // cbz r0, label1
574cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "beq.w 1f\n" +
575cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count1, "ldr r0, [r0]\n") +
576cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "0:\n"
577cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "cmp r0, #0\n"              // cbz r0, label2
578cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "beq.n 2f\n"
579cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n" +
580cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") +
581cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n";
582cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "TwoCbzFirstBeyondMaxB16Offset");
583cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
584cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label0.Position()) + 4u,
585cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label0.Position()));
586cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label1.Position()) + 6u,
587cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label1.Position()));
588cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label2.Position()) + 6u,
589cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label2.Position()));
590cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
591cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
592cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralMax1KiB) {
593cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678);
594cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ LoadLiteral(arm::R0, literal);
595cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label;
596cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label);
597cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count = 511;
598cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count; ++i) {
599cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
600cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
601cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
602cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
603cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n"
604cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "ldr.n r0, [pc, #((2f - 1b - 2) & ~2)]\n" +
605cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") +
606cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".align 2, 0\n"
607cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n"
608cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x12345678\n";
609cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "LoadLiteralMax1KiB");
610cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
611cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 0u,
612cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label.Position()));
613cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
614cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
615cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralBeyondMax1KiB) {
616cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678);
617cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ LoadLiteral(arm::R0, literal);
618cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label;
619cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label);
620cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count = 512;
621cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count; ++i) {
622cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
623cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
624cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
625cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
626cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n"
627cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "ldr.w r0, [pc, #((2f - 1b - 2) & ~2)]\n" +
628cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") +
629cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".align 2, 0\n"
630cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n"
631cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x12345678\n";
632cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "LoadLiteralBeyondMax1KiB");
633cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
634cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 2u,
635cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label.Position()));
636cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
637cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
638cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralMax4KiB) {
639cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678);
640cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ LoadLiteral(arm::R1, literal);
641cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label;
642cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label);
643cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count = 2046;
644cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count; ++i) {
645cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
646cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
647cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
648cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
649cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n"
650cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "ldr.w r1, [pc, #((2f - 1b - 2) & ~2)]\n" +
651cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") +
652cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".align 2, 0\n"
653cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n"
654cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x12345678\n";
655cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "LoadLiteralMax4KiB");
656cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
657cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 2u,
658cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label.Position()));
659cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
660cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
661cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralBeyondMax4KiB) {
662cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678);
663cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ LoadLiteral(arm::R1, literal);
664cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label;
665cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label);
666cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count = 2047;
667cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count; ++i) {
668cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
669cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
670cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
671cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
672cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "movw r1, #4096\n"  // "as" does not consider (2f - 1f - 4) a constant expression for movw.
673cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n"
674cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "add r1, pc\n"
675cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "ldr r1, [r1, #0]\n" +
676cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") +
677cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".align 2, 0\n"
678cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n"
679cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x12345678\n";
680cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "LoadLiteralBeyondMax4KiB");
681cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
682cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 6u,
683cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label.Position()));
684cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
685cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
686cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralMax64KiB) {
687cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678);
688cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ LoadLiteral(arm::R1, literal);
689cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label;
690cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label);
691cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count = (1u << 15) - 2u;
692cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count; ++i) {
693cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
694cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
695cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
696cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
697cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "movw r1, #0xfffc\n"  // "as" does not consider (2f - 1f - 4) a constant expression for movw.
698cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n"
699cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "add r1, pc\n"
700cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "ldr r1, [r1, #0]\n" +
701cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") +
702cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".align 2, 0\n"
703cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n"
704cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x12345678\n";
705cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "LoadLiteralMax64KiB");
706cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
707cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 6u,
708cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label.Position()));
709cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
710cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
711cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralBeyondMax64KiB) {
712cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678);
713cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ LoadLiteral(arm::R1, literal);
714cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label;
715cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label);
716cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count = (1u << 15) - 1u;
717cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count; ++i) {
718cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
719cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
720cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
721cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
722cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "mov.w r1, #((2f - 1f - 4) & ~0xfff)\n"
723cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n"
724cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "add r1, pc\n"
725cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "ldr r1, [r1, #((2f - 1b - 4) & 0xfff)]\n" +
726cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") +
727cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".align 2, 0\n"
728cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n"
729cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x12345678\n";
730cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "LoadLiteralBeyondMax64KiB");
731cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
732cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 8u,
733cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label.Position()));
734cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
735cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
736cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralMax1MiB) {
737cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678);
738cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ LoadLiteral(arm::R1, literal);
739cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label;
740cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label);
741cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count = (1u << 19) - 3u;
742cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count; ++i) {
743cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
744cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
745cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
746cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
747cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "mov.w r1, #((2f - 1f - 4) & ~0xfff)\n"
748cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n"
749cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "add r1, pc\n"
750cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "ldr r1, [r1, #((2f - 1b - 4) & 0xfff)]\n" +
751cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") +
752cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".align 2, 0\n"
753cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n"
754cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x12345678\n";
755cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "LoadLiteralMax1MiB");
756cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
757cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 8u,
758cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label.Position()));
759cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
760cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
761cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralBeyondMax1MiB) {
762cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678);
763cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ LoadLiteral(arm::R1, literal);
764cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label;
765cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label);
766cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count = (1u << 19) - 2u;
767cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count; ++i) {
768cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
769cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
770cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
771cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
772cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // "as" does not consider ((2f - 1f - 4) & 0xffff) a constant expression for movw.
773cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "movw r1, #(0x100000 & 0xffff)\n"
774cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // "as" does not consider ((2f - 1f - 4) >> 16) a constant expression for movt.
775cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "movt r1, #(0x100000 >> 16)\n"
776cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n"
777cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "add r1, pc\n"
778cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "ldr.w r1, [r1, #0]\n" +
779cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") +
780cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".align 2, 0\n"
781cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n"
782cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x12345678\n";
783cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "LoadLiteralBeyondMax1MiB");
784cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
785cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 12u,
786cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label.Position()));
787cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
788cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
789cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralFar) {
790cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678);
791cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ LoadLiteral(arm::R1, literal);
792cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label;
793cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label);
794cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count = (1u << 19) - 2u + 0x1234;
795cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count; ++i) {
796cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
797cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
798cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
799cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
800cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // "as" does not consider ((2f - 1f - 4) & 0xffff) a constant expression for movw.
801cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "movw r1, #((0x100000 + 2 * 0x1234) & 0xffff)\n"
802cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // "as" does not consider ((2f - 1f - 4) >> 16) a constant expression for movt.
803cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "movt r1, #((0x100000 + 2 * 0x1234) >> 16)\n"
804cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n"
805cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "add r1, pc\n"
806cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "ldr.w r1, [r1, #0]\n" +
807cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") +
808cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".align 2, 0\n"
809cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n"
810cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x12345678\n";
811cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "LoadLiteralFar");
812cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
813cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 12u,
814cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label.Position()));
815cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
816cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
817cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralWideMax1KiB) {
818cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  arm::Literal* literal = __ NewLiteral<int64_t>(INT64_C(0x1234567887654321));
819cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ LoadLiteral(arm::R1, arm::R3, literal);
820cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label;
821cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label);
822cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count = 510;
823cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count; ++i) {
824cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
825cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
826cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
827cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
828cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n"
829cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "ldrd r1, r3, [pc, #((2f - 1b - 2) & ~2)]\n" +
830cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") +
831cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".align 2, 0\n"
832cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n"
833cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x87654321\n"
834cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x12345678\n";
835cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "LoadLiteralWideMax1KiB");
836cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
837cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 0u,
838cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label.Position()));
839cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
840cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
841cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralWideBeyondMax1KiB) {
842cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  arm::Literal* literal = __ NewLiteral<int64_t>(INT64_C(0x1234567887654321));
843cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ LoadLiteral(arm::R1, arm::R3, literal);
844cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label;
845cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label);
846cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count = 511;
847cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count; ++i) {
848cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
849cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
850cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
851cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
852cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "mov.w ip, #((2f - 1f - 4) & ~0x3ff)\n"
853cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n"
854cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "add ip, pc\n"
855cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "ldrd r1, r3, [ip, #((2f - 1b - 4) & 0x3ff)]\n" +
856cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") +
857cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".align 2, 0\n"
858cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n"
859cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x87654321\n"
860cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x12345678\n";
861cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "LoadLiteralWideBeyondMax1KiB");
862cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
863cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 6u,
864cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label.Position()));
865cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
866cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
867cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralSingleMax256KiB) {
868cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // The literal size must match but the type doesn't, so use an int32_t rather than float.
869cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678);
870cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ LoadLiteral(arm::S3, literal);
871cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label;
872cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label);
873cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count = (1 << 17) - 3u;
874cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count; ++i) {
875cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
876cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
877cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
878cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
879cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "mov.w ip, #((2f - 1f - 4) & ~0x3ff)\n"
880cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n"
881cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "add ip, pc\n"
882cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "vldr s3, [ip, #((2f - 1b - 4) & 0x3ff)]\n" +
883cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") +
884cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".align 2, 0\n"
885cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n"
886cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x12345678\n";
887cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "LoadLiteralSingleMax256KiB");
888cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
889cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 6u,
890cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label.Position()));
891cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
892cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
893cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralDoubleBeyondMax256KiB) {
894cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // The literal size must match but the type doesn't, so use an int64_t rather than double.
895cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  arm::Literal* literal = __ NewLiteral<int64_t>(INT64_C(0x1234567887654321));
896cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ LoadLiteral(arm::D3, literal);
897cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label;
898cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label);
899cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count = (1 << 17) - 2u;
900cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count; ++i) {
901cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
902cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
903cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
904cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
905cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // "as" does not consider ((2f - 1f - 4) & 0xffff) a constant expression for movw.
906cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "movw ip, #(0x40000 & 0xffff)\n"
907cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // "as" does not consider ((2f - 1f - 4) >> 16) a constant expression for movt.
908cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "movt ip, #(0x40000 >> 16)\n"
909cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n"
910cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "add ip, pc\n"
911cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "vldr d3, [ip, #0]\n" +
912cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") +
913cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".align 2, 0\n"
914cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n"
915cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x87654321\n"
916cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x12345678\n";
917cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "LoadLiteralDoubleBeyondMax256KiB");
918cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
919cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 10u,
920cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label.Position()));
921cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
922cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
923cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralDoubleFar) {
924cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // The literal size must match but the type doesn't, so use an int64_t rather than double.
925cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  arm::Literal* literal = __ NewLiteral<int64_t>(INT64_C(0x1234567887654321));
926cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ LoadLiteral(arm::D3, literal);
927cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  Label label;
928cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  __ Bind(&label);
929cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  constexpr size_t kLdrR0R0Count = (1 << 17) - 2u + 0x1234;
930cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  for (size_t i = 0; i != kLdrR0R0Count; ++i) {
931cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
932cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
933cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
934cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  std::string expected =
935cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // "as" does not consider ((2f - 1f - 4) & 0xffff) a constant expression for movw.
936cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "movw ip, #((0x40000 + 2 * 0x1234) & 0xffff)\n"
937cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      // "as" does not consider ((2f - 1f - 4) >> 16) a constant expression for movt.
938cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "movt ip, #((0x40000 + 2 * 0x1234) >> 16)\n"
939cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "1:\n"
940cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "add ip, pc\n"
941cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "vldr d3, [ip, #0]\n" +
942cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") +
943cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".align 2, 0\n"
944cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      "2:\n"
945cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x87654321\n"
946cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ".word 0x12345678\n";
947cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  DriverStr(expected, "LoadLiteralDoubleFar");
948cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
949cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 10u,
950cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko            __ GetAdjustedPosition(label.Position()));
951cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko}
952cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
953663c93448e50599d411b2403585b90513dbf8e3aVladimir MarkoTEST_F(AssemblerThumb2Test, LoadLiteralBeyondMax1KiBDueToAlignmentOnSecondPass) {
954663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  // First part: as TwoCbzBeyondMaxOffset but add one 16-bit instruction to the end,
955663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  // so that the size is not Aligned<4>(.). On the first pass, the assembler resizes
956663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  // the second CBZ because it's out of range, then it will resize the first CBZ
957663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  // which has been pushed out of range. Thus, after the first pass, the code size
958663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  // will appear Aligned<4>(.) but the final size will not be.
959663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  Label label0, label1, label2;
960663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  __ cbz(arm::R0, &label1);
961663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  constexpr size_t kLdrR0R0Count1 = 63;
962663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  for (size_t i = 0; i != kLdrR0R0Count1; ++i) {
963663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
964663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  }
965663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  __ Bind(&label0);
966663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  __ cbz(arm::R0, &label2);
967663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  __ Bind(&label1);
968663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  constexpr size_t kLdrR0R0Count2 = 65;
969663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  for (size_t i = 0; i != kLdrR0R0Count2; ++i) {
970663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
971663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  }
972663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  __ Bind(&label2);
973663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  __ ldr(arm::R0, arm::Address(arm::R0));
974663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko
975663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  std::string expected_part1 =
976663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      "cmp r0, #0\n"              // cbz r0, label1
977663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      "beq.n 1f\n" +
978663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      RepeatInsn(kLdrR0R0Count1, "ldr r0, [r0]\n") +
979663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      "0:\n"
980663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      "cmp r0, #0\n"              // cbz r0, label2
981663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      "beq.n 2f\n"
982663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      "1:\n" +
983663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      RepeatInsn(kLdrR0R0Count2, "ldr r0, [r0]\n") +
984663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      "2:\n"                      // Here the offset is Aligned<4>(.).
985663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      "ldr r0, [r0]\n";           // Make the first part
986663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko
987663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  // Second part: as LoadLiteralMax1KiB with the caveat that the offset of the load
988663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  // literal will not be Aligned<4>(.) but it will appear to be when we process the
989663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  // instruction during the first pass, so the literal will need a padding and it
990663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  // will push the literal out of range, so we shall end up with "ldr.w".
991663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  arm::Literal* literal = __ NewLiteral<int32_t>(0x12345678);
992663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  __ LoadLiteral(arm::R0, literal);
993663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  Label label;
994663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  __ Bind(&label);
995663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  constexpr size_t kLdrR0R0Count = 511;
996663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  for (size_t i = 0; i != kLdrR0R0Count; ++i) {
997663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
998663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  }
999663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko
1000663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  std::string expected =
1001663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      expected_part1 +
1002663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      "1:\n"
1003663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      "ldr.w r0, [pc, #((2f - 1b - 2) & ~2)]\n" +
1004663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      RepeatInsn(kLdrR0R0Count, "ldr r0, [r0]\n") +
1005663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      ".align 2, 0\n"
1006663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      "2:\n"
1007663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko      ".word 0x12345678\n";
1008663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  DriverStr(expected, "LoadLiteralMax1KiB");
1009663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko
1010663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko  EXPECT_EQ(static_cast<uint32_t>(label.Position()) + 6u,
1011663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko            __ GetAdjustedPosition(label.Position()));
1012663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko}
1013663c93448e50599d411b2403585b90513dbf8e3aVladimir Marko
1014611d3395e9efc0ab8dbfa4a197fa022fbd8c7204Scott WakelingTEST_F(AssemblerThumb2Test, Clz) {
1015611d3395e9efc0ab8dbfa4a197fa022fbd8c7204Scott Wakeling  __ clz(arm::R0, arm::R1);
1016611d3395e9efc0ab8dbfa4a197fa022fbd8c7204Scott Wakeling
1017611d3395e9efc0ab8dbfa4a197fa022fbd8c7204Scott Wakeling  const char* expected = "clz r0, r1\n";
1018611d3395e9efc0ab8dbfa4a197fa022fbd8c7204Scott Wakeling
1019611d3395e9efc0ab8dbfa4a197fa022fbd8c7204Scott Wakeling  DriverStr(expected, "clz");
1020611d3395e9efc0ab8dbfa4a197fa022fbd8c7204Scott Wakeling}
1021611d3395e9efc0ab8dbfa4a197fa022fbd8c7204Scott Wakeling
10221a28fc43ea7daa624ada9af40e30de64d4e946a8Roland Levillain}  // namespace art
1023