1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "assembler_mips.h"
18 
19 #include <map>
20 
21 #include "base/stl_util.h"
22 #include "utils/assembler_test.h"
23 
24 #define __ GetAssembler()->
25 
26 namespace art {
27 
28 struct MIPSCpuRegisterCompare {
operator ()art::MIPSCpuRegisterCompare29   bool operator()(const mips::Register& a, const mips::Register& b) const {
30     return a < b;
31   }
32 };
33 
34 class AssemblerMIPS32r6Test : public AssemblerTest<mips::MipsAssembler,
35                                                    mips::Register,
36                                                    mips::FRegister,
37                                                    uint32_t> {
38  public:
39   typedef AssemblerTest<mips::MipsAssembler, mips::Register, mips::FRegister, uint32_t> Base;
40 
AssemblerMIPS32r6Test()41   AssemblerMIPS32r6Test() :
42     instruction_set_features_(MipsInstructionSetFeatures::FromVariant("mips32r6", nullptr)) {
43   }
44 
45  protected:
46   // Get the typically used name for this architecture, e.g., aarch64, x86-64, ...
GetArchitectureString()47   std::string GetArchitectureString() OVERRIDE {
48     return "mips";
49   }
50 
GetAssemblerCmdName()51   std::string GetAssemblerCmdName() OVERRIDE {
52     // We assemble and link for MIPS32R6. See GetAssemblerParameters() for details.
53     return "gcc";
54   }
55 
GetAssemblerParameters()56   std::string GetAssemblerParameters() OVERRIDE {
57     // We assemble and link for MIPS32R6. The reason is that object files produced for MIPS32R6
58     // (and MIPS64R6) with the GNU assembler don't have correct final offsets in PC-relative
59     // branches in the .text section and so they require a relocation pass (there's a relocation
60     // section, .rela.text, that has the needed info to fix up the branches).
61     // We use "-modd-spreg" so we can use odd-numbered single precision FPU registers.
62     // We put the code at address 0x1000000 (instead of 0) to avoid overlapping with the
63     // .MIPS.abiflags section (there doesn't seem to be a way to suppress its generation easily).
64     return " -march=mips32r6 -modd-spreg -Wa,--no-warn"
65         " -Wl,-Ttext=0x1000000 -Wl,-e0x1000000 -nostdlib";
66   }
67 
Pad(std::vector<uint8_t> & data)68   void Pad(std::vector<uint8_t>& data) OVERRIDE {
69     // The GNU linker unconditionally pads the code segment with NOPs to a size that is a multiple
70     // of 16 and there doesn't appear to be a way to suppress this padding. Our assembler doesn't
71     // pad, so, in order for two assembler outputs to match, we need to match the padding as well.
72     // NOP is encoded as four zero bytes on MIPS.
73     size_t pad_size = RoundUp(data.size(), 16u) - data.size();
74     data.insert(data.end(), pad_size, 0);
75   }
76 
GetDisassembleParameters()77   std::string GetDisassembleParameters() OVERRIDE {
78     return " -D -bbinary -mmips:isa32r6";
79   }
80 
CreateAssembler(ArenaAllocator * arena)81   mips::MipsAssembler* CreateAssembler(ArenaAllocator* arena) OVERRIDE {
82     return new (arena) mips::MipsAssembler(arena, instruction_set_features_.get());
83   }
84 
SetUpHelpers()85   void SetUpHelpers() OVERRIDE {
86     if (registers_.size() == 0) {
87       registers_.push_back(new mips::Register(mips::ZERO));
88       registers_.push_back(new mips::Register(mips::AT));
89       registers_.push_back(new mips::Register(mips::V0));
90       registers_.push_back(new mips::Register(mips::V1));
91       registers_.push_back(new mips::Register(mips::A0));
92       registers_.push_back(new mips::Register(mips::A1));
93       registers_.push_back(new mips::Register(mips::A2));
94       registers_.push_back(new mips::Register(mips::A3));
95       registers_.push_back(new mips::Register(mips::T0));
96       registers_.push_back(new mips::Register(mips::T1));
97       registers_.push_back(new mips::Register(mips::T2));
98       registers_.push_back(new mips::Register(mips::T3));
99       registers_.push_back(new mips::Register(mips::T4));
100       registers_.push_back(new mips::Register(mips::T5));
101       registers_.push_back(new mips::Register(mips::T6));
102       registers_.push_back(new mips::Register(mips::T7));
103       registers_.push_back(new mips::Register(mips::S0));
104       registers_.push_back(new mips::Register(mips::S1));
105       registers_.push_back(new mips::Register(mips::S2));
106       registers_.push_back(new mips::Register(mips::S3));
107       registers_.push_back(new mips::Register(mips::S4));
108       registers_.push_back(new mips::Register(mips::S5));
109       registers_.push_back(new mips::Register(mips::S6));
110       registers_.push_back(new mips::Register(mips::S7));
111       registers_.push_back(new mips::Register(mips::T8));
112       registers_.push_back(new mips::Register(mips::T9));
113       registers_.push_back(new mips::Register(mips::K0));
114       registers_.push_back(new mips::Register(mips::K1));
115       registers_.push_back(new mips::Register(mips::GP));
116       registers_.push_back(new mips::Register(mips::SP));
117       registers_.push_back(new mips::Register(mips::FP));
118       registers_.push_back(new mips::Register(mips::RA));
119 
120       secondary_register_names_.emplace(mips::Register(mips::ZERO), "zero");
121       secondary_register_names_.emplace(mips::Register(mips::AT), "at");
122       secondary_register_names_.emplace(mips::Register(mips::V0), "v0");
123       secondary_register_names_.emplace(mips::Register(mips::V1), "v1");
124       secondary_register_names_.emplace(mips::Register(mips::A0), "a0");
125       secondary_register_names_.emplace(mips::Register(mips::A1), "a1");
126       secondary_register_names_.emplace(mips::Register(mips::A2), "a2");
127       secondary_register_names_.emplace(mips::Register(mips::A3), "a3");
128       secondary_register_names_.emplace(mips::Register(mips::T0), "t0");
129       secondary_register_names_.emplace(mips::Register(mips::T1), "t1");
130       secondary_register_names_.emplace(mips::Register(mips::T2), "t2");
131       secondary_register_names_.emplace(mips::Register(mips::T3), "t3");
132       secondary_register_names_.emplace(mips::Register(mips::T4), "t4");
133       secondary_register_names_.emplace(mips::Register(mips::T5), "t5");
134       secondary_register_names_.emplace(mips::Register(mips::T6), "t6");
135       secondary_register_names_.emplace(mips::Register(mips::T7), "t7");
136       secondary_register_names_.emplace(mips::Register(mips::S0), "s0");
137       secondary_register_names_.emplace(mips::Register(mips::S1), "s1");
138       secondary_register_names_.emplace(mips::Register(mips::S2), "s2");
139       secondary_register_names_.emplace(mips::Register(mips::S3), "s3");
140       secondary_register_names_.emplace(mips::Register(mips::S4), "s4");
141       secondary_register_names_.emplace(mips::Register(mips::S5), "s5");
142       secondary_register_names_.emplace(mips::Register(mips::S6), "s6");
143       secondary_register_names_.emplace(mips::Register(mips::S7), "s7");
144       secondary_register_names_.emplace(mips::Register(mips::T8), "t8");
145       secondary_register_names_.emplace(mips::Register(mips::T9), "t9");
146       secondary_register_names_.emplace(mips::Register(mips::K0), "k0");
147       secondary_register_names_.emplace(mips::Register(mips::K1), "k1");
148       secondary_register_names_.emplace(mips::Register(mips::GP), "gp");
149       secondary_register_names_.emplace(mips::Register(mips::SP), "sp");
150       secondary_register_names_.emplace(mips::Register(mips::FP), "fp");
151       secondary_register_names_.emplace(mips::Register(mips::RA), "ra");
152 
153       fp_registers_.push_back(new mips::FRegister(mips::F0));
154       fp_registers_.push_back(new mips::FRegister(mips::F1));
155       fp_registers_.push_back(new mips::FRegister(mips::F2));
156       fp_registers_.push_back(new mips::FRegister(mips::F3));
157       fp_registers_.push_back(new mips::FRegister(mips::F4));
158       fp_registers_.push_back(new mips::FRegister(mips::F5));
159       fp_registers_.push_back(new mips::FRegister(mips::F6));
160       fp_registers_.push_back(new mips::FRegister(mips::F7));
161       fp_registers_.push_back(new mips::FRegister(mips::F8));
162       fp_registers_.push_back(new mips::FRegister(mips::F9));
163       fp_registers_.push_back(new mips::FRegister(mips::F10));
164       fp_registers_.push_back(new mips::FRegister(mips::F11));
165       fp_registers_.push_back(new mips::FRegister(mips::F12));
166       fp_registers_.push_back(new mips::FRegister(mips::F13));
167       fp_registers_.push_back(new mips::FRegister(mips::F14));
168       fp_registers_.push_back(new mips::FRegister(mips::F15));
169       fp_registers_.push_back(new mips::FRegister(mips::F16));
170       fp_registers_.push_back(new mips::FRegister(mips::F17));
171       fp_registers_.push_back(new mips::FRegister(mips::F18));
172       fp_registers_.push_back(new mips::FRegister(mips::F19));
173       fp_registers_.push_back(new mips::FRegister(mips::F20));
174       fp_registers_.push_back(new mips::FRegister(mips::F21));
175       fp_registers_.push_back(new mips::FRegister(mips::F22));
176       fp_registers_.push_back(new mips::FRegister(mips::F23));
177       fp_registers_.push_back(new mips::FRegister(mips::F24));
178       fp_registers_.push_back(new mips::FRegister(mips::F25));
179       fp_registers_.push_back(new mips::FRegister(mips::F26));
180       fp_registers_.push_back(new mips::FRegister(mips::F27));
181       fp_registers_.push_back(new mips::FRegister(mips::F28));
182       fp_registers_.push_back(new mips::FRegister(mips::F29));
183       fp_registers_.push_back(new mips::FRegister(mips::F30));
184       fp_registers_.push_back(new mips::FRegister(mips::F31));
185     }
186   }
187 
TearDown()188   void TearDown() OVERRIDE {
189     AssemblerTest::TearDown();
190     STLDeleteElements(&registers_);
191     STLDeleteElements(&fp_registers_);
192   }
193 
GetRegisters()194   std::vector<mips::Register*> GetRegisters() OVERRIDE {
195     return registers_;
196   }
197 
GetFPRegisters()198   std::vector<mips::FRegister*> GetFPRegisters() OVERRIDE {
199     return fp_registers_;
200   }
201 
CreateImmediate(int64_t imm_value)202   uint32_t CreateImmediate(int64_t imm_value) OVERRIDE {
203     return imm_value;
204   }
205 
GetSecondaryRegisterName(const mips::Register & reg)206   std::string GetSecondaryRegisterName(const mips::Register& reg) OVERRIDE {
207     CHECK(secondary_register_names_.find(reg) != secondary_register_names_.end());
208     return secondary_register_names_[reg];
209   }
210 
RepeatInsn(size_t count,const std::string & insn)211   std::string RepeatInsn(size_t count, const std::string& insn) {
212     std::string result;
213     for (; count != 0u; --count) {
214       result += insn;
215     }
216     return result;
217   }
218 
BranchCondTwoRegsHelper(void (mips::MipsAssembler::* f)(mips::Register,mips::Register,mips::MipsLabel *),const std::string & instr_name)219   void BranchCondTwoRegsHelper(void (mips::MipsAssembler::*f)(mips::Register,
220                                                               mips::Register,
221                                                               mips::MipsLabel*),
222                                const std::string& instr_name) {
223     mips::MipsLabel label;
224     (Base::GetAssembler()->*f)(mips::A0, mips::A1, &label);
225     constexpr size_t kAdduCount1 = 63;
226     for (size_t i = 0; i != kAdduCount1; ++i) {
227       __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
228     }
229     __ Bind(&label);
230     constexpr size_t kAdduCount2 = 64;
231     for (size_t i = 0; i != kAdduCount2; ++i) {
232       __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
233     }
234     (Base::GetAssembler()->*f)(mips::A2, mips::A3, &label);
235 
236     std::string expected =
237         ".set noreorder\n" +
238         instr_name + " $a0, $a1, 1f\n"
239         "nop\n" +
240         RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
241         "1:\n" +
242         RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
243         instr_name + " $a2, $a3, 1b\n"
244         "nop\n";
245     DriverStr(expected, instr_name);
246   }
247 
248  private:
249   std::vector<mips::Register*> registers_;
250   std::map<mips::Register, std::string, MIPSCpuRegisterCompare> secondary_register_names_;
251 
252   std::vector<mips::FRegister*> fp_registers_;
253   std::unique_ptr<const MipsInstructionSetFeatures> instruction_set_features_;
254 };
255 
256 
TEST_F(AssemblerMIPS32r6Test,Toolchain)257 TEST_F(AssemblerMIPS32r6Test, Toolchain) {
258   EXPECT_TRUE(CheckTools());
259 }
260 
TEST_F(AssemblerMIPS32r6Test,MulR6)261 TEST_F(AssemblerMIPS32r6Test, MulR6) {
262   DriverStr(RepeatRRR(&mips::MipsAssembler::MulR6, "mul ${reg1}, ${reg2}, ${reg3}"), "MulR6");
263 }
264 
TEST_F(AssemblerMIPS32r6Test,MuhR6)265 TEST_F(AssemblerMIPS32r6Test, MuhR6) {
266   DriverStr(RepeatRRR(&mips::MipsAssembler::MuhR6, "muh ${reg1}, ${reg2}, ${reg3}"), "MuhR6");
267 }
268 
TEST_F(AssemblerMIPS32r6Test,MuhuR6)269 TEST_F(AssemblerMIPS32r6Test, MuhuR6) {
270   DriverStr(RepeatRRR(&mips::MipsAssembler::MuhuR6, "muhu ${reg1}, ${reg2}, ${reg3}"), "MuhuR6");
271 }
272 
TEST_F(AssemblerMIPS32r6Test,DivR6)273 TEST_F(AssemblerMIPS32r6Test, DivR6) {
274   DriverStr(RepeatRRR(&mips::MipsAssembler::DivR6, "div ${reg1}, ${reg2}, ${reg3}"), "DivR6");
275 }
276 
TEST_F(AssemblerMIPS32r6Test,ModR6)277 TEST_F(AssemblerMIPS32r6Test, ModR6) {
278   DriverStr(RepeatRRR(&mips::MipsAssembler::ModR6, "mod ${reg1}, ${reg2}, ${reg3}"), "ModR6");
279 }
280 
TEST_F(AssemblerMIPS32r6Test,DivuR6)281 TEST_F(AssemblerMIPS32r6Test, DivuR6) {
282   DriverStr(RepeatRRR(&mips::MipsAssembler::DivuR6, "divu ${reg1}, ${reg2}, ${reg3}"), "DivuR6");
283 }
284 
TEST_F(AssemblerMIPS32r6Test,ModuR6)285 TEST_F(AssemblerMIPS32r6Test, ModuR6) {
286   DriverStr(RepeatRRR(&mips::MipsAssembler::ModuR6, "modu ${reg1}, ${reg2}, ${reg3}"), "ModuR6");
287 }
288 
289 //////////
290 // MISC //
291 //////////
292 
TEST_F(AssemblerMIPS32r6Test,Aui)293 TEST_F(AssemblerMIPS32r6Test, Aui) {
294   DriverStr(RepeatRRIb(&mips::MipsAssembler::Aui, 16, "aui ${reg1}, ${reg2}, {imm}"), "Aui");
295 }
296 
TEST_F(AssemblerMIPS32r6Test,Auipc)297 TEST_F(AssemblerMIPS32r6Test, Auipc) {
298   DriverStr(RepeatRIb(&mips::MipsAssembler::Auipc, 16, "auipc ${reg}, {imm}"), "Auipc");
299 }
300 
TEST_F(AssemblerMIPS32r6Test,Lwpc)301 TEST_F(AssemblerMIPS32r6Test, Lwpc) {
302   // Lwpc() takes an unsigned 19-bit immediate, while the GNU assembler needs a signed offset,
303   // hence the sign extension from bit 18 with `imm - ((imm & 0x40000) << 1)`.
304   // The GNU assembler also wants the offset to be a multiple of 4, which it will shift right
305   // by 2 positions when encoding, hence `<< 2` to compensate for that shift.
306   // We capture the value of the immediate with `.set imm, {imm}` because the value is needed
307   // twice for the sign extension, but `{imm}` is substituted only once.
308   const char* code = ".set imm, {imm}\nlw ${reg}, ((imm - ((imm & 0x40000) << 1)) << 2)($pc)";
309   DriverStr(RepeatRIb(&mips::MipsAssembler::Lwpc, 19, code), "Lwpc");
310 }
311 
TEST_F(AssemblerMIPS32r6Test,Addiupc)312 TEST_F(AssemblerMIPS32r6Test, Addiupc) {
313   // The comment from the Lwpc() test applies to this Addiupc() test as well.
314   const char* code = ".set imm, {imm}\naddiupc ${reg}, (imm - ((imm & 0x40000) << 1)) << 2";
315   DriverStr(RepeatRIb(&mips::MipsAssembler::Addiupc, 19, code), "Addiupc");
316 }
317 
TEST_F(AssemblerMIPS32r6Test,Bitswap)318 TEST_F(AssemblerMIPS32r6Test, Bitswap) {
319   DriverStr(RepeatRR(&mips::MipsAssembler::Bitswap, "bitswap ${reg1}, ${reg2}"), "bitswap");
320 }
321 
TEST_F(AssemblerMIPS32r6Test,Lsa)322 TEST_F(AssemblerMIPS32r6Test, Lsa) {
323   DriverStr(RepeatRRRIb(&mips::MipsAssembler::Lsa,
324                         2,
325                         "lsa ${reg1}, ${reg2}, ${reg3}, {imm}",
326                         1),
327             "lsa");
328 }
329 
TEST_F(AssemblerMIPS32r6Test,Seleqz)330 TEST_F(AssemblerMIPS32r6Test, Seleqz) {
331   DriverStr(RepeatRRR(&mips::MipsAssembler::Seleqz, "seleqz ${reg1}, ${reg2}, ${reg3}"),
332             "seleqz");
333 }
334 
TEST_F(AssemblerMIPS32r6Test,Selnez)335 TEST_F(AssemblerMIPS32r6Test, Selnez) {
336   DriverStr(RepeatRRR(&mips::MipsAssembler::Selnez, "selnez ${reg1}, ${reg2}, ${reg3}"),
337             "selnez");
338 }
339 
TEST_F(AssemblerMIPS32r6Test,ClzR6)340 TEST_F(AssemblerMIPS32r6Test, ClzR6) {
341   DriverStr(RepeatRR(&mips::MipsAssembler::ClzR6, "clz ${reg1}, ${reg2}"), "clzR6");
342 }
343 
TEST_F(AssemblerMIPS32r6Test,CloR6)344 TEST_F(AssemblerMIPS32r6Test, CloR6) {
345   DriverStr(RepeatRR(&mips::MipsAssembler::CloR6, "clo ${reg1}, ${reg2}"), "cloR6");
346 }
347 
348 ////////////////////
349 // FLOATING POINT //
350 ////////////////////
351 
TEST_F(AssemblerMIPS32r6Test,SelS)352 TEST_F(AssemblerMIPS32r6Test, SelS) {
353   DriverStr(RepeatFFF(&mips::MipsAssembler::SelS, "sel.s ${reg1}, ${reg2}, ${reg3}"), "sel.s");
354 }
355 
TEST_F(AssemblerMIPS32r6Test,SelD)356 TEST_F(AssemblerMIPS32r6Test, SelD) {
357   DriverStr(RepeatFFF(&mips::MipsAssembler::SelD, "sel.d ${reg1}, ${reg2}, ${reg3}"), "sel.d");
358 }
359 
TEST_F(AssemblerMIPS32r6Test,SeleqzS)360 TEST_F(AssemblerMIPS32r6Test, SeleqzS) {
361   DriverStr(RepeatFFF(&mips::MipsAssembler::SeleqzS, "seleqz.s ${reg1}, ${reg2}, ${reg3}"),
362             "seleqz.s");
363 }
364 
TEST_F(AssemblerMIPS32r6Test,SeleqzD)365 TEST_F(AssemblerMIPS32r6Test, SeleqzD) {
366   DriverStr(RepeatFFF(&mips::MipsAssembler::SeleqzD, "seleqz.d ${reg1}, ${reg2}, ${reg3}"),
367             "seleqz.d");
368 }
369 
TEST_F(AssemblerMIPS32r6Test,SelnezS)370 TEST_F(AssemblerMIPS32r6Test, SelnezS) {
371   DriverStr(RepeatFFF(&mips::MipsAssembler::SelnezS, "selnez.s ${reg1}, ${reg2}, ${reg3}"),
372             "selnez.s");
373 }
374 
TEST_F(AssemblerMIPS32r6Test,SelnezD)375 TEST_F(AssemblerMIPS32r6Test, SelnezD) {
376   DriverStr(RepeatFFF(&mips::MipsAssembler::SelnezD, "selnez.d ${reg1}, ${reg2}, ${reg3}"),
377             "selnez.d");
378 }
379 
TEST_F(AssemblerMIPS32r6Test,ClassS)380 TEST_F(AssemblerMIPS32r6Test, ClassS) {
381   DriverStr(RepeatFF(&mips::MipsAssembler::ClassS, "class.s ${reg1}, ${reg2}"), "class.s");
382 }
383 
TEST_F(AssemblerMIPS32r6Test,ClassD)384 TEST_F(AssemblerMIPS32r6Test, ClassD) {
385   DriverStr(RepeatFF(&mips::MipsAssembler::ClassD, "class.d ${reg1}, ${reg2}"), "class.d");
386 }
387 
TEST_F(AssemblerMIPS32r6Test,MinS)388 TEST_F(AssemblerMIPS32r6Test, MinS) {
389   DriverStr(RepeatFFF(&mips::MipsAssembler::MinS, "min.s ${reg1}, ${reg2}, ${reg3}"), "min.s");
390 }
391 
TEST_F(AssemblerMIPS32r6Test,MinD)392 TEST_F(AssemblerMIPS32r6Test, MinD) {
393   DriverStr(RepeatFFF(&mips::MipsAssembler::MinD, "min.d ${reg1}, ${reg2}, ${reg3}"), "min.d");
394 }
395 
TEST_F(AssemblerMIPS32r6Test,MaxS)396 TEST_F(AssemblerMIPS32r6Test, MaxS) {
397   DriverStr(RepeatFFF(&mips::MipsAssembler::MaxS, "max.s ${reg1}, ${reg2}, ${reg3}"), "max.s");
398 }
399 
TEST_F(AssemblerMIPS32r6Test,MaxD)400 TEST_F(AssemblerMIPS32r6Test, MaxD) {
401   DriverStr(RepeatFFF(&mips::MipsAssembler::MaxD, "max.d ${reg1}, ${reg2}, ${reg3}"), "max.d");
402 }
403 
TEST_F(AssemblerMIPS32r6Test,CmpUnS)404 TEST_F(AssemblerMIPS32r6Test, CmpUnS) {
405   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUnS, "cmp.un.s ${reg1}, ${reg2}, ${reg3}"),
406             "cmp.un.s");
407 }
408 
TEST_F(AssemblerMIPS32r6Test,CmpEqS)409 TEST_F(AssemblerMIPS32r6Test, CmpEqS) {
410   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpEqS, "cmp.eq.s ${reg1}, ${reg2}, ${reg3}"),
411             "cmp.eq.s");
412 }
413 
TEST_F(AssemblerMIPS32r6Test,CmpUeqS)414 TEST_F(AssemblerMIPS32r6Test, CmpUeqS) {
415   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUeqS, "cmp.ueq.s ${reg1}, ${reg2}, ${reg3}"),
416             "cmp.ueq.s");
417 }
418 
TEST_F(AssemblerMIPS32r6Test,CmpLtS)419 TEST_F(AssemblerMIPS32r6Test, CmpLtS) {
420   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpLtS, "cmp.lt.s ${reg1}, ${reg2}, ${reg3}"),
421             "cmp.lt.s");
422 }
423 
TEST_F(AssemblerMIPS32r6Test,CmpUltS)424 TEST_F(AssemblerMIPS32r6Test, CmpUltS) {
425   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUltS, "cmp.ult.s ${reg1}, ${reg2}, ${reg3}"),
426             "cmp.ult.s");
427 }
428 
TEST_F(AssemblerMIPS32r6Test,CmpLeS)429 TEST_F(AssemblerMIPS32r6Test, CmpLeS) {
430   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpLeS, "cmp.le.s ${reg1}, ${reg2}, ${reg3}"),
431             "cmp.le.s");
432 }
433 
TEST_F(AssemblerMIPS32r6Test,CmpUleS)434 TEST_F(AssemblerMIPS32r6Test, CmpUleS) {
435   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUleS, "cmp.ule.s ${reg1}, ${reg2}, ${reg3}"),
436             "cmp.ule.s");
437 }
438 
TEST_F(AssemblerMIPS32r6Test,CmpOrS)439 TEST_F(AssemblerMIPS32r6Test, CmpOrS) {
440   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpOrS, "cmp.or.s ${reg1}, ${reg2}, ${reg3}"),
441             "cmp.or.s");
442 }
443 
TEST_F(AssemblerMIPS32r6Test,CmpUneS)444 TEST_F(AssemblerMIPS32r6Test, CmpUneS) {
445   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUneS, "cmp.une.s ${reg1}, ${reg2}, ${reg3}"),
446             "cmp.une.s");
447 }
448 
TEST_F(AssemblerMIPS32r6Test,CmpNeS)449 TEST_F(AssemblerMIPS32r6Test, CmpNeS) {
450   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpNeS, "cmp.ne.s ${reg1}, ${reg2}, ${reg3}"),
451             "cmp.ne.s");
452 }
453 
TEST_F(AssemblerMIPS32r6Test,CmpUnD)454 TEST_F(AssemblerMIPS32r6Test, CmpUnD) {
455   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUnD, "cmp.un.d ${reg1}, ${reg2}, ${reg3}"),
456             "cmp.un.d");
457 }
458 
TEST_F(AssemblerMIPS32r6Test,CmpEqD)459 TEST_F(AssemblerMIPS32r6Test, CmpEqD) {
460   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpEqD, "cmp.eq.d ${reg1}, ${reg2}, ${reg3}"),
461             "cmp.eq.d");
462 }
463 
TEST_F(AssemblerMIPS32r6Test,CmpUeqD)464 TEST_F(AssemblerMIPS32r6Test, CmpUeqD) {
465   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUeqD, "cmp.ueq.d ${reg1}, ${reg2}, ${reg3}"),
466             "cmp.ueq.d");
467 }
468 
TEST_F(AssemblerMIPS32r6Test,CmpLtD)469 TEST_F(AssemblerMIPS32r6Test, CmpLtD) {
470   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpLtD, "cmp.lt.d ${reg1}, ${reg2}, ${reg3}"),
471             "cmp.lt.d");
472 }
473 
TEST_F(AssemblerMIPS32r6Test,CmpUltD)474 TEST_F(AssemblerMIPS32r6Test, CmpUltD) {
475   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUltD, "cmp.ult.d ${reg1}, ${reg2}, ${reg3}"),
476             "cmp.ult.d");
477 }
478 
TEST_F(AssemblerMIPS32r6Test,CmpLeD)479 TEST_F(AssemblerMIPS32r6Test, CmpLeD) {
480   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpLeD, "cmp.le.d ${reg1}, ${reg2}, ${reg3}"),
481             "cmp.le.d");
482 }
483 
TEST_F(AssemblerMIPS32r6Test,CmpUleD)484 TEST_F(AssemblerMIPS32r6Test, CmpUleD) {
485   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUleD, "cmp.ule.d ${reg1}, ${reg2}, ${reg3}"),
486             "cmp.ule.d");
487 }
488 
TEST_F(AssemblerMIPS32r6Test,CmpOrD)489 TEST_F(AssemblerMIPS32r6Test, CmpOrD) {
490   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpOrD, "cmp.or.d ${reg1}, ${reg2}, ${reg3}"),
491             "cmp.or.d");
492 }
493 
TEST_F(AssemblerMIPS32r6Test,CmpUneD)494 TEST_F(AssemblerMIPS32r6Test, CmpUneD) {
495   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUneD, "cmp.une.d ${reg1}, ${reg2}, ${reg3}"),
496             "cmp.une.d");
497 }
498 
TEST_F(AssemblerMIPS32r6Test,CmpNeD)499 TEST_F(AssemblerMIPS32r6Test, CmpNeD) {
500   DriverStr(RepeatFFF(&mips::MipsAssembler::CmpNeD, "cmp.ne.d ${reg1}, ${reg2}, ${reg3}"),
501             "cmp.ne.d");
502 }
503 
TEST_F(AssemblerMIPS32r6Test,LoadDFromOffset)504 TEST_F(AssemblerMIPS32r6Test, LoadDFromOffset) {
505   __ LoadDFromOffset(mips::F0, mips::A0, -0x8000);
506   __ LoadDFromOffset(mips::F0, mips::A0, +0);
507   __ LoadDFromOffset(mips::F0, mips::A0, +0x7FF8);
508   __ LoadDFromOffset(mips::F0, mips::A0, +0x7FFB);
509   __ LoadDFromOffset(mips::F0, mips::A0, +0x7FFC);
510   __ LoadDFromOffset(mips::F0, mips::A0, +0x7FFF);
511   __ LoadDFromOffset(mips::F0, mips::A0, -0xFFF0);
512   __ LoadDFromOffset(mips::F0, mips::A0, -0x8008);
513   __ LoadDFromOffset(mips::F0, mips::A0, -0x8001);
514   __ LoadDFromOffset(mips::F0, mips::A0, +0x8000);
515   __ LoadDFromOffset(mips::F0, mips::A0, +0xFFF0);
516   __ LoadDFromOffset(mips::F0, mips::A0, -0x17FE8);
517   __ LoadDFromOffset(mips::F0, mips::A0, -0x0FFF8);
518   __ LoadDFromOffset(mips::F0, mips::A0, -0x0FFF1);
519   __ LoadDFromOffset(mips::F0, mips::A0, +0x0FFF1);
520   __ LoadDFromOffset(mips::F0, mips::A0, +0x0FFF8);
521   __ LoadDFromOffset(mips::F0, mips::A0, +0x17FE8);
522   __ LoadDFromOffset(mips::F0, mips::A0, -0x17FF0);
523   __ LoadDFromOffset(mips::F0, mips::A0, -0x17FE9);
524   __ LoadDFromOffset(mips::F0, mips::A0, +0x17FE9);
525   __ LoadDFromOffset(mips::F0, mips::A0, +0x17FF0);
526   __ LoadDFromOffset(mips::F0, mips::A0, +0x12345678);
527 
528   const char* expected =
529       "ldc1 $f0, -0x8000($a0)\n"
530       "ldc1 $f0, 0($a0)\n"
531       "ldc1 $f0, 0x7FF8($a0)\n"
532       "lwc1 $f0, 0x7FFB($a0)\n"
533       "lw $t8, 0x7FFF($a0)\n"
534       "mthc1 $t8, $f0\n"
535       "addiu $at, $a0, 0x7FF8\n"
536       "lwc1 $f0, 4($at)\n"
537       "lw $t8, 8($at)\n"
538       "mthc1 $t8, $f0\n"
539       "addiu $at, $a0, 0x7FF8\n"
540       "lwc1 $f0, 7($at)\n"
541       "lw $t8, 11($at)\n"
542       "mthc1 $t8, $f0\n"
543       "addiu $at, $a0, -0x7FF8\n"
544       "ldc1 $f0, -0x7FF8($at)\n"
545       "addiu $at, $a0, -0x7FF8\n"
546       "ldc1 $f0, -0x10($at)\n"
547       "addiu $at, $a0, -0x7FF8\n"
548       "lwc1 $f0, -9($at)\n"
549       "lw $t8, -5($at)\n"
550       "mthc1 $t8, $f0\n"
551       "addiu $at, $a0, 0x7FF8\n"
552       "ldc1 $f0, 8($at)\n"
553       "addiu $at, $a0, 0x7FF8\n"
554       "ldc1 $f0, 0x7FF8($at)\n"
555       "aui $at, $a0, 0xFFFF\n"
556       "ldc1 $f0, -0x7FE8($at)\n"
557       "aui $at, $a0, 0xFFFF\n"
558       "ldc1 $f0, 0x8($at)\n"
559       "aui $at, $a0, 0xFFFF\n"
560       "lwc1 $f0, 0xF($at)\n"
561       "lw $t8, 0x13($at)\n"
562       "mthc1 $t8, $f0\n"
563       "aui $at, $a0, 0x1\n"
564       "lwc1 $f0, -0xF($at)\n"
565       "lw $t8, -0xB($at)\n"
566       "mthc1 $t8, $f0\n"
567       "aui $at, $a0, 0x1\n"
568       "ldc1 $f0, -0x8($at)\n"
569       "aui $at, $a0, 0x1\n"
570       "ldc1 $f0, 0x7FE8($at)\n"
571       "aui $at, $a0, 0xFFFF\n"
572       "ldc1 $f0, -0x7FF0($at)\n"
573       "aui $at, $a0, 0xFFFF\n"
574       "lwc1 $f0, -0x7FE9($at)\n"
575       "lw $t8, -0x7FE5($at)\n"
576       "mthc1 $t8, $f0\n"
577       "aui $at, $a0, 0x1\n"
578       "lwc1 $f0, 0x7FE9($at)\n"
579       "lw $t8, 0x7FED($at)\n"
580       "mthc1 $t8, $f0\n"
581       "aui $at, $a0, 0x1\n"
582       "ldc1 $f0, 0x7FF0($at)\n"
583       "aui $at, $a0, 0x1234\n"
584       "ldc1 $f0, 0x5678($at)\n";
585   DriverStr(expected, "LoadDFromOffset");
586 }
587 
TEST_F(AssemblerMIPS32r6Test,StoreDToOffset)588 TEST_F(AssemblerMIPS32r6Test, StoreDToOffset) {
589   __ StoreDToOffset(mips::F0, mips::A0, -0x8000);
590   __ StoreDToOffset(mips::F0, mips::A0, +0);
591   __ StoreDToOffset(mips::F0, mips::A0, +0x7FF8);
592   __ StoreDToOffset(mips::F0, mips::A0, +0x7FFB);
593   __ StoreDToOffset(mips::F0, mips::A0, +0x7FFC);
594   __ StoreDToOffset(mips::F0, mips::A0, +0x7FFF);
595   __ StoreDToOffset(mips::F0, mips::A0, -0xFFF0);
596   __ StoreDToOffset(mips::F0, mips::A0, -0x8008);
597   __ StoreDToOffset(mips::F0, mips::A0, -0x8001);
598   __ StoreDToOffset(mips::F0, mips::A0, +0x8000);
599   __ StoreDToOffset(mips::F0, mips::A0, +0xFFF0);
600   __ StoreDToOffset(mips::F0, mips::A0, -0x17FE8);
601   __ StoreDToOffset(mips::F0, mips::A0, -0x0FFF8);
602   __ StoreDToOffset(mips::F0, mips::A0, -0x0FFF1);
603   __ StoreDToOffset(mips::F0, mips::A0, +0x0FFF1);
604   __ StoreDToOffset(mips::F0, mips::A0, +0x0FFF8);
605   __ StoreDToOffset(mips::F0, mips::A0, +0x17FE8);
606   __ StoreDToOffset(mips::F0, mips::A0, -0x17FF0);
607   __ StoreDToOffset(mips::F0, mips::A0, -0x17FE9);
608   __ StoreDToOffset(mips::F0, mips::A0, +0x17FE9);
609   __ StoreDToOffset(mips::F0, mips::A0, +0x17FF0);
610   __ StoreDToOffset(mips::F0, mips::A0, +0x12345678);
611 
612   const char* expected =
613       "sdc1 $f0, -0x8000($a0)\n"
614       "sdc1 $f0, 0($a0)\n"
615       "sdc1 $f0, 0x7FF8($a0)\n"
616       "mfhc1 $t8, $f0\n"
617       "swc1 $f0, 0x7FFB($a0)\n"
618       "sw $t8, 0x7FFF($a0)\n"
619       "addiu $at, $a0, 0x7FF8\n"
620       "mfhc1 $t8, $f0\n"
621       "swc1 $f0, 4($at)\n"
622       "sw $t8, 8($at)\n"
623       "addiu $at, $a0, 0x7FF8\n"
624       "mfhc1 $t8, $f0\n"
625       "swc1 $f0, 7($at)\n"
626       "sw $t8, 11($at)\n"
627       "addiu $at, $a0, -0x7FF8\n"
628       "sdc1 $f0, -0x7FF8($at)\n"
629       "addiu $at, $a0, -0x7FF8\n"
630       "sdc1 $f0, -0x10($at)\n"
631       "addiu $at, $a0, -0x7FF8\n"
632       "mfhc1 $t8, $f0\n"
633       "swc1 $f0, -9($at)\n"
634       "sw $t8, -5($at)\n"
635       "addiu $at, $a0, 0x7FF8\n"
636       "sdc1 $f0, 8($at)\n"
637       "addiu $at, $a0, 0x7FF8\n"
638       "sdc1 $f0, 0x7FF8($at)\n"
639       "aui $at, $a0, 0xFFFF\n"
640       "sdc1 $f0, -0x7FE8($at)\n"
641       "aui $at, $a0, 0xFFFF\n"
642       "sdc1 $f0, 0x8($at)\n"
643       "aui $at, $a0, 0xFFFF\n"
644       "mfhc1 $t8, $f0\n"
645       "swc1 $f0, 0xF($at)\n"
646       "sw $t8, 0x13($at)\n"
647       "aui $at, $a0, 0x1\n"
648       "mfhc1 $t8, $f0\n"
649       "swc1 $f0, -0xF($at)\n"
650       "sw $t8, -0xB($at)\n"
651       "aui $at, $a0, 0x1\n"
652       "sdc1 $f0, -0x8($at)\n"
653       "aui $at, $a0, 0x1\n"
654       "sdc1 $f0, 0x7FE8($at)\n"
655       "aui $at, $a0, 0xFFFF\n"
656       "sdc1 $f0, -0x7FF0($at)\n"
657       "aui $at, $a0, 0xFFFF\n"
658       "mfhc1 $t8, $f0\n"
659       "swc1 $f0, -0x7FE9($at)\n"
660       "sw $t8, -0x7FE5($at)\n"
661       "aui $at, $a0, 0x1\n"
662       "mfhc1 $t8, $f0\n"
663       "swc1 $f0, 0x7FE9($at)\n"
664       "sw $t8, 0x7FED($at)\n"
665       "aui $at, $a0, 0x1\n"
666       "sdc1 $f0, 0x7FF0($at)\n"
667       "aui $at, $a0, 0x1234\n"
668       "sdc1 $f0, 0x5678($at)\n";
669   DriverStr(expected, "StoreDToOffset");
670 }
671 
TEST_F(AssemblerMIPS32r6Test,LoadFarthestNearLabelAddress)672 TEST_F(AssemblerMIPS32r6Test, LoadFarthestNearLabelAddress) {
673   mips::MipsLabel label;
674   __ LoadLabelAddress(mips::V0, mips::ZERO, &label);
675   constexpr size_t kAdduCount = 0x3FFDE;
676   for (size_t i = 0; i != kAdduCount; ++i) {
677     __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
678   }
679   __ Bind(&label);
680 
681   std::string expected =
682       "lapc $v0, 1f\n" +
683       RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
684       "1:\n";
685   DriverStr(expected, "LoadFarthestNearLabelAddress");
686 }
687 
TEST_F(AssemblerMIPS32r6Test,LoadNearestFarLabelAddress)688 TEST_F(AssemblerMIPS32r6Test, LoadNearestFarLabelAddress) {
689   mips::MipsLabel label;
690   __ LoadLabelAddress(mips::V0, mips::ZERO, &label);
691   constexpr size_t kAdduCount = 0x3FFDF;
692   for (size_t i = 0; i != kAdduCount; ++i) {
693     __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
694   }
695   __ Bind(&label);
696 
697   std::string expected =
698       "1:\n"
699       "auipc $at, %hi(2f - 1b)\n"
700       "addiu $v0, $at, %lo(2f - 1b)\n" +
701       RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
702       "2:\n";
703   DriverStr(expected, "LoadNearestFarLabelAddress");
704 }
705 
TEST_F(AssemblerMIPS32r6Test,LoadFarthestNearLiteral)706 TEST_F(AssemblerMIPS32r6Test, LoadFarthestNearLiteral) {
707   mips::Literal* literal = __ NewLiteral<uint32_t>(0x12345678);
708   __ LoadLiteral(mips::V0, mips::ZERO, literal);
709   constexpr size_t kAdduCount = 0x3FFDE;
710   for (size_t i = 0; i != kAdduCount; ++i) {
711     __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
712   }
713 
714   std::string expected =
715       "lwpc $v0, 1f\n" +
716       RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
717       "1:\n"
718       ".word 0x12345678\n";
719   DriverStr(expected, "LoadFarthestNearLiteral");
720 }
721 
TEST_F(AssemblerMIPS32r6Test,LoadNearestFarLiteral)722 TEST_F(AssemblerMIPS32r6Test, LoadNearestFarLiteral) {
723   mips::Literal* literal = __ NewLiteral<uint32_t>(0x12345678);
724   __ LoadLiteral(mips::V0, mips::ZERO, literal);
725   constexpr size_t kAdduCount = 0x3FFDF;
726   for (size_t i = 0; i != kAdduCount; ++i) {
727     __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
728   }
729 
730   std::string expected =
731       "1:\n"
732       "auipc $at, %hi(2f - 1b)\n"
733       "lw $v0, %lo(2f - 1b)($at)\n" +
734       RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
735       "2:\n"
736       ".word 0x12345678\n";
737   DriverStr(expected, "LoadNearestFarLiteral");
738 }
739 
740 //////////////
741 // BRANCHES //
742 //////////////
743 
TEST_F(AssemblerMIPS32r6Test,ImpossibleReordering)744 TEST_F(AssemblerMIPS32r6Test, ImpossibleReordering) {
745   mips::MipsLabel label;
746   __ SetReorder(true);
747   __ Bind(&label);
748 
749   __ CmpLtD(mips::F0, mips::F2, mips::F4);
750   __ Bc1nez(mips::F0, &label);  // F0 dependency.
751 
752   __ MulD(mips::F10, mips::F2, mips::F4);
753   __ Bc1eqz(mips::F10, &label);  // F10 dependency.
754 
755   std::string expected =
756       ".set noreorder\n"
757       "1:\n"
758 
759       "cmp.lt.d $f0, $f2, $f4\n"
760       "bc1nez $f0, 1b\n"
761       "nop\n"
762 
763       "mul.d $f10, $f2, $f4\n"
764       "bc1eqz $f10, 1b\n"
765       "nop\n";
766   DriverStr(expected, "ImpossibleReordering");
767 }
768 
TEST_F(AssemblerMIPS32r6Test,Reordering)769 TEST_F(AssemblerMIPS32r6Test, Reordering) {
770   mips::MipsLabel label;
771   __ SetReorder(true);
772   __ Bind(&label);
773 
774   __ CmpLtD(mips::F0, mips::F2, mips::F4);
775   __ Bc1nez(mips::F2, &label);
776 
777   __ MulD(mips::F0, mips::F2, mips::F4);
778   __ Bc1eqz(mips::F4, &label);
779 
780   std::string expected =
781       ".set noreorder\n"
782       "1:\n"
783 
784       "bc1nez $f2, 1b\n"
785       "cmp.lt.d $f0, $f2, $f4\n"
786 
787       "bc1eqz $f4, 1b\n"
788       "mul.d $f0, $f2, $f4\n";
789   DriverStr(expected, "Reordering");
790 }
791 
TEST_F(AssemblerMIPS32r6Test,SetReorder)792 TEST_F(AssemblerMIPS32r6Test, SetReorder) {
793   mips::MipsLabel label1, label2, label3, label4;
794 
795   __ SetReorder(true);
796   __ Bind(&label1);
797   __ Addu(mips::T0, mips::T1, mips::T2);
798   __ Bc1nez(mips::F0, &label1);
799 
800   __ SetReorder(false);
801   __ Bind(&label2);
802   __ Addu(mips::T0, mips::T1, mips::T2);
803   __ Bc1nez(mips::F0, &label2);
804 
805   __ SetReorder(true);
806   __ Bind(&label3);
807   __ Addu(mips::T0, mips::T1, mips::T2);
808   __ Bc1eqz(mips::F0, &label3);
809 
810   __ SetReorder(false);
811   __ Bind(&label4);
812   __ Addu(mips::T0, mips::T1, mips::T2);
813   __ Bc1eqz(mips::F0, &label4);
814 
815   std::string expected =
816       ".set noreorder\n"
817       "1:\n"
818       "bc1nez $f0, 1b\n"
819       "addu $t0, $t1, $t2\n"
820 
821       "2:\n"
822       "addu $t0, $t1, $t2\n"
823       "bc1nez $f0, 2b\n"
824       "nop\n"
825 
826       "3:\n"
827       "bc1eqz $f0, 3b\n"
828       "addu $t0, $t1, $t2\n"
829 
830       "4:\n"
831       "addu $t0, $t1, $t2\n"
832       "bc1eqz $f0, 4b\n"
833       "nop\n";
834   DriverStr(expected, "SetReorder");
835 }
836 
TEST_F(AssemblerMIPS32r6Test,LongBranchReorder)837 TEST_F(AssemblerMIPS32r6Test, LongBranchReorder) {
838   mips::MipsLabel label;
839   __ SetReorder(true);
840   __ Subu(mips::T0, mips::T1, mips::T2);
841   __ Bc1nez(mips::F0, &label);
842   constexpr uint32_t kAdduCount1 = (1u << 15) + 1;
843   for (uint32_t i = 0; i != kAdduCount1; ++i) {
844     __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
845   }
846   __ Bind(&label);
847   constexpr uint32_t kAdduCount2 = (1u << 15) + 1;
848   for (uint32_t i = 0; i != kAdduCount2; ++i) {
849     __ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
850   }
851   __ Subu(mips::T0, mips::T1, mips::T2);
852   __ Bc1eqz(mips::F0, &label);
853 
854   uint32_t offset_forward = 2 + kAdduCount1;  // 2: account for auipc and jic.
855   offset_forward <<= 2;
856   offset_forward += (offset_forward & 0x8000) << 1;  // Account for sign extension in jic.
857 
858   uint32_t offset_back = -(kAdduCount2 + 2);  // 2: account for subu and bc1nez.
859   offset_back <<= 2;
860   offset_back += (offset_back & 0x8000) << 1;  // Account for sign extension in jic.
861 
862   std::ostringstream oss;
863   oss <<
864       ".set noreorder\n"
865       "subu $t0, $t1, $t2\n"
866       "bc1eqz $f0, 1f\n"
867       "auipc $at, 0x" << std::hex << High16Bits(offset_forward) << "\n"
868       "jic $at, 0x" << std::hex << Low16Bits(offset_forward) << "\n"
869       "1:\n" <<
870       RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") <<
871       "2:\n" <<
872       RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") <<
873       "subu $t0, $t1, $t2\n"
874       "bc1nez $f0, 3f\n"
875       "auipc $at, 0x" << std::hex << High16Bits(offset_back) << "\n"
876       "jic $at, 0x" << std::hex << Low16Bits(offset_back) << "\n"
877       "3:\n";
878   std::string expected = oss.str();
879   DriverStr(expected, "LongBeqc");
880 }
881 
882 // TODO: MipsAssembler::Bc
883 //       MipsAssembler::Jic
884 //       MipsAssembler::Jialc
885 //       MipsAssembler::Bltc
886 //       MipsAssembler::Bltzc
887 //       MipsAssembler::Bgtzc
888 //       MipsAssembler::Bgec
889 //       MipsAssembler::Bgezc
890 //       MipsAssembler::Blezc
891 //       MipsAssembler::Bltuc
892 //       MipsAssembler::Bgeuc
893 //       MipsAssembler::Beqc
894 //       MipsAssembler::Bnec
895 //       MipsAssembler::Beqzc
896 //       MipsAssembler::Bnezc
897 //       MipsAssembler::Bc1eqz
898 //       MipsAssembler::Bc1nez
899 //       MipsAssembler::Buncond
900 //       MipsAssembler::Bcond
901 //       MipsAssembler::Call
902 
903 // TODO:  AssemblerMIPS32r6Test.B
904 //        AssemblerMIPS32r6Test.Beq
905 //        AssemblerMIPS32r6Test.Bne
906 //        AssemblerMIPS32r6Test.Beqz
907 //        AssemblerMIPS32r6Test.Bnez
908 //        AssemblerMIPS32r6Test.Bltz
909 //        AssemblerMIPS32r6Test.Bgez
910 //        AssemblerMIPS32r6Test.Blez
911 //        AssemblerMIPS32r6Test.Bgtz
912 //        AssemblerMIPS32r6Test.Blt
913 //        AssemblerMIPS32r6Test.Bge
914 //        AssemblerMIPS32r6Test.Bltu
915 //        AssemblerMIPS32r6Test.Bgeu
916 
917 #undef __
918 
919 }  // namespace art
920