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