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
40using namespace v8::internal;
41
42
43bool 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() \
91if (failure) { \
92    V8_Fatal(__FILE__, __LINE__, "MIPS Disassembler tests failed.\n"); \
93  }
94
95
96TEST(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