1849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe/*
2849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe * Copyright (C) 2014 The Android Open Source Project
3849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe *
4849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe * Licensed under the Apache License, Version 2.0 (the "License");
5849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe * you may not use this file except in compliance with the License.
6849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe * You may obtain a copy of the License at
7849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe *
8849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe *      http://www.apache.org/licenses/LICENSE-2.0
9849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe *
10849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe * Unless required by applicable law or agreed to in writing, software
11849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe * distributed under the License is distributed on an "AS IS" BASIS,
12849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe * See the License for the specific language governing permissions and
14849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe * limitations under the License.
15849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe */
16849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
17849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe#ifndef ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_TEST_H_
18849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe#define ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_TEST_H_
19849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
20849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe#include "utils/assembler_test.h"
21849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
22849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampenamespace art {
23849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
2473cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Markotemplate<typename Ass,
2573cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko         typename Reg,
2673cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko         typename FPReg,
2773cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko         typename Imm,
2873cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko         typename SOp,
2973cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko         typename Cond,
3073cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko         typename SetCc>
31849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampeclass AssemblerArmTest : public AssemblerTest<Ass, Reg, FPReg, Imm> {
32849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe public:
33849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  typedef AssemblerTest<Ass, Reg, FPReg, Imm> Base;
34849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
35849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  using Base::GetRegisters;
36849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  using Base::GetRegName;
37849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  using Base::CreateImmediate;
38849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  using Base::WarnOnCombinations;
39849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
40849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  static constexpr int64_t kFullImmRangeThreshold = 32;
41849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
42849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  virtual void FillImmediates(std::vector<Imm>& immediates, int64_t imm_min, int64_t imm_max) {
43849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    // Small range: do completely.
44849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    if (imm_max - imm_min <= kFullImmRangeThreshold) {
45849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      for (int64_t i = imm_min; i <= imm_max; ++i) {
46849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        immediates.push_back(CreateImmediate(i));
47849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
48849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    } else {
49849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      immediates.push_back(CreateImmediate(imm_min));
50849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      immediates.push_back(CreateImmediate(imm_max));
51849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      if (imm_min < imm_max - 1) {
52849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        immediates.push_back(CreateImmediate(imm_min + 1));
53849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
54849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      if (imm_min < imm_max - 2) {
55849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        immediates.push_back(CreateImmediate(imm_min + 2));
56849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
57849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      if (imm_min < imm_max - 3) {
58849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        immediates.push_back(CreateImmediate(imm_max - 1));
59849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
60849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      if (imm_min < imm_max - 4) {
61849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        immediates.push_back(CreateImmediate((imm_min + imm_max) / 2));
62849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
63849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    }
64849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  }
65849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
66849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  std::string RepeatRRIIC(void (Ass::*f)(Reg, Reg, Imm, Imm, Cond),
67849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                          int64_t imm1_min, int64_t imm1_max,
68849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                          int64_t imm2_min, int64_t imm2_max,
69849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                          std::string fmt) {
70849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    return RepeatTemplatedRRIIC(f, GetRegisters(), GetRegisters(),
71849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
72849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
73849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                imm1_min, imm1_max, imm2_min, imm2_max,
74849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                fmt);
75849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  }
76849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
77849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  template <typename Reg1, typename Reg2>
78849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  std::string RepeatTemplatedRRIIC(void (Ass::*f)(Reg1, Reg2, Imm, Imm, Cond),
79849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                   const std::vector<Reg1*> reg1_registers,
80849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                   const std::vector<Reg2*> reg2_registers,
81849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                   std::string (AssemblerArmTest::*GetName1)(const Reg1&),
82849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                   std::string (AssemblerArmTest::*GetName2)(const Reg2&),
83849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                   int64_t imm1_min, int64_t imm1_max,
84849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                   int64_t imm2_min, int64_t imm2_max,
85849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                   std::string fmt) {
86849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    std::vector<Imm> immediates1;
87849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    FillImmediates(immediates1, imm1_min, imm1_max);
88849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    std::vector<Imm> immediates2;
89849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    FillImmediates(immediates2, imm2_min, imm2_max);
90849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
91849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    std::vector<Cond>& cond = GetConditions();
92849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
93849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    WarnOnCombinations(cond.size() * immediates1.size() * immediates2.size() *
94849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                       reg1_registers.size() * reg2_registers.size());
95849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
96849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    std::ostringstream oss;
97849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    bool first = true;
98849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    for (Cond& c : cond) {
99849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      std::string after_cond = fmt;
100849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
101849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      size_t cond_index = after_cond.find(COND_TOKEN);
102849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      if (cond_index != std::string::npos) {
10373cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko        after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
104849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
105849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
106849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      for (Imm i : immediates1) {
107849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        std::string base = after_cond;
108849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
109849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        size_t imm1_index = base.find(IMM1_TOKEN);
110849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        if (imm1_index != std::string::npos) {
111849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          std::ostringstream sreg;
112849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          sreg << i;
113849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          std::string imm_string = sreg.str();
114849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          base.replace(imm1_index, ConstexprStrLen(IMM1_TOKEN), imm_string);
115849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        }
116849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
117849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        for (Imm j : immediates2) {
118849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          std::string base2 = base;
119849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
120849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          size_t imm2_index = base2.find(IMM2_TOKEN);
121849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          if (imm2_index != std::string::npos) {
122849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            std::ostringstream sreg;
123849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            sreg << j;
124849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            std::string imm_string = sreg.str();
125849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            base2.replace(imm2_index, ConstexprStrLen(IMM2_TOKEN), imm_string);
126849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          }
127849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
128849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          for (auto reg1 : reg1_registers) {
129849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            std::string base3 = base2;
130849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
131849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            std::string reg1_string = (this->*GetName1)(*reg1);
132849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            size_t reg1_index;
133849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            while ((reg1_index = base3.find(Base::REG1_TOKEN)) != std::string::npos) {
134849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              base3.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string);
135849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            }
136849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
137849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            for (auto reg2 : reg2_registers) {
138849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              std::string base4 = base3;
139849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
140849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              std::string reg2_string = (this->*GetName2)(*reg2);
141849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              size_t reg2_index;
142849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              while ((reg2_index = base4.find(Base::REG2_TOKEN)) != std::string::npos) {
143849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                base4.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string);
144849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              }
145849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
146849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              if (first) {
147849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                first = false;
148849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              } else {
149849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                oss << "\n";
150849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              }
151849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              oss << base4;
152849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
153849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              (Base::GetAssembler()->*f)(*reg1, *reg2, i, j, c);
154849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            }
155849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          }
156849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        }
157849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
158849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    }
159849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    // Add a newline at the end.
160849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    oss << "\n";
161849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
162849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    return oss.str();
163849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  }
164849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
165849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  std::string RepeatRRiiC(void (Ass::*f)(Reg, Reg, Imm, Imm, Cond),
166849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                          std::vector<std::pair<Imm, Imm>>& immediates,
167849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                          std::string fmt) {
168cad2f0acd86b792b8dba790791e6753948dbe7dfIgor Murashkin    return RepeatTemplatedRRiiC<Reg, Reg>(f, GetRegisters(), GetRegisters(),
169849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
170849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
171849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        immediates, fmt);
172849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  }
173849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
174849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  template <typename Reg1, typename Reg2>
175849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  std::string RepeatTemplatedRRiiC(void (Ass::*f)(Reg1, Reg2, Imm, Imm, Cond),
176849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        const std::vector<Reg1*> reg1_registers,
177849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        const std::vector<Reg2*> reg2_registers,
178849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        std::string (AssemblerArmTest::*GetName1)(const Reg1&),
179849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        std::string (AssemblerArmTest::*GetName2)(const Reg2&),
180849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        std::vector<std::pair<Imm, Imm>>& immediates,
181849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        std::string fmt) {
182849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    std::vector<Cond>& cond = GetConditions();
183849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
184849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    WarnOnCombinations(cond.size() * immediates.size() * reg1_registers.size() *
185849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                       reg2_registers.size());
186849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
187849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    std::ostringstream oss;
188849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    bool first = true;
189849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    for (Cond& c : cond) {
190849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      std::string after_cond = fmt;
191849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
192849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      size_t cond_index = after_cond.find(COND_TOKEN);
193849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      if (cond_index != std::string::npos) {
19473cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko        after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
195849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
196849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
197849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      for (std::pair<Imm, Imm>& pair : immediates) {
198849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        Imm i = pair.first;
199849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        Imm j = pair.second;
200849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        std::string after_imm1 = after_cond;
201849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
202849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        size_t imm1_index = after_imm1.find(IMM1_TOKEN);
203849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        if (imm1_index != std::string::npos) {
204849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          std::ostringstream sreg;
205849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          sreg << i;
206849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          std::string imm_string = sreg.str();
207849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          after_imm1.replace(imm1_index, ConstexprStrLen(IMM1_TOKEN), imm_string);
208849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        }
209849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
210849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        std::string after_imm2 = after_imm1;
211849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
212849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        size_t imm2_index = after_imm2.find(IMM2_TOKEN);
213849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        if (imm2_index != std::string::npos) {
214849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          std::ostringstream sreg;
215849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          sreg << j;
216849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          std::string imm_string = sreg.str();
217849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          after_imm2.replace(imm2_index, ConstexprStrLen(IMM2_TOKEN), imm_string);
218849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        }
219849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
220849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        for (auto reg1 : reg1_registers) {
221849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          std::string after_reg1 = after_imm2;
222849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
223849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          std::string reg1_string = (this->*GetName1)(*reg1);
224849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          size_t reg1_index;
225849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          while ((reg1_index = after_reg1.find(Base::REG1_TOKEN)) != std::string::npos) {
226849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            after_reg1.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string);
227849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          }
228849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
229849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          for (auto reg2 : reg2_registers) {
230849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            std::string after_reg2 = after_reg1;
231849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
232849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            std::string reg2_string = (this->*GetName2)(*reg2);
233849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            size_t reg2_index;
234849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            while ((reg2_index = after_reg2.find(Base::REG2_TOKEN)) != std::string::npos) {
235849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              after_reg2.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string);
236849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            }
237849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
238849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            if (first) {
239849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              first = false;
240849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            } else {
241849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              oss << "\n";
242849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            }
243849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            oss << after_reg2;
244849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
245849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            (Base::GetAssembler()->*f)(*reg1, *reg2, i, j, c);
246849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          }
247849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        }
248849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
249849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    }
250849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    // Add a newline at the end.
251849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    oss << "\n";
252849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
253849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    return oss.str();
254849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  }
255849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
256849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  std::string RepeatRRC(void (Ass::*f)(Reg, Reg, Cond), std::string fmt) {
257849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    return RepeatTemplatedRRC(f, GetRegisters(), GetRegisters(), GetConditions(),
258849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
259849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
260849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        fmt);
261849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  }
262849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
263849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  template <typename Reg1, typename Reg2>
264849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  std::string RepeatTemplatedRRC(void (Ass::*f)(Reg1, Reg2, Cond),
265849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                 const std::vector<Reg1*>& reg1_registers,
266849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                 const std::vector<Reg2*>& reg2_registers,
267849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                 const std::vector<Cond>& cond,
268849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                 std::string (AssemblerArmTest::*GetName1)(const Reg1&),
269849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                 std::string (AssemblerArmTest::*GetName2)(const Reg2&),
270849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                 std::string fmt) {
271849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    WarnOnCombinations(cond.size() * reg1_registers.size() * reg2_registers.size());
272849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
273849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    std::ostringstream oss;
274849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    bool first = true;
275849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    for (const Cond& c : cond) {
276849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      std::string after_cond = fmt;
277849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
278849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      size_t cond_index = after_cond.find(COND_TOKEN);
279849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      if (cond_index != std::string::npos) {
28073cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko        after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
281849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
282849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
283849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      for (auto reg1 : reg1_registers) {
284849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        std::string after_reg1 = after_cond;
285849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
286849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        std::string reg1_string = (this->*GetName1)(*reg1);
287849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        size_t reg1_index;
288849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        while ((reg1_index = after_reg1.find(Base::REG1_TOKEN)) != std::string::npos) {
289849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          after_reg1.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string);
290849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        }
291849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
292849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        for (auto reg2 : reg2_registers) {
293849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          std::string after_reg2 = after_reg1;
294849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
295849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          std::string reg2_string = (this->*GetName2)(*reg2);
296849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          size_t reg2_index;
297849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          while ((reg2_index = after_reg2.find(Base::REG2_TOKEN)) != std::string::npos) {
298849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            after_reg2.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string);
299849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          }
300849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
301849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          if (first) {
302849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            first = false;
303849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          } else {
304849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            oss << "\n";
305849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          }
306849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          oss << after_reg2;
307849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
308849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          (Base::GetAssembler()->*f)(*reg1, *reg2, c);
309849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        }
310849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
311849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    }
312849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    // Add a newline at the end.
313849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    oss << "\n";
314849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
315849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    return oss.str();
316849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  }
317849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
318849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  std::string RepeatRRRC(void (Ass::*f)(Reg, Reg, Reg, Cond), std::string fmt) {
319849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    return RepeatTemplatedRRRC(f, GetRegisters(), GetRegisters(), GetRegisters(), GetConditions(),
320849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                               &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
321849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                               &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
322849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                               &AssemblerArmTest::template GetRegName<RegisterView::kUsePrimaryName>,
323849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                               fmt);
324849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  }
325849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
326849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  template <typename Reg1, typename Reg2, typename Reg3>
327849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  std::string RepeatTemplatedRRRC(void (Ass::*f)(Reg1, Reg2, Reg3, Cond),
328849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                  const std::vector<Reg1*>& reg1_registers,
329849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                  const std::vector<Reg2*>& reg2_registers,
330849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                  const std::vector<Reg3*>& reg3_registers,
331849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                  const std::vector<Cond>& cond,
332849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                  std::string (AssemblerArmTest::*GetName1)(const Reg1&),
333849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                  std::string (AssemblerArmTest::*GetName2)(const Reg2&),
334849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                  std::string (AssemblerArmTest::*GetName3)(const Reg3&),
335849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                  std::string fmt) {
336849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    WarnOnCombinations(cond.size() * reg1_registers.size() * reg2_registers.size() *
337849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                       reg3_registers.size());
338849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
339849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    std::ostringstream oss;
340849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    bool first = true;
341849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    for (const Cond& c : cond) {
342849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      std::string after_cond = fmt;
343849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
344849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      size_t cond_index = after_cond.find(COND_TOKEN);
345849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      if (cond_index != std::string::npos) {
34673cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko        after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
347849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
348849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
349849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      for (auto reg1 : reg1_registers) {
350849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        std::string after_reg1 = after_cond;
351849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
352849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        std::string reg1_string = (this->*GetName1)(*reg1);
353849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        size_t reg1_index;
354849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        while ((reg1_index = after_reg1.find(Base::REG1_TOKEN)) != std::string::npos) {
355849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          after_reg1.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string);
356849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        }
357849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
358849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        for (auto reg2 : reg2_registers) {
359849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          std::string after_reg2 = after_reg1;
360849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
361849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          std::string reg2_string = (this->*GetName2)(*reg2);
362849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          size_t reg2_index;
363849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          while ((reg2_index = after_reg2.find(Base::REG2_TOKEN)) != std::string::npos) {
364849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            after_reg2.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string);
365849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          }
366849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
367849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          for (auto reg3 : reg3_registers) {
368849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            std::string after_reg3 = after_reg2;
369849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
370849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            std::string reg3_string = (this->*GetName3)(*reg3);
371849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            size_t reg3_index;
372849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            while ((reg3_index = after_reg3.find(REG3_TOKEN)) != std::string::npos) {
373849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              after_reg3.replace(reg3_index, ConstexprStrLen(REG3_TOKEN), reg3_string);
374849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            }
375849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
376849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            if (first) {
377849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              first = false;
378849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            } else {
379849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              oss << "\n";
380849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            }
381849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            oss << after_reg3;
382849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
383849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            (Base::GetAssembler()->*f)(*reg1, *reg2, *reg3, c);
384849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          }
385849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        }
386849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
387849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    }
388849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    // Add a newline at the end.
389849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    oss << "\n";
390849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
391849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    return oss.str();
392849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  }
393849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
394849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  template <typename RegT>
395849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  std::string RepeatTemplatedRSC(void (Ass::*f)(RegT, SOp, Cond),
396849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                 const std::vector<RegT*>& registers,
397849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                 const std::vector<SOp>& shifts,
398849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                 const std::vector<Cond>& cond,
399849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                 std::string (AssemblerArmTest::*GetName)(const RegT&),
400849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                 std::string fmt) {
401849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    WarnOnCombinations(cond.size() * registers.size() * shifts.size());
402849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
403849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    std::ostringstream oss;
404849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    bool first = true;
405849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    for (const Cond& c : cond) {
406849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      std::string after_cond = fmt;
407849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
408849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      size_t cond_index = after_cond.find(COND_TOKEN);
409849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      if (cond_index != std::string::npos) {
41073cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko        after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
411849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
412849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
413849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      for (const SOp& shift : shifts) {
414849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        std::string after_shift = after_cond;
415849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
416849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        std::string shift_string = GetShiftString(shift);
417849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        size_t shift_index;
418849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        while ((shift_index = after_shift.find(Base::SHIFT_TOKEN)) != std::string::npos) {
419849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          after_shift.replace(shift_index, ConstexprStrLen(Base::SHIFT_TOKEN), shift_string);
420849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        }
421849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
422849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        for (auto reg : registers) {
423849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          std::string after_reg = after_shift;
424849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
425849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          std::string reg_string = (this->*GetName)(*reg);
426849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          size_t reg_index;
427849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          while ((reg_index = after_reg.find(Base::REG_TOKEN)) != std::string::npos) {
428849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            after_reg.replace(reg_index, ConstexprStrLen(Base::REG_TOKEN), reg_string);
429849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          }
430849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
431849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          if (first) {
432849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            first = false;
433849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          } else {
434849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            oss << "\n";
435849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          }
436849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          oss << after_reg;
437849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
438849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          (Base::GetAssembler()->*f)(*reg, shift, c);
439849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        }
440849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
441849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    }
442849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    // Add a newline at the end.
443849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    oss << "\n";
444849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
445849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    return oss.str();
446849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  }
447849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
448849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  template <typename Reg1, typename Reg2>
449849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  std::string RepeatTemplatedRRSC(void (Ass::*f)(Reg1, Reg2, const SOp&, Cond),
450849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                  const std::vector<Reg1*>& reg1_registers,
451849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                  const std::vector<Reg2*>& reg2_registers,
452849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                  const std::vector<SOp>& shifts,
453849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                  const std::vector<Cond>& cond,
454849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                  std::string (AssemblerArmTest::*GetName1)(const Reg1&),
455849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                  std::string (AssemblerArmTest::*GetName2)(const Reg2&),
456849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe                                  std::string fmt) {
457849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    WarnOnCombinations(cond.size() * reg1_registers.size() * reg2_registers.size() * shifts.size());
458849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
459849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    std::ostringstream oss;
460849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    bool first = true;
461849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    for (const Cond& c : cond) {
462849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      std::string after_cond = fmt;
463849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
464849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      size_t cond_index = after_cond.find(COND_TOKEN);
465849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      if (cond_index != std::string::npos) {
46673cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko        after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
467849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
468849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
469849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      for (const SOp& shift : shifts) {
470849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        std::string after_shift = after_cond;
471849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
472849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        std::string shift_string = GetShiftString(shift);
473849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        size_t shift_index;
474849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        while ((shift_index = after_shift.find(SHIFT_TOKEN)) != std::string::npos) {
475849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          after_shift.replace(shift_index, ConstexprStrLen(SHIFT_TOKEN), shift_string);
476849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        }
477849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
478849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        for (auto reg1 : reg1_registers) {
479849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          std::string after_reg1 = after_shift;
480849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
481849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          std::string reg1_string = (this->*GetName1)(*reg1);
482849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          size_t reg1_index;
483849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          while ((reg1_index = after_reg1.find(Base::REG1_TOKEN)) != std::string::npos) {
484849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            after_reg1.replace(reg1_index, ConstexprStrLen(Base::REG1_TOKEN), reg1_string);
485849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          }
486849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
487849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          for (auto reg2 : reg2_registers) {
488849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            std::string after_reg2 = after_reg1;
489849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
490849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            std::string reg2_string = (this->*GetName2)(*reg2);
491849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            size_t reg2_index;
492849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            while ((reg2_index = after_reg2.find(Base::REG2_TOKEN)) != std::string::npos) {
493849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              after_reg2.replace(reg2_index, ConstexprStrLen(Base::REG2_TOKEN), reg2_string);
494849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            }
495849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
496849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            if (first) {
497849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              first = false;
498849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            } else {
499849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe              oss << "\n";
500849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            }
501849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            oss << after_reg2;
502849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
503849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe            (Base::GetAssembler()->*f)(*reg1, *reg2, shift, c);
504849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe          }
505849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        }
506849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
507849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    }
508849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    // Add a newline at the end.
509849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    oss << "\n";
510849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
511849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    return oss.str();
512849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  }
513849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
514849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe protected:
515849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  explicit AssemblerArmTest() {}
516849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
517849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  virtual std::vector<Cond>& GetConditions() = 0;
518849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  virtual std::string GetConditionString(Cond c) = 0;
519849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
52073cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual std::vector<SetCc>& GetSetCcs() = 0;
52173cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  virtual std::string GetSetCcString(SetCc s) = 0;
52273cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko
523849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  virtual std::vector<SOp>& GetShiftOperands() = 0;
524849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  virtual std::string GetShiftString(SOp sop) = 0;
525849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
526849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  virtual Reg GetPCRegister() = 0;
527849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  virtual std::vector<Reg*> GetRegistersWithoutPC() {
528849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    std::vector<Reg*> without_pc = GetRegisters();
529849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    Reg pc_reg = GetPCRegister();
530849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
531849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    for (auto it = without_pc.begin(); it != without_pc.end(); ++it) {
532849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      if (**it == pc_reg) {
533849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        without_pc.erase(it);
534849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe        break;
535849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe      }
536849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    }
537849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
538849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe    return without_pc;
539849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  }
540849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
541849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  static constexpr const char* IMM1_TOKEN = "{imm1}";
542849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  static constexpr const char* IMM2_TOKEN = "{imm2}";
543849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  static constexpr const char* REG3_TOKEN = "{reg3}";
544849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  static constexpr const char* REG4_TOKEN = "{reg4}";
545849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  static constexpr const char* COND_TOKEN = "{cond}";
54673cf0fb75de2a449ce4fe329b5f1fb42eef1372fVladimir Marko  static constexpr const char* SET_CC_TOKEN = "{s}";
547849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  static constexpr const char* SHIFT_TOKEN = "{shift}";
548849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
549849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe private:
550849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe  DISALLOW_COPY_AND_ASSIGN(AssemblerArmTest);
551849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe};
552849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
553849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe}  // namespace art
554849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe
555849cc5e54cbd05f4efbd6082e03547ed9284639fAndreas Gampe#endif  // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_TEST_H_
556