41453337f2a630ba8a96dca324348e5a8adc0b5d
[platform/upstream/nodejs.git] / deps / v8 / test / unittests / compiler / mips64 / instruction-selector-mips64-unittest.cc
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file
4
5 #include "test/unittests/compiler/instruction-selector-unittest.h"
6
7 namespace v8 {
8 namespace internal {
9 namespace compiler {
10
11 namespace {
12 template <typename T>
13 struct MachInst {
14   T constructor;
15   const char* constructor_name;
16   ArchOpcode arch_opcode;
17   MachineType machine_type;
18 };
19
20 template <typename T>
21 std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) {
22   return os << mi.constructor_name;
23 }
24
25 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1;
26 typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2;
27
28
29 // To avoid duplicated code IntCmp helper structure
30 // is created. It contains MachInst2 with two nodes and expected_size
31 // because different cmp instructions have different size.
32 struct IntCmp {
33   MachInst2 mi;
34   uint32_t expected_size;
35 };
36
37 struct FPCmp {
38   MachInst2 mi;
39   FlagsCondition cond;
40 };
41
42 const FPCmp kFPCmpInstructions[] = {
43     {{&RawMachineAssembler::Float64Equal, "Float64Equal", kMips64CmpD,
44       kMachFloat64},
45      kEqual},
46     {{&RawMachineAssembler::Float64LessThan, "Float64LessThan", kMips64CmpD,
47       kMachFloat64},
48      kUnsignedLessThan},
49     {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
50       kMips64CmpD, kMachFloat64},
51      kUnsignedLessThanOrEqual},
52     {{&RawMachineAssembler::Float64GreaterThan, "Float64GreaterThan",
53       kMips64CmpD, kMachFloat64},
54      kUnsignedLessThan},
55     {{&RawMachineAssembler::Float64GreaterThanOrEqual,
56       "Float64GreaterThanOrEqual", kMips64CmpD, kMachFloat64},
57      kUnsignedLessThanOrEqual}};
58
59 struct Conversion {
60   // The machine_type field in MachInst1 represents the destination type.
61   MachInst1 mi;
62   MachineType src_machine_type;
63 };
64
65
66 // ----------------------------------------------------------------------------
67 // Logical instructions.
68 // ----------------------------------------------------------------------------
69
70
71 const MachInst2 kLogicalInstructions[] = {
72     {&RawMachineAssembler::Word32And, "Word32And", kMips64And, kMachInt32},
73     {&RawMachineAssembler::Word64And, "Word64And", kMips64And, kMachInt64},
74     {&RawMachineAssembler::Word32Or, "Word32Or", kMips64Or, kMachInt32},
75     {&RawMachineAssembler::Word64Or, "Word64Or", kMips64Or, kMachInt64},
76     {&RawMachineAssembler::Word32Xor, "Word32Xor", kMips64Xor, kMachInt32},
77     {&RawMachineAssembler::Word64Xor, "Word64Xor", kMips64Xor, kMachInt64}};
78
79
80 // ----------------------------------------------------------------------------
81 // Shift instructions.
82 // ----------------------------------------------------------------------------
83
84
85 const MachInst2 kShiftInstructions[] = {
86     {&RawMachineAssembler::Word32Shl, "Word32Shl", kMips64Shl, kMachInt32},
87     {&RawMachineAssembler::Word64Shl, "Word64Shl", kMips64Dshl, kMachInt64},
88     {&RawMachineAssembler::Word32Shr, "Word32Shr", kMips64Shr, kMachInt32},
89     {&RawMachineAssembler::Word64Shr, "Word64Shr", kMips64Dshr, kMachInt64},
90     {&RawMachineAssembler::Word32Sar, "Word32Sar", kMips64Sar, kMachInt32},
91     {&RawMachineAssembler::Word64Sar, "Word64Sar", kMips64Dsar, kMachInt64},
92     {&RawMachineAssembler::Word32Ror, "Word32Ror", kMips64Ror, kMachInt32},
93     {&RawMachineAssembler::Word64Ror, "Word64Ror", kMips64Dror, kMachInt64}};
94
95
96 // ----------------------------------------------------------------------------
97 // MUL/DIV instructions.
98 // ----------------------------------------------------------------------------
99
100
101 const MachInst2 kMulDivInstructions[] = {
102     {&RawMachineAssembler::Int32Mul, "Int32Mul", kMips64Mul, kMachInt32},
103     {&RawMachineAssembler::Int32Div, "Int32Div", kMips64Div, kMachInt32},
104     {&RawMachineAssembler::Uint32Div, "Uint32Div", kMips64DivU, kMachUint32},
105     {&RawMachineAssembler::Int64Mul, "Int64Mul", kMips64Dmul, kMachInt64},
106     {&RawMachineAssembler::Int64Div, "Int64Div", kMips64Ddiv, kMachInt64},
107     {&RawMachineAssembler::Uint64Div, "Uint64Div", kMips64DdivU, kMachUint64},
108     {&RawMachineAssembler::Float64Mul, "Float64Mul", kMips64MulD, kMachFloat64},
109     {&RawMachineAssembler::Float64Div, "Float64Div", kMips64DivD,
110      kMachFloat64}};
111
112
113 // ----------------------------------------------------------------------------
114 // MOD instructions.
115 // ----------------------------------------------------------------------------
116
117
118 const MachInst2 kModInstructions[] = {
119     {&RawMachineAssembler::Int32Mod, "Int32Mod", kMips64Mod, kMachInt32},
120     {&RawMachineAssembler::Uint32Mod, "Uint32Mod", kMips64ModU, kMachInt32},
121     {&RawMachineAssembler::Float64Mod, "Float64Mod", kMips64ModD,
122      kMachFloat64}};
123
124
125 // ----------------------------------------------------------------------------
126 // Arithmetic FPU instructions.
127 // ----------------------------------------------------------------------------
128
129
130 const MachInst2 kFPArithInstructions[] = {
131     {&RawMachineAssembler::Float64Add, "Float64Add", kMips64AddD, kMachFloat64},
132     {&RawMachineAssembler::Float64Sub, "Float64Sub", kMips64SubD,
133      kMachFloat64}};
134
135
136 // ----------------------------------------------------------------------------
137 // IntArithTest instructions, two nodes.
138 // ----------------------------------------------------------------------------
139
140
141 const MachInst2 kAddSubInstructions[] = {
142     {&RawMachineAssembler::Int32Add, "Int32Add", kMips64Add, kMachInt32},
143     {&RawMachineAssembler::Int64Add, "Int64Add", kMips64Dadd, kMachInt64},
144     {&RawMachineAssembler::Int32Sub, "Int32Sub", kMips64Sub, kMachInt32},
145     {&RawMachineAssembler::Int64Sub, "Int64Sub", kMips64Dsub, kMachInt64}};
146
147
148 // ----------------------------------------------------------------------------
149 // IntArithTest instructions, one node.
150 // ----------------------------------------------------------------------------
151
152
153 const MachInst1 kAddSubOneInstructions[] = {
154     {&RawMachineAssembler::Int32Neg, "Int32Neg", kMips64Sub, kMachInt32},
155     {&RawMachineAssembler::Int64Neg, "Int64Neg", kMips64Dsub, kMachInt64}};
156
157
158 // ----------------------------------------------------------------------------
159 // Arithmetic compare instructions.
160 // ----------------------------------------------------------------------------
161
162
163 const IntCmp kCmpInstructions[] = {
164     {{&RawMachineAssembler::WordEqual, "WordEqual", kMips64Cmp, kMachInt64},
165      1U},
166     {{&RawMachineAssembler::WordNotEqual, "WordNotEqual", kMips64Cmp,
167       kMachInt64},
168      1U},
169     {{&RawMachineAssembler::Word32Equal, "Word32Equal", kMips64Cmp32,
170       kMachInt32},
171      1U},
172     {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kMips64Cmp32,
173       kMachInt32},
174      1U},
175     {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMips64Cmp32,
176       kMachInt32},
177      1U},
178     {{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
179       kMips64Cmp32, kMachInt32},
180      1U},
181     {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kMips64Cmp32,
182       kMachInt32},
183      1U},
184     {{&RawMachineAssembler::Int32GreaterThanOrEqual, "Int32GreaterThanOrEqual",
185       kMips64Cmp32, kMachInt32},
186      1U},
187     {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMips64Cmp32,
188       kMachUint32},
189      1U},
190     {{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
191       kMips64Cmp32, kMachUint32},
192      1U}};
193
194
195 // ----------------------------------------------------------------------------
196 // Conversion instructions.
197 // ----------------------------------------------------------------------------
198
199 const Conversion kConversionInstructions[] = {
200     // Conversion instructions are related to machine_operator.h:
201     // FPU conversions:
202     // Convert representation of integers between float64 and int32/uint32.
203     // The precise rounding mode and handling of out of range inputs are *not*
204     // defined for these operators, since they are intended only for use with
205     // integers.
206     // mips instructions:
207     // mtc1, cvt.d.w
208     {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64",
209       kMips64CvtDW, kMachFloat64},
210      kMachInt32},
211
212     // mips instructions:
213     // cvt.d.uw
214     {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64",
215       kMips64CvtDUw, kMachFloat64},
216      kMachInt32},
217
218     // mips instructions:
219     // mfc1, trunc double to word, for more details look at mips macro
220     // asm and mips asm file
221     {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32",
222       kMips64TruncWD, kMachFloat64},
223      kMachInt32},
224
225     // mips instructions:
226     // trunc double to unsigned word, for more details look at mips macro
227     // asm and mips asm file
228     {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32",
229       kMips64TruncUwD, kMachFloat64},
230      kMachInt32}};
231
232 }  // namespace
233
234
235 typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest;
236
237 TEST_P(InstructionSelectorFPCmpTest, Parameter) {
238   const FPCmp cmp = GetParam();
239   StreamBuilder m(this, kMachInt32, cmp.mi.machine_type, cmp.mi.machine_type);
240   m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
241   Stream s = m.Build();
242   ASSERT_EQ(1U, s.size());
243   EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
244   EXPECT_EQ(2U, s[0]->InputCount());
245   EXPECT_EQ(1U, s[0]->OutputCount());
246   EXPECT_EQ(kFlags_set, s[0]->flags_mode());
247   EXPECT_EQ(cmp.cond, s[0]->flags_condition());
248 }
249
250 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
251                         ::testing::ValuesIn(kFPCmpInstructions));
252
253 // ----------------------------------------------------------------------------
254 // Arithmetic compare instructions integers
255 // ----------------------------------------------------------------------------
256 typedef InstructionSelectorTestWithParam<IntCmp> InstructionSelectorCmpTest;
257
258
259 TEST_P(InstructionSelectorCmpTest, Parameter) {
260   const IntCmp cmp = GetParam();
261   const MachineType type = cmp.mi.machine_type;
262   StreamBuilder m(this, type, type, type);
263   m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1)));
264   Stream s = m.Build();
265   ASSERT_EQ(cmp.expected_size, s.size());
266   EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
267   EXPECT_EQ(2U, s[0]->InputCount());
268   EXPECT_EQ(1U, s[0]->OutputCount());
269 }
270
271 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorCmpTest,
272                         ::testing::ValuesIn(kCmpInstructions));
273
274 // ----------------------------------------------------------------------------
275 // Shift instructions.
276 // ----------------------------------------------------------------------------
277 typedef InstructionSelectorTestWithParam<MachInst2>
278     InstructionSelectorShiftTest;
279
280 TEST_P(InstructionSelectorShiftTest, Immediate) {
281   const MachInst2 dpi = GetParam();
282   const MachineType type = dpi.machine_type;
283   TRACED_FORRANGE(int32_t, imm, 0, (ElementSizeOf(type) * 8) - 1) {
284     StreamBuilder m(this, type, type);
285     m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)));
286     Stream s = m.Build();
287     ASSERT_EQ(1U, s.size());
288     EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
289     EXPECT_EQ(2U, s[0]->InputCount());
290     EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
291     EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
292     EXPECT_EQ(1U, s[0]->OutputCount());
293   }
294 }
295
296 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest,
297                         ::testing::ValuesIn(kShiftInstructions));
298
299 // ----------------------------------------------------------------------------
300 // Logical instructions.
301 // ----------------------------------------------------------------------------
302 typedef InstructionSelectorTestWithParam<MachInst2>
303     InstructionSelectorLogicalTest;
304
305
306 TEST_P(InstructionSelectorLogicalTest, Parameter) {
307   const MachInst2 dpi = GetParam();
308   const MachineType type = dpi.machine_type;
309   StreamBuilder m(this, type, type, type);
310   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
311   Stream s = m.Build();
312   ASSERT_EQ(1U, s.size());
313   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
314   EXPECT_EQ(2U, s[0]->InputCount());
315   EXPECT_EQ(1U, s[0]->OutputCount());
316 }
317
318 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest,
319                         ::testing::ValuesIn(kLogicalInstructions));
320
321 // ----------------------------------------------------------------------------
322 // MUL/DIV instructions.
323 // ----------------------------------------------------------------------------
324 typedef InstructionSelectorTestWithParam<MachInst2>
325     InstructionSelectorMulDivTest;
326
327 TEST_P(InstructionSelectorMulDivTest, Parameter) {
328   const MachInst2 dpi = GetParam();
329   const MachineType type = dpi.machine_type;
330   StreamBuilder m(this, type, type, type);
331   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
332   Stream s = m.Build();
333   ASSERT_EQ(1U, s.size());
334   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
335   EXPECT_EQ(2U, s[0]->InputCount());
336   EXPECT_EQ(1U, s[0]->OutputCount());
337 }
338
339 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest,
340                         ::testing::ValuesIn(kMulDivInstructions));
341
342 // ----------------------------------------------------------------------------
343 // MOD instructions.
344 // ----------------------------------------------------------------------------
345 typedef InstructionSelectorTestWithParam<MachInst2> InstructionSelectorModTest;
346
347 TEST_P(InstructionSelectorModTest, Parameter) {
348   const MachInst2 dpi = GetParam();
349   const MachineType type = dpi.machine_type;
350   StreamBuilder m(this, type, type, type);
351   m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)));
352   Stream s = m.Build();
353   ASSERT_EQ(1U, s.size());
354   EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
355   EXPECT_EQ(2U, s[0]->InputCount());
356   EXPECT_EQ(1U, s[0]->OutputCount());
357 }
358
359 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorModTest,
360                         ::testing::ValuesIn(kModInstructions));
361
362 // ----------------------------------------------------------------------------
363 // Floating point instructions.
364 // ----------------------------------------------------------------------------
365 typedef InstructionSelectorTestWithParam<MachInst2>
366     InstructionSelectorFPArithTest;
367
368 TEST_P(InstructionSelectorFPArithTest, Parameter) {
369   const MachInst2 fpa = GetParam();
370   StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type);
371   m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1)));
372   Stream s = m.Build();
373   ASSERT_EQ(1U, s.size());
374   EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode());
375   EXPECT_EQ(2U, s[0]->InputCount());
376   EXPECT_EQ(1U, s[0]->OutputCount());
377 }
378
379 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest,
380                         ::testing::ValuesIn(kFPArithInstructions));
381 // ----------------------------------------------------------------------------
382 // Integer arithmetic
383 // ----------------------------------------------------------------------------
384 typedef InstructionSelectorTestWithParam<MachInst2>
385     InstructionSelectorIntArithTwoTest;
386
387 TEST_P(InstructionSelectorIntArithTwoTest, Parameter) {
388   const MachInst2 intpa = GetParam();
389   StreamBuilder m(this, intpa.machine_type, intpa.machine_type,
390                   intpa.machine_type);
391   m.Return((m.*intpa.constructor)(m.Parameter(0), m.Parameter(1)));
392   Stream s = m.Build();
393   ASSERT_EQ(1U, s.size());
394   EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode());
395   EXPECT_EQ(2U, s[0]->InputCount());
396   EXPECT_EQ(1U, s[0]->OutputCount());
397 }
398
399 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
400                         InstructionSelectorIntArithTwoTest,
401                         ::testing::ValuesIn(kAddSubInstructions));
402
403
404 // ----------------------------------------------------------------------------
405 // One node.
406 // ----------------------------------------------------------------------------
407
408
409 typedef InstructionSelectorTestWithParam<MachInst1>
410     InstructionSelectorIntArithOneTest;
411
412 TEST_P(InstructionSelectorIntArithOneTest, Parameter) {
413   const MachInst1 intpa = GetParam();
414   StreamBuilder m(this, intpa.machine_type, intpa.machine_type,
415                   intpa.machine_type);
416   m.Return((m.*intpa.constructor)(m.Parameter(0)));
417   Stream s = m.Build();
418   ASSERT_EQ(1U, s.size());
419   EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode());
420   EXPECT_EQ(2U, s[0]->InputCount());
421   EXPECT_EQ(1U, s[0]->OutputCount());
422 }
423
424 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
425                         InstructionSelectorIntArithOneTest,
426                         ::testing::ValuesIn(kAddSubOneInstructions));
427 // ----------------------------------------------------------------------------
428 // Conversions.
429 // ----------------------------------------------------------------------------
430 typedef InstructionSelectorTestWithParam<Conversion>
431     InstructionSelectorConversionTest;
432
433 TEST_P(InstructionSelectorConversionTest, Parameter) {
434   const Conversion conv = GetParam();
435   StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type);
436   m.Return((m.*conv.mi.constructor)(m.Parameter(0)));
437   Stream s = m.Build();
438   ASSERT_EQ(1U, s.size());
439   EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode());
440   EXPECT_EQ(1U, s[0]->InputCount());
441   EXPECT_EQ(1U, s[0]->OutputCount());
442 }
443
444 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
445                         InstructionSelectorConversionTest,
446                         ::testing::ValuesIn(kConversionInstructions));
447
448
449 // ----------------------------------------------------------------------------
450 // Loads and stores.
451 // ----------------------------------------------------------------------------
452
453
454 namespace {
455
456 struct MemoryAccess {
457   MachineType type;
458   ArchOpcode load_opcode;
459   ArchOpcode store_opcode;
460 };
461
462 static const MemoryAccess kMemoryAccesses[] = {
463     {kMachInt8, kMips64Lb, kMips64Sb},
464     {kMachUint8, kMips64Lbu, kMips64Sb},
465     {kMachInt16, kMips64Lh, kMips64Sh},
466     {kMachUint16, kMips64Lhu, kMips64Sh},
467     {kMachInt32, kMips64Lw, kMips64Sw},
468     {kRepFloat32, kMips64Lwc1, kMips64Swc1},
469     {kRepFloat64, kMips64Ldc1, kMips64Sdc1},
470     {kMachInt64, kMips64Ld, kMips64Sd}};
471
472
473 struct MemoryAccessImm {
474   MachineType type;
475   ArchOpcode load_opcode;
476   ArchOpcode store_opcode;
477   bool (InstructionSelectorTest::Stream::*val_predicate)(
478       const InstructionOperand*) const;
479   const int32_t immediates[40];
480 };
481
482
483 std::ostream& operator<<(std::ostream& os, const MemoryAccessImm& acc) {
484   return os << acc.type;
485 }
486
487
488 struct MemoryAccessImm1 {
489   MachineType type;
490   ArchOpcode load_opcode;
491   ArchOpcode store_opcode;
492   bool (InstructionSelectorTest::Stream::*val_predicate)(
493       const InstructionOperand*) const;
494   const int32_t immediates[5];
495 };
496
497
498 std::ostream& operator<<(std::ostream& os, const MemoryAccessImm1& acc) {
499   return os << acc.type;
500 }
501
502
503 // ----------------------------------------------------------------------------
504 // Loads and stores immediate values
505 // ----------------------------------------------------------------------------
506
507
508 const MemoryAccessImm kMemoryAccessesImm[] = {
509     {kMachInt8,
510      kMips64Lb,
511      kMips64Sb,
512      &InstructionSelectorTest::Stream::IsInteger,
513      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
514       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
515       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
516     {kMachUint8,
517      kMips64Lbu,
518      kMips64Sb,
519      &InstructionSelectorTest::Stream::IsInteger,
520      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
521       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
522       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
523     {kMachInt16,
524      kMips64Lh,
525      kMips64Sh,
526      &InstructionSelectorTest::Stream::IsInteger,
527      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
528       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
529       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
530     {kMachUint16,
531      kMips64Lhu,
532      kMips64Sh,
533      &InstructionSelectorTest::Stream::IsInteger,
534      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
535       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
536       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
537     {kMachInt32,
538      kMips64Lw,
539      kMips64Sw,
540      &InstructionSelectorTest::Stream::IsInteger,
541      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
542       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
543       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
544     {kMachFloat32,
545      kMips64Lwc1,
546      kMips64Swc1,
547      &InstructionSelectorTest::Stream::IsDouble,
548      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
549       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
550       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
551     {kMachFloat64,
552      kMips64Ldc1,
553      kMips64Sdc1,
554      &InstructionSelectorTest::Stream::IsDouble,
555      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
556       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
557       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
558     {kMachInt64,
559      kMips64Ld,
560      kMips64Sd,
561      &InstructionSelectorTest::Stream::IsInteger,
562      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
563       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
564       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}};
565
566
567 const MemoryAccessImm1 kMemoryAccessImmMoreThan16bit[] = {
568     {kMachInt8,
569      kMips64Lb,
570      kMips64Sb,
571      &InstructionSelectorTest::Stream::IsInteger,
572      {-65000, -55000, 32777, 55000, 65000}},
573     {kMachInt8,
574      kMips64Lbu,
575      kMips64Sb,
576      &InstructionSelectorTest::Stream::IsInteger,
577      {-65000, -55000, 32777, 55000, 65000}},
578     {kMachInt16,
579      kMips64Lh,
580      kMips64Sh,
581      &InstructionSelectorTest::Stream::IsInteger,
582      {-65000, -55000, 32777, 55000, 65000}},
583     {kMachInt16,
584      kMips64Lhu,
585      kMips64Sh,
586      &InstructionSelectorTest::Stream::IsInteger,
587      {-65000, -55000, 32777, 55000, 65000}},
588     {kMachInt32,
589      kMips64Lw,
590      kMips64Sw,
591      &InstructionSelectorTest::Stream::IsInteger,
592      {-65000, -55000, 32777, 55000, 65000}},
593     {kMachFloat32,
594      kMips64Lwc1,
595      kMips64Swc1,
596      &InstructionSelectorTest::Stream::IsDouble,
597      {-65000, -55000, 32777, 55000, 65000}},
598     {kMachFloat64,
599      kMips64Ldc1,
600      kMips64Sdc1,
601      &InstructionSelectorTest::Stream::IsDouble,
602      {-65000, -55000, 32777, 55000, 65000}},
603     {kMachInt64,
604      kMips64Ld,
605      kMips64Sd,
606      &InstructionSelectorTest::Stream::IsInteger,
607      {-65000, -55000, 32777, 55000, 65000}}};
608
609 }  // namespace
610
611
612 typedef InstructionSelectorTestWithParam<MemoryAccess>
613     InstructionSelectorMemoryAccessTest;
614
615 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
616   const MemoryAccess memacc = GetParam();
617   StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32);
618   m.Return(m.Load(memacc.type, m.Parameter(0)));
619   Stream s = m.Build();
620   ASSERT_EQ(1U, s.size());
621   EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
622   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
623 }
624
625
626 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
627   const MemoryAccess memacc = GetParam();
628   StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type);
629   m.Store(memacc.type, m.Parameter(0), m.Parameter(1));
630   m.Return(m.Int32Constant(0));
631   Stream s = m.Build();
632   ASSERT_EQ(1U, s.size());
633   EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
634   EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
635 }
636
637 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
638                         InstructionSelectorMemoryAccessTest,
639                         ::testing::ValuesIn(kMemoryAccesses));
640
641
642 // ----------------------------------------------------------------------------
643 // Load immediate.
644 // ----------------------------------------------------------------------------
645
646
647 typedef InstructionSelectorTestWithParam<MemoryAccessImm>
648     InstructionSelectorMemoryAccessImmTest;
649
650 TEST_P(InstructionSelectorMemoryAccessImmTest, LoadWithImmediateIndex) {
651   const MemoryAccessImm memacc = GetParam();
652   TRACED_FOREACH(int32_t, index, memacc.immediates) {
653     StreamBuilder m(this, memacc.type, kMachPtr);
654     m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
655     Stream s = m.Build();
656     ASSERT_EQ(1U, s.size());
657     EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
658     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
659     ASSERT_EQ(2U, s[0]->InputCount());
660     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
661     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
662     ASSERT_EQ(1U, s[0]->OutputCount());
663     EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
664   }
665 }
666
667
668 // ----------------------------------------------------------------------------
669 // Store immediate.
670 // ----------------------------------------------------------------------------
671
672
673 TEST_P(InstructionSelectorMemoryAccessImmTest, StoreWithImmediateIndex) {
674   const MemoryAccessImm memacc = GetParam();
675   TRACED_FOREACH(int32_t, index, memacc.immediates) {
676     StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
677     m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
678             m.Parameter(1));
679     m.Return(m.Int32Constant(0));
680     Stream s = m.Build();
681     ASSERT_EQ(1U, s.size());
682     EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
683     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
684     ASSERT_EQ(3U, s[0]->InputCount());
685     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
686     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
687     EXPECT_EQ(0U, s[0]->OutputCount());
688   }
689 }
690
691 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
692                         InstructionSelectorMemoryAccessImmTest,
693                         ::testing::ValuesIn(kMemoryAccessesImm));
694
695
696 // ----------------------------------------------------------------------------
697 // Load/store offsets more than 16 bits.
698 // ----------------------------------------------------------------------------
699
700
701 typedef InstructionSelectorTestWithParam<MemoryAccessImm1>
702     InstructionSelectorMemoryAccessImmMoreThan16bitTest;
703
704 TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,
705        LoadWithImmediateIndex) {
706   const MemoryAccessImm1 memacc = GetParam();
707   TRACED_FOREACH(int32_t, index, memacc.immediates) {
708     StreamBuilder m(this, memacc.type, kMachPtr);
709     m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index)));
710     Stream s = m.Build();
711     ASSERT_EQ(2U, s.size());
712     // kMips64Dadd is expected opcode
713     // size more than 16 bits wide
714     EXPECT_EQ(kMips64Dadd, s[0]->arch_opcode());
715     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
716     EXPECT_EQ(2U, s[0]->InputCount());
717     EXPECT_EQ(1U, s[0]->OutputCount());
718   }
719 }
720
721 TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest,
722        StoreWithImmediateIndex) {
723   const MemoryAccessImm1 memacc = GetParam();
724   TRACED_FOREACH(int32_t, index, memacc.immediates) {
725     StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type);
726     m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index),
727             m.Parameter(1));
728     m.Return(m.Int32Constant(0));
729     Stream s = m.Build();
730     ASSERT_EQ(2U, s.size());
731     // kMips64Add is expected opcode
732     // size more than 16 bits wide
733     EXPECT_EQ(kMips64Dadd, s[0]->arch_opcode());
734     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
735     EXPECT_EQ(2U, s[0]->InputCount());
736     EXPECT_EQ(1U, s[0]->OutputCount());
737   }
738 }
739
740 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
741                         InstructionSelectorMemoryAccessImmMoreThan16bitTest,
742                         ::testing::ValuesIn(kMemoryAccessImmMoreThan16bit));
743
744
745 // ----------------------------------------------------------------------------
746 // kMips64Cmp with zero testing.
747 // ----------------------------------------------------------------------------
748
749
750 TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
751   {
752     StreamBuilder m(this, kMachInt32, kMachInt32);
753     m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
754     Stream s = m.Build();
755     ASSERT_EQ(1U, s.size());
756     EXPECT_EQ(kMips64Cmp32, s[0]->arch_opcode());
757     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
758     ASSERT_EQ(2U, s[0]->InputCount());
759     EXPECT_EQ(1U, s[0]->OutputCount());
760     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
761     EXPECT_EQ(kEqual, s[0]->flags_condition());
762   }
763   {
764     StreamBuilder m(this, kMachInt32, kMachInt32);
765     m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
766     Stream s = m.Build();
767     ASSERT_EQ(1U, s.size());
768     EXPECT_EQ(kMips64Cmp32, s[0]->arch_opcode());
769     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
770     ASSERT_EQ(2U, s[0]->InputCount());
771     EXPECT_EQ(1U, s[0]->OutputCount());
772     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
773     EXPECT_EQ(kEqual, s[0]->flags_condition());
774   }
775 }
776
777
778 TEST_F(InstructionSelectorTest, Word64EqualWithZero) {
779   {
780     StreamBuilder m(this, kMachInt64, kMachInt64);
781     m.Return(m.Word64Equal(m.Parameter(0), m.Int64Constant(0)));
782     Stream s = m.Build();
783     ASSERT_EQ(1U, s.size());
784     EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
785     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
786     ASSERT_EQ(2U, s[0]->InputCount());
787     EXPECT_EQ(1U, s[0]->OutputCount());
788     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
789     EXPECT_EQ(kEqual, s[0]->flags_condition());
790   }
791   {
792     StreamBuilder m(this, kMachInt64, kMachInt64);
793     m.Return(m.Word64Equal(m.Int32Constant(0), m.Parameter(0)));
794     Stream s = m.Build();
795     ASSERT_EQ(1U, s.size());
796     EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
797     EXPECT_EQ(kMode_None, s[0]->addressing_mode());
798     ASSERT_EQ(2U, s[0]->InputCount());
799     EXPECT_EQ(1U, s[0]->OutputCount());
800     EXPECT_EQ(kFlags_set, s[0]->flags_mode());
801     EXPECT_EQ(kEqual, s[0]->flags_condition());
802   }
803 }
804
805 }  // namespace compiler
806 }  // namespace internal
807 }  // namespace v8