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