The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / test / cctest / test-assembler-mips.cc @ f230a1cf

History | View | Annotate | Download (33.9 KB)

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
#include "v8.h"
29

    
30
#include "disassembler.h"
31
#include "factory.h"
32
#include "macro-assembler.h"
33
#include "mips/macro-assembler-mips.h"
34
#include "mips/simulator-mips.h"
35

    
36
#include "cctest.h"
37

    
38
using namespace v8::internal;
39

    
40

    
41
// Define these function prototypes to match JSEntryFunction in execution.cc.
42
typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
43
typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
44
typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4);
45

    
46

    
47
#define __ assm.
48

    
49

    
50
TEST(MIPS0) {
51
  CcTest::InitializeVM();
52
  Isolate* isolate = CcTest::i_isolate();
53
  HandleScope scope(isolate);
54

    
55
  MacroAssembler assm(isolate, NULL, 0);
56

    
57
  // Addition.
58
  __ addu(v0, a0, a1);
59
  __ jr(ra);
60
  __ nop();
61

    
62
  CodeDesc desc;
63
  assm.GetCode(&desc);
64
  Object* code = CcTest::heap()->CreateCode(
65
      desc,
66
      Code::ComputeFlags(Code::STUB),
67
      Handle<Code>())->ToObjectChecked();
68
  CHECK(code->IsCode());
69
  F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
70
  int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
71
  ::printf("f() = %d\n", res);
72
  CHECK_EQ(0xabc, res);
73
}
74

    
75

    
76
TEST(MIPS1) {
77
  CcTest::InitializeVM();
78
  Isolate* isolate = CcTest::i_isolate();
79
  HandleScope scope(isolate);
80

    
81
  MacroAssembler assm(isolate, NULL, 0);
82
  Label L, C;
83

    
84
  __ mov(a1, a0);
85
  __ li(v0, 0);
86
  __ b(&C);
87
  __ nop();
88

    
89
  __ bind(&L);
90
  __ addu(v0, v0, a1);
91
  __ addiu(a1, a1, -1);
92

    
93
  __ bind(&C);
94
  __ xori(v1, a1, 0);
95
  __ Branch(&L, ne, v1, Operand(0));
96
  __ nop();
97

    
98
  __ jr(ra);
99
  __ nop();
100

    
101
  CodeDesc desc;
102
  assm.GetCode(&desc);
103
  Object* code = CcTest::heap()->CreateCode(
104
      desc,
105
      Code::ComputeFlags(Code::STUB),
106
      Handle<Code>())->ToObjectChecked();
107
  CHECK(code->IsCode());
108
  F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
109
  int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0));
110
  ::printf("f() = %d\n", res);
111
  CHECK_EQ(1275, res);
112
}
113

    
114

    
115
TEST(MIPS2) {
116
  CcTest::InitializeVM();
117
  Isolate* isolate = CcTest::i_isolate();
118
  HandleScope scope(isolate);
119

    
120
  MacroAssembler assm(isolate, NULL, 0);
121

    
122
  Label exit, error;
123

    
124
  // ----- Test all instructions.
125

    
126
  // Test lui, ori, and addiu, used in the li pseudo-instruction.
127
  // This way we can then safely load registers with chosen values.
128

    
129
  __ ori(t0, zero_reg, 0);
130
  __ lui(t0, 0x1234);
131
  __ ori(t0, t0, 0);
132
  __ ori(t0, t0, 0x0f0f);
133
  __ ori(t0, t0, 0xf0f0);
134
  __ addiu(t1, t0, 1);
135
  __ addiu(t2, t1, -0x10);
136

    
137
  // Load values in temporary registers.
138
  __ li(t0, 0x00000004);
139
  __ li(t1, 0x00001234);
140
  __ li(t2, 0x12345678);
141
  __ li(t3, 0x7fffffff);
142
  __ li(t4, 0xfffffffc);
143
  __ li(t5, 0xffffedcc);
144
  __ li(t6, 0xedcba988);
145
  __ li(t7, 0x80000000);
146

    
147
  // SPECIAL class.
148
  __ srl(v0, t2, 8);    // 0x00123456
149
  __ sll(v0, v0, 11);   // 0x91a2b000
150
  __ sra(v0, v0, 3);    // 0xf2345600
151
  __ srav(v0, v0, t0);  // 0xff234560
152
  __ sllv(v0, v0, t0);  // 0xf2345600
153
  __ srlv(v0, v0, t0);  // 0x0f234560
154
  __ Branch(&error, ne, v0, Operand(0x0f234560));
155
  __ nop();
156

    
157
  __ addu(v0, t0, t1);   // 0x00001238
158
  __ subu(v0, v0, t0);  // 0x00001234
159
  __ Branch(&error, ne, v0, Operand(0x00001234));
160
  __ nop();
161
  __ addu(v1, t3, t0);
162
  __ Branch(&error, ne, v1, Operand(0x80000003));
163
  __ nop();
164
  __ subu(v1, t7, t0);  // 0x7ffffffc
165
  __ Branch(&error, ne, v1, Operand(0x7ffffffc));
166
  __ nop();
167

    
168
  __ and_(v0, t1, t2);  // 0x00001230
169
  __ or_(v0, v0, t1);   // 0x00001234
170
  __ xor_(v0, v0, t2);  // 0x1234444c
171
  __ nor(v0, v0, t2);   // 0xedcba987
172
  __ Branch(&error, ne, v0, Operand(0xedcba983));
173
  __ nop();
174

    
175
  __ slt(v0, t7, t3);
176
  __ Branch(&error, ne, v0, Operand(0x1));
177
  __ nop();
178
  __ sltu(v0, t7, t3);
179
  __ Branch(&error, ne, v0, Operand(0x0));
180
  __ nop();
181
  // End of SPECIAL class.
182

    
183
  __ addiu(v0, zero_reg, 0x7421);  // 0x00007421
184
  __ addiu(v0, v0, -0x1);  // 0x00007420
185
  __ addiu(v0, v0, -0x20);  // 0x00007400
186
  __ Branch(&error, ne, v0, Operand(0x00007400));
187
  __ nop();
188
  __ addiu(v1, t3, 0x1);  // 0x80000000
189
  __ Branch(&error, ne, v1, Operand(0x80000000));
190
  __ nop();
191

    
192
  __ slti(v0, t1, 0x00002000);  // 0x1
193
  __ slti(v0, v0, 0xffff8000);  // 0x0
194
  __ Branch(&error, ne, v0, Operand(0x0));
195
  __ nop();
196
  __ sltiu(v0, t1, 0x00002000);  // 0x1
197
  __ sltiu(v0, v0, 0x00008000);  // 0x1
198
  __ Branch(&error, ne, v0, Operand(0x1));
199
  __ nop();
200

    
201
  __ andi(v0, t1, 0xf0f0);  // 0x00001030
202
  __ ori(v0, v0, 0x8a00);  // 0x00009a30
203
  __ xori(v0, v0, 0x83cc);  // 0x000019fc
204
  __ Branch(&error, ne, v0, Operand(0x000019fc));
205
  __ nop();
206
  __ lui(v1, 0x8123);  // 0x81230000
207
  __ Branch(&error, ne, v1, Operand(0x81230000));
208
  __ nop();
209

    
210
  // Bit twiddling instructions & conditional moves.
211
  // Uses t0-t7 as set above.
212
  __ Clz(v0, t0);       // 29
213
  __ Clz(v1, t1);       // 19
214
  __ addu(v0, v0, v1);  // 48
215
  __ Clz(v1, t2);       // 3
216
  __ addu(v0, v0, v1);  // 51
217
  __ Clz(v1, t7);       // 0
218
  __ addu(v0, v0, v1);  // 51
219
  __ Branch(&error, ne, v0, Operand(51));
220
  __ Movn(a0, t3, t0);  // Move a0<-t3 (t0 is NOT 0).
221
  __ Ins(a0, t1, 12, 8);  // 0x7ff34fff
222
  __ Branch(&error, ne, a0, Operand(0x7ff34fff));
223
  __ Movz(a0, t6, t7);    // a0 not updated (t7 is NOT 0).
224
  __ Ext(a1, a0, 8, 12);  // 0x34f
225
  __ Branch(&error, ne, a1, Operand(0x34f));
226
  __ Movz(a0, t6, v1);    // a0<-t6, v0 is 0, from 8 instr back.
227
  __ Branch(&error, ne, a0, Operand(t6));
228

    
229
  // Everything was correctly executed. Load the expected result.
230
  __ li(v0, 0x31415926);
231
  __ b(&exit);
232
  __ nop();
233

    
234
  __ bind(&error);
235
  // Got an error. Return a wrong result.
236
  __ li(v0, 666);
237

    
238
  __ bind(&exit);
239
  __ jr(ra);
240
  __ nop();
241

    
242
  CodeDesc desc;
243
  assm.GetCode(&desc);
244
  Object* code = CcTest::heap()->CreateCode(
245
      desc,
246
      Code::ComputeFlags(Code::STUB),
247
      Handle<Code>())->ToObjectChecked();
248
  CHECK(code->IsCode());
249
  F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
250
  int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
251
  ::printf("f() = %d\n", res);
252
  CHECK_EQ(0x31415926, res);
253
}
254

    
255

    
256
TEST(MIPS3) {
257
  // Test floating point instructions.
258
  CcTest::InitializeVM();
259
  Isolate* isolate = CcTest::i_isolate();
260
  HandleScope scope(isolate);
261

    
262
  typedef struct {
263
    double a;
264
    double b;
265
    double c;
266
    double d;
267
    double e;
268
    double f;
269
    double g;
270
    double h;
271
    double i;
272
  } T;
273
  T t;
274

    
275
  // Create a function that accepts &t, and loads, manipulates, and stores
276
  // the doubles t.a ... t.f.
277
  MacroAssembler assm(isolate, NULL, 0);
278
  Label L, C;
279

    
280
  __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
281
  __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
282
  __ add_d(f8, f4, f6);
283
  __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, c)) );  // c = a + b.
284

    
285
  __ mov_d(f10, f8);  // c
286
  __ neg_d(f12, f6);  // -b
287
  __ sub_d(f10, f10, f12);
288
  __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, d)) );  // d = c - (-b).
289

    
290
  __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) );   // b = a.
291

    
292
  __ li(t0, 120);
293
  __ mtc1(t0, f14);
294
  __ cvt_d_w(f14, f14);   // f14 = 120.0.
295
  __ mul_d(f10, f10, f14);
296
  __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, e)) );  // e = d * 120 = 1.8066e16.
297

    
298
  __ div_d(f12, f10, f4);
299
  __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) );  // f = e / a = 120.44.
300

    
301
  __ sqrt_d(f14, f12);
302
  __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, g)) );
303
  // g = sqrt(f) = 10.97451593465515908537
304

    
305
  if (kArchVariant == kMips32r2) {
306
    __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, h)) );
307
    __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, i)) );
308
    __ madd_d(f14, f6, f4, f6);
309
    __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, h)) );
310
  }
311

    
312
  __ jr(ra);
313
  __ nop();
314

    
315
  CodeDesc desc;
316
  assm.GetCode(&desc);
317
  Object* code = CcTest::heap()->CreateCode(
318
      desc,
319
      Code::ComputeFlags(Code::STUB),
320
      Handle<Code>())->ToObjectChecked();
321
  CHECK(code->IsCode());
322
  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
323
  t.a = 1.5e14;
324
  t.b = 2.75e11;
325
  t.c = 0.0;
326
  t.d = 0.0;
327
  t.e = 0.0;
328
  t.f = 0.0;
329
  t.h = 1.5;
330
  t.i = 2.75;
331
  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
332
  USE(dummy);
333
  CHECK_EQ(1.5e14, t.a);
334
  CHECK_EQ(1.5e14, t.b);
335
  CHECK_EQ(1.50275e14, t.c);
336
  CHECK_EQ(1.50550e14, t.d);
337
  CHECK_EQ(1.8066e16, t.e);
338
  CHECK_EQ(120.44, t.f);
339
  CHECK_EQ(10.97451593465515908537, t.g);
340
  if (kArchVariant == kMips32r2) {
341
    CHECK_EQ(6.875, t.h);
342
  }
343
}
344

    
345

    
346
TEST(MIPS4) {
347
  // Test moves between floating point and integer registers.
348
  CcTest::InitializeVM();
349
  Isolate* isolate = CcTest::i_isolate();
350
  HandleScope scope(isolate);
351

    
352
  typedef struct {
353
    double a;
354
    double b;
355
    double c;
356
  } T;
357
  T t;
358

    
359
  Assembler assm(isolate, NULL, 0);
360
  Label L, C;
361

    
362
  __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
363
  __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
364

    
365
  // Swap f4 and f6, by using four integer registers, t0-t3.
366
  __ mfc1(t0, f4);
367
  __ mfc1(t1, f5);
368
  __ mfc1(t2, f6);
369
  __ mfc1(t3, f7);
370

    
371
  __ mtc1(t0, f6);
372
  __ mtc1(t1, f7);
373
  __ mtc1(t2, f4);
374
  __ mtc1(t3, f5);
375

    
376
  // Store the swapped f4 and f5 back to memory.
377
  __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
378
  __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, c)) );
379

    
380
  __ jr(ra);
381
  __ nop();
382

    
383
  CodeDesc desc;
384
  assm.GetCode(&desc);
385
  Object* code = CcTest::heap()->CreateCode(
386
      desc,
387
      Code::ComputeFlags(Code::STUB),
388
      Handle<Code>())->ToObjectChecked();
389
  CHECK(code->IsCode());
390
  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
391
  t.a = 1.5e22;
392
  t.b = 2.75e11;
393
  t.c = 17.17;
394
  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
395
  USE(dummy);
396

    
397
  CHECK_EQ(2.75e11, t.a);
398
  CHECK_EQ(2.75e11, t.b);
399
  CHECK_EQ(1.5e22, t.c);
400
}
401

    
402

    
403
TEST(MIPS5) {
404
  // Test conversions between doubles and integers.
405
  CcTest::InitializeVM();
406
  Isolate* isolate = CcTest::i_isolate();
407
  HandleScope scope(isolate);
408

    
409
  typedef struct {
410
    double a;
411
    double b;
412
    int i;
413
    int j;
414
  } T;
415
  T t;
416

    
417
  Assembler assm(isolate, NULL, 0);
418
  Label L, C;
419

    
420
  // Load all structure elements to registers.
421
  __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
422
  __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
423
  __ lw(t0, MemOperand(a0, OFFSET_OF(T, i)) );
424
  __ lw(t1, MemOperand(a0, OFFSET_OF(T, j)) );
425

    
426
  // Convert double in f4 to int in element i.
427
  __ cvt_w_d(f8, f4);
428
  __ mfc1(t2, f8);
429
  __ sw(t2, MemOperand(a0, OFFSET_OF(T, i)) );
430

    
431
  // Convert double in f6 to int in element j.
432
  __ cvt_w_d(f10, f6);
433
  __ mfc1(t3, f10);
434
  __ sw(t3, MemOperand(a0, OFFSET_OF(T, j)) );
435

    
436
  // Convert int in original i (t0) to double in a.
437
  __ mtc1(t0, f12);
438
  __ cvt_d_w(f0, f12);
439
  __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) );
440

    
441
  // Convert int in original j (t1) to double in b.
442
  __ mtc1(t1, f14);
443
  __ cvt_d_w(f2, f14);
444
  __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) );
445

    
446
  __ jr(ra);
447
  __ nop();
448

    
449
  CodeDesc desc;
450
  assm.GetCode(&desc);
451
  Object* code = CcTest::heap()->CreateCode(
452
      desc,
453
      Code::ComputeFlags(Code::STUB),
454
      Handle<Code>())->ToObjectChecked();
455
  CHECK(code->IsCode());
456
  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
457
  t.a = 1.5e4;
458
  t.b = 2.75e8;
459
  t.i = 12345678;
460
  t.j = -100000;
461
  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
462
  USE(dummy);
463

    
464
  CHECK_EQ(12345678.0, t.a);
465
  CHECK_EQ(-100000.0, t.b);
466
  CHECK_EQ(15000, t.i);
467
  CHECK_EQ(275000000, t.j);
468
}
469

    
470

    
471
TEST(MIPS6) {
472
  // Test simple memory loads and stores.
473
  CcTest::InitializeVM();
474
  Isolate* isolate = CcTest::i_isolate();
475
  HandleScope scope(isolate);
476

    
477
  typedef struct {
478
    uint32_t ui;
479
    int32_t si;
480
    int32_t r1;
481
    int32_t r2;
482
    int32_t r3;
483
    int32_t r4;
484
    int32_t r5;
485
    int32_t r6;
486
  } T;
487
  T t;
488

    
489
  Assembler assm(isolate, NULL, 0);
490
  Label L, C;
491

    
492
  // Basic word load/store.
493
  __ lw(t0, MemOperand(a0, OFFSET_OF(T, ui)) );
494
  __ sw(t0, MemOperand(a0, OFFSET_OF(T, r1)) );
495

    
496
  // lh with positive data.
497
  __ lh(t1, MemOperand(a0, OFFSET_OF(T, ui)) );
498
  __ sw(t1, MemOperand(a0, OFFSET_OF(T, r2)) );
499

    
500
  // lh with negative data.
501
  __ lh(t2, MemOperand(a0, OFFSET_OF(T, si)) );
502
  __ sw(t2, MemOperand(a0, OFFSET_OF(T, r3)) );
503

    
504
  // lhu with negative data.
505
  __ lhu(t3, MemOperand(a0, OFFSET_OF(T, si)) );
506
  __ sw(t3, MemOperand(a0, OFFSET_OF(T, r4)) );
507

    
508
  // lb with negative data.
509
  __ lb(t4, MemOperand(a0, OFFSET_OF(T, si)) );
510
  __ sw(t4, MemOperand(a0, OFFSET_OF(T, r5)) );
511

    
512
  // sh writes only 1/2 of word.
513
  __ lui(t5, 0x3333);
514
  __ ori(t5, t5, 0x3333);
515
  __ sw(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
516
  __ lhu(t5, MemOperand(a0, OFFSET_OF(T, si)) );
517
  __ sh(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
518

    
519
  __ jr(ra);
520
  __ nop();
521

    
522
  CodeDesc desc;
523
  assm.GetCode(&desc);
524
  Object* code = CcTest::heap()->CreateCode(
525
      desc,
526
      Code::ComputeFlags(Code::STUB),
527
      Handle<Code>())->ToObjectChecked();
528
  CHECK(code->IsCode());
529
  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
530
  t.ui = 0x11223344;
531
  t.si = 0x99aabbcc;
532
  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
533
  USE(dummy);
534

    
535
  CHECK_EQ(0x11223344, t.r1);
536
  CHECK_EQ(0x3344, t.r2);
537
  CHECK_EQ(0xffffbbcc, t.r3);
538
  CHECK_EQ(0x0000bbcc, t.r4);
539
  CHECK_EQ(0xffffffcc, t.r5);
540
  CHECK_EQ(0x3333bbcc, t.r6);
541
}
542

    
543

    
544
TEST(MIPS7) {
545
  // Test floating point compare and branch instructions.
546
  CcTest::InitializeVM();
547
  Isolate* isolate = CcTest::i_isolate();
548
  HandleScope scope(isolate);
549

    
550
  typedef struct {
551
    double a;
552
    double b;
553
    double c;
554
    double d;
555
    double e;
556
    double f;
557
    int32_t result;
558
  } T;
559
  T t;
560

    
561
  // Create a function that accepts &t, and loads, manipulates, and stores
562
  // the doubles t.a ... t.f.
563
  MacroAssembler assm(isolate, NULL, 0);
564
  Label neither_is_nan, less_than, outa_here;
565

    
566
  __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
567
  __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
568
  __ c(UN, D, f4, f6);
569
  __ bc1f(&neither_is_nan);
570
  __ nop();
571
  __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
572
  __ Branch(&outa_here);
573

    
574
  __ bind(&neither_is_nan);
575

    
576
  if (kArchVariant == kLoongson) {
577
    __ c(OLT, D, f6, f4);
578
    __ bc1t(&less_than);
579
  } else {
580
    __ c(OLT, D, f6, f4, 2);
581
    __ bc1t(&less_than, 2);
582
  }
583
  __ nop();
584
  __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
585
  __ Branch(&outa_here);
586

    
587
  __ bind(&less_than);
588
  __ Addu(t0, zero_reg, Operand(1));
589
  __ sw(t0, MemOperand(a0, OFFSET_OF(T, result)) );  // Set true.
590

    
591

    
592
  // This test-case should have additional tests.
593

    
594
  __ bind(&outa_here);
595

    
596
  __ jr(ra);
597
  __ nop();
598

    
599
  CodeDesc desc;
600
  assm.GetCode(&desc);
601
  Object* code = CcTest::heap()->CreateCode(
602
      desc,
603
      Code::ComputeFlags(Code::STUB),
604
      Handle<Code>())->ToObjectChecked();
605
  CHECK(code->IsCode());
606
  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
607
  t.a = 1.5e14;
608
  t.b = 2.75e11;
609
  t.c = 2.0;
610
  t.d = -4.0;
611
  t.e = 0.0;
612
  t.f = 0.0;
613
  t.result = 0;
614
  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
615
  USE(dummy);
616
  CHECK_EQ(1.5e14, t.a);
617
  CHECK_EQ(2.75e11, t.b);
618
  CHECK_EQ(1, t.result);
619
}
620

    
621

    
622
TEST(MIPS8) {
623
  // Test ROTR and ROTRV instructions.
624
  CcTest::InitializeVM();
625
  Isolate* isolate = CcTest::i_isolate();
626
  HandleScope scope(isolate);
627

    
628
  typedef struct {
629
    int32_t input;
630
    int32_t result_rotr_4;
631
    int32_t result_rotr_8;
632
    int32_t result_rotr_12;
633
    int32_t result_rotr_16;
634
    int32_t result_rotr_20;
635
    int32_t result_rotr_24;
636
    int32_t result_rotr_28;
637
    int32_t result_rotrv_4;
638
    int32_t result_rotrv_8;
639
    int32_t result_rotrv_12;
640
    int32_t result_rotrv_16;
641
    int32_t result_rotrv_20;
642
    int32_t result_rotrv_24;
643
    int32_t result_rotrv_28;
644
  } T;
645
  T t;
646

    
647
  MacroAssembler assm(isolate, NULL, 0);
648

    
649
  // Basic word load.
650
  __ lw(t0, MemOperand(a0, OFFSET_OF(T, input)) );
651

    
652
  // ROTR instruction (called through the Ror macro).
653
  __ Ror(t1, t0, 0x0004);
654
  __ Ror(t2, t0, 0x0008);
655
  __ Ror(t3, t0, 0x000c);
656
  __ Ror(t4, t0, 0x0010);
657
  __ Ror(t5, t0, 0x0014);
658
  __ Ror(t6, t0, 0x0018);
659
  __ Ror(t7, t0, 0x001c);
660

    
661
  // Basic word store.
662
  __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotr_4)) );
663
  __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotr_8)) );
664
  __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotr_12)) );
665
  __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotr_16)) );
666
  __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotr_20)) );
667
  __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotr_24)) );
668
  __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotr_28)) );
669

    
670
  // ROTRV instruction (called through the Ror macro).
671
  __ li(t7, 0x0004);
672
  __ Ror(t1, t0, t7);
673
  __ li(t7, 0x0008);
674
  __ Ror(t2, t0, t7);
675
  __ li(t7, 0x000C);
676
  __ Ror(t3, t0, t7);
677
  __ li(t7, 0x0010);
678
  __ Ror(t4, t0, t7);
679
  __ li(t7, 0x0014);
680
  __ Ror(t5, t0, t7);
681
  __ li(t7, 0x0018);
682
  __ Ror(t6, t0, t7);
683
  __ li(t7, 0x001C);
684
  __ Ror(t7, t0, t7);
685

    
686
  // Basic word store.
687
  __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotrv_4)) );
688
  __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotrv_8)) );
689
  __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotrv_12)) );
690
  __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotrv_16)) );
691
  __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotrv_20)) );
692
  __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotrv_24)) );
693
  __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotrv_28)) );
694

    
695
  __ jr(ra);
696
  __ nop();
697

    
698
  CodeDesc desc;
699
  assm.GetCode(&desc);
700
  Object* code = CcTest::heap()->CreateCode(
701
      desc,
702
      Code::ComputeFlags(Code::STUB),
703
      Handle<Code>())->ToObjectChecked();
704
  CHECK(code->IsCode());
705
  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
706
  t.input = 0x12345678;
707
  Object* dummy = CALL_GENERATED_CODE(f, &t, 0x0, 0, 0, 0);
708
  USE(dummy);
709
  CHECK_EQ(0x81234567, t.result_rotr_4);
710
  CHECK_EQ(0x78123456, t.result_rotr_8);
711
  CHECK_EQ(0x67812345, t.result_rotr_12);
712
  CHECK_EQ(0x56781234, t.result_rotr_16);
713
  CHECK_EQ(0x45678123, t.result_rotr_20);
714
  CHECK_EQ(0x34567812, t.result_rotr_24);
715
  CHECK_EQ(0x23456781, t.result_rotr_28);
716

    
717
  CHECK_EQ(0x81234567, t.result_rotrv_4);
718
  CHECK_EQ(0x78123456, t.result_rotrv_8);
719
  CHECK_EQ(0x67812345, t.result_rotrv_12);
720
  CHECK_EQ(0x56781234, t.result_rotrv_16);
721
  CHECK_EQ(0x45678123, t.result_rotrv_20);
722
  CHECK_EQ(0x34567812, t.result_rotrv_24);
723
  CHECK_EQ(0x23456781, t.result_rotrv_28);
724
}
725

    
726

    
727
TEST(MIPS9) {
728
  // Test BRANCH improvements.
729
  CcTest::InitializeVM();
730
  Isolate* isolate = CcTest::i_isolate();
731
  HandleScope scope(isolate);
732

    
733
  MacroAssembler assm(isolate, NULL, 0);
734
  Label exit, exit2, exit3;
735

    
736
  __ Branch(&exit, ge, a0, Operand(0x00000000));
737
  __ Branch(&exit2, ge, a0, Operand(0x00001FFF));
738
  __ Branch(&exit3, ge, a0, Operand(0x0001FFFF));
739

    
740
  __ bind(&exit);
741
  __ bind(&exit2);
742
  __ bind(&exit3);
743
  __ jr(ra);
744
  __ nop();
745

    
746
  CodeDesc desc;
747
  assm.GetCode(&desc);
748
  Object* code = CcTest::heap()->CreateCode(
749
      desc,
750
      Code::ComputeFlags(Code::STUB),
751
      Handle<Code>())->ToObjectChecked();
752
  CHECK(code->IsCode());
753
}
754

    
755

    
756
TEST(MIPS10) {
757
  // Test conversions between doubles and long integers.
758
  // Test hos the long ints map to FP regs pairs.
759
  CcTest::InitializeVM();
760
  Isolate* isolate = CcTest::i_isolate();
761
  HandleScope scope(isolate);
762

    
763
  typedef struct {
764
    double a;
765
    double b;
766
    int32_t dbl_mant;
767
    int32_t dbl_exp;
768
    int32_t long_hi;
769
    int32_t long_lo;
770
    int32_t b_long_hi;
771
    int32_t b_long_lo;
772
  } T;
773
  T t;
774

    
775
  Assembler assm(isolate, NULL, 0);
776
  Label L, C;
777

    
778
  if (kArchVariant == kMips32r2) {
779
    // Load all structure elements to registers.
780
    __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a)));
781

    
782
    // Save the raw bits of the double.
783
    __ mfc1(t0, f0);
784
    __ mfc1(t1, f1);
785
    __ sw(t0, MemOperand(a0, OFFSET_OF(T, dbl_mant)));
786
    __ sw(t1, MemOperand(a0, OFFSET_OF(T, dbl_exp)));
787

    
788
    // Convert double in f0 to long, save hi/lo parts.
789
    __ cvt_l_d(f0, f0);
790
    __ mfc1(t0, f0);  // f0 has LS 32 bits of long.
791
    __ mfc1(t1, f1);  // f1 has MS 32 bits of long.
792
    __ sw(t0, MemOperand(a0, OFFSET_OF(T, long_lo)));
793
    __ sw(t1, MemOperand(a0, OFFSET_OF(T, long_hi)));
794

    
795
    // Convert the b long integers to double b.
796
    __ lw(t0, MemOperand(a0, OFFSET_OF(T, b_long_lo)));
797
    __ lw(t1, MemOperand(a0, OFFSET_OF(T, b_long_hi)));
798
    __ mtc1(t0, f8);  // f8 has LS 32-bits.
799
    __ mtc1(t1, f9);  // f9 has MS 32-bits.
800
    __ cvt_d_l(f10, f8);
801
    __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, b)));
802

    
803
    __ jr(ra);
804
    __ nop();
805

    
806
    CodeDesc desc;
807
    assm.GetCode(&desc);
808
    Object* code = CcTest::heap()->CreateCode(
809
        desc,
810
        Code::ComputeFlags(Code::STUB),
811
        Handle<Code>())->ToObjectChecked();
812
    CHECK(code->IsCode());
813
    F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
814
    t.a = 2.147483647e9;       // 0x7fffffff -> 0x41DFFFFFFFC00000 as double.
815
    t.b_long_hi = 0x000000ff;  // 0xFF00FF00FF -> 0x426FE01FE01FE000 as double.
816
    t.b_long_lo = 0x00ff00ff;
817
    Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
818
    USE(dummy);
819

    
820
    CHECK_EQ(0x41DFFFFF, t.dbl_exp);
821
    CHECK_EQ(0xFFC00000, t.dbl_mant);
822
    CHECK_EQ(0, t.long_hi);
823
    CHECK_EQ(0x7fffffff, t.long_lo);
824
    // 0xFF00FF00FF -> 1.095233372415e12.
825
    CHECK_EQ(1.095233372415e12, t.b);
826
  }
827
}
828

    
829

    
830
TEST(MIPS11) {
831
  // Test LWL, LWR, SWL and SWR instructions.
832
  CcTest::InitializeVM();
833
  Isolate* isolate = CcTest::i_isolate();
834
  HandleScope scope(isolate);
835

    
836
  typedef struct {
837
    int32_t reg_init;
838
    int32_t mem_init;
839
    int32_t lwl_0;
840
    int32_t lwl_1;
841
    int32_t lwl_2;
842
    int32_t lwl_3;
843
    int32_t lwr_0;
844
    int32_t lwr_1;
845
    int32_t lwr_2;
846
    int32_t lwr_3;
847
    int32_t swl_0;
848
    int32_t swl_1;
849
    int32_t swl_2;
850
    int32_t swl_3;
851
    int32_t swr_0;
852
    int32_t swr_1;
853
    int32_t swr_2;
854
    int32_t swr_3;
855
  } T;
856
  T t;
857

    
858
  Assembler assm(isolate, NULL, 0);
859

    
860
  // Test all combinations of LWL and vAddr.
861
  __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
862
  __ lwl(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
863
  __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwl_0)) );
864

    
865
  __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
866
  __ lwl(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) );
867
  __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwl_1)) );
868

    
869
  __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
870
  __ lwl(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) );
871
  __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwl_2)) );
872

    
873
  __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
874
  __ lwl(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) );
875
  __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwl_3)) );
876

    
877
  // Test all combinations of LWR and vAddr.
878
  __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
879
  __ lwr(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
880
  __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwr_0)) );
881

    
882
  __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
883
  __ lwr(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) );
884
  __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwr_1)) );
885

    
886
  __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
887
  __ lwr(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) );
888
  __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwr_2)) );
889

    
890
  __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
891
  __ lwr(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) );
892
  __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwr_3)) );
893

    
894
  // Test all combinations of SWL and vAddr.
895
  __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
896
  __ sw(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) );
897
  __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
898
  __ swl(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) );
899

    
900
  __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) );
901
  __ sw(t1, MemOperand(a0, OFFSET_OF(T, swl_1)) );
902
  __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
903
  __ swl(t1, MemOperand(a0, OFFSET_OF(T, swl_1) + 1) );
904

    
905
  __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) );
906
  __ sw(t2, MemOperand(a0, OFFSET_OF(T, swl_2)) );
907
  __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
908
  __ swl(t2, MemOperand(a0, OFFSET_OF(T, swl_2) + 2) );
909

    
910
  __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) );
911
  __ sw(t3, MemOperand(a0, OFFSET_OF(T, swl_3)) );
912
  __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
913
  __ swl(t3, MemOperand(a0, OFFSET_OF(T, swl_3) + 3) );
914

    
915
  // Test all combinations of SWR and vAddr.
916
  __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
917
  __ sw(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) );
918
  __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
919
  __ swr(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) );
920

    
921
  __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) );
922
  __ sw(t1, MemOperand(a0, OFFSET_OF(T, swr_1)) );
923
  __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
924
  __ swr(t1, MemOperand(a0, OFFSET_OF(T, swr_1) + 1) );
925

    
926
  __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) );
927
  __ sw(t2, MemOperand(a0, OFFSET_OF(T, swr_2)) );
928
  __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
929
  __ swr(t2, MemOperand(a0, OFFSET_OF(T, swr_2) + 2) );
930

    
931
  __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) );
932
  __ sw(t3, MemOperand(a0, OFFSET_OF(T, swr_3)) );
933
  __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
934
  __ swr(t3, MemOperand(a0, OFFSET_OF(T, swr_3) + 3) );
935

    
936
  __ jr(ra);
937
  __ nop();
938

    
939
  CodeDesc desc;
940
  assm.GetCode(&desc);
941
  Object* code = CcTest::heap()->CreateCode(
942
      desc,
943
      Code::ComputeFlags(Code::STUB),
944
      Handle<Code>())->ToObjectChecked();
945
  CHECK(code->IsCode());
946
  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
947
  t.reg_init = 0xaabbccdd;
948
  t.mem_init = 0x11223344;
949

    
950
  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
951
  USE(dummy);
952

    
953
  CHECK_EQ(0x44bbccdd, t.lwl_0);
954
  CHECK_EQ(0x3344ccdd, t.lwl_1);
955
  CHECK_EQ(0x223344dd, t.lwl_2);
956
  CHECK_EQ(0x11223344, t.lwl_3);
957

    
958
  CHECK_EQ(0x11223344, t.lwr_0);
959
  CHECK_EQ(0xaa112233, t.lwr_1);
960
  CHECK_EQ(0xaabb1122, t.lwr_2);
961
  CHECK_EQ(0xaabbcc11, t.lwr_3);
962

    
963
  CHECK_EQ(0x112233aa, t.swl_0);
964
  CHECK_EQ(0x1122aabb, t.swl_1);
965
  CHECK_EQ(0x11aabbcc, t.swl_2);
966
  CHECK_EQ(0xaabbccdd, t.swl_3);
967

    
968
  CHECK_EQ(0xaabbccdd, t.swr_0);
969
  CHECK_EQ(0xbbccdd44, t.swr_1);
970
  CHECK_EQ(0xccdd3344, t.swr_2);
971
  CHECK_EQ(0xdd223344, t.swr_3);
972
}
973

    
974

    
975
TEST(MIPS12) {
976
  CcTest::InitializeVM();
977
  Isolate* isolate = CcTest::i_isolate();
978
  HandleScope scope(isolate);
979

    
980
  typedef struct {
981
      int32_t  x;
982
      int32_t  y;
983
      int32_t  y1;
984
      int32_t  y2;
985
      int32_t  y3;
986
      int32_t  y4;
987
  } T;
988
  T t;
989

    
990
  MacroAssembler assm(isolate, NULL, 0);
991

    
992
  __ mov(t6, fp);  // Save frame pointer.
993
  __ mov(fp, a0);  // Access struct T by fp.
994
  __ lw(t0, MemOperand(a0, OFFSET_OF(T, y)) );
995
  __ lw(t3, MemOperand(a0, OFFSET_OF(T, y4)) );
996

    
997
  __ addu(t1, t0, t3);
998
  __ subu(t4, t0, t3);
999
  __ nop();
1000
  __ push(t0);  // These instructions disappear after opt.
1001
  __ Pop();
1002
  __ addu(t0, t0, t0);
1003
  __ nop();
1004
  __ Pop();     // These instructions disappear after opt.
1005
  __ push(t3);
1006
  __ nop();
1007
  __ push(t3);  // These instructions disappear after opt.
1008
  __ pop(t3);
1009
  __ nop();
1010
  __ push(t3);
1011
  __ pop(t4);
1012
  __ nop();
1013
  __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1014
  __ lw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1015
  __ nop();
1016
  __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1017
  __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
1018
  __ nop();
1019
  __ push(t1);
1020
  __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
1021
  __ pop(t1);
1022
  __ nop();
1023
  __ push(t1);
1024
  __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1025
  __ pop(t1);
1026
  __ nop();
1027
  __ push(t1);
1028
  __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1029
  __ pop(t2);
1030
  __ nop();
1031
  __ push(t2);
1032
  __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1033
  __ pop(t1);
1034
  __ nop();
1035
  __ push(t1);
1036
  __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1037
  __ pop(t3);
1038
  __ nop();
1039

    
1040
  __ mov(fp, t6);
1041
  __ jr(ra);
1042
  __ nop();
1043

    
1044
  CodeDesc desc;
1045
  assm.GetCode(&desc);
1046
  Object* code = CcTest::heap()->CreateCode(
1047
      desc,
1048
      Code::ComputeFlags(Code::STUB),
1049
      Handle<Code>())->ToObjectChecked();
1050
  CHECK(code->IsCode());
1051
  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1052
  t.x = 1;
1053
  t.y = 2;
1054
  t.y1 = 3;
1055
  t.y2 = 4;
1056
  t.y3 = 0XBABA;
1057
  t.y4 = 0xDEDA;
1058

    
1059
  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1060
  USE(dummy);
1061

    
1062
  CHECK_EQ(3, t.y1);
1063
}
1064

    
1065

    
1066
TEST(MIPS13) {
1067
  // Test Cvt_d_uw and Trunc_uw_d macros.
1068
  CcTest::InitializeVM();
1069
  Isolate* isolate = CcTest::i_isolate();
1070
  HandleScope scope(isolate);
1071

    
1072
  typedef struct {
1073
    double cvt_big_out;
1074
    double cvt_small_out;
1075
    uint32_t trunc_big_out;
1076
    uint32_t trunc_small_out;
1077
    uint32_t cvt_big_in;
1078
    uint32_t cvt_small_in;
1079
  } T;
1080
  T t;
1081

    
1082
  MacroAssembler assm(isolate, NULL, 0);
1083

    
1084
  __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_small_in)));
1085
  __ Cvt_d_uw(f10, t0, f22);
1086
  __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out)));
1087

    
1088
  __ Trunc_uw_d(f10, f10, f22);
1089
  __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out)));
1090

    
1091
  __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_big_in)));
1092
  __ Cvt_d_uw(f8, t0, f22);
1093
  __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out)));
1094

    
1095
  __ Trunc_uw_d(f8, f8, f22);
1096
  __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out)));
1097

    
1098
  __ jr(ra);
1099
  __ nop();
1100

    
1101
  CodeDesc desc;
1102
  assm.GetCode(&desc);
1103
  Object* code = CcTest::heap()->CreateCode(
1104
      desc,
1105
      Code::ComputeFlags(Code::STUB),
1106
      Handle<Code>())->ToObjectChecked();
1107
  CHECK(code->IsCode());
1108
  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1109

    
1110
  t.cvt_big_in = 0xFFFFFFFF;
1111
  t.cvt_small_in  = 333;
1112

    
1113
  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1114
  USE(dummy);
1115

    
1116
  CHECK_EQ(t.cvt_big_out, static_cast<double>(t.cvt_big_in));
1117
  CHECK_EQ(t.cvt_small_out, static_cast<double>(t.cvt_small_in));
1118

    
1119
  CHECK_EQ(static_cast<int>(t.trunc_big_out), static_cast<int>(t.cvt_big_in));
1120
  CHECK_EQ(static_cast<int>(t.trunc_small_out),
1121
           static_cast<int>(t.cvt_small_in));
1122
}
1123

    
1124

    
1125
TEST(MIPS14) {
1126
  // Test round, floor, ceil, trunc, cvt.
1127
  CcTest::InitializeVM();
1128
  Isolate* isolate = CcTest::i_isolate();
1129
  HandleScope scope(isolate);
1130

    
1131
#define ROUND_STRUCT_ELEMENT(x) \
1132
  int32_t x##_up_out; \
1133
  int32_t x##_down_out; \
1134
  int32_t neg_##x##_up_out; \
1135
  int32_t neg_##x##_down_out; \
1136
  uint32_t x##_err1_out; \
1137
  uint32_t x##_err2_out; \
1138
  uint32_t x##_err3_out; \
1139
  uint32_t x##_err4_out; \
1140
  int32_t x##_invalid_result;
1141

    
1142
  typedef struct {
1143
    double round_up_in;
1144
    double round_down_in;
1145
    double neg_round_up_in;
1146
    double neg_round_down_in;
1147
    double err1_in;
1148
    double err2_in;
1149
    double err3_in;
1150
    double err4_in;
1151

    
1152
    ROUND_STRUCT_ELEMENT(round)
1153
    ROUND_STRUCT_ELEMENT(floor)
1154
    ROUND_STRUCT_ELEMENT(ceil)
1155
    ROUND_STRUCT_ELEMENT(trunc)
1156
    ROUND_STRUCT_ELEMENT(cvt)
1157
  } T;
1158
  T t;
1159

    
1160
#undef ROUND_STRUCT_ELEMENT
1161

    
1162
  MacroAssembler assm(isolate, NULL, 0);
1163

    
1164
  // Save FCSR.
1165
  __ cfc1(a1, FCSR);
1166
  // Disable FPU exceptions.
1167
  __ ctc1(zero_reg, FCSR);
1168
#define RUN_ROUND_TEST(x) \
1169
  __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_up_in))); \
1170
  __ x##_w_d(f0, f0); \
1171
  __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_up_out))); \
1172
  \
1173
  __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_down_in))); \
1174
  __ x##_w_d(f0, f0); \
1175
  __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_down_out))); \
1176
  \
1177
  __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_up_in))); \
1178
  __ x##_w_d(f0, f0); \
1179
  __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_up_out))); \
1180
  \
1181
  __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_down_in))); \
1182
  __ x##_w_d(f0, f0); \
1183
  __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_down_out))); \
1184
  \
1185
  __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err1_in))); \
1186
  __ ctc1(zero_reg, FCSR); \
1187
  __ x##_w_d(f0, f0); \
1188
  __ cfc1(a2, FCSR); \
1189
  __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err1_out))); \
1190
  \
1191
  __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err2_in))); \
1192
  __ ctc1(zero_reg, FCSR); \
1193
  __ x##_w_d(f0, f0); \
1194
  __ cfc1(a2, FCSR); \
1195
  __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err2_out))); \
1196
  \
1197
  __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err3_in))); \
1198
  __ ctc1(zero_reg, FCSR); \
1199
  __ x##_w_d(f0, f0); \
1200
  __ cfc1(a2, FCSR); \
1201
  __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err3_out))); \
1202
  \
1203
  __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err4_in))); \
1204
  __ ctc1(zero_reg, FCSR); \
1205
  __ x##_w_d(f0, f0); \
1206
  __ cfc1(a2, FCSR); \
1207
  __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err4_out))); \
1208
  __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_invalid_result)));
1209

    
1210
  RUN_ROUND_TEST(round)
1211
  RUN_ROUND_TEST(floor)
1212
  RUN_ROUND_TEST(ceil)
1213
  RUN_ROUND_TEST(trunc)
1214
  RUN_ROUND_TEST(cvt)
1215

    
1216
  // Restore FCSR.
1217
  __ ctc1(a1, FCSR);
1218

    
1219
  __ jr(ra);
1220
  __ nop();
1221

    
1222
  CodeDesc desc;
1223
  assm.GetCode(&desc);
1224
  Object* code = CcTest::heap()->CreateCode(
1225
      desc,
1226
      Code::ComputeFlags(Code::STUB),
1227
      Handle<Code>())->ToObjectChecked();
1228
  CHECK(code->IsCode());
1229
  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1230

    
1231
  t.round_up_in = 123.51;
1232
  t.round_down_in = 123.49;
1233
  t.neg_round_up_in = -123.5;
1234
  t.neg_round_down_in = -123.49;
1235
  t.err1_in = 123.51;
1236
  t.err2_in = 1;
1237
  t.err3_in = static_cast<double>(1) + 0xFFFFFFFF;
1238
  t.err4_in = NAN;
1239

    
1240
  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1241
  USE(dummy);
1242

    
1243
#define GET_FPU_ERR(x) (static_cast<int>(x & kFCSRFlagMask))
1244
#define CHECK_ROUND_RESULT(type) \
1245
  CHECK(GET_FPU_ERR(t.type##_err1_out) & kFCSRInexactFlagMask); \
1246
  CHECK_EQ(0, GET_FPU_ERR(t.type##_err2_out)); \
1247
  CHECK(GET_FPU_ERR(t.type##_err3_out) & kFCSRInvalidOpFlagMask); \
1248
  CHECK(GET_FPU_ERR(t.type##_err4_out) & kFCSRInvalidOpFlagMask); \
1249
  CHECK_EQ(kFPUInvalidResult, t.type##_invalid_result);
1250

    
1251
  CHECK_ROUND_RESULT(round);
1252
  CHECK_ROUND_RESULT(floor);
1253
  CHECK_ROUND_RESULT(ceil);
1254
  CHECK_ROUND_RESULT(cvt);
1255
}
1256

    
1257

    
1258
TEST(MIPS15) {
1259
  // Test chaining of label usages within instructions (issue 1644).
1260
  CcTest::InitializeVM();
1261
  Isolate* isolate = CcTest::i_isolate();
1262
  HandleScope scope(isolate);
1263
  Assembler assm(isolate, NULL, 0);
1264

    
1265
  Label target;
1266
  __ beq(v0, v1, &target);
1267
  __ nop();
1268
  __ bne(v0, v1, &target);
1269
  __ nop();
1270
  __ bind(&target);
1271
  __ nop();
1272
}
1273

    
1274
#undef __