blob: 1928a753fd90a2414affdbd5af9b3f9e596ad66b [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};
1493 float inputsf[kTableLength] = {3.0, 2.0, 3.0, fnan, -0.0, 0.0, fnan,
1494 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
1527 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1528
1529 if (i < kTableLength - 1) {
1530 CHECK_EQ(test.c, outputsdmin[i]);
1531 CHECK_EQ(test.d, outputsdmax[i]);
1532 CHECK_EQ(test.g, outputsfmin[i]);
1533 CHECK_EQ(test.h, outputsfmax[i]);
1534 } else {
1535 CHECK(std::isnan(test.c));
1536 CHECK(std::isnan(test.d));
1537 CHECK(std::isnan(test.g));
1538 CHECK(std::isnan(test.h));
1539 }
1540 }
1541 }
1542}
1543
1544
1545TEST(rint_d) {
1546 if (IsMipsArchVariant(kMips32r6)) {
1547 const int kTableLength = 30;
1548 CcTest::InitializeVM();
1549 Isolate* isolate = CcTest::i_isolate();
1550 HandleScope scope(isolate);
1551 MacroAssembler assm(isolate, NULL, 0,
1552 v8::internal::CodeObjectRequired::kYes);
1553
1554 typedef struct test_float {
1555 double a;
1556 double b;
1557 int fcsr;
1558 }TestFloat;
1559
1560 TestFloat test;
1561 double inputs[kTableLength] = {18446744073709551617.0,
1562 4503599627370496.0, -4503599627370496.0,
1563 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
1564 1.7976931348623157E+308, 6.27463370218383111104242366943E-307,
1565 309485009821345068724781056.89,
1566 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
1567 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
1568 37778931862957161709568.0, 37778931862957161709569.0,
1569 37778931862957161709580.0, 37778931862957161709581.0,
1570 37778931862957161709582.0, 37778931862957161709583.0,
1571 37778931862957161709584.0, 37778931862957161709585.0,
1572 37778931862957161709586.0, 37778931862957161709587.0};
1573 double outputs_RN[kTableLength] = {18446744073709551617.0,
1574 4503599627370496.0, -4503599627370496.0,
1575 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
1576 1.7976931348623157E308, 0,
1577 309485009821345068724781057.0,
1578 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
1579 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
1580 37778931862957161709568.0, 37778931862957161709569.0,
1581 37778931862957161709580.0, 37778931862957161709581.0,
1582 37778931862957161709582.0, 37778931862957161709583.0,
1583 37778931862957161709584.0, 37778931862957161709585.0,
1584 37778931862957161709586.0, 37778931862957161709587.0};
1585 double outputs_RZ[kTableLength] = {18446744073709551617.0,
1586 4503599627370496.0, -4503599627370496.0,
1587 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
1588 1.7976931348623157E308, 0,
1589 309485009821345068724781057.0,
1590 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
1591 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
1592 37778931862957161709568.0, 37778931862957161709569.0,
1593 37778931862957161709580.0, 37778931862957161709581.0,
1594 37778931862957161709582.0, 37778931862957161709583.0,
1595 37778931862957161709584.0, 37778931862957161709585.0,
1596 37778931862957161709586.0, 37778931862957161709587.0};
1597 double outputs_RP[kTableLength] = {18446744073709551617.0,
1598 4503599627370496.0, -4503599627370496.0,
1599 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
1600 1.7976931348623157E308, 1,
1601 309485009821345068724781057.0,
1602 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
1603 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
1604 37778931862957161709568.0, 37778931862957161709569.0,
1605 37778931862957161709580.0, 37778931862957161709581.0,
1606 37778931862957161709582.0, 37778931862957161709583.0,
1607 37778931862957161709584.0, 37778931862957161709585.0,
1608 37778931862957161709586.0, 37778931862957161709587.0};
1609 double outputs_RM[kTableLength] = {18446744073709551617.0,
1610 4503599627370496.0, -4503599627370496.0,
1611 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147,
1612 1.7976931348623157E308, 0,
1613 309485009821345068724781057.0,
1614 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
1615 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
1616 37778931862957161709568.0, 37778931862957161709569.0,
1617 37778931862957161709580.0, 37778931862957161709581.0,
1618 37778931862957161709582.0, 37778931862957161709583.0,
1619 37778931862957161709584.0, 37778931862957161709585.0,
1620 37778931862957161709586.0, 37778931862957161709587.0};
1621 int fcsr_inputs[4] =
1622 {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf};
1623 double* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM};
1624 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)) );
1625 __ lw(t0, MemOperand(a0, offsetof(TestFloat, fcsr)) );
1626 __ cfc1(t1, FCSR);
1627 __ ctc1(t0, FCSR);
1628 __ rint_d(f8, f4);
1629 __ sdc1(f8, MemOperand(a0, offsetof(TestFloat, b)) );
1630 __ ctc1(t1, FCSR);
1631 __ jr(ra);
1632 __ nop();
1633
1634 CodeDesc desc;
1635 assm.GetCode(&desc);
1636 Handle<Code> code = isolate->factory()->NewCode(
1637 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1638 F3 f = FUNCTION_CAST<F3>(code->entry());
1639
1640 for (int j = 0; j < 4; j++) {
1641 test.fcsr = fcsr_inputs[j];
1642 for (int i = 0; i < kTableLength; i++) {
1643 test.a = inputs[i];
1644 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1645 CHECK_EQ(test.b, outputs[j][i]);
1646 }
1647 }
1648 }
1649}
1650
1651
1652TEST(sel) {
1653 if (IsMipsArchVariant(kMips32r6)) {
1654 CcTest::InitializeVM();
1655 Isolate* isolate = CcTest::i_isolate();
1656 HandleScope scope(isolate);
1657 MacroAssembler assm(isolate, NULL, 0,
1658 v8::internal::CodeObjectRequired::kYes);
1659
1660 typedef struct test {
1661 double dd;
1662 double ds;
1663 double dt;
1664 float fd;
1665 float fs;
1666 float ft;
1667 } Test;
1668
1669 Test test;
1670 __ ldc1(f0, MemOperand(a0, offsetof(Test, dd)) ); // test
1671 __ ldc1(f2, MemOperand(a0, offsetof(Test, ds)) ); // src1
1672 __ ldc1(f4, MemOperand(a0, offsetof(Test, dt)) ); // src2
1673 __ lwc1(f6, MemOperand(a0, offsetof(Test, fd)) ); // test
1674 __ lwc1(f8, MemOperand(a0, offsetof(Test, fs)) ); // src1
1675 __ lwc1(f10, MemOperand(a0, offsetof(Test, ft)) ); // src2
1676 __ sel_d(f0, f2, f4);
1677 __ sel_s(f6, f8, f10);
1678 __ sdc1(f0, MemOperand(a0, offsetof(Test, dd)) );
1679 __ swc1(f6, MemOperand(a0, offsetof(Test, fd)) );
1680 __ jr(ra);
1681 __ nop();
1682 CodeDesc desc;
1683 assm.GetCode(&desc);
1684 Handle<Code> code = isolate->factory()->NewCode(
1685 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1686 F3 f = FUNCTION_CAST<F3>(code->entry());
1687
1688 const int test_size = 3;
1689 const int input_size = 5;
1690
1691 double inputs_dt[input_size] = {0.0, 65.2, -70.32,
1692 18446744073709551621.0, -18446744073709551621.0};
1693 double inputs_ds[input_size] = {0.1, 69.88, -91.325,
1694 18446744073709551625.0, -18446744073709551625.0};
1695 float inputs_ft[input_size] = {0.0, 65.2, -70.32,
1696 18446744073709551621.0, -18446744073709551621.0};
1697 float inputs_fs[input_size] = {0.1, 69.88, -91.325,
1698 18446744073709551625.0, -18446744073709551625.0};
1699 double tests_D[test_size*2] = {2.8, 2.9, -2.8, -2.9,
1700 18446744073709551616.0, 18446744073709555712.0};
1701 float tests_S[test_size*2] = {2.9, 2.8, -2.9, -2.8,
1702 18446744073709551616.0, 18446746272732807168.0};
1703 for (int j=0; j < test_size; j+=2) {
1704 for (int i=0; i < input_size; i++) {
1705 test.dt = inputs_dt[i];
1706 test.dd = tests_D[j];
1707 test.ds = inputs_ds[i];
1708 test.ft = inputs_ft[i];
1709 test.fd = tests_S[j];
1710 test.fs = inputs_fs[i];
1711 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1712 CHECK_EQ(test.dd, inputs_ds[i]);
1713 CHECK_EQ(test.fd, inputs_fs[i]);
1714
1715 test.dd = tests_D[j+1];
1716 test.fd = tests_S[j+1];
1717 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1718 CHECK_EQ(test.dd, inputs_dt[i]);
1719 CHECK_EQ(test.fd, inputs_ft[i]);
1720 }
1721 }
1722 }
1723}
1724
1725
1726TEST(rint_s) {
1727 if (IsMipsArchVariant(kMips32r6)) {
1728 const int kTableLength = 30;
1729 CcTest::InitializeVM();
1730 Isolate* isolate = CcTest::i_isolate();
1731 HandleScope scope(isolate);
1732 MacroAssembler assm(isolate, NULL, 0,
1733 v8::internal::CodeObjectRequired::kYes);
1734
1735 typedef struct test_float {
1736 float a;
1737 float b;
1738 int fcsr;
1739 }TestFloat;
1740
1741 TestFloat test;
1742 float inputs[kTableLength] = {18446744073709551617.0,
1743 4503599627370496.0, -4503599627370496.0,
1744 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
1745 1.7976931348623157E+38, 6.27463370218383111104242366943E-37,
1746 309485009821345068724781056.89,
1747 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
1748 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
1749 37778931862957161709568.0, 37778931862957161709569.0,
1750 37778931862957161709580.0, 37778931862957161709581.0,
1751 37778931862957161709582.0, 37778931862957161709583.0,
1752 37778931862957161709584.0, 37778931862957161709585.0,
1753 37778931862957161709586.0, 37778931862957161709587.0};
1754 float outputs_RN[kTableLength] = {18446744073709551617.0,
1755 4503599627370496.0, -4503599627370496.0,
1756 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
1757 1.7976931348623157E38, 0,
1758 309485009821345068724781057.0,
1759 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
1760 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
1761 37778931862957161709568.0, 37778931862957161709569.0,
1762 37778931862957161709580.0, 37778931862957161709581.0,
1763 37778931862957161709582.0, 37778931862957161709583.0,
1764 37778931862957161709584.0, 37778931862957161709585.0,
1765 37778931862957161709586.0, 37778931862957161709587.0};
1766 float outputs_RZ[kTableLength] = {18446744073709551617.0,
1767 4503599627370496.0, -4503599627370496.0,
1768 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
1769 1.7976931348623157E38, 0,
1770 309485009821345068724781057.0,
1771 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
1772 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
1773 37778931862957161709568.0, 37778931862957161709569.0,
1774 37778931862957161709580.0, 37778931862957161709581.0,
1775 37778931862957161709582.0, 37778931862957161709583.0,
1776 37778931862957161709584.0, 37778931862957161709585.0,
1777 37778931862957161709586.0, 37778931862957161709587.0};
1778 float outputs_RP[kTableLength] = {18446744073709551617.0,
1779 4503599627370496.0, -4503599627370496.0,
1780 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
1781 1.7976931348623157E38, 1,
1782 309485009821345068724781057.0,
1783 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
1784 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
1785 37778931862957161709568.0, 37778931862957161709569.0,
1786 37778931862957161709580.0, 37778931862957161709581.0,
1787 37778931862957161709582.0, 37778931862957161709583.0,
1788 37778931862957161709584.0, 37778931862957161709585.0,
1789 37778931862957161709586.0, 37778931862957161709587.0};
1790 float outputs_RM[kTableLength] = {18446744073709551617.0,
1791 4503599627370496.0, -4503599627370496.0,
1792 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37,
1793 1.7976931348623157E38, 0,
1794 309485009821345068724781057.0,
1795 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
1796 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
1797 37778931862957161709568.0, 37778931862957161709569.0,
1798 37778931862957161709580.0, 37778931862957161709581.0,
1799 37778931862957161709582.0, 37778931862957161709583.0,
1800 37778931862957161709584.0, 37778931862957161709585.0,
1801 37778931862957161709586.0, 37778931862957161709587.0};
1802 int fcsr_inputs[4] =
1803 {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf};
1804 float* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM};
1805 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, a)) );
1806 __ lw(t0, MemOperand(a0, offsetof(TestFloat, fcsr)) );
1807 __ cfc1(t1, FCSR);
1808 __ ctc1(t0, FCSR);
1809 __ rint_s(f8, f4);
1810 __ swc1(f8, MemOperand(a0, offsetof(TestFloat, b)) );
1811 __ ctc1(t1, FCSR);
1812 __ jr(ra);
1813 __ nop();
1814
1815 CodeDesc desc;
1816 assm.GetCode(&desc);
1817 Handle<Code> code = isolate->factory()->NewCode(
1818 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1819 F3 f = FUNCTION_CAST<F3>(code->entry());
1820
1821 for (int j = 0; j < 4; j++) {
1822 test.fcsr = fcsr_inputs[j];
1823 for (int i = 0; i < kTableLength; i++) {
1824 test.a = inputs[i];
1825 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1826 CHECK_EQ(test.b, outputs[j][i]);
1827 }
1828 }
1829 }
1830}
1831
1832
1833TEST(Cvt_d_uw) {
1834 CcTest::InitializeVM();
1835 Isolate* isolate = CcTest::i_isolate();
1836 HandleScope scope(isolate);
1837 MacroAssembler assm(isolate, NULL, 0,
1838 v8::internal::CodeObjectRequired::kYes);
1839
1840 typedef struct test_struct {
1841 unsigned input;
1842 uint64_t output;
1843 } TestStruct;
1844
1845 unsigned inputs[] = {
1846 0x0, 0xffffffff, 0x80000000, 0x7fffffff
1847 };
1848
1849 uint64_t outputs[] = {
1850 0x0, 0x41efffffffe00000,
1851 0x41e0000000000000, 0x41dfffffffc00000
1852 };
1853
1854 int kTableLength = sizeof(inputs)/sizeof(inputs[0]);
1855
1856 TestStruct test;
1857
1858 __ lw(t1, MemOperand(a0, offsetof(TestStruct, input)));
1859 __ Cvt_d_uw(f4, t1, f6);
1860 __ sdc1(f4, MemOperand(a0, offsetof(TestStruct, output)));
1861 __ jr(ra);
1862 __ nop();
1863
1864 CodeDesc desc;
1865 assm.GetCode(&desc);
1866 Handle<Code> code = isolate->factory()->NewCode(
1867 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1868 F3 f = FUNCTION_CAST<F3>(code->entry());
1869 for (int i = 0; i < kTableLength; i++) {
1870 test.input = inputs[i];
1871 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1872 // Check outputs
1873 CHECK_EQ(test.output, outputs[i]);
1874 }
1875}
1876
1877
1878TEST(mina_maxa) {
1879 if (IsMipsArchVariant(kMips32r6)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001880 const int kTableLength = 23;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001881 CcTest::InitializeVM();
1882 Isolate* isolate = CcTest::i_isolate();
1883 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001884 MacroAssembler assm(isolate, nullptr, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001885 v8::internal::CodeObjectRequired::kYes);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001886 const double dnan = std::numeric_limits<double>::quiet_NaN();
1887 const double dinf = std::numeric_limits<double>::infinity();
1888 const double dminf = -std::numeric_limits<double>::infinity();
1889 const float fnan = std::numeric_limits<float>::quiet_NaN();
1890 const float finf = std::numeric_limits<float>::infinity();
1891 const float fminf = std::numeric_limits<float>::infinity();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001892
Ben Murdoch097c5b22016-05-18 11:27:45 +01001893 struct TestFloat {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001894 double a;
1895 double b;
1896 double resd;
1897 double resd1;
1898 float c;
1899 float d;
1900 float resf;
1901 float resf1;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001902 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001903
1904 TestFloat test;
1905 double inputsa[kTableLength] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001906 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9, -9.8, -10.0, -8.9, -9.8,
1907 dnan, 3.0, -0.0, 0.0, dinf, dnan, 42.0, dinf, dminf, dinf, dnan};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001908 double inputsb[kTableLength] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001909 4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8, 9.8, -9.8, -11.2, -9.8,
1910 3.0, dnan, 0.0, -0.0, dnan, dinf, dinf, 42.0, dinf, dminf, dnan};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001911 double resd[kTableLength] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001912 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9, -9.8, -9.8, -8.9, -9.8,
1913 3.0, 3.0, -0.0, -0.0, dinf, dinf, 42.0, 42.0, dminf, dminf, dnan};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001914 double resd1[kTableLength] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001915 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8, 9.8, -10.0, -11.2, -9.8,
1916 3.0, 3.0, 0.0, 0.0, dinf, dinf, dinf, dinf, dinf, dinf, dnan};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001917 float inputsc[kTableLength] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001918 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9, -9.8, -10.0, -8.9, -9.8,
1919 fnan, 3.0, -0.0, 0.0, finf, fnan, 42.0, finf, fminf, finf, fnan};
1920 float inputsd[kTableLength] = {4.8, 5.3, 6.1, -10.0, -8.9, -9.8,
1921 9.8, 9.8, 9.8, -9.8, -11.2, -9.8,
1922 3.0, fnan, -0.0, 0.0, fnan, finf,
1923 finf, 42.0, finf, fminf, fnan};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001924 float resf[kTableLength] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001925 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9, -9.8, -9.8, -8.9, -9.8,
1926 3.0, 3.0, -0.0, -0.0, finf, finf, 42.0, 42.0, fminf, fminf, fnan};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001927 float resf1[kTableLength] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001928 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8, 9.8, -10.0, -11.2, -9.8,
1929 3.0, 3.0, 0.0, 0.0, finf, finf, finf, finf, finf, finf, fnan};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001930
1931 __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
1932 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, b)) );
1933 __ lwc1(f8, MemOperand(a0, offsetof(TestFloat, c)) );
1934 __ lwc1(f10, MemOperand(a0, offsetof(TestFloat, d)) );
1935 __ mina_d(f6, f2, f4);
1936 __ mina_s(f12, f8, f10);
1937 __ maxa_d(f14, f2, f4);
1938 __ maxa_s(f16, f8, f10);
1939 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, resf)) );
1940 __ sdc1(f6, MemOperand(a0, offsetof(TestFloat, resd)) );
1941 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, resf1)) );
1942 __ sdc1(f14, MemOperand(a0, offsetof(TestFloat, resd1)) );
1943 __ jr(ra);
1944 __ nop();
1945
1946 CodeDesc desc;
1947 assm.GetCode(&desc);
1948 Handle<Code> code = isolate->factory()->NewCode(
1949 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1950 F3 f = FUNCTION_CAST<F3>(code->entry());
1951 for (int i = 0; i < kTableLength; i++) {
1952 test.a = inputsa[i];
1953 test.b = inputsb[i];
1954 test.c = inputsc[i];
1955 test.d = inputsd[i];
1956 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
1957 if (i < kTableLength - 1) {
1958 CHECK_EQ(test.resd, resd[i]);
1959 CHECK_EQ(test.resf, resf[i]);
1960 CHECK_EQ(test.resd1, resd1[i]);
1961 CHECK_EQ(test.resf1, resf1[i]);
1962 } else {
1963 CHECK(std::isnan(test.resd));
1964 CHECK(std::isnan(test.resf));
1965 CHECK(std::isnan(test.resd1));
1966 CHECK(std::isnan(test.resf1));
1967 }
1968 }
1969 }
1970}
1971
1972
1973// ----------------------mips32r2 specific tests----------------------
1974TEST(trunc_l) {
1975 if (IsMipsArchVariant(kMips32r2) && IsFp64Mode()) {
1976 CcTest::InitializeVM();
1977 Isolate* isolate = CcTest::i_isolate();
1978 HandleScope scope(isolate);
1979 MacroAssembler assm(isolate, NULL, 0,
1980 v8::internal::CodeObjectRequired::kYes);
1981 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult);
1982 typedef struct test_float {
1983 uint32_t isNaN2008;
1984 double a;
1985 float b;
1986 int64_t c; // a trunc result
1987 int64_t d; // b trunc result
1988 }Test;
1989 const int kTableLength = 15;
1990 double inputs_D[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<double>::quiet_NaN(),
1995 std::numeric_limits<double>::infinity()
1996 };
1997 float inputs_S[kTableLength] = {
1998 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
1999 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2000 2147483648.0,
2001 std::numeric_limits<float>::quiet_NaN(),
2002 std::numeric_limits<float>::infinity()
2003 };
2004 double outputs[kTableLength] = {
2005 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2006 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
2007 2147483648.0, dFPU64InvalidResult,
2008 dFPU64InvalidResult};
2009 double outputsNaN2008[kTableLength] = {
2010 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2011 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
2012 2147483648.0,
2013 0,
2014 dFPU64InvalidResult};
2015
2016 __ cfc1(t1, FCSR);
2017 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
2018 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2019 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
2020 __ trunc_l_d(f8, f4);
2021 __ trunc_l_s(f10, f6);
2022 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) );
2023 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) );
2024 __ jr(ra);
2025 __ nop();
2026 Test test;
2027 CodeDesc desc;
2028 assm.GetCode(&desc);
2029 Handle<Code> code = isolate->factory()->NewCode(
2030 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2031 F3 f = FUNCTION_CAST<F3>(code->entry());
2032 for (int i = 0; i < kTableLength; i++) {
2033 test.a = inputs_D[i];
2034 test.b = inputs_S[i];
2035 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2036 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) &&
2037 kArchVariant == kMips32r6) {
2038 CHECK_EQ(test.c, outputsNaN2008[i]);
2039 } else {
2040 CHECK_EQ(test.c, outputs[i]);
2041 }
2042 CHECK_EQ(test.d, test.c);
2043 }
2044 }
2045}
2046
2047
2048TEST(movz_movn) {
2049 if (IsMipsArchVariant(kMips32r2)) {
2050 const int kTableLength = 4;
2051 CcTest::InitializeVM();
2052 Isolate* isolate = CcTest::i_isolate();
2053 HandleScope scope(isolate);
2054 MacroAssembler assm(isolate, NULL, 0,
2055 v8::internal::CodeObjectRequired::kYes);
2056
2057 typedef struct test_float {
2058 int64_t rt;
2059 double a;
2060 double b;
2061 double bold;
2062 double b1;
2063 double bold1;
2064 float c;
2065 float d;
2066 float dold;
2067 float d1;
2068 float dold1;
2069 }TestFloat;
2070
2071 TestFloat test;
2072 double inputs_D[kTableLength] = {
2073 5.3, -5.3, 5.3, -2.9
2074 };
2075 double inputs_S[kTableLength] = {
2076 4.8, 4.8, -4.8, -0.29
2077 };
2078
2079 float outputs_S[kTableLength] = {
2080 4.8, 4.8, -4.8, -0.29
2081 };
2082 double outputs_D[kTableLength] = {
2083 5.3, -5.3, 5.3, -2.9
2084 };
2085
2086 __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
2087 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, c)) );
2088 __ lw(t0, MemOperand(a0, offsetof(TestFloat, rt)) );
2089 __ Move(f12, 0.0);
2090 __ Move(f10, 0.0);
2091 __ Move(f16, 0.0);
2092 __ Move(f14, 0.0);
2093 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, bold)) );
2094 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, dold)) );
2095 __ sdc1(f16, MemOperand(a0, offsetof(TestFloat, bold1)) );
2096 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, dold1)) );
2097 __ movz_s(f10, f6, t0);
2098 __ movz_d(f12, f2, t0);
2099 __ movn_s(f14, f6, t0);
2100 __ movn_d(f16, f2, t0);
2101 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, d)) );
2102 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, b)) );
2103 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, d1)) );
2104 __ sdc1(f16, MemOperand(a0, offsetof(TestFloat, b1)) );
2105 __ jr(ra);
2106 __ nop();
2107
2108 CodeDesc desc;
2109 assm.GetCode(&desc);
2110 Handle<Code> code = isolate->factory()->NewCode(
2111 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2112 F3 f = FUNCTION_CAST<F3>(code->entry());
2113 for (int i = 0; i < kTableLength; i++) {
2114 test.a = inputs_D[i];
2115 test.c = inputs_S[i];
2116
2117 test.rt = 1;
2118 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2119 CHECK_EQ(test.b, test.bold);
2120 CHECK_EQ(test.d, test.dold);
2121 CHECK_EQ(test.b1, outputs_D[i]);
2122 CHECK_EQ(test.d1, outputs_S[i]);
2123
2124 test.rt = 0;
2125 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2126 CHECK_EQ(test.b, outputs_D[i]);
2127 CHECK_EQ(test.d, outputs_S[i]);
2128 CHECK_EQ(test.b1, test.bold1);
2129 CHECK_EQ(test.d1, test.dold1);
2130 }
2131 }
2132}
2133
2134
2135TEST(movt_movd) {
2136 if (IsMipsArchVariant(kMips32r2)) {
2137 const int kTableLength = 4;
2138 CcTest::InitializeVM();
2139 Isolate* isolate = CcTest::i_isolate();
2140
2141 typedef struct test_float {
2142 double srcd;
2143 double dstd;
2144 double dstdold;
2145 double dstd1;
2146 double dstdold1;
2147 float srcf;
2148 float dstf;
2149 float dstfold;
2150 float dstf1;
2151 float dstfold1;
2152 int32_t cc;
2153 int32_t fcsr;
2154 }TestFloat;
2155
2156 TestFloat test;
2157 double inputs_D[kTableLength] = {
2158 5.3, -5.3, 20.8, -2.9
2159 };
2160 double inputs_S[kTableLength] = {
2161 4.88, 4.8, -4.8, -0.29
2162 };
2163
2164 float outputs_S[kTableLength] = {
2165 4.88, 4.8, -4.8, -0.29
2166 };
2167 double outputs_D[kTableLength] = {
2168 5.3, -5.3, 20.8, -2.9
2169 };
2170 int condition_flags[8] = {0, 1, 2, 3, 4, 5, 6, 7};
2171
2172 for (int i = 0; i < kTableLength; i++) {
2173 test.srcd = inputs_D[i];
2174 test.srcf = inputs_S[i];
2175
2176 for (int j = 0; j< 8; j++) {
2177 test.cc = condition_flags[j];
2178 if (test.cc == 0) {
2179 test.fcsr = 1 << 23;
2180 } else {
2181 test.fcsr = 1 << (24+condition_flags[j]);
2182 }
2183 HandleScope scope(isolate);
2184 MacroAssembler assm(isolate, NULL, 0,
2185 v8::internal::CodeObjectRequired::kYes);
2186 __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, srcd)) );
2187 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, srcf)) );
2188 __ lw(t1, MemOperand(a0, offsetof(TestFloat, fcsr)) );
2189 __ cfc1(t0, FCSR);
2190 __ ctc1(t1, FCSR);
2191 __ li(t2, 0x0);
2192 __ mtc1(t2, f12);
2193 __ mtc1(t2, f10);
2194 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstdold)) );
2195 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstfold)) );
2196 __ movt_s(f12, f4, test.cc);
2197 __ movt_d(f10, f2, test.cc);
2198 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstf)) );
2199 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstd)) );
2200 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstdold1)) );
2201 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstfold1)) );
2202 __ movf_s(f12, f4, test.cc);
2203 __ movf_d(f10, f2, test.cc);
2204 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstf1)) );
2205 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstd1)) );
2206 __ ctc1(t0, FCSR);
2207 __ jr(ra);
2208 __ nop();
2209
2210 CodeDesc desc;
2211 assm.GetCode(&desc);
2212 Handle<Code> code = isolate->factory()->NewCode(
2213 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2214 F3 f = FUNCTION_CAST<F3>(code->entry());
2215
2216 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2217 CHECK_EQ(test.dstf, outputs_S[i]);
2218 CHECK_EQ(test.dstd, outputs_D[i]);
2219 CHECK_EQ(test.dstf1, test.dstfold1);
2220 CHECK_EQ(test.dstd1, test.dstdold1);
2221 test.fcsr = 0;
2222 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2223 CHECK_EQ(test.dstf, test.dstfold);
2224 CHECK_EQ(test.dstd, test.dstdold);
2225 CHECK_EQ(test.dstf1, outputs_S[i]);
2226 CHECK_EQ(test.dstd1, outputs_D[i]);
2227 }
2228 }
2229 }
2230}
2231
2232
2233// ----------------------tests for all archs--------------------------
2234TEST(cvt_w_d) {
2235 CcTest::InitializeVM();
2236 Isolate* isolate = CcTest::i_isolate();
2237 HandleScope scope(isolate);
2238 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2239
2240 typedef struct test_float {
2241 double a;
2242 int32_t b;
2243 int32_t fcsr;
2244 }Test;
2245 const int kTableLength = 24;
2246 double inputs[kTableLength] = {
2247 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2248 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2249 2147483637.0, 2147483638.0, 2147483639.0,
2250 2147483640.0, 2147483641.0, 2147483642.0,
2251 2147483643.0, 2147483644.0, 2147483645.0,
2252 2147483646.0, 2147483647.0, 2147483653.0
2253 };
2254 double outputs_RN[kTableLength] = {
2255 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
2256 -2.0, -3.0, -2.0, -3.0, -4.0, -4.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_RZ[kTableLength] = {
2262 2.0, 2.0, 2.0, 3.0, 3.0, 3.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_RP[kTableLength] = {
2269 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
2270 -2.0, -2.0, -2.0, -3.0, -3.0, -3.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 double outputs_RM[kTableLength] = {
2276 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2277 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
2278 2147483637.0, 2147483638.0, 2147483639.0,
2279 2147483640.0, 2147483641.0, 2147483642.0,
2280 2147483643.0, 2147483644.0, 2147483645.0,
2281 2147483646.0, 2147483647.0, kFPUInvalidResult};
2282 int fcsr_inputs[4] =
2283 {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf};
2284 double* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM};
2285 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2286 __ lw(t0, MemOperand(a0, offsetof(Test, fcsr)) );
2287 __ cfc1(t1, FCSR);
2288 __ ctc1(t0, FCSR);
2289 __ cvt_w_d(f8, f4);
2290 __ swc1(f8, MemOperand(a0, offsetof(Test, b)) );
2291 __ ctc1(t1, FCSR);
2292 __ jr(ra);
2293 __ nop();
2294 Test test;
2295 CodeDesc desc;
2296 assm.GetCode(&desc);
2297 Handle<Code> code = isolate->factory()->NewCode(
2298 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2299 F3 f = FUNCTION_CAST<F3>(code->entry());
2300 for (int j = 0; j < 4; j++) {
2301 test.fcsr = fcsr_inputs[j];
2302 for (int i = 0; i < kTableLength; i++) {
2303 test.a = inputs[i];
2304 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2305 CHECK_EQ(test.b, outputs[j][i]);
2306 }
2307 }
2308}
2309
2310
2311TEST(trunc_w) {
2312 CcTest::InitializeVM();
2313 Isolate* isolate = CcTest::i_isolate();
2314 HandleScope scope(isolate);
2315 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2316
2317 typedef struct test_float {
2318 uint32_t isNaN2008;
2319 double a;
2320 float b;
2321 int32_t c; // a trunc result
2322 int32_t d; // b trunc result
2323 }Test;
2324 const int kTableLength = 15;
2325 double inputs_D[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<double>::quiet_NaN(),
2330 std::numeric_limits<double>::infinity()
2331 };
2332 float inputs_S[kTableLength] = {
2333 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2334 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2335 2147483648.0,
2336 std::numeric_limits<float>::quiet_NaN(),
2337 std::numeric_limits<float>::infinity()
2338 };
2339 double outputs[kTableLength] = {
2340 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2341 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
2342 kFPUInvalidResult, kFPUInvalidResult,
2343 kFPUInvalidResult};
2344 double outputsNaN2008[kTableLength] = {
2345 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2346 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
2347 kFPUInvalidResult,
2348 0,
2349 kFPUInvalidResult};
2350
2351 __ cfc1(t1, FCSR);
2352 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
2353 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2354 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
2355 __ trunc_w_d(f8, f4);
2356 __ trunc_w_s(f10, f6);
2357 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) );
2358 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) );
2359 __ jr(ra);
2360 __ nop();
2361 Test test;
2362 CodeDesc desc;
2363 assm.GetCode(&desc);
2364 Handle<Code> code = isolate->factory()->NewCode(
2365 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2366 F3 f = FUNCTION_CAST<F3>(code->entry());
2367 for (int i = 0; i < kTableLength; i++) {
2368 test.a = inputs_D[i];
2369 test.b = inputs_S[i];
2370 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2371 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips32r6) {
2372 CHECK_EQ(test.c, outputsNaN2008[i]);
2373 } else {
2374 CHECK_EQ(test.c, outputs[i]);
2375 }
2376 CHECK_EQ(test.d, test.c);
2377 }
2378}
2379
2380
2381TEST(round_w) {
2382 CcTest::InitializeVM();
2383 Isolate* isolate = CcTest::i_isolate();
2384 HandleScope scope(isolate);
2385 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2386
2387 typedef struct test_float {
2388 uint32_t isNaN2008;
2389 double a;
2390 float b;
2391 int32_t c; // a trunc result
2392 int32_t d; // b trunc result
2393 }Test;
2394 const int kTableLength = 15;
2395 double inputs_D[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<double>::quiet_NaN(),
2400 std::numeric_limits<double>::infinity()
2401 };
2402 float inputs_S[kTableLength] = {
2403 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2404 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2405 2147483648.0,
2406 std::numeric_limits<float>::quiet_NaN(),
2407 std::numeric_limits<float>::infinity()
2408 };
2409 double outputs[kTableLength] = {
2410 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
2411 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
2412 kFPUInvalidResult, kFPUInvalidResult,
2413 kFPUInvalidResult};
2414 double outputsNaN2008[kTableLength] = {
2415 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
2416 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
2417 kFPUInvalidResult, 0,
2418 kFPUInvalidResult};
2419
2420 __ cfc1(t1, FCSR);
2421 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
2422 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2423 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
2424 __ round_w_d(f8, f4);
2425 __ round_w_s(f10, f6);
2426 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) );
2427 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) );
2428 __ jr(ra);
2429 __ nop();
2430 Test test;
2431 CodeDesc desc;
2432 assm.GetCode(&desc);
2433 Handle<Code> code = isolate->factory()->NewCode(
2434 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2435 F3 f = FUNCTION_CAST<F3>(code->entry());
2436 for (int i = 0; i < kTableLength; i++) {
2437 test.a = inputs_D[i];
2438 test.b = inputs_S[i];
2439 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2440 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips32r6) {
2441 CHECK_EQ(test.c, outputsNaN2008[i]);
2442 } else {
2443 CHECK_EQ(test.c, outputs[i]);
2444 }
2445 CHECK_EQ(test.d, test.c);
2446 }
2447}
2448
2449
2450TEST(round_l) {
2451 if (IsFp64Mode()) {
2452 CcTest::InitializeVM();
2453 Isolate* isolate = CcTest::i_isolate();
2454 HandleScope scope(isolate);
2455 MacroAssembler assm(isolate, NULL, 0,
2456 v8::internal::CodeObjectRequired::kYes);
2457 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult);
2458 typedef struct test_float {
2459 uint32_t isNaN2008;
2460 double a;
2461 float b;
2462 int64_t c;
2463 int64_t d;
2464 }Test;
2465 const int kTableLength = 15;
2466 double inputs_D[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<double>::quiet_NaN(),
2471 std::numeric_limits<double>::infinity()
2472 };
2473 float inputs_S[kTableLength] = {
2474 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2475 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2476 2147483648.0,
2477 std::numeric_limits<float>::quiet_NaN(),
2478 std::numeric_limits<float>::infinity()
2479 };
2480 double outputs[kTableLength] = {
2481 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
2482 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
2483 2147483648.0, dFPU64InvalidResult,
2484 dFPU64InvalidResult};
2485 double outputsNaN2008[kTableLength] = {
2486 2.0, 3.0, 2.0, 3.0, 4.0, 4.0,
2487 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0,
2488 2147483648.0,
2489 0,
2490 dFPU64InvalidResult};
2491
2492 __ cfc1(t1, FCSR);
2493 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
2494 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2495 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
2496 __ round_l_d(f8, f4);
2497 __ round_l_s(f10, f6);
2498 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) );
2499 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) );
2500 __ jr(ra);
2501 __ nop();
2502 Test test;
2503 CodeDesc desc;
2504 assm.GetCode(&desc);
2505 Handle<Code> code = isolate->factory()->NewCode(
2506 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2507 F3 f = FUNCTION_CAST<F3>(code->entry());
2508 for (int i = 0; i < kTableLength; i++) {
2509 test.a = inputs_D[i];
2510 test.b = inputs_S[i];
2511 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2512 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) &&
2513 kArchVariant == kMips32r6) {
2514 CHECK_EQ(test.c, outputsNaN2008[i]);
2515 } else {
2516 CHECK_EQ(test.c, outputs[i]);
2517 }
2518 CHECK_EQ(test.d, test.c);
2519 }
2520 }
2521}
2522
2523
2524TEST(sub) {
2525 const int kTableLength = 12;
2526 CcTest::InitializeVM();
2527 Isolate* isolate = CcTest::i_isolate();
2528 HandleScope scope(isolate);
2529 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2530
2531 typedef struct test_float {
2532 float a;
2533 float b;
2534 float resultS;
2535 double c;
2536 double d;
2537 double resultD;
2538 }TestFloat;
2539
2540 TestFloat test;
2541 double inputfs_D[kTableLength] = {
2542 5.3, 4.8, 2.9, -5.3, -4.8, -2.9,
2543 5.3, 4.8, 2.9, -5.3, -4.8, -2.9
2544 };
2545 double inputft_D[kTableLength] = {
2546 4.8, 5.3, 2.9, 4.8, 5.3, 2.9,
2547 -4.8, -5.3, -2.9, -4.8, -5.3, -2.9
2548 };
2549 double outputs_D[kTableLength] = {
2550 0.5, -0.5, 0.0, -10.1, -10.1, -5.8,
2551 10.1, 10.1, 5.8, -0.5, 0.5, 0.0
2552 };
2553 float inputfs_S[kTableLength] = {
2554 5.3, 4.8, 2.9, -5.3, -4.8, -2.9,
2555 5.3, 4.8, 2.9, -5.3, -4.8, -2.9
2556 };
2557 float inputft_S[kTableLength] = {
2558 4.8, 5.3, 2.9, 4.8, 5.3, 2.9,
2559 -4.8, -5.3, -2.9, -4.8, -5.3, -2.9
2560 };
2561 float outputs_S[kTableLength] = {
2562 0.5, -0.5, 0.0, -10.1, -10.1, -5.8,
2563 10.1, 10.1, 5.8, -0.5, 0.5, 0.0
2564 };
2565 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
2566 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b)) );
2567 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) );
2568 __ ldc1(f10, MemOperand(a0, offsetof(TestFloat, d)) );
2569 __ sub_s(f6, f2, f4);
2570 __ sub_d(f12, f8, f10);
2571 __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) );
2572 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) );
2573 __ jr(ra);
2574 __ nop();
2575
2576 CodeDesc desc;
2577 assm.GetCode(&desc);
2578 Handle<Code> code = isolate->factory()->NewCode(
2579 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2580 F3 f = FUNCTION_CAST<F3>(code->entry());
2581 for (int i = 0; i < kTableLength; i++) {
2582 test.a = inputfs_S[i];
2583 test.b = inputft_S[i];
2584 test.c = inputfs_D[i];
2585 test.d = inputft_D[i];
2586 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2587 CHECK_EQ(test.resultS, outputs_S[i]);
2588 CHECK_EQ(test.resultD, outputs_D[i]);
2589 }
2590}
2591
2592
2593TEST(sqrt_rsqrt_recip) {
2594 const int kTableLength = 4;
2595 const double deltaDouble = 2E-15;
2596 const float deltaFloat = 2E-7;
2597 const float sqrt2_s = sqrt(2);
2598 const double sqrt2_d = sqrt(2);
2599 CcTest::InitializeVM();
2600 Isolate* isolate = CcTest::i_isolate();
2601 HandleScope scope(isolate);
2602 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2603
2604 typedef struct test_float {
2605 float a;
2606 float resultS;
2607 float resultS1;
2608 float resultS2;
2609 double c;
2610 double resultD;
2611 double resultD1;
2612 double resultD2;
2613 }TestFloat;
2614 TestFloat test;
2615
2616 double inputs_D[kTableLength] = {
2617 0.0L, 4.0L, 2.0L, 4e-28L
2618 };
2619
2620 double outputs_D[kTableLength] = {
2621 0.0L, 2.0L, sqrt2_d, 2e-14L
2622 };
2623 float inputs_S[kTableLength] = {
2624 0.0, 4.0, 2.0, 4e-28
2625 };
2626
2627 float outputs_S[kTableLength] = {
2628 0.0, 2.0, sqrt2_s, 2e-14
2629 };
2630
2631
2632 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
2633 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) );
2634 __ sqrt_s(f6, f2);
2635 __ sqrt_d(f12, f8);
2636
2637 if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
2638 __ rsqrt_d(f14, f8);
2639 __ rsqrt_s(f16, f2);
2640 __ recip_d(f18, f8);
2641 __ recip_s(f4, f2);
2642 }
2643 __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) );
2644 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) );
2645
2646 if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
2647 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, resultS1)) );
2648 __ sdc1(f14, MemOperand(a0, offsetof(TestFloat, resultD1)) );
2649 __ swc1(f4, MemOperand(a0, offsetof(TestFloat, resultS2)) );
2650 __ sdc1(f18, MemOperand(a0, offsetof(TestFloat, resultD2)) );
2651 }
2652 __ jr(ra);
2653 __ nop();
2654
2655 CodeDesc desc;
2656 assm.GetCode(&desc);
2657 Handle<Code> code = isolate->factory()->NewCode(
2658 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2659 F3 f = FUNCTION_CAST<F3>(code->entry());
2660
2661 for (int i = 0; i < kTableLength; i++) {
2662 float f1;
2663 double d1;
2664 test.a = inputs_S[i];
2665 test.c = inputs_D[i];
2666
2667 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2668
2669 CHECK_EQ(test.resultS, outputs_S[i]);
2670 CHECK_EQ(test.resultD, outputs_D[i]);
2671
2672 if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
2673 if (i != 0) {
2674 f1 = test.resultS1 - 1.0F/outputs_S[i];
2675 f1 = (f1 < 0) ? f1 : -f1;
2676 CHECK(f1 <= deltaFloat);
2677 d1 = test.resultD1 - 1.0L/outputs_D[i];
2678 d1 = (d1 < 0) ? d1 : -d1;
2679 CHECK(d1 <= deltaDouble);
2680 f1 = test.resultS2 - 1.0F/inputs_S[i];
2681 f1 = (f1 < 0) ? f1 : -f1;
2682 CHECK(f1 <= deltaFloat);
2683 d1 = test.resultD2 - 1.0L/inputs_D[i];
2684 d1 = (d1 < 0) ? d1 : -d1;
2685 CHECK(d1 <= deltaDouble);
2686 } else {
2687 CHECK_EQ(test.resultS1, 1.0F/outputs_S[i]);
2688 CHECK_EQ(test.resultD1, 1.0L/outputs_D[i]);
2689 CHECK_EQ(test.resultS2, 1.0F/inputs_S[i]);
2690 CHECK_EQ(test.resultD2, 1.0L/inputs_D[i]);
2691 }
2692 }
2693 }
2694}
2695
2696
2697TEST(neg) {
2698 const int kTableLength = 3;
2699 CcTest::InitializeVM();
2700 Isolate* isolate = CcTest::i_isolate();
2701 HandleScope scope(isolate);
2702 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2703
2704 typedef struct test_float {
2705 float a;
2706 float resultS;
2707 double c;
2708 double resultD;
2709 }TestFloat;
2710
2711 TestFloat test;
2712 double inputs_D[kTableLength] = {
2713 0.0, 4.0, -2.0
2714 };
2715
2716 double outputs_D[kTableLength] = {
2717 0.0, -4.0, 2.0
2718 };
2719 float inputs_S[kTableLength] = {
2720 0.0, 4.0, -2.0
2721 };
2722
2723 float outputs_S[kTableLength] = {
2724 0.0, -4.0, 2.0
2725 };
2726 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
2727 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) );
2728 __ neg_s(f6, f2);
2729 __ neg_d(f12, f8);
2730 __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) );
2731 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) );
2732 __ jr(ra);
2733 __ nop();
2734
2735 CodeDesc desc;
2736 assm.GetCode(&desc);
2737 Handle<Code> code = isolate->factory()->NewCode(
2738 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2739 F3 f = FUNCTION_CAST<F3>(code->entry());
2740 for (int i = 0; i < kTableLength; i++) {
2741 test.a = inputs_S[i];
2742 test.c = inputs_D[i];
2743 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2744 CHECK_EQ(test.resultS, outputs_S[i]);
2745 CHECK_EQ(test.resultD, outputs_D[i]);
2746 }
2747}
2748
2749
2750TEST(mul) {
2751 const int kTableLength = 4;
2752 CcTest::InitializeVM();
2753 Isolate* isolate = CcTest::i_isolate();
2754 HandleScope scope(isolate);
2755 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2756
2757 typedef struct test_float {
2758 float a;
2759 float b;
2760 float resultS;
2761 double c;
2762 double d;
2763 double resultD;
2764 }TestFloat;
2765
2766 TestFloat test;
2767 double inputfs_D[kTableLength] = {
2768 5.3, -5.3, 5.3, -2.9
2769 };
2770 double inputft_D[kTableLength] = {
2771 4.8, 4.8, -4.8, -0.29
2772 };
2773
2774 float inputfs_S[kTableLength] = {
2775 5.3, -5.3, 5.3, -2.9
2776 };
2777 float inputft_S[kTableLength] = {
2778 4.8, 4.8, -4.8, -0.29
2779 };
2780
2781 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
2782 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b)) );
2783 __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, c)) );
2784 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, d)) );
2785 __ mul_s(f10, f2, f4);
2786 __ mul_d(f12, f6, f8);
2787 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, resultS)) );
2788 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) );
2789 __ jr(ra);
2790 __ nop();
2791
2792 CodeDesc desc;
2793 assm.GetCode(&desc);
2794 Handle<Code> code = isolate->factory()->NewCode(
2795 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2796 F3 f = FUNCTION_CAST<F3>(code->entry());
2797 for (int i = 0; i < kTableLength; i++) {
2798 test.a = inputfs_S[i];
2799 test.b = inputft_S[i];
2800 test.c = inputfs_D[i];
2801 test.d = inputft_D[i];
2802 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2803 CHECK_EQ(test.resultS, inputfs_S[i]*inputft_S[i]);
2804 CHECK_EQ(test.resultD, inputfs_D[i]*inputft_D[i]);
2805 }
2806}
2807
2808
2809TEST(mov) {
2810 const int kTableLength = 4;
2811 CcTest::InitializeVM();
2812 Isolate* isolate = CcTest::i_isolate();
2813 HandleScope scope(isolate);
2814 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2815
2816 typedef struct test_float {
2817 double a;
2818 double b;
2819 float c;
2820 float d;
2821 }TestFloat;
2822
2823 TestFloat test;
2824 double inputs_D[kTableLength] = {
2825 5.3, -5.3, 5.3, -2.9
2826 };
2827 double inputs_S[kTableLength] = {
2828 4.8, 4.8, -4.8, -0.29
2829 };
2830
2831 float outputs_S[kTableLength] = {
2832 4.8, 4.8, -4.8, -0.29
2833 };
2834 double outputs_D[kTableLength] = {
2835 5.3, -5.3, 5.3, -2.9
2836 };
2837
2838 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)) );
2839 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, c)) );
2840 __ mov_s(f8, f6);
2841 __ mov_d(f10, f4);
2842 __ swc1(f8, MemOperand(a0, offsetof(TestFloat, d)) );
2843 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, b)) );
2844
2845 __ jr(ra);
2846 __ nop();
2847
2848 CodeDesc desc;
2849 assm.GetCode(&desc);
2850 Handle<Code> code = isolate->factory()->NewCode(
2851 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2852 F3 f = FUNCTION_CAST<F3>(code->entry());
2853 for (int i = 0; i < kTableLength; i++) {
2854 test.a = inputs_D[i];
2855 test.c = inputs_S[i];
2856
2857 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2858 CHECK_EQ(test.b, outputs_D[i]);
2859 CHECK_EQ(test.d, outputs_S[i]);
2860 }
2861}
2862
2863
2864TEST(floor_w) {
2865 CcTest::InitializeVM();
2866 Isolate* isolate = CcTest::i_isolate();
2867 HandleScope scope(isolate);
2868 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
2869
2870 typedef struct test_float {
2871 uint32_t isNaN2008;
2872 double a;
2873 float b;
2874 int32_t c; // a floor result
2875 int32_t d; // b floor result
2876 }Test;
2877 const int kTableLength = 15;
2878 double inputs_D[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<double>::quiet_NaN(),
2883 std::numeric_limits<double>::infinity()
2884 };
2885 float inputs_S[kTableLength] = {
2886 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2887 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2888 2147483648.0,
2889 std::numeric_limits<float>::quiet_NaN(),
2890 std::numeric_limits<float>::infinity()
2891 };
2892 double outputs[kTableLength] = {
2893 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2894 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
2895 kFPUInvalidResult, kFPUInvalidResult,
2896 kFPUInvalidResult};
2897 double outputsNaN2008[kTableLength] = {
2898 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2899 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
2900 kFPUInvalidResult,
2901 0,
2902 kFPUInvalidResult};
2903
2904 __ cfc1(t1, FCSR);
2905 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
2906 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2907 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
2908 __ floor_w_d(f8, f4);
2909 __ floor_w_s(f10, f6);
2910 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) );
2911 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) );
2912 __ jr(ra);
2913 __ nop();
2914 Test test;
2915 CodeDesc desc;
2916 assm.GetCode(&desc);
2917 Handle<Code> code = isolate->factory()->NewCode(
2918 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2919 F3 f = FUNCTION_CAST<F3>(code->entry());
2920 for (int i = 0; i < kTableLength; i++) {
2921 test.a = inputs_D[i];
2922 test.b = inputs_S[i];
2923 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2924 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips32r6) {
2925 CHECK_EQ(test.c, outputsNaN2008[i]);
2926 } else {
2927 CHECK_EQ(test.c, outputs[i]);
2928 }
2929 CHECK_EQ(test.d, test.c);
2930 }
2931}
2932
2933
2934TEST(floor_l) {
2935 if (IsFp64Mode()) {
2936 CcTest::InitializeVM();
2937 Isolate* isolate = CcTest::i_isolate();
2938 HandleScope scope(isolate);
2939 MacroAssembler assm(isolate, NULL, 0,
2940 v8::internal::CodeObjectRequired::kYes);
2941 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult);
2942 typedef struct test_float {
2943 uint32_t isNaN2008;
2944 double a;
2945 float b;
2946 int64_t c;
2947 int64_t d;
2948 }Test;
2949 const int kTableLength = 15;
2950 double inputs_D[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<double>::quiet_NaN(),
2955 std::numeric_limits<double>::infinity()
2956 };
2957 float inputs_S[kTableLength] = {
2958 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
2959 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
2960 2147483648.0,
2961 std::numeric_limits<float>::quiet_NaN(),
2962 std::numeric_limits<float>::infinity()
2963 };
2964 double outputs[kTableLength] = {
2965 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2966 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
2967 2147483648.0, dFPU64InvalidResult,
2968 dFPU64InvalidResult};
2969 double outputsNaN2008[kTableLength] = {
2970 2.0, 2.0, 2.0, 3.0, 3.0, 3.0,
2971 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0,
2972 2147483648.0,
2973 0,
2974 dFPU64InvalidResult};
2975
2976 __ cfc1(t1, FCSR);
2977 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
2978 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
2979 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
2980 __ floor_l_d(f8, f4);
2981 __ floor_l_s(f10, f6);
2982 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) );
2983 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) );
2984 __ jr(ra);
2985 __ nop();
2986 Test test;
2987 CodeDesc desc;
2988 assm.GetCode(&desc);
2989 Handle<Code> code = isolate->factory()->NewCode(
2990 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2991 F3 f = FUNCTION_CAST<F3>(code->entry());
2992 for (int i = 0; i < kTableLength; i++) {
2993 test.a = inputs_D[i];
2994 test.b = inputs_S[i];
2995 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
2996 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) &&
2997 kArchVariant == kMips32r6) {
2998 CHECK_EQ(test.c, outputsNaN2008[i]);
2999 } else {
3000 CHECK_EQ(test.c, outputs[i]);
3001 }
3002 CHECK_EQ(test.d, test.c);
3003 }
3004 }
3005}
3006
3007
3008TEST(ceil_w) {
3009 CcTest::InitializeVM();
3010 Isolate* isolate = CcTest::i_isolate();
3011 HandleScope scope(isolate);
3012 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
3013
3014 typedef struct test_float {
3015 uint32_t isNaN2008;
3016 double a;
3017 float b;
3018 int32_t c; // a floor result
3019 int32_t d; // b floor result
3020 }Test;
3021 const int kTableLength = 15;
3022 double inputs_D[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<double>::quiet_NaN(),
3027 std::numeric_limits<double>::infinity()
3028 };
3029 float inputs_S[kTableLength] = {
3030 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
3031 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
3032 2147483648.0,
3033 std::numeric_limits<float>::quiet_NaN(),
3034 std::numeric_limits<float>::infinity()
3035 };
3036 double outputs[kTableLength] = {
3037 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
3038 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
3039 kFPUInvalidResult, kFPUInvalidResult,
3040 kFPUInvalidResult};
3041 double outputsNaN2008[kTableLength] = {
3042 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
3043 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
3044 kFPUInvalidResult,
3045 0,
3046 kFPUInvalidResult};
3047
3048 __ cfc1(t1, FCSR);
3049 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
3050 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
3051 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
3052 __ ceil_w_d(f8, f4);
3053 __ ceil_w_s(f10, f6);
3054 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) );
3055 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) );
3056 __ jr(ra);
3057 __ nop();
3058 Test test;
3059 CodeDesc desc;
3060 assm.GetCode(&desc);
3061 Handle<Code> code = isolate->factory()->NewCode(
3062 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3063 F3 f = FUNCTION_CAST<F3>(code->entry());
3064 for (int i = 0; i < kTableLength; i++) {
3065 test.a = inputs_D[i];
3066 test.b = inputs_S[i];
3067 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3068 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips32r6) {
3069 CHECK_EQ(test.c, outputsNaN2008[i]);
3070 } else {
3071 CHECK_EQ(test.c, outputs[i]);
3072 }
3073 CHECK_EQ(test.d, test.c);
3074 }
3075}
3076
3077
3078TEST(ceil_l) {
3079 if (IsFp64Mode()) {
3080 CcTest::InitializeVM();
3081 Isolate* isolate = CcTest::i_isolate();
3082 HandleScope scope(isolate);
3083 MacroAssembler assm(isolate, NULL, 0,
3084 v8::internal::CodeObjectRequired::kYes);
3085 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult);
3086 typedef struct test_float {
3087 uint32_t isNaN2008;
3088 double a;
3089 float b;
3090 int64_t c;
3091 int64_t d;
3092 }Test;
3093 const int kTableLength = 15;
3094 double inputs_D[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<double>::quiet_NaN(),
3099 std::numeric_limits<double>::infinity()
3100 };
3101 float inputs_S[kTableLength] = {
3102 2.1, 2.6, 2.5, 3.1, 3.6, 3.5,
3103 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5,
3104 2147483648.0,
3105 std::numeric_limits<float>::quiet_NaN(),
3106 std::numeric_limits<float>::infinity()
3107 };
3108 double outputs[kTableLength] = {
3109 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
3110 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
3111 2147483648.0, dFPU64InvalidResult,
3112 dFPU64InvalidResult};
3113 double outputsNaN2008[kTableLength] = {
3114 3.0, 3.0, 3.0, 4.0, 4.0, 4.0,
3115 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0,
3116 2147483648.0,
3117 0,
3118 dFPU64InvalidResult};
3119
3120 __ cfc1(t1, FCSR);
3121 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008)));
3122 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) );
3123 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) );
3124 __ ceil_l_d(f8, f4);
3125 __ ceil_l_s(f10, f6);
3126 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) );
3127 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) );
3128 __ jr(ra);
3129 __ nop();
3130 Test test;
3131 CodeDesc desc;
3132 assm.GetCode(&desc);
3133 Handle<Code> code = isolate->factory()->NewCode(
3134 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3135 F3 f = FUNCTION_CAST<F3>(code->entry());
3136 for (int i = 0; i < kTableLength; i++) {
3137 test.a = inputs_D[i];
3138 test.b = inputs_S[i];
3139 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3140 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) &&
3141 kArchVariant == kMips32r6) {
3142 CHECK_EQ(test.c, outputsNaN2008[i]);
3143 } else {
3144 CHECK_EQ(test.c, outputs[i]);
3145 }
3146 CHECK_EQ(test.d, test.c);
3147 }
3148 }
3149}
3150
3151
3152TEST(jump_tables1) {
3153 // Test jump tables with forward jumps.
3154 CcTest::InitializeVM();
3155 Isolate* isolate = CcTest::i_isolate();
3156 HandleScope scope(isolate);
3157 Assembler assm(isolate, nullptr, 0);
3158
3159 const int kNumCases = 512;
3160 int values[kNumCases];
3161 isolate->random_number_generator()->NextBytes(values, sizeof(values));
3162 Label labels[kNumCases];
3163
3164 __ addiu(sp, sp, -4);
3165 __ sw(ra, MemOperand(sp));
3166
3167 Label done;
3168 {
3169 __ BlockTrampolinePoolFor(kNumCases + 7);
3170 PredictableCodeSizeScope predictable(
3171 &assm, (kNumCases + 7) * Assembler::kInstrSize);
3172 Label here;
3173
3174 __ bal(&here);
3175 __ nop();
3176 __ bind(&here);
3177 __ sll(at, a0, 2);
3178 __ addu(at, at, ra);
3179 __ lw(at, MemOperand(at, 5 * Assembler::kInstrSize));
3180 __ jr(at);
3181 __ nop();
3182 for (int i = 0; i < kNumCases; ++i) {
3183 __ dd(&labels[i]);
3184 }
3185 }
3186
3187 for (int i = 0; i < kNumCases; ++i) {
3188 __ bind(&labels[i]);
3189 __ lui(v0, (values[i] >> 16) & 0xffff);
3190 __ ori(v0, v0, values[i] & 0xffff);
3191 __ b(&done);
3192 __ nop();
3193 }
3194
3195 __ bind(&done);
3196 __ lw(ra, MemOperand(sp));
3197 __ addiu(sp, sp, 4);
3198 __ jr(ra);
3199 __ nop();
3200
3201 CodeDesc desc;
3202 assm.GetCode(&desc);
3203 Handle<Code> code = isolate->factory()->NewCode(
3204 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3205#ifdef OBJECT_PRINT
3206 code->Print(std::cout);
3207#endif
3208 F1 f = FUNCTION_CAST<F1>(code->entry());
3209 for (int i = 0; i < kNumCases; ++i) {
3210 int res = reinterpret_cast<int>(
3211 CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0));
3212 ::printf("f(%d) = %d\n", i, res);
3213 CHECK_EQ(values[i], res);
3214 }
3215}
3216
3217
3218TEST(jump_tables2) {
3219 // Test jump tables with backward jumps.
3220 CcTest::InitializeVM();
3221 Isolate* isolate = CcTest::i_isolate();
3222 HandleScope scope(isolate);
3223 Assembler assm(isolate, nullptr, 0);
3224
3225 const int kNumCases = 512;
3226 int values[kNumCases];
3227 isolate->random_number_generator()->NextBytes(values, sizeof(values));
3228 Label labels[kNumCases];
3229
3230 __ addiu(sp, sp, -4);
3231 __ sw(ra, MemOperand(sp));
3232
3233 Label done, dispatch;
3234 __ b(&dispatch);
3235 __ nop();
3236
3237 for (int i = 0; i < kNumCases; ++i) {
3238 __ bind(&labels[i]);
3239 __ lui(v0, (values[i] >> 16) & 0xffff);
3240 __ ori(v0, v0, values[i] & 0xffff);
3241 __ b(&done);
3242 __ nop();
3243 }
3244
3245 __ bind(&dispatch);
3246 {
3247 __ BlockTrampolinePoolFor(kNumCases + 7);
3248 PredictableCodeSizeScope predictable(
3249 &assm, (kNumCases + 7) * Assembler::kInstrSize);
3250 Label here;
3251
3252 __ bal(&here);
3253 __ nop();
3254 __ bind(&here);
3255 __ sll(at, a0, 2);
3256 __ addu(at, at, ra);
3257 __ lw(at, MemOperand(at, 5 * Assembler::kInstrSize));
3258 __ jr(at);
3259 __ nop();
3260 for (int i = 0; i < kNumCases; ++i) {
3261 __ dd(&labels[i]);
3262 }
3263 }
3264
3265 __ bind(&done);
3266 __ lw(ra, MemOperand(sp));
3267 __ addiu(sp, sp, 4);
3268 __ jr(ra);
3269 __ nop();
3270
3271 CodeDesc desc;
3272 assm.GetCode(&desc);
3273 Handle<Code> code = isolate->factory()->NewCode(
3274 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3275#ifdef OBJECT_PRINT
3276 code->Print(std::cout);
3277#endif
3278 F1 f = FUNCTION_CAST<F1>(code->entry());
3279 for (int i = 0; i < kNumCases; ++i) {
3280 int res = reinterpret_cast<int>(
3281 CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0));
3282 ::printf("f(%d) = %d\n", i, res);
3283 CHECK_EQ(values[i], res);
3284 }
3285}
3286
3287
3288TEST(jump_tables3) {
3289 // Test jump tables with backward jumps and embedded heap objects.
3290 CcTest::InitializeVM();
3291 Isolate* isolate = CcTest::i_isolate();
3292 HandleScope scope(isolate);
3293 Assembler assm(isolate, nullptr, 0);
3294
3295 const int kNumCases = 256;
3296 Handle<Object> values[kNumCases];
3297 for (int i = 0; i < kNumCases; ++i) {
3298 double value = isolate->random_number_generator()->NextDouble();
3299 values[i] = isolate->factory()->NewHeapNumber(value, IMMUTABLE, TENURED);
3300 }
3301 Label labels[kNumCases];
3302 Object* obj;
3303 int32_t imm32;
3304
3305 __ addiu(sp, sp, -4);
3306 __ sw(ra, MemOperand(sp));
3307
3308 Label done, dispatch;
3309 __ b(&dispatch);
3310
3311
3312 for (int i = 0; i < kNumCases; ++i) {
3313 __ bind(&labels[i]);
3314 obj = *values[i];
3315 imm32 = reinterpret_cast<intptr_t>(obj);
3316 __ lui(v0, (imm32 >> 16) & 0xffff);
3317 __ ori(v0, v0, imm32 & 0xffff);
3318 __ b(&done);
3319 __ nop();
3320 }
3321
3322 __ bind(&dispatch);
3323 {
3324 __ BlockTrampolinePoolFor(kNumCases + 7);
3325 PredictableCodeSizeScope predictable(
3326 &assm, (kNumCases + 7) * Assembler::kInstrSize);
3327 Label here;
3328
3329 __ bal(&here);
3330 __ nop();
3331 __ bind(&here);
3332 __ sll(at, a0, 2);
3333 __ addu(at, at, ra);
3334 __ lw(at, MemOperand(at, 5 * Assembler::kInstrSize));
3335 __ jr(at);
3336 __ nop();
3337 for (int i = 0; i < kNumCases; ++i) {
3338 __ dd(&labels[i]);
3339 }
3340 }
3341
3342 __ bind(&done);
3343 __ lw(ra, MemOperand(sp));
3344 __ addiu(sp, sp, 4);
3345 __ jr(ra);
3346 __ nop();
3347
3348 CodeDesc desc;
3349 assm.GetCode(&desc);
3350 Handle<Code> code = isolate->factory()->NewCode(
3351 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3352#ifdef OBJECT_PRINT
3353 code->Print(std::cout);
3354#endif
3355 F1 f = FUNCTION_CAST<F1>(code->entry());
3356 for (int i = 0; i < kNumCases; ++i) {
3357 Handle<Object> result(
3358 CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0), isolate);
3359#ifdef OBJECT_PRINT
3360 ::printf("f(%d) = ", i);
3361 result->Print(std::cout);
3362 ::printf("\n");
3363#endif
3364 CHECK(values[i].is_identical_to(result));
3365 }
3366}
3367
3368
3369TEST(BITSWAP) {
3370 // Test BITSWAP
3371 if (IsMipsArchVariant(kMips32r6)) {
3372 CcTest::InitializeVM();
3373 Isolate* isolate = CcTest::i_isolate();
3374 HandleScope scope(isolate);
3375
3376 typedef struct {
3377 int32_t r1;
3378 int32_t r2;
3379 int32_t r3;
3380 int32_t r4;
3381 } T;
3382 T t;
3383
3384 Assembler assm(isolate, NULL, 0);
3385
3386 __ lw(a2, MemOperand(a0, offsetof(T, r1)));
3387 __ nop();
3388 __ bitswap(a1, a2);
3389 __ sw(a1, MemOperand(a0, offsetof(T, r1)));
3390
3391 __ lw(a2, MemOperand(a0, offsetof(T, r2)));
3392 __ nop();
3393 __ bitswap(a1, a2);
3394 __ sw(a1, MemOperand(a0, offsetof(T, r2)));
3395
3396 __ jr(ra);
3397 __ nop();
3398
3399 CodeDesc desc;
3400 assm.GetCode(&desc);
3401 Handle<Code> code = isolate->factory()->NewCode(
3402 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3403 F3 f = FUNCTION_CAST<F3>(code->entry());
3404 t.r1 = 0x781A15C3;
3405 t.r2 = 0x8B71FCDE;
3406 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
3407 USE(dummy);
3408
3409 CHECK_EQ(static_cast<int32_t>(0x1E58A8C3), t.r1);
3410 CHECK_EQ(static_cast<int32_t>(0xD18E3F7B), t.r2);
3411 }
3412}
3413
3414
3415TEST(class_fmt) {
3416 if (IsMipsArchVariant(kMips32r6)) {
3417 // Test CLASS.fmt instruction.
3418 CcTest::InitializeVM();
3419 Isolate* isolate = CcTest::i_isolate();
3420 HandleScope scope(isolate);
3421
3422 typedef struct {
3423 double dSignalingNan;
3424 double dQuietNan;
3425 double dNegInf;
3426 double dNegNorm;
3427 double dNegSubnorm;
3428 double dNegZero;
3429 double dPosInf;
3430 double dPosNorm;
3431 double dPosSubnorm;
3432 double dPosZero;
3433 float fSignalingNan;
3434 float fQuietNan;
3435 float fNegInf;
3436 float fNegNorm;
3437 float fNegSubnorm;
3438 float fNegZero;
3439 float fPosInf;
3440 float fPosNorm;
3441 float fPosSubnorm;
3442 float fPosZero; } T;
3443 T t;
3444
3445 // Create a function that accepts &t, and loads, manipulates, and stores
3446 // the doubles t.a ... t.f.
3447 MacroAssembler assm(isolate, NULL, 0,
3448 v8::internal::CodeObjectRequired::kYes);
3449
3450 __ ldc1(f4, MemOperand(a0, offsetof(T, dSignalingNan)));
3451 __ class_d(f6, f4);
3452 __ sdc1(f6, MemOperand(a0, offsetof(T, dSignalingNan)));
3453
3454 __ ldc1(f4, MemOperand(a0, offsetof(T, dQuietNan)));
3455 __ class_d(f6, f4);
3456 __ sdc1(f6, MemOperand(a0, offsetof(T, dQuietNan)));
3457
3458 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegInf)));
3459 __ class_d(f6, f4);
3460 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegInf)));
3461
3462 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegNorm)));
3463 __ class_d(f6, f4);
3464 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegNorm)));
3465
3466 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegSubnorm)));
3467 __ class_d(f6, f4);
3468 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegSubnorm)));
3469
3470 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegZero)));
3471 __ class_d(f6, f4);
3472 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegZero)));
3473
3474 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosInf)));
3475 __ class_d(f6, f4);
3476 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosInf)));
3477
3478 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosNorm)));
3479 __ class_d(f6, f4);
3480 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosNorm)));
3481
3482 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosSubnorm)));
3483 __ class_d(f6, f4);
3484 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosSubnorm)));
3485
3486 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosZero)));
3487 __ class_d(f6, f4);
3488 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosZero)));
3489
3490 // Testing instruction CLASS.S
3491 __ lwc1(f4, MemOperand(a0, offsetof(T, fSignalingNan)));
3492 __ class_s(f6, f4);
3493 __ swc1(f6, MemOperand(a0, offsetof(T, fSignalingNan)));
3494
3495 __ lwc1(f4, MemOperand(a0, offsetof(T, fQuietNan)));
3496 __ class_s(f6, f4);
3497 __ swc1(f6, MemOperand(a0, offsetof(T, fQuietNan)));
3498
3499 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegInf)));
3500 __ class_s(f6, f4);
3501 __ swc1(f6, MemOperand(a0, offsetof(T, fNegInf)));
3502
3503 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegNorm)));
3504 __ class_s(f6, f4);
3505 __ swc1(f6, MemOperand(a0, offsetof(T, fNegNorm)));
3506
3507 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegSubnorm)));
3508 __ class_s(f6, f4);
3509 __ swc1(f6, MemOperand(a0, offsetof(T, fNegSubnorm)));
3510
3511 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegZero)));
3512 __ class_s(f6, f4);
3513 __ swc1(f6, MemOperand(a0, offsetof(T, fNegZero)));
3514
3515 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosInf)));
3516 __ class_s(f6, f4);
3517 __ swc1(f6, MemOperand(a0, offsetof(T, fPosInf)));
3518
3519 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosNorm)));
3520 __ class_s(f6, f4);
3521 __ swc1(f6, MemOperand(a0, offsetof(T, fPosNorm)));
3522
3523 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosSubnorm)));
3524 __ class_s(f6, f4);
3525 __ swc1(f6, MemOperand(a0, offsetof(T, fPosSubnorm)));
3526
3527 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosZero)));
3528 __ class_s(f6, f4);
3529 __ swc1(f6, MemOperand(a0, offsetof(T, fPosZero)));
3530
3531 __ jr(ra);
3532 __ nop();
3533
3534 CodeDesc desc;
3535 assm.GetCode(&desc);
3536 Handle<Code> code = isolate->factory()->NewCode(
3537 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3538 F3 f = FUNCTION_CAST<F3>(code->entry());
3539
3540 t.dSignalingNan = std::numeric_limits<double>::signaling_NaN();
3541 t.dQuietNan = std::numeric_limits<double>::quiet_NaN();
3542 t.dNegInf = -1.0 / 0.0;
3543 t.dNegNorm = -5.0;
3544 t.dNegSubnorm = -DBL_MIN / 2.0;
3545 t.dNegZero = -0.0;
3546 t.dPosInf = 2.0 / 0.0;
3547 t.dPosNorm = 275.35;
3548 t.dPosSubnorm = DBL_MIN / 2.0;
3549 t.dPosZero = +0.0;
3550 // Float test values
3551
3552 t.fSignalingNan = std::numeric_limits<float>::signaling_NaN();
3553 t.fQuietNan = std::numeric_limits<float>::quiet_NaN();
3554 t.fNegInf = -0.5/0.0;
3555 t.fNegNorm = -FLT_MIN;
3556 t.fNegSubnorm = -FLT_MIN / 1.5;
3557 t.fNegZero = -0.0;
3558 t.fPosInf = 100000.0 / 0.0;
3559 t.fPosNorm = FLT_MAX;
3560 t.fPosSubnorm = FLT_MIN / 20.0;
3561 t.fPosZero = +0.0;
3562
3563 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
3564 USE(dummy);
3565 // Expected double results.
3566 CHECK_EQ(bit_cast<int64_t>(t.dSignalingNan), 0x001);
3567 CHECK_EQ(bit_cast<int64_t>(t.dQuietNan), 0x002);
3568 CHECK_EQ(bit_cast<int64_t>(t.dNegInf), 0x004);
3569 CHECK_EQ(bit_cast<int64_t>(t.dNegNorm), 0x008);
3570 CHECK_EQ(bit_cast<int64_t>(t.dNegSubnorm), 0x010);
3571 CHECK_EQ(bit_cast<int64_t>(t.dNegZero), 0x020);
3572 CHECK_EQ(bit_cast<int64_t>(t.dPosInf), 0x040);
3573 CHECK_EQ(bit_cast<int64_t>(t.dPosNorm), 0x080);
3574 CHECK_EQ(bit_cast<int64_t>(t.dPosSubnorm), 0x100);
3575 CHECK_EQ(bit_cast<int64_t>(t.dPosZero), 0x200);
3576
3577 // Expected float results.
3578 CHECK_EQ(bit_cast<int32_t>(t.fSignalingNan), 0x001);
3579 CHECK_EQ(bit_cast<int32_t>(t.fQuietNan), 0x002);
3580 CHECK_EQ(bit_cast<int32_t>(t.fNegInf), 0x004);
3581 CHECK_EQ(bit_cast<int32_t>(t.fNegNorm), 0x008);
3582 CHECK_EQ(bit_cast<int32_t>(t.fNegSubnorm), 0x010);
3583 CHECK_EQ(bit_cast<int32_t>(t.fNegZero), 0x020);
3584 CHECK_EQ(bit_cast<int32_t>(t.fPosInf), 0x040);
3585 CHECK_EQ(bit_cast<int32_t>(t.fPosNorm), 0x080);
3586 CHECK_EQ(bit_cast<int32_t>(t.fPosSubnorm), 0x100);
3587 CHECK_EQ(bit_cast<int32_t>(t.fPosZero), 0x200);
3588 }
3589}
3590
3591
3592TEST(ABS) {
3593 CcTest::InitializeVM();
3594 Isolate* isolate = CcTest::i_isolate();
3595 HandleScope scope(isolate);
3596 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
3597
3598 typedef struct test_float {
3599 int64_t fir;
3600 double a;
3601 float b;
3602 double fcsr;
3603 } TestFloat;
3604
3605 TestFloat test;
3606
3607 // Save FIR.
3608 __ cfc1(a1, FCSR);
3609 // Disable FPU exceptions.
3610 __ ctc1(zero_reg, FCSR);
3611
3612 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)));
3613 __ abs_d(f10, f4);
3614 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, a)));
3615
3616 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b)));
3617 __ abs_s(f10, f4);
3618 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, b)));
3619
3620 // Restore FCSR.
3621 __ ctc1(a1, FCSR);
3622
3623 __ jr(ra);
3624 __ nop();
3625
3626 CodeDesc desc;
3627 assm.GetCode(&desc);
3628 Handle<Code> code = isolate->factory()->NewCode(
3629 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3630 F3 f = FUNCTION_CAST<F3>(code->entry());
3631 test.a = -2.0;
3632 test.b = -2.0;
3633 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3634 CHECK_EQ(test.a, 2.0);
3635 CHECK_EQ(test.b, 2.0);
3636
3637 test.a = 2.0;
3638 test.b = 2.0;
3639 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3640 CHECK_EQ(test.a, 2.0);
3641 CHECK_EQ(test.b, 2.0);
3642
3643 // Testing biggest positive number
3644 test.a = std::numeric_limits<double>::max();
3645 test.b = std::numeric_limits<float>::max();
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 negative number
3651 test.a = -std::numeric_limits<double>::max(); // lowest()
3652 test.b = -std::numeric_limits<float>::max(); // lowest()
3653 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3654 CHECK_EQ(test.a, std::numeric_limits<double>::max());
3655 CHECK_EQ(test.b, std::numeric_limits<float>::max());
3656
3657 // Testing smallest positive number
3658 test.a = -std::numeric_limits<double>::min();
3659 test.b = -std::numeric_limits<float>::min();
3660 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3661 CHECK_EQ(test.a, std::numeric_limits<double>::min());
3662 CHECK_EQ(test.b, std::numeric_limits<float>::min());
3663
3664 // Testing infinity
3665 test.a = -std::numeric_limits<double>::max()
3666 / std::numeric_limits<double>::min();
3667 test.b = -std::numeric_limits<float>::max()
3668 / std::numeric_limits<float>::min();
3669 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3670 CHECK_EQ(test.a, std::numeric_limits<double>::max()
3671 / std::numeric_limits<double>::min());
3672 CHECK_EQ(test.b, std::numeric_limits<float>::max()
3673 / std::numeric_limits<float>::min());
3674
3675 test.a = std::numeric_limits<double>::quiet_NaN();
3676 test.b = std::numeric_limits<float>::quiet_NaN();
3677 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3678 CHECK_EQ(std::isnan(test.a), true);
3679 CHECK_EQ(std::isnan(test.b), true);
3680
3681 test.a = std::numeric_limits<double>::signaling_NaN();
3682 test.b = std::numeric_limits<float>::signaling_NaN();
3683 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3684 CHECK_EQ(std::isnan(test.a), true);
3685 CHECK_EQ(std::isnan(test.b), true);
3686}
3687
3688
3689TEST(ADD_FMT) {
3690 CcTest::InitializeVM();
3691 Isolate* isolate = CcTest::i_isolate();
3692 HandleScope scope(isolate);
3693 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
3694
3695 typedef struct test_float {
3696 double a;
3697 double b;
3698 double c;
3699 float fa;
3700 float fb;
3701 float fc;
3702 } TestFloat;
3703
3704 TestFloat test;
3705
3706 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)));
3707 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b)));
3708 __ add_d(f10, f8, f4);
3709 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c)));
3710
3711 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, fa)));
3712 __ lwc1(f8, MemOperand(a0, offsetof(TestFloat, fb)));
3713 __ add_s(f10, f8, f4);
3714 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, fc)));
3715
3716 __ jr(ra);
3717 __ nop();
3718
3719 CodeDesc desc;
3720 assm.GetCode(&desc);
3721 Handle<Code> code = isolate->factory()->NewCode(
3722 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3723 F3 f = FUNCTION_CAST<F3>(code->entry());
3724 test.a = 2.0;
3725 test.b = 3.0;
3726 test.fa = 2.0;
3727 test.fb = 3.0;
3728 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3729 CHECK_EQ(test.c, 5.0);
3730 CHECK_EQ(test.fc, 5.0);
3731
3732 test.a = std::numeric_limits<double>::max();
3733 test.b = -std::numeric_limits<double>::max(); // lowest()
3734 test.fa = std::numeric_limits<float>::max();
3735 test.fb = -std::numeric_limits<float>::max(); // lowest()
3736 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3737 CHECK_EQ(test.c, 0.0);
3738 CHECK_EQ(test.fc, 0.0);
3739
3740 test.a = std::numeric_limits<double>::max();
3741 test.b = std::numeric_limits<double>::max();
3742 test.fa = std::numeric_limits<float>::max();
3743 test.fb = std::numeric_limits<float>::max();
3744 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3745 CHECK_EQ(std::isfinite(test.c), false);
3746 CHECK_EQ(std::isfinite(test.fc), false);
3747
3748 test.a = 5.0;
3749 test.b = std::numeric_limits<double>::signaling_NaN();
3750 test.fa = 5.0;
3751 test.fb = std::numeric_limits<float>::signaling_NaN();
3752 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3753 CHECK_EQ(std::isnan(test.c), true);
3754 CHECK_EQ(std::isnan(test.fc), true);
3755}
3756
3757
3758TEST(C_COND_FMT) {
3759 if ((IsMipsArchVariant(kMips32r1)) || (IsMipsArchVariant(kMips32r2))) {
3760 CcTest::InitializeVM();
3761 Isolate* isolate = CcTest::i_isolate();
3762 HandleScope scope(isolate);
3763 MacroAssembler assm(isolate, NULL, 0,
3764 v8::internal::CodeObjectRequired::kYes);
3765
3766 typedef struct test_float {
3767 double dOp1;
3768 double dOp2;
3769 uint32_t dF;
3770 uint32_t dUn;
3771 uint32_t dEq;
3772 uint32_t dUeq;
3773 uint32_t dOlt;
3774 uint32_t dUlt;
3775 uint32_t dOle;
3776 uint32_t dUle;
3777 float fOp1;
3778 float fOp2;
3779 uint32_t fF;
3780 uint32_t fUn;
3781 uint32_t fEq;
3782 uint32_t fUeq;
3783 uint32_t fOlt;
3784 uint32_t fUlt;
3785 uint32_t fOle;
3786 uint32_t fUle;
3787 } TestFloat;
3788
3789 TestFloat test;
3790
3791 __ li(t1, 1);
3792
3793 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, dOp1)));
3794 __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, dOp2)));
3795
3796 __ lwc1(f14, MemOperand(a0, offsetof(TestFloat, fOp1)));
3797 __ lwc1(f16, MemOperand(a0, offsetof(TestFloat, fOp2)));
3798
3799 __ mov(t2, zero_reg);
3800 __ mov(t3, zero_reg);
3801 __ c_d(F, f4, f6, 0);
3802 __ c_s(F, f14, f16, 2);
3803 __ movt(t2, t1, 0);
3804 __ movt(t3, t1, 2);
3805 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dF)) );
3806 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fF)) );
3807
3808 __ mov(t2, zero_reg);
3809 __ mov(t3, zero_reg);
3810 __ c_d(UN, f4, f6, 2);
3811 __ c_s(UN, f14, f16, 4);
3812 __ movt(t2, t1, 2);
3813 __ movt(t3, t1, 4);
3814 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUn)) );
3815 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUn)) );
3816
3817 __ mov(t2, zero_reg);
3818 __ mov(t3, zero_reg);
3819 __ c_d(EQ, f4, f6, 4);
3820 __ c_s(EQ, f14, f16, 6);
3821 __ movt(t2, t1, 4);
3822 __ movt(t3, t1, 6);
3823 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dEq)) );
3824 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fEq)) );
3825
3826 __ mov(t2, zero_reg);
3827 __ mov(t3, zero_reg);
3828 __ c_d(UEQ, f4, f6, 6);
3829 __ c_s(UEQ, f14, f16, 0);
3830 __ movt(t2, t1, 6);
3831 __ movt(t3, t1, 0);
3832 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUeq)) );
3833 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUeq)) );
3834
3835 __ mov(t2, zero_reg);
3836 __ mov(t3, zero_reg);
3837 __ c_d(OLT, f4, f6, 0);
3838 __ c_s(OLT, f14, f16, 2);
3839 __ movt(t2, t1, 0);
3840 __ movt(t3, t1, 2);
3841 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dOlt)) );
3842 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fOlt)) );
3843
3844 __ mov(t2, zero_reg);
3845 __ mov(t3, zero_reg);
3846 __ c_d(ULT, f4, f6, 2);
3847 __ c_s(ULT, f14, f16, 4);
3848 __ movt(t2, t1, 2);
3849 __ movt(t3, t1, 4);
3850 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUlt)) );
3851 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUlt)) );
3852
3853 __ mov(t2, zero_reg);
3854 __ mov(t3, zero_reg);
3855 __ c_d(OLE, f4, f6, 4);
3856 __ c_s(OLE, f14, f16, 6);
3857 __ movt(t2, t1, 4);
3858 __ movt(t3, t1, 6);
3859 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dOle)) );
3860 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fOle)) );
3861
3862 __ mov(t2, zero_reg);
3863 __ mov(t3, zero_reg);
3864 __ c_d(ULE, f4, f6, 6);
3865 __ c_s(ULE, f14, f16, 0);
3866 __ movt(t2, t1, 6);
3867 __ movt(t3, t1, 0);
3868 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUle)) );
3869 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUle)) );
3870
3871 __ jr(ra);
3872 __ nop();
3873
3874 CodeDesc desc;
3875 assm.GetCode(&desc);
3876 Handle<Code> code = isolate->factory()->NewCode(
3877 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3878 F3 f = FUNCTION_CAST<F3>(code->entry());
3879 test.dOp1 = 2.0;
3880 test.dOp2 = 3.0;
3881 test.fOp1 = 2.0;
3882 test.fOp2 = 3.0;
3883 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3884 CHECK_EQ(test.dF, 0U);
3885 CHECK_EQ(test.dUn, 0U);
3886 CHECK_EQ(test.dEq, 0U);
3887 CHECK_EQ(test.dUeq, 0U);
3888 CHECK_EQ(test.dOlt, 1U);
3889 CHECK_EQ(test.dUlt, 1U);
3890 CHECK_EQ(test.dOle, 1U);
3891 CHECK_EQ(test.dUle, 1U);
3892 CHECK_EQ(test.fF, 0U);
3893 CHECK_EQ(test.fUn, 0U);
3894 CHECK_EQ(test.fEq, 0U);
3895 CHECK_EQ(test.fUeq, 0U);
3896 CHECK_EQ(test.fOlt, 1U);
3897 CHECK_EQ(test.fUlt, 1U);
3898 CHECK_EQ(test.fOle, 1U);
3899 CHECK_EQ(test.fUle, 1U);
3900
3901 test.dOp1 = std::numeric_limits<double>::max();
3902 test.dOp2 = std::numeric_limits<double>::min();
3903 test.fOp1 = std::numeric_limits<float>::min();
3904 test.fOp2 = -std::numeric_limits<float>::max(); // lowest()
3905 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3906 CHECK_EQ(test.dF, 0U);
3907 CHECK_EQ(test.dUn, 0U);
3908 CHECK_EQ(test.dEq, 0U);
3909 CHECK_EQ(test.dUeq, 0U);
3910 CHECK_EQ(test.dOlt, 0U);
3911 CHECK_EQ(test.dUlt, 0U);
3912 CHECK_EQ(test.dOle, 0U);
3913 CHECK_EQ(test.dUle, 0U);
3914 CHECK_EQ(test.fF, 0U);
3915 CHECK_EQ(test.fUn, 0U);
3916 CHECK_EQ(test.fEq, 0U);
3917 CHECK_EQ(test.fUeq, 0U);
3918 CHECK_EQ(test.fOlt, 0U);
3919 CHECK_EQ(test.fUlt, 0U);
3920 CHECK_EQ(test.fOle, 0U);
3921 CHECK_EQ(test.fUle, 0U);
3922
3923 test.dOp1 = -std::numeric_limits<double>::max(); // lowest()
3924 test.dOp2 = -std::numeric_limits<double>::max(); // lowest()
3925 test.fOp1 = std::numeric_limits<float>::max();
3926 test.fOp2 = std::numeric_limits<float>::max();
3927 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3928 CHECK_EQ(test.dF, 0U);
3929 CHECK_EQ(test.dUn, 0U);
3930 CHECK_EQ(test.dEq, 1U);
3931 CHECK_EQ(test.dUeq, 1U);
3932 CHECK_EQ(test.dOlt, 0U);
3933 CHECK_EQ(test.dUlt, 0U);
3934 CHECK_EQ(test.dOle, 1U);
3935 CHECK_EQ(test.dUle, 1U);
3936 CHECK_EQ(test.fF, 0U);
3937 CHECK_EQ(test.fUn, 0U);
3938 CHECK_EQ(test.fEq, 1U);
3939 CHECK_EQ(test.fUeq, 1U);
3940 CHECK_EQ(test.fOlt, 0U);
3941 CHECK_EQ(test.fUlt, 0U);
3942 CHECK_EQ(test.fOle, 1U);
3943 CHECK_EQ(test.fUle, 1U);
3944
3945 test.dOp1 = std::numeric_limits<double>::quiet_NaN();
3946 test.dOp2 = 0.0;
3947 test.fOp1 = std::numeric_limits<float>::quiet_NaN();
3948 test.fOp2 = 0.0;
3949 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
3950 CHECK_EQ(test.dF, 0U);
3951 CHECK_EQ(test.dUn, 1U);
3952 CHECK_EQ(test.dEq, 0U);
3953 CHECK_EQ(test.dUeq, 1U);
3954 CHECK_EQ(test.dOlt, 0U);
3955 CHECK_EQ(test.dUlt, 1U);
3956 CHECK_EQ(test.dOle, 0U);
3957 CHECK_EQ(test.dUle, 1U);
3958 CHECK_EQ(test.fF, 0U);
3959 CHECK_EQ(test.fUn, 1U);
3960 CHECK_EQ(test.fEq, 0U);
3961 CHECK_EQ(test.fUeq, 1U);
3962 CHECK_EQ(test.fOlt, 0U);
3963 CHECK_EQ(test.fUlt, 1U);
3964 CHECK_EQ(test.fOle, 0U);
3965 CHECK_EQ(test.fUle, 1U);
3966 }
3967}
3968
3969
3970TEST(CMP_COND_FMT) {
3971 if (IsMipsArchVariant(kMips32r6)) {
3972 CcTest::InitializeVM();
3973 Isolate* isolate = CcTest::i_isolate();
3974 HandleScope scope(isolate);
3975 MacroAssembler assm(isolate, NULL, 0,
3976 v8::internal::CodeObjectRequired::kYes);
3977
3978 typedef struct test_float {
3979 double dOp1;
3980 double dOp2;
3981 double dF;
3982 double dUn;
3983 double dEq;
3984 double dUeq;
3985 double dOlt;
3986 double dUlt;
3987 double dOle;
3988 double dUle;
3989 double dOr;
3990 double dUne;
3991 double dNe;
3992 float fOp1;
3993 float fOp2;
3994 float fF;
3995 float fUn;
3996 float fEq;
3997 float fUeq;
3998 float fOlt;
3999 float fUlt;
4000 float fOle;
4001 float fUle;
4002 float fOr;
4003 float fUne;
4004 float fNe;
4005 } TestFloat;
4006
4007 TestFloat test;
4008
4009 __ li(t1, 1);
4010
4011 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, dOp1)));
4012 __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, dOp2)));
4013
4014 __ lwc1(f14, MemOperand(a0, offsetof(TestFloat, fOp1)));
4015 __ lwc1(f16, MemOperand(a0, offsetof(TestFloat, fOp2)));
4016
4017 __ cmp_d(F, f2, f4, f6);
4018 __ cmp_s(F, f12, f14, f16);
4019 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dF)) );
4020 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fF)) );
4021
4022 __ cmp_d(UN, f2, f4, f6);
4023 __ cmp_s(UN, f12, f14, f16);
4024 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUn)) );
4025 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUn)) );
4026
4027 __ cmp_d(EQ, f2, f4, f6);
4028 __ cmp_s(EQ, f12, f14, f16);
4029 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dEq)) );
4030 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fEq)) );
4031
4032 __ cmp_d(UEQ, f2, f4, f6);
4033 __ cmp_s(UEQ, f12, f14, f16);
4034 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUeq)) );
4035 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUeq)) );
4036
4037 __ cmp_d(LT, f2, f4, f6);
4038 __ cmp_s(LT, f12, f14, f16);
4039 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOlt)) );
4040 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOlt)) );
4041
4042 __ cmp_d(ULT, f2, f4, f6);
4043 __ cmp_s(ULT, f12, f14, f16);
4044 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUlt)) );
4045 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUlt)) );
4046
4047 __ cmp_d(LE, f2, f4, f6);
4048 __ cmp_s(LE, f12, f14, f16);
4049 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOle)) );
4050 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOle)) );
4051
4052 __ cmp_d(ULE, f2, f4, f6);
4053 __ cmp_s(ULE, f12, f14, f16);
4054 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUle)) );
4055 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUle)) );
4056
4057 __ cmp_d(ORD, f2, f4, f6);
4058 __ cmp_s(ORD, f12, f14, f16);
4059 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOr)) );
4060 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOr)) );
4061
4062 __ cmp_d(UNE, f2, f4, f6);
4063 __ cmp_s(UNE, f12, f14, f16);
4064 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUne)) );
4065 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUne)) );
4066
4067 __ cmp_d(NE, f2, f4, f6);
4068 __ cmp_s(NE, f12, f14, f16);
4069 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dNe)) );
4070 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fNe)) );
4071
4072 __ jr(ra);
4073 __ nop();
4074
4075 CodeDesc desc;
4076 assm.GetCode(&desc);
4077 Handle<Code> code = isolate->factory()->NewCode(
4078 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4079 F3 f = FUNCTION_CAST<F3>(code->entry());
4080 uint64_t dTrue = 0xFFFFFFFFFFFFFFFF;
4081 uint64_t dFalse = 0x0000000000000000;
4082 uint32_t fTrue = 0xFFFFFFFF;
4083 uint32_t fFalse = 0x00000000;
4084
4085 test.dOp1 = 2.0;
4086 test.dOp2 = 3.0;
4087 test.fOp1 = 2.0;
4088 test.fOp2 = 3.0;
4089 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4090 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse);
4091 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse);
4092 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse);
4093 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dFalse);
4094 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dTrue);
4095 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dTrue);
4096 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dTrue);
4097 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue);
4098 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue);
4099 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue);
4100 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dTrue);
4101 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse);
4102 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse);
4103 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse);
4104 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fFalse);
4105 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fTrue);
4106 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fTrue);
4107 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fTrue);
4108 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue);
4109
4110 test.dOp1 = std::numeric_limits<double>::max();
4111 test.dOp2 = std::numeric_limits<double>::min();
4112 test.fOp1 = std::numeric_limits<float>::min();
4113 test.fOp2 = -std::numeric_limits<float>::max(); // lowest()
4114 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4115 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse);
4116 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse);
4117 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse);
4118 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dFalse);
4119 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse);
4120 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dFalse);
4121 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dFalse);
4122 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dFalse);
4123 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue);
4124 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue);
4125 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dTrue);
4126 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse);
4127 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse);
4128 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse);
4129 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fFalse);
4130 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse);
4131 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fFalse);
4132 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fFalse);
4133 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fFalse);
4134
4135 test.dOp1 = -std::numeric_limits<double>::max(); // lowest()
4136 test.dOp2 = -std::numeric_limits<double>::max(); // lowest()
4137 test.fOp1 = std::numeric_limits<float>::max();
4138 test.fOp2 = std::numeric_limits<float>::max();
4139 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4140 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse);
4141 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse);
4142 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dTrue);
4143 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dTrue);
4144 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse);
4145 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dFalse);
4146 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dTrue);
4147 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue);
4148 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue);
4149 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dFalse);
4150 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dFalse);
4151 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse);
4152 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse);
4153 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fTrue);
4154 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fTrue);
4155 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse);
4156 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fFalse);
4157 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fTrue);
4158 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue);
4159
4160 test.dOp1 = std::numeric_limits<double>::quiet_NaN();
4161 test.dOp2 = 0.0;
4162 test.fOp1 = std::numeric_limits<float>::quiet_NaN();
4163 test.fOp2 = 0.0;
4164 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4165 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse);
4166 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dTrue);
4167 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse);
4168 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dTrue);
4169 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse);
4170 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dTrue);
4171 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dFalse);
4172 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue);
4173 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dFalse);
4174 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue);
4175 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dFalse);
4176 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse);
4177 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fTrue);
4178 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse);
4179 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fTrue);
4180 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse);
4181 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fTrue);
4182 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fFalse);
4183 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue);
4184 }
4185}
4186
4187
4188TEST(CVT) {
4189 CcTest::InitializeVM();
4190 Isolate* isolate = CcTest::i_isolate();
4191 HandleScope scope(isolate);
4192 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4193
4194 typedef struct test_float {
4195 float cvt_d_s_in;
4196 double cvt_d_s_out;
4197 int32_t cvt_d_w_in;
4198 double cvt_d_w_out;
4199 int64_t cvt_d_l_in;
4200 double cvt_d_l_out;
4201
4202 float cvt_l_s_in;
4203 int64_t cvt_l_s_out;
4204 double cvt_l_d_in;
4205 int64_t cvt_l_d_out;
4206
4207 double cvt_s_d_in;
4208 float cvt_s_d_out;
4209 int32_t cvt_s_w_in;
4210 float cvt_s_w_out;
4211 int64_t cvt_s_l_in;
4212 float cvt_s_l_out;
4213
4214 float cvt_w_s_in;
4215 int32_t cvt_w_s_out;
4216 double cvt_w_d_in;
4217 int32_t cvt_w_d_out;
4218 } TestFloat;
4219
4220 TestFloat test;
4221
4222 // Save FCSR.
4223 __ cfc1(a1, FCSR);
4224 // Disable FPU exceptions.
4225 __ ctc1(zero_reg, FCSR);
4226
4227#define GENERATE_CVT_TEST(x, y, z) \
4228 __ y##c1(f0, MemOperand(a0, offsetof(TestFloat, x##_in))); \
4229 __ x(f0, f0); \
4230 __ nop(); \
4231 __ z##c1(f0, MemOperand(a0, offsetof(TestFloat, x##_out)));
4232
4233 GENERATE_CVT_TEST(cvt_d_s, lw, sd)
4234 GENERATE_CVT_TEST(cvt_d_w, lw, sd)
4235 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4236 IsFp64Mode()) {
4237 GENERATE_CVT_TEST(cvt_d_l, ld, sd)
4238 }
4239
4240 if (IsFp64Mode()) {
4241 GENERATE_CVT_TEST(cvt_l_s, lw, sd)
4242 GENERATE_CVT_TEST(cvt_l_d, ld, sd)
4243 }
4244
4245 GENERATE_CVT_TEST(cvt_s_d, ld, sw)
4246 GENERATE_CVT_TEST(cvt_s_w, lw, sw)
4247 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4248 IsFp64Mode()) {
4249 GENERATE_CVT_TEST(cvt_s_l, ld, sw)
4250 }
4251
4252 GENERATE_CVT_TEST(cvt_w_s, lw, sw)
4253 GENERATE_CVT_TEST(cvt_w_d, ld, sw)
4254
4255 // Restore FCSR.
4256 __ ctc1(a1, FCSR);
4257
4258 __ jr(ra);
4259 __ nop();
4260
4261 CodeDesc desc;
4262 assm.GetCode(&desc);
4263 Handle<Code> code = isolate->factory()->NewCode(
4264 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4265 F3 f = FUNCTION_CAST<F3>(code->entry());
4266
4267 test.cvt_d_s_in = -0.51;
4268 test.cvt_d_w_in = -1;
4269 test.cvt_d_l_in = -1;
4270 test.cvt_l_s_in = -0.51;
4271 test.cvt_l_d_in = -0.51;
4272 test.cvt_s_d_in = -0.51;
4273 test.cvt_s_w_in = -1;
4274 test.cvt_s_l_in = -1;
4275 test.cvt_w_s_in = -0.51;
4276 test.cvt_w_d_in = -0.51;
4277
4278 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4279 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
4280 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
4281 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4282 IsFp64Mode()) {
4283 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
4284 }
4285 if (IsFp64Mode()) {
4286 CHECK_EQ(test.cvt_l_s_out, -1);
4287 CHECK_EQ(test.cvt_l_d_out, -1);
4288 }
4289 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
4290 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
4291 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4292 IsFp64Mode()) {
4293 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
4294 }
4295 CHECK_EQ(test.cvt_w_s_out, -1);
4296 CHECK_EQ(test.cvt_w_d_out, -1);
4297
4298
4299 test.cvt_d_s_in = 0.49;
4300 test.cvt_d_w_in = 1;
4301 test.cvt_d_l_in = 1;
4302 test.cvt_l_s_in = 0.49;
4303 test.cvt_l_d_in = 0.49;
4304 test.cvt_s_d_in = 0.49;
4305 test.cvt_s_w_in = 1;
4306 test.cvt_s_l_in = 1;
4307 test.cvt_w_s_in = 0.49;
4308 test.cvt_w_d_in = 0.49;
4309
4310 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4311 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
4312 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
4313 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4314 IsFp64Mode()) {
4315 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
4316 }
4317 if (IsFp64Mode()) {
4318 CHECK_EQ(test.cvt_l_s_out, 0);
4319 CHECK_EQ(test.cvt_l_d_out, 0);
4320 }
4321 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
4322 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
4323 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4324 IsFp64Mode()) {
4325 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
4326 }
4327 CHECK_EQ(test.cvt_w_s_out, 0);
4328 CHECK_EQ(test.cvt_w_d_out, 0);
4329
4330 test.cvt_d_s_in = std::numeric_limits<float>::max();
4331 test.cvt_d_w_in = std::numeric_limits<int32_t>::max();
4332 test.cvt_d_l_in = std::numeric_limits<int64_t>::max();
4333 test.cvt_l_s_in = std::numeric_limits<float>::max();
4334 test.cvt_l_d_in = std::numeric_limits<double>::max();
4335 test.cvt_s_d_in = std::numeric_limits<double>::max();
4336 test.cvt_s_w_in = std::numeric_limits<int32_t>::max();
4337 test.cvt_s_l_in = std::numeric_limits<int64_t>::max();
4338 test.cvt_w_s_in = std::numeric_limits<float>::max();
4339 test.cvt_w_d_in = std::numeric_limits<double>::max();
4340
4341 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4342 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
4343 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
4344 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4345 IsFp64Mode()) {
4346 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
4347 }
4348 if (IsFp64Mode()) {
4349 CHECK_EQ(test.cvt_l_s_out, std::numeric_limits<int64_t>::max());
4350 CHECK_EQ(test.cvt_l_d_out, std::numeric_limits<int64_t>::max());
4351 }
4352 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
4353 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
4354 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4355 IsFp64Mode()) {
4356 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
4357 }
4358 CHECK_EQ(test.cvt_w_s_out, std::numeric_limits<int32_t>::max());
4359 CHECK_EQ(test.cvt_w_d_out, std::numeric_limits<int32_t>::max());
4360
4361
4362 test.cvt_d_s_in = -std::numeric_limits<float>::max(); // lowest()
4363 test.cvt_d_w_in = std::numeric_limits<int32_t>::min(); // lowest()
4364 test.cvt_d_l_in = std::numeric_limits<int64_t>::min(); // lowest()
4365 test.cvt_l_s_in = -std::numeric_limits<float>::max(); // lowest()
4366 test.cvt_l_d_in = -std::numeric_limits<double>::max(); // lowest()
4367 test.cvt_s_d_in = -std::numeric_limits<double>::max(); // lowest()
4368 test.cvt_s_w_in = std::numeric_limits<int32_t>::min(); // lowest()
4369 test.cvt_s_l_in = std::numeric_limits<int64_t>::min(); // lowest()
4370 test.cvt_w_s_in = -std::numeric_limits<float>::max(); // lowest()
4371 test.cvt_w_d_in = -std::numeric_limits<double>::max(); // lowest()
4372
4373 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4374 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
4375 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
4376 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4377 IsFp64Mode()) {
4378 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
4379 }
4380 // The returned value when converting from fixed-point to float-point
4381 // is not consistent between board, simulator and specification
4382 // in this test case, therefore modifying the test
4383 if (IsFp64Mode()) {
4384 CHECK(test.cvt_l_s_out == std::numeric_limits<int64_t>::min() ||
4385 test.cvt_l_s_out == std::numeric_limits<int64_t>::max());
4386 CHECK(test.cvt_l_d_out == std::numeric_limits<int64_t>::min() ||
4387 test.cvt_l_d_out == std::numeric_limits<int64_t>::max());
4388 }
4389 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
4390 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
4391 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4392 IsFp64Mode()) {
4393 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
4394 }
4395 CHECK(test.cvt_w_s_out == std::numeric_limits<int32_t>::min() ||
4396 test.cvt_w_s_out == std::numeric_limits<int32_t>::max());
4397 CHECK(test.cvt_w_d_out == std::numeric_limits<int32_t>::min() ||
4398 test.cvt_w_d_out == std::numeric_limits<int32_t>::max());
4399
4400
4401 test.cvt_d_s_in = std::numeric_limits<float>::min();
4402 test.cvt_d_w_in = std::numeric_limits<int32_t>::min();
4403 test.cvt_d_l_in = std::numeric_limits<int64_t>::min();
4404 test.cvt_l_s_in = std::numeric_limits<float>::min();
4405 test.cvt_l_d_in = std::numeric_limits<double>::min();
4406 test.cvt_s_d_in = std::numeric_limits<double>::min();
4407 test.cvt_s_w_in = std::numeric_limits<int32_t>::min();
4408 test.cvt_s_l_in = std::numeric_limits<int64_t>::min();
4409 test.cvt_w_s_in = std::numeric_limits<float>::min();
4410 test.cvt_w_d_in = std::numeric_limits<double>::min();
4411
4412 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4413 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in));
4414 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in));
4415 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4416 IsFp64Mode()) {
4417 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in));
4418 }
4419 if (IsFp64Mode()) {
4420 CHECK_EQ(test.cvt_l_s_out, 0);
4421 CHECK_EQ(test.cvt_l_d_out, 0);
4422 }
4423 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in));
4424 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in));
4425 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
4426 IsFp64Mode()) {
4427 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in));
4428 }
4429 CHECK_EQ(test.cvt_w_s_out, 0);
4430 CHECK_EQ(test.cvt_w_d_out, 0);
4431}
4432
4433
4434TEST(DIV_FMT) {
4435 CcTest::InitializeVM();
4436 Isolate* isolate = CcTest::i_isolate();
4437 HandleScope scope(isolate);
4438 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4439
4440 typedef struct test {
4441 double dOp1;
4442 double dOp2;
4443 double dRes;
4444 float fOp1;
4445 float fOp2;
4446 float fRes;
4447 } Test;
4448
4449 Test test;
4450
4451 // Save FCSR.
4452 __ cfc1(a1, FCSR);
4453 // Disable FPU exceptions.
4454 __ ctc1(zero_reg, FCSR);
4455
4456 __ ldc1(f4, MemOperand(a0, offsetof(Test, dOp1)) );
4457 __ ldc1(f2, MemOperand(a0, offsetof(Test, dOp2)) );
4458 __ nop();
4459 __ div_d(f6, f4, f2);
4460 __ sdc1(f6, MemOperand(a0, offsetof(Test, dRes)) );
4461
4462 __ lwc1(f4, MemOperand(a0, offsetof(Test, fOp1)) );
4463 __ lwc1(f2, MemOperand(a0, offsetof(Test, fOp2)) );
4464 __ nop();
4465 __ div_s(f6, f4, f2);
4466 __ swc1(f6, MemOperand(a0, offsetof(Test, fRes)) );
4467
4468 // Restore FCSR.
4469 __ ctc1(a1, FCSR);
4470
4471 __ jr(ra);
4472 __ nop();
4473
4474 CodeDesc desc;
4475 assm.GetCode(&desc);
4476 Handle<Code> code = isolate->factory()->NewCode(
4477 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4478
4479 F3 f = FUNCTION_CAST<F3>(code->entry());
4480
4481 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4482
4483 const int test_size = 3;
4484
4485 double dOp1[test_size] = {
4486 5.0,
4487 DBL_MAX,
4488 DBL_MAX,
4489 };
4490 double dOp2[test_size] = {
4491 2.0,
4492 2.0,
4493 -DBL_MAX,
4494 };
4495 double dRes[test_size] = {
4496 2.5,
4497 DBL_MAX / 2.0,
4498 -1.0,
4499 };
4500 float fOp1[test_size] = {
4501 5.0,
4502 FLT_MAX,
4503 FLT_MAX,
4504 };
4505 float fOp2[test_size] = {
4506 2.0,
4507 2.0,
4508 -FLT_MAX,
4509 };
4510 float fRes[test_size] = {
4511 2.5,
4512 FLT_MAX / 2.0,
4513 -1.0,
4514 };
4515
4516 for (int i = 0; i < test_size; i++) {
4517 test.dOp1 = dOp1[i];
4518 test.dOp2 = dOp2[i];
4519 test.fOp1 = fOp1[i];
4520 test.fOp2 = fOp2[i];
4521
4522 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4523 CHECK_EQ(test.dRes, dRes[i]);
4524 CHECK_EQ(test.fRes, fRes[i]);
4525 }
4526
4527 test.dOp1 = DBL_MAX;
4528 test.dOp2 = -0.0;
4529 test.fOp1 = FLT_MAX;
4530 test.fOp2 = -0.0;
4531
4532 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4533 CHECK_EQ(false, std::isfinite(test.dRes));
4534 CHECK_EQ(false, std::isfinite(test.fRes));
4535
4536 test.dOp1 = 0.0;
4537 test.dOp2 = -0.0;
4538 test.fOp1 = 0.0;
4539 test.fOp2 = -0.0;
4540
4541 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4542 CHECK_EQ(true, std::isnan(test.dRes));
4543 CHECK_EQ(true, std::isnan(test.fRes));
4544
4545 test.dOp1 = std::numeric_limits<double>::quiet_NaN();
4546 test.dOp2 = -5.0;
4547 test.fOp1 = std::numeric_limits<float>::quiet_NaN();
4548 test.fOp2 = -5.0;
4549
4550 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0));
4551 CHECK_EQ(true, std::isnan(test.dRes));
4552 CHECK_EQ(true, std::isnan(test.fRes));
4553}
4554
4555
4556uint32_t run_align(uint32_t rs_value, uint32_t rt_value, uint8_t bp) {
4557 Isolate* isolate = CcTest::i_isolate();
4558 HandleScope scope(isolate);
4559
4560 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4561
4562 __ align(v0, a0, a1, bp);
4563 __ jr(ra);
4564 __ nop();
4565
4566 CodeDesc desc;
4567 assm.GetCode(&desc);
4568 Handle<Code> code = isolate->factory()->NewCode(
4569 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4570
4571 F2 f = FUNCTION_CAST<F2>(code->entry());
4572
4573 uint32_t res = reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(
4574 isolate, f, rs_value, rt_value, 0, 0, 0));
4575
4576 return res;
4577}
4578
4579
4580TEST(r6_align) {
4581 if (IsMipsArchVariant(kMips32r6)) {
4582 CcTest::InitializeVM();
4583
4584 struct TestCaseAlign {
4585 uint32_t rs_value;
4586 uint32_t rt_value;
4587 uint8_t bp;
4588 uint32_t expected_res;
4589 };
4590
4591 struct TestCaseAlign tc[] = {
4592 // rs_value, rt_value, bp, expected_res
4593 { 0x11223344, 0xaabbccdd, 0, 0xaabbccdd },
4594 { 0x11223344, 0xaabbccdd, 1, 0xbbccdd11 },
4595 { 0x11223344, 0xaabbccdd, 2, 0xccdd1122 },
4596 { 0x11223344, 0xaabbccdd, 3, 0xdd112233 },
4597 };
4598
4599 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAlign);
4600 for (size_t i = 0; i < nr_test_cases; ++i) {
4601 CHECK_EQ(tc[i].expected_res, run_align(tc[i].rs_value,
4602 tc[i].rt_value, tc[i].bp));
4603 }
4604 }
4605}
4606
4607uint32_t PC; // The program counter.
4608
4609uint32_t run_aluipc(int16_t offset) {
4610 Isolate* isolate = CcTest::i_isolate();
4611 HandleScope scope(isolate);
4612
4613 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4614
4615 __ aluipc(v0, offset);
4616 __ jr(ra);
4617 __ nop();
4618
4619 CodeDesc desc;
4620 assm.GetCode(&desc);
4621 Handle<Code> code = isolate->factory()->NewCode(
4622 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4623
4624 F2 f = FUNCTION_CAST<F2>(code->entry());
4625 PC = (uint32_t) f; // Set the program counter.
4626
4627 uint32_t res = reinterpret_cast<uint32_t>(
4628 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
4629
4630 return res;
4631}
4632
4633
4634TEST(r6_aluipc) {
4635 if (IsMipsArchVariant(kMips32r6)) {
4636 CcTest::InitializeVM();
4637
4638 struct TestCaseAluipc {
4639 int16_t offset;
4640 };
4641
4642 struct TestCaseAluipc tc[] = {
4643 // offset
4644 { -32768 }, // 0x8000
4645 { -1 }, // 0xFFFF
4646 { 0 },
4647 { 1 },
4648 { 32767 }, // 0x7FFF
4649 };
4650
4651 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAluipc);
4652 for (size_t i = 0; i < nr_test_cases; ++i) {
4653 PC = 0;
4654 uint32_t res = run_aluipc(tc[i].offset);
4655 // Now, the program_counter (PC) is set.
4656 uint32_t expected_res = ~0x0FFFF & (PC + (tc[i].offset << 16));
4657 CHECK_EQ(expected_res, res);
4658 }
4659 }
4660}
4661
4662
4663uint32_t run_auipc(int16_t offset) {
4664 Isolate* isolate = CcTest::i_isolate();
4665 HandleScope scope(isolate);
4666
4667 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4668
4669 __ auipc(v0, offset);
4670 __ jr(ra);
4671 __ nop();
4672
4673 CodeDesc desc;
4674 assm.GetCode(&desc);
4675 Handle<Code> code = isolate->factory()->NewCode(
4676 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4677
4678 F2 f = FUNCTION_CAST<F2>(code->entry());
4679 PC = (uint32_t) f; // Set the program counter.
4680
4681 uint32_t res = reinterpret_cast<uint32_t>(
4682 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
4683
4684 return res;
4685}
4686
4687
4688TEST(r6_auipc) {
4689 if (IsMipsArchVariant(kMips32r6)) {
4690 CcTest::InitializeVM();
4691
4692 struct TestCaseAuipc {
4693 int16_t offset;
4694 };
4695
4696 struct TestCaseAuipc tc[] = {
4697 // offset
4698 { -32768 }, // 0x8000
4699 { -1 }, // 0xFFFF
4700 { 0 },
4701 { 1 },
4702 { 32767 }, // 0x7FFF
4703 };
4704
4705 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAuipc);
4706 for (size_t i = 0; i < nr_test_cases; ++i) {
4707 PC = 0;
4708 uint32_t res = run_auipc(tc[i].offset);
4709 // Now, the program_counter (PC) is set.
4710 uint32_t expected_res = PC + (tc[i].offset << 16);
4711 CHECK_EQ(expected_res, res);
4712 }
4713 }
4714}
4715
4716
4717uint32_t run_lwpc(int offset) {
4718 Isolate* isolate = CcTest::i_isolate();
4719 HandleScope scope(isolate);
4720
4721 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4722
4723 // 256k instructions; 2^8k
4724 // addiu t7, t0, 0xffff; (0x250fffff)
4725 // ...
4726 // addiu t4, t0, 0x0000; (0x250c0000)
4727 uint32_t addiu_start_1 = 0x25000000;
4728 for (int32_t i = 0xfffff; i >= 0xc0000; --i) {
4729 uint32_t addiu_new = addiu_start_1 + i;
4730 __ dd(addiu_new);
4731 }
4732
4733 __ lwpc(t8, offset); // offset 0; 0xef080000 (t8 register)
4734 __ mov(v0, t8);
4735
4736 // 256k instructions; 2^8k
4737 // addiu t0, t0, 0x0000; (0x25080000)
4738 // ...
4739 // addiu t3, t0, 0xffff; (0x250bffff)
4740 uint32_t addiu_start_2 = 0x25000000;
4741 for (int32_t i = 0x80000; i <= 0xbffff; ++i) {
4742 uint32_t addiu_new = addiu_start_2 + i;
4743 __ dd(addiu_new);
4744 }
4745
4746 __ jr(ra);
4747 __ nop();
4748
4749 CodeDesc desc;
4750 assm.GetCode(&desc);
4751 Handle<Code> code = isolate->factory()->NewCode(
4752 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4753
4754 F2 f = FUNCTION_CAST<F2>(code->entry());
4755
4756 uint32_t res = reinterpret_cast<uint32_t>(
4757 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
4758
4759 return res;
4760}
4761
4762
4763TEST(r6_lwpc) {
4764 if (IsMipsArchVariant(kMips32r6)) {
4765 CcTest::InitializeVM();
4766
4767 struct TestCaseLwpc {
4768 int offset;
4769 uint32_t expected_res;
4770 };
4771
4772 struct TestCaseLwpc tc[] = {
4773 // offset, expected_res
4774 { -262144, 0x250fffff }, // offset 0x40000
4775 { -4, 0x250c0003 },
4776 { -1, 0x250c0000 },
4777 { 0, 0xef080000 },
4778 { 1, 0x03001025 }, // mov(v0, t8)
4779 { 2, 0x25080000 },
4780 { 4, 0x25080002 },
4781 { 262143, 0x250bfffd }, // offset 0x3ffff
4782 };
4783
4784 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLwpc);
4785 for (size_t i = 0; i < nr_test_cases; ++i) {
4786 uint32_t res = run_lwpc(tc[i].offset);
4787 CHECK_EQ(tc[i].expected_res, res);
4788 }
4789 }
4790}
4791
4792
4793uint32_t run_jic(int16_t offset) {
4794 Isolate* isolate = CcTest::i_isolate();
4795 HandleScope scope(isolate);
4796
4797 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4798
4799 Label get_program_counter, stop_execution;
4800 __ push(ra);
4801 __ li(v0, 0);
4802 __ li(t1, 0x66);
4803
4804 __ addiu(v0, v0, 0x1); // <-- offset = -32
4805 __ addiu(v0, v0, 0x2);
4806 __ addiu(v0, v0, 0x10);
4807 __ addiu(v0, v0, 0x20);
4808 __ beq(v0, t1, &stop_execution);
4809 __ nop();
4810
4811 __ bal(&get_program_counter); // t0 <- program counter
4812 __ nop();
4813 __ jic(t0, offset);
4814
4815 __ addiu(v0, v0, 0x100);
4816 __ addiu(v0, v0, 0x200);
4817 __ addiu(v0, v0, 0x1000);
4818 __ addiu(v0, v0, 0x2000); // <--- offset = 16
4819 __ pop(ra);
4820 __ jr(ra);
4821 __ nop();
4822
4823 __ bind(&get_program_counter);
4824 __ mov(t0, ra);
4825 __ jr(ra);
4826 __ nop();
4827
4828 __ bind(&stop_execution);
4829 __ pop(ra);
4830 __ jr(ra);
4831 __ nop();
4832
4833 CodeDesc desc;
4834 assm.GetCode(&desc);
4835 Handle<Code> code = isolate->factory()->NewCode(
4836 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4837
4838 F2 f = FUNCTION_CAST<F2>(code->entry());
4839
4840 uint32_t res = reinterpret_cast<uint32_t>(
4841 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
4842
4843 return res;
4844}
4845
4846
4847TEST(r6_jic) {
4848 if (IsMipsArchVariant(kMips32r6)) {
4849 CcTest::InitializeVM();
4850
4851 struct TestCaseJic {
4852 // As rt will be used t0 register which will have value of
4853 // the program counter for the jic instruction.
4854 int16_t offset;
4855 uint32_t expected_res;
4856 };
4857
4858 struct TestCaseJic tc[] = {
4859 // offset, expected_result
4860 { 16, 0x2033 },
4861 { 4, 0x3333 },
4862 { -32, 0x66 },
4863 };
4864
4865 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJic);
4866 for (size_t i = 0; i < nr_test_cases; ++i) {
4867 uint32_t res = run_jic(tc[i].offset);
4868 CHECK_EQ(tc[i].expected_res, res);
4869 }
4870 }
4871}
4872
4873
4874uint64_t run_beqzc(int32_t value, int32_t offset) {
4875 Isolate* isolate = CcTest::i_isolate();
4876 HandleScope scope(isolate);
4877
4878 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4879
4880 Label stop_execution;
4881 __ li(v0, 0);
4882 __ li(t1, 0x66);
4883
4884 __ addiu(v0, v0, 0x1); // <-- offset = -32
4885 __ addiu(v0, v0, 0x2);
4886 __ addiu(v0, v0, 0x10);
4887 __ addiu(v0, v0, 0x20);
4888 __ beq(v0, t1, &stop_execution);
4889 __ nop();
4890
4891 __ beqzc(a0, offset); // BEQZC rs, offset
4892
4893 __ addiu(v0, v0, 0x1);
4894 __ addiu(v0, v0, 0x100);
4895 __ addiu(v0, v0, 0x200);
4896 __ addiu(v0, v0, 0x1000);
4897 __ addiu(v0, v0, 0x2000); // <--- offset = 16
4898 __ jr(ra);
4899 __ nop();
4900
4901 __ bind(&stop_execution);
4902 __ jr(ra);
4903 __ nop();
4904
4905 CodeDesc desc;
4906 assm.GetCode(&desc);
4907 Handle<Code> code = isolate->factory()->NewCode(
4908 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
4909
4910 F2 f = FUNCTION_CAST<F2>(code->entry());
4911
4912 uint32_t res = reinterpret_cast<uint32_t>(
4913 CALL_GENERATED_CODE(isolate, f, value, 0, 0, 0, 0));
4914
4915 return res;
4916}
4917
4918
4919TEST(r6_beqzc) {
4920 if (IsMipsArchVariant(kMips32r6)) {
4921 CcTest::InitializeVM();
4922
4923 struct TestCaseBeqzc {
4924 uint32_t value;
4925 int32_t offset;
4926 uint32_t expected_res;
4927 };
4928
4929 struct TestCaseBeqzc tc[] = {
4930 // value, offset, expected_res
4931 { 0x0, -8, 0x66 },
4932 { 0x0, 0, 0x3334 },
4933 { 0x0, 1, 0x3333 },
4934 { 0xabc, 1, 0x3334 },
4935 { 0x0, 4, 0x2033 },
4936 };
4937
4938 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBeqzc);
4939 for (size_t i = 0; i < nr_test_cases; ++i) {
4940 uint32_t res = run_beqzc(tc[i].value, tc[i].offset);
4941 CHECK_EQ(tc[i].expected_res, res);
4942 }
4943 }
4944}
4945
4946
4947uint32_t run_jialc(int16_t offset) {
4948 Isolate* isolate = CcTest::i_isolate();
4949 HandleScope scope(isolate);
4950
4951 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
4952
4953 Label main_block, get_program_counter;
4954 __ push(ra);
4955 __ li(v0, 0);
4956 __ beq(v0, v0, &main_block);
4957 __ nop();
4958
4959 // Block 1
4960 __ addiu(v0, v0, 0x1); // <-- offset = -40
4961 __ addiu(v0, v0, 0x2);
4962 __ jr(ra);
4963 __ nop();
4964
4965 // Block 2
4966 __ addiu(v0, v0, 0x10); // <-- offset = -24
4967 __ addiu(v0, v0, 0x20);
4968 __ jr(ra);
4969 __ nop();
4970
4971 // Block 3 (Main)
4972 __ bind(&main_block);
4973 __ bal(&get_program_counter); // t0 <- program counter
4974 __ nop();
4975 __ jialc(t0, offset);
4976 __ addiu(v0, v0, 0x4);
4977 __ pop(ra);
4978 __ jr(ra);
4979 __ nop();
4980
4981 // Block 4
4982 __ addiu(v0, v0, 0x100); // <-- offset = 20
4983 __ addiu(v0, v0, 0x200);
4984 __ jr(ra);
4985 __ nop();
4986
4987 // Block 5
4988 __ addiu(v0, v0, 0x1000); // <--- offset = 36
4989 __ addiu(v0, v0, 0x2000);
4990 __ jr(ra);
4991 __ nop();
4992
4993 __ bind(&get_program_counter);
4994 __ mov(t0, ra);
4995 __ jr(ra);
4996 __ nop();
4997
4998
4999 CodeDesc desc;
5000 assm.GetCode(&desc);
5001 Handle<Code> code = isolate->factory()->NewCode(
5002 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5003
5004 F2 f = FUNCTION_CAST<F2>(code->entry());
5005
5006 uint32_t res = reinterpret_cast<uint32_t>(
5007 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5008
5009 return res;
5010}
5011
5012
5013TEST(r6_jialc) {
5014 if (IsMipsArchVariant(kMips32r6)) {
5015 CcTest::InitializeVM();
5016
5017 struct TestCaseJialc {
5018 int16_t offset;
5019 uint32_t expected_res;
5020 };
5021
5022 struct TestCaseJialc tc[] = {
5023 // offset, expected_res
5024 { -40, 0x7 },
5025 { -24, 0x34 },
5026 { 20, 0x304 },
5027 { 36, 0x3004 }
5028 };
5029
5030 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJialc);
5031 for (size_t i = 0; i < nr_test_cases; ++i) {
5032 uint32_t res = run_jialc(tc[i].offset);
5033 CHECK_EQ(tc[i].expected_res, res);
5034 }
5035 }
5036}
5037
Ben Murdoch097c5b22016-05-18 11:27:45 +01005038static uint32_t run_addiupc(int32_t imm19) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005039 Isolate* isolate = CcTest::i_isolate();
5040 HandleScope scope(isolate);
5041
5042 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5043
5044 __ addiupc(v0, imm19);
5045 __ jr(ra);
5046 __ nop();
5047
5048 CodeDesc desc;
5049 assm.GetCode(&desc);
5050 Handle<Code> code = isolate->factory()->NewCode(
5051 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5052
5053 F2 f = FUNCTION_CAST<F2>(code->entry());
5054 PC = (uint32_t) f; // Set the program counter.
5055
5056 uint32_t rs = reinterpret_cast<uint32_t>(
5057 CALL_GENERATED_CODE(isolate, f, imm19, 0, 0, 0, 0));
5058
5059 return rs;
5060}
5061
5062
5063TEST(r6_addiupc) {
5064 if (IsMipsArchVariant(kMips32r6)) {
5065 CcTest::InitializeVM();
5066
5067 struct TestCaseAddiupc {
5068 int32_t imm19;
5069 };
5070
Ben Murdoch097c5b22016-05-18 11:27:45 +01005071 TestCaseAddiupc tc[] = {
5072 // imm19
5073 {-262144}, // 0x40000
5074 {-1}, // 0x7FFFF
5075 {0},
5076 {1}, // 0x00001
5077 {262143} // 0x3FFFF
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005078 };
5079
5080 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAddiupc);
5081 for (size_t i = 0; i < nr_test_cases; ++i) {
5082 PC = 0;
5083 uint32_t res = run_addiupc(tc[i].imm19);
5084 // Now, the program_counter (PC) is set.
5085 uint32_t expected_res = PC + (tc[i].imm19 << 2);
5086 CHECK_EQ(expected_res, res);
5087 }
5088 }
5089}
5090
5091
5092int32_t run_bc(int32_t offset) {
5093 Isolate* isolate = CcTest::i_isolate();
5094 HandleScope scope(isolate);
5095
5096 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5097
5098 Label continue_1, stop_execution;
5099 __ push(ra);
5100 __ li(v0, 0);
5101 __ li(t8, 0);
5102 __ li(t9, 2); // A condition for stopping execution.
5103
5104 for (int32_t i = -100; i <= -11; ++i) {
5105 __ addiu(v0, v0, 1);
5106 }
5107
5108 __ addiu(t8, t8, 1); // -10
5109
5110 __ beq(t8, t9, &stop_execution); // -9
5111 __ nop(); // -8
5112 __ beq(t8, t8, &continue_1); // -7
5113 __ nop(); // -6
5114
5115 __ bind(&stop_execution);
5116 __ pop(ra); // -5, -4
5117 __ jr(ra); // -3
5118 __ nop(); // -2
5119
5120 __ bind(&continue_1);
5121 __ bc(offset); // -1
5122
5123 for (int32_t i = 0; i <= 99; ++i) {
5124 __ addiu(v0, v0, 1);
5125 }
5126
5127 __ pop(ra);
5128 __ jr(ra);
5129 __ nop();
5130
5131 CodeDesc desc;
5132 assm.GetCode(&desc);
5133 Handle<Code> code = isolate->factory()->NewCode(
5134 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5135
5136 F2 f = FUNCTION_CAST<F2>(code->entry());
5137
5138 int32_t res = reinterpret_cast<int32_t>(
5139 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5140
5141 return res;
5142}
5143
5144
5145TEST(r6_bc) {
5146 if (IsMipsArchVariant(kMips32r6)) {
5147 CcTest::InitializeVM();
5148
5149 struct TestCaseBc {
5150 int32_t offset;
5151 int32_t expected_res;
5152 };
5153
5154 struct TestCaseBc tc[] = {
5155 // offset, expected_result
5156 { -100, (abs(-100) - 10) * 2 },
5157 { -11, (abs(-100) - 10 + 1) },
5158 { 0, (abs(-100) - 10 + 1 + 99) },
5159 { 1, (abs(-100) - 10 + 99) },
5160 { 99, (abs(-100) - 10 + 1) },
5161 };
5162
5163 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBc);
5164 for (size_t i = 0; i < nr_test_cases; ++i) {
5165 int32_t res = run_bc(tc[i].offset);
5166 CHECK_EQ(tc[i].expected_res, res);
5167 }
5168 }
5169}
5170
5171
5172int32_t run_balc(int32_t offset) {
5173 Isolate* isolate = CcTest::i_isolate();
5174 HandleScope scope(isolate);
5175
5176 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5177
5178 Label continue_1, stop_execution;
5179 __ push(ra);
5180 __ li(v0, 0);
5181 __ li(t8, 0);
5182 __ li(t9, 2); // A condition for stopping execution.
5183
5184 __ beq(t8, t8, &continue_1);
5185 __ nop();
5186
5187 uint32_t instruction_addiu = 0x24420001; // addiu v0, v0, 1
5188 for (int32_t i = -117; i <= -57; ++i) {
5189 __ dd(instruction_addiu);
5190 }
5191 __ jr(ra); // -56
5192 __ nop(); // -55
5193
5194 for (int32_t i = -54; i <= -4; ++i) {
5195 __ dd(instruction_addiu);
5196 }
5197 __ jr(ra); // -3
5198 __ nop(); // -2
5199
5200 __ bind(&continue_1);
5201 __ balc(offset); // -1
5202
5203 __ pop(ra); // 0, 1
5204 __ jr(ra); // 2
5205 __ nop(); // 3
5206
5207 for (int32_t i = 4; i <= 44; ++i) {
5208 __ dd(instruction_addiu);
5209 }
5210 __ jr(ra);
5211 __ nop();
5212
5213 CodeDesc desc;
5214 assm.GetCode(&desc);
5215 Handle<Code> code = isolate->factory()->NewCode(
5216 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5217
5218 F2 f = FUNCTION_CAST<F2>(code->entry());
5219
5220 int32_t res = reinterpret_cast<int32_t>(
5221 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5222
5223 return res;
5224}
5225
5226
5227uint32_t run_aui(uint32_t rs, uint16_t offset) {
5228 Isolate* isolate = CcTest::i_isolate();
5229 HandleScope scope(isolate);
5230
5231 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5232
5233 __ li(t0, rs);
5234 __ aui(v0, t0, offset);
5235 __ jr(ra);
5236 __ nop();
5237
5238 CodeDesc desc;
5239 assm.GetCode(&desc);
5240 Handle<Code> code = isolate->factory()->NewCode(
5241 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5242
5243 F2 f = FUNCTION_CAST<F2>(code->entry());
5244
5245 uint32_t res =
5246 reinterpret_cast<uint32_t>
5247 (CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5248
5249 return res;
5250}
5251
5252
5253TEST(r6_aui) {
5254 if (IsMipsArchVariant(kMips32r6)) {
5255 CcTest::InitializeVM();
5256
5257 struct TestCaseAui {
5258 uint32_t rs;
5259 uint16_t offset;
5260 uint32_t ref_res;
5261 };
5262
5263 struct TestCaseAui tc[] = {
5264 // input, offset, result
5265 {0xfffeffff, 1, 0xffffffff},
5266 {0xffffffff, 0, 0xffffffff},
5267 {0, 0xffff, 0xffff0000},
5268 {0x0008ffff, 0xfff7, 0xffffffff},
5269 {32767, 32767, 0x7fff7fff},
5270 // overflow cases
5271 {0xffffffff, 0x1, 0x0000ffff},
5272 {0xffffffff, 0xffff, 0xfffeffff},
5273 };
5274
5275 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAui);
5276 for (size_t i = 0; i < nr_test_cases; ++i) {
5277 PC = 0;
5278 uint32_t res = run_aui(tc[i].rs, tc[i].offset);
5279 CHECK_EQ(tc[i].ref_res, res);
5280 }
5281 }
5282}
5283
5284
5285TEST(r6_balc) {
5286 if (IsMipsArchVariant(kMips32r6)) {
5287 CcTest::InitializeVM();
5288
5289 struct TestCaseBalc {
5290 int32_t offset;
5291 int32_t expected_res;
5292 };
5293
5294 struct TestCaseBalc tc[] = {
5295 // offset, expected_result
5296 { -117, 61 },
5297 { -54, 51 },
5298 { 0, 0 },
5299 { 4, 41 },
5300 };
5301
5302 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBalc);
5303 for (size_t i = 0; i < nr_test_cases; ++i) {
5304 int32_t res = run_balc(tc[i].offset);
5305 CHECK_EQ(tc[i].expected_res, res);
5306 }
5307 }
5308}
5309
5310
5311uint32_t run_bal(int16_t offset) {
5312 Isolate* isolate = CcTest::i_isolate();
5313 HandleScope scope(isolate);
5314
5315 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
5316
5317 __ mov(t0, ra);
5318 __ bal(offset); // Equivalent for "BGEZAL zero_reg, offset".
5319 __ nop();
5320
5321 __ mov(ra, t0);
5322 __ jr(ra);
5323 __ nop();
5324
5325 __ li(v0, 1);
5326 __ jr(ra);
5327 __ nop();
5328
5329 CodeDesc desc;
5330 assm.GetCode(&desc);
5331 Handle<Code> code = isolate->factory()->NewCode(
5332 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5333
5334 F2 f = FUNCTION_CAST<F2>(code->entry());
5335
5336 uint32_t res = reinterpret_cast<uint32_t>(
5337 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
5338
5339 return res;
5340}
5341
5342
5343TEST(bal) {
5344 CcTest::InitializeVM();
5345
5346 struct TestCaseBal {
5347 int16_t offset;
5348 uint32_t expected_res;
5349 };
5350
5351 struct TestCaseBal tc[] = {
5352 // offset, expected_res
5353 { 4, 1 },
5354 };
5355
5356 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBal);
5357 for (size_t i = 0; i < nr_test_cases; ++i) {
5358 CHECK_EQ(tc[i].expected_res, run_bal(tc[i].offset));
5359 }
5360}
5361
5362
5363static uint32_t run_lsa(uint32_t rt, uint32_t rs, int8_t sa) {
5364 Isolate* isolate = CcTest::i_isolate();
5365 HandleScope scope(isolate);
5366 MacroAssembler assm(isolate, nullptr, 0,
5367 v8::internal::CodeObjectRequired::kYes);
5368
5369 __ lsa(v0, a0, a1, sa);
5370 __ jr(ra);
5371 __ nop();
5372
5373 CodeDesc desc;
5374 assm.GetCode(&desc);
5375 Handle<Code> code = isolate->factory()->NewCode(
5376 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5377
5378 F1 f = FUNCTION_CAST<F1>(code->entry());
5379
5380 uint32_t res = reinterpret_cast<uint32_t>(
5381 CALL_GENERATED_CODE(isolate, f, rt, rs, 0, 0, 0));
5382
5383 return res;
5384}
5385
5386
5387TEST(lsa) {
5388 if (!IsMipsArchVariant(kMips32r6)) return;
5389
5390 CcTest::InitializeVM();
5391 struct TestCaseLsa {
5392 int32_t rt;
5393 int32_t rs;
5394 uint8_t sa;
5395 uint32_t expected_res;
5396 };
5397
5398 struct TestCaseLsa tc[] = {
5399 // rt, rs, sa, expected_res
5400 {0x4, 0x1, 1, 0x6},
5401 {0x4, 0x1, 2, 0x8},
5402 {0x4, 0x1, 3, 0xc},
5403 {0x4, 0x1, 4, 0x14},
5404 {0x0, 0x1, 1, 0x2},
5405 {0x0, 0x1, 2, 0x4},
5406 {0x0, 0x1, 3, 0x8},
5407 {0x0, 0x1, 4, 0x10},
5408 {0x4, 0x0, 1, 0x4},
5409 {0x4, 0x0, 2, 0x4},
5410 {0x4, 0x0, 3, 0x4},
5411 {0x4, 0x0, 4, 0x4},
5412 {0x4, INT32_MAX, 1, 0x2}, // Shift overflow.
5413 {0x4, INT32_MAX >> 1, 2, 0x0}, // Shift overflow.
5414 {0x4, INT32_MAX >> 2, 3, 0xfffffffc}, // Shift overflow.
5415 {0x4, INT32_MAX >> 3, 4, 0xfffffff4}, // Shift overflow.
5416 {INT32_MAX - 1, 0x1, 1, 0x80000000}, // Signed adition overflow.
5417 {INT32_MAX - 3, 0x1, 2, 0x80000000}, // Signed addition overflow.
5418 {INT32_MAX - 7, 0x1, 3, 0x80000000}, // Signed addition overflow.
5419 {INT32_MAX - 15, 0x1, 4, 0x80000000}, // Signed addition overflow.
5420 {-2, 0x1, 1, 0x0}, // Addition overflow.
5421 {-4, 0x1, 2, 0x0}, // Addition overflow.
5422 {-8, 0x1, 3, 0x0}, // Addition overflow.
5423 {-16, 0x1, 4, 0x0}}; // Addition overflow.
5424
5425 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLsa);
5426 for (size_t i = 0; i < nr_test_cases; ++i) {
5427 uint32_t res = run_lsa(tc[i].rt, tc[i].rs, tc[i].sa);
5428 PrintF("0x%x =? 0x%x == lsa(v0, %x, %x, %hhu)\n", tc[i].expected_res, res,
5429 tc[i].rt, tc[i].rs, tc[i].sa);
5430 CHECK_EQ(tc[i].expected_res, res);
5431 }
5432}
5433
5434
5435TEST(Trampoline) {
5436 // Private member of Assembler class.
5437 static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
5438
5439 CcTest::InitializeVM();
5440 Isolate* isolate = CcTest::i_isolate();
5441 HandleScope scope(isolate);
5442
5443 MacroAssembler assm(isolate, nullptr, 0,
5444 v8::internal::CodeObjectRequired::kYes);
5445 Label done;
5446 size_t nr_calls = kMaxBranchOffset / (2 * Instruction::kInstrSize) + 2;
5447
5448 for (size_t i = 0; i < nr_calls; ++i) {
5449 __ BranchShort(&done, eq, a0, Operand(a1));
5450 }
5451 __ bind(&done);
5452 __ Ret(USE_DELAY_SLOT);
5453 __ mov(v0, zero_reg);
5454
5455 CodeDesc desc;
5456 assm.GetCode(&desc);
5457 Handle<Code> code = isolate->factory()->NewCode(
5458 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
5459 F2 f = FUNCTION_CAST<F2>(code->entry());
5460
5461 int32_t res = reinterpret_cast<int32_t>(
5462 CALL_GENERATED_CODE(isolate, f, 42, 42, 0, 0, 0));
5463 CHECK_EQ(res, 0);
5464}
5465
Andrei Popescu402d9372010-02-26 13:31:12 +00005466#undef __