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