1c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky/*
2c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * Copyright (C) 2015 The Android Open Source Project
3c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky *
4c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * Licensed under the Apache License, Version 2.0 (the "License");
5c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * you may not use this file except in compliance with the License.
6c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * You may obtain a copy of the License at
7c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky *
8c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky *      http://www.apache.org/licenses/LICENSE-2.0
9c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky *
10c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * Unless required by applicable law or agreed to in writing, software
11c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * distributed under the License is distributed on an "AS IS" BASIS,
12c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * See the License for the specific language governing permissions and
14c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * limitations under the License.
15c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky */
16c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
17c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#include <memory>
18c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#include <vector>
19c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
20c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#include "arch/instruction_set.h"
21c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#include "cfi_test.h"
22c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#include "gtest/gtest.h"
23c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#include "optimizing/code_generator.h"
240a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray#include "optimizing/optimizing_unit_test.h"
25c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#include "utils/assembler.h"
2610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko#include "utils/arm/assembler_thumb2.h"
2710ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko#include "utils/mips/assembler_mips.h"
28a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze#include "utils/mips64/assembler_mips64.h"
29c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
30c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#include "optimizing/optimizing_cfi_test_expected.inc"
31c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
32c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbeckynamespace art {
33c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
34c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky// Run the tests only on host.
35c60e1b755c5632dfeb04c333489ede52ee5c945fAndreas Gampe#ifndef __ANDROID__
36c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
37e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierclass OptimizingCFITest : public CFITest {
38c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky public:
39c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky  // Enable this flag to generate the expected outputs.
40c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky  static constexpr bool kGenerateExpected = false;
41c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
4210ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  OptimizingCFITest()
4310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko      : pool_(),
4410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko        allocator_(&pool_),
4510ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko        opts_(),
4610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko        isa_features_(),
4710ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko        graph_(nullptr),
4810ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko        code_gen_(),
4910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko        blocks_(allocator_.Adapter()) {}
5010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko
5110ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  void SetUpFrame(InstructionSet isa) {
52c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    // Setup simple context.
53c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    std::string error;
5410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    isa_features_.reset(InstructionSetFeatures::FromVariant(isa, "default", &error));
5510ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    graph_ = CreateGraph(&allocator_);
56c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    // Generate simple frame with some spills.
57d58b837ae41c6d8ce010c362e8f85bd938715900Vladimir Marko    code_gen_ = CodeGenerator::Create(graph_, isa, *isa_features_, opts_);
5810ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    code_gen_->GetAssembler()->cfi().SetEnabled(true);
59c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    const int frame_size = 64;
60c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    int core_reg = 0;
61c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    int fp_reg = 0;
62c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    for (int i = 0; i < 2; i++) {  // Two registers of each kind.
63c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky      for (; core_reg < 32; core_reg++) {
6410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko        if (code_gen_->IsCoreCalleeSaveRegister(core_reg)) {
65c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky          auto location = Location::RegisterLocation(core_reg);
6610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko          code_gen_->AddAllocatedRegister(location);
67c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky          core_reg++;
68c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky          break;
69c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky        }
70c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky      }
71c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky      for (; fp_reg < 32; fp_reg++) {
7210ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko        if (code_gen_->IsFloatingPointCalleeSaveRegister(fp_reg)) {
73c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky          auto location = Location::FpuRegisterLocation(fp_reg);
7410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko          code_gen_->AddAllocatedRegister(location);
75c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky          fp_reg++;
76c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky          break;
77c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky        }
78c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky      }
79c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    }
8010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    code_gen_->block_order_ = &blocks_;
8110ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    code_gen_->ComputeSpillMask();
8210ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    code_gen_->SetFrameSize(frame_size);
8310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    code_gen_->GenerateFrameEntry();
8410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  }
8510ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko
8610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  void Finish() {
8710ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    code_gen_->GenerateFrameExit();
8810ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    code_gen_->Finalize(&code_allocator_);
8910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  }
9010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko
9110ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  void Check(InstructionSet isa,
9210ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko             const char* isa_str,
9310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko             const std::vector<uint8_t>& expected_asm,
9410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko             const std::vector<uint8_t>& expected_cfi) {
95c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    // Get the outputs.
9610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    const std::vector<uint8_t>& actual_asm = code_allocator_.GetMemory();
9710ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    Assembler* opt_asm = code_gen_->GetAssembler();
98c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    const std::vector<uint8_t>& actual_cfi = *(opt_asm->cfi().data());
99c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
100c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    if (kGenerateExpected) {
101c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky      GenerateExpected(stdout, isa, isa_str, actual_asm, actual_cfi);
102c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    } else {
103c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky      EXPECT_EQ(expected_asm, actual_asm);
104c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky      EXPECT_EQ(expected_cfi, actual_cfi);
105c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    }
106c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky  }
10746325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky
10810ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  void TestImpl(InstructionSet isa, const char*
10910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko                isa_str,
11010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko                const std::vector<uint8_t>& expected_asm,
11110ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko                const std::vector<uint8_t>& expected_cfi) {
11210ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    SetUpFrame(isa);
11310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    Finish();
11410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    Check(isa, isa_str, expected_asm, expected_cfi);
11510ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  }
11610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko
11710ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  CodeGenerator* GetCodeGenerator() {
11810ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    return code_gen_.get();
11910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  }
12010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko
12146325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky private:
12246325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky  class InternalCodeAllocator : public CodeAllocator {
12346325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky   public:
12446325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky    InternalCodeAllocator() {}
12546325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky
12646325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky    virtual uint8_t* Allocate(size_t size) {
12746325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky      memory_.resize(size);
12846325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky      return memory_.data();
12946325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky    }
13046325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky
13146325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky    const std::vector<uint8_t>& GetMemory() { return memory_; }
13246325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky
13346325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky   private:
13446325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky    std::vector<uint8_t> memory_;
13546325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky
13646325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky    DISALLOW_COPY_AND_ASSIGN(InternalCodeAllocator);
13746325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky  };
13810ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko
13910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  ArenaPool pool_;
14010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  ArenaAllocator allocator_;
14110ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  CompilerOptions opts_;
14210ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  std::unique_ptr<const InstructionSetFeatures> isa_features_;
14310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  HGraph* graph_;
14410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  std::unique_ptr<CodeGenerator> code_gen_;
14510ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  ArenaVector<HBasicBlock*> blocks_;
14610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  InternalCodeAllocator code_allocator_;
147c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky};
148c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
14910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko#define TEST_ISA(isa)                                         \
15010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  TEST_F(OptimizingCFITest, isa) {                            \
15110ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    std::vector<uint8_t> expected_asm(                        \
15210ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko        expected_asm_##isa,                                   \
15310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko        expected_asm_##isa + arraysize(expected_asm_##isa));  \
15410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    std::vector<uint8_t> expected_cfi(                        \
15510ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko        expected_cfi_##isa,                                   \
15610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko        expected_cfi_##isa + arraysize(expected_cfi_##isa));  \
15710ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    TestImpl(isa, #isa, expected_asm, expected_cfi);          \
158c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky  }
159c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
160c6b4dd8980350aaf250f0185f73e9c42ec17cd57David SrbeckyTEST_ISA(kThumb2)
161c6b4dd8980350aaf250f0185f73e9c42ec17cd57David SrbeckyTEST_ISA(kArm64)
162c6b4dd8980350aaf250f0185f73e9c42ec17cd57David SrbeckyTEST_ISA(kX86)
163c6b4dd8980350aaf250f0185f73e9c42ec17cd57David SrbeckyTEST_ISA(kX86_64)
16410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir MarkoTEST_ISA(kMips)
16510ef6941648aad04d54527d4a7a6070bf7065e88Vladimir MarkoTEST_ISA(kMips64)
16610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko
16710ef6941648aad04d54527d4a7a6070bf7065e88Vladimir MarkoTEST_F(OptimizingCFITest, kThumb2Adjust) {
16810ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  std::vector<uint8_t> expected_asm(
16910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko      expected_asm_kThumb2_adjust,
17010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko      expected_asm_kThumb2_adjust + arraysize(expected_asm_kThumb2_adjust));
17110ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  std::vector<uint8_t> expected_cfi(
17210ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko      expected_cfi_kThumb2_adjust,
17310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko      expected_cfi_kThumb2_adjust + arraysize(expected_cfi_kThumb2_adjust));
17410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  SetUpFrame(kThumb2);
17510ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko#define __ down_cast<arm::Thumb2Assembler*>(GetCodeGenerator()->GetAssembler())->
17610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  Label target;
17710ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  __ CompareAndBranchIfZero(arm::R0, &target);
17810ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  // Push the target out of range of CBZ.
17910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  for (size_t i = 0; i != 65; ++i) {
18010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    __ ldr(arm::R0, arm::Address(arm::R0));
18110ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  }
18210ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  __ Bind(&target);
18310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko#undef __
18410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  Finish();
18510ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  Check(kThumb2, "kThumb2_adjust", expected_asm, expected_cfi);
18610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko}
18710ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko
18810ef6941648aad04d54527d4a7a6070bf7065e88Vladimir MarkoTEST_F(OptimizingCFITest, kMipsAdjust) {
18910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  // One NOP in delay slot, 1 << 15 NOPS have size 1 << 17 which exceeds 18-bit signed maximum.
19010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  static constexpr size_t kNumNops = 1u + (1u << 15);
19110ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  std::vector<uint8_t> expected_asm(
19210ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko      expected_asm_kMips_adjust_head,
19310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko      expected_asm_kMips_adjust_head + arraysize(expected_asm_kMips_adjust_head));
19410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  expected_asm.resize(expected_asm.size() + kNumNops * 4u, 0u);
19510ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  expected_asm.insert(
19610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko      expected_asm.end(),
19710ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko      expected_asm_kMips_adjust_tail,
19810ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko      expected_asm_kMips_adjust_tail + arraysize(expected_asm_kMips_adjust_tail));
19910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  std::vector<uint8_t> expected_cfi(
20010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko      expected_cfi_kMips_adjust,
20110ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko      expected_cfi_kMips_adjust + arraysize(expected_cfi_kMips_adjust));
20210ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  SetUpFrame(kMips);
20310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko#define __ down_cast<mips::MipsAssembler*>(GetCodeGenerator()->GetAssembler())->
20410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  mips::MipsLabel target;
20510ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  __ Beqz(mips::A0, &target);
20610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  // Push the target out of range of BEQZ.
20710ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  for (size_t i = 0; i != kNumNops; ++i) {
20810ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    __ Nop();
20910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  }
21010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  __ Bind(&target);
21110ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko#undef __
21210ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  Finish();
21310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  Check(kMips, "kMips_adjust", expected_asm, expected_cfi);
21410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko}
215c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
216a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey FrunzeTEST_F(OptimizingCFITest, kMips64Adjust) {
217a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  // One NOP in forbidden slot, 1 << 15 NOPS have size 1 << 17 which exceeds 18-bit signed maximum.
218a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  static constexpr size_t kNumNops = 1u + (1u << 15);
219a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  std::vector<uint8_t> expected_asm(
220a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze      expected_asm_kMips64_adjust_head,
221a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze      expected_asm_kMips64_adjust_head + arraysize(expected_asm_kMips64_adjust_head));
222a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  expected_asm.resize(expected_asm.size() + kNumNops * 4u, 0u);
223a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  expected_asm.insert(
224a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze      expected_asm.end(),
225a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze      expected_asm_kMips64_adjust_tail,
226a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze      expected_asm_kMips64_adjust_tail + arraysize(expected_asm_kMips64_adjust_tail));
227a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  std::vector<uint8_t> expected_cfi(
228a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze      expected_cfi_kMips64_adjust,
229a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze      expected_cfi_kMips64_adjust + arraysize(expected_cfi_kMips64_adjust));
230a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  SetUpFrame(kMips64);
231a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze#define __ down_cast<mips64::Mips64Assembler*>(GetCodeGenerator()->GetAssembler())->
232a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  mips64::Mips64Label target;
233a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  __ Beqc(mips64::A1, mips64::A2, &target);
234a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  // Push the target out of range of BEQC.
235a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  for (size_t i = 0; i != kNumNops; ++i) {
236a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze    __ Nop();
237a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  }
238a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  __ Bind(&target);
239a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze#undef __
240a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  Finish();
241a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze  Check(kMips64, "kMips64_adjust", expected_asm, expected_cfi);
242a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze}
243a0e87b0a97fadd54540ec7e8331b61bebd82d378Alexey Frunze
244c60e1b755c5632dfeb04c333489ede52ee5c945fAndreas Gampe#endif  // __ANDROID__
245c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
246c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky}  // namespace art
247