1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28 
29 #include <stdlib.h>
30 
31 #include "src/v8.h"
32 
33 #include "src/debug.h"
34 #include "src/disasm.h"
35 #include "src/disassembler.h"
36 #include "src/macro-assembler.h"
37 #include "src/serialize.h"
38 #include "test/cctest/cctest.h"
39 
40 using namespace v8::internal;
41 
42 
DisassembleAndCompare(byte * pc,const char * compare_string)43 bool DisassembleAndCompare(byte* pc, const char* compare_string) {
44   disasm::NameConverter converter;
45   disasm::Disassembler disasm(converter);
46   EmbeddedVector<char, 128> disasm_buffer;
47 
48   disasm.InstructionDecode(disasm_buffer, pc);
49 
50   if (strcmp(compare_string, disasm_buffer.start()) != 0) {
51     fprintf(stderr,
52             "expected: \n"
53             "%s\n"
54             "disassembled: \n"
55             "%s\n\n",
56             compare_string, disasm_buffer.start());
57     return false;
58   }
59   return true;
60 }
61 
62 
63 // Set up V8 to a state where we can at least run the assembler and
64 // disassembler. Declare the variables and allocate the data structures used
65 // in the rest of the macros.
66 #define SET_UP()                                          \
67   CcTest::InitializeVM();                                 \
68   Isolate* isolate = CcTest::i_isolate();                  \
69   HandleScope scope(isolate);                             \
70   byte *buffer = reinterpret_cast<byte*>(malloc(4*1024)); \
71   Assembler assm(isolate, buffer, 4*1024);                \
72   bool failure = false;
73 
74 
75 // This macro assembles one instruction using the preallocated assembler and
76 // disassembles the generated instruction, comparing the output to the expected
77 // value. If the comparison fails an error message is printed, but the test
78 // continues to run until the end.
79 #define COMPARE(asm_, compare_string) \
80   { \
81     int pc_offset = assm.pc_offset(); \
82     byte *progcounter = &buffer[pc_offset]; \
83     assm.asm_; \
84     if (!DisassembleAndCompare(progcounter, compare_string)) failure = true; \
85   }
86 
87 
88 // Verify that all invocations of the COMPARE macro passed successfully.
89 // Exit with a failure if at least one of the tests failed.
90 #define VERIFY_RUN() \
91 if (failure) { \
92     V8_Fatal(__FILE__, __LINE__, "MIPS Disassembler tests failed.\n"); \
93   }
94 
95 
TEST(Type0)96 TEST(Type0) {
97   SET_UP();
98 
99   COMPARE(addu(a0, a1, a2),
100           "00a62021       addu    a0, a1, a2");
101   COMPARE(addu(t2, t3, t4),
102           "016c5021       addu    t2, t3, t4");
103   COMPARE(addu(v0, v1, s0),
104           "00701021       addu    v0, v1, s0");
105 
106   COMPARE(subu(a0, a1, a2),
107           "00a62023       subu    a0, a1, a2");
108   COMPARE(subu(t2, t3, t4),
109           "016c5023       subu    t2, t3, t4");
110   COMPARE(subu(v0, v1, s0),
111           "00701023       subu    v0, v1, s0");
112 
113   if (!IsMipsArchVariant(kMips32r6)) {
114     COMPARE(mult(a0, a1),
115             "00850018       mult    a0, a1");
116     COMPARE(mult(t2, t3),
117             "014b0018       mult    t2, t3");
118     COMPARE(mult(v0, v1),
119             "00430018       mult    v0, v1");
120 
121     COMPARE(multu(a0, a1),
122             "00850019       multu   a0, a1");
123     COMPARE(multu(t2, t3),
124             "014b0019       multu   t2, t3");
125     COMPARE(multu(v0, v1),
126             "00430019       multu   v0, v1");
127 
128     COMPARE(div(a0, a1),
129             "0085001a       div     a0, a1");
130     COMPARE(div(t2, t3),
131             "014b001a       div     t2, t3");
132     COMPARE(div(v0, v1),
133             "0043001a       div     v0, v1");
134 
135     COMPARE(divu(a0, a1),
136             "0085001b       divu    a0, a1");
137     COMPARE(divu(t2, t3),
138             "014b001b       divu    t2, t3");
139     COMPARE(divu(v0, v1),
140             "0043001b       divu    v0, v1");
141 
142     if (!IsMipsArchVariant(kLoongson)) {
143       COMPARE(mul(a0, a1, a2),
144               "70a62002       mul     a0, a1, a2");
145       COMPARE(mul(t2, t3, t4),
146               "716c5002       mul     t2, t3, t4");
147       COMPARE(mul(v0, v1, s0),
148               "70701002       mul     v0, v1, s0");
149     }
150   } else {  // MIPS32r6.
151     COMPARE(mul(a0, a1, a2),
152             "00a62098       mul    a0, a1, a2");
153     COMPARE(muh(a0, a1, a2),
154             "00a620d8       muh    a0, a1, a2");
155     COMPARE(mul(t1, t2, t3),
156             "014b4898       mul    t1, t2, t3");
157     COMPARE(muh(t1, t2, t3),
158             "014b48d8       muh    t1, t2, t3");
159     COMPARE(mul(v0, v1, a0),
160             "00641098       mul    v0, v1, a0");
161     COMPARE(muh(v0, v1, a0),
162             "006410d8       muh    v0, v1, a0");
163 
164     COMPARE(mulu(a0, a1, a2),
165             "00a62099       mulu   a0, a1, a2");
166     COMPARE(muhu(a0, a1, a2),
167             "00a620d9       muhu   a0, a1, a2");
168     COMPARE(mulu(t1, t2, t3),
169             "014b4899       mulu   t1, t2, t3");
170     COMPARE(muhu(t1, t2, t3),
171             "014b48d9       muhu   t1, t2, t3");
172     COMPARE(mulu(v0, v1, a0),
173             "00641099       mulu   v0, v1, a0");
174     COMPARE(muhu(v0, v1, a0),
175             "006410d9       muhu   v0, v1, a0");
176 
177     COMPARE(div(a0, a1, a2),
178             "00a6209a       div    a0, a1, a2");
179     COMPARE(mod(a0, a1, a2),
180             "00a620da       mod    a0, a1, a2");
181     COMPARE(div(t1, t2, t3),
182             "014b489a       div    t1, t2, t3");
183     COMPARE(mod(t1, t2, t3),
184             "014b48da       mod    t1, t2, t3");
185     COMPARE(div(v0, v1, a0),
186             "0064109a       div    v0, v1, a0");
187     COMPARE(mod(v0, v1, a0),
188             "006410da       mod    v0, v1, a0");
189 
190     COMPARE(divu(a0, a1, a2),
191             "00a6209b       divu   a0, a1, a2");
192     COMPARE(modu(a0, a1, a2),
193             "00a620db       modu   a0, a1, a2");
194     COMPARE(divu(t1, t2, t3),
195             "014b489b       divu   t1, t2, t3");
196     COMPARE(modu(t1, t2, t3),
197             "014b48db       modu   t1, t2, t3");
198     COMPARE(divu(v0, v1, a0),
199             "0064109b       divu   v0, v1, a0");
200     COMPARE(modu(v0, v1, a0),
201             "006410db       modu   v0, v1, a0");
202 
203     COMPARE(bovc(a0, a0, static_cast<int16_t>(0)),
204             "20840000       bovc  a0, a0, 0");
205     COMPARE(bovc(a1, a0, static_cast<int16_t>(0)),
206             "20a40000       bovc  a1, a0, 0");
207     COMPARE(bovc(a1, a0, 32767),
208             "20a47fff       bovc  a1, a0, 32767");
209     COMPARE(bovc(a1, a0, -32768),
210             "20a48000       bovc  a1, a0, -32768");
211 
212     COMPARE(bnvc(a0, a0, static_cast<int16_t>(0)),
213             "60840000       bnvc  a0, a0, 0");
214     COMPARE(bnvc(a1, a0, static_cast<int16_t>(0)),
215             "60a40000       bnvc  a1, a0, 0");
216     COMPARE(bnvc(a1, a0, 32767),
217             "60a47fff       bnvc  a1, a0, 32767");
218     COMPARE(bnvc(a1, a0, -32768),
219             "60a48000       bnvc  a1, a0, -32768");
220 
221     COMPARE(beqzc(a0, 0),
222             "d8800000       beqzc   a0, 0x0");
223     COMPARE(beqzc(a0, 0xfffff),                   // 0x0fffff ==  1048575.
224             "d88fffff       beqzc   a0, 0xfffff");
225     COMPARE(beqzc(a0, 0x100000),                  // 0x100000 == -1048576.
226             "d8900000       beqzc   a0, 0x100000");
227 
228     COMPARE(bnezc(a0, 0),
229             "f8800000       bnezc   a0, 0x0");
230     COMPARE(bnezc(a0, 0xfffff),                   // 0x0fffff ==  1048575.
231             "f88fffff       bnezc   a0, 0xfffff");
232     COMPARE(bnezc(a0, 0x100000),                  // 0x100000 == -1048576.
233             "f8900000       bnezc   a0, 0x100000");
234   }
235 
236   COMPARE(addiu(a0, a1, 0x0),
237           "24a40000       addiu   a0, a1, 0");
238   COMPARE(addiu(s0, s1, 32767),
239           "26307fff       addiu   s0, s1, 32767");
240   COMPARE(addiu(t2, t3, -32768),
241           "256a8000       addiu   t2, t3, -32768");
242   COMPARE(addiu(v0, v1, -1),
243           "2462ffff       addiu   v0, v1, -1");
244 
245   COMPARE(and_(a0, a1, a2),
246           "00a62024       and     a0, a1, a2");
247   COMPARE(and_(s0, s1, s2),
248           "02328024       and     s0, s1, s2");
249   COMPARE(and_(t2, t3, t4),
250           "016c5024       and     t2, t3, t4");
251   COMPARE(and_(v0, v1, a2),
252           "00661024       and     v0, v1, a2");
253 
254   COMPARE(or_(a0, a1, a2),
255           "00a62025       or      a0, a1, a2");
256   COMPARE(or_(s0, s1, s2),
257           "02328025       or      s0, s1, s2");
258   COMPARE(or_(t2, t3, t4),
259           "016c5025       or      t2, t3, t4");
260   COMPARE(or_(v0, v1, a2),
261           "00661025       or      v0, v1, a2");
262 
263   COMPARE(xor_(a0, a1, a2),
264           "00a62026       xor     a0, a1, a2");
265   COMPARE(xor_(s0, s1, s2),
266           "02328026       xor     s0, s1, s2");
267   COMPARE(xor_(t2, t3, t4),
268           "016c5026       xor     t2, t3, t4");
269   COMPARE(xor_(v0, v1, a2),
270           "00661026       xor     v0, v1, a2");
271 
272   COMPARE(nor(a0, a1, a2),
273           "00a62027       nor     a0, a1, a2");
274   COMPARE(nor(s0, s1, s2),
275           "02328027       nor     s0, s1, s2");
276   COMPARE(nor(t2, t3, t4),
277           "016c5027       nor     t2, t3, t4");
278   COMPARE(nor(v0, v1, a2),
279           "00661027       nor     v0, v1, a2");
280 
281   COMPARE(andi(a0, a1, 0x1),
282           "30a40001       andi    a0, a1, 0x1");
283   COMPARE(andi(v0, v1, 0xffff),
284           "3062ffff       andi    v0, v1, 0xffff");
285 
286   COMPARE(ori(a0, a1, 0x1),
287           "34a40001       ori     a0, a1, 0x1");
288   COMPARE(ori(v0, v1, 0xffff),
289           "3462ffff       ori     v0, v1, 0xffff");
290 
291   COMPARE(xori(a0, a1, 0x1),
292           "38a40001       xori    a0, a1, 0x1");
293   COMPARE(xori(v0, v1, 0xffff),
294           "3862ffff       xori    v0, v1, 0xffff");
295 
296   COMPARE(lui(a0, 0x1),
297           "3c040001       lui     a0, 0x1");
298   COMPARE(lui(v0, 0xffff),
299           "3c02ffff       lui     v0, 0xffff");
300 
301   COMPARE(sll(a0, a1, 0),
302           "00052000       sll     a0, a1, 0");
303   COMPARE(sll(s0, s1, 8),
304           "00118200       sll     s0, s1, 8");
305   COMPARE(sll(t2, t3, 24),
306           "000b5600       sll     t2, t3, 24");
307   COMPARE(sll(v0, v1, 31),
308           "000317c0       sll     v0, v1, 31");
309 
310   COMPARE(sllv(a0, a1, a2),
311           "00c52004       sllv    a0, a1, a2");
312   COMPARE(sllv(s0, s1, s2),
313           "02518004       sllv    s0, s1, s2");
314   COMPARE(sllv(t2, t3, t4),
315           "018b5004       sllv    t2, t3, t4");
316   COMPARE(sllv(v0, v1, fp),
317           "03c31004       sllv    v0, v1, fp");
318 
319   COMPARE(srl(a0, a1, 0),
320           "00052002       srl     a0, a1, 0");
321   COMPARE(srl(s0, s1, 8),
322           "00118202       srl     s0, s1, 8");
323   COMPARE(srl(t2, t3, 24),
324           "000b5602       srl     t2, t3, 24");
325   COMPARE(srl(v0, v1, 31),
326           "000317c2       srl     v0, v1, 31");
327 
328   COMPARE(srlv(a0, a1, a2),
329           "00c52006       srlv    a0, a1, a2");
330   COMPARE(srlv(s0, s1, s2),
331           "02518006       srlv    s0, s1, s2");
332   COMPARE(srlv(t2, t3, t4),
333           "018b5006       srlv    t2, t3, t4");
334   COMPARE(srlv(v0, v1, fp),
335           "03c31006       srlv    v0, v1, fp");
336 
337   COMPARE(sra(a0, a1, 0),
338           "00052003       sra     a0, a1, 0");
339   COMPARE(sra(s0, s1, 8),
340           "00118203       sra     s0, s1, 8");
341   COMPARE(sra(t2, t3, 24),
342           "000b5603       sra     t2, t3, 24");
343   COMPARE(sra(v0, v1, 31),
344           "000317c3       sra     v0, v1, 31");
345 
346   COMPARE(srav(a0, a1, a2),
347           "00c52007       srav    a0, a1, a2");
348   COMPARE(srav(s0, s1, s2),
349           "02518007       srav    s0, s1, s2");
350   COMPARE(srav(t2, t3, t4),
351           "018b5007       srav    t2, t3, t4");
352   COMPARE(srav(v0, v1, fp),
353           "03c31007       srav    v0, v1, fp");
354 
355   if (IsMipsArchVariant(kMips32r2)) {
356     COMPARE(rotr(a0, a1, 0),
357             "00252002       rotr    a0, a1, 0");
358     COMPARE(rotr(s0, s1, 8),
359             "00318202       rotr    s0, s1, 8");
360     COMPARE(rotr(t2, t3, 24),
361             "002b5602       rotr    t2, t3, 24");
362     COMPARE(rotr(v0, v1, 31),
363             "002317c2       rotr    v0, v1, 31");
364 
365     COMPARE(rotrv(a0, a1, a2),
366             "00c52046       rotrv   a0, a1, a2");
367     COMPARE(rotrv(s0, s1, s2),
368             "02518046       rotrv   s0, s1, s2");
369     COMPARE(rotrv(t2, t3, t4),
370             "018b5046       rotrv   t2, t3, t4");
371     COMPARE(rotrv(v0, v1, fp),
372             "03c31046       rotrv   v0, v1, fp");
373   }
374 
375   COMPARE(break_(0),
376           "0000000d       break, code: 0x00000 (0)");
377   COMPARE(break_(261120),
378           "00ff000d       break, code: 0x3fc00 (261120)");
379   COMPARE(break_(1047552),
380           "03ff000d       break, code: 0xffc00 (1047552)");
381 
382   COMPARE(tge(a0, a1, 0),
383           "00850030       tge     a0, a1, code: 0x000");
384   COMPARE(tge(s0, s1, 1023),
385           "0211fff0       tge     s0, s1, code: 0x3ff");
386   COMPARE(tgeu(a0, a1, 0),
387           "00850031       tgeu    a0, a1, code: 0x000");
388   COMPARE(tgeu(s0, s1, 1023),
389           "0211fff1       tgeu    s0, s1, code: 0x3ff");
390   COMPARE(tlt(a0, a1, 0),
391           "00850032       tlt     a0, a1, code: 0x000");
392   COMPARE(tlt(s0, s1, 1023),
393           "0211fff2       tlt     s0, s1, code: 0x3ff");
394   COMPARE(tltu(a0, a1, 0),
395           "00850033       tltu    a0, a1, code: 0x000");
396   COMPARE(tltu(s0, s1, 1023),
397           "0211fff3       tltu    s0, s1, code: 0x3ff");
398   COMPARE(teq(a0, a1, 0),
399           "00850034       teq     a0, a1, code: 0x000");
400   COMPARE(teq(s0, s1, 1023),
401           "0211fff4       teq     s0, s1, code: 0x3ff");
402   COMPARE(tne(a0, a1, 0),
403           "00850036       tne     a0, a1, code: 0x000");
404   COMPARE(tne(s0, s1, 1023),
405           "0211fff6       tne     s0, s1, code: 0x3ff");
406 
407   COMPARE(mfhi(a0),
408           "00002010       mfhi    a0");
409   COMPARE(mfhi(s2),
410           "00009010       mfhi    s2");
411   COMPARE(mfhi(t4),
412           "00006010       mfhi    t4");
413   COMPARE(mfhi(v1),
414           "00001810       mfhi    v1");
415   COMPARE(mflo(a0),
416           "00002012       mflo    a0");
417   COMPARE(mflo(s2),
418           "00009012       mflo    s2");
419   COMPARE(mflo(t4),
420           "00006012       mflo    t4");
421   COMPARE(mflo(v1),
422           "00001812       mflo    v1");
423 
424   COMPARE(slt(a0, a1, a2),
425           "00a6202a       slt     a0, a1, a2");
426   COMPARE(slt(s0, s1, s2),
427           "0232802a       slt     s0, s1, s2");
428   COMPARE(slt(t2, t3, t4),
429           "016c502a       slt     t2, t3, t4");
430   COMPARE(slt(v0, v1, a2),
431           "0066102a       slt     v0, v1, a2");
432   COMPARE(sltu(a0, a1, a2),
433           "00a6202b       sltu    a0, a1, a2");
434   COMPARE(sltu(s0, s1, s2),
435           "0232802b       sltu    s0, s1, s2");
436   COMPARE(sltu(t2, t3, t4),
437           "016c502b       sltu    t2, t3, t4");
438   COMPARE(sltu(v0, v1, a2),
439           "0066102b       sltu    v0, v1, a2");
440 
441   COMPARE(slti(a0, a1, 0),
442           "28a40000       slti    a0, a1, 0");
443   COMPARE(slti(s0, s1, 32767),
444           "2a307fff       slti    s0, s1, 32767");
445   COMPARE(slti(t2, t3, -32768),
446           "296a8000       slti    t2, t3, -32768");
447   COMPARE(slti(v0, v1, -1),
448           "2862ffff       slti    v0, v1, -1");
449   COMPARE(sltiu(a0, a1, 0),
450           "2ca40000       sltiu   a0, a1, 0");
451   COMPARE(sltiu(s0, s1, 32767),
452           "2e307fff       sltiu   s0, s1, 32767");
453   COMPARE(sltiu(t2, t3, -32768),
454           "2d6a8000       sltiu   t2, t3, -32768");
455   COMPARE(sltiu(v0, v1, -1),
456           "2c62ffff       sltiu   v0, v1, -1");
457 
458   if (!IsMipsArchVariant(kLoongson)) {
459     COMPARE(movz(a0, a1, a2),
460             "00a6200a       movz    a0, a1, a2");
461     COMPARE(movz(s0, s1, s2),
462             "0232800a       movz    s0, s1, s2");
463     COMPARE(movz(t2, t3, t4),
464             "016c500a       movz    t2, t3, t4");
465     COMPARE(movz(v0, v1, a2),
466             "0066100a       movz    v0, v1, a2");
467     COMPARE(movn(a0, a1, a2),
468             "00a6200b       movn    a0, a1, a2");
469     COMPARE(movn(s0, s1, s2),
470             "0232800b       movn    s0, s1, s2");
471     COMPARE(movn(t2, t3, t4),
472             "016c500b       movn    t2, t3, t4");
473     COMPARE(movn(v0, v1, a2),
474             "0066100b       movn    v0, v1, a2");
475 
476     COMPARE(movt(a0, a1, 1),
477             "00a52001       movt    a0, a1, 1");
478     COMPARE(movt(s0, s1, 2),
479             "02298001       movt    s0, s1, 2");
480     COMPARE(movt(t2, t3, 3),
481             "016d5001       movt    t2, t3, 3");
482     COMPARE(movt(v0, v1, 7),
483             "007d1001       movt    v0, v1, 7");
484     COMPARE(movf(a0, a1, 0),
485             "00a02001       movf    a0, a1, 0");
486     COMPARE(movf(s0, s1, 4),
487             "02308001       movf    s0, s1, 4");
488     COMPARE(movf(t2, t3, 5),
489             "01745001       movf    t2, t3, 5");
490     COMPARE(movf(v0, v1, 6),
491             "00781001       movf    v0, v1, 6");
492 
493     if (IsMipsArchVariant(kMips32r6)) {
494       COMPARE(clz(a0, a1),
495               "00a02050       clz     a0, a1");
496       COMPARE(clz(s6, s7),
497               "02e0b050       clz     s6, s7");
498       COMPARE(clz(v0, v1),
499               "00601050       clz     v0, v1");
500     } else {
501       COMPARE(clz(a0, a1),
502               "70a42020       clz     a0, a1");
503       COMPARE(clz(s6, s7),
504               "72f6b020       clz     s6, s7");
505       COMPARE(clz(v0, v1),
506               "70621020       clz     v0, v1");
507     }
508   }
509 
510   if (IsMipsArchVariant(kMips32r2)) {
511     COMPARE(ins_(a0, a1, 31, 1),
512             "7ca4ffc4       ins     a0, a1, 31, 1");
513     COMPARE(ins_(s6, s7, 30, 2),
514             "7ef6ff84       ins     s6, s7, 30, 2");
515     COMPARE(ins_(v0, v1, 0, 32),
516             "7c62f804       ins     v0, v1, 0, 32");
517     COMPARE(ext_(a0, a1, 31, 1),
518             "7ca407c0       ext     a0, a1, 31, 1");
519     COMPARE(ext_(s6, s7, 30, 2),
520             "7ef60f80       ext     s6, s7, 30, 2");
521     COMPARE(ext_(v0, v1, 0, 32),
522             "7c62f800       ext     v0, v1, 0, 32");
523   }
524 
525   VERIFY_RUN();
526 }
527