• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 AssemblerMIPS32r5Test : public AssemblerTest<mips::MipsAssembler,
35                                                    mips::MipsLabel,
36                                                    mips::Register,
37                                                    mips::FRegister,
38                                                    uint32_t,
39                                                    mips::VectorRegister> {
40  public:
41   typedef AssemblerTest<mips::MipsAssembler,
42                         mips::MipsLabel,
43                         mips::Register,
44                         mips::FRegister,
45                         uint32_t,
46                         mips::VectorRegister> Base;
47 
AssemblerMIPS32r5Test()48   AssemblerMIPS32r5Test() :
49     instruction_set_features_(MipsInstructionSetFeatures::FromVariant("mips32r5", nullptr)) {
50   }
51 
52  protected:
53   // Get the typically used name for this architecture, e.g., aarch64, x86-64, ...
GetArchitectureString()54   std::string GetArchitectureString() OVERRIDE {
55     return "mips";
56   }
57 
GetAssemblerParameters()58   std::string GetAssemblerParameters() OVERRIDE {
59     return " --no-warn -32 -march=mips32r5 -mmsa";
60   }
61 
Pad(std::vector<uint8_t> & data)62   void Pad(std::vector<uint8_t>& data) OVERRIDE {
63     // The GNU linker unconditionally pads the code segment with NOPs to a size that is a multiple
64     // of 16 and there doesn't appear to be a way to suppress this padding. Our assembler doesn't
65     // pad, so, in order for two assembler outputs to match, we need to match the padding as well.
66     // NOP is encoded as four zero bytes on MIPS.
67     size_t pad_size = RoundUp(data.size(), 16u) - data.size();
68     data.insert(data.end(), pad_size, 0);
69   }
70 
GetDisassembleParameters()71   std::string GetDisassembleParameters() OVERRIDE {
72     return " -D -bbinary -mmips:isa32r5";
73   }
74 
CreateAssembler(ArenaAllocator * allocator)75   mips::MipsAssembler* CreateAssembler(ArenaAllocator* allocator) OVERRIDE {
76     return new (allocator) mips::MipsAssembler(allocator, instruction_set_features_.get());
77   }
78 
SetUpHelpers()79   void SetUpHelpers() OVERRIDE {
80     if (registers_.size() == 0) {
81       registers_.push_back(new mips::Register(mips::ZERO));
82       registers_.push_back(new mips::Register(mips::AT));
83       registers_.push_back(new mips::Register(mips::V0));
84       registers_.push_back(new mips::Register(mips::V1));
85       registers_.push_back(new mips::Register(mips::A0));
86       registers_.push_back(new mips::Register(mips::A1));
87       registers_.push_back(new mips::Register(mips::A2));
88       registers_.push_back(new mips::Register(mips::A3));
89       registers_.push_back(new mips::Register(mips::T0));
90       registers_.push_back(new mips::Register(mips::T1));
91       registers_.push_back(new mips::Register(mips::T2));
92       registers_.push_back(new mips::Register(mips::T3));
93       registers_.push_back(new mips::Register(mips::T4));
94       registers_.push_back(new mips::Register(mips::T5));
95       registers_.push_back(new mips::Register(mips::T6));
96       registers_.push_back(new mips::Register(mips::T7));
97       registers_.push_back(new mips::Register(mips::S0));
98       registers_.push_back(new mips::Register(mips::S1));
99       registers_.push_back(new mips::Register(mips::S2));
100       registers_.push_back(new mips::Register(mips::S3));
101       registers_.push_back(new mips::Register(mips::S4));
102       registers_.push_back(new mips::Register(mips::S5));
103       registers_.push_back(new mips::Register(mips::S6));
104       registers_.push_back(new mips::Register(mips::S7));
105       registers_.push_back(new mips::Register(mips::T8));
106       registers_.push_back(new mips::Register(mips::T9));
107       registers_.push_back(new mips::Register(mips::K0));
108       registers_.push_back(new mips::Register(mips::K1));
109       registers_.push_back(new mips::Register(mips::GP));
110       registers_.push_back(new mips::Register(mips::SP));
111       registers_.push_back(new mips::Register(mips::FP));
112       registers_.push_back(new mips::Register(mips::RA));
113 
114       secondary_register_names_.emplace(mips::Register(mips::ZERO), "zero");
115       secondary_register_names_.emplace(mips::Register(mips::AT), "at");
116       secondary_register_names_.emplace(mips::Register(mips::V0), "v0");
117       secondary_register_names_.emplace(mips::Register(mips::V1), "v1");
118       secondary_register_names_.emplace(mips::Register(mips::A0), "a0");
119       secondary_register_names_.emplace(mips::Register(mips::A1), "a1");
120       secondary_register_names_.emplace(mips::Register(mips::A2), "a2");
121       secondary_register_names_.emplace(mips::Register(mips::A3), "a3");
122       secondary_register_names_.emplace(mips::Register(mips::T0), "t0");
123       secondary_register_names_.emplace(mips::Register(mips::T1), "t1");
124       secondary_register_names_.emplace(mips::Register(mips::T2), "t2");
125       secondary_register_names_.emplace(mips::Register(mips::T3), "t3");
126       secondary_register_names_.emplace(mips::Register(mips::T4), "t4");
127       secondary_register_names_.emplace(mips::Register(mips::T5), "t5");
128       secondary_register_names_.emplace(mips::Register(mips::T6), "t6");
129       secondary_register_names_.emplace(mips::Register(mips::T7), "t7");
130       secondary_register_names_.emplace(mips::Register(mips::S0), "s0");
131       secondary_register_names_.emplace(mips::Register(mips::S1), "s1");
132       secondary_register_names_.emplace(mips::Register(mips::S2), "s2");
133       secondary_register_names_.emplace(mips::Register(mips::S3), "s3");
134       secondary_register_names_.emplace(mips::Register(mips::S4), "s4");
135       secondary_register_names_.emplace(mips::Register(mips::S5), "s5");
136       secondary_register_names_.emplace(mips::Register(mips::S6), "s6");
137       secondary_register_names_.emplace(mips::Register(mips::S7), "s7");
138       secondary_register_names_.emplace(mips::Register(mips::T8), "t8");
139       secondary_register_names_.emplace(mips::Register(mips::T9), "t9");
140       secondary_register_names_.emplace(mips::Register(mips::K0), "k0");
141       secondary_register_names_.emplace(mips::Register(mips::K1), "k1");
142       secondary_register_names_.emplace(mips::Register(mips::GP), "gp");
143       secondary_register_names_.emplace(mips::Register(mips::SP), "sp");
144       secondary_register_names_.emplace(mips::Register(mips::FP), "fp");
145       secondary_register_names_.emplace(mips::Register(mips::RA), "ra");
146 
147       fp_registers_.push_back(new mips::FRegister(mips::F0));
148       fp_registers_.push_back(new mips::FRegister(mips::F1));
149       fp_registers_.push_back(new mips::FRegister(mips::F2));
150       fp_registers_.push_back(new mips::FRegister(mips::F3));
151       fp_registers_.push_back(new mips::FRegister(mips::F4));
152       fp_registers_.push_back(new mips::FRegister(mips::F5));
153       fp_registers_.push_back(new mips::FRegister(mips::F6));
154       fp_registers_.push_back(new mips::FRegister(mips::F7));
155       fp_registers_.push_back(new mips::FRegister(mips::F8));
156       fp_registers_.push_back(new mips::FRegister(mips::F9));
157       fp_registers_.push_back(new mips::FRegister(mips::F10));
158       fp_registers_.push_back(new mips::FRegister(mips::F11));
159       fp_registers_.push_back(new mips::FRegister(mips::F12));
160       fp_registers_.push_back(new mips::FRegister(mips::F13));
161       fp_registers_.push_back(new mips::FRegister(mips::F14));
162       fp_registers_.push_back(new mips::FRegister(mips::F15));
163       fp_registers_.push_back(new mips::FRegister(mips::F16));
164       fp_registers_.push_back(new mips::FRegister(mips::F17));
165       fp_registers_.push_back(new mips::FRegister(mips::F18));
166       fp_registers_.push_back(new mips::FRegister(mips::F19));
167       fp_registers_.push_back(new mips::FRegister(mips::F20));
168       fp_registers_.push_back(new mips::FRegister(mips::F21));
169       fp_registers_.push_back(new mips::FRegister(mips::F22));
170       fp_registers_.push_back(new mips::FRegister(mips::F23));
171       fp_registers_.push_back(new mips::FRegister(mips::F24));
172       fp_registers_.push_back(new mips::FRegister(mips::F25));
173       fp_registers_.push_back(new mips::FRegister(mips::F26));
174       fp_registers_.push_back(new mips::FRegister(mips::F27));
175       fp_registers_.push_back(new mips::FRegister(mips::F28));
176       fp_registers_.push_back(new mips::FRegister(mips::F29));
177       fp_registers_.push_back(new mips::FRegister(mips::F30));
178       fp_registers_.push_back(new mips::FRegister(mips::F31));
179 
180       vec_registers_.push_back(new mips::VectorRegister(mips::W0));
181       vec_registers_.push_back(new mips::VectorRegister(mips::W1));
182       vec_registers_.push_back(new mips::VectorRegister(mips::W2));
183       vec_registers_.push_back(new mips::VectorRegister(mips::W3));
184       vec_registers_.push_back(new mips::VectorRegister(mips::W4));
185       vec_registers_.push_back(new mips::VectorRegister(mips::W5));
186       vec_registers_.push_back(new mips::VectorRegister(mips::W6));
187       vec_registers_.push_back(new mips::VectorRegister(mips::W7));
188       vec_registers_.push_back(new mips::VectorRegister(mips::W8));
189       vec_registers_.push_back(new mips::VectorRegister(mips::W9));
190       vec_registers_.push_back(new mips::VectorRegister(mips::W10));
191       vec_registers_.push_back(new mips::VectorRegister(mips::W11));
192       vec_registers_.push_back(new mips::VectorRegister(mips::W12));
193       vec_registers_.push_back(new mips::VectorRegister(mips::W13));
194       vec_registers_.push_back(new mips::VectorRegister(mips::W14));
195       vec_registers_.push_back(new mips::VectorRegister(mips::W15));
196       vec_registers_.push_back(new mips::VectorRegister(mips::W16));
197       vec_registers_.push_back(new mips::VectorRegister(mips::W17));
198       vec_registers_.push_back(new mips::VectorRegister(mips::W18));
199       vec_registers_.push_back(new mips::VectorRegister(mips::W19));
200       vec_registers_.push_back(new mips::VectorRegister(mips::W20));
201       vec_registers_.push_back(new mips::VectorRegister(mips::W21));
202       vec_registers_.push_back(new mips::VectorRegister(mips::W22));
203       vec_registers_.push_back(new mips::VectorRegister(mips::W23));
204       vec_registers_.push_back(new mips::VectorRegister(mips::W24));
205       vec_registers_.push_back(new mips::VectorRegister(mips::W25));
206       vec_registers_.push_back(new mips::VectorRegister(mips::W26));
207       vec_registers_.push_back(new mips::VectorRegister(mips::W27));
208       vec_registers_.push_back(new mips::VectorRegister(mips::W28));
209       vec_registers_.push_back(new mips::VectorRegister(mips::W29));
210       vec_registers_.push_back(new mips::VectorRegister(mips::W30));
211       vec_registers_.push_back(new mips::VectorRegister(mips::W31));
212     }
213   }
214 
TearDown()215   void TearDown() OVERRIDE {
216     AssemblerTest::TearDown();
217     STLDeleteElements(&registers_);
218     STLDeleteElements(&fp_registers_);
219     STLDeleteElements(&vec_registers_);
220   }
221 
GetAddresses()222   std::vector<mips::MipsLabel> GetAddresses() {
223     UNIMPLEMENTED(FATAL) << "Feature not implemented yet";
224     UNREACHABLE();
225   }
226 
GetRegisters()227   std::vector<mips::Register*> GetRegisters() OVERRIDE {
228     return registers_;
229   }
230 
GetFPRegisters()231   std::vector<mips::FRegister*> GetFPRegisters() OVERRIDE {
232     return fp_registers_;
233   }
234 
GetVectorRegisters()235   std::vector<mips::VectorRegister*> GetVectorRegisters() OVERRIDE {
236     return vec_registers_;
237   }
238 
CreateImmediate(int64_t imm_value)239   uint32_t CreateImmediate(int64_t imm_value) OVERRIDE {
240     return imm_value;
241   }
242 
GetSecondaryRegisterName(const mips::Register & reg)243   std::string GetSecondaryRegisterName(const mips::Register& reg) OVERRIDE {
244     CHECK(secondary_register_names_.find(reg) != secondary_register_names_.end());
245     return secondary_register_names_[reg];
246   }
247 
RepeatInsn(size_t count,const std::string & insn)248   std::string RepeatInsn(size_t count, const std::string& insn) {
249     std::string result;
250     for (; count != 0u; --count) {
251       result += insn;
252     }
253     return result;
254   }
255 
256  private:
257   std::vector<mips::Register*> registers_;
258   std::map<mips::Register, std::string, MIPSCpuRegisterCompare> secondary_register_names_;
259 
260   std::vector<mips::FRegister*> fp_registers_;
261   std::vector<mips::VectorRegister*> vec_registers_;
262   std::unique_ptr<const MipsInstructionSetFeatures> instruction_set_features_;
263 };
264 
TEST_F(AssemblerMIPS32r5Test,Toolchain)265 TEST_F(AssemblerMIPS32r5Test, Toolchain) {
266   EXPECT_TRUE(CheckTools());
267 }
268 
TEST_F(AssemblerMIPS32r5Test,LoadQFromOffset)269 TEST_F(AssemblerMIPS32r5Test, LoadQFromOffset) {
270   __ LoadQFromOffset(mips::F0, mips::A0, 0);
271   __ LoadQFromOffset(mips::F0, mips::A0, 1);
272   __ LoadQFromOffset(mips::F0, mips::A0, 2);
273   __ LoadQFromOffset(mips::F0, mips::A0, 4);
274   __ LoadQFromOffset(mips::F0, mips::A0, 8);
275   __ LoadQFromOffset(mips::F0, mips::A0, 511);
276   __ LoadQFromOffset(mips::F0, mips::A0, 512);
277   __ LoadQFromOffset(mips::F0, mips::A0, 513);
278   __ LoadQFromOffset(mips::F0, mips::A0, 514);
279   __ LoadQFromOffset(mips::F0, mips::A0, 516);
280   __ LoadQFromOffset(mips::F0, mips::A0, 1022);
281   __ LoadQFromOffset(mips::F0, mips::A0, 1024);
282   __ LoadQFromOffset(mips::F0, mips::A0, 1025);
283   __ LoadQFromOffset(mips::F0, mips::A0, 1026);
284   __ LoadQFromOffset(mips::F0, mips::A0, 1028);
285   __ LoadQFromOffset(mips::F0, mips::A0, 2044);
286   __ LoadQFromOffset(mips::F0, mips::A0, 2048);
287   __ LoadQFromOffset(mips::F0, mips::A0, 2049);
288   __ LoadQFromOffset(mips::F0, mips::A0, 2050);
289   __ LoadQFromOffset(mips::F0, mips::A0, 2052);
290   __ LoadQFromOffset(mips::F0, mips::A0, 4088);
291   __ LoadQFromOffset(mips::F0, mips::A0, 4096);
292   __ LoadQFromOffset(mips::F0, mips::A0, 4097);
293   __ LoadQFromOffset(mips::F0, mips::A0, 4098);
294   __ LoadQFromOffset(mips::F0, mips::A0, 4100);
295   __ LoadQFromOffset(mips::F0, mips::A0, 4104);
296   __ LoadQFromOffset(mips::F0, mips::A0, 0x7FFC);
297   __ LoadQFromOffset(mips::F0, mips::A0, 0x8000);
298   __ LoadQFromOffset(mips::F0, mips::A0, 0x10000);
299   __ LoadQFromOffset(mips::F0, mips::A0, 0x12345678);
300   __ LoadQFromOffset(mips::F0, mips::A0, 0x12350078);
301   __ LoadQFromOffset(mips::F0, mips::A0, -256);
302   __ LoadQFromOffset(mips::F0, mips::A0, -511);
303   __ LoadQFromOffset(mips::F0, mips::A0, -513);
304   __ LoadQFromOffset(mips::F0, mips::A0, -1022);
305   __ LoadQFromOffset(mips::F0, mips::A0, -1026);
306   __ LoadQFromOffset(mips::F0, mips::A0, -2044);
307   __ LoadQFromOffset(mips::F0, mips::A0, -2052);
308   __ LoadQFromOffset(mips::F0, mips::A0, -4096);
309   __ LoadQFromOffset(mips::F0, mips::A0, -4104);
310   __ LoadQFromOffset(mips::F0, mips::A0, -32768);
311   __ LoadQFromOffset(mips::F0, mips::A0, -36856);
312   __ LoadQFromOffset(mips::F0, mips::A0, 36856);
313   __ LoadQFromOffset(mips::F0, mips::A0, -69608);
314   __ LoadQFromOffset(mips::F0, mips::A0, 69608);
315   __ LoadQFromOffset(mips::F0, mips::A0, 0xABCDEF00);
316   __ LoadQFromOffset(mips::F0, mips::A0, 0x7FFFABCD);
317 
318   const char* expected =
319       "ld.d $w0, 0($a0)\n"
320       "ld.b $w0, 1($a0)\n"
321       "ld.h $w0, 2($a0)\n"
322       "ld.w $w0, 4($a0)\n"
323       "ld.d $w0, 8($a0)\n"
324       "ld.b $w0, 511($a0)\n"
325       "ld.d $w0, 512($a0)\n"
326       "addiu $at, $a0, 513\n"
327       "ld.b $w0, 0($at)\n"
328       "ld.h $w0, 514($a0)\n"
329       "ld.w $w0, 516($a0)\n"
330       "ld.h $w0, 1022($a0)\n"
331       "ld.d $w0, 1024($a0)\n"
332       "addiu $at, $a0, 1025\n"
333       "ld.b $w0, 0($at)\n"
334       "addiu $at, $a0, 1026\n"
335       "ld.h $w0, 0($at)\n"
336       "ld.w $w0, 1028($a0)\n"
337       "ld.w $w0, 2044($a0)\n"
338       "ld.d $w0, 2048($a0)\n"
339       "addiu $at, $a0, 2049\n"
340       "ld.b $w0, 0($at)\n"
341       "addiu $at, $a0, 2050\n"
342       "ld.h $w0, 0($at)\n"
343       "addiu $at, $a0, 2052\n"
344       "ld.w $w0, 0($at)\n"
345       "ld.d $w0, 4088($a0)\n"
346       "addiu $at, $a0, 4096\n"
347       "ld.d $w0, 0($at)\n"
348       "addiu $at, $a0, 4097\n"
349       "ld.b $w0, 0($at)\n"
350       "addiu $at, $a0, 4098\n"
351       "ld.h $w0, 0($at)\n"
352       "addiu $at, $a0, 4100\n"
353       "ld.w $w0, 0($at)\n"
354       "addiu $at, $a0, 4104\n"
355       "ld.d $w0, 0($at)\n"
356       "addiu $at, $a0, 0x7FFC\n"
357       "ld.w $w0, 0($at)\n"
358       "addiu $at, $a0, 0x7FF8\n"
359       "ld.d $w0, 8($at)\n"
360       "addiu $at, $a0, 32760\n"
361       "addiu $at, $at, 32760\n"
362       "ld.d $w0, 16($at)\n"
363       "lui $at, 4660\n"
364       "addu $at, $at, $a0\n"
365       "addiu $at, $at, 24576\n"
366       "ld.d $w0, -2440($at) # 0xF678\n"
367       "lui $at, 4661\n"
368       "addu $at, $at, $a0\n"
369       "ld.d $w0, 120($at)\n"
370       "ld.d $w0, -256($a0)\n"
371       "ld.b $w0, -511($a0)\n"
372       "addiu $at, $a0, -513\n"
373       "ld.b $w0, 0($at)\n"
374       "ld.h $w0, -1022($a0)\n"
375       "addiu $at, $a0, -1026\n"
376       "ld.h $w0, 0($at)\n"
377       "ld.w $w0, -2044($a0)\n"
378       "addiu $at, $a0, -2052\n"
379       "ld.w $w0, 0($at)\n"
380       "ld.d $w0, -4096($a0)\n"
381       "addiu $at, $a0, -4104\n"
382       "ld.d $w0, 0($at)\n"
383       "addiu $at, $a0, -32768\n"
384       "ld.d $w0, 0($at)\n"
385       "addiu $at, $a0, -32760\n"
386       "addiu $at, $at, -4096\n"
387       "ld.d $w0, 0($at)\n"
388       "addiu $at, $a0, 32760\n"
389       "addiu $at, $at, 4096\n"
390       "ld.d $w0, 0($at)\n"
391       "addiu $at, $a0, -32760\n"
392       "addiu $at, $at, -32760\n"
393       "ld.d $w0, -4088($at)\n"
394       "addiu $at, $a0, 32760\n"
395       "addiu $at, $at, 32760\n"
396       "ld.d $w0, 4088($at)\n"
397       "lui $at, 0xABCE\n"
398       "addu $at, $at, $a0\n"
399       "addiu $at, $at, -8192 # 0xE000\n"
400       "ld.d $w0, 0xF00($at)\n"
401       "lui $at, 0x8000\n"
402       "addu $at, $at, $a0\n"
403       "addiu $at, $at, -21504 # 0xAC00\n"
404       "ld.b $w0, -51($at) # 0xFFCD\n";
405   DriverStr(expected, "LoadQFromOffset");
406 }
407 
TEST_F(AssemblerMIPS32r5Test,StoreQToOffset)408 TEST_F(AssemblerMIPS32r5Test, StoreQToOffset) {
409   __ StoreQToOffset(mips::F0, mips::A0, 0);
410   __ StoreQToOffset(mips::F0, mips::A0, 1);
411   __ StoreQToOffset(mips::F0, mips::A0, 2);
412   __ StoreQToOffset(mips::F0, mips::A0, 4);
413   __ StoreQToOffset(mips::F0, mips::A0, 8);
414   __ StoreQToOffset(mips::F0, mips::A0, 511);
415   __ StoreQToOffset(mips::F0, mips::A0, 512);
416   __ StoreQToOffset(mips::F0, mips::A0, 513);
417   __ StoreQToOffset(mips::F0, mips::A0, 514);
418   __ StoreQToOffset(mips::F0, mips::A0, 516);
419   __ StoreQToOffset(mips::F0, mips::A0, 1022);
420   __ StoreQToOffset(mips::F0, mips::A0, 1024);
421   __ StoreQToOffset(mips::F0, mips::A0, 1025);
422   __ StoreQToOffset(mips::F0, mips::A0, 1026);
423   __ StoreQToOffset(mips::F0, mips::A0, 1028);
424   __ StoreQToOffset(mips::F0, mips::A0, 2044);
425   __ StoreQToOffset(mips::F0, mips::A0, 2048);
426   __ StoreQToOffset(mips::F0, mips::A0, 2049);
427   __ StoreQToOffset(mips::F0, mips::A0, 2050);
428   __ StoreQToOffset(mips::F0, mips::A0, 2052);
429   __ StoreQToOffset(mips::F0, mips::A0, 4088);
430   __ StoreQToOffset(mips::F0, mips::A0, 4096);
431   __ StoreQToOffset(mips::F0, mips::A0, 4097);
432   __ StoreQToOffset(mips::F0, mips::A0, 4098);
433   __ StoreQToOffset(mips::F0, mips::A0, 4100);
434   __ StoreQToOffset(mips::F0, mips::A0, 4104);
435   __ StoreQToOffset(mips::F0, mips::A0, 0x7FFC);
436   __ StoreQToOffset(mips::F0, mips::A0, 0x8000);
437   __ StoreQToOffset(mips::F0, mips::A0, 0x10000);
438   __ StoreQToOffset(mips::F0, mips::A0, 0x12345678);
439   __ StoreQToOffset(mips::F0, mips::A0, 0x12350078);
440   __ StoreQToOffset(mips::F0, mips::A0, -256);
441   __ StoreQToOffset(mips::F0, mips::A0, -511);
442   __ StoreQToOffset(mips::F0, mips::A0, -513);
443   __ StoreQToOffset(mips::F0, mips::A0, -1022);
444   __ StoreQToOffset(mips::F0, mips::A0, -1026);
445   __ StoreQToOffset(mips::F0, mips::A0, -2044);
446   __ StoreQToOffset(mips::F0, mips::A0, -2052);
447   __ StoreQToOffset(mips::F0, mips::A0, -4096);
448   __ StoreQToOffset(mips::F0, mips::A0, -4104);
449   __ StoreQToOffset(mips::F0, mips::A0, -32768);
450   __ StoreQToOffset(mips::F0, mips::A0, -36856);
451   __ StoreQToOffset(mips::F0, mips::A0, 36856);
452   __ StoreQToOffset(mips::F0, mips::A0, -69608);
453   __ StoreQToOffset(mips::F0, mips::A0, 69608);
454   __ StoreQToOffset(mips::F0, mips::A0, 0xABCDEF00);
455   __ StoreQToOffset(mips::F0, mips::A0, 0x7FFFABCD);
456 
457   const char* expected =
458       "st.d $w0, 0($a0)\n"
459       "st.b $w0, 1($a0)\n"
460       "st.h $w0, 2($a0)\n"
461       "st.w $w0, 4($a0)\n"
462       "st.d $w0, 8($a0)\n"
463       "st.b $w0, 511($a0)\n"
464       "st.d $w0, 512($a0)\n"
465       "addiu $at, $a0, 513\n"
466       "st.b $w0, 0($at)\n"
467       "st.h $w0, 514($a0)\n"
468       "st.w $w0, 516($a0)\n"
469       "st.h $w0, 1022($a0)\n"
470       "st.d $w0, 1024($a0)\n"
471       "addiu $at, $a0, 1025\n"
472       "st.b $w0, 0($at)\n"
473       "addiu $at, $a0, 1026\n"
474       "st.h $w0, 0($at)\n"
475       "st.w $w0, 1028($a0)\n"
476       "st.w $w0, 2044($a0)\n"
477       "st.d $w0, 2048($a0)\n"
478       "addiu $at, $a0, 2049\n"
479       "st.b $w0, 0($at)\n"
480       "addiu $at, $a0, 2050\n"
481       "st.h $w0, 0($at)\n"
482       "addiu $at, $a0, 2052\n"
483       "st.w $w0, 0($at)\n"
484       "st.d $w0, 4088($a0)\n"
485       "addiu $at, $a0, 4096\n"
486       "st.d $w0, 0($at)\n"
487       "addiu $at, $a0, 4097\n"
488       "st.b $w0, 0($at)\n"
489       "addiu $at, $a0, 4098\n"
490       "st.h $w0, 0($at)\n"
491       "addiu $at, $a0, 4100\n"
492       "st.w $w0, 0($at)\n"
493       "addiu $at, $a0, 4104\n"
494       "st.d $w0, 0($at)\n"
495       "addiu $at, $a0, 0x7FFC\n"
496       "st.w $w0, 0($at)\n"
497       "addiu $at, $a0, 0x7FF8\n"
498       "st.d $w0, 8($at)\n"
499       "addiu $at, $a0, 32760\n"
500       "addiu $at, $at, 32760\n"
501       "st.d $w0, 16($at)\n"
502       "lui $at, 4660\n"
503       "addu $at, $at, $a0\n"
504       "addiu $at, $at, 24576\n"
505       "st.d $w0, -2440($at) # 0xF678\n"
506       "lui $at, 4661\n"
507       "addu $at, $at, $a0\n"
508       "st.d $w0, 120($at)\n"
509       "st.d $w0, -256($a0)\n"
510       "st.b $w0, -511($a0)\n"
511       "addiu $at, $a0, -513\n"
512       "st.b $w0, 0($at)\n"
513       "st.h $w0, -1022($a0)\n"
514       "addiu $at, $a0, -1026\n"
515       "st.h $w0, 0($at)\n"
516       "st.w $w0, -2044($a0)\n"
517       "addiu $at, $a0, -2052\n"
518       "st.w $w0, 0($at)\n"
519       "st.d $w0, -4096($a0)\n"
520       "addiu $at, $a0, -4104\n"
521       "st.d $w0, 0($at)\n"
522       "addiu $at, $a0, -32768\n"
523       "st.d $w0, 0($at)\n"
524       "addiu $at, $a0, -32760\n"
525       "addiu $at, $at, -4096\n"
526       "st.d $w0, 0($at)\n"
527       "addiu $at, $a0, 32760\n"
528       "addiu $at, $at, 4096\n"
529       "st.d $w0, 0($at)\n"
530       "addiu $at, $a0, -32760\n"
531       "addiu $at, $at, -32760\n"
532       "st.d $w0, -4088($at)\n"
533       "addiu $at, $a0, 32760\n"
534       "addiu $at, $at, 32760\n"
535       "st.d $w0, 4088($at)\n"
536       "lui $at, 0xABCE\n"
537       "addu $at, $at, $a0\n"
538       "addiu $at, $at, -8192 # 0xE000\n"
539       "st.d $w0, 0xF00($at)\n"
540       "lui $at, 0x8000\n"
541       "addu $at, $at, $a0\n"
542       "addiu $at, $at, -21504 # 0xAC00\n"
543       "st.b $w0, -51($at) # 0xFFCD\n";
544   DriverStr(expected, "StoreQToOffset");
545 }
546 
547 #undef __
548 }  // namespace art
549