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 "v8.h"
32
33#include "debug.h"
34#include "disasm.h"
35#include "disassembler.h"
36#include "macro-assembler.h"
37#include "serialize.h"
38#include "cctest.h"
39
40using namespace v8::internal;
41
42
43static v8::Persistent<v8::Context> env;
44
45static void InitializeVM() {
46  // Disable compilation of natives.
47  FLAG_disable_native_files = true;
48  if (env.IsEmpty()) {
49    env = v8::Context::New();
50  }
51}
52
53
54bool DisassembleAndCompare(byte* pc, const char* compare_string) {
55  disasm::NameConverter converter;
56  disasm::Disassembler disasm(converter);
57  EmbeddedVector<char, 128> disasm_buffer;
58
59  disasm.InstructionDecode(disasm_buffer, pc);
60
61  if (strcmp(compare_string, disasm_buffer.start()) != 0) {
62    fprintf(stderr,
63            "expected: \n"
64            "%s\n"
65            "disassembled: \n"
66            "%s\n\n",
67            compare_string, disasm_buffer.start());
68    return false;
69  }
70  return true;
71}
72
73
74// Set up V8 to a state where we can at least run the assembler and
75// disassembler. Declare the variables and allocate the data structures used
76// in the rest of the macros.
77#define SET_UP()                                           \
78  InitializeVM();                                         \
79  v8::HandleScope scope;                                  \
80  byte *buffer = reinterpret_cast<byte*>(malloc(4*1024)); \
81  Assembler assm(Isolate::Current(), buffer, 4*1024);     \
82  bool failure = false;
83
84
85// This macro assembles one instruction using the preallocated assembler and
86// disassembles the generated instruction, comparing the output to the expected
87// value. If the comparison fails an error message is printed, but the test
88// continues to run until the end.
89#define COMPARE(asm_, compare_string) \
90  { \
91    int pc_offset = assm.pc_offset(); \
92    byte *progcounter = &buffer[pc_offset]; \
93    assm.asm_; \
94    if (!DisassembleAndCompare(progcounter, compare_string)) failure = true; \
95  }
96
97
98// Verify that all invocations of the COMPARE macro passed successfully.
99// Exit with a failure if at least one of the tests failed.
100#define VERIFY_RUN() \
101if (failure) { \
102    V8_Fatal(__FILE__, __LINE__, "MIPS Disassembler tests failed.\n"); \
103  }
104
105
106TEST(Type0) {
107  SET_UP();
108
109  COMPARE(addu(a0, a1, a2),
110          "00a62021       addu    a0, a1, a2");
111  COMPARE(addu(t2, t3, t4),
112          "016c5021       addu    t2, t3, t4");
113  COMPARE(addu(v0, v1, s0),
114          "00701021       addu    v0, v1, s0");
115
116  COMPARE(subu(a0, a1, a2),
117          "00a62023       subu    a0, a1, a2");
118  COMPARE(subu(t2, t3, t4),
119          "016c5023       subu    t2, t3, t4");
120  COMPARE(subu(v0, v1, s0),
121          "00701023       subu    v0, v1, s0");
122
123  COMPARE(mult(a0, a1),
124          "00850018       mult    a0, a1");
125  COMPARE(mult(t2, t3),
126          "014b0018       mult    t2, t3");
127  COMPARE(mult(v0, v1),
128          "00430018       mult    v0, v1");
129
130  COMPARE(multu(a0, a1),
131          "00850019       multu   a0, a1");
132  COMPARE(multu(t2, t3),
133          "014b0019       multu   t2, t3");
134  COMPARE(multu(v0, v1),
135          "00430019       multu   v0, v1");
136
137  COMPARE(div(a0, a1),
138          "0085001a       div     a0, a1");
139  COMPARE(div(t2, t3),
140          "014b001a       div     t2, t3");
141  COMPARE(div(v0, v1),
142          "0043001a       div     v0, v1");
143
144  COMPARE(divu(a0, a1),
145          "0085001b       divu    a0, a1");
146  COMPARE(divu(t2, t3),
147          "014b001b       divu    t2, t3");
148  COMPARE(divu(v0, v1),
149          "0043001b       divu    v0, v1");
150
151  if (kArchVariant != kLoongson) {
152    COMPARE(mul(a0, a1, a2),
153            "70a62002       mul     a0, a1, a2");
154    COMPARE(mul(t2, t3, t4),
155            "716c5002       mul     t2, t3, t4");
156    COMPARE(mul(v0, v1, s0),
157            "70701002       mul     v0, v1, s0");
158  }
159
160  COMPARE(addiu(a0, a1, 0x0),
161          "24a40000       addiu   a0, a1, 0");
162  COMPARE(addiu(s0, s1, 32767),
163          "26307fff       addiu   s0, s1, 32767");
164  COMPARE(addiu(t2, t3, -32768),
165          "256a8000       addiu   t2, t3, -32768");
166  COMPARE(addiu(v0, v1, -1),
167          "2462ffff       addiu   v0, v1, -1");
168
169  COMPARE(and_(a0, a1, a2),
170          "00a62024       and     a0, a1, a2");
171  COMPARE(and_(s0, s1, s2),
172          "02328024       and     s0, s1, s2");
173  COMPARE(and_(t2, t3, t4),
174          "016c5024       and     t2, t3, t4");
175  COMPARE(and_(v0, v1, a2),
176          "00661024       and     v0, v1, a2");
177
178  COMPARE(or_(a0, a1, a2),
179          "00a62025       or      a0, a1, a2");
180  COMPARE(or_(s0, s1, s2),
181          "02328025       or      s0, s1, s2");
182  COMPARE(or_(t2, t3, t4),
183          "016c5025       or      t2, t3, t4");
184  COMPARE(or_(v0, v1, a2),
185          "00661025       or      v0, v1, a2");
186
187  COMPARE(xor_(a0, a1, a2),
188          "00a62026       xor     a0, a1, a2");
189  COMPARE(xor_(s0, s1, s2),
190          "02328026       xor     s0, s1, s2");
191  COMPARE(xor_(t2, t3, t4),
192          "016c5026       xor     t2, t3, t4");
193  COMPARE(xor_(v0, v1, a2),
194          "00661026       xor     v0, v1, a2");
195
196  COMPARE(nor(a0, a1, a2),
197          "00a62027       nor     a0, a1, a2");
198  COMPARE(nor(s0, s1, s2),
199          "02328027       nor     s0, s1, s2");
200  COMPARE(nor(t2, t3, t4),
201          "016c5027       nor     t2, t3, t4");
202  COMPARE(nor(v0, v1, a2),
203          "00661027       nor     v0, v1, a2");
204
205  COMPARE(andi(a0, a1, 0x1),
206          "30a40001       andi    a0, a1, 0x1");
207  COMPARE(andi(v0, v1, 0xffff),
208          "3062ffff       andi    v0, v1, 0xffff");
209
210  COMPARE(ori(a0, a1, 0x1),
211          "34a40001       ori     a0, a1, 0x1");
212  COMPARE(ori(v0, v1, 0xffff),
213          "3462ffff       ori     v0, v1, 0xffff");
214
215  COMPARE(xori(a0, a1, 0x1),
216          "38a40001       xori    a0, a1, 0x1");
217  COMPARE(xori(v0, v1, 0xffff),
218          "3862ffff       xori    v0, v1, 0xffff");
219
220  COMPARE(lui(a0, 0x1),
221          "3c040001       lui     a0, 0x1");
222  COMPARE(lui(v0, 0xffff),
223          "3c02ffff       lui     v0, 0xffff");
224
225  COMPARE(sll(a0, a1, 0),
226          "00052000       sll     a0, a1, 0");
227  COMPARE(sll(s0, s1, 8),
228          "00118200       sll     s0, s1, 8");
229  COMPARE(sll(t2, t3, 24),
230          "000b5600       sll     t2, t3, 24");
231  COMPARE(sll(v0, v1, 31),
232          "000317c0       sll     v0, v1, 31");
233
234  COMPARE(sllv(a0, a1, a2),
235          "00c52004       sllv    a0, a1, a2");
236  COMPARE(sllv(s0, s1, s2),
237          "02518004       sllv    s0, s1, s2");
238  COMPARE(sllv(t2, t3, t4),
239          "018b5004       sllv    t2, t3, t4");
240  COMPARE(sllv(v0, v1, fp),
241          "03c31004       sllv    v0, v1, fp");
242
243  COMPARE(srl(a0, a1, 0),
244          "00052002       srl     a0, a1, 0");
245  COMPARE(srl(s0, s1, 8),
246          "00118202       srl     s0, s1, 8");
247  COMPARE(srl(t2, t3, 24),
248          "000b5602       srl     t2, t3, 24");
249  COMPARE(srl(v0, v1, 31),
250          "000317c2       srl     v0, v1, 31");
251
252  COMPARE(srlv(a0, a1, a2),
253          "00c52006       srlv    a0, a1, a2");
254  COMPARE(srlv(s0, s1, s2),
255          "02518006       srlv    s0, s1, s2");
256  COMPARE(srlv(t2, t3, t4),
257          "018b5006       srlv    t2, t3, t4");
258  COMPARE(srlv(v0, v1, fp),
259          "03c31006       srlv    v0, v1, fp");
260
261  COMPARE(sra(a0, a1, 0),
262          "00052003       sra     a0, a1, 0");
263  COMPARE(sra(s0, s1, 8),
264          "00118203       sra     s0, s1, 8");
265  COMPARE(sra(t2, t3, 24),
266          "000b5603       sra     t2, t3, 24");
267  COMPARE(sra(v0, v1, 31),
268          "000317c3       sra     v0, v1, 31");
269
270  COMPARE(srav(a0, a1, a2),
271          "00c52007       srav    a0, a1, a2");
272  COMPARE(srav(s0, s1, s2),
273          "02518007       srav    s0, s1, s2");
274  COMPARE(srav(t2, t3, t4),
275          "018b5007       srav    t2, t3, t4");
276  COMPARE(srav(v0, v1, fp),
277          "03c31007       srav    v0, v1, fp");
278
279  if (kArchVariant == kMips32r2) {
280    COMPARE(rotr(a0, a1, 0),
281            "00252002       rotr    a0, a1, 0");
282    COMPARE(rotr(s0, s1, 8),
283            "00318202       rotr    s0, s1, 8");
284    COMPARE(rotr(t2, t3, 24),
285            "002b5602       rotr    t2, t3, 24");
286    COMPARE(rotr(v0, v1, 31),
287            "002317c2       rotr    v0, v1, 31");
288
289    COMPARE(rotrv(a0, a1, a2),
290            "00c52046       rotrv   a0, a1, a2");
291    COMPARE(rotrv(s0, s1, s2),
292            "02518046       rotrv   s0, s1, s2");
293    COMPARE(rotrv(t2, t3, t4),
294            "018b5046       rotrv   t2, t3, t4");
295    COMPARE(rotrv(v0, v1, fp),
296            "03c31046       rotrv   v0, v1, fp");
297  }
298
299  COMPARE(break_(0),
300          "0000000d       break, code: 0x00000 (0)");
301  COMPARE(break_(261120),
302          "00ff000d       break, code: 0x3fc00 (261120)");
303  COMPARE(break_(1047552),
304          "03ff000d       break, code: 0xffc00 (1047552)");
305
306  COMPARE(tge(a0, a1, 0),
307          "00850030       tge     a0, a1, code: 0x000");
308  COMPARE(tge(s0, s1, 1023),
309          "0211fff0       tge     s0, s1, code: 0x3ff");
310  COMPARE(tgeu(a0, a1, 0),
311          "00850031       tgeu    a0, a1, code: 0x000");
312  COMPARE(tgeu(s0, s1, 1023),
313          "0211fff1       tgeu    s0, s1, code: 0x3ff");
314  COMPARE(tlt(a0, a1, 0),
315          "00850032       tlt     a0, a1, code: 0x000");
316  COMPARE(tlt(s0, s1, 1023),
317          "0211fff2       tlt     s0, s1, code: 0x3ff");
318  COMPARE(tltu(a0, a1, 0),
319          "00850033       tltu    a0, a1, code: 0x000");
320  COMPARE(tltu(s0, s1, 1023),
321          "0211fff3       tltu    s0, s1, code: 0x3ff");
322  COMPARE(teq(a0, a1, 0),
323          "00850034       teq     a0, a1, code: 0x000");
324  COMPARE(teq(s0, s1, 1023),
325          "0211fff4       teq     s0, s1, code: 0x3ff");
326  COMPARE(tne(a0, a1, 0),
327          "00850036       tne     a0, a1, code: 0x000");
328  COMPARE(tne(s0, s1, 1023),
329          "0211fff6       tne     s0, s1, code: 0x3ff");
330
331  COMPARE(mfhi(a0),
332          "00002010       mfhi    a0");
333  COMPARE(mfhi(s2),
334          "00009010       mfhi    s2");
335  COMPARE(mfhi(t4),
336          "00006010       mfhi    t4");
337  COMPARE(mfhi(v1),
338          "00001810       mfhi    v1");
339  COMPARE(mflo(a0),
340          "00002012       mflo    a0");
341  COMPARE(mflo(s2),
342          "00009012       mflo    s2");
343  COMPARE(mflo(t4),
344          "00006012       mflo    t4");
345  COMPARE(mflo(v1),
346          "00001812       mflo    v1");
347
348  COMPARE(slt(a0, a1, a2),
349          "00a6202a       slt     a0, a1, a2");
350  COMPARE(slt(s0, s1, s2),
351          "0232802a       slt     s0, s1, s2");
352  COMPARE(slt(t2, t3, t4),
353          "016c502a       slt     t2, t3, t4");
354  COMPARE(slt(v0, v1, a2),
355          "0066102a       slt     v0, v1, a2");
356  COMPARE(sltu(a0, a1, a2),
357          "00a6202b       sltu    a0, a1, a2");
358  COMPARE(sltu(s0, s1, s2),
359          "0232802b       sltu    s0, s1, s2");
360  COMPARE(sltu(t2, t3, t4),
361          "016c502b       sltu    t2, t3, t4");
362  COMPARE(sltu(v0, v1, a2),
363          "0066102b       sltu    v0, v1, a2");
364
365  COMPARE(slti(a0, a1, 0),
366          "28a40000       slti    a0, a1, 0");
367  COMPARE(slti(s0, s1, 32767),
368          "2a307fff       slti    s0, s1, 32767");
369  COMPARE(slti(t2, t3, -32768),
370          "296a8000       slti    t2, t3, -32768");
371  COMPARE(slti(v0, v1, -1),
372          "2862ffff       slti    v0, v1, -1");
373  COMPARE(sltiu(a0, a1, 0),
374          "2ca40000       sltiu   a0, a1, 0");
375  COMPARE(sltiu(s0, s1, 32767),
376          "2e307fff       sltiu   s0, s1, 32767");
377  COMPARE(sltiu(t2, t3, -32768),
378          "2d6a8000       sltiu   t2, t3, -32768");
379  COMPARE(sltiu(v0, v1, -1),
380          "2c62ffff       sltiu   v0, v1, -1");
381
382  if (kArchVariant != kLoongson) {
383    COMPARE(movz(a0, a1, a2),
384            "00a6200a       movz    a0, a1, a2");
385    COMPARE(movz(s0, s1, s2),
386            "0232800a       movz    s0, s1, s2");
387    COMPARE(movz(t2, t3, t4),
388            "016c500a       movz    t2, t3, t4");
389    COMPARE(movz(v0, v1, a2),
390            "0066100a       movz    v0, v1, a2");
391    COMPARE(movn(a0, a1, a2),
392            "00a6200b       movn    a0, a1, a2");
393    COMPARE(movn(s0, s1, s2),
394            "0232800b       movn    s0, s1, s2");
395    COMPARE(movn(t2, t3, t4),
396            "016c500b       movn    t2, t3, t4");
397    COMPARE(movn(v0, v1, a2),
398            "0066100b       movn    v0, v1, a2");
399
400    COMPARE(movt(a0, a1, 1),
401            "00a52001       movt    a0, a1, 1");
402    COMPARE(movt(s0, s1, 2),
403            "02298001       movt    s0, s1, 2");
404    COMPARE(movt(t2, t3, 3),
405            "016d5001       movt    t2, t3, 3");
406    COMPARE(movt(v0, v1, 7),
407            "007d1001       movt    v0, v1, 7");
408    COMPARE(movf(a0, a1, 0),
409            "00a02001       movf    a0, a1, 0");
410    COMPARE(movf(s0, s1, 4),
411            "02308001       movf    s0, s1, 4");
412    COMPARE(movf(t2, t3, 5),
413            "01745001       movf    t2, t3, 5");
414    COMPARE(movf(v0, v1, 6),
415            "00781001       movf    v0, v1, 6");
416
417    COMPARE(clz(a0, a1),
418            "70a42020       clz     a0, a1");
419    COMPARE(clz(s6, s7),
420            "72f6b020       clz     s6, s7");
421    COMPARE(clz(v0, v1),
422            "70621020       clz     v0, v1");
423  }
424
425  if (kArchVariant == kMips32r2) {
426    COMPARE(ins_(a0, a1, 31, 1),
427            "7ca4ffc4       ins     a0, a1, 31, 1");
428    COMPARE(ins_(s6, s7, 30, 2),
429            "7ef6ff84       ins     s6, s7, 30, 2");
430    COMPARE(ins_(v0, v1, 0, 32),
431            "7c62f804       ins     v0, v1, 0, 32");
432    COMPARE(ext_(a0, a1, 31, 1),
433            "7ca407c0       ext     a0, a1, 31, 1");
434    COMPARE(ext_(s6, s7, 30, 2),
435            "7ef60f80       ext     s6, s7, 30, 2");
436    COMPARE(ext_(v0, v1, 0, 32),
437            "7c62f800       ext     v0, v1, 0, 32");
438  }
439
440  VERIFY_RUN();
441}
442