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