blob: b8a04267e79dc0ec328063cfd1824875f1d6caf6 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Andrei Popescu402d9372010-02-26 13:31:12 +00002// 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028#include <iostream> // NOLINT(readability/streams)
29
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030#include "src/v8.h"
Andrei Popescu402d9372010-02-26 13:31:12 +000031
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032#include "src/base/utils/random-number-generator.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033#include "src/disassembler.h"
34#include "src/factory.h"
35#include "src/macro-assembler.h"
36#include "src/mips/macro-assembler-mips.h"
37#include "src/mips/simulator-mips.h"
Andrei Popescu402d9372010-02-26 13:31:12 +000038
Ben Murdochb8a8cc12014-11-26 15:28:44 +000039#include "test/cctest/cctest.h"
Andrei Popescu402d9372010-02-26 13:31:12 +000040
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000041
Andrei Popescu402d9372010-02-26 13:31:12 +000042using namespace v8::internal;
43
44
45// Define these function prototypes to match JSEntryFunction in execution.cc.
46typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
47typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
48typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4);
49
50
Andrei Popescu402d9372010-02-26 13:31:12 +000051#define __ assm.
52
53TEST(MIPS0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000054 CcTest::InitializeVM();
55 Isolate* isolate = CcTest::i_isolate();
56 HandleScope scope(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000057
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Andrei Popescu402d9372010-02-26 13:31:12 +000059
60 // Addition.
61 __ addu(v0, a0, a1);
62 __ jr(ra);
63 __ nop();
64
65 CodeDesc desc;
66 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000067 Handle<Code> code = isolate->factory()->NewCode(
68 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
69 F2 f = FUNCTION_CAST<F2>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070 int res = reinterpret_cast<int>(
71 CALL_GENERATED_CODE(isolate, f, 0xab0, 0xc, 0, 0, 0));
72 CHECK_EQ(static_cast<int32_t>(0xabc), res);
Andrei Popescu402d9372010-02-26 13:31:12 +000073}
74
75
76TEST(MIPS1) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000077 CcTest::InitializeVM();
78 Isolate* isolate = CcTest::i_isolate();
79 HandleScope scope(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000080
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Andrei Popescu402d9372010-02-26 13:31:12 +000082 Label L, C;
83
84 __ mov(a1, a0);
85 __ li(v0, 0);
86 __ b(&C);
87 __ nop();
88
89 __ bind(&L);
Steve Block44f0eee2011-05-26 01:26:41 +010090 __ addu(v0, v0, a1);
Andrei Popescu402d9372010-02-26 13:31:12 +000091 __ addiu(a1, a1, -1);
92
93 __ bind(&C);
94 __ xori(v1, a1, 0);
Steve Block44f0eee2011-05-26 01:26:41 +010095 __ Branch(&L, ne, v1, Operand(0));
Andrei Popescu402d9372010-02-26 13:31:12 +000096 __ nop();
97
98 __ jr(ra);
99 __ nop();
100
101 CodeDesc desc;
102 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000103 Handle<Code> code = isolate->factory()->NewCode(
104 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
105 F1 f = FUNCTION_CAST<F1>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000106 int res = reinterpret_cast<int>(
107 CALL_GENERATED_CODE(isolate, f, 50, 0, 0, 0, 0));
Andrei Popescu402d9372010-02-26 13:31:12 +0000108 CHECK_EQ(1275, res);
109}
110
111
112TEST(MIPS2) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000113 CcTest::InitializeVM();
114 Isolate* isolate = CcTest::i_isolate();
115 HandleScope scope(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +0000116
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Andrei Popescu402d9372010-02-26 13:31:12 +0000118
119 Label exit, error;
120
121 // ----- Test all instructions.
122
123 // Test lui, ori, and addiu, used in the li pseudo-instruction.
124 // This way we can then safely load registers with chosen values.
125
126 __ ori(t0, zero_reg, 0);
127 __ lui(t0, 0x1234);
128 __ ori(t0, t0, 0);
129 __ ori(t0, t0, 0x0f0f);
130 __ ori(t0, t0, 0xf0f0);
131 __ addiu(t1, t0, 1);
132 __ addiu(t2, t1, -0x10);
133
134 // Load values in temporary registers.
135 __ li(t0, 0x00000004);
136 __ li(t1, 0x00001234);
137 __ li(t2, 0x12345678);
138 __ li(t3, 0x7fffffff);
139 __ li(t4, 0xfffffffc);
140 __ li(t5, 0xffffedcc);
141 __ li(t6, 0xedcba988);
142 __ li(t7, 0x80000000);
143
144 // SPECIAL class.
145 __ srl(v0, t2, 8); // 0x00123456
146 __ sll(v0, v0, 11); // 0x91a2b000
147 __ sra(v0, v0, 3); // 0xf2345600
148 __ srav(v0, v0, t0); // 0xff234560
149 __ sllv(v0, v0, t0); // 0xf2345600
150 __ srlv(v0, v0, t0); // 0x0f234560
Steve Block44f0eee2011-05-26 01:26:41 +0100151 __ Branch(&error, ne, v0, Operand(0x0f234560));
Andrei Popescu402d9372010-02-26 13:31:12 +0000152 __ nop();
153
Steve Block44f0eee2011-05-26 01:26:41 +0100154 __ addu(v0, t0, t1); // 0x00001238
155 __ subu(v0, v0, t0); // 0x00001234
156 __ Branch(&error, ne, v0, Operand(0x00001234));
Andrei Popescu402d9372010-02-26 13:31:12 +0000157 __ nop();
158 __ addu(v1, t3, t0);
Steve Block44f0eee2011-05-26 01:26:41 +0100159 __ Branch(&error, ne, v1, Operand(0x80000003));
Andrei Popescu402d9372010-02-26 13:31:12 +0000160 __ nop();
161 __ subu(v1, t7, t0); // 0x7ffffffc
Steve Block44f0eee2011-05-26 01:26:41 +0100162 __ Branch(&error, ne, v1, Operand(0x7ffffffc));
Andrei Popescu402d9372010-02-26 13:31:12 +0000163 __ nop();
164
165 __ and_(v0, t1, t2); // 0x00001230
166 __ or_(v0, v0, t1); // 0x00001234
167 __ xor_(v0, v0, t2); // 0x1234444c
168 __ nor(v0, v0, t2); // 0xedcba987
Steve Block44f0eee2011-05-26 01:26:41 +0100169 __ Branch(&error, ne, v0, Operand(0xedcba983));
Andrei Popescu402d9372010-02-26 13:31:12 +0000170 __ nop();
171
172 __ slt(v0, t7, t3);
Steve Block44f0eee2011-05-26 01:26:41 +0100173 __ Branch(&error, ne, v0, Operand(0x1));
Andrei Popescu402d9372010-02-26 13:31:12 +0000174 __ nop();
175 __ sltu(v0, t7, t3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000176 __ Branch(&error, ne, v0, Operand(zero_reg));
Andrei Popescu402d9372010-02-26 13:31:12 +0000177 __ nop();
178 // End of SPECIAL class.
179
Steve Block44f0eee2011-05-26 01:26:41 +0100180 __ addiu(v0, zero_reg, 0x7421); // 0x00007421
181 __ addiu(v0, v0, -0x1); // 0x00007420
Andrei Popescu402d9372010-02-26 13:31:12 +0000182 __ addiu(v0, v0, -0x20); // 0x00007400
Steve Block44f0eee2011-05-26 01:26:41 +0100183 __ Branch(&error, ne, v0, Operand(0x00007400));
Andrei Popescu402d9372010-02-26 13:31:12 +0000184 __ nop();
185 __ addiu(v1, t3, 0x1); // 0x80000000
Steve Block44f0eee2011-05-26 01:26:41 +0100186 __ Branch(&error, ne, v1, Operand(0x80000000));
Andrei Popescu402d9372010-02-26 13:31:12 +0000187 __ nop();
188
189 __ slti(v0, t1, 0x00002000); // 0x1
190 __ slti(v0, v0, 0xffff8000); // 0x0
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000191 __ Branch(&error, ne, v0, Operand(zero_reg));
Andrei Popescu402d9372010-02-26 13:31:12 +0000192 __ nop();
193 __ sltiu(v0, t1, 0x00002000); // 0x1
194 __ sltiu(v0, v0, 0x00008000); // 0x1
Steve Block44f0eee2011-05-26 01:26:41 +0100195 __ Branch(&error, ne, v0, Operand(0x1));
Andrei Popescu402d9372010-02-26 13:31:12 +0000196 __ nop();
197
198 __ andi(v0, t1, 0xf0f0); // 0x00001030
199 __ ori(v0, v0, 0x8a00); // 0x00009a30
200 __ xori(v0, v0, 0x83cc); // 0x000019fc
Steve Block44f0eee2011-05-26 01:26:41 +0100201 __ Branch(&error, ne, v0, Operand(0x000019fc));
Andrei Popescu402d9372010-02-26 13:31:12 +0000202 __ nop();
203 __ lui(v1, 0x8123); // 0x81230000
Steve Block44f0eee2011-05-26 01:26:41 +0100204 __ Branch(&error, ne, v1, Operand(0x81230000));
Andrei Popescu402d9372010-02-26 13:31:12 +0000205 __ nop();
206
Steve Block44f0eee2011-05-26 01:26:41 +0100207 // Bit twiddling instructions & conditional moves.
208 // Uses t0-t7 as set above.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100209 __ Clz(v0, t0); // 29
210 __ Clz(v1, t1); // 19
Steve Block44f0eee2011-05-26 01:26:41 +0100211 __ addu(v0, v0, v1); // 48
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100212 __ Clz(v1, t2); // 3
Steve Block44f0eee2011-05-26 01:26:41 +0100213 __ addu(v0, v0, v1); // 51
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100214 __ Clz(v1, t7); // 0
Steve Block44f0eee2011-05-26 01:26:41 +0100215 __ addu(v0, v0, v1); // 51
216 __ Branch(&error, ne, v0, Operand(51));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100217 __ Movn(a0, t3, t0); // Move a0<-t3 (t0 is NOT 0).
Steve Block44f0eee2011-05-26 01:26:41 +0100218 __ Ins(a0, t1, 12, 8); // 0x7ff34fff
219 __ Branch(&error, ne, a0, Operand(0x7ff34fff));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100220 __ Movz(a0, t6, t7); // a0 not updated (t7 is NOT 0).
Steve Block44f0eee2011-05-26 01:26:41 +0100221 __ Ext(a1, a0, 8, 12); // 0x34f
222 __ Branch(&error, ne, a1, Operand(0x34f));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100223 __ Movz(a0, t6, v1); // a0<-t6, v0 is 0, from 8 instr back.
Steve Block44f0eee2011-05-26 01:26:41 +0100224 __ Branch(&error, ne, a0, Operand(t6));
225
Andrei Popescu402d9372010-02-26 13:31:12 +0000226 // Everything was correctly executed. Load the expected result.
227 __ li(v0, 0x31415926);
228 __ b(&exit);
229 __ nop();
230
231 __ bind(&error);
232 // Got an error. Return a wrong result.
Steve Block44f0eee2011-05-26 01:26:41 +0100233 __ li(v0, 666);
Andrei Popescu402d9372010-02-26 13:31:12 +0000234
235 __ bind(&exit);
236 __ jr(ra);
237 __ nop();
238
239 CodeDesc desc;
240 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241 Handle<Code> code = isolate->factory()->NewCode(
242 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
243 F2 f = FUNCTION_CAST<F2>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000244 int res = reinterpret_cast<int>(
245 CALL_GENERATED_CODE(isolate, f, 0xab0, 0xc, 0, 0, 0));
246 CHECK_EQ(static_cast<int32_t>(0x31415926), res);
Andrei Popescu402d9372010-02-26 13:31:12 +0000247}
248
Steve Block44f0eee2011-05-26 01:26:41 +0100249
250TEST(MIPS3) {
251 // Test floating point instructions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000252 CcTest::InitializeVM();
253 Isolate* isolate = CcTest::i_isolate();
254 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100255
256 typedef struct {
257 double a;
258 double b;
259 double c;
260 double d;
261 double e;
262 double f;
263 double g;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000264 double h;
265 double i;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000266 float fa;
267 float fb;
268 float fc;
269 float fd;
270 float fe;
271 float ff;
272 float fg;
Steve Block44f0eee2011-05-26 01:26:41 +0100273 } T;
274 T t;
275
276 // Create a function that accepts &t, and loads, manipulates, and stores
277 // the doubles t.a ... t.f.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000278 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Steve Block44f0eee2011-05-26 01:26:41 +0100279 Label L, C;
280
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281 // Double precision floating point instructions.
282 __ ldc1(f4, MemOperand(a0, offsetof(T, a)) );
283 __ ldc1(f6, MemOperand(a0, offsetof(T, b)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000284 __ add_d(f8, f4, f6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 __ sdc1(f8, MemOperand(a0, offsetof(T, c)) ); // c = a + b.
Steve Block44f0eee2011-05-26 01:26:41 +0100286
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000287 __ mov_d(f10, f8); // c
288 __ neg_d(f12, f6); // -b
289 __ sub_d(f10, f10, f12);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000290 __ sdc1(f10, MemOperand(a0, offsetof(T, d)) ); // d = c - (-b).
Steve Block44f0eee2011-05-26 01:26:41 +0100291
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000292 __ sdc1(f4, MemOperand(a0, offsetof(T, b)) ); // b = a.
Steve Block44f0eee2011-05-26 01:26:41 +0100293
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000294 __ li(t0, 120);
295 __ mtc1(t0, f14);
296 __ cvt_d_w(f14, f14); // f14 = 120.0.
297 __ mul_d(f10, f10, f14);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000298 __ sdc1(f10, MemOperand(a0, offsetof(T, e)) ); // e = d * 120 = 1.8066e16.
Steve Block44f0eee2011-05-26 01:26:41 +0100299
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000300 __ div_d(f12, f10, f4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 __ sdc1(f12, MemOperand(a0, offsetof(T, f)) ); // f = e / a = 120.44.
Steve Block44f0eee2011-05-26 01:26:41 +0100302
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000303 __ sqrt_d(f14, f12);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000304 __ sdc1(f14, MemOperand(a0, offsetof(T, g)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000305 // g = sqrt(f) = 10.97451593465515908537
Steve Block44f0eee2011-05-26 01:26:41 +0100306
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000307 if (IsMipsArchVariant(kMips32r2)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000308 __ ldc1(f4, MemOperand(a0, offsetof(T, h)) );
309 __ ldc1(f6, MemOperand(a0, offsetof(T, i)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000310 __ madd_d(f14, f6, f4, f6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000311 __ sdc1(f14, MemOperand(a0, offsetof(T, h)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000312 }
Steve Block44f0eee2011-05-26 01:26:41 +0100313
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000314 // Single precision floating point instructions.
315 __ lwc1(f4, MemOperand(a0, offsetof(T, fa)) );
316 __ lwc1(f6, MemOperand(a0, offsetof(T, fb)) );
317 __ add_s(f8, f4, f6);
318 __ swc1(f8, MemOperand(a0, offsetof(T, fc)) ); // fc = fa + fb.
319
320 __ neg_s(f10, f6); // -fb
321 __ sub_s(f10, f8, f10);
322 __ swc1(f10, MemOperand(a0, offsetof(T, fd)) ); // fd = fc - (-fb).
323
324 __ swc1(f4, MemOperand(a0, offsetof(T, fb)) ); // fb = fa.
325
326 __ li(t0, 120);
327 __ mtc1(t0, f14);
328 __ cvt_s_w(f14, f14); // f14 = 120.0.
329 __ mul_s(f10, f10, f14);
330 __ swc1(f10, MemOperand(a0, offsetof(T, fe)) ); // fe = fd * 120
331
332 __ div_s(f12, f10, f4);
333 __ swc1(f12, MemOperand(a0, offsetof(T, ff)) ); // ff = fe / fa
334
335 __ sqrt_s(f14, f12);
336 __ swc1(f14, MemOperand(a0, offsetof(T, fg)) );
337
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000338 __ jr(ra);
339 __ nop();
Steve Block44f0eee2011-05-26 01:26:41 +0100340
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000341 CodeDesc desc;
342 assm.GetCode(&desc);
343 Handle<Code> code = isolate->factory()->NewCode(
344 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
345 F3 f = FUNCTION_CAST<F3>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000346 // Double test values.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000347 t.a = 1.5e14;
348 t.b = 2.75e11;
349 t.c = 0.0;
350 t.d = 0.0;
351 t.e = 0.0;
352 t.f = 0.0;
353 t.h = 1.5;
354 t.i = 2.75;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000355 // Single test values.
356 t.fa = 1.5e6;
357 t.fb = 2.75e4;
358 t.fc = 0.0;
359 t.fd = 0.0;
360 t.fe = 0.0;
361 t.ff = 0.0;
362 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000363 USE(dummy);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364 // Expected double results.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000365 CHECK_EQ(1.5e14, t.a);
366 CHECK_EQ(1.5e14, t.b);
367 CHECK_EQ(1.50275e14, t.c);
368 CHECK_EQ(1.50550e14, t.d);
369 CHECK_EQ(1.8066e16, t.e);
370 CHECK_EQ(120.44, t.f);
371 CHECK_EQ(10.97451593465515908537, t.g);
372 if (IsMipsArchVariant(kMips32r2)) {
373 CHECK_EQ(6.875, t.h);
Steve Block44f0eee2011-05-26 01:26:41 +0100374 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000375 // Expected single results.
376 CHECK_EQ(1.5e6, t.fa);
377 CHECK_EQ(1.5e6, t.fb);
378 CHECK_EQ(1.5275e06, t.fc);
379 CHECK_EQ(1.5550e06, t.fd);
380 CHECK_EQ(1.866e08, t.fe);
381 CHECK_EQ(124.40000152587890625, t.ff);
382 CHECK_EQ(11.1534748077392578125, t.fg);
Steve Block44f0eee2011-05-26 01:26:41 +0100383}
384
385
386TEST(MIPS4) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100387 // Exchange between GP anf FP registers is done through memory
388 // on FPXX compiled binaries and architectures that do not support
389 // MTHC1 and MTFC1. If this is the case, skipping this test.
390 if (IsFpxxMode() &&
391 (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson))) {
392 return;
393 }
394
Steve Block44f0eee2011-05-26 01:26:41 +0100395 // Test moves between floating point and integer registers.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000396 CcTest::InitializeVM();
397 Isolate* isolate = CcTest::i_isolate();
398 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100399
400 typedef struct {
401 double a;
402 double b;
403 double c;
404 } T;
405 T t;
406
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000407 Assembler assm(isolate, NULL, 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100408 Label L, C;
409
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000410 __ ldc1(f4, MemOperand(a0, offsetof(T, a)) );
411 __ ldc1(f6, MemOperand(a0, offsetof(T, b)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100412
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413 // Swap f4 and f6, by using four integer registers, t0-t3.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100414 if (IsFp32Mode()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100415 __ mfc1(t0, f4);
416 __ mfc1(t1, f5);
417 __ mfc1(t2, f6);
418 __ mfc1(t3, f7);
419
420 __ mtc1(t0, f6);
421 __ mtc1(t1, f7);
422 __ mtc1(t2, f4);
423 __ mtc1(t3, f5);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000424 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000425 CHECK(!IsMipsArchVariant(kMips32r1) && !IsMipsArchVariant(kLoongson));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100426 DCHECK(IsFp64Mode() || IsFpxxMode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000427 __ mfc1(t0, f4);
428 __ mfhc1(t1, f4);
429 __ mfc1(t2, f6);
430 __ mfhc1(t3, f6);
Steve Block44f0eee2011-05-26 01:26:41 +0100431
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000432 __ mtc1(t0, f6);
433 __ mthc1(t1, f6);
434 __ mtc1(t2, f4);
435 __ mthc1(t3, f4);
Steve Block44f0eee2011-05-26 01:26:41 +0100436 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100437
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000438 // Store the swapped f4 and f5 back to memory.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000439 __ sdc1(f4, MemOperand(a0, offsetof(T, a)) );
440 __ sdc1(f6, MemOperand(a0, offsetof(T, c)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000441
442 __ jr(ra);
443 __ nop();
444
445 CodeDesc desc;
446 assm.GetCode(&desc);
447 Handle<Code> code = isolate->factory()->NewCode(
448 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
449 F3 f = FUNCTION_CAST<F3>(code->entry());
450 t.a = 1.5e22;
451 t.b = 2.75e11;
452 t.c = 17.17;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000453 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000454 USE(dummy);
455
456 CHECK_EQ(2.75e11, t.a);
457 CHECK_EQ(2.75e11, t.b);
458 CHECK_EQ(1.5e22, t.c);
Steve Block44f0eee2011-05-26 01:26:41 +0100459}
460
461
462TEST(MIPS5) {
463 // Test conversions between doubles and integers.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000464 CcTest::InitializeVM();
465 Isolate* isolate = CcTest::i_isolate();
466 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100467
468 typedef struct {
469 double a;
470 double b;
471 int i;
472 int j;
473 } T;
474 T t;
475
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000476 Assembler assm(isolate, NULL, 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100477 Label L, C;
478
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000479 // Load all structure elements to registers.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000480 __ ldc1(f4, MemOperand(a0, offsetof(T, a)) );
481 __ ldc1(f6, MemOperand(a0, offsetof(T, b)) );
482 __ lw(t0, MemOperand(a0, offsetof(T, i)) );
483 __ lw(t1, MemOperand(a0, offsetof(T, j)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100484
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000485 // Convert double in f4 to int in element i.
486 __ cvt_w_d(f8, f4);
487 __ mfc1(t2, f8);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000488 __ sw(t2, MemOperand(a0, offsetof(T, i)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100489
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000490 // Convert double in f6 to int in element j.
491 __ cvt_w_d(f10, f6);
492 __ mfc1(t3, f10);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000493 __ sw(t3, MemOperand(a0, offsetof(T, j)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100494
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000495 // Convert int in original i (t0) to double in a.
496 __ mtc1(t0, f12);
497 __ cvt_d_w(f0, f12);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000498 __ sdc1(f0, MemOperand(a0, offsetof(T, a)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100499
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000500 // Convert int in original j (t1) to double in b.
501 __ mtc1(t1, f14);
502 __ cvt_d_w(f2, f14);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000503 __ sdc1(f2, MemOperand(a0, offsetof(T, b)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100504
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000505 __ jr(ra);
506 __ nop();
Steve Block44f0eee2011-05-26 01:26:41 +0100507
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000508 CodeDesc desc;
509 assm.GetCode(&desc);
510 Handle<Code> code = isolate->factory()->NewCode(
511 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
512 F3 f = FUNCTION_CAST<F3>(code->entry());
513 t.a = 1.5e4;
514 t.b = 2.75e8;
515 t.i = 12345678;
516 t.j = -100000;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000517 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000518 USE(dummy);
Steve Block44f0eee2011-05-26 01:26:41 +0100519
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000520 CHECK_EQ(12345678.0, t.a);
521 CHECK_EQ(-100000.0, t.b);
522 CHECK_EQ(15000, t.i);
523 CHECK_EQ(275000000, t.j);
Steve Block44f0eee2011-05-26 01:26:41 +0100524}
525
526
527TEST(MIPS6) {
528 // Test simple memory loads and stores.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000529 CcTest::InitializeVM();
530 Isolate* isolate = CcTest::i_isolate();
531 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100532
533 typedef struct {
534 uint32_t ui;
535 int32_t si;
536 int32_t r1;
537 int32_t r2;
538 int32_t r3;
539 int32_t r4;
540 int32_t r5;
541 int32_t r6;
542 } T;
543 T t;
544
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000545 Assembler assm(isolate, NULL, 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100546 Label L, C;
547
548 // Basic word load/store.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000549 __ lw(t0, MemOperand(a0, offsetof(T, ui)) );
550 __ sw(t0, MemOperand(a0, offsetof(T, r1)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100551
552 // lh with positive data.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000553 __ lh(t1, MemOperand(a0, offsetof(T, ui)) );
554 __ sw(t1, MemOperand(a0, offsetof(T, r2)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100555
556 // lh with negative data.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000557 __ lh(t2, MemOperand(a0, offsetof(T, si)) );
558 __ sw(t2, MemOperand(a0, offsetof(T, r3)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100559
560 // lhu with negative data.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000561 __ lhu(t3, MemOperand(a0, offsetof(T, si)) );
562 __ sw(t3, MemOperand(a0, offsetof(T, r4)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100563
564 // lb with negative data.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000565 __ lb(t4, MemOperand(a0, offsetof(T, si)) );
566 __ sw(t4, MemOperand(a0, offsetof(T, r5)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100567
568 // sh writes only 1/2 of word.
569 __ lui(t5, 0x3333);
570 __ ori(t5, t5, 0x3333);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000571 __ sw(t5, MemOperand(a0, offsetof(T, r6)) );
572 __ lhu(t5, MemOperand(a0, offsetof(T, si)) );
573 __ sh(t5, MemOperand(a0, offsetof(T, r6)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100574
575 __ jr(ra);
576 __ nop();
577
578 CodeDesc desc;
579 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000580 Handle<Code> code = isolate->factory()->NewCode(
581 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
582 F3 f = FUNCTION_CAST<F3>(code->entry());
Steve Block44f0eee2011-05-26 01:26:41 +0100583 t.ui = 0x11223344;
584 t.si = 0x99aabbcc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000585 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100586 USE(dummy);
587
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000588 CHECK_EQ(static_cast<int32_t>(0x11223344), t.r1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000589#if __BYTE_ORDER == __LITTLE_ENDIAN
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000590 CHECK_EQ(static_cast<int32_t>(0x3344), t.r2);
591 CHECK_EQ(static_cast<int32_t>(0xffffbbcc), t.r3);
592 CHECK_EQ(static_cast<int32_t>(0x0000bbcc), t.r4);
593 CHECK_EQ(static_cast<int32_t>(0xffffffcc), t.r5);
594 CHECK_EQ(static_cast<int32_t>(0x3333bbcc), t.r6);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000595#elif __BYTE_ORDER == __BIG_ENDIAN
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000596 CHECK_EQ(static_cast<int32_t>(0x1122), t.r2);
597 CHECK_EQ(static_cast<int32_t>(0xffff99aa), t.r3);
598 CHECK_EQ(static_cast<int32_t>(0x000099aa), t.r4);
599 CHECK_EQ(static_cast<int32_t>(0xffffff99), t.r5);
600 CHECK_EQ(static_cast<int32_t>(0x99aa3333), t.r6);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000601#else
602#error Unknown endianness
603#endif
Steve Block44f0eee2011-05-26 01:26:41 +0100604}
605
606
607TEST(MIPS7) {
608 // Test floating point compare and branch instructions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000609 CcTest::InitializeVM();
610 Isolate* isolate = CcTest::i_isolate();
611 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100612
613 typedef struct {
614 double a;
615 double b;
616 double c;
617 double d;
618 double e;
619 double f;
620 int32_t result;
621 } T;
622 T t;
623
624 // Create a function that accepts &t, and loads, manipulates, and stores
625 // the doubles t.a ... t.f.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000626 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Steve Block44f0eee2011-05-26 01:26:41 +0100627 Label neither_is_nan, less_than, outa_here;
628
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000629 __ ldc1(f4, MemOperand(a0, offsetof(T, a)) );
630 __ ldc1(f6, MemOperand(a0, offsetof(T, b)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000631 if (!IsMipsArchVariant(kMips32r6)) {
632 __ c(UN, D, f4, f6);
633 __ bc1f(&neither_is_nan);
634 } else {
635 __ cmp(UN, L, f2, f4, f6);
636 __ bc1eqz(&neither_is_nan, f2);
Steve Block44f0eee2011-05-26 01:26:41 +0100637 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000638 __ nop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000639 __ sw(zero_reg, MemOperand(a0, offsetof(T, result)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000640 __ Branch(&outa_here);
641
642 __ bind(&neither_is_nan);
643
644 if (IsMipsArchVariant(kLoongson)) {
645 __ c(OLT, D, f6, f4);
646 __ bc1t(&less_than);
647 } else if (IsMipsArchVariant(kMips32r6)) {
648 __ cmp(OLT, L, f2, f6, f4);
649 __ bc1nez(&less_than, f2);
650 } else {
651 __ c(OLT, D, f6, f4, 2);
652 __ bc1t(&less_than, 2);
653 }
654
655 __ nop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000656 __ sw(zero_reg, MemOperand(a0, offsetof(T, result)) );
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000657 __ Branch(&outa_here);
658
659 __ bind(&less_than);
660 __ Addu(t0, zero_reg, Operand(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000661 __ sw(t0, MemOperand(a0, offsetof(T, result)) ); // Set true.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000662
663
664 // This test-case should have additional tests.
665
666 __ bind(&outa_here);
667
668 __ jr(ra);
669 __ nop();
670
671 CodeDesc desc;
672 assm.GetCode(&desc);
673 Handle<Code> code = isolate->factory()->NewCode(
674 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
675 F3 f = FUNCTION_CAST<F3>(code->entry());
676 t.a = 1.5e14;
677 t.b = 2.75e11;
678 t.c = 2.0;
679 t.d = -4.0;
680 t.e = 0.0;
681 t.f = 0.0;
682 t.result = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000683 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000684 USE(dummy);
685 CHECK_EQ(1.5e14, t.a);
686 CHECK_EQ(2.75e11, t.b);
687 CHECK_EQ(1, t.result);
Steve Block44f0eee2011-05-26 01:26:41 +0100688}
689
690
691TEST(MIPS8) {
692 // Test ROTR and ROTRV instructions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000693 if (IsMipsArchVariant(kMips32r2)) {
694 CcTest::InitializeVM();
695 Isolate* isolate = CcTest::i_isolate();
696 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100697
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000698 typedef struct {
699 int32_t input;
700 int32_t result_rotr_4;
701 int32_t result_rotr_8;
702 int32_t result_rotr_12;
703 int32_t result_rotr_16;
704 int32_t result_rotr_20;
705 int32_t result_rotr_24;
706 int32_t result_rotr_28;
707 int32_t result_rotrv_4;
708 int32_t result_rotrv_8;
709 int32_t result_rotrv_12;
710 int32_t result_rotrv_16;
711 int32_t result_rotrv_20;
712 int32_t result_rotrv_24;
713 int32_t result_rotrv_28;
714 } T;
715 T t;
Steve Block44f0eee2011-05-26 01:26:41 +0100716
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000717 MacroAssembler assm(isolate, NULL, 0,
718 v8::internal::CodeObjectRequired::kYes);
Steve Block44f0eee2011-05-26 01:26:41 +0100719
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000720 // Basic word load.
721 __ lw(t0, MemOperand(a0, offsetof(T, input)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100722
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000723 // ROTR instruction (called through the Ror macro).
724 __ Ror(t1, t0, 0x0004);
725 __ Ror(t2, t0, 0x0008);
726 __ Ror(t3, t0, 0x000c);
727 __ Ror(t4, t0, 0x0010);
728 __ Ror(t5, t0, 0x0014);
729 __ Ror(t6, t0, 0x0018);
730 __ Ror(t7, t0, 0x001c);
Steve Block44f0eee2011-05-26 01:26:41 +0100731
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000732 // Basic word store.
733 __ sw(t1, MemOperand(a0, offsetof(T, result_rotr_4)) );
734 __ sw(t2, MemOperand(a0, offsetof(T, result_rotr_8)) );
735 __ sw(t3, MemOperand(a0, offsetof(T, result_rotr_12)) );
736 __ sw(t4, MemOperand(a0, offsetof(T, result_rotr_16)) );
737 __ sw(t5, MemOperand(a0, offsetof(T, result_rotr_20)) );
738 __ sw(t6, MemOperand(a0, offsetof(T, result_rotr_24)) );
739 __ sw(t7, MemOperand(a0, offsetof(T, result_rotr_28)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100740
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000741 // ROTRV instruction (called through the Ror macro).
742 __ li(t7, 0x0004);
743 __ Ror(t1, t0, t7);
744 __ li(t7, 0x0008);
745 __ Ror(t2, t0, t7);
746 __ li(t7, 0x000C);
747 __ Ror(t3, t0, t7);
748 __ li(t7, 0x0010);
749 __ Ror(t4, t0, t7);
750 __ li(t7, 0x0014);
751 __ Ror(t5, t0, t7);
752 __ li(t7, 0x0018);
753 __ Ror(t6, t0, t7);
754 __ li(t7, 0x001C);
755 __ Ror(t7, t0, t7);
Steve Block44f0eee2011-05-26 01:26:41 +0100756
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000757 // Basic word store.
758 __ sw(t1, MemOperand(a0, offsetof(T, result_rotrv_4)) );
759 __ sw(t2, MemOperand(a0, offsetof(T, result_rotrv_8)) );
760 __ sw(t3, MemOperand(a0, offsetof(T, result_rotrv_12)) );
761 __ sw(t4, MemOperand(a0, offsetof(T, result_rotrv_16)) );
762 __ sw(t5, MemOperand(a0, offsetof(T, result_rotrv_20)) );
763 __ sw(t6, MemOperand(a0, offsetof(T, result_rotrv_24)) );
764 __ sw(t7, MemOperand(a0, offsetof(T, result_rotrv_28)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100765
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000766 __ jr(ra);
767 __ nop();
Steve Block44f0eee2011-05-26 01:26:41 +0100768
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000769 CodeDesc desc;
770 assm.GetCode(&desc);
771 Handle<Code> code = isolate->factory()->NewCode(
772 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
773 F3 f = FUNCTION_CAST<F3>(code->entry());
774 t.input = 0x12345678;
775 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0x0, 0, 0, 0);
776 USE(dummy);
777 CHECK_EQ(static_cast<int32_t>(0x81234567), t.result_rotr_4);
778 CHECK_EQ(static_cast<int32_t>(0x78123456), t.result_rotr_8);
779 CHECK_EQ(static_cast<int32_t>(0x67812345), t.result_rotr_12);
780 CHECK_EQ(static_cast<int32_t>(0x56781234), t.result_rotr_16);
781 CHECK_EQ(static_cast<int32_t>(0x45678123), t.result_rotr_20);
782 CHECK_EQ(static_cast<int32_t>(0x34567812), t.result_rotr_24);
783 CHECK_EQ(static_cast<int32_t>(0x23456781), t.result_rotr_28);
Steve Block44f0eee2011-05-26 01:26:41 +0100784
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000785 CHECK_EQ(static_cast<int32_t>(0x81234567), t.result_rotrv_4);
786 CHECK_EQ(static_cast<int32_t>(0x78123456), t.result_rotrv_8);
787 CHECK_EQ(static_cast<int32_t>(0x67812345), t.result_rotrv_12);
788 CHECK_EQ(static_cast<int32_t>(0x56781234), t.result_rotrv_16);
789 CHECK_EQ(static_cast<int32_t>(0x45678123), t.result_rotrv_20);
790 CHECK_EQ(static_cast<int32_t>(0x34567812), t.result_rotrv_24);
791 CHECK_EQ(static_cast<int32_t>(0x23456781), t.result_rotrv_28);
792 }
Steve Block44f0eee2011-05-26 01:26:41 +0100793}
794
795
796TEST(MIPS9) {
797 // Test BRANCH improvements.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000798 CcTest::InitializeVM();
799 Isolate* isolate = CcTest::i_isolate();
800 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100801
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000802 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Steve Block44f0eee2011-05-26 01:26:41 +0100803 Label exit, exit2, exit3;
804
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000805 __ Branch(&exit, ge, a0, Operand(zero_reg));
Steve Block44f0eee2011-05-26 01:26:41 +0100806 __ Branch(&exit2, ge, a0, Operand(0x00001FFF));
807 __ Branch(&exit3, ge, a0, Operand(0x0001FFFF));
808
809 __ bind(&exit);
810 __ bind(&exit2);
811 __ bind(&exit3);
812 __ jr(ra);
813 __ nop();
814
815 CodeDesc desc;
816 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000817 isolate->factory()->NewCode(
818 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Steve Block44f0eee2011-05-26 01:26:41 +0100819}
820
821
822TEST(MIPS10) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000823 // Test conversions between doubles and words.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000824 CcTest::InitializeVM();
825 Isolate* isolate = CcTest::i_isolate();
826 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100827
828 typedef struct {
829 double a;
830 double b;
831 int32_t dbl_mant;
832 int32_t dbl_exp;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000833 int32_t word;
834 int32_t b_word;
Steve Block44f0eee2011-05-26 01:26:41 +0100835 } T;
836 T t;
837
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000838 Assembler assm(isolate, NULL, 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100839 Label L, C;
840
Ben Murdoch097c5b22016-05-18 11:27:45 +0100841 if (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson)) return;
Steve Block44f0eee2011-05-26 01:26:41 +0100842
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000843 // Load all structure elements to registers.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000844 // (f0, f1) = a (fp32), f0 = a (fp64)
845 __ ldc1(f0, MemOperand(a0, offsetof(T, a)));
Steve Block44f0eee2011-05-26 01:26:41 +0100846
Ben Murdoch097c5b22016-05-18 11:27:45 +0100847 __ mfc1(t0, f0); // t0 = f0(31..0)
848 __ mfhc1(t1, f0); // t1 = sign_extend(f0(63..32))
849 __ sw(t0, MemOperand(a0, offsetof(T, dbl_mant))); // dbl_mant = t0
850 __ sw(t1, MemOperand(a0, offsetof(T, dbl_exp))); // dbl_exp = t1
Steve Block44f0eee2011-05-26 01:26:41 +0100851
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000852 // Convert double in f0 to word, save hi/lo parts.
853 __ cvt_w_d(f0, f0); // a_word = (word)a
854 __ mfc1(t0, f0); // f0 has a 32-bits word. t0 = a_word
855 __ sw(t0, MemOperand(a0, offsetof(T, word))); // word = a_word
Steve Block44f0eee2011-05-26 01:26:41 +0100856
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000857 // Convert the b word to double b.
858 __ lw(t0, MemOperand(a0, offsetof(T, b_word)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000859 __ mtc1(t0, f8); // f8 has a 32-bits word.
860 __ cvt_d_w(f10, f8);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000861 __ sdc1(f10, MemOperand(a0, offsetof(T, b)));
Steve Block44f0eee2011-05-26 01:26:41 +0100862
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000863 __ jr(ra);
864 __ nop();
Steve Block44f0eee2011-05-26 01:26:41 +0100865
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000866 CodeDesc desc;
867 assm.GetCode(&desc);
868 Handle<Code> code = isolate->factory()->NewCode(
869 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
870 F3 f = FUNCTION_CAST<F3>(code->entry());
871 t.a = 2.147483646e+09; // 0x7FFFFFFE -> 0xFF80000041DFFFFF as double.
872 t.b_word = 0x0ff00ff0; // 0x0FF00FF0 -> 0x as double.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000873 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000874 USE(dummy);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000875 CHECK_EQ(static_cast<int32_t>(0x41DFFFFF), t.dbl_exp);
876 CHECK_EQ(static_cast<int32_t>(0xFF800000), t.dbl_mant);
877 CHECK_EQ(static_cast<int32_t>(0x7FFFFFFE), t.word);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000878 // 0x0FF00FF0 -> 2.6739096+e08
879 CHECK_EQ(2.6739096e08, t.b);
Steve Block44f0eee2011-05-26 01:26:41 +0100880}
881
882
883TEST(MIPS11) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000884 // Do not run test on MIPS32r6, as these instructions are removed.
885 if (IsMipsArchVariant(kMips32r6)) return;
Steve Block44f0eee2011-05-26 01:26:41 +0100886 // Test LWL, LWR, SWL and SWR instructions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000887 CcTest::InitializeVM();
888 Isolate* isolate = CcTest::i_isolate();
889 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100890
891 typedef struct {
892 int32_t reg_init;
893 int32_t mem_init;
894 int32_t lwl_0;
895 int32_t lwl_1;
896 int32_t lwl_2;
897 int32_t lwl_3;
898 int32_t lwr_0;
899 int32_t lwr_1;
900 int32_t lwr_2;
901 int32_t lwr_3;
902 int32_t swl_0;
903 int32_t swl_1;
904 int32_t swl_2;
905 int32_t swl_3;
906 int32_t swr_0;
907 int32_t swr_1;
908 int32_t swr_2;
909 int32_t swr_3;
910 } T;
911 T t;
912
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000913 Assembler assm(isolate, NULL, 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100914
915 // Test all combinations of LWL and vAddr.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000916 __ lw(t0, MemOperand(a0, offsetof(T, reg_init)) );
917 __ lwl(t0, MemOperand(a0, offsetof(T, mem_init)) );
918 __ sw(t0, MemOperand(a0, offsetof(T, lwl_0)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100919
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000920 __ lw(t1, MemOperand(a0, offsetof(T, reg_init)) );
921 __ lwl(t1, MemOperand(a0, offsetof(T, mem_init) + 1) );
922 __ sw(t1, MemOperand(a0, offsetof(T, lwl_1)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100923
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000924 __ lw(t2, MemOperand(a0, offsetof(T, reg_init)) );
925 __ lwl(t2, MemOperand(a0, offsetof(T, mem_init) + 2) );
926 __ sw(t2, MemOperand(a0, offsetof(T, lwl_2)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100927
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000928 __ lw(t3, MemOperand(a0, offsetof(T, reg_init)) );
929 __ lwl(t3, MemOperand(a0, offsetof(T, mem_init) + 3) );
930 __ sw(t3, MemOperand(a0, offsetof(T, lwl_3)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100931
932 // Test all combinations of LWR and vAddr.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000933 __ lw(t0, MemOperand(a0, offsetof(T, reg_init)) );
934 __ lwr(t0, MemOperand(a0, offsetof(T, mem_init)) );
935 __ sw(t0, MemOperand(a0, offsetof(T, lwr_0)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100936
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000937 __ lw(t1, MemOperand(a0, offsetof(T, reg_init)) );
938 __ lwr(t1, MemOperand(a0, offsetof(T, mem_init) + 1) );
939 __ sw(t1, MemOperand(a0, offsetof(T, lwr_1)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100940
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000941 __ lw(t2, MemOperand(a0, offsetof(T, reg_init)) );
942 __ lwr(t2, MemOperand(a0, offsetof(T, mem_init) + 2) );
943 __ sw(t2, MemOperand(a0, offsetof(T, lwr_2)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100944
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000945 __ lw(t3, MemOperand(a0, offsetof(T, reg_init)) );
946 __ lwr(t3, MemOperand(a0, offsetof(T, mem_init) + 3) );
947 __ sw(t3, MemOperand(a0, offsetof(T, lwr_3)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100948
949 // Test all combinations of SWL and vAddr.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000950 __ lw(t0, MemOperand(a0, offsetof(T, mem_init)) );
951 __ sw(t0, MemOperand(a0, offsetof(T, swl_0)) );
952 __ lw(t0, MemOperand(a0, offsetof(T, reg_init)) );
953 __ swl(t0, MemOperand(a0, offsetof(T, swl_0)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100954
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000955 __ lw(t1, MemOperand(a0, offsetof(T, mem_init)) );
956 __ sw(t1, MemOperand(a0, offsetof(T, swl_1)) );
957 __ lw(t1, MemOperand(a0, offsetof(T, reg_init)) );
958 __ swl(t1, MemOperand(a0, offsetof(T, swl_1) + 1) );
Steve Block44f0eee2011-05-26 01:26:41 +0100959
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000960 __ lw(t2, MemOperand(a0, offsetof(T, mem_init)) );
961 __ sw(t2, MemOperand(a0, offsetof(T, swl_2)) );
962 __ lw(t2, MemOperand(a0, offsetof(T, reg_init)) );
963 __ swl(t2, MemOperand(a0, offsetof(T, swl_2) + 2) );
Steve Block44f0eee2011-05-26 01:26:41 +0100964
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000965 __ lw(t3, MemOperand(a0, offsetof(T, mem_init)) );
966 __ sw(t3, MemOperand(a0, offsetof(T, swl_3)) );
967 __ lw(t3, MemOperand(a0, offsetof(T, reg_init)) );
968 __ swl(t3, MemOperand(a0, offsetof(T, swl_3) + 3) );
Steve Block44f0eee2011-05-26 01:26:41 +0100969
970 // Test all combinations of SWR and vAddr.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000971 __ lw(t0, MemOperand(a0, offsetof(T, mem_init)) );
972 __ sw(t0, MemOperand(a0, offsetof(T, swr_0)) );
973 __ lw(t0, MemOperand(a0, offsetof(T, reg_init)) );
974 __ swr(t0, MemOperand(a0, offsetof(T, swr_0)) );
Steve Block44f0eee2011-05-26 01:26:41 +0100975
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000976 __ lw(t1, MemOperand(a0, offsetof(T, mem_init)) );
977 __ sw(t1, MemOperand(a0, offsetof(T, swr_1)) );
978 __ lw(t1, MemOperand(a0, offsetof(T, reg_init)) );
979 __ swr(t1, MemOperand(a0, offsetof(T, swr_1) + 1) );
Steve Block44f0eee2011-05-26 01:26:41 +0100980
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000981 __ lw(t2, MemOperand(a0, offsetof(T, mem_init)) );
982 __ sw(t2, MemOperand(a0, offsetof(T, swr_2)) );
983 __ lw(t2, MemOperand(a0, offsetof(T, reg_init)) );
984 __ swr(t2, MemOperand(a0, offsetof(T, swr_2) + 2) );
Steve Block44f0eee2011-05-26 01:26:41 +0100985
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000986 __ lw(t3, MemOperand(a0, offsetof(T, mem_init)) );
987 __ sw(t3, MemOperand(a0, offsetof(T, swr_3)) );
988 __ lw(t3, MemOperand(a0, offsetof(T, reg_init)) );
989 __ swr(t3, MemOperand(a0, offsetof(T, swr_3) + 3) );
Steve Block44f0eee2011-05-26 01:26:41 +0100990
991 __ jr(ra);
992 __ nop();
993
994 CodeDesc desc;
995 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000996 Handle<Code> code = isolate->factory()->NewCode(
997 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
998 F3 f = FUNCTION_CAST<F3>(code->entry());
Steve Block44f0eee2011-05-26 01:26:41 +0100999 t.reg_init = 0xaabbccdd;
1000 t.mem_init = 0x11223344;
1001
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001002 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Steve Block44f0eee2011-05-26 01:26:41 +01001003 USE(dummy);
1004
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001005#if __BYTE_ORDER == __LITTLE_ENDIAN
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001006 CHECK_EQ(static_cast<int32_t>(0x44bbccdd), t.lwl_0);
1007 CHECK_EQ(static_cast<int32_t>(0x3344ccdd), t.lwl_1);
1008 CHECK_EQ(static_cast<int32_t>(0x223344dd), t.lwl_2);
1009 CHECK_EQ(static_cast<int32_t>(0x11223344), t.lwl_3);
Steve Block44f0eee2011-05-26 01:26:41 +01001010
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001011 CHECK_EQ(static_cast<int32_t>(0x11223344), t.lwr_0);
1012 CHECK_EQ(static_cast<int32_t>(0xaa112233), t.lwr_1);
1013 CHECK_EQ(static_cast<int32_t>(0xaabb1122), t.lwr_2);
1014 CHECK_EQ(static_cast<int32_t>(0xaabbcc11), t.lwr_3);
Steve Block44f0eee2011-05-26 01:26:41 +01001015
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001016 CHECK_EQ(static_cast<int32_t>(0x112233aa), t.swl_0);
1017 CHECK_EQ(static_cast<int32_t>(0x1122aabb), t.swl_1);
1018 CHECK_EQ(static_cast<int32_t>(0x11aabbcc), t.swl_2);
1019 CHECK_EQ(static_cast<int32_t>(0xaabbccdd), t.swl_3);
Steve Block44f0eee2011-05-26 01:26:41 +01001020
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001021 CHECK_EQ(static_cast<int32_t>(0xaabbccdd), t.swr_0);
1022 CHECK_EQ(static_cast<int32_t>(0xbbccdd44), t.swr_1);
1023 CHECK_EQ(static_cast<int32_t>(0xccdd3344), t.swr_2);
1024 CHECK_EQ(static_cast<int32_t>(0xdd223344), t.swr_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001025#elif __BYTE_ORDER == __BIG_ENDIAN
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001026 CHECK_EQ(static_cast<int32_t>(0x11223344), t.lwl_0);
1027 CHECK_EQ(static_cast<int32_t>(0x223344dd), t.lwl_1);
1028 CHECK_EQ(static_cast<int32_t>(0x3344ccdd), t.lwl_2);
1029 CHECK_EQ(static_cast<int32_t>(0x44bbccdd), t.lwl_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001030
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001031 CHECK_EQ(static_cast<int32_t>(0xaabbcc11), t.lwr_0);
1032 CHECK_EQ(static_cast<int32_t>(0xaabb1122), t.lwr_1);
1033 CHECK_EQ(static_cast<int32_t>(0xaa112233), t.lwr_2);
1034 CHECK_EQ(static_cast<int32_t>(0x11223344), t.lwr_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001035
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001036 CHECK_EQ(static_cast<int32_t>(0xaabbccdd), t.swl_0);
1037 CHECK_EQ(static_cast<int32_t>(0x11aabbcc), t.swl_1);
1038 CHECK_EQ(static_cast<int32_t>(0x1122aabb), t.swl_2);
1039 CHECK_EQ(static_cast<int32_t>(0x112233aa), t.swl_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001040
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001041 CHECK_EQ(static_cast<int32_t>(0xdd223344), t.swr_0);
1042 CHECK_EQ(static_cast<int32_t>(0xccdd3344), t.swr_1);
1043 CHECK_EQ(static_cast<int32_t>(0xbbccdd44), t.swr_2);
1044 CHECK_EQ(static_cast<int32_t>(0xaabbccdd), t.swr_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001045#else
1046#error Unknown endianness
1047#endif
Steve Block44f0eee2011-05-26 01:26:41 +01001048}
1049
1050
1051TEST(MIPS12) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001052 CcTest::InitializeVM();
1053 Isolate* isolate = CcTest::i_isolate();
1054 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +01001055
1056 typedef struct {
1057 int32_t x;
1058 int32_t y;
1059 int32_t y1;
1060 int32_t y2;
1061 int32_t y3;
1062 int32_t y4;
1063 } T;
1064 T t;
1065
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001066 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Steve Block44f0eee2011-05-26 01:26:41 +01001067
1068 __ mov(t6, fp); // Save frame pointer.
1069 __ mov(fp, a0); // Access struct T by fp.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001070 __ lw(t0, MemOperand(a0, offsetof(T, y)) );
1071 __ lw(t3, MemOperand(a0, offsetof(T, y4)) );
Steve Block44f0eee2011-05-26 01:26:41 +01001072
1073 __ addu(t1, t0, t3);
1074 __ subu(t4, t0, t3);
1075 __ nop();
Ben Murdoch257744e2011-11-30 15:57:28 +00001076 __ push(t0); // These instructions disappear after opt.
Steve Block44f0eee2011-05-26 01:26:41 +01001077 __ Pop();
1078 __ addu(t0, t0, t0);
1079 __ nop();
1080 __ Pop(); // These instructions disappear after opt.
Ben Murdoch257744e2011-11-30 15:57:28 +00001081 __ push(t3);
Steve Block44f0eee2011-05-26 01:26:41 +01001082 __ nop();
Ben Murdoch257744e2011-11-30 15:57:28 +00001083 __ push(t3); // These instructions disappear after opt.
1084 __ pop(t3);
Steve Block44f0eee2011-05-26 01:26:41 +01001085 __ nop();
Ben Murdoch257744e2011-11-30 15:57:28 +00001086 __ push(t3);
1087 __ pop(t4);
Steve Block44f0eee2011-05-26 01:26:41 +01001088 __ nop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001089 __ sw(t0, MemOperand(fp, offsetof(T, y)) );
1090 __ lw(t0, MemOperand(fp, offsetof(T, y)) );
Steve Block44f0eee2011-05-26 01:26:41 +01001091 __ nop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001092 __ sw(t0, MemOperand(fp, offsetof(T, y)) );
1093 __ lw(t1, MemOperand(fp, offsetof(T, y)) );
Steve Block44f0eee2011-05-26 01:26:41 +01001094 __ nop();
Ben Murdoch257744e2011-11-30 15:57:28 +00001095 __ push(t1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001096 __ lw(t1, MemOperand(fp, offsetof(T, y)) );
Ben Murdoch257744e2011-11-30 15:57:28 +00001097 __ pop(t1);
Steve Block44f0eee2011-05-26 01:26:41 +01001098 __ nop();
Ben Murdoch257744e2011-11-30 15:57:28 +00001099 __ push(t1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001100 __ lw(t2, MemOperand(fp, offsetof(T, y)) );
Ben Murdoch257744e2011-11-30 15:57:28 +00001101 __ pop(t1);
Steve Block44f0eee2011-05-26 01:26:41 +01001102 __ nop();
Ben Murdoch257744e2011-11-30 15:57:28 +00001103 __ push(t1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001104 __ lw(t2, MemOperand(fp, offsetof(T, y)) );
Ben Murdoch257744e2011-11-30 15:57:28 +00001105 __ pop(t2);
Steve Block44f0eee2011-05-26 01:26:41 +01001106 __ nop();
Ben Murdoch257744e2011-11-30 15:57:28 +00001107 __ push(t2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001108 __ lw(t2, MemOperand(fp, offsetof(T, y)) );
Ben Murdoch257744e2011-11-30 15:57:28 +00001109 __ pop(t1);
Steve Block44f0eee2011-05-26 01:26:41 +01001110 __ nop();
Ben Murdoch257744e2011-11-30 15:57:28 +00001111 __ push(t1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001112 __ lw(t2, MemOperand(fp, offsetof(T, y)) );
Ben Murdoch257744e2011-11-30 15:57:28 +00001113 __ pop(t3);
Steve Block44f0eee2011-05-26 01:26:41 +01001114 __ nop();
1115
1116 __ mov(fp, t6);
1117 __ jr(ra);
1118 __ nop();
1119
1120 CodeDesc desc;
1121 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001122 Handle<Code> code = isolate->factory()->NewCode(
1123 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1124 F3 f = FUNCTION_CAST<F3>(code->entry());
Steve Block44f0eee2011-05-26 01:26:41 +01001125 t.x = 1;
1126 t.y = 2;
1127 t.y1 = 3;
1128 t.y2 = 4;
1129 t.y3 = 0XBABA;
1130 t.y4 = 0xDEDA;
1131
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001132 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Steve Block44f0eee2011-05-26 01:26:41 +01001133 USE(dummy);
1134
1135 CHECK_EQ(3, t.y1);
1136}
1137
1138
1139TEST(MIPS13) {
1140 // Test Cvt_d_uw and Trunc_uw_d macros.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001141 CcTest::InitializeVM();
1142 Isolate* isolate = CcTest::i_isolate();
1143 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +01001144
1145 typedef struct {
1146 double cvt_big_out;
1147 double cvt_small_out;
1148 uint32_t trunc_big_out;
1149 uint32_t trunc_small_out;
1150 uint32_t cvt_big_in;
1151 uint32_t cvt_small_in;
1152 } T;
1153 T t;
1154
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001155 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Steve Block44f0eee2011-05-26 01:26:41 +01001156
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001157 __ sw(t0, MemOperand(a0, offsetof(T, cvt_small_in)));
1158 __ Cvt_d_uw(f10, t0, f4);
1159 __ sdc1(f10, MemOperand(a0, offsetof(T, cvt_small_out)));
Steve Block44f0eee2011-05-26 01:26:41 +01001160
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001161 __ Trunc_uw_d(f10, f10, f4);
1162 __ swc1(f10, MemOperand(a0, offsetof(T, trunc_small_out)));
Steve Block44f0eee2011-05-26 01:26:41 +01001163
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001164 __ sw(t0, MemOperand(a0, offsetof(T, cvt_big_in)));
1165 __ Cvt_d_uw(f8, t0, f4);
1166 __ sdc1(f8, MemOperand(a0, offsetof(T, cvt_big_out)));
Steve Block44f0eee2011-05-26 01:26:41 +01001167
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001168 __ Trunc_uw_d(f8, f8, f4);
1169 __ swc1(f8, MemOperand(a0, offsetof(T, trunc_big_out)));
Steve Block44f0eee2011-05-26 01:26:41 +01001170
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001171 __ jr(ra);
1172 __ nop();
Steve Block44f0eee2011-05-26 01:26:41 +01001173
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001174 CodeDesc desc;
1175 assm.GetCode(&desc);
1176 Handle<Code> code = isolate->factory()->NewCode(
1177 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1178 F3 f = FUNCTION_CAST<F3>(code->entry());
Steve Block44f0eee2011-05-26 01:26:41 +01001179
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001180 t.cvt_big_in = 0xFFFFFFFF;
1181 t.cvt_small_in = 333;
Steve Block44f0eee2011-05-26 01:26:41 +01001182
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001183 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001184 USE(dummy);
Steve Block44f0eee2011-05-26 01:26:41 +01001185
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001186 CHECK_EQ(t.cvt_big_out, static_cast<double>(t.cvt_big_in));
1187 CHECK_EQ(t.cvt_small_out, static_cast<double>(t.cvt_small_in));
Steve Block44f0eee2011-05-26 01:26:41 +01001188
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001189 CHECK_EQ(static_cast<int>(t.trunc_big_out), static_cast<int>(t.cvt_big_in));
1190 CHECK_EQ(static_cast<int>(t.trunc_small_out),
1191 static_cast<int>(t.cvt_small_in));
Steve Block44f0eee2011-05-26 01:26:41 +01001192}
1193
1194
1195TEST(MIPS14) {
1196 // Test round, floor, ceil, trunc, cvt.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001197 CcTest::InitializeVM();
1198 Isolate* isolate = CcTest::i_isolate();
1199 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +01001200
1201#define ROUND_STRUCT_ELEMENT(x) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001202 uint32_t x##_isNaN2008; \
Steve Block44f0eee2011-05-26 01:26:41 +01001203 int32_t x##_up_out; \
1204 int32_t x##_down_out; \
1205 int32_t neg_##x##_up_out; \
1206 int32_t neg_##x##_down_out; \
Ben Murdoch257744e2011-11-30 15:57:28 +00001207 uint32_t x##_err1_out; \
1208 uint32_t x##_err2_out; \
1209 uint32_t x##_err3_out; \
1210 uint32_t x##_err4_out; \
Steve Block44f0eee2011-05-26 01:26:41 +01001211 int32_t x##_invalid_result;
1212
1213 typedef struct {
1214 double round_up_in;
1215 double round_down_in;
1216 double neg_round_up_in;
1217 double neg_round_down_in;
1218 double err1_in;
1219 double err2_in;
1220 double err3_in;
1221 double err4_in;
1222
1223 ROUND_STRUCT_ELEMENT(round)
1224 ROUND_STRUCT_ELEMENT(floor)
1225 ROUND_STRUCT_ELEMENT(ceil)
1226 ROUND_STRUCT_ELEMENT(trunc)
1227 ROUND_STRUCT_ELEMENT(cvt)
1228 } T;
1229 T t;
1230
1231#undef ROUND_STRUCT_ELEMENT
1232
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001233 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
Steve Block44f0eee2011-05-26 01:26:41 +01001234
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001235 // Save FCSR.
1236 __ cfc1(a1, FCSR);
1237 // Disable FPU exceptions.
1238 __ ctc1(zero_reg, FCSR);
Steve Block44f0eee2011-05-26 01:26:41 +01001239#define RUN_ROUND_TEST(x) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001240 __ cfc1(t0, FCSR);\
1241 __ sw(t0, MemOperand(a0, offsetof(T, x##_isNaN2008))); \
1242 __ ldc1(f0, MemOperand(a0, offsetof(T, round_up_in))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001243 __ x##_w_d(f0, f0); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001244 __ swc1(f0, MemOperand(a0, offsetof(T, x##_up_out))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001245 \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001246 __ ldc1(f0, MemOperand(a0, offsetof(T, round_down_in))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001247 __ x##_w_d(f0, f0); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001248 __ swc1(f0, MemOperand(a0, offsetof(T, x##_down_out))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001249 \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001250 __ ldc1(f0, MemOperand(a0, offsetof(T, neg_round_up_in))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001251 __ x##_w_d(f0, f0); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001252 __ swc1(f0, MemOperand(a0, offsetof(T, neg_##x##_up_out))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001253 \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001254 __ ldc1(f0, MemOperand(a0, offsetof(T, neg_round_down_in))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001255 __ x##_w_d(f0, f0); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001256 __ swc1(f0, MemOperand(a0, offsetof(T, neg_##x##_down_out))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001257 \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001258 __ ldc1(f0, MemOperand(a0, offsetof(T, err1_in))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001259 __ ctc1(zero_reg, FCSR); \
1260 __ x##_w_d(f0, f0); \
1261 __ cfc1(a2, FCSR); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001262 __ sw(a2, MemOperand(a0, offsetof(T, x##_err1_out))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001263 \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001264 __ ldc1(f0, MemOperand(a0, offsetof(T, err2_in))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001265 __ ctc1(zero_reg, FCSR); \
1266 __ x##_w_d(f0, f0); \
1267 __ cfc1(a2, FCSR); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001268 __ sw(a2, MemOperand(a0, offsetof(T, x##_err2_out))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001269 \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001270 __ ldc1(f0, MemOperand(a0, offsetof(T, err3_in))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001271 __ ctc1(zero_reg, FCSR); \
1272 __ x##_w_d(f0, f0); \
1273 __ cfc1(a2, FCSR); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001274 __ sw(a2, MemOperand(a0, offsetof(T, x##_err3_out))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001275 \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001276 __ ldc1(f0, MemOperand(a0, offsetof(T, err4_in))); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001277 __ ctc1(zero_reg, FCSR); \
1278 __ x##_w_d(f0, f0); \
1279 __ cfc1(a2, FCSR); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001280 __ sw(a2, MemOperand(a0, offsetof(T, x##_err4_out))); \
1281 __ swc1(f0, MemOperand(a0, offsetof(T, x##_invalid_result)));
Steve Block44f0eee2011-05-26 01:26:41 +01001282
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001283 RUN_ROUND_TEST(round)
1284 RUN_ROUND_TEST(floor)
1285 RUN_ROUND_TEST(ceil)
1286 RUN_ROUND_TEST(trunc)
1287 RUN_ROUND_TEST(cvt)
Steve Block44f0eee2011-05-26 01:26:41 +01001288
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001289 // Restore FCSR.
1290 __ ctc1(a1, FCSR);
Steve Block44f0eee2011-05-26 01:26:41 +01001291
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001292 __ jr(ra);
1293 __ nop();
Steve Block44f0eee2011-05-26 01:26:41 +01001294
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001295 CodeDesc desc;
1296 assm.GetCode(&desc);
1297 Handle<Code> code = isolate->factory()->NewCode(
1298 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1299 F3 f = FUNCTION_CAST<F3>(code->entry());
Steve Block44f0eee2011-05-26 01:26:41 +01001300
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001301 t.round_up_in = 123.51;
1302 t.round_down_in = 123.49;
1303 t.neg_round_up_in = -123.5;
1304 t.neg_round_down_in = -123.49;
1305 t.err1_in = 123.51;
1306 t.err2_in = 1;
1307 t.err3_in = static_cast<double>(1) + 0xFFFFFFFF;
1308 t.err4_in = NAN;
Steve Block44f0eee2011-05-26 01:26:41 +01001309
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001310 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001311 USE(dummy);
Steve Block44f0eee2011-05-26 01:26:41 +01001312
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001313#define GET_FPU_ERR(x) (static_cast<int>(x & kFCSRFlagMask))
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001314#define CHECK_NAN2008(x) (x & kFCSRNaN2008FlagMask)
1315#define CHECK_ROUND_RESULT(type) \
1316 CHECK(GET_FPU_ERR(t.type##_err1_out) & kFCSRInexactFlagMask); \
1317 CHECK_EQ(0, GET_FPU_ERR(t.type##_err2_out)); \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001318 CHECK(GET_FPU_ERR(t.type##_err3_out) & kFCSRInvalidOpFlagMask); \
1319 CHECK(GET_FPU_ERR(t.type##_err4_out) & kFCSRInvalidOpFlagMask); \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001320 if (CHECK_NAN2008(t.type##_isNaN2008) && kArchVariant == kMips32r6) {\
1321 CHECK_EQ(static_cast<int32_t>(0), t.type##_invalid_result);\
1322 } else {\
1323 CHECK_EQ(static_cast<int32_t>(kFPUInvalidResult), t.type##_invalid_result);\
1324 }
1325
Steve Block44f0eee2011-05-26 01:26:41 +01001326
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001327 CHECK_ROUND_RESULT(round);
1328 CHECK_ROUND_RESULT(floor);
1329 CHECK_ROUND_RESULT(ceil);
1330 CHECK_ROUND_RESULT(cvt);
Steve Block44f0eee2011-05-26 01:26:41 +01001331}
1332
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001333
1334TEST(MIPS15) {
1335 // Test chaining of label usages within instructions (issue 1644).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001336 CcTest::InitializeVM();
1337 Isolate* isolate = CcTest::i_isolate();
1338 HandleScope scope(isolate);
1339 Assembler assm(isolate, NULL, 0);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001340
1341 Label target;
1342 __ beq(v0, v1, &target);
Ben Murdoch589d6972011-11-30 16:04:58 +00001343 __ nop();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001344 __ bne(v0, v1, &target);
Ben Murdoch589d6972011-11-30 16:04:58 +00001345 __ nop();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001346 __ bind(&target);
1347 __ nop();
1348}
1349
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001350
1351// ----------------------mips32r6 specific tests----------------------
1352TEST(seleqz_selnez) {
1353 if (IsMipsArchVariant(kMips32r6)) {
1354 CcTest::InitializeVM();
1355 Isolate* isolate = CcTest::i_isolate();
1356 HandleScope scope(isolate);
1357 MacroAssembler assm(isolate, NULL, 0,
1358 v8::internal::CodeObjectRequired::kYes);
1359
1360 typedef struct test {
1361 int a;
1362 int b;
1363 int c;
1364 int d;
1365 double e;
1366 double f;
1367 double g;
1368 double h;
1369 float i;
1370 float j;
1371 float k;
1372 float l;
1373 } Test;
1374
1375 Test test;
1376 // Integer part of test.
1377 __ addiu(t1, zero_reg, 1); // t1 = 1
1378 __ seleqz(t3, t1, zero_reg); // t3 = 1
1379 __ sw(t3, MemOperand(a0, offsetof(Test, a))); // a = 1
1380 __ seleqz(t2, t1, t1); // t2 = 0
1381 __ sw(t2, MemOperand(a0, offsetof(Test, b))); // b = 0
1382 __ selnez(t3, t1, zero_reg); // t3 = 1;
1383 __ sw(t3, MemOperand(a0, offsetof(Test, c))); // c = 0
1384 __ selnez(t3, t1, t1); // t3 = 1
1385 __ sw(t3, MemOperand(a0, offsetof(Test, d))); // d = 1
1386 // Floating point part of test.
1387 __ ldc1(f0, MemOperand(a0, offsetof(Test, e)) ); // src
1388 __ ldc1(f2, MemOperand(a0, offsetof(Test, f)) ); // test
1389 __ lwc1(f8, MemOperand(a0, offsetof(Test, i)) ); // src
1390 __ lwc1(f10, MemOperand(a0, offsetof(Test, j)) ); // test
1391 __ seleqz_d(f4, f0, f2);
1392 __ selnez_d(f6, f0, f2);
1393 __ seleqz_s(f12, f8, f10);
1394 __ selnez_s(f14, f8, f10);
1395 __ sdc1(f4, MemOperand(a0, offsetof(Test, g)) ); // src
1396 __ sdc1(f6, MemOperand(a0, offsetof(Test, h)) ); // src
1397 __ swc1(f12, MemOperand(a0, offsetof(Test, k)) ); // src
1398 __ swc1(f14, MemOperand(a0, offsetof(Test, l)) ); // src
1399 __ jr(ra);
1400 __ nop();
1401 CodeDesc desc;
1402 assm.GetCode(&desc);
1403 Handle<Code> code = isolate->factory()->NewCode(
1404 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1405 F3 f = FUNCTION_CAST<F3>(code->entry());
1406
1407 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1408
1409 CHECK_EQ(test.a, 1);
1410 CHECK_EQ(test.b, 0);
1411 CHECK_EQ(test.c, 0);
1412 CHECK_EQ(test.d, 1);
1413
1414 const int test_size = 3;
1415 const int input_size = 5;
1416
1417 double inputs_D[input_size] = {0.0, 65.2, -70.32,
1418 18446744073709551621.0, -18446744073709551621.0};
1419 double outputs_D[input_size] = {0.0, 65.2, -70.32,
1420 18446744073709551621.0, -18446744073709551621.0};
1421 double tests_D[test_size*2] = {2.8, 2.9, -2.8, -2.9,
1422 18446744073709551616.0, 18446744073709555712.0};
1423 float inputs_S[input_size] = {0.0, 65.2, -70.32,
1424 18446744073709551621.0, -18446744073709551621.0};
1425 float outputs_S[input_size] = {0.0, 65.2, -70.32,
1426 18446744073709551621.0, -18446744073709551621.0};
1427 float tests_S[test_size*2] = {2.9, 2.8, -2.9, -2.8,
1428 18446744073709551616.0, 18446746272732807168.0};
1429 for (int j=0; j < test_size; j+=2) {
1430 for (int i=0; i < input_size; i++) {
1431 test.e = inputs_D[i];
1432 test.f = tests_D[j];
1433 test.i = inputs_S[i];
1434 test.j = tests_S[j];
1435 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1436 CHECK_EQ(test.g, outputs_D[i]);
1437 CHECK_EQ(test.h, 0);
1438 CHECK_EQ(test.k, outputs_S[i]);
1439 CHECK_EQ(test.l, 0);
1440
1441 test.f = tests_D[j+1];
1442 test.j = tests_S[j+1];
1443 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1444 CHECK_EQ(test.g, 0);
1445 CHECK_EQ(test.h, outputs_D[i]);
1446 CHECK_EQ(test.k, 0);
1447 CHECK_EQ(test.l, outputs_S[i]);
1448 }
1449 }
1450 }
1451}
1452
1453
1454TEST(min_max) {
1455 if (IsMipsArchVariant(kMips32r6)) {
1456 CcTest::InitializeVM();
1457 Isolate* isolate = CcTest::i_isolate();
1458 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001459 MacroAssembler assm(isolate, nullptr, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001460 v8::internal::CodeObjectRequired::kYes);
1461
Ben Murdoch097c5b22016-05-18 11:27:45 +01001462 struct TestFloat {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001463 double a;
1464 double b;
1465 double c;
1466 double d;
1467 float e;
1468 float f;
1469 float g;
1470 float h;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001471 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001472
1473 TestFloat test;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001474 const double dnan = std::numeric_limits<double>::quiet_NaN();
1475 const double dinf = std::numeric_limits<double>::infinity();
1476 const double dminf = -std::numeric_limits<double>::infinity();
1477 const float fnan = std::numeric_limits<float>::quiet_NaN();
1478 const float finf = std::numeric_limits<float>::infinity();
1479 const float fminf = std::numeric_limits<float>::infinity();
1480 const int kTableLength = 13;
1481 double inputsa[kTableLength] = {2.0, 3.0, dnan, 3.0, -0.0, 0.0, dinf,
1482 dnan, 42.0, dinf, dminf, dinf, dnan};
1483 double inputsb[kTableLength] = {3.0, 2.0, 3.0, dnan, 0.0, -0.0, dnan,
1484 dinf, dinf, 42.0, dinf, dminf, dnan};
1485 double outputsdmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, -0.0,
1486 -0.0, dinf, dinf, 42.0, 42.0,
1487 dminf, dminf, dnan};
1488 double outputsdmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, 0.0, 0.0, dinf,
1489 dinf, dinf, dinf, dinf, dinf, dnan};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001490
Ben Murdoch097c5b22016-05-18 11:27:45 +01001491 float inputse[kTableLength] = {2.0, 3.0, fnan, 3.0, -0.0, 0.0, finf,
1492 fnan, 42.0, finf, fminf, finf, fnan};
Ben Murdochda12d292016-06-02 14:46:10 +01001493 float inputsf[kTableLength] = {3.0, 2.0, 3.0, fnan, 0.0, -0.0, fnan,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001494 finf, finf, 42.0, finf, fminf, fnan};
1495 float outputsfmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, -0.0,
1496 -0.0, finf, finf, 42.0, 42.0,
1497 fminf, fminf, fnan};
1498 float outputsfmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, 0.0, 0.0, finf,
1499 finf, finf, finf, finf, finf, fnan};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001500
1501 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)));
1502 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b)));
1503 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, e)));
1504 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, f)));
1505 __ min_d(f10, f4, f8);
1506 __ max_d(f12, f4, f8);
1507 __ min_s(f14, f2, f6);
1508 __ max_s(f16, f2, f6);
1509 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c)));
1510 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, d)));
1511 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, g)));
1512 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, h)));
1513 __ jr(ra);
1514 __ nop();
1515
1516 CodeDesc desc;
1517 assm.GetCode(&desc);
1518 Handle<Code> code = isolate->factory()->NewCode(
1519 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1520 F3 f = FUNCTION_CAST<F3>(code->entry());
1521 for (int i = 0; i < kTableLength; i++) {
1522 test.a = inputsa[i];
1523 test.b = inputsb[i];
1524 test.e = inputse[i];
1525 test.f = inputsf[i];
1526
Ben Murdochda12d292016-06-02 14:46:10 +01001527 CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001528
Ben Murdochda12d292016-06-02 14:46:10 +01001529 CHECK_EQ(0, memcmp(&test.c, &outputsdmin[i], sizeof(test.c)));
1530 CHECK_EQ(0, memcmp(&test.d, &outputsdmax[i], sizeof(test.d)));
1531 CHECK_EQ(0, memcmp(&test.g, &outputsfmin[i], sizeof(test.g)));
1532 CHECK_EQ(0, memcmp(&test.h, &outputsfmax[i], sizeof(test.h)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001533 }
1534 }
1535}
1536
1537
1538TEST(rint_d) {
1539 if (IsMipsArchVariant(kMips32r6)) {
1540 const int kTableLength = 30;
1541 CcTest::InitializeVM();
1542 Isolate* isolate = CcTest::i_isolate();
1543 HandleScope scope(isolate);
1544 MacroAssembler assm(isolate, NULL, 0,
1545 v8::internal::CodeObjectRequired::kYes);
1546
1547 typedef struct test_float {
1548 double a;
1549 double b;
1550 int fcsr;
1551 }TestFloat;
1552
1553 TestFloat test;
1554 double inputs[kTableLength] = {18446744073709551617.0,
1555 4503599627370496.0, -4503599627370496.0,
1556 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
1557 1.7976931348623157E+308, 6.27463370218383111104242366943E-307,
1558 309485009821345068724781056.89,
1559 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
1560 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
1561 37778931862957161709568.0, 37778931862957161709569.0,
1562 37778931862957161709580.0, 37778931862957161709581.0,
1563 37778931862957161709582.0, 37778931862957161709583.0,
1564 37778931862957161709584.0, 37778931862957161709585.0,
1565 37778931862957161709586.0, 37778931862957161709587.0};
1566 double outputs_RN[kTableLength] = {18446744073709551617.0,
1567 4503599627370496.0, -4503599627370496.0,
1568 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
1569 1.7976931348623157E308, 0,
1570 309485009821345068724781057.0,
1571 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
1572 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
1573 37778931862957161709568.0, 37778931862957161709569.0,
1574 37778931862957161709580.0, 37778931862957161709581.0,
1575 37778931862957161709582.0, 37778931862957161709583.0,
1576 37778931862957161709584.0, 37778931862957161709585.0,
1577 37778931862957161709586.0, 37778931862957161709587.0};
1578 double outputs_RZ[kTableLength] = {18446744073709551617.0,
1579 4503599627370496.0, -4503599627370496.0,
1580 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
1581 1.7976931348623157E308, 0,
1582 309485009821345068724781057.0,
1583 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
1584 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
1585 37778931862957161709568.0, 37778931862957161709569.0,
1586 37778931862957161709580.0, 37778931862957161709581.0,
1587 37778931862957161709582.0, 37778931862957161709583.0,
1588 37778931862957161709584.0, 37778931862957161709585.0,
1589 37778931862957161709586.0, 37778931862957161709587.0};
1590 double outputs_RP[kTableLength] = {18446744073709551617.0,
1591 4503599627370496.0, -4503599627370496.0,
1592 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
1593 1.7976931348623157E308, 1,
1594 309485009821345068724781057.0,
1595 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
1596 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
1597 37778931862957161709568.0, 37778931862957161709569.0,
1598 37778931862957161709580.0, 37778931862957161709581.0,
1599 37778931862957161709582.0, 37778931862957161709583.0,
1600 37778931862957161709584.0, 37778931862957161709585.0,
1601 37778931862957161709586.0, 37778931862957161709587.0};
1602 double outputs_RM[kTableLength] = {18446744073709551617.0,
1603 4503599627370496.0, -4503599627370496.0,
1604 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
1605 1.7976931348623157E308, 0,
1606 309485009821345068724781057.0,
1607 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
1608 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
1609 37778931862957161709568.0, 37778931862957161709569.0,
1610 37778931862957161709580.0, 37778931862957161709581.0,
1611 37778931862957161709582.0, 37778931862957161709583.0,
1612 37778931862957161709584.0, 37778931862957161709585.0,
1613 37778931862957161709586.0, 37778931862957161709587.0};
1614 int fcsr_inputs[4] =
1615 {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf};
1616 double* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM};
1617 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)) );
1618 __ lw(t0, MemOperand(a0, offsetof(TestFloat, fcsr)) );
1619 __ cfc1(t1, FCSR);
1620 __ ctc1(t0, FCSR);
1621 __ rint_d(f8, f4);
1622 __ sdc1(f8, MemOperand(a0, offsetof(TestFloat, b)) );
1623 __ ctc1(t1, FCSR);
1624 __ jr(ra);
1625 __ nop();
1626
1627 CodeDesc desc;
1628 assm.GetCode(&desc);
1629 Handle<Code> code = isolate->factory()->NewCode(
1630 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1631 F3 f = FUNCTION_CAST<F3>(code->entry());
1632
1633 for (int j = 0; j < 4; j++) {
1634 test.fcsr = fcsr_inputs[j];
1635 for (int i = 0; i < kTableLength; i++) {
1636 test.a = inputs[i];
1637 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1638 CHECK_EQ(test.b, outputs[j][i]);
1639 }
1640 }
1641 }
1642}
1643
1644
1645TEST(sel) {
1646 if (IsMipsArchVariant(kMips32r6)) {
1647 CcTest::InitializeVM();
1648 Isolate* isolate = CcTest::i_isolate();
1649 HandleScope scope(isolate);
1650 MacroAssembler assm(isolate, NULL, 0,
1651 v8::internal::CodeObjectRequired::kYes);
1652
1653 typedef struct test {
1654 double dd;
1655 double ds;
1656 double dt;
1657 float fd;
1658 float fs;
1659 float ft;
1660 } Test;
1661
1662 Test test;
1663 __ ldc1(f0, MemOperand(a0, offsetof(Test, dd)) ); // test
1664 __ ldc1(f2, MemOperand(a0, offsetof(Test, ds)) ); // src1
1665 __ ldc1(f4, MemOperand(a0, offsetof(Test, dt)) ); // src2
1666 __ lwc1(f6, MemOperand(a0, offsetof(Test, fd)) ); // test
1667 __ lwc1(f8, MemOperand(a0, offsetof(Test, fs)) ); // src1
1668 __ lwc1(f10, MemOperand(a0, offsetof(Test, ft)) ); // src2
1669 __ sel_d(f0, f2, f4);
1670 __ sel_s(f6, f8, f10);
1671 __ sdc1(f0, MemOperand(a0, offsetof(Test, dd)) );
1672 __ swc1(f6, MemOperand(a0, offsetof(Test, fd)) );
1673 __ jr(ra);
1674 __ nop();
1675 CodeDesc desc;
1676 assm.GetCode(&desc);
1677 Handle<Code> code = isolate->factory()->NewCode(
1678 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1679 F3 f = FUNCTION_CAST<F3>(code->entry());
1680
1681 const int test_size = 3;
1682 const int input_size = 5;
1683
1684 double inputs_dt[input_size] = {0.0, 65.2, -70.32,
1685 18446744073709551621.0, -18446744073709551621.0};
1686 double inputs_ds[input_size] = {0.1, 69.88, -91.325,
1687 18446744073709551625.0, -18446744073709551625.0};
1688 float inputs_ft[input_size] = {0.0, 65.2, -70.32,
1689 18446744073709551621.0, -18446744073709551621.0};
1690 float inputs_fs[input_size] = {0.1, 69.88, -91.325,
1691 18446744073709551625.0, -18446744073709551625.0};
1692 double tests_D[test_size*2] = {2.8, 2.9, -2.8, -2.9,
1693 18446744073709551616.0, 18446744073709555712.0};
1694 float tests_S[test_size*2] = {2.9, 2.8, -2.9, -2.8,
1695 18446744073709551616.0, 18446746272732807168.0};
1696 for (int j=0; j < test_size; j+=2) {
1697 for (int i=0; i < input_size; i++) {
1698 test.dt = inputs_dt[i];
1699 test.dd = tests_D[j];
1700 test.ds = inputs_ds[i];
1701 test.ft = inputs_ft[i];
1702 test.fd = tests_S[j];
1703 test.fs = inputs_fs[i];
1704 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1705 CHECK_EQ(test.dd, inputs_ds[i]);
1706 CHECK_EQ(test.fd, inputs_fs[i]);
1707
1708 test.dd = tests_D[j+1];
1709 test.fd = tests_S[j+1];
1710 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1711 CHECK_EQ(test.dd, inputs_dt[i]);
1712 CHECK_EQ(test.fd, inputs_ft[i]);
1713 }
1714 }
1715 }
1716}
1717
1718
1719TEST(rint_s) {
1720 if (IsMipsArchVariant(kMips32r6)) {
1721 const int kTableLength = 30;
1722 CcTest::InitializeVM();
1723 Isolate* isolate = CcTest::i_isolate();
1724 HandleScope scope(isolate);
1725 MacroAssembler assm(isolate, NULL, 0,
1726 v8::internal::CodeObjectRequired::kYes);
1727
1728 typedef struct test_float {
1729 float a;
1730 float b;
1731 int fcsr;
1732 }TestFloat;
1733
1734 TestFloat test;
1735 float inputs[kTableLength] = {18446744073709551617.0,
1736 4503599627370496.0, -4503599627370496.0,
1737 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
1738 1.7976931348623157E+38, 6.27463370218383111104242366943E-37,
1739 309485009821345068724781056.89,
1740 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
1741 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
1742 37778931862957161709568.0, 37778931862957161709569.0,
1743 37778931862957161709580.0, 37778931862957161709581.0,
1744 37778931862957161709582.0, 37778931862957161709583.0,
1745 37778931862957161709584.0, 37778931862957161709585.0,
1746 37778931862957161709586.0, 37778931862957161709587.0};
1747 float outputs_RN[kTableLength] = {18446744073709551617.0,
1748 4503599627370496.0, -4503599627370496.0,
1749 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
1750 1.7976931348623157E38, 0,
1751 309485009821345068724781057.0,
1752 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
1753 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
1754 37778931862957161709568.0, 37778931862957161709569.0,
1755 37778931862957161709580.0, 37778931862957161709581.0,
1756 37778931862957161709582.0, 37778931862957161709583.0,
1757 37778931862957161709584.0, 37778931862957161709585.0,
1758 37778931862957161709586.0, 37778931862957161709587.0};
1759 float outputs_RZ[kTableLength] = {18446744073709551617.0,
1760 4503599627370496.0, -4503599627370496.0,
1761 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
1762 1.7976931348623157E38, 0,
1763 309485009821345068724781057.0,
1764 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
1765 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
1766 37778931862957161709568.0, 37778931862957161709569.0,
1767 37778931862957161709580.0, 37778931862957161709581.0,
1768 37778931862957161709582.0, 37778931862957161709583.0,
1769 37778931862957161709584.0, 37778931862957161709585.0,
1770 37778931862957161709586.0, 37778931862957161709587.0};
1771 float outputs_RP[kTableLength] = {18446744073709551617.0,
1772 4503599627370496.0, -4503599627370496.0,
1773 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
1774 1.7976931348623157E38, 1,
1775 309485009821345068724781057.0,
1776 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
1777 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
1778 37778931862957161709568.0, 37778931862957161709569.0,
1779 37778931862957161709580.0, 37778931862957161709581.0,
1780 37778931862957161709582.0, 37778931862957161709583.0,
1781 37778931862957161709584.0, 37778931862957161709585.0,
1782 37778931862957161709586.0, 37778931862957161709587.0};
1783 float outputs_RM[kTableLength] = {18446744073709551617.0,
1784 4503599627370496.0, -4503599627370496.0,
1785 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
1786 1.7976931348623157E38, 0,
1787 309485009821345068724781057.0,
1788 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
1789 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
1790 37778931862957161709568.0, 37778931862957161709569.0,
1791 37778931862957161709580.0, 37778931862957161709581.0,
1792 37778931862957161709582.0, 37778931862957161709583.0,
1793 37778931862957161709584.0, 37778931862957161709585.0,
1794 37778931862957161709586.0, 37778931862957161709587.0};
1795 int fcsr_inputs[4] =
1796 {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf};
1797 float* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM};
1798 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, a)) );
1799 __ lw(t0, MemOperand(a0, offsetof(TestFloat, fcsr)) );
1800 __ cfc1(t1, FCSR);
1801 __ ctc1(t0, FCSR);
1802 __ rint_s(f8, f4);
1803 __ swc1(f8, MemOperand(a0, offsetof(TestFloat, b)) );
1804 __ ctc1(t1, FCSR);
1805 __ jr(ra);
1806 __ nop();
1807
1808 CodeDesc desc;
1809 assm.GetCode(&desc);
1810 Handle<Code> code = isolate->factory()->NewCode(
1811 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1812 F3 f = FUNCTION_CAST<F3>(code->entry());
1813
1814 for (int j = 0; j < 4; j++) {
1815 test.fcsr = fcsr_inputs[j];
1816 for (int i = 0; i < kTableLength; i++) {
1817 test.a = inputs[i];
1818 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1819 CHECK_EQ(test.b, outputs[j][i]);
1820 }
1821 }
1822 }
1823}
1824
1825
1826TEST(Cvt_d_uw) {
1827 CcTest::InitializeVM();
1828 Isolate* isolate = CcTest::i_isolate();
1829 HandleScope scope(isolate);
1830 MacroAssembler assm(isolate, NULL, 0,
1831 v8::internal::CodeObjectRequired::kYes);
1832
1833 typedef struct test_struct {
1834 unsigned input;
1835 uint64_t output;
1836 } TestStruct;
1837
1838 unsigned inputs[] = {
1839 0x0, 0xffffffff, 0x80000000, 0x7fffffff
1840 };
1841
1842 uint64_t outputs[] = {
1843 0x0, 0x41efffffffe00000,
1844 0x41e0000000000000, 0x41dfffffffc00000
1845 };
1846
1847 int kTableLength = sizeof(inputs)/sizeof(inputs[0]);
1848
1849 TestStruct test;
1850
1851 __ lw(t1, MemOperand(a0, offsetof(TestStruct, input)));
1852 __ Cvt_d_uw(f4, t1, f6);
1853 __ sdc1(f4, MemOperand(a0, offsetof(TestStruct, output)));
1854 __ jr(ra);
1855 __ nop();
1856
1857 CodeDesc desc;
1858 assm.GetCode(&desc);
1859 Handle<Code> code = isolate->factory()->NewCode(
1860 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1861 F3 f = FUNCTION_CAST<F3>(code->entry());
1862 for (int i = 0; i < kTableLength; i++) {
1863 test.input = inputs[i];
1864 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1865 // Check outputs
1866 CHECK_EQ(test.output, outputs[i]);
1867 }
1868}
1869
1870
1871TEST(mina_maxa) {
1872 if (IsMipsArchVariant(kMips32r6)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001873 const int kTableLength = 23;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001874 CcTest::InitializeVM();
1875 Isolate* isolate = CcTest::i_isolate();
1876 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001877 MacroAssembler assm(isolate, nullptr, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001878 v8::internal::CodeObjectRequired::kYes);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001879 const double dnan = std::numeric_limits<double>::quiet_NaN();
1880 const double dinf = std::numeric_limits<double>::infinity();
1881 const double dminf = -std::numeric_limits<double>::infinity();
1882 const float fnan = std::numeric_limits<float>::quiet_NaN();
1883 const float finf = std::numeric_limits<float>::infinity();
1884 const float fminf = std::numeric_limits<float>::infinity();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001885
Ben Murdoch097c5b22016-05-18 11:27:45 +01001886 struct TestFloat {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001887 double a;
1888 double b;
1889 double resd;
1890 double resd1;
1891 float c;
1892 float d;
1893 float resf;
1894 float resf1;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001895 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001896
1897 TestFloat test;
1898 double inputsa[kTableLength] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001899 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9, -9.8, -10.0, -8.9, -9.8,
1900 dnan, 3.0, -0.0, 0.0, dinf, dnan, 42.0, dinf, dminf, dinf, dnan};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001901 double inputsb[kTableLength] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001902 4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8, 9.8, -9.8, -11.2, -9.8,
1903 3.0, dnan, 0.0, -0.0, dnan, dinf, dinf, 42.0, dinf, dminf, dnan};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001904 double resd[kTableLength] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001905 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9, -9.8, -9.8, -8.9, -9.8,
1906 3.0, 3.0, -0.0, -0.0, dinf, dinf, 42.0, 42.0, dminf, dminf, dnan};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001907 double resd1[kTableLength] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001908 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8, 9.8, -10.0, -11.2, -9.8,
1909 3.0, 3.0, 0.0, 0.0, dinf, dinf, dinf, dinf, dinf, dinf, dnan};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001910 float inputsc[kTableLength] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001911 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9, -9.8, -10.0, -8.9, -9.8,
1912 fnan, 3.0, -0.0, 0.0, finf, fnan, 42.0, finf, fminf, finf, fnan};
1913 float inputsd[kTableLength] = {4.8, 5.3, 6.1, -10.0, -8.9, -9.8,
1914 9.8, 9.8, 9.8, -9.8, -11.2, -9.8,
1915 3.0, fnan, -0.0, 0.0, fnan, finf,
1916 finf, 42.0, finf, fminf, fnan};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001917 float resf[kTableLength] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001918 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9, -9.8, -9.8, -8.9, -9.8,
1919 3.0, 3.0, -0.0, -0.0, finf, finf, 42.0, 42.0, fminf, fminf, fnan};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001920 float resf1[kTableLength] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001921 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8, 9.8, -10.0, -11.2, -9.8,
1922 3.0, 3.0, 0.0, 0.0, finf, finf, finf, finf, finf, finf, fnan};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001923
1924 __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
1925 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, b)) );
1926 __ lwc1(f8, MemOperand(a0, offsetof(TestFloat, c)) );
1927 __ lwc1(f10, MemOperand(a0, offsetof(TestFloat, d)) );
1928 __ mina_d(f6, f2, f4);
1929 __ mina_s(f12, f8, f10);
1930 __ maxa_d(f14, f2, f4);
1931 __ maxa_s(f16, f8, f10);
1932 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, resf)) );
1933 __ sdc1(f6, MemOperand(a0, offsetof(TestFloat, resd)) );
1934 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, resf1)) );
1935 __ sdc1(f14, MemOperand(a0, offsetof(TestFloat, resd1)) );
1936 __ jr(ra);
1937 __ nop();
1938
1939 CodeDesc desc;
1940 assm.GetCode(&desc);
1941 Handle<Code> code = isolate->factory()->NewCode(
1942 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1943 F3 f = FUNCTION_CAST<F3>(code->entry());
1944 for (int i = 0; i < kTableLength; i++) {
1945 test.a = inputsa[i];
1946 test.b = inputsb[i];
1947 test.c = inputsc[i];
1948 test.d = inputsd[i];
1949 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1950 if (i < kTableLength - 1) {
1951 CHECK_EQ(test.resd, resd[i]);
1952 CHECK_EQ(test.resf, resf[i]);
1953 CHECK_EQ(test.resd1, resd1[i]);
1954 CHECK_EQ(test.resf1, resf1[i]);
1955 } else {
1956 CHECK(std::isnan(test.resd));
1957 CHECK(std::isnan(test.resf));
1958 CHECK(std::isnan(test.resd1));
1959 CHECK(std::isnan(test.resf1));
1960 }
1961 }
1962 }
1963}
1964
1965
1966// ----------------------mips32r2 specific tests----------------------
1967TEST(trunc_l) {
1968 if (IsMipsArchVariant(kMips32r2) && IsFp64Mode()) {
1969 CcTest::InitializeVM();
1970 Isolate* isolate = CcTest::i_isolate();
1971 HandleScope scope(isolate);
1972 MacroAssembler assm(isolate, NULL, 0,
1973 v8::internal::CodeObjectRequired::kYes);
1974 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult);
1975 typedef struct test_float {
1976 uint32_t isNaN2008;
1977 double a;
1978 float b;
1979 int64_t c; // a trunc result
1980 int64_t d; // b trunc result
1981 }Test;
1982 const int kTableLength = 15;
1983 double inputs_D[kTableLength] = {
1984 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
1985 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
1986 2147483648.0,
1987 std::numeric_limits<double>::quiet_NaN(),
1988 std::numeric_limits<double>::infinity()
1989 };
1990 float inputs_S[kTableLength] = {
1991 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
1992 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
1993 2147483648.0,
1994 std::numeric_limits<float>::quiet_NaN(),
1995 std::numeric_limits<float>::infinity()
1996 };
1997 double outputs[kTableLength] = {
1998 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
1999 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
2000 2147483648.0, dFPU64InvalidResult,
2001 dFPU64InvalidResult};
2002 double outputsNaN2008[kTableLength] = {
2003 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2004 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
2005 2147483648.0,
2006 0,
2007 dFPU64InvalidResult};
2008
2009 __ cfc1(t1, FCSR);
2010 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
2011 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2012 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
2013 __ trunc_l_d(f8, f4);
2014 __ trunc_l_s(f10, f6);
2015 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) );
2016 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) );
2017 __ jr(ra);
2018 __ nop();
2019 Test test;
2020 CodeDesc desc;
2021 assm.GetCode(&desc);
2022 Handle<Code> code = isolate->factory()->NewCode(
2023 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2024 F3 f = FUNCTION_CAST<F3>(code->entry());
2025 for (int i = 0; i < kTableLength; i++) {
2026 test.a = inputs_D[i];
2027 test.b = inputs_S[i];
2028 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2029 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) &&
2030 kArchVariant == kMips32r6) {
2031 CHECK_EQ(test.c, outputsNaN2008[i]);
2032 } else {
2033 CHECK_EQ(test.c, outputs[i]);
2034 }
2035 CHECK_EQ(test.d, test.c);
2036 }
2037 }
2038}
2039
2040
2041TEST(movz_movn) {
2042 if (IsMipsArchVariant(kMips32r2)) {
2043 const int kTableLength = 4;
2044 CcTest::InitializeVM();
2045 Isolate* isolate = CcTest::i_isolate();
2046 HandleScope scope(isolate);
2047 MacroAssembler assm(isolate, NULL, 0,
2048 v8::internal::CodeObjectRequired::kYes);
2049
2050 typedef struct test_float {
2051 int64_t rt;
2052 double a;
2053 double b;
2054 double bold;
2055 double b1;
2056 double bold1;
2057 float c;
2058 float d;
2059 float dold;
2060 float d1;
2061 float dold1;
2062 }TestFloat;
2063
2064 TestFloat test;
2065 double inputs_D[kTableLength] = {
2066 5.3, -5.3, 5.3, -2.9
2067 };
2068 double inputs_S[kTableLength] = {
2069 4.8, 4.8, -4.8, -0.29
2070 };
2071
2072 float outputs_S[kTableLength] = {
2073 4.8, 4.8, -4.8, -0.29
2074 };
2075 double outputs_D[kTableLength] = {
2076 5.3, -5.3, 5.3, -2.9
2077 };
2078
2079 __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
2080 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, c)) );
2081 __ lw(t0, MemOperand(a0, offsetof(TestFloat, rt)) );
2082 __ Move(f12, 0.0);
2083 __ Move(f10, 0.0);
2084 __ Move(f16, 0.0);
2085 __ Move(f14, 0.0);
2086 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, bold)) );
2087 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, dold)) );
2088 __ sdc1(f16, MemOperand(a0, offsetof(TestFloat, bold1)) );
2089 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, dold1)) );
2090 __ movz_s(f10, f6, t0);
2091 __ movz_d(f12, f2, t0);
2092 __ movn_s(f14, f6, t0);
2093 __ movn_d(f16, f2, t0);
2094 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, d)) );
2095 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, b)) );
2096 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, d1)) );
2097 __ sdc1(f16, MemOperand(a0, offsetof(TestFloat, b1)) );
2098 __ jr(ra);
2099 __ nop();
2100
2101 CodeDesc desc;
2102 assm.GetCode(&desc);
2103 Handle<Code> code = isolate->factory()->NewCode(
2104 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2105 F3 f = FUNCTION_CAST<F3>(code->entry());
2106 for (int i = 0; i < kTableLength; i++) {
2107 test.a = inputs_D[i];
2108 test.c = inputs_S[i];
2109
2110 test.rt = 1;
2111 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2112 CHECK_EQ(test.b, test.bold);
2113 CHECK_EQ(test.d, test.dold);
2114 CHECK_EQ(test.b1, outputs_D[i]);
2115 CHECK_EQ(test.d1, outputs_S[i]);
2116
2117 test.rt = 0;
2118 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2119 CHECK_EQ(test.b, outputs_D[i]);
2120 CHECK_EQ(test.d, outputs_S[i]);
2121 CHECK_EQ(test.b1, test.bold1);
2122 CHECK_EQ(test.d1, test.dold1);
2123 }
2124 }
2125}
2126
2127
2128TEST(movt_movd) {
2129 if (IsMipsArchVariant(kMips32r2)) {
2130 const int kTableLength = 4;
2131 CcTest::InitializeVM();
2132 Isolate* isolate = CcTest::i_isolate();
2133
2134 typedef struct test_float {
2135 double srcd;
2136 double dstd;
2137 double dstdold;
2138 double dstd1;
2139 double dstdold1;
2140 float srcf;
2141 float dstf;
2142 float dstfold;
2143 float dstf1;
2144 float dstfold1;
2145 int32_t cc;
2146 int32_t fcsr;
2147 }TestFloat;
2148
2149 TestFloat test;
2150 double inputs_D[kTableLength] = {
2151 5.3, -5.3, 20.8, -2.9
2152 };
2153 double inputs_S[kTableLength] = {
2154 4.88, 4.8, -4.8, -0.29
2155 };
2156
2157 float outputs_S[kTableLength] = {
2158 4.88, 4.8, -4.8, -0.29
2159 };
2160 double outputs_D[kTableLength] = {
2161 5.3, -5.3, 20.8, -2.9
2162 };
2163 int condition_flags[8] = {0, 1, 2, 3, 4, 5, 6, 7};
2164
2165 for (int i = 0; i < kTableLength; i++) {
2166 test.srcd = inputs_D[i];
2167 test.srcf = inputs_S[i];
2168
2169 for (int j = 0; j< 8; j++) {
2170 test.cc = condition_flags[j];
2171 if (test.cc == 0) {
2172 test.fcsr = 1 << 23;
2173 } else {
2174 test.fcsr = 1 << (24+condition_flags[j]);
2175 }
2176 HandleScope scope(isolate);
2177 MacroAssembler assm(isolate, NULL, 0,
2178 v8::internal::CodeObjectRequired::kYes);
2179 __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, srcd)) );
2180 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, srcf)) );
2181 __ lw(t1, MemOperand(a0, offsetof(TestFloat, fcsr)) );
2182 __ cfc1(t0, FCSR);
2183 __ ctc1(t1, FCSR);
2184 __ li(t2, 0x0);
2185 __ mtc1(t2, f12);
2186 __ mtc1(t2, f10);
2187 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstdold)) );
2188 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstfold)) );
2189 __ movt_s(f12, f4, test.cc);
2190 __ movt_d(f10, f2, test.cc);
2191 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstf)) );
2192 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstd)) );
2193 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstdold1)) );
2194 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstfold1)) );
2195 __ movf_s(f12, f4, test.cc);
2196 __ movf_d(f10, f2, test.cc);
2197 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstf1)) );
2198 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstd1)) );
2199 __ ctc1(t0, FCSR);
2200 __ jr(ra);
2201 __ nop();
2202
2203 CodeDesc desc;
2204 assm.GetCode(&desc);
2205 Handle<Code> code = isolate->factory()->NewCode(
2206 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2207 F3 f = FUNCTION_CAST<F3>(code->entry());
2208
2209 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2210 CHECK_EQ(test.dstf, outputs_S[i]);
2211 CHECK_EQ(test.dstd, outputs_D[i]);
2212 CHECK_EQ(test.dstf1, test.dstfold1);
2213 CHECK_EQ(test.dstd1, test.dstdold1);
2214 test.fcsr = 0;
2215 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2216 CHECK_EQ(test.dstf, test.dstfold);
2217 CHECK_EQ(test.dstd, test.dstdold);
2218 CHECK_EQ(test.dstf1, outputs_S[i]);
2219 CHECK_EQ(test.dstd1, outputs_D[i]);
2220 }
2221 }
2222 }
2223}
2224
2225
2226// ----------------------tests for all archs--------------------------
2227TEST(cvt_w_d) {
2228 CcTest::InitializeVM();
2229 Isolate* isolate = CcTest::i_isolate();
2230 HandleScope scope(isolate);
2231 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2232
2233 typedef struct test_float {
2234 double a;
2235 int32_t b;
2236 int32_t fcsr;
2237 }Test;
2238 const int kTableLength = 24;
2239 double inputs[kTableLength] = {
2240 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2241 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2242 2147483637.0, 2147483638.0, 2147483639.0,
2243 2147483640.0, 2147483641.0, 2147483642.0,
2244 2147483643.0, 2147483644.0, 2147483645.0,
2245 2147483646.0, 2147483647.0, 2147483653.0
2246 };
2247 double outputs_RN[kTableLength] = {
2248 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
2249 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
2250 2147483637.0, 2147483638.0, 2147483639.0,
2251 2147483640.0, 2147483641.0, 2147483642.0,
2252 2147483643.0, 2147483644.0, 2147483645.0,
2253 2147483646.0, 2147483647.0, kFPUInvalidResult};
2254 double outputs_RZ[kTableLength] = {
2255 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2256 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
2257 2147483637.0, 2147483638.0, 2147483639.0,
2258 2147483640.0, 2147483641.0, 2147483642.0,
2259 2147483643.0, 2147483644.0, 2147483645.0,
2260 2147483646.0, 2147483647.0, kFPUInvalidResult};
2261 double outputs_RP[kTableLength] = {
2262 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
2263 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
2264 2147483637.0, 2147483638.0, 2147483639.0,
2265 2147483640.0, 2147483641.0, 2147483642.0,
2266 2147483643.0, 2147483644.0, 2147483645.0,
2267 2147483646.0, 2147483647.0, kFPUInvalidResult};
2268 double outputs_RM[kTableLength] = {
2269 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2270 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
2271 2147483637.0, 2147483638.0, 2147483639.0,
2272 2147483640.0, 2147483641.0, 2147483642.0,
2273 2147483643.0, 2147483644.0, 2147483645.0,
2274 2147483646.0, 2147483647.0, kFPUInvalidResult};
2275 int fcsr_inputs[4] =
2276 {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf};
2277 double* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM};
2278 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2279 __ lw(t0, MemOperand(a0, offsetof(Test, fcsr)) );
2280 __ cfc1(t1, FCSR);
2281 __ ctc1(t0, FCSR);
2282 __ cvt_w_d(f8, f4);
2283 __ swc1(f8, MemOperand(a0, offsetof(Test, b)) );
2284 __ ctc1(t1, FCSR);
2285 __ jr(ra);
2286 __ nop();
2287 Test test;
2288 CodeDesc desc;
2289 assm.GetCode(&desc);
2290 Handle<Code> code = isolate->factory()->NewCode(
2291 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2292 F3 f = FUNCTION_CAST<F3>(code->entry());
2293 for (int j = 0; j < 4; j++) {
2294 test.fcsr = fcsr_inputs[j];
2295 for (int i = 0; i < kTableLength; i++) {
2296 test.a = inputs[i];
2297 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2298 CHECK_EQ(test.b, outputs[j][i]);
2299 }
2300 }
2301}
2302
2303
2304TEST(trunc_w) {
2305 CcTest::InitializeVM();
2306 Isolate* isolate = CcTest::i_isolate();
2307 HandleScope scope(isolate);
2308 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2309
2310 typedef struct test_float {
2311 uint32_t isNaN2008;
2312 double a;
2313 float b;
2314 int32_t c; // a trunc result
2315 int32_t d; // b trunc result
2316 }Test;
2317 const int kTableLength = 15;
2318 double inputs_D[kTableLength] = {
2319 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2320 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2321 2147483648.0,
2322 std::numeric_limits<double>::quiet_NaN(),
2323 std::numeric_limits<double>::infinity()
2324 };
2325 float inputs_S[kTableLength] = {
2326 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2327 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2328 2147483648.0,
2329 std::numeric_limits<float>::quiet_NaN(),
2330 std::numeric_limits<float>::infinity()
2331 };
2332 double outputs[kTableLength] = {
2333 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2334 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
2335 kFPUInvalidResult, kFPUInvalidResult,
2336 kFPUInvalidResult};
2337 double outputsNaN2008[kTableLength] = {
2338 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2339 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
2340 kFPUInvalidResult,
2341 0,
2342 kFPUInvalidResult};
2343
2344 __ cfc1(t1, FCSR);
2345 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
2346 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2347 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
2348 __ trunc_w_d(f8, f4);
2349 __ trunc_w_s(f10, f6);
2350 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) );
2351 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) );
2352 __ jr(ra);
2353 __ nop();
2354 Test test;
2355 CodeDesc desc;
2356 assm.GetCode(&desc);
2357 Handle<Code> code = isolate->factory()->NewCode(
2358 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2359 F3 f = FUNCTION_CAST<F3>(code->entry());
2360 for (int i = 0; i < kTableLength; i++) {
2361 test.a = inputs_D[i];
2362 test.b = inputs_S[i];
2363 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2364 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips32r6) {
2365 CHECK_EQ(test.c, outputsNaN2008[i]);
2366 } else {
2367 CHECK_EQ(test.c, outputs[i]);
2368 }
2369 CHECK_EQ(test.d, test.c);
2370 }
2371}
2372
2373
2374TEST(round_w) {
2375 CcTest::InitializeVM();
2376 Isolate* isolate = CcTest::i_isolate();
2377 HandleScope scope(isolate);
2378 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2379
2380 typedef struct test_float {
2381 uint32_t isNaN2008;
2382 double a;
2383 float b;
2384 int32_t c; // a trunc result
2385 int32_t d; // b trunc result
2386 }Test;
2387 const int kTableLength = 15;
2388 double inputs_D[kTableLength] = {
2389 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2390 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2391 2147483648.0,
2392 std::numeric_limits<double>::quiet_NaN(),
2393 std::numeric_limits<double>::infinity()
2394 };
2395 float inputs_S[kTableLength] = {
2396 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2397 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2398 2147483648.0,
2399 std::numeric_limits<float>::quiet_NaN(),
2400 std::numeric_limits<float>::infinity()
2401 };
2402 double outputs[kTableLength] = {
2403 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
2404 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
2405 kFPUInvalidResult, kFPUInvalidResult,
2406 kFPUInvalidResult};
2407 double outputsNaN2008[kTableLength] = {
2408 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
2409 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
2410 kFPUInvalidResult, 0,
2411 kFPUInvalidResult};
2412
2413 __ cfc1(t1, FCSR);
2414 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
2415 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2416 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
2417 __ round_w_d(f8, f4);
2418 __ round_w_s(f10, f6);
2419 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) );
2420 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) );
2421 __ jr(ra);
2422 __ nop();
2423 Test test;
2424 CodeDesc desc;
2425 assm.GetCode(&desc);
2426 Handle<Code> code = isolate->factory()->NewCode(
2427 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2428 F3 f = FUNCTION_CAST<F3>(code->entry());
2429 for (int i = 0; i < kTableLength; i++) {
2430 test.a = inputs_D[i];
2431 test.b = inputs_S[i];
2432 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2433 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips32r6) {
2434 CHECK_EQ(test.c, outputsNaN2008[i]);
2435 } else {
2436 CHECK_EQ(test.c, outputs[i]);
2437 }
2438 CHECK_EQ(test.d, test.c);
2439 }
2440}
2441
2442
2443TEST(round_l) {
2444 if (IsFp64Mode()) {
2445 CcTest::InitializeVM();
2446 Isolate* isolate = CcTest::i_isolate();
2447 HandleScope scope(isolate);
2448 MacroAssembler assm(isolate, NULL, 0,
2449 v8::internal::CodeObjectRequired::kYes);
2450 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult);
2451 typedef struct test_float {
2452 uint32_t isNaN2008;
2453 double a;
2454 float b;
2455 int64_t c;
2456 int64_t d;
2457 }Test;
2458 const int kTableLength = 15;
2459 double inputs_D[kTableLength] = {
2460 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2461 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2462 2147483648.0,
2463 std::numeric_limits<double>::quiet_NaN(),
2464 std::numeric_limits<double>::infinity()
2465 };
2466 float inputs_S[kTableLength] = {
2467 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2468 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2469 2147483648.0,
2470 std::numeric_limits<float>::quiet_NaN(),
2471 std::numeric_limits<float>::infinity()
2472 };
2473 double outputs[kTableLength] = {
2474 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
2475 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
2476 2147483648.0, dFPU64InvalidResult,
2477 dFPU64InvalidResult};
2478 double outputsNaN2008[kTableLength] = {
2479 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
2480 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
2481 2147483648.0,
2482 0,
2483 dFPU64InvalidResult};
2484
2485 __ cfc1(t1, FCSR);
2486 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
2487 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2488 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
2489 __ round_l_d(f8, f4);
2490 __ round_l_s(f10, f6);
2491 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) );
2492 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) );
2493 __ jr(ra);
2494 __ nop();
2495 Test test;
2496 CodeDesc desc;
2497 assm.GetCode(&desc);
2498 Handle<Code> code = isolate->factory()->NewCode(
2499 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2500 F3 f = FUNCTION_CAST<F3>(code->entry());
2501 for (int i = 0; i < kTableLength; i++) {
2502 test.a = inputs_D[i];
2503 test.b = inputs_S[i];
2504 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2505 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) &&
2506 kArchVariant == kMips32r6) {
2507 CHECK_EQ(test.c, outputsNaN2008[i]);
2508 } else {
2509 CHECK_EQ(test.c, outputs[i]);
2510 }
2511 CHECK_EQ(test.d, test.c);
2512 }
2513 }
2514}
2515
2516
2517TEST(sub) {
2518 const int kTableLength = 12;
2519 CcTest::InitializeVM();
2520 Isolate* isolate = CcTest::i_isolate();
2521 HandleScope scope(isolate);
2522 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2523
2524 typedef struct test_float {
2525 float a;
2526 float b;
2527 float resultS;
2528 double c;
2529 double d;
2530 double resultD;
2531 }TestFloat;
2532
2533 TestFloat test;
2534 double inputfs_D[kTableLength] = {
2535 5.3, 4.8, 2.9, -5.3, -4.8, -2.9,
2536 5.3, 4.8, 2.9, -5.3, -4.8, -2.9
2537 };
2538 double inputft_D[kTableLength] = {
2539 4.8, 5.3, 2.9, 4.8, 5.3, 2.9,
2540 -4.8, -5.3, -2.9, -4.8, -5.3, -2.9
2541 };
2542 double outputs_D[kTableLength] = {
2543 0.5, -0.5, 0.0, -10.1, -10.1, -5.8,
2544 10.1, 10.1, 5.8, -0.5, 0.5, 0.0
2545 };
2546 float inputfs_S[kTableLength] = {
2547 5.3, 4.8, 2.9, -5.3, -4.8, -2.9,
2548 5.3, 4.8, 2.9, -5.3, -4.8, -2.9
2549 };
2550 float inputft_S[kTableLength] = {
2551 4.8, 5.3, 2.9, 4.8, 5.3, 2.9,
2552 -4.8, -5.3, -2.9, -4.8, -5.3, -2.9
2553 };
2554 float outputs_S[kTableLength] = {
2555 0.5, -0.5, 0.0, -10.1, -10.1, -5.8,
2556 10.1, 10.1, 5.8, -0.5, 0.5, 0.0
2557 };
2558 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
2559 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b)) );
2560 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) );
2561 __ ldc1(f10, MemOperand(a0, offsetof(TestFloat, d)) );
2562 __ sub_s(f6, f2, f4);
2563 __ sub_d(f12, f8, f10);
2564 __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) );
2565 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) );
2566 __ jr(ra);
2567 __ nop();
2568
2569 CodeDesc desc;
2570 assm.GetCode(&desc);
2571 Handle<Code> code = isolate->factory()->NewCode(
2572 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2573 F3 f = FUNCTION_CAST<F3>(code->entry());
2574 for (int i = 0; i < kTableLength; i++) {
2575 test.a = inputfs_S[i];
2576 test.b = inputft_S[i];
2577 test.c = inputfs_D[i];
2578 test.d = inputft_D[i];
2579 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2580 CHECK_EQ(test.resultS, outputs_S[i]);
2581 CHECK_EQ(test.resultD, outputs_D[i]);
2582 }
2583}
2584
2585
2586TEST(sqrt_rsqrt_recip) {
2587 const int kTableLength = 4;
2588 const double deltaDouble = 2E-15;
2589 const float deltaFloat = 2E-7;
2590 const float sqrt2_s = sqrt(2);
2591 const double sqrt2_d = sqrt(2);
2592 CcTest::InitializeVM();
2593 Isolate* isolate = CcTest::i_isolate();
2594 HandleScope scope(isolate);
2595 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2596
2597 typedef struct test_float {
2598 float a;
2599 float resultS;
2600 float resultS1;
2601 float resultS2;
2602 double c;
2603 double resultD;
2604 double resultD1;
2605 double resultD2;
2606 }TestFloat;
2607 TestFloat test;
2608
2609 double inputs_D[kTableLength] = {
2610 0.0L, 4.0L, 2.0L, 4e-28L
2611 };
2612
2613 double outputs_D[kTableLength] = {
2614 0.0L, 2.0L, sqrt2_d, 2e-14L
2615 };
2616 float inputs_S[kTableLength] = {
2617 0.0, 4.0, 2.0, 4e-28
2618 };
2619
2620 float outputs_S[kTableLength] = {
2621 0.0, 2.0, sqrt2_s, 2e-14
2622 };
2623
2624
2625 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
2626 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) );
2627 __ sqrt_s(f6, f2);
2628 __ sqrt_d(f12, f8);
2629
2630 if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
2631 __ rsqrt_d(f14, f8);
2632 __ rsqrt_s(f16, f2);
2633 __ recip_d(f18, f8);
2634 __ recip_s(f4, f2);
2635 }
2636 __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) );
2637 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) );
2638
2639 if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
2640 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, resultS1)) );
2641 __ sdc1(f14, MemOperand(a0, offsetof(TestFloat, resultD1)) );
2642 __ swc1(f4, MemOperand(a0, offsetof(TestFloat, resultS2)) );
2643 __ sdc1(f18, MemOperand(a0, offsetof(TestFloat, resultD2)) );
2644 }
2645 __ jr(ra);
2646 __ nop();
2647
2648 CodeDesc desc;
2649 assm.GetCode(&desc);
2650 Handle<Code> code = isolate->factory()->NewCode(
2651 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2652 F3 f = FUNCTION_CAST<F3>(code->entry());
2653
2654 for (int i = 0; i < kTableLength; i++) {
2655 float f1;
2656 double d1;
2657 test.a = inputs_S[i];
2658 test.c = inputs_D[i];
2659
2660 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2661
2662 CHECK_EQ(test.resultS, outputs_S[i]);
2663 CHECK_EQ(test.resultD, outputs_D[i]);
2664
2665 if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
2666 if (i != 0) {
2667 f1 = test.resultS1 - 1.0F/outputs_S[i];
2668 f1 = (f1 < 0) ? f1 : -f1;
2669 CHECK(f1 <= deltaFloat);
2670 d1 = test.resultD1 - 1.0L/outputs_D[i];
2671 d1 = (d1 < 0) ? d1 : -d1;
2672 CHECK(d1 <= deltaDouble);
2673 f1 = test.resultS2 - 1.0F/inputs_S[i];
2674 f1 = (f1 < 0) ? f1 : -f1;
2675 CHECK(f1 <= deltaFloat);
2676 d1 = test.resultD2 - 1.0L/inputs_D[i];
2677 d1 = (d1 < 0) ? d1 : -d1;
2678 CHECK(d1 <= deltaDouble);
2679 } else {
2680 CHECK_EQ(test.resultS1, 1.0F/outputs_S[i]);
2681 CHECK_EQ(test.resultD1, 1.0L/outputs_D[i]);
2682 CHECK_EQ(test.resultS2, 1.0F/inputs_S[i]);
2683 CHECK_EQ(test.resultD2, 1.0L/inputs_D[i]);
2684 }
2685 }
2686 }
2687}
2688
2689
2690TEST(neg) {
2691 const int kTableLength = 3;
2692 CcTest::InitializeVM();
2693 Isolate* isolate = CcTest::i_isolate();
2694 HandleScope scope(isolate);
2695 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2696
2697 typedef struct test_float {
2698 float a;
2699 float resultS;
2700 double c;
2701 double resultD;
2702 }TestFloat;
2703
2704 TestFloat test;
2705 double inputs_D[kTableLength] = {
2706 0.0, 4.0, -2.0
2707 };
2708
2709 double outputs_D[kTableLength] = {
2710 0.0, -4.0, 2.0
2711 };
2712 float inputs_S[kTableLength] = {
2713 0.0, 4.0, -2.0
2714 };
2715
2716 float outputs_S[kTableLength] = {
2717 0.0, -4.0, 2.0
2718 };
2719 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
2720 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) );
2721 __ neg_s(f6, f2);
2722 __ neg_d(f12, f8);
2723 __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) );
2724 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) );
2725 __ jr(ra);
2726 __ nop();
2727
2728 CodeDesc desc;
2729 assm.GetCode(&desc);
2730 Handle<Code> code = isolate->factory()->NewCode(
2731 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2732 F3 f = FUNCTION_CAST<F3>(code->entry());
2733 for (int i = 0; i < kTableLength; i++) {
2734 test.a = inputs_S[i];
2735 test.c = inputs_D[i];
2736 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2737 CHECK_EQ(test.resultS, outputs_S[i]);
2738 CHECK_EQ(test.resultD, outputs_D[i]);
2739 }
2740}
2741
2742
2743TEST(mul) {
2744 const int kTableLength = 4;
2745 CcTest::InitializeVM();
2746 Isolate* isolate = CcTest::i_isolate();
2747 HandleScope scope(isolate);
2748 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2749
2750 typedef struct test_float {
2751 float a;
2752 float b;
2753 float resultS;
2754 double c;
2755 double d;
2756 double resultD;
2757 }TestFloat;
2758
2759 TestFloat test;
2760 double inputfs_D[kTableLength] = {
2761 5.3, -5.3, 5.3, -2.9
2762 };
2763 double inputft_D[kTableLength] = {
2764 4.8, 4.8, -4.8, -0.29
2765 };
2766
2767 float inputfs_S[kTableLength] = {
2768 5.3, -5.3, 5.3, -2.9
2769 };
2770 float inputft_S[kTableLength] = {
2771 4.8, 4.8, -4.8, -0.29
2772 };
2773
2774 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
2775 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b)) );
2776 __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, c)) );
2777 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, d)) );
2778 __ mul_s(f10, f2, f4);
2779 __ mul_d(f12, f6, f8);
2780 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, resultS)) );
2781 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) );
2782 __ jr(ra);
2783 __ nop();
2784
2785 CodeDesc desc;
2786 assm.GetCode(&desc);
2787 Handle<Code> code = isolate->factory()->NewCode(
2788 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2789 F3 f = FUNCTION_CAST<F3>(code->entry());
2790 for (int i = 0; i < kTableLength; i++) {
2791 test.a = inputfs_S[i];
2792 test.b = inputft_S[i];
2793 test.c = inputfs_D[i];
2794 test.d = inputft_D[i];
2795 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2796 CHECK_EQ(test.resultS, inputfs_S[i]*inputft_S[i]);
2797 CHECK_EQ(test.resultD, inputfs_D[i]*inputft_D[i]);
2798 }
2799}
2800
2801
2802TEST(mov) {
2803 const int kTableLength = 4;
2804 CcTest::InitializeVM();
2805 Isolate* isolate = CcTest::i_isolate();
2806 HandleScope scope(isolate);
2807 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2808
2809 typedef struct test_float {
2810 double a;
2811 double b;
2812 float c;
2813 float d;
2814 }TestFloat;
2815
2816 TestFloat test;
2817 double inputs_D[kTableLength] = {
2818 5.3, -5.3, 5.3, -2.9
2819 };
2820 double inputs_S[kTableLength] = {
2821 4.8, 4.8, -4.8, -0.29
2822 };
2823
2824 float outputs_S[kTableLength] = {
2825 4.8, 4.8, -4.8, -0.29
2826 };
2827 double outputs_D[kTableLength] = {
2828 5.3, -5.3, 5.3, -2.9
2829 };
2830
2831 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)) );
2832 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, c)) );
2833 __ mov_s(f8, f6);
2834 __ mov_d(f10, f4);
2835 __ swc1(f8, MemOperand(a0, offsetof(TestFloat, d)) );
2836 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, b)) );
2837
2838 __ jr(ra);
2839 __ nop();
2840
2841 CodeDesc desc;
2842 assm.GetCode(&desc);
2843 Handle<Code> code = isolate->factory()->NewCode(
2844 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2845 F3 f = FUNCTION_CAST<F3>(code->entry());
2846 for (int i = 0; i < kTableLength; i++) {
2847 test.a = inputs_D[i];
2848 test.c = inputs_S[i];
2849
2850 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2851 CHECK_EQ(test.b, outputs_D[i]);
2852 CHECK_EQ(test.d, outputs_S[i]);
2853 }
2854}
2855
2856
2857TEST(floor_w) {
2858 CcTest::InitializeVM();
2859 Isolate* isolate = CcTest::i_isolate();
2860 HandleScope scope(isolate);
2861 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2862
2863 typedef struct test_float {
2864 uint32_t isNaN2008;
2865 double a;
2866 float b;
2867 int32_t c; // a floor result
2868 int32_t d; // b floor result
2869 }Test;
2870 const int kTableLength = 15;
2871 double inputs_D[kTableLength] = {
2872 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2873 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2874 2147483648.0,
2875 std::numeric_limits<double>::quiet_NaN(),
2876 std::numeric_limits<double>::infinity()
2877 };
2878 float inputs_S[kTableLength] = {
2879 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2880 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2881 2147483648.0,
2882 std::numeric_limits<float>::quiet_NaN(),
2883 std::numeric_limits<float>::infinity()
2884 };
2885 double outputs[kTableLength] = {
2886 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2887 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
2888 kFPUInvalidResult, kFPUInvalidResult,
2889 kFPUInvalidResult};
2890 double outputsNaN2008[kTableLength] = {
2891 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2892 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
2893 kFPUInvalidResult,
2894 0,
2895 kFPUInvalidResult};
2896
2897 __ cfc1(t1, FCSR);
2898 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
2899 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2900 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
2901 __ floor_w_d(f8, f4);
2902 __ floor_w_s(f10, f6);
2903 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) );
2904 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) );
2905 __ jr(ra);
2906 __ nop();
2907 Test test;
2908 CodeDesc desc;
2909 assm.GetCode(&desc);
2910 Handle<Code> code = isolate->factory()->NewCode(
2911 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2912 F3 f = FUNCTION_CAST<F3>(code->entry());
2913 for (int i = 0; i < kTableLength; i++) {
2914 test.a = inputs_D[i];
2915 test.b = inputs_S[i];
2916 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2917 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips32r6) {
2918 CHECK_EQ(test.c, outputsNaN2008[i]);
2919 } else {
2920 CHECK_EQ(test.c, outputs[i]);
2921 }
2922 CHECK_EQ(test.d, test.c);
2923 }
2924}
2925
2926
2927TEST(floor_l) {
2928 if (IsFp64Mode()) {
2929 CcTest::InitializeVM();
2930 Isolate* isolate = CcTest::i_isolate();
2931 HandleScope scope(isolate);
2932 MacroAssembler assm(isolate, NULL, 0,
2933 v8::internal::CodeObjectRequired::kYes);
2934 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult);
2935 typedef struct test_float {
2936 uint32_t isNaN2008;
2937 double a;
2938 float b;
2939 int64_t c;
2940 int64_t d;
2941 }Test;
2942 const int kTableLength = 15;
2943 double inputs_D[kTableLength] = {
2944 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2945 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2946 2147483648.0,
2947 std::numeric_limits<double>::quiet_NaN(),
2948 std::numeric_limits<double>::infinity()
2949 };
2950 float inputs_S[kTableLength] = {
2951 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2952 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2953 2147483648.0,
2954 std::numeric_limits<float>::quiet_NaN(),
2955 std::numeric_limits<float>::infinity()
2956 };
2957 double outputs[kTableLength] = {
2958 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2959 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
2960 2147483648.0, dFPU64InvalidResult,
2961 dFPU64InvalidResult};
2962 double outputsNaN2008[kTableLength] = {
2963 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2964 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
2965 2147483648.0,
2966 0,
2967 dFPU64InvalidResult};
2968
2969 __ cfc1(t1, FCSR);
2970 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
2971 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2972 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
2973 __ floor_l_d(f8, f4);
2974 __ floor_l_s(f10, f6);
2975 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) );
2976 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) );
2977 __ jr(ra);
2978 __ nop();
2979 Test test;
2980 CodeDesc desc;
2981 assm.GetCode(&desc);
2982 Handle<Code> code = isolate->factory()->NewCode(
2983 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2984 F3 f = FUNCTION_CAST<F3>(code->entry());
2985 for (int i = 0; i < kTableLength; i++) {
2986 test.a = inputs_D[i];
2987 test.b = inputs_S[i];
2988 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2989 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) &&
2990 kArchVariant == kMips32r6) {
2991 CHECK_EQ(test.c, outputsNaN2008[i]);
2992 } else {
2993 CHECK_EQ(test.c, outputs[i]);
2994 }
2995 CHECK_EQ(test.d, test.c);
2996 }
2997 }
2998}
2999
3000
3001TEST(ceil_w) {
3002 CcTest::InitializeVM();
3003 Isolate* isolate = CcTest::i_isolate();
3004 HandleScope scope(isolate);
3005 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
3006
3007 typedef struct test_float {
3008 uint32_t isNaN2008;
3009 double a;
3010 float b;
3011 int32_t c; // a floor result
3012 int32_t d; // b floor result
3013 }Test;
3014 const int kTableLength = 15;
3015 double inputs_D[kTableLength] = {
3016 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
3017 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
3018 2147483648.0,
3019 std::numeric_limits<double>::quiet_NaN(),
3020 std::numeric_limits<double>::infinity()
3021 };
3022 float inputs_S[kTableLength] = {
3023 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
3024 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
3025 2147483648.0,
3026 std::numeric_limits<float>::quiet_NaN(),
3027 std::numeric_limits<float>::infinity()
3028 };
3029 double outputs[kTableLength] = {
3030 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
3031 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
3032 kFPUInvalidResult, kFPUInvalidResult,
3033 kFPUInvalidResult};
3034 double outputsNaN2008[kTableLength] = {
3035 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
3036 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
3037 kFPUInvalidResult,
3038 0,
3039 kFPUInvalidResult};
3040
3041 __ cfc1(t1, FCSR);
3042 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
3043 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
3044 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
3045 __ ceil_w_d(f8, f4);
3046 __ ceil_w_s(f10, f6);
3047 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) );
3048 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) );
3049 __ jr(ra);
3050 __ nop();
3051 Test test;
3052 CodeDesc desc;
3053 assm.GetCode(&desc);
3054 Handle<Code> code = isolate->factory()->NewCode(
3055 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3056 F3 f = FUNCTION_CAST<F3>(code->entry());
3057 for (int i = 0; i < kTableLength; i++) {
3058 test.a = inputs_D[i];
3059 test.b = inputs_S[i];
3060 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3061 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips32r6) {
3062 CHECK_EQ(test.c, outputsNaN2008[i]);
3063 } else {
3064 CHECK_EQ(test.c, outputs[i]);
3065 }
3066 CHECK_EQ(test.d, test.c);
3067 }
3068}
3069
3070
3071TEST(ceil_l) {
3072 if (IsFp64Mode()) {
3073 CcTest::InitializeVM();
3074 Isolate* isolate = CcTest::i_isolate();
3075 HandleScope scope(isolate);
3076 MacroAssembler assm(isolate, NULL, 0,
3077 v8::internal::CodeObjectRequired::kYes);
3078 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult);
3079 typedef struct test_float {
3080 uint32_t isNaN2008;
3081 double a;
3082 float b;
3083 int64_t c;
3084 int64_t d;
3085 }Test;
3086 const int kTableLength = 15;
3087 double inputs_D[kTableLength] = {
3088 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
3089 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
3090 2147483648.0,
3091 std::numeric_limits<double>::quiet_NaN(),
3092 std::numeric_limits<double>::infinity()
3093 };
3094 float inputs_S[kTableLength] = {
3095 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
3096 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
3097 2147483648.0,
3098 std::numeric_limits<float>::quiet_NaN(),
3099 std::numeric_limits<float>::infinity()
3100 };
3101 double outputs[kTableLength] = {
3102 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
3103 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
3104 2147483648.0, dFPU64InvalidResult,
3105 dFPU64InvalidResult};
3106 double outputsNaN2008[kTableLength] = {
3107 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
3108 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
3109 2147483648.0,
3110 0,
3111 dFPU64InvalidResult};
3112
3113 __ cfc1(t1, FCSR);
3114 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
3115 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
3116 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
3117 __ ceil_l_d(f8, f4);
3118 __ ceil_l_s(f10, f6);
3119 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) );
3120 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) );
3121 __ jr(ra);
3122 __ nop();
3123 Test test;
3124 CodeDesc desc;
3125 assm.GetCode(&desc);
3126 Handle<Code> code = isolate->factory()->NewCode(
3127 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3128 F3 f = FUNCTION_CAST<F3>(code->entry());
3129 for (int i = 0; i < kTableLength; i++) {
3130 test.a = inputs_D[i];
3131 test.b = inputs_S[i];
3132 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3133 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) &&
3134 kArchVariant == kMips32r6) {
3135 CHECK_EQ(test.c, outputsNaN2008[i]);
3136 } else {
3137 CHECK_EQ(test.c, outputs[i]);
3138 }
3139 CHECK_EQ(test.d, test.c);
3140 }
3141 }
3142}
3143
3144
3145TEST(jump_tables1) {
3146 // Test jump tables with forward jumps.
3147 CcTest::InitializeVM();
3148 Isolate* isolate = CcTest::i_isolate();
3149 HandleScope scope(isolate);
3150 Assembler assm(isolate, nullptr, 0);
3151
3152 const int kNumCases = 512;
3153 int values[kNumCases];
3154 isolate->random_number_generator()->NextBytes(values, sizeof(values));
3155 Label labels[kNumCases];
3156
3157 __ addiu(sp, sp, -4);
3158 __ sw(ra, MemOperand(sp));
3159
3160 Label done;
3161 {
3162 __ BlockTrampolinePoolFor(kNumCases + 7);
3163 PredictableCodeSizeScope predictable(
3164 &assm, (kNumCases + 7) * Assembler::kInstrSize);
3165 Label here;
3166
3167 __ bal(&here);
3168 __ nop();
3169 __ bind(&here);
3170 __ sll(at, a0, 2);
3171 __ addu(at, at, ra);
3172 __ lw(at, MemOperand(at, 5 * Assembler::kInstrSize));
3173 __ jr(at);
3174 __ nop();
3175 for (int i = 0; i < kNumCases; ++i) {
3176 __ dd(&labels[i]);
3177 }
3178 }
3179
3180 for (int i = 0; i < kNumCases; ++i) {
3181 __ bind(&labels[i]);
3182 __ lui(v0, (values[i] >> 16) & 0xffff);
3183 __ ori(v0, v0, values[i] & 0xffff);
3184 __ b(&done);
3185 __ nop();
3186 }
3187
3188 __ bind(&done);
3189 __ lw(ra, MemOperand(sp));
3190 __ addiu(sp, sp, 4);
3191 __ jr(ra);
3192 __ nop();
3193
3194 CodeDesc desc;
3195 assm.GetCode(&desc);
3196 Handle<Code> code = isolate->factory()->NewCode(
3197 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3198#ifdef OBJECT_PRINT
3199 code->Print(std::cout);
3200#endif
3201 F1 f = FUNCTION_CAST<F1>(code->entry());
3202 for (int i = 0; i < kNumCases; ++i) {
3203 int res = reinterpret_cast<int>(
3204 CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0));
3205 ::printf("f(%d) = %d\n", i, res);
3206 CHECK_EQ(values[i], res);
3207 }
3208}
3209
3210
3211TEST(jump_tables2) {
3212 // Test jump tables with backward jumps.
3213 CcTest::InitializeVM();
3214 Isolate* isolate = CcTest::i_isolate();
3215 HandleScope scope(isolate);
3216 Assembler assm(isolate, nullptr, 0);
3217
3218 const int kNumCases = 512;
3219 int values[kNumCases];
3220 isolate->random_number_generator()->NextBytes(values, sizeof(values));
3221 Label labels[kNumCases];
3222
3223 __ addiu(sp, sp, -4);
3224 __ sw(ra, MemOperand(sp));
3225
3226 Label done, dispatch;
3227 __ b(&dispatch);
3228 __ nop();
3229
3230 for (int i = 0; i < kNumCases; ++i) {
3231 __ bind(&labels[i]);
3232 __ lui(v0, (values[i] >> 16) & 0xffff);
3233 __ ori(v0, v0, values[i] & 0xffff);
3234 __ b(&done);
3235 __ nop();
3236 }
3237
3238 __ bind(&dispatch);
3239 {
3240 __ BlockTrampolinePoolFor(kNumCases + 7);
3241 PredictableCodeSizeScope predictable(
3242 &assm, (kNumCases + 7) * Assembler::kInstrSize);
3243 Label here;
3244
3245 __ bal(&here);
3246 __ nop();
3247 __ bind(&here);
3248 __ sll(at, a0, 2);
3249 __ addu(at, at, ra);
3250 __ lw(at, MemOperand(at, 5 * Assembler::kInstrSize));
3251 __ jr(at);
3252 __ nop();
3253 for (int i = 0; i < kNumCases; ++i) {
3254 __ dd(&labels[i]);
3255 }
3256 }
3257
3258 __ bind(&done);
3259 __ lw(ra, MemOperand(sp));
3260 __ addiu(sp, sp, 4);
3261 __ jr(ra);
3262 __ nop();
3263
3264 CodeDesc desc;
3265 assm.GetCode(&desc);
3266 Handle<Code> code = isolate->factory()->NewCode(
3267 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3268#ifdef OBJECT_PRINT
3269 code->Print(std::cout);
3270#endif
3271 F1 f = FUNCTION_CAST<F1>(code->entry());
3272 for (int i = 0; i < kNumCases; ++i) {
3273 int res = reinterpret_cast<int>(
3274 CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0));
3275 ::printf("f(%d) = %d\n", i, res);
3276 CHECK_EQ(values[i], res);
3277 }
3278}
3279
3280
3281TEST(jump_tables3) {
3282 // Test jump tables with backward jumps and embedded heap objects.
3283 CcTest::InitializeVM();
3284 Isolate* isolate = CcTest::i_isolate();
3285 HandleScope scope(isolate);
3286 Assembler assm(isolate, nullptr, 0);
3287
3288 const int kNumCases = 256;
3289 Handle<Object> values[kNumCases];
3290 for (int i = 0; i < kNumCases; ++i) {
3291 double value = isolate->random_number_generator()->NextDouble();
3292 values[i] = isolate->factory()->NewHeapNumber(value, IMMUTABLE, TENURED);
3293 }
3294 Label labels[kNumCases];
3295 Object* obj;
3296 int32_t imm32;
3297
3298 __ addiu(sp, sp, -4);
3299 __ sw(ra, MemOperand(sp));
3300
3301 Label done, dispatch;
3302 __ b(&dispatch);
3303
3304
3305 for (int i = 0; i < kNumCases; ++i) {
3306 __ bind(&labels[i]);
3307 obj = *values[i];
3308 imm32 = reinterpret_cast<intptr_t>(obj);
3309 __ lui(v0, (imm32 >> 16) & 0xffff);
3310 __ ori(v0, v0, imm32 & 0xffff);
3311 __ b(&done);
3312 __ nop();
3313 }
3314
3315 __ bind(&dispatch);
3316 {
3317 __ BlockTrampolinePoolFor(kNumCases + 7);
3318 PredictableCodeSizeScope predictable(
3319 &assm, (kNumCases + 7) * Assembler::kInstrSize);
3320 Label here;
3321
3322 __ bal(&here);
3323 __ nop();
3324 __ bind(&here);
3325 __ sll(at, a0, 2);
3326 __ addu(at, at, ra);
3327 __ lw(at, MemOperand(at, 5 * Assembler::kInstrSize));
3328 __ jr(at);
3329 __ nop();
3330 for (int i = 0; i < kNumCases; ++i) {
3331 __ dd(&labels[i]);
3332 }
3333 }
3334
3335 __ bind(&done);
3336 __ lw(ra, MemOperand(sp));
3337 __ addiu(sp, sp, 4);
3338 __ jr(ra);
3339 __ nop();
3340
3341 CodeDesc desc;
3342 assm.GetCode(&desc);
3343 Handle<Code> code = isolate->factory()->NewCode(
3344 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3345#ifdef OBJECT_PRINT
3346 code->Print(std::cout);
3347#endif
3348 F1 f = FUNCTION_CAST<F1>(code->entry());
3349 for (int i = 0; i < kNumCases; ++i) {
3350 Handle<Object> result(
3351 CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0), isolate);
3352#ifdef OBJECT_PRINT
3353 ::printf("f(%d) = ", i);
3354 result->Print(std::cout);
3355 ::printf("\n");
3356#endif
3357 CHECK(values[i].is_identical_to(result));
3358 }
3359}
3360
3361
3362TEST(BITSWAP) {
3363 // Test BITSWAP
3364 if (IsMipsArchVariant(kMips32r6)) {
3365 CcTest::InitializeVM();
3366 Isolate* isolate = CcTest::i_isolate();
3367 HandleScope scope(isolate);
3368
3369 typedef struct {
3370 int32_t r1;
3371 int32_t r2;
3372 int32_t r3;
3373 int32_t r4;
3374 } T;
3375 T t;
3376
3377 Assembler assm(isolate, NULL, 0);
3378
3379 __ lw(a2, MemOperand(a0, offsetof(T, r1)));
3380 __ nop();
3381 __ bitswap(a1, a2);
3382 __ sw(a1, MemOperand(a0, offsetof(T, r1)));
3383
3384 __ lw(a2, MemOperand(a0, offsetof(T, r2)));
3385 __ nop();
3386 __ bitswap(a1, a2);
3387 __ sw(a1, MemOperand(a0, offsetof(T, r2)));
3388
3389 __ jr(ra);
3390 __ nop();
3391
3392 CodeDesc desc;
3393 assm.GetCode(&desc);
3394 Handle<Code> code = isolate->factory()->NewCode(
3395 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3396 F3 f = FUNCTION_CAST<F3>(code->entry());
3397 t.r1 = 0x781A15C3;
3398 t.r2 = 0x8B71FCDE;
3399 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
3400 USE(dummy);
3401
3402 CHECK_EQ(static_cast<int32_t>(0x1E58A8C3), t.r1);
3403 CHECK_EQ(static_cast<int32_t>(0xD18E3F7B), t.r2);
3404 }
3405}
3406
3407
3408TEST(class_fmt) {
3409 if (IsMipsArchVariant(kMips32r6)) {
3410 // Test CLASS.fmt instruction.
3411 CcTest::InitializeVM();
3412 Isolate* isolate = CcTest::i_isolate();
3413 HandleScope scope(isolate);
3414
3415 typedef struct {
3416 double dSignalingNan;
3417 double dQuietNan;
3418 double dNegInf;
3419 double dNegNorm;
3420 double dNegSubnorm;
3421 double dNegZero;
3422 double dPosInf;
3423 double dPosNorm;
3424 double dPosSubnorm;
3425 double dPosZero;
3426 float fSignalingNan;
3427 float fQuietNan;
3428 float fNegInf;
3429 float fNegNorm;
3430 float fNegSubnorm;
3431 float fNegZero;
3432 float fPosInf;
3433 float fPosNorm;
3434 float fPosSubnorm;
3435 float fPosZero; } T;
3436 T t;
3437
3438 // Create a function that accepts &t, and loads, manipulates, and stores
3439 // the doubles t.a ... t.f.
3440 MacroAssembler assm(isolate, NULL, 0,
3441 v8::internal::CodeObjectRequired::kYes);
3442
3443 __ ldc1(f4, MemOperand(a0, offsetof(T, dSignalingNan)));
3444 __ class_d(f6, f4);
3445 __ sdc1(f6, MemOperand(a0, offsetof(T, dSignalingNan)));
3446
3447 __ ldc1(f4, MemOperand(a0, offsetof(T, dQuietNan)));
3448 __ class_d(f6, f4);
3449 __ sdc1(f6, MemOperand(a0, offsetof(T, dQuietNan)));
3450
3451 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegInf)));
3452 __ class_d(f6, f4);
3453 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegInf)));
3454
3455 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegNorm)));
3456 __ class_d(f6, f4);
3457 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegNorm)));
3458
3459 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegSubnorm)));
3460 __ class_d(f6, f4);
3461 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegSubnorm)));
3462
3463 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegZero)));
3464 __ class_d(f6, f4);
3465 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegZero)));
3466
3467 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosInf)));
3468 __ class_d(f6, f4);
3469 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosInf)));
3470
3471 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosNorm)));
3472 __ class_d(f6, f4);
3473 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosNorm)));
3474
3475 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosSubnorm)));
3476 __ class_d(f6, f4);
3477 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosSubnorm)));
3478
3479 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosZero)));
3480 __ class_d(f6, f4);
3481 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosZero)));
3482
3483 // Testing instruction CLASS.S
3484 __ lwc1(f4, MemOperand(a0, offsetof(T, fSignalingNan)));
3485 __ class_s(f6, f4);
3486 __ swc1(f6, MemOperand(a0, offsetof(T, fSignalingNan)));
3487
3488 __ lwc1(f4, MemOperand(a0, offsetof(T, fQuietNan)));
3489 __ class_s(f6, f4);
3490 __ swc1(f6, MemOperand(a0, offsetof(T, fQuietNan)));
3491
3492 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegInf)));
3493 __ class_s(f6, f4);
3494 __ swc1(f6, MemOperand(a0, offsetof(T, fNegInf)));
3495
3496 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegNorm)));
3497 __ class_s(f6, f4);
3498 __ swc1(f6, MemOperand(a0, offsetof(T, fNegNorm)));
3499
3500 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegSubnorm)));
3501 __ class_s(f6, f4);
3502 __ swc1(f6, MemOperand(a0, offsetof(T, fNegSubnorm)));
3503
3504 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegZero)));
3505 __ class_s(f6, f4);
3506 __ swc1(f6, MemOperand(a0, offsetof(T, fNegZero)));
3507
3508 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosInf)));
3509 __ class_s(f6, f4);
3510 __ swc1(f6, MemOperand(a0, offsetof(T, fPosInf)));
3511
3512 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosNorm)));
3513 __ class_s(f6, f4);
3514 __ swc1(f6, MemOperand(a0, offsetof(T, fPosNorm)));
3515
3516 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosSubnorm)));
3517 __ class_s(f6, f4);
3518 __ swc1(f6, MemOperand(a0, offsetof(T, fPosSubnorm)));
3519
3520 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosZero)));
3521 __ class_s(f6, f4);
3522 __ swc1(f6, MemOperand(a0, offsetof(T, fPosZero)));
3523
3524 __ jr(ra);
3525 __ nop();
3526
3527 CodeDesc desc;
3528 assm.GetCode(&desc);
3529 Handle<Code> code = isolate->factory()->NewCode(
3530 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3531 F3 f = FUNCTION_CAST<F3>(code->entry());
3532
3533 t.dSignalingNan = std::numeric_limits<double>::signaling_NaN();
3534 t.dQuietNan = std::numeric_limits<double>::quiet_NaN();
3535 t.dNegInf = -1.0 / 0.0;
3536 t.dNegNorm = -5.0;
3537 t.dNegSubnorm = -DBL_MIN / 2.0;
3538 t.dNegZero = -0.0;
3539 t.dPosInf = 2.0 / 0.0;
3540 t.dPosNorm = 275.35;
3541 t.dPosSubnorm = DBL_MIN / 2.0;
3542 t.dPosZero = +0.0;
3543 // Float test values
3544
3545 t.fSignalingNan = std::numeric_limits<float>::signaling_NaN();
3546 t.fQuietNan = std::numeric_limits<float>::quiet_NaN();
3547 t.fNegInf = -0.5/0.0;
3548 t.fNegNorm = -FLT_MIN;
3549 t.fNegSubnorm = -FLT_MIN / 1.5;
3550 t.fNegZero = -0.0;
3551 t.fPosInf = 100000.0 / 0.0;
3552 t.fPosNorm = FLT_MAX;
3553 t.fPosSubnorm = FLT_MIN / 20.0;
3554 t.fPosZero = +0.0;
3555
3556 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
3557 USE(dummy);
3558 // Expected double results.
3559 CHECK_EQ(bit_cast<int64_t>(t.dSignalingNan), 0x001);
3560 CHECK_EQ(bit_cast<int64_t>(t.dQuietNan), 0x002);
3561 CHECK_EQ(bit_cast<int64_t>(t.dNegInf), 0x004);
3562 CHECK_EQ(bit_cast<int64_t>(t.dNegNorm), 0x008);
3563 CHECK_EQ(bit_cast<int64_t>(t.dNegSubnorm), 0x010);
3564 CHECK_EQ(bit_cast<int64_t>(t.dNegZero), 0x020);
3565 CHECK_EQ(bit_cast<int64_t>(t.dPosInf), 0x040);
3566 CHECK_EQ(bit_cast<int64_t>(t.dPosNorm), 0x080);
3567 CHECK_EQ(bit_cast<int64_t>(t.dPosSubnorm), 0x100);
3568 CHECK_EQ(bit_cast<int64_t>(t.dPosZero), 0x200);
3569
3570 // Expected float results.
3571 CHECK_EQ(bit_cast<int32_t>(t.fSignalingNan), 0x001);
3572 CHECK_EQ(bit_cast<int32_t>(t.fQuietNan), 0x002);
3573 CHECK_EQ(bit_cast<int32_t>(t.fNegInf), 0x004);
3574 CHECK_EQ(bit_cast<int32_t>(t.fNegNorm), 0x008);
3575 CHECK_EQ(bit_cast<int32_t>(t.fNegSubnorm), 0x010);
3576 CHECK_EQ(bit_cast<int32_t>(t.fNegZero), 0x020);
3577 CHECK_EQ(bit_cast<int32_t>(t.fPosInf), 0x040);
3578 CHECK_EQ(bit_cast<int32_t>(t.fPosNorm), 0x080);
3579 CHECK_EQ(bit_cast<int32_t>(t.fPosSubnorm), 0x100);
3580 CHECK_EQ(bit_cast<int32_t>(t.fPosZero), 0x200);
3581 }
3582}
3583
3584
3585TEST(ABS) {
3586 CcTest::InitializeVM();
3587 Isolate* isolate = CcTest::i_isolate();
3588 HandleScope scope(isolate);
3589 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
3590
3591 typedef struct test_float {
3592 int64_t fir;
3593 double a;
3594 float b;
3595 double fcsr;
3596 } TestFloat;
3597
3598 TestFloat test;
3599
3600 // Save FIR.
3601 __ cfc1(a1, FCSR);
3602 // Disable FPU exceptions.
3603 __ ctc1(zero_reg, FCSR);
3604
3605 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)));
3606 __ abs_d(f10, f4);
3607 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, a)));
3608
3609 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b)));
3610 __ abs_s(f10, f4);
3611 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, b)));
3612
3613 // Restore FCSR.
3614 __ ctc1(a1, FCSR);
3615
3616 __ jr(ra);
3617 __ nop();
3618
3619 CodeDesc desc;
3620 assm.GetCode(&desc);
3621 Handle<Code> code = isolate->factory()->NewCode(
3622 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3623 F3 f = FUNCTION_CAST<F3>(code->entry());
3624 test.a = -2.0;
3625 test.b = -2.0;
3626 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3627 CHECK_EQ(test.a, 2.0);
3628 CHECK_EQ(test.b, 2.0);
3629
3630 test.a = 2.0;
3631 test.b = 2.0;
3632 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3633 CHECK_EQ(test.a, 2.0);
3634 CHECK_EQ(test.b, 2.0);
3635
3636 // Testing biggest positive number
3637 test.a = std::numeric_limits<double>::max();
3638 test.b = std::numeric_limits<float>::max();
3639 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3640 CHECK_EQ(test.a, std::numeric_limits<double>::max());
3641 CHECK_EQ(test.b, std::numeric_limits<float>::max());
3642
3643 // Testing smallest negative number
3644 test.a = -std::numeric_limits<double>::max(); // lowest()
3645 test.b = -std::numeric_limits<float>::max(); // lowest()
3646 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3647 CHECK_EQ(test.a, std::numeric_limits<double>::max());
3648 CHECK_EQ(test.b, std::numeric_limits<float>::max());
3649
3650 // Testing smallest positive number
3651 test.a = -std::numeric_limits<double>::min();
3652 test.b = -std::numeric_limits<float>::min();
3653 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3654 CHECK_EQ(test.a, std::numeric_limits<double>::min());
3655 CHECK_EQ(test.b, std::numeric_limits<float>::min());
3656
3657 // Testing infinity
3658 test.a = -std::numeric_limits<double>::max()
3659 / std::numeric_limits<double>::min();
3660 test.b = -std::numeric_limits<float>::max()
3661 / std::numeric_limits<float>::min();
3662 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3663 CHECK_EQ(test.a, std::numeric_limits<double>::max()
3664 / std::numeric_limits<double>::min());
3665 CHECK_EQ(test.b, std::numeric_limits<float>::max()
3666 / std::numeric_limits<float>::min());
3667
3668 test.a = std::numeric_limits<double>::quiet_NaN();
3669 test.b = std::numeric_limits<float>::quiet_NaN();
3670 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3671 CHECK_EQ(std::isnan(test.a), true);
3672 CHECK_EQ(std::isnan(test.b), true);
3673
3674 test.a = std::numeric_limits<double>::signaling_NaN();
3675 test.b = std::numeric_limits<float>::signaling_NaN();
3676 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3677 CHECK_EQ(std::isnan(test.a), true);
3678 CHECK_EQ(std::isnan(test.b), true);
3679}
3680
3681
3682TEST(ADD_FMT) {
3683 CcTest::InitializeVM();
3684 Isolate* isolate = CcTest::i_isolate();
3685 HandleScope scope(isolate);
3686 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
3687
3688 typedef struct test_float {
3689 double a;
3690 double b;
3691 double c;
3692 float fa;
3693 float fb;
3694 float fc;
3695 } TestFloat;
3696
3697 TestFloat test;
3698
3699 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)));
3700 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b)));
3701 __ add_d(f10, f8, f4);
3702 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c)));
3703
3704 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, fa)));
3705 __ lwc1(f8, MemOperand(a0, offsetof(TestFloat, fb)));
3706 __ add_s(f10, f8, f4);
3707 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, fc)));
3708
3709 __ jr(ra);
3710 __ nop();
3711
3712 CodeDesc desc;
3713 assm.GetCode(&desc);
3714 Handle<Code> code = isolate->factory()->NewCode(
3715 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3716 F3 f = FUNCTION_CAST<F3>(code->entry());
3717 test.a = 2.0;
3718 test.b = 3.0;
3719 test.fa = 2.0;
3720 test.fb = 3.0;
3721 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3722 CHECK_EQ(test.c, 5.0);
3723 CHECK_EQ(test.fc, 5.0);
3724
3725 test.a = std::numeric_limits<double>::max();
3726 test.b = -std::numeric_limits<double>::max(); // lowest()
3727 test.fa = std::numeric_limits<float>::max();
3728 test.fb = -std::numeric_limits<float>::max(); // lowest()
3729 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3730 CHECK_EQ(test.c, 0.0);
3731 CHECK_EQ(test.fc, 0.0);
3732
3733 test.a = std::numeric_limits<double>::max();
3734 test.b = std::numeric_limits<double>::max();
3735 test.fa = std::numeric_limits<float>::max();
3736 test.fb = std::numeric_limits<float>::max();
3737 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3738 CHECK_EQ(std::isfinite(test.c), false);
3739 CHECK_EQ(std::isfinite(test.fc), false);
3740
3741 test.a = 5.0;
3742 test.b = std::numeric_limits<double>::signaling_NaN();
3743 test.fa = 5.0;
3744 test.fb = std::numeric_limits<float>::signaling_NaN();
3745 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3746 CHECK_EQ(std::isnan(test.c), true);
3747 CHECK_EQ(std::isnan(test.fc), true);
3748}
3749
3750
3751TEST(C_COND_FMT) {
3752 if ((IsMipsArchVariant(kMips32r1)) || (IsMipsArchVariant(kMips32r2))) {
3753 CcTest::InitializeVM();
3754 Isolate* isolate = CcTest::i_isolate();
3755 HandleScope scope(isolate);
3756 MacroAssembler assm(isolate, NULL, 0,
3757 v8::internal::CodeObjectRequired::kYes);
3758
3759 typedef struct test_float {
3760 double dOp1;
3761 double dOp2;
3762 uint32_t dF;
3763 uint32_t dUn;
3764 uint32_t dEq;
3765 uint32_t dUeq;
3766 uint32_t dOlt;
3767 uint32_t dUlt;
3768 uint32_t dOle;
3769 uint32_t dUle;
3770 float fOp1;
3771 float fOp2;
3772 uint32_t fF;
3773 uint32_t fUn;
3774 uint32_t fEq;
3775 uint32_t fUeq;
3776 uint32_t fOlt;
3777 uint32_t fUlt;
3778 uint32_t fOle;
3779 uint32_t fUle;
3780 } TestFloat;
3781
3782 TestFloat test;
3783
3784 __ li(t1, 1);
3785
3786 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, dOp1)));
3787 __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, dOp2)));
3788
3789 __ lwc1(f14, MemOperand(a0, offsetof(TestFloat, fOp1)));
3790 __ lwc1(f16, MemOperand(a0, offsetof(TestFloat, fOp2)));
3791
3792 __ mov(t2, zero_reg);
3793 __ mov(t3, zero_reg);
3794 __ c_d(F, f4, f6, 0);
3795 __ c_s(F, f14, f16, 2);
3796 __ movt(t2, t1, 0);
3797 __ movt(t3, t1, 2);
3798 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dF)) );
3799 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fF)) );
3800
3801 __ mov(t2, zero_reg);
3802 __ mov(t3, zero_reg);
3803 __ c_d(UN, f4, f6, 2);
3804 __ c_s(UN, f14, f16, 4);
3805 __ movt(t2, t1, 2);
3806 __ movt(t3, t1, 4);
3807 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUn)) );
3808 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUn)) );
3809
3810 __ mov(t2, zero_reg);
3811 __ mov(t3, zero_reg);
3812 __ c_d(EQ, f4, f6, 4);
3813 __ c_s(EQ, f14, f16, 6);
3814 __ movt(t2, t1, 4);
3815 __ movt(t3, t1, 6);
3816 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dEq)) );
3817 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fEq)) );
3818
3819 __ mov(t2, zero_reg);
3820 __ mov(t3, zero_reg);
3821 __ c_d(UEQ, f4, f6, 6);
3822 __ c_s(UEQ, f14, f16, 0);
3823 __ movt(t2, t1, 6);
3824 __ movt(t3, t1, 0);
3825 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUeq)) );
3826 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUeq)) );
3827
3828 __ mov(t2, zero_reg);
3829 __ mov(t3, zero_reg);
3830 __ c_d(OLT, f4, f6, 0);
3831 __ c_s(OLT, f14, f16, 2);
3832 __ movt(t2, t1, 0);
3833 __ movt(t3, t1, 2);
3834 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dOlt)) );
3835 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fOlt)) );
3836
3837 __ mov(t2, zero_reg);
3838 __ mov(t3, zero_reg);
3839 __ c_d(ULT, f4, f6, 2);
3840 __ c_s(ULT, f14, f16, 4);
3841 __ movt(t2, t1, 2);
3842 __ movt(t3, t1, 4);
3843 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUlt)) );
3844 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUlt)) );
3845
3846 __ mov(t2, zero_reg);
3847 __ mov(t3, zero_reg);
3848 __ c_d(OLE, f4, f6, 4);
3849 __ c_s(OLE, f14, f16, 6);
3850 __ movt(t2, t1, 4);
3851 __ movt(t3, t1, 6);
3852 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dOle)) );
3853 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fOle)) );
3854
3855 __ mov(t2, zero_reg);
3856 __ mov(t3, zero_reg);
3857 __ c_d(ULE, f4, f6, 6);
3858 __ c_s(ULE, f14, f16, 0);
3859 __ movt(t2, t1, 6);
3860 __ movt(t3, t1, 0);
3861 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUle)) );
3862 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUle)) );
3863
3864 __ jr(ra);
3865 __ nop();
3866
3867 CodeDesc desc;
3868 assm.GetCode(&desc);
3869 Handle<Code> code = isolate->factory()->NewCode(
3870 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3871 F3 f = FUNCTION_CAST<F3>(code->entry());
3872 test.dOp1 = 2.0;
3873 test.dOp2 = 3.0;
3874 test.fOp1 = 2.0;
3875 test.fOp2 = 3.0;
3876 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3877 CHECK_EQ(test.dF, 0U);
3878 CHECK_EQ(test.dUn, 0U);
3879 CHECK_EQ(test.dEq, 0U);
3880 CHECK_EQ(test.dUeq, 0U);
3881 CHECK_EQ(test.dOlt, 1U);
3882 CHECK_EQ(test.dUlt, 1U);
3883 CHECK_EQ(test.dOle, 1U);
3884 CHECK_EQ(test.dUle, 1U);
3885 CHECK_EQ(test.fF, 0U);
3886 CHECK_EQ(test.fUn, 0U);
3887 CHECK_EQ(test.fEq, 0U);
3888 CHECK_EQ(test.fUeq, 0U);
3889 CHECK_EQ(test.fOlt, 1U);
3890 CHECK_EQ(test.fUlt, 1U);
3891 CHECK_EQ(test.fOle, 1U);
3892 CHECK_EQ(test.fUle, 1U);
3893
3894 test.dOp1 = std::numeric_limits<double>::max();
3895 test.dOp2 = std::numeric_limits<double>::min();
3896 test.fOp1 = std::numeric_limits<float>::min();
3897 test.fOp2 = -std::numeric_limits<float>::max(); // lowest()
3898 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3899 CHECK_EQ(test.dF, 0U);
3900 CHECK_EQ(test.dUn, 0U);
3901 CHECK_EQ(test.dEq, 0U);
3902 CHECK_EQ(test.dUeq, 0U);
3903 CHECK_EQ(test.dOlt, 0U);
3904 CHECK_EQ(test.dUlt, 0U);
3905 CHECK_EQ(test.dOle, 0U);
3906 CHECK_EQ(test.dUle, 0U);
3907 CHECK_EQ(test.fF, 0U);
3908 CHECK_EQ(test.fUn, 0U);
3909 CHECK_EQ(test.fEq, 0U);
3910 CHECK_EQ(test.fUeq, 0U);
3911 CHECK_EQ(test.fOlt, 0U);
3912 CHECK_EQ(test.fUlt, 0U);
3913 CHECK_EQ(test.fOle, 0U);
3914 CHECK_EQ(test.fUle, 0U);
3915
3916 test.dOp1 = -std::numeric_limits<double>::max(); // lowest()
3917 test.dOp2 = -std::numeric_limits<double>::max(); // lowest()
3918 test.fOp1 = std::numeric_limits<float>::max();
3919 test.fOp2 = std::numeric_limits<float>::max();
3920 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3921 CHECK_EQ(test.dF, 0U);
3922 CHECK_EQ(test.dUn, 0U);
3923 CHECK_EQ(test.dEq, 1U);
3924 CHECK_EQ(test.dUeq, 1U);
3925 CHECK_EQ(test.dOlt, 0U);
3926 CHECK_EQ(test.dUlt, 0U);
3927 CHECK_EQ(test.dOle, 1U);
3928 CHECK_EQ(test.dUle, 1U);
3929 CHECK_EQ(test.fF, 0U);
3930 CHECK_EQ(test.fUn, 0U);
3931 CHECK_EQ(test.fEq, 1U);
3932 CHECK_EQ(test.fUeq, 1U);
3933 CHECK_EQ(test.fOlt, 0U);
3934 CHECK_EQ(test.fUlt, 0U);
3935 CHECK_EQ(test.fOle, 1U);
3936 CHECK_EQ(test.fUle, 1U);
3937
3938 test.dOp1 = std::numeric_limits<double>::quiet_NaN();
3939 test.dOp2 = 0.0;
3940 test.fOp1 = std::numeric_limits<float>::quiet_NaN();
3941 test.fOp2 = 0.0;
3942 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3943 CHECK_EQ(test.dF, 0U);
3944 CHECK_EQ(test.dUn, 1U);
3945 CHECK_EQ(test.dEq, 0U);
3946 CHECK_EQ(test.dUeq, 1U);
3947 CHECK_EQ(test.dOlt, 0U);
3948 CHECK_EQ(test.dUlt, 1U);
3949 CHECK_EQ(test.dOle, 0U);
3950 CHECK_EQ(test.dUle, 1U);
3951 CHECK_EQ(test.fF, 0U);
3952 CHECK_EQ(test.fUn, 1U);
3953 CHECK_EQ(test.fEq, 0U);
3954 CHECK_EQ(test.fUeq, 1U);
3955 CHECK_EQ(test.fOlt, 0U);
3956 CHECK_EQ(test.fUlt, 1U);
3957 CHECK_EQ(test.fOle, 0U);
3958 CHECK_EQ(test.fUle, 1U);
3959 }
3960}
3961
3962
3963TEST(CMP_COND_FMT) {
3964 if (IsMipsArchVariant(kMips32r6)) {
3965 CcTest::InitializeVM();
3966 Isolate* isolate = CcTest::i_isolate();
3967 HandleScope scope(isolate);
3968 MacroAssembler assm(isolate, NULL, 0,
3969 v8::internal::CodeObjectRequired::kYes);
3970
3971 typedef struct test_float {
3972 double dOp1;
3973 double dOp2;
3974 double dF;
3975 double dUn;
3976 double dEq;
3977 double dUeq;
3978 double dOlt;
3979 double dUlt;
3980 double dOle;
3981 double dUle;
3982 double dOr;
3983 double dUne;
3984 double dNe;
3985 float fOp1;
3986 float fOp2;
3987 float fF;
3988 float fUn;
3989 float fEq;
3990 float fUeq;
3991 float fOlt;
3992 float fUlt;
3993 float fOle;
3994 float fUle;
3995 float fOr;
3996 float fUne;
3997 float fNe;
3998 } TestFloat;
3999
4000 TestFloat test;
4001
4002 __ li(t1, 1);
4003
4004 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, dOp1)));
4005 __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, dOp2)));
4006
4007 __ lwc1(f14, MemOperand(a0, offsetof(TestFloat, fOp1)));
4008 __ lwc1(f16, MemOperand(a0, offsetof(TestFloat, fOp2)));
4009
4010 __ cmp_d(F, f2, f4, f6);
4011 __ cmp_s(F, f12, f14, f16);
4012 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dF)) );
4013 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fF)) );
4014
4015 __ cmp_d(UN, f2, f4, f6);
4016 __ cmp_s(UN, f12, f14, f16);
4017 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUn)) );
4018 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUn)) );
4019
4020 __ cmp_d(EQ, f2, f4, f6);
4021 __ cmp_s(EQ, f12, f14, f16);
4022 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dEq)) );
4023 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fEq)) );
4024
4025 __ cmp_d(UEQ, f2, f4, f6);
4026 __ cmp_s(UEQ, f12, f14, f16);
4027 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUeq)) );
4028 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUeq)) );
4029
4030 __ cmp_d(LT, f2, f4, f6);
4031 __ cmp_s(LT, f12, f14, f16);
4032 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOlt)) );
4033 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOlt)) );
4034
4035 __ cmp_d(ULT, f2, f4, f6);
4036 __ cmp_s(ULT, f12, f14, f16);
4037 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUlt)) );
4038 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUlt)) );
4039
4040 __ cmp_d(LE, f2, f4, f6);
4041 __ cmp_s(LE, f12, f14, f16);
4042 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOle)) );
4043 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOle)) );
4044
4045 __ cmp_d(ULE, f2, f4, f6);
4046 __ cmp_s(ULE, f12, f14, f16);
4047 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUle)) );
4048 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUle)) );
4049
4050 __ cmp_d(ORD, f2, f4, f6);
4051 __ cmp_s(ORD, f12, f14, f16);
4052 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOr)) );
4053 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOr)) );
4054
4055 __ cmp_d(UNE, f2, f4, f6);
4056 __ cmp_s(UNE, f12, f14, f16);
4057 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUne)) );
4058 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUne)) );
4059
4060 __ cmp_d(NE, f2, f4, f6);
4061 __ cmp_s(NE, f12, f14, f16);
4062 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dNe)) );
4063 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fNe)) );
4064
4065 __ jr(ra);
4066 __ nop();
4067
4068 CodeDesc desc;
4069 assm.GetCode(&desc);
4070 Handle<Code> code = isolate->factory()->NewCode(
4071 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4072 F3 f = FUNCTION_CAST<F3>(code->entry());
4073 uint64_t dTrue = 0xFFFFFFFFFFFFFFFF;
4074 uint64_t dFalse = 0x0000000000000000;
4075 uint32_t fTrue = 0xFFFFFFFF;
4076 uint32_t fFalse = 0x00000000;
4077
4078 test.dOp1 = 2.0;
4079 test.dOp2 = 3.0;
4080 test.fOp1 = 2.0;
4081 test.fOp2 = 3.0;
4082 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4083 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse);
4084 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse);
4085 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse);
4086 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dFalse);
4087 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dTrue);
4088 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dTrue);
4089 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dTrue);
4090 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue);
4091 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue);
4092 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue);
4093 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dTrue);
4094 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse);
4095 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse);
4096 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse);
4097 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fFalse);
4098 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fTrue);
4099 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fTrue);
4100 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fTrue);
4101 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue);
4102
4103 test.dOp1 = std::numeric_limits<double>::max();
4104 test.dOp2 = std::numeric_limits<double>::min();
4105 test.fOp1 = std::numeric_limits<float>::min();
4106 test.fOp2 = -std::numeric_limits<float>::max(); // lowest()
4107 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4108 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse);
4109 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse);
4110 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse);
4111 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dFalse);
4112 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse);
4113 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dFalse);
4114 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dFalse);
4115 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dFalse);
4116 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue);
4117 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue);
4118 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dTrue);
4119 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse);
4120 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse);
4121 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse);
4122 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fFalse);
4123 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse);
4124 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fFalse);
4125 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fFalse);
4126 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fFalse);
4127
4128 test.dOp1 = -std::numeric_limits<double>::max(); // lowest()
4129 test.dOp2 = -std::numeric_limits<double>::max(); // lowest()
4130 test.fOp1 = std::numeric_limits<float>::max();
4131 test.fOp2 = std::numeric_limits<float>::max();
4132 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4133 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse);
4134 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse);
4135 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dTrue);
4136 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dTrue);
4137 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse);
4138 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dFalse);
4139 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dTrue);
4140 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue);
4141 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue);
4142 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dFalse);
4143 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dFalse);
4144 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse);
4145 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse);
4146 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fTrue);
4147 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fTrue);
4148 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse);
4149 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fFalse);
4150 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fTrue);
4151 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue);
4152
4153 test.dOp1 = std::numeric_limits<double>::quiet_NaN();
4154 test.dOp2 = 0.0;
4155 test.fOp1 = std::numeric_limits<float>::quiet_NaN();
4156 test.fOp2 = 0.0;
4157 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4158 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse);
4159 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dTrue);
4160 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse);
4161 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dTrue);
4162 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse);
4163 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dTrue);
4164 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dFalse);
4165 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue);
4166 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dFalse);
4167 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue);
4168 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dFalse);
4169 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse);
4170 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fTrue);
4171 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse);
4172 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fTrue);
4173 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse);
4174 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fTrue);
4175 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fFalse);
4176 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue);
4177 }
4178}
4179
4180
4181TEST(CVT) {
4182 CcTest::InitializeVM();
4183 Isolate* isolate = CcTest::i_isolate();
4184 HandleScope scope(isolate);
4185 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4186
4187 typedef struct test_float {
4188 float cvt_d_s_in;
4189 double cvt_d_s_out;
4190 int32_t cvt_d_w_in;
4191 double cvt_d_w_out;
4192 int64_t cvt_d_l_in;
4193 double cvt_d_l_out;
4194
4195 float cvt_l_s_in;
4196 int64_t cvt_l_s_out;
4197 double cvt_l_d_in;
4198 int64_t cvt_l_d_out;
4199
4200 double cvt_s_d_in;
4201 float cvt_s_d_out;
4202 int32_t cvt_s_w_in;
4203 float cvt_s_w_out;
4204 int64_t cvt_s_l_in;
4205 float cvt_s_l_out;
4206
4207 float cvt_w_s_in;
4208 int32_t cvt_w_s_out;
4209 double cvt_w_d_in;
4210 int32_t cvt_w_d_out;
4211 } TestFloat;
4212
4213 TestFloat test;
4214
4215 // Save FCSR.
4216 __ cfc1(a1, FCSR);
4217 // Disable FPU exceptions.
4218 __ ctc1(zero_reg, FCSR);
4219
4220#define GENERATE_CVT_TEST(x, y, z) \
4221 __ y##c1(f0, MemOperand(a0, offsetof(TestFloat, x##_in))); \
4222 __ x(f0, f0); \
4223 __ nop(); \
4224 __ z##c1(f0, MemOperand(a0, offsetof(TestFloat, x##_out)));
4225
4226 GENERATE_CVT_TEST(cvt_d_s, lw, sd)
4227 GENERATE_CVT_TEST(cvt_d_w, lw, sd)
4228 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4229 IsFp64Mode()) {
4230 GENERATE_CVT_TEST(cvt_d_l, ld, sd)
4231 }
4232
4233 if (IsFp64Mode()) {
4234 GENERATE_CVT_TEST(cvt_l_s, lw, sd)
4235 GENERATE_CVT_TEST(cvt_l_d, ld, sd)
4236 }
4237
4238 GENERATE_CVT_TEST(cvt_s_d, ld, sw)
4239 GENERATE_CVT_TEST(cvt_s_w, lw, sw)
4240 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4241 IsFp64Mode()) {
4242 GENERATE_CVT_TEST(cvt_s_l, ld, sw)
4243 }
4244
4245 GENERATE_CVT_TEST(cvt_w_s, lw, sw)
4246 GENERATE_CVT_TEST(cvt_w_d, ld, sw)
4247
4248 // Restore FCSR.
4249 __ ctc1(a1, FCSR);
4250
4251 __ jr(ra);
4252 __ nop();
4253
4254 CodeDesc desc;
4255 assm.GetCode(&desc);
4256 Handle<Code> code = isolate->factory()->NewCode(
4257 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4258 F3 f = FUNCTION_CAST<F3>(code->entry());
4259
4260 test.cvt_d_s_in = -0.51;
4261 test.cvt_d_w_in = -1;
4262 test.cvt_d_l_in = -1;
4263 test.cvt_l_s_in = -0.51;
4264 test.cvt_l_d_in = -0.51;
4265 test.cvt_s_d_in = -0.51;
4266 test.cvt_s_w_in = -1;
4267 test.cvt_s_l_in = -1;
4268 test.cvt_w_s_in = -0.51;
4269 test.cvt_w_d_in = -0.51;
4270
4271 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4272 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
4273 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
4274 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4275 IsFp64Mode()) {
4276 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
4277 }
4278 if (IsFp64Mode()) {
4279 CHECK_EQ(test.cvt_l_s_out, -1);
4280 CHECK_EQ(test.cvt_l_d_out, -1);
4281 }
4282 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
4283 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
4284 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4285 IsFp64Mode()) {
4286 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
4287 }
4288 CHECK_EQ(test.cvt_w_s_out, -1);
4289 CHECK_EQ(test.cvt_w_d_out, -1);
4290
4291
4292 test.cvt_d_s_in = 0.49;
4293 test.cvt_d_w_in = 1;
4294 test.cvt_d_l_in = 1;
4295 test.cvt_l_s_in = 0.49;
4296 test.cvt_l_d_in = 0.49;
4297 test.cvt_s_d_in = 0.49;
4298 test.cvt_s_w_in = 1;
4299 test.cvt_s_l_in = 1;
4300 test.cvt_w_s_in = 0.49;
4301 test.cvt_w_d_in = 0.49;
4302
4303 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4304 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
4305 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
4306 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4307 IsFp64Mode()) {
4308 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
4309 }
4310 if (IsFp64Mode()) {
4311 CHECK_EQ(test.cvt_l_s_out, 0);
4312 CHECK_EQ(test.cvt_l_d_out, 0);
4313 }
4314 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
4315 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
4316 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4317 IsFp64Mode()) {
4318 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
4319 }
4320 CHECK_EQ(test.cvt_w_s_out, 0);
4321 CHECK_EQ(test.cvt_w_d_out, 0);
4322
4323 test.cvt_d_s_in = std::numeric_limits<float>::max();
4324 test.cvt_d_w_in = std::numeric_limits<int32_t>::max();
4325 test.cvt_d_l_in = std::numeric_limits<int64_t>::max();
4326 test.cvt_l_s_in = std::numeric_limits<float>::max();
4327 test.cvt_l_d_in = std::numeric_limits<double>::max();
4328 test.cvt_s_d_in = std::numeric_limits<double>::max();
4329 test.cvt_s_w_in = std::numeric_limits<int32_t>::max();
4330 test.cvt_s_l_in = std::numeric_limits<int64_t>::max();
4331 test.cvt_w_s_in = std::numeric_limits<float>::max();
4332 test.cvt_w_d_in = std::numeric_limits<double>::max();
4333
4334 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4335 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
4336 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
4337 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4338 IsFp64Mode()) {
4339 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
4340 }
4341 if (IsFp64Mode()) {
4342 CHECK_EQ(test.cvt_l_s_out, std::numeric_limits<int64_t>::max());
4343 CHECK_EQ(test.cvt_l_d_out, std::numeric_limits<int64_t>::max());
4344 }
4345 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
4346 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
4347 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4348 IsFp64Mode()) {
4349 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
4350 }
4351 CHECK_EQ(test.cvt_w_s_out, std::numeric_limits<int32_t>::max());
4352 CHECK_EQ(test.cvt_w_d_out, std::numeric_limits<int32_t>::max());
4353
4354
4355 test.cvt_d_s_in = -std::numeric_limits<float>::max(); // lowest()
4356 test.cvt_d_w_in = std::numeric_limits<int32_t>::min(); // lowest()
4357 test.cvt_d_l_in = std::numeric_limits<int64_t>::min(); // lowest()
4358 test.cvt_l_s_in = -std::numeric_limits<float>::max(); // lowest()
4359 test.cvt_l_d_in = -std::numeric_limits<double>::max(); // lowest()
4360 test.cvt_s_d_in = -std::numeric_limits<double>::max(); // lowest()
4361 test.cvt_s_w_in = std::numeric_limits<int32_t>::min(); // lowest()
4362 test.cvt_s_l_in = std::numeric_limits<int64_t>::min(); // lowest()
4363 test.cvt_w_s_in = -std::numeric_limits<float>::max(); // lowest()
4364 test.cvt_w_d_in = -std::numeric_limits<double>::max(); // lowest()
4365
4366 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4367 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
4368 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
4369 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4370 IsFp64Mode()) {
4371 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
4372 }
4373 // The returned value when converting from fixed-point to float-point
4374 // is not consistent between board, simulator and specification
4375 // in this test case, therefore modifying the test
4376 if (IsFp64Mode()) {
4377 CHECK(test.cvt_l_s_out == std::numeric_limits<int64_t>::min() ||
4378 test.cvt_l_s_out == std::numeric_limits<int64_t>::max());
4379 CHECK(test.cvt_l_d_out == std::numeric_limits<int64_t>::min() ||
4380 test.cvt_l_d_out == std::numeric_limits<int64_t>::max());
4381 }
4382 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
4383 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
4384 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4385 IsFp64Mode()) {
4386 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
4387 }
4388 CHECK(test.cvt_w_s_out == std::numeric_limits<int32_t>::min() ||
4389 test.cvt_w_s_out == std::numeric_limits<int32_t>::max());
4390 CHECK(test.cvt_w_d_out == std::numeric_limits<int32_t>::min() ||
4391 test.cvt_w_d_out == std::numeric_limits<int32_t>::max());
4392
4393
4394 test.cvt_d_s_in = std::numeric_limits<float>::min();
4395 test.cvt_d_w_in = std::numeric_limits<int32_t>::min();
4396 test.cvt_d_l_in = std::numeric_limits<int64_t>::min();
4397 test.cvt_l_s_in = std::numeric_limits<float>::min();
4398 test.cvt_l_d_in = std::numeric_limits<double>::min();
4399 test.cvt_s_d_in = std::numeric_limits<double>::min();
4400 test.cvt_s_w_in = std::numeric_limits<int32_t>::min();
4401 test.cvt_s_l_in = std::numeric_limits<int64_t>::min();
4402 test.cvt_w_s_in = std::numeric_limits<float>::min();
4403 test.cvt_w_d_in = std::numeric_limits<double>::min();
4404
4405 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4406 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
4407 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
4408 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4409 IsFp64Mode()) {
4410 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
4411 }
4412 if (IsFp64Mode()) {
4413 CHECK_EQ(test.cvt_l_s_out, 0);
4414 CHECK_EQ(test.cvt_l_d_out, 0);
4415 }
4416 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
4417 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
4418 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4419 IsFp64Mode()) {
4420 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
4421 }
4422 CHECK_EQ(test.cvt_w_s_out, 0);
4423 CHECK_EQ(test.cvt_w_d_out, 0);
4424}
4425
4426
4427TEST(DIV_FMT) {
4428 CcTest::InitializeVM();
4429 Isolate* isolate = CcTest::i_isolate();
4430 HandleScope scope(isolate);
4431 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4432
4433 typedef struct test {
4434 double dOp1;
4435 double dOp2;
4436 double dRes;
4437 float fOp1;
4438 float fOp2;
4439 float fRes;
4440 } Test;
4441
4442 Test test;
4443
4444 // Save FCSR.
4445 __ cfc1(a1, FCSR);
4446 // Disable FPU exceptions.
4447 __ ctc1(zero_reg, FCSR);
4448
4449 __ ldc1(f4, MemOperand(a0, offsetof(Test, dOp1)) );
4450 __ ldc1(f2, MemOperand(a0, offsetof(Test, dOp2)) );
4451 __ nop();
4452 __ div_d(f6, f4, f2);
4453 __ sdc1(f6, MemOperand(a0, offsetof(Test, dRes)) );
4454
4455 __ lwc1(f4, MemOperand(a0, offsetof(Test, fOp1)) );
4456 __ lwc1(f2, MemOperand(a0, offsetof(Test, fOp2)) );
4457 __ nop();
4458 __ div_s(f6, f4, f2);
4459 __ swc1(f6, MemOperand(a0, offsetof(Test, fRes)) );
4460
4461 // Restore FCSR.
4462 __ ctc1(a1, FCSR);
4463
4464 __ jr(ra);
4465 __ nop();
4466
4467 CodeDesc desc;
4468 assm.GetCode(&desc);
4469 Handle<Code> code = isolate->factory()->NewCode(
4470 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4471
4472 F3 f = FUNCTION_CAST<F3>(code->entry());
4473
4474 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4475
4476 const int test_size = 3;
4477
4478 double dOp1[test_size] = {
4479 5.0,
4480 DBL_MAX,
4481 DBL_MAX,
4482 };
4483 double dOp2[test_size] = {
4484 2.0,
4485 2.0,
4486 -DBL_MAX,
4487 };
4488 double dRes[test_size] = {
4489 2.5,
4490 DBL_MAX / 2.0,
4491 -1.0,
4492 };
4493 float fOp1[test_size] = {
4494 5.0,
4495 FLT_MAX,
4496 FLT_MAX,
4497 };
4498 float fOp2[test_size] = {
4499 2.0,
4500 2.0,
4501 -FLT_MAX,
4502 };
4503 float fRes[test_size] = {
4504 2.5,
4505 FLT_MAX / 2.0,
4506 -1.0,
4507 };
4508
4509 for (int i = 0; i < test_size; i++) {
4510 test.dOp1 = dOp1[i];
4511 test.dOp2 = dOp2[i];
4512 test.fOp1 = fOp1[i];
4513 test.fOp2 = fOp2[i];
4514
4515 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4516 CHECK_EQ(test.dRes, dRes[i]);
4517 CHECK_EQ(test.fRes, fRes[i]);
4518 }
4519
4520 test.dOp1 = DBL_MAX;
4521 test.dOp2 = -0.0;
4522 test.fOp1 = FLT_MAX;
4523 test.fOp2 = -0.0;
4524
4525 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4526 CHECK_EQ(false, std::isfinite(test.dRes));
4527 CHECK_EQ(false, std::isfinite(test.fRes));
4528
4529 test.dOp1 = 0.0;
4530 test.dOp2 = -0.0;
4531 test.fOp1 = 0.0;
4532 test.fOp2 = -0.0;
4533
4534 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4535 CHECK_EQ(true, std::isnan(test.dRes));
4536 CHECK_EQ(true, std::isnan(test.fRes));
4537
4538 test.dOp1 = std::numeric_limits<double>::quiet_NaN();
4539 test.dOp2 = -5.0;
4540 test.fOp1 = std::numeric_limits<float>::quiet_NaN();
4541 test.fOp2 = -5.0;
4542
4543 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4544 CHECK_EQ(true, std::isnan(test.dRes));
4545 CHECK_EQ(true, std::isnan(test.fRes));
4546}
4547
4548
4549uint32_t run_align(uint32_t rs_value, uint32_t rt_value, uint8_t bp) {
4550 Isolate* isolate = CcTest::i_isolate();
4551 HandleScope scope(isolate);
4552
4553 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4554
4555 __ align(v0, a0, a1, bp);
4556 __ jr(ra);
4557 __ nop();
4558
4559 CodeDesc desc;
4560 assm.GetCode(&desc);
4561 Handle<Code> code = isolate->factory()->NewCode(
4562 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4563
4564 F2 f = FUNCTION_CAST<F2>(code->entry());
4565
4566 uint32_t res = reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(
4567 isolate, f, rs_value, rt_value, 0, 0, 0));
4568
4569 return res;
4570}
4571
4572
4573TEST(r6_align) {
4574 if (IsMipsArchVariant(kMips32r6)) {
4575 CcTest::InitializeVM();
4576
4577 struct TestCaseAlign {
4578 uint32_t rs_value;
4579 uint32_t rt_value;
4580 uint8_t bp;
4581 uint32_t expected_res;
4582 };
4583
4584 struct TestCaseAlign tc[] = {
4585 // rs_value, rt_value, bp, expected_res
4586 { 0x11223344, 0xaabbccdd, 0, 0xaabbccdd },
4587 { 0x11223344, 0xaabbccdd, 1, 0xbbccdd11 },
4588 { 0x11223344, 0xaabbccdd, 2, 0xccdd1122 },
4589 { 0x11223344, 0xaabbccdd, 3, 0xdd112233 },
4590 };
4591
4592 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAlign);
4593 for (size_t i = 0; i < nr_test_cases; ++i) {
4594 CHECK_EQ(tc[i].expected_res, run_align(tc[i].rs_value,
4595 tc[i].rt_value, tc[i].bp));
4596 }
4597 }
4598}
4599
4600uint32_t PC; // The program counter.
4601
4602uint32_t run_aluipc(int16_t offset) {
4603 Isolate* isolate = CcTest::i_isolate();
4604 HandleScope scope(isolate);
4605
4606 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4607
4608 __ aluipc(v0, offset);
4609 __ jr(ra);
4610 __ nop();
4611
4612 CodeDesc desc;
4613 assm.GetCode(&desc);
4614 Handle<Code> code = isolate->factory()->NewCode(
4615 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4616
4617 F2 f = FUNCTION_CAST<F2>(code->entry());
4618 PC = (uint32_t) f; // Set the program counter.
4619
4620 uint32_t res = reinterpret_cast<uint32_t>(
4621 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
4622
4623 return res;
4624}
4625
4626
4627TEST(r6_aluipc) {
4628 if (IsMipsArchVariant(kMips32r6)) {
4629 CcTest::InitializeVM();
4630
4631 struct TestCaseAluipc {
4632 int16_t offset;
4633 };
4634
4635 struct TestCaseAluipc tc[] = {
4636 // offset
4637 { -32768 }, // 0x8000
4638 { -1 }, // 0xFFFF
4639 { 0 },
4640 { 1 },
4641 { 32767 }, // 0x7FFF
4642 };
4643
4644 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAluipc);
4645 for (size_t i = 0; i < nr_test_cases; ++i) {
4646 PC = 0;
4647 uint32_t res = run_aluipc(tc[i].offset);
4648 // Now, the program_counter (PC) is set.
4649 uint32_t expected_res = ~0x0FFFF & (PC + (tc[i].offset << 16));
4650 CHECK_EQ(expected_res, res);
4651 }
4652 }
4653}
4654
4655
4656uint32_t run_auipc(int16_t offset) {
4657 Isolate* isolate = CcTest::i_isolate();
4658 HandleScope scope(isolate);
4659
4660 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4661
4662 __ auipc(v0, offset);
4663 __ jr(ra);
4664 __ nop();
4665
4666 CodeDesc desc;
4667 assm.GetCode(&desc);
4668 Handle<Code> code = isolate->factory()->NewCode(
4669 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4670
4671 F2 f = FUNCTION_CAST<F2>(code->entry());
4672 PC = (uint32_t) f; // Set the program counter.
4673
4674 uint32_t res = reinterpret_cast<uint32_t>(
4675 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
4676
4677 return res;
4678}
4679
4680
4681TEST(r6_auipc) {
4682 if (IsMipsArchVariant(kMips32r6)) {
4683 CcTest::InitializeVM();
4684
4685 struct TestCaseAuipc {
4686 int16_t offset;
4687 };
4688
4689 struct TestCaseAuipc tc[] = {
4690 // offset
4691 { -32768 }, // 0x8000
4692 { -1 }, // 0xFFFF
4693 { 0 },
4694 { 1 },
4695 { 32767 }, // 0x7FFF
4696 };
4697
4698 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAuipc);
4699 for (size_t i = 0; i < nr_test_cases; ++i) {
4700 PC = 0;
4701 uint32_t res = run_auipc(tc[i].offset);
4702 // Now, the program_counter (PC) is set.
4703 uint32_t expected_res = PC + (tc[i].offset << 16);
4704 CHECK_EQ(expected_res, res);
4705 }
4706 }
4707}
4708
4709
4710uint32_t run_lwpc(int offset) {
4711 Isolate* isolate = CcTest::i_isolate();
4712 HandleScope scope(isolate);
4713
4714 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4715
4716 // 256k instructions; 2^8k
4717 // addiu t7, t0, 0xffff; (0x250fffff)
4718 // ...
4719 // addiu t4, t0, 0x0000; (0x250c0000)
4720 uint32_t addiu_start_1 = 0x25000000;
4721 for (int32_t i = 0xfffff; i >= 0xc0000; --i) {
4722 uint32_t addiu_new = addiu_start_1 + i;
4723 __ dd(addiu_new);
4724 }
4725
4726 __ lwpc(t8, offset); // offset 0; 0xef080000 (t8 register)
4727 __ mov(v0, t8);
4728
4729 // 256k instructions; 2^8k
4730 // addiu t0, t0, 0x0000; (0x25080000)
4731 // ...
4732 // addiu t3, t0, 0xffff; (0x250bffff)
4733 uint32_t addiu_start_2 = 0x25000000;
4734 for (int32_t i = 0x80000; i <= 0xbffff; ++i) {
4735 uint32_t addiu_new = addiu_start_2 + i;
4736 __ dd(addiu_new);
4737 }
4738
4739 __ jr(ra);
4740 __ nop();
4741
4742 CodeDesc desc;
4743 assm.GetCode(&desc);
4744 Handle<Code> code = isolate->factory()->NewCode(
4745 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4746
4747 F2 f = FUNCTION_CAST<F2>(code->entry());
4748
4749 uint32_t res = reinterpret_cast<uint32_t>(
4750 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
4751
4752 return res;
4753}
4754
4755
4756TEST(r6_lwpc) {
4757 if (IsMipsArchVariant(kMips32r6)) {
4758 CcTest::InitializeVM();
4759
4760 struct TestCaseLwpc {
4761 int offset;
4762 uint32_t expected_res;
4763 };
4764
4765 struct TestCaseLwpc tc[] = {
4766 // offset, expected_res
4767 { -262144, 0x250fffff }, // offset 0x40000
4768 { -4, 0x250c0003 },
4769 { -1, 0x250c0000 },
4770 { 0, 0xef080000 },
4771 { 1, 0x03001025 }, // mov(v0, t8)
4772 { 2, 0x25080000 },
4773 { 4, 0x25080002 },
4774 { 262143, 0x250bfffd }, // offset 0x3ffff
4775 };
4776
4777 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLwpc);
4778 for (size_t i = 0; i < nr_test_cases; ++i) {
4779 uint32_t res = run_lwpc(tc[i].offset);
4780 CHECK_EQ(tc[i].expected_res, res);
4781 }
4782 }
4783}
4784
4785
4786uint32_t run_jic(int16_t offset) {
4787 Isolate* isolate = CcTest::i_isolate();
4788 HandleScope scope(isolate);
4789
4790 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4791
4792 Label get_program_counter, stop_execution;
4793 __ push(ra);
4794 __ li(v0, 0);
4795 __ li(t1, 0x66);
4796
4797 __ addiu(v0, v0, 0x1); // <-- offset = -32
4798 __ addiu(v0, v0, 0x2);
4799 __ addiu(v0, v0, 0x10);
4800 __ addiu(v0, v0, 0x20);
4801 __ beq(v0, t1, &stop_execution);
4802 __ nop();
4803
4804 __ bal(&get_program_counter); // t0 <- program counter
4805 __ nop();
4806 __ jic(t0, offset);
4807
4808 __ addiu(v0, v0, 0x100);
4809 __ addiu(v0, v0, 0x200);
4810 __ addiu(v0, v0, 0x1000);
4811 __ addiu(v0, v0, 0x2000); // <--- offset = 16
4812 __ pop(ra);
4813 __ jr(ra);
4814 __ nop();
4815
4816 __ bind(&get_program_counter);
4817 __ mov(t0, ra);
4818 __ jr(ra);
4819 __ nop();
4820
4821 __ bind(&stop_execution);
4822 __ pop(ra);
4823 __ jr(ra);
4824 __ nop();
4825
4826 CodeDesc desc;
4827 assm.GetCode(&desc);
4828 Handle<Code> code = isolate->factory()->NewCode(
4829 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4830
4831 F2 f = FUNCTION_CAST<F2>(code->entry());
4832
4833 uint32_t res = reinterpret_cast<uint32_t>(
4834 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
4835
4836 return res;
4837}
4838
4839
4840TEST(r6_jic) {
4841 if (IsMipsArchVariant(kMips32r6)) {
4842 CcTest::InitializeVM();
4843
4844 struct TestCaseJic {
4845 // As rt will be used t0 register which will have value of
4846 // the program counter for the jic instruction.
4847 int16_t offset;
4848 uint32_t expected_res;
4849 };
4850
4851 struct TestCaseJic tc[] = {
4852 // offset, expected_result
4853 { 16, 0x2033 },
4854 { 4, 0x3333 },
4855 { -32, 0x66 },
4856 };
4857
4858 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJic);
4859 for (size_t i = 0; i < nr_test_cases; ++i) {
4860 uint32_t res = run_jic(tc[i].offset);
4861 CHECK_EQ(tc[i].expected_res, res);
4862 }
4863 }
4864}
4865
4866
4867uint64_t run_beqzc(int32_t value, int32_t offset) {
4868 Isolate* isolate = CcTest::i_isolate();
4869 HandleScope scope(isolate);
4870
4871 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4872
4873 Label stop_execution;
4874 __ li(v0, 0);
4875 __ li(t1, 0x66);
4876
4877 __ addiu(v0, v0, 0x1); // <-- offset = -32
4878 __ addiu(v0, v0, 0x2);
4879 __ addiu(v0, v0, 0x10);
4880 __ addiu(v0, v0, 0x20);
4881 __ beq(v0, t1, &stop_execution);
4882 __ nop();
4883
4884 __ beqzc(a0, offset); // BEQZC rs, offset
4885
4886 __ addiu(v0, v0, 0x1);
4887 __ addiu(v0, v0, 0x100);
4888 __ addiu(v0, v0, 0x200);
4889 __ addiu(v0, v0, 0x1000);
4890 __ addiu(v0, v0, 0x2000); // <--- offset = 16
4891 __ jr(ra);
4892 __ nop();
4893
4894 __ bind(&stop_execution);
4895 __ jr(ra);
4896 __ nop();
4897
4898 CodeDesc desc;
4899 assm.GetCode(&desc);
4900 Handle<Code> code = isolate->factory()->NewCode(
4901 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4902
4903 F2 f = FUNCTION_CAST<F2>(code->entry());
4904
4905 uint32_t res = reinterpret_cast<uint32_t>(
4906 CALL_GENERATED_CODE(isolate, f, value, 0, 0, 0, 0));
4907
4908 return res;
4909}
4910
4911
4912TEST(r6_beqzc) {
4913 if (IsMipsArchVariant(kMips32r6)) {
4914 CcTest::InitializeVM();
4915
4916 struct TestCaseBeqzc {
4917 uint32_t value;
4918 int32_t offset;
4919 uint32_t expected_res;
4920 };
4921
4922 struct TestCaseBeqzc tc[] = {
4923 // value, offset, expected_res
4924 { 0x0, -8, 0x66 },
4925 { 0x0, 0, 0x3334 },
4926 { 0x0, 1, 0x3333 },
4927 { 0xabc, 1, 0x3334 },
4928 { 0x0, 4, 0x2033 },
4929 };
4930
4931 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBeqzc);
4932 for (size_t i = 0; i < nr_test_cases; ++i) {
4933 uint32_t res = run_beqzc(tc[i].value, tc[i].offset);
4934 CHECK_EQ(tc[i].expected_res, res);
4935 }
4936 }
4937}
4938
4939
4940uint32_t run_jialc(int16_t offset) {
4941 Isolate* isolate = CcTest::i_isolate();
4942 HandleScope scope(isolate);
4943
4944 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4945
4946 Label main_block, get_program_counter;
4947 __ push(ra);
4948 __ li(v0, 0);
4949 __ beq(v0, v0, &main_block);
4950 __ nop();
4951
4952 // Block 1
4953 __ addiu(v0, v0, 0x1); // <-- offset = -40
4954 __ addiu(v0, v0, 0x2);
4955 __ jr(ra);
4956 __ nop();
4957
4958 // Block 2
4959 __ addiu(v0, v0, 0x10); // <-- offset = -24
4960 __ addiu(v0, v0, 0x20);
4961 __ jr(ra);
4962 __ nop();
4963
4964 // Block 3 (Main)
4965 __ bind(&main_block);
4966 __ bal(&get_program_counter); // t0 <- program counter
4967 __ nop();
4968 __ jialc(t0, offset);
4969 __ addiu(v0, v0, 0x4);
4970 __ pop(ra);
4971 __ jr(ra);
4972 __ nop();
4973
4974 // Block 4
4975 __ addiu(v0, v0, 0x100); // <-- offset = 20
4976 __ addiu(v0, v0, 0x200);
4977 __ jr(ra);
4978 __ nop();
4979
4980 // Block 5
4981 __ addiu(v0, v0, 0x1000); // <--- offset = 36
4982 __ addiu(v0, v0, 0x2000);
4983 __ jr(ra);
4984 __ nop();
4985
4986 __ bind(&get_program_counter);
4987 __ mov(t0, ra);
4988 __ jr(ra);
4989 __ nop();
4990
4991
4992 CodeDesc desc;
4993 assm.GetCode(&desc);
4994 Handle<Code> code = isolate->factory()->NewCode(
4995 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4996
4997 F2 f = FUNCTION_CAST<F2>(code->entry());
4998
4999 uint32_t res = reinterpret_cast<uint32_t>(
5000 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5001
5002 return res;
5003}
5004
5005
5006TEST(r6_jialc) {
5007 if (IsMipsArchVariant(kMips32r6)) {
5008 CcTest::InitializeVM();
5009
5010 struct TestCaseJialc {
5011 int16_t offset;
5012 uint32_t expected_res;
5013 };
5014
5015 struct TestCaseJialc tc[] = {
5016 // offset, expected_res
5017 { -40, 0x7 },
5018 { -24, 0x34 },
5019 { 20, 0x304 },
5020 { 36, 0x3004 }
5021 };
5022
5023 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJialc);
5024 for (size_t i = 0; i < nr_test_cases; ++i) {
5025 uint32_t res = run_jialc(tc[i].offset);
5026 CHECK_EQ(tc[i].expected_res, res);
5027 }
5028 }
5029}
5030
Ben Murdoch097c5b22016-05-18 11:27:45 +01005031static uint32_t run_addiupc(int32_t imm19) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005032 Isolate* isolate = CcTest::i_isolate();
5033 HandleScope scope(isolate);
5034
5035 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5036
5037 __ addiupc(v0, imm19);
5038 __ jr(ra);
5039 __ nop();
5040
5041 CodeDesc desc;
5042 assm.GetCode(&desc);
5043 Handle<Code> code = isolate->factory()->NewCode(
5044 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5045
5046 F2 f = FUNCTION_CAST<F2>(code->entry());
5047 PC = (uint32_t) f; // Set the program counter.
5048
5049 uint32_t rs = reinterpret_cast<uint32_t>(
5050 CALL_GENERATED_CODE(isolate, f, imm19, 0, 0, 0, 0));
5051
5052 return rs;
5053}
5054
5055
5056TEST(r6_addiupc) {
5057 if (IsMipsArchVariant(kMips32r6)) {
5058 CcTest::InitializeVM();
5059
5060 struct TestCaseAddiupc {
5061 int32_t imm19;
5062 };
5063
Ben Murdoch097c5b22016-05-18 11:27:45 +01005064 TestCaseAddiupc tc[] = {
5065 // imm19
5066 {-262144}, // 0x40000
5067 {-1}, // 0x7FFFF
5068 {0},
5069 {1}, // 0x00001
5070 {262143} // 0x3FFFF
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005071 };
5072
5073 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAddiupc);
5074 for (size_t i = 0; i < nr_test_cases; ++i) {
5075 PC = 0;
5076 uint32_t res = run_addiupc(tc[i].imm19);
5077 // Now, the program_counter (PC) is set.
5078 uint32_t expected_res = PC + (tc[i].imm19 << 2);
5079 CHECK_EQ(expected_res, res);
5080 }
5081 }
5082}
5083
5084
5085int32_t run_bc(int32_t offset) {
5086 Isolate* isolate = CcTest::i_isolate();
5087 HandleScope scope(isolate);
5088
5089 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5090
5091 Label continue_1, stop_execution;
5092 __ push(ra);
5093 __ li(v0, 0);
5094 __ li(t8, 0);
5095 __ li(t9, 2); // A condition for stopping execution.
5096
5097 for (int32_t i = -100; i <= -11; ++i) {
5098 __ addiu(v0, v0, 1);
5099 }
5100
5101 __ addiu(t8, t8, 1); // -10
5102
5103 __ beq(t8, t9, &stop_execution); // -9
5104 __ nop(); // -8
5105 __ beq(t8, t8, &continue_1); // -7
5106 __ nop(); // -6
5107
5108 __ bind(&stop_execution);
5109 __ pop(ra); // -5, -4
5110 __ jr(ra); // -3
5111 __ nop(); // -2
5112
5113 __ bind(&continue_1);
5114 __ bc(offset); // -1
5115
5116 for (int32_t i = 0; i <= 99; ++i) {
5117 __ addiu(v0, v0, 1);
5118 }
5119
5120 __ pop(ra);
5121 __ jr(ra);
5122 __ nop();
5123
5124 CodeDesc desc;
5125 assm.GetCode(&desc);
5126 Handle<Code> code = isolate->factory()->NewCode(
5127 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5128
5129 F2 f = FUNCTION_CAST<F2>(code->entry());
5130
5131 int32_t res = reinterpret_cast<int32_t>(
5132 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5133
5134 return res;
5135}
5136
5137
5138TEST(r6_bc) {
5139 if (IsMipsArchVariant(kMips32r6)) {
5140 CcTest::InitializeVM();
5141
5142 struct TestCaseBc {
5143 int32_t offset;
5144 int32_t expected_res;
5145 };
5146
5147 struct TestCaseBc tc[] = {
5148 // offset, expected_result
5149 { -100, (abs(-100) - 10) * 2 },
5150 { -11, (abs(-100) - 10 + 1) },
5151 { 0, (abs(-100) - 10 + 1 + 99) },
5152 { 1, (abs(-100) - 10 + 99) },
5153 { 99, (abs(-100) - 10 + 1) },
5154 };
5155
5156 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBc);
5157 for (size_t i = 0; i < nr_test_cases; ++i) {
5158 int32_t res = run_bc(tc[i].offset);
5159 CHECK_EQ(tc[i].expected_res, res);
5160 }
5161 }
5162}
5163
5164
5165int32_t run_balc(int32_t offset) {
5166 Isolate* isolate = CcTest::i_isolate();
5167 HandleScope scope(isolate);
5168
5169 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5170
5171 Label continue_1, stop_execution;
5172 __ push(ra);
5173 __ li(v0, 0);
5174 __ li(t8, 0);
5175 __ li(t9, 2); // A condition for stopping execution.
5176
5177 __ beq(t8, t8, &continue_1);
5178 __ nop();
5179
5180 uint32_t instruction_addiu = 0x24420001; // addiu v0, v0, 1
5181 for (int32_t i = -117; i <= -57; ++i) {
5182 __ dd(instruction_addiu);
5183 }
5184 __ jr(ra); // -56
5185 __ nop(); // -55
5186
5187 for (int32_t i = -54; i <= -4; ++i) {
5188 __ dd(instruction_addiu);
5189 }
5190 __ jr(ra); // -3
5191 __ nop(); // -2
5192
5193 __ bind(&continue_1);
5194 __ balc(offset); // -1
5195
5196 __ pop(ra); // 0, 1
5197 __ jr(ra); // 2
5198 __ nop(); // 3
5199
5200 for (int32_t i = 4; i <= 44; ++i) {
5201 __ dd(instruction_addiu);
5202 }
5203 __ jr(ra);
5204 __ nop();
5205
5206 CodeDesc desc;
5207 assm.GetCode(&desc);
5208 Handle<Code> code = isolate->factory()->NewCode(
5209 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5210
5211 F2 f = FUNCTION_CAST<F2>(code->entry());
5212
5213 int32_t res = reinterpret_cast<int32_t>(
5214 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5215
5216 return res;
5217}
5218
5219
5220uint32_t run_aui(uint32_t rs, uint16_t offset) {
5221 Isolate* isolate = CcTest::i_isolate();
5222 HandleScope scope(isolate);
5223
5224 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5225
5226 __ li(t0, rs);
5227 __ aui(v0, t0, offset);
5228 __ jr(ra);
5229 __ nop();
5230
5231 CodeDesc desc;
5232 assm.GetCode(&desc);
5233 Handle<Code> code = isolate->factory()->NewCode(
5234 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5235
5236 F2 f = FUNCTION_CAST<F2>(code->entry());
5237
5238 uint32_t res =
5239 reinterpret_cast<uint32_t>
5240 (CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5241
5242 return res;
5243}
5244
5245
5246TEST(r6_aui) {
5247 if (IsMipsArchVariant(kMips32r6)) {
5248 CcTest::InitializeVM();
5249
5250 struct TestCaseAui {
5251 uint32_t rs;
5252 uint16_t offset;
5253 uint32_t ref_res;
5254 };
5255
5256 struct TestCaseAui tc[] = {
5257 // input, offset, result
5258 {0xfffeffff, 1, 0xffffffff},
5259 {0xffffffff, 0, 0xffffffff},
5260 {0, 0xffff, 0xffff0000},
5261 {0x0008ffff, 0xfff7, 0xffffffff},
5262 {32767, 32767, 0x7fff7fff},
5263 // overflow cases
5264 {0xffffffff, 0x1, 0x0000ffff},
5265 {0xffffffff, 0xffff, 0xfffeffff},
5266 };
5267
5268 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAui);
5269 for (size_t i = 0; i < nr_test_cases; ++i) {
5270 PC = 0;
5271 uint32_t res = run_aui(tc[i].rs, tc[i].offset);
5272 CHECK_EQ(tc[i].ref_res, res);
5273 }
5274 }
5275}
5276
5277
5278TEST(r6_balc) {
5279 if (IsMipsArchVariant(kMips32r6)) {
5280 CcTest::InitializeVM();
5281
5282 struct TestCaseBalc {
5283 int32_t offset;
5284 int32_t expected_res;
5285 };
5286
5287 struct TestCaseBalc tc[] = {
5288 // offset, expected_result
5289 { -117, 61 },
5290 { -54, 51 },
5291 { 0, 0 },
5292 { 4, 41 },
5293 };
5294
5295 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBalc);
5296 for (size_t i = 0; i < nr_test_cases; ++i) {
5297 int32_t res = run_balc(tc[i].offset);
5298 CHECK_EQ(tc[i].expected_res, res);
5299 }
5300 }
5301}
5302
5303
5304uint32_t run_bal(int16_t offset) {
5305 Isolate* isolate = CcTest::i_isolate();
5306 HandleScope scope(isolate);
5307
5308 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5309
5310 __ mov(t0, ra);
5311 __ bal(offset); // Equivalent for "BGEZAL zero_reg, offset".
5312 __ nop();
5313
5314 __ mov(ra, t0);
5315 __ jr(ra);
5316 __ nop();
5317
5318 __ li(v0, 1);
5319 __ jr(ra);
5320 __ nop();
5321
5322 CodeDesc desc;
5323 assm.GetCode(&desc);
5324 Handle<Code> code = isolate->factory()->NewCode(
5325 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5326
5327 F2 f = FUNCTION_CAST<F2>(code->entry());
5328
5329 uint32_t res = reinterpret_cast<uint32_t>(
5330 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5331
5332 return res;
5333}
5334
5335
5336TEST(bal) {
5337 CcTest::InitializeVM();
5338
5339 struct TestCaseBal {
5340 int16_t offset;
5341 uint32_t expected_res;
5342 };
5343
5344 struct TestCaseBal tc[] = {
5345 // offset, expected_res
5346 { 4, 1 },
5347 };
5348
5349 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBal);
5350 for (size_t i = 0; i < nr_test_cases; ++i) {
5351 CHECK_EQ(tc[i].expected_res, run_bal(tc[i].offset));
5352 }
5353}
5354
5355
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005356TEST(Trampoline) {
5357 // Private member of Assembler class.
5358 static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
5359
5360 CcTest::InitializeVM();
5361 Isolate* isolate = CcTest::i_isolate();
5362 HandleScope scope(isolate);
5363
5364 MacroAssembler assm(isolate, nullptr, 0,
5365 v8::internal::CodeObjectRequired::kYes);
5366 Label done;
5367 size_t nr_calls = kMaxBranchOffset / (2 * Instruction::kInstrSize) + 2;
5368
5369 for (size_t i = 0; i < nr_calls; ++i) {
5370 __ BranchShort(&done, eq, a0, Operand(a1));
5371 }
5372 __ bind(&done);
5373 __ Ret(USE_DELAY_SLOT);
5374 __ mov(v0, zero_reg);
5375
5376 CodeDesc desc;
5377 assm.GetCode(&desc);
5378 Handle<Code> code = isolate->factory()->NewCode(
5379 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5380 F2 f = FUNCTION_CAST<F2>(code->entry());
5381
5382 int32_t res = reinterpret_cast<int32_t>(
5383 CALL_GENERATED_CODE(isolate, f, 42, 42, 0, 0, 0));
5384 CHECK_EQ(res, 0);
5385}
5386
Andrei Popescu402d9372010-02-26 13:31:12 +00005387#undef __