blob: ca11a2ae1f16de3f2aed537e88564b9657e65910 [file] [log] [blame]
Ben Murdoch257744e2011-11-30 15:57:28 +00001// Copyright 2011 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
28#include "v8.h"
29
30#include "disassembler.h"
31#include "factory.h"
32#include "macro-assembler.h"
33#include "mips/macro-assembler-mips.h"
34#include "mips/simulator-mips.h"
35
36#include "cctest.h"
37
38using namespace v8::internal;
39
40
41// Define these function prototypes to match JSEntryFunction in execution.cc.
42typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
43typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
44typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4);
45
46
47static v8::Persistent<v8::Context> env;
48
49
Andrei Popescu402d9372010-02-26 13:31:12 +000050static void InitializeVM() {
Steve Block6ded16b2010-05-10 14:33:55 +010051 // Disable compilation of natives.
52 FLAG_disable_native_files = true;
Andrei Popescu402d9372010-02-26 13:31:12 +000053
Andrei Popescu402d9372010-02-26 13:31:12 +000054 if (env.IsEmpty()) {
55 env = v8::Context::New();
56 }
57}
58
59
60#define __ assm.
61
Steve Block44f0eee2011-05-26 01:26:41 +010062
Andrei Popescu402d9372010-02-26 13:31:12 +000063TEST(MIPS0) {
64 InitializeVM();
65 v8::HandleScope scope;
66
Ben Murdoch257744e2011-11-30 15:57:28 +000067 MacroAssembler assm(Isolate::Current(), NULL, 0);
Andrei Popescu402d9372010-02-26 13:31:12 +000068
69 // Addition.
70 __ addu(v0, a0, a1);
71 __ jr(ra);
72 __ nop();
73
74 CodeDesc desc;
75 assm.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +010076 Object* code = HEAP->CreateCode(
77 desc,
78 Code::ComputeFlags(Code::STUB),
79 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000080 CHECK(code->IsCode());
Andrei Popescu402d9372010-02-26 13:31:12 +000081 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
82 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
83 ::printf("f() = %d\n", res);
84 CHECK_EQ(0xabc, res);
85}
86
87
88TEST(MIPS1) {
89 InitializeVM();
90 v8::HandleScope scope;
91
Ben Murdoch257744e2011-11-30 15:57:28 +000092 MacroAssembler assm(Isolate::Current(), NULL, 0);
Andrei Popescu402d9372010-02-26 13:31:12 +000093 Label L, C;
94
95 __ mov(a1, a0);
96 __ li(v0, 0);
97 __ b(&C);
98 __ nop();
99
100 __ bind(&L);
Steve Block44f0eee2011-05-26 01:26:41 +0100101 __ addu(v0, v0, a1);
Andrei Popescu402d9372010-02-26 13:31:12 +0000102 __ addiu(a1, a1, -1);
103
104 __ bind(&C);
105 __ xori(v1, a1, 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100106 __ Branch(&L, ne, v1, Operand(0));
Andrei Popescu402d9372010-02-26 13:31:12 +0000107 __ nop();
108
109 __ jr(ra);
110 __ nop();
111
112 CodeDesc desc;
113 assm.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +0100114 Object* code = HEAP->CreateCode(
115 desc,
116 Code::ComputeFlags(Code::STUB),
117 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +0000118 CHECK(code->IsCode());
Andrei Popescu402d9372010-02-26 13:31:12 +0000119 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
120 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0));
121 ::printf("f() = %d\n", res);
122 CHECK_EQ(1275, res);
123}
124
125
126TEST(MIPS2) {
127 InitializeVM();
128 v8::HandleScope scope;
129
Ben Murdoch257744e2011-11-30 15:57:28 +0000130 MacroAssembler assm(Isolate::Current(), NULL, 0);
Andrei Popescu402d9372010-02-26 13:31:12 +0000131
132 Label exit, error;
133
134 // ----- Test all instructions.
135
136 // Test lui, ori, and addiu, used in the li pseudo-instruction.
137 // This way we can then safely load registers with chosen values.
138
139 __ ori(t0, zero_reg, 0);
140 __ lui(t0, 0x1234);
141 __ ori(t0, t0, 0);
142 __ ori(t0, t0, 0x0f0f);
143 __ ori(t0, t0, 0xf0f0);
144 __ addiu(t1, t0, 1);
145 __ addiu(t2, t1, -0x10);
146
147 // Load values in temporary registers.
148 __ li(t0, 0x00000004);
149 __ li(t1, 0x00001234);
150 __ li(t2, 0x12345678);
151 __ li(t3, 0x7fffffff);
152 __ li(t4, 0xfffffffc);
153 __ li(t5, 0xffffedcc);
154 __ li(t6, 0xedcba988);
155 __ li(t7, 0x80000000);
156
157 // SPECIAL class.
158 __ srl(v0, t2, 8); // 0x00123456
159 __ sll(v0, v0, 11); // 0x91a2b000
160 __ sra(v0, v0, 3); // 0xf2345600
161 __ srav(v0, v0, t0); // 0xff234560
162 __ sllv(v0, v0, t0); // 0xf2345600
163 __ srlv(v0, v0, t0); // 0x0f234560
Steve Block44f0eee2011-05-26 01:26:41 +0100164 __ Branch(&error, ne, v0, Operand(0x0f234560));
Andrei Popescu402d9372010-02-26 13:31:12 +0000165 __ nop();
166
Steve Block44f0eee2011-05-26 01:26:41 +0100167 __ addu(v0, t0, t1); // 0x00001238
168 __ subu(v0, v0, t0); // 0x00001234
169 __ Branch(&error, ne, v0, Operand(0x00001234));
Andrei Popescu402d9372010-02-26 13:31:12 +0000170 __ nop();
171 __ addu(v1, t3, t0);
Steve Block44f0eee2011-05-26 01:26:41 +0100172 __ Branch(&error, ne, v1, Operand(0x80000003));
Andrei Popescu402d9372010-02-26 13:31:12 +0000173 __ nop();
174 __ subu(v1, t7, t0); // 0x7ffffffc
Steve Block44f0eee2011-05-26 01:26:41 +0100175 __ Branch(&error, ne, v1, Operand(0x7ffffffc));
Andrei Popescu402d9372010-02-26 13:31:12 +0000176 __ nop();
177
178 __ and_(v0, t1, t2); // 0x00001230
179 __ or_(v0, v0, t1); // 0x00001234
180 __ xor_(v0, v0, t2); // 0x1234444c
181 __ nor(v0, v0, t2); // 0xedcba987
Steve Block44f0eee2011-05-26 01:26:41 +0100182 __ Branch(&error, ne, v0, Operand(0xedcba983));
Andrei Popescu402d9372010-02-26 13:31:12 +0000183 __ nop();
184
185 __ slt(v0, t7, t3);
Steve Block44f0eee2011-05-26 01:26:41 +0100186 __ Branch(&error, ne, v0, Operand(0x1));
Andrei Popescu402d9372010-02-26 13:31:12 +0000187 __ nop();
188 __ sltu(v0, t7, t3);
Steve Block44f0eee2011-05-26 01:26:41 +0100189 __ Branch(&error, ne, v0, Operand(0x0));
Andrei Popescu402d9372010-02-26 13:31:12 +0000190 __ nop();
191 // End of SPECIAL class.
192
Steve Block44f0eee2011-05-26 01:26:41 +0100193 __ addiu(v0, zero_reg, 0x7421); // 0x00007421
194 __ addiu(v0, v0, -0x1); // 0x00007420
Andrei Popescu402d9372010-02-26 13:31:12 +0000195 __ addiu(v0, v0, -0x20); // 0x00007400
Steve Block44f0eee2011-05-26 01:26:41 +0100196 __ Branch(&error, ne, v0, Operand(0x00007400));
Andrei Popescu402d9372010-02-26 13:31:12 +0000197 __ nop();
198 __ addiu(v1, t3, 0x1); // 0x80000000
Steve Block44f0eee2011-05-26 01:26:41 +0100199 __ Branch(&error, ne, v1, Operand(0x80000000));
Andrei Popescu402d9372010-02-26 13:31:12 +0000200 __ nop();
201
202 __ slti(v0, t1, 0x00002000); // 0x1
203 __ slti(v0, v0, 0xffff8000); // 0x0
Steve Block44f0eee2011-05-26 01:26:41 +0100204 __ Branch(&error, ne, v0, Operand(0x0));
Andrei Popescu402d9372010-02-26 13:31:12 +0000205 __ nop();
206 __ sltiu(v0, t1, 0x00002000); // 0x1
207 __ sltiu(v0, v0, 0x00008000); // 0x1
Steve Block44f0eee2011-05-26 01:26:41 +0100208 __ Branch(&error, ne, v0, Operand(0x1));
Andrei Popescu402d9372010-02-26 13:31:12 +0000209 __ nop();
210
211 __ andi(v0, t1, 0xf0f0); // 0x00001030
212 __ ori(v0, v0, 0x8a00); // 0x00009a30
213 __ xori(v0, v0, 0x83cc); // 0x000019fc
Steve Block44f0eee2011-05-26 01:26:41 +0100214 __ Branch(&error, ne, v0, Operand(0x000019fc));
Andrei Popescu402d9372010-02-26 13:31:12 +0000215 __ nop();
216 __ lui(v1, 0x8123); // 0x81230000
Steve Block44f0eee2011-05-26 01:26:41 +0100217 __ Branch(&error, ne, v1, Operand(0x81230000));
Andrei Popescu402d9372010-02-26 13:31:12 +0000218 __ nop();
219
Steve Block44f0eee2011-05-26 01:26:41 +0100220 // Bit twiddling instructions & conditional moves.
221 // Uses t0-t7 as set above.
222 __ clz(v0, t0); // 29
223 __ clz(v1, t1); // 19
224 __ addu(v0, v0, v1); // 48
225 __ clz(v1, t2); // 3
226 __ addu(v0, v0, v1); // 51
227 __ clz(v1, t7); // 0
228 __ addu(v0, v0, v1); // 51
229 __ Branch(&error, ne, v0, Operand(51));
230 __ movn(a0, t3, t0); // Move a0<-t3 (t0 is NOT 0).
231 __ Ins(a0, t1, 12, 8); // 0x7ff34fff
232 __ Branch(&error, ne, a0, Operand(0x7ff34fff));
233 __ movz(a0, t6, t7); // a0 not updated (t7 is NOT 0).
234 __ Ext(a1, a0, 8, 12); // 0x34f
235 __ Branch(&error, ne, a1, Operand(0x34f));
236 __ movz(a0, t6, v1); // a0<-t6, v0 is 0, from 8 instr back.
237 __ Branch(&error, ne, a0, Operand(t6));
238
Andrei Popescu402d9372010-02-26 13:31:12 +0000239 // Everything was correctly executed. Load the expected result.
240 __ li(v0, 0x31415926);
241 __ b(&exit);
242 __ nop();
243
244 __ bind(&error);
245 // Got an error. Return a wrong result.
Steve Block44f0eee2011-05-26 01:26:41 +0100246 __ li(v0, 666);
Andrei Popescu402d9372010-02-26 13:31:12 +0000247
248 __ bind(&exit);
249 __ jr(ra);
250 __ nop();
251
252 CodeDesc desc;
253 assm.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +0100254 Object* code = HEAP->CreateCode(
255 desc,
256 Code::ComputeFlags(Code::STUB),
257 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +0000258 CHECK(code->IsCode());
Andrei Popescu402d9372010-02-26 13:31:12 +0000259 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
260 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
261 ::printf("f() = %d\n", res);
262 CHECK_EQ(0x31415926, res);
263}
264
Steve Block44f0eee2011-05-26 01:26:41 +0100265
266TEST(MIPS3) {
267 // Test floating point instructions.
268 InitializeVM();
269 v8::HandleScope scope;
270
271 typedef struct {
272 double a;
273 double b;
274 double c;
275 double d;
276 double e;
277 double f;
278 double g;
279 } T;
280 T t;
281
282 // Create a function that accepts &t, and loads, manipulates, and stores
283 // the doubles t.a ... t.f.
Ben Murdoch257744e2011-11-30 15:57:28 +0000284 MacroAssembler assm(Isolate::Current(), NULL, 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100285 Label L, C;
286
Ben Murdoch257744e2011-11-30 15:57:28 +0000287 if (CpuFeatures::IsSupported(FPU)) {
Steve Block44f0eee2011-05-26 01:26:41 +0100288 CpuFeatures::Scope scope(FPU);
289
290 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
291 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
292 __ add_d(f8, f4, f6);
293 __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, c)) ); // c = a + b.
294
295 __ mov_d(f10, f8); // c
296 __ neg_d(f12, f6); // -b
297 __ sub_d(f10, f10, f12);
298 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, d)) ); // d = c - (-b).
299
300 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) ); // b = a.
301
302 __ li(t0, 120);
303 __ mtc1(t0, f14);
304 __ cvt_d_w(f14, f14); // f14 = 120.0.
305 __ mul_d(f10, f10, f14);
306 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, e)) ); // e = d * 120 = 1.8066e16.
307
308 __ div_d(f12, f10, f4);
309 __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) ); // f = e / a = 120.44.
310
311 __ sqrt_d(f14, f12);
312 __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, g)) );
313 // g = sqrt(f) = 10.97451593465515908537
314
315 __ jr(ra);
316 __ nop();
317
318 CodeDesc desc;
319 assm.GetCode(&desc);
320 Object* code = HEAP->CreateCode(
321 desc,
322 Code::ComputeFlags(Code::STUB),
323 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
324 CHECK(code->IsCode());
325 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
326 t.a = 1.5e14;
327 t.b = 2.75e11;
328 t.c = 0.0;
329 t.d = 0.0;
330 t.e = 0.0;
331 t.f = 0.0;
332 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
333 USE(dummy);
334 CHECK_EQ(1.5e14, t.a);
335 CHECK_EQ(1.5e14, t.b);
336 CHECK_EQ(1.50275e14, t.c);
337 CHECK_EQ(1.50550e14, t.d);
338 CHECK_EQ(1.8066e16, t.e);
339 CHECK_EQ(120.44, t.f);
340 CHECK_EQ(10.97451593465515908537, t.g);
341 }
342}
343
344
345TEST(MIPS4) {
346 // Test moves between floating point and integer registers.
347 InitializeVM();
348 v8::HandleScope scope;
349
350 typedef struct {
351 double a;
352 double b;
353 double c;
354 } T;
355 T t;
356
Ben Murdoch257744e2011-11-30 15:57:28 +0000357 Assembler assm(Isolate::Current(), NULL, 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100358 Label L, C;
359
Ben Murdoch257744e2011-11-30 15:57:28 +0000360 if (CpuFeatures::IsSupported(FPU)) {
Steve Block44f0eee2011-05-26 01:26:41 +0100361 CpuFeatures::Scope scope(FPU);
362
363 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
364 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
365
366 // Swap f4 and f6, by using four integer registers, t0-t3.
367 __ mfc1(t0, f4);
368 __ mfc1(t1, f5);
369 __ mfc1(t2, f6);
370 __ mfc1(t3, f7);
371
372 __ mtc1(t0, f6);
373 __ mtc1(t1, f7);
374 __ mtc1(t2, f4);
375 __ mtc1(t3, f5);
376
377 // Store the swapped f4 and f5 back to memory.
378 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
379 __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, c)) );
380
381 __ jr(ra);
382 __ nop();
383
384 CodeDesc desc;
385 assm.GetCode(&desc);
386 Object* code = HEAP->CreateCode(
387 desc,
388 Code::ComputeFlags(Code::STUB),
389 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
390 CHECK(code->IsCode());
391 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
392 t.a = 1.5e22;
393 t.b = 2.75e11;
394 t.c = 17.17;
395 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
396 USE(dummy);
397
398 CHECK_EQ(2.75e11, t.a);
399 CHECK_EQ(2.75e11, t.b);
400 CHECK_EQ(1.5e22, t.c);
401 }
402}
403
404
405TEST(MIPS5) {
406 // Test conversions between doubles and integers.
407 InitializeVM();
408 v8::HandleScope scope;
409
410 typedef struct {
411 double a;
412 double b;
413 int i;
414 int j;
415 } T;
416 T t;
417
Ben Murdoch257744e2011-11-30 15:57:28 +0000418 Assembler assm(Isolate::Current(), NULL, 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100419 Label L, C;
420
Ben Murdoch257744e2011-11-30 15:57:28 +0000421 if (CpuFeatures::IsSupported(FPU)) {
Steve Block44f0eee2011-05-26 01:26:41 +0100422 CpuFeatures::Scope scope(FPU);
423
424 // Load all structure elements to registers.
425 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
426 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
427 __ lw(t0, MemOperand(a0, OFFSET_OF(T, i)) );
428 __ lw(t1, MemOperand(a0, OFFSET_OF(T, j)) );
429
430 // Convert double in f4 to int in element i.
431 __ cvt_w_d(f8, f4);
432 __ mfc1(t2, f8);
433 __ sw(t2, MemOperand(a0, OFFSET_OF(T, i)) );
434
435 // Convert double in f6 to int in element j.
436 __ cvt_w_d(f10, f6);
437 __ mfc1(t3, f10);
438 __ sw(t3, MemOperand(a0, OFFSET_OF(T, j)) );
439
440 // Convert int in original i (t0) to double in a.
441 __ mtc1(t0, f12);
442 __ cvt_d_w(f0, f12);
443 __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) );
444
445 // Convert int in original j (t1) to double in b.
446 __ mtc1(t1, f14);
447 __ cvt_d_w(f2, f14);
448 __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) );
449
450 __ jr(ra);
451 __ nop();
452
453 CodeDesc desc;
454 assm.GetCode(&desc);
455 Object* code = HEAP->CreateCode(
456 desc,
457 Code::ComputeFlags(Code::STUB),
458 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
459 CHECK(code->IsCode());
460 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
461 t.a = 1.5e4;
462 t.b = 2.75e8;
463 t.i = 12345678;
464 t.j = -100000;
465 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
466 USE(dummy);
467
468 CHECK_EQ(12345678.0, t.a);
469 CHECK_EQ(-100000.0, t.b);
470 CHECK_EQ(15000, t.i);
471 CHECK_EQ(275000000, t.j);
472 }
473}
474
475
476TEST(MIPS6) {
477 // Test simple memory loads and stores.
478 InitializeVM();
479 v8::HandleScope scope;
480
481 typedef struct {
482 uint32_t ui;
483 int32_t si;
484 int32_t r1;
485 int32_t r2;
486 int32_t r3;
487 int32_t r4;
488 int32_t r5;
489 int32_t r6;
490 } T;
491 T t;
492
Ben Murdoch257744e2011-11-30 15:57:28 +0000493 Assembler assm(Isolate::Current(), NULL, 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100494 Label L, C;
495
496 // Basic word load/store.
497 __ lw(t0, MemOperand(a0, OFFSET_OF(T, ui)) );
498 __ sw(t0, MemOperand(a0, OFFSET_OF(T, r1)) );
499
500 // lh with positive data.
501 __ lh(t1, MemOperand(a0, OFFSET_OF(T, ui)) );
502 __ sw(t1, MemOperand(a0, OFFSET_OF(T, r2)) );
503
504 // lh with negative data.
505 __ lh(t2, MemOperand(a0, OFFSET_OF(T, si)) );
506 __ sw(t2, MemOperand(a0, OFFSET_OF(T, r3)) );
507
508 // lhu with negative data.
509 __ lhu(t3, MemOperand(a0, OFFSET_OF(T, si)) );
510 __ sw(t3, MemOperand(a0, OFFSET_OF(T, r4)) );
511
512 // lb with negative data.
513 __ lb(t4, MemOperand(a0, OFFSET_OF(T, si)) );
514 __ sw(t4, MemOperand(a0, OFFSET_OF(T, r5)) );
515
516 // sh writes only 1/2 of word.
517 __ lui(t5, 0x3333);
518 __ ori(t5, t5, 0x3333);
519 __ sw(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
520 __ lhu(t5, MemOperand(a0, OFFSET_OF(T, si)) );
521 __ sh(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
522
523 __ jr(ra);
524 __ nop();
525
526 CodeDesc desc;
527 assm.GetCode(&desc);
528 Object* code = HEAP->CreateCode(
529 desc,
530 Code::ComputeFlags(Code::STUB),
531 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
532 CHECK(code->IsCode());
533 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
534 t.ui = 0x11223344;
535 t.si = 0x99aabbcc;
536 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
537 USE(dummy);
538
539 CHECK_EQ(0x11223344, t.r1);
540 CHECK_EQ(0x3344, t.r2);
541 CHECK_EQ(0xffffbbcc, t.r3);
542 CHECK_EQ(0x0000bbcc, t.r4);
543 CHECK_EQ(0xffffffcc, t.r5);
544 CHECK_EQ(0x3333bbcc, t.r6);
545}
546
547
548TEST(MIPS7) {
549 // Test floating point compare and branch instructions.
550 InitializeVM();
551 v8::HandleScope scope;
552
553 typedef struct {
554 double a;
555 double b;
556 double c;
557 double d;
558 double e;
559 double f;
560 int32_t result;
561 } T;
562 T t;
563
564 // Create a function that accepts &t, and loads, manipulates, and stores
565 // the doubles t.a ... t.f.
Ben Murdoch257744e2011-11-30 15:57:28 +0000566 MacroAssembler assm(Isolate::Current(), NULL, 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100567 Label neither_is_nan, less_than, outa_here;
568
Ben Murdoch257744e2011-11-30 15:57:28 +0000569 if (CpuFeatures::IsSupported(FPU)) {
Steve Block44f0eee2011-05-26 01:26:41 +0100570 CpuFeatures::Scope scope(FPU);
571
572 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
573 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
574 __ c(UN, D, f4, f6);
575 __ bc1f(&neither_is_nan);
576 __ nop();
577 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
578 __ Branch(&outa_here);
579
580 __ bind(&neither_is_nan);
581
582 __ c(OLT, D, f6, f4, 2);
583 __ bc1t(&less_than, 2);
584 __ nop();
585 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
586 __ Branch(&outa_here);
587
588 __ bind(&less_than);
589 __ Addu(t0, zero_reg, Operand(1));
590 __ sw(t0, MemOperand(a0, OFFSET_OF(T, result)) ); // Set true.
591
592
593 // This test-case should have additional tests.
594
595 __ bind(&outa_here);
596
597 __ jr(ra);
598 __ nop();
599
600 CodeDesc desc;
601 assm.GetCode(&desc);
602 Object* code = HEAP->CreateCode(
603 desc,
604 Code::ComputeFlags(Code::STUB),
605 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
606 CHECK(code->IsCode());
607 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
608 t.a = 1.5e14;
609 t.b = 2.75e11;
610 t.c = 2.0;
611 t.d = -4.0;
612 t.e = 0.0;
613 t.f = 0.0;
614 t.result = 0;
615 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
616 USE(dummy);
617 CHECK_EQ(1.5e14, t.a);
618 CHECK_EQ(2.75e11, t.b);
619 CHECK_EQ(1, t.result);
620 }
621}
622
623
624TEST(MIPS8) {
625 // Test ROTR and ROTRV instructions.
626 InitializeVM();
627 v8::HandleScope scope;
628
629 typedef struct {
630 int32_t input;
631 int32_t result_rotr_4;
632 int32_t result_rotr_8;
633 int32_t result_rotr_12;
634 int32_t result_rotr_16;
635 int32_t result_rotr_20;
636 int32_t result_rotr_24;
637 int32_t result_rotr_28;
638 int32_t result_rotrv_4;
639 int32_t result_rotrv_8;
640 int32_t result_rotrv_12;
641 int32_t result_rotrv_16;
642 int32_t result_rotrv_20;
643 int32_t result_rotrv_24;
644 int32_t result_rotrv_28;
645 } T;
646 T t;
647
Ben Murdoch257744e2011-11-30 15:57:28 +0000648 MacroAssembler assm(Isolate::Current(), NULL, 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100649
650 // Basic word load.
651 __ lw(t0, MemOperand(a0, OFFSET_OF(T, input)) );
652
653 // ROTR instruction (called through the Ror macro).
654 __ Ror(t1, t0, 0x0004);
655 __ Ror(t2, t0, 0x0008);
656 __ Ror(t3, t0, 0x000c);
657 __ Ror(t4, t0, 0x0010);
658 __ Ror(t5, t0, 0x0014);
659 __ Ror(t6, t0, 0x0018);
660 __ Ror(t7, t0, 0x001c);
661
662 // Basic word store.
663 __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotr_4)) );
664 __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotr_8)) );
665 __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotr_12)) );
666 __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotr_16)) );
667 __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotr_20)) );
668 __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotr_24)) );
669 __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotr_28)) );
670
671 // ROTRV instruction (called through the Ror macro).
672 __ li(t7, 0x0004);
673 __ Ror(t1, t0, t7);
674 __ li(t7, 0x0008);
675 __ Ror(t2, t0, t7);
676 __ li(t7, 0x000C);
677 __ Ror(t3, t0, t7);
678 __ li(t7, 0x0010);
679 __ Ror(t4, t0, t7);
680 __ li(t7, 0x0014);
681 __ Ror(t5, t0, t7);
682 __ li(t7, 0x0018);
683 __ Ror(t6, t0, t7);
684 __ li(t7, 0x001C);
685 __ Ror(t7, t0, t7);
686
687 // Basic word store.
688 __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotrv_4)) );
689 __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotrv_8)) );
690 __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotrv_12)) );
691 __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotrv_16)) );
692 __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotrv_20)) );
693 __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotrv_24)) );
694 __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotrv_28)) );
695
696 __ jr(ra);
697 __ nop();
698
699 CodeDesc desc;
700 assm.GetCode(&desc);
701 Object* code = HEAP->CreateCode(
702 desc,
703 Code::ComputeFlags(Code::STUB),
704 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
705 CHECK(code->IsCode());
706 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
707 t.input = 0x12345678;
708 Object* dummy = CALL_GENERATED_CODE(f, &t, 0x0, 0, 0, 0);
709 USE(dummy);
710 CHECK_EQ(0x81234567, t.result_rotr_4);
711 CHECK_EQ(0x78123456, t.result_rotr_8);
712 CHECK_EQ(0x67812345, t.result_rotr_12);
713 CHECK_EQ(0x56781234, t.result_rotr_16);
714 CHECK_EQ(0x45678123, t.result_rotr_20);
715 CHECK_EQ(0x34567812, t.result_rotr_24);
716 CHECK_EQ(0x23456781, t.result_rotr_28);
717
718 CHECK_EQ(0x81234567, t.result_rotrv_4);
719 CHECK_EQ(0x78123456, t.result_rotrv_8);
720 CHECK_EQ(0x67812345, t.result_rotrv_12);
721 CHECK_EQ(0x56781234, t.result_rotrv_16);
722 CHECK_EQ(0x45678123, t.result_rotrv_20);
723 CHECK_EQ(0x34567812, t.result_rotrv_24);
724 CHECK_EQ(0x23456781, t.result_rotrv_28);
725}
726
727
728TEST(MIPS9) {
729 // Test BRANCH improvements.
730 InitializeVM();
731 v8::HandleScope scope;
732
Ben Murdoch257744e2011-11-30 15:57:28 +0000733 MacroAssembler assm(Isolate::Current(), NULL, 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100734 Label exit, exit2, exit3;
735
736 __ Branch(&exit, ge, a0, Operand(0x00000000));
737 __ Branch(&exit2, ge, a0, Operand(0x00001FFF));
738 __ Branch(&exit3, ge, a0, Operand(0x0001FFFF));
739
740 __ bind(&exit);
741 __ bind(&exit2);
742 __ bind(&exit3);
743 __ jr(ra);
744 __ nop();
745
746 CodeDesc desc;
747 assm.GetCode(&desc);
748 Object* code = HEAP->CreateCode(
749 desc,
750 Code::ComputeFlags(Code::STUB),
751 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
752 CHECK(code->IsCode());
753}
754
755
756TEST(MIPS10) {
757 // Test conversions between doubles and long integers.
758 // Test hos the long ints map to FP regs pairs.
759 InitializeVM();
760 v8::HandleScope scope;
761
762 typedef struct {
763 double a;
764 double b;
765 int32_t dbl_mant;
766 int32_t dbl_exp;
767 int32_t long_hi;
768 int32_t long_lo;
769 int32_t b_long_hi;
770 int32_t b_long_lo;
771 } T;
772 T t;
773
Ben Murdoch257744e2011-11-30 15:57:28 +0000774 Assembler assm(Isolate::Current(), NULL, 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100775 Label L, C;
776
Ben Murdoch257744e2011-11-30 15:57:28 +0000777 if (CpuFeatures::IsSupported(FPU)) {
Steve Block44f0eee2011-05-26 01:26:41 +0100778 CpuFeatures::Scope scope(FPU);
779
780 // Load all structure elements to registers.
781 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a)));
782
783 // Save the raw bits of the double.
784 __ mfc1(t0, f0);
785 __ mfc1(t1, f1);
786 __ sw(t0, MemOperand(a0, OFFSET_OF(T, dbl_mant)));
787 __ sw(t1, MemOperand(a0, OFFSET_OF(T, dbl_exp)));
788
789 // Convert double in f0 to long, save hi/lo parts.
790 __ cvt_l_d(f0, f0);
791 __ mfc1(t0, f0); // f0 has LS 32 bits of long.
792 __ mfc1(t1, f1); // f1 has MS 32 bits of long.
793 __ sw(t0, MemOperand(a0, OFFSET_OF(T, long_lo)));
794 __ sw(t1, MemOperand(a0, OFFSET_OF(T, long_hi)));
795
796 // Convert the b long integers to double b.
797 __ lw(t0, MemOperand(a0, OFFSET_OF(T, b_long_lo)));
798 __ lw(t1, MemOperand(a0, OFFSET_OF(T, b_long_hi)));
799 __ mtc1(t0, f8); // f8 has LS 32-bits.
800 __ mtc1(t1, f9); // f9 has MS 32-bits.
801 __ cvt_d_l(f10, f8);
802 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, b)));
803
804 __ jr(ra);
805 __ nop();
806
807 CodeDesc desc;
808 assm.GetCode(&desc);
809 Object* code = HEAP->CreateCode(
810 desc,
811 Code::ComputeFlags(Code::STUB),
812 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
813 CHECK(code->IsCode());
814 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
815 t.a = 2.147483647e9; // 0x7fffffff -> 0x41DFFFFFFFC00000 as double.
816 t.b_long_hi = 0x000000ff; // 0xFF00FF00FF -> 0x426FE01FE01FE000 as double.
817 t.b_long_lo = 0x00ff00ff;
818 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
819 USE(dummy);
820
821 CHECK_EQ(0x41DFFFFF, t.dbl_exp);
822 CHECK_EQ(0xFFC00000, t.dbl_mant);
823 CHECK_EQ(0, t.long_hi);
824 CHECK_EQ(0x7fffffff, t.long_lo);
825 // 0xFF00FF00FF -> 1.095233372415e12.
826 CHECK_EQ(1.095233372415e12, t.b);
827 }
828}
829
830
831TEST(MIPS11) {
832 // Test LWL, LWR, SWL and SWR instructions.
833 InitializeVM();
834 v8::HandleScope scope;
835
836 typedef struct {
837 int32_t reg_init;
838 int32_t mem_init;
839 int32_t lwl_0;
840 int32_t lwl_1;
841 int32_t lwl_2;
842 int32_t lwl_3;
843 int32_t lwr_0;
844 int32_t lwr_1;
845 int32_t lwr_2;
846 int32_t lwr_3;
847 int32_t swl_0;
848 int32_t swl_1;
849 int32_t swl_2;
850 int32_t swl_3;
851 int32_t swr_0;
852 int32_t swr_1;
853 int32_t swr_2;
854 int32_t swr_3;
855 } T;
856 T t;
857
Ben Murdoch257744e2011-11-30 15:57:28 +0000858 Assembler assm(Isolate::Current(), NULL, 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100859
860 // Test all combinations of LWL and vAddr.
861 __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
862 __ lwl(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
863 __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwl_0)) );
864
865 __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
866 __ lwl(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) );
867 __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwl_1)) );
868
869 __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
870 __ lwl(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) );
871 __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwl_2)) );
872
873 __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
874 __ lwl(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) );
875 __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwl_3)) );
876
877 // Test all combinations of LWR and vAddr.
878 __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
879 __ lwr(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
880 __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwr_0)) );
881
882 __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
883 __ lwr(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) );
884 __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwr_1)) );
885
886 __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
887 __ lwr(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) );
888 __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwr_2)) );
889
890 __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
891 __ lwr(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) );
892 __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwr_3)) );
893
894 // Test all combinations of SWL and vAddr.
895 __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
896 __ sw(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) );
897 __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
898 __ swl(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) );
899
900 __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) );
901 __ sw(t1, MemOperand(a0, OFFSET_OF(T, swl_1)) );
902 __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
903 __ swl(t1, MemOperand(a0, OFFSET_OF(T, swl_1) + 1) );
904
905 __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) );
906 __ sw(t2, MemOperand(a0, OFFSET_OF(T, swl_2)) );
907 __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
908 __ swl(t2, MemOperand(a0, OFFSET_OF(T, swl_2) + 2) );
909
910 __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) );
911 __ sw(t3, MemOperand(a0, OFFSET_OF(T, swl_3)) );
912 __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
913 __ swl(t3, MemOperand(a0, OFFSET_OF(T, swl_3) + 3) );
914
915 // Test all combinations of SWR and vAddr.
916 __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
917 __ sw(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) );
918 __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
919 __ swr(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) );
920
921 __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) );
922 __ sw(t1, MemOperand(a0, OFFSET_OF(T, swr_1)) );
923 __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
924 __ swr(t1, MemOperand(a0, OFFSET_OF(T, swr_1) + 1) );
925
926 __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) );
927 __ sw(t2, MemOperand(a0, OFFSET_OF(T, swr_2)) );
928 __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
929 __ swr(t2, MemOperand(a0, OFFSET_OF(T, swr_2) + 2) );
930
931 __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) );
932 __ sw(t3, MemOperand(a0, OFFSET_OF(T, swr_3)) );
933 __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
934 __ swr(t3, MemOperand(a0, OFFSET_OF(T, swr_3) + 3) );
935
936 __ jr(ra);
937 __ nop();
938
939 CodeDesc desc;
940 assm.GetCode(&desc);
941 Object* code = HEAP->CreateCode(
942 desc,
943 Code::ComputeFlags(Code::STUB),
944 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
945 CHECK(code->IsCode());
946 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
947 t.reg_init = 0xaabbccdd;
948 t.mem_init = 0x11223344;
949
950 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
951 USE(dummy);
952
953 CHECK_EQ(0x44bbccdd, t.lwl_0);
954 CHECK_EQ(0x3344ccdd, t.lwl_1);
955 CHECK_EQ(0x223344dd, t.lwl_2);
956 CHECK_EQ(0x11223344, t.lwl_3);
957
958 CHECK_EQ(0x11223344, t.lwr_0);
959 CHECK_EQ(0xaa112233, t.lwr_1);
960 CHECK_EQ(0xaabb1122, t.lwr_2);
961 CHECK_EQ(0xaabbcc11, t.lwr_3);
962
963 CHECK_EQ(0x112233aa, t.swl_0);
964 CHECK_EQ(0x1122aabb, t.swl_1);
965 CHECK_EQ(0x11aabbcc, t.swl_2);
966 CHECK_EQ(0xaabbccdd, t.swl_3);
967
968 CHECK_EQ(0xaabbccdd, t.swr_0);
969 CHECK_EQ(0xbbccdd44, t.swr_1);
970 CHECK_EQ(0xccdd3344, t.swr_2);
971 CHECK_EQ(0xdd223344, t.swr_3);
972}
973
974
975TEST(MIPS12) {
976 InitializeVM();
977 v8::HandleScope scope;
978
979 typedef struct {
980 int32_t x;
981 int32_t y;
982 int32_t y1;
983 int32_t y2;
984 int32_t y3;
985 int32_t y4;
986 } T;
987 T t;
988
Ben Murdoch257744e2011-11-30 15:57:28 +0000989 MacroAssembler assm(Isolate::Current(), NULL, 0);
Steve Block44f0eee2011-05-26 01:26:41 +0100990
991 __ mov(t6, fp); // Save frame pointer.
992 __ mov(fp, a0); // Access struct T by fp.
993 __ lw(t0, MemOperand(a0, OFFSET_OF(T, y)) );
994 __ lw(t3, MemOperand(a0, OFFSET_OF(T, y4)) );
995
996 __ addu(t1, t0, t3);
997 __ subu(t4, t0, t3);
998 __ nop();
Ben Murdoch257744e2011-11-30 15:57:28 +0000999 __ push(t0); // These instructions disappear after opt.
Steve Block44f0eee2011-05-26 01:26:41 +01001000 __ Pop();
1001 __ addu(t0, t0, t0);
1002 __ nop();
1003 __ Pop(); // These instructions disappear after opt.
Ben Murdoch257744e2011-11-30 15:57:28 +00001004 __ push(t3);
Steve Block44f0eee2011-05-26 01:26:41 +01001005 __ nop();
Ben Murdoch257744e2011-11-30 15:57:28 +00001006 __ push(t3); // These instructions disappear after opt.
1007 __ pop(t3);
Steve Block44f0eee2011-05-26 01:26:41 +01001008 __ nop();
Ben Murdoch257744e2011-11-30 15:57:28 +00001009 __ push(t3);
1010 __ pop(t4);
Steve Block44f0eee2011-05-26 01:26:41 +01001011 __ nop();
1012 __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1013 __ lw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1014 __ nop();
1015 __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1016 __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
1017 __ nop();
Ben Murdoch257744e2011-11-30 15:57:28 +00001018 __ push(t1);
Steve Block44f0eee2011-05-26 01:26:41 +01001019 __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
Ben Murdoch257744e2011-11-30 15:57:28 +00001020 __ pop(t1);
Steve Block44f0eee2011-05-26 01:26:41 +01001021 __ nop();
Ben Murdoch257744e2011-11-30 15:57:28 +00001022 __ push(t1);
Steve Block44f0eee2011-05-26 01:26:41 +01001023 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
Ben Murdoch257744e2011-11-30 15:57:28 +00001024 __ pop(t1);
Steve Block44f0eee2011-05-26 01:26:41 +01001025 __ nop();
Ben Murdoch257744e2011-11-30 15:57:28 +00001026 __ push(t1);
Steve Block44f0eee2011-05-26 01:26:41 +01001027 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
Ben Murdoch257744e2011-11-30 15:57:28 +00001028 __ pop(t2);
Steve Block44f0eee2011-05-26 01:26:41 +01001029 __ nop();
Ben Murdoch257744e2011-11-30 15:57:28 +00001030 __ push(t2);
Steve Block44f0eee2011-05-26 01:26:41 +01001031 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
Ben Murdoch257744e2011-11-30 15:57:28 +00001032 __ pop(t1);
Steve Block44f0eee2011-05-26 01:26:41 +01001033 __ nop();
Ben Murdoch257744e2011-11-30 15:57:28 +00001034 __ push(t1);
Steve Block44f0eee2011-05-26 01:26:41 +01001035 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
Ben Murdoch257744e2011-11-30 15:57:28 +00001036 __ pop(t3);
Steve Block44f0eee2011-05-26 01:26:41 +01001037 __ nop();
1038
1039 __ mov(fp, t6);
1040 __ jr(ra);
1041 __ nop();
1042
1043 CodeDesc desc;
1044 assm.GetCode(&desc);
1045 Object* code = HEAP->CreateCode(
1046 desc,
1047 Code::ComputeFlags(Code::STUB),
1048 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
1049 CHECK(code->IsCode());
1050 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1051 t.x = 1;
1052 t.y = 2;
1053 t.y1 = 3;
1054 t.y2 = 4;
1055 t.y3 = 0XBABA;
1056 t.y4 = 0xDEDA;
1057
1058 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1059 USE(dummy);
1060
1061 CHECK_EQ(3, t.y1);
1062}
1063
1064
1065TEST(MIPS13) {
1066 // Test Cvt_d_uw and Trunc_uw_d macros.
1067 InitializeVM();
1068 v8::HandleScope scope;
1069
1070 typedef struct {
1071 double cvt_big_out;
1072 double cvt_small_out;
1073 uint32_t trunc_big_out;
1074 uint32_t trunc_small_out;
1075 uint32_t cvt_big_in;
1076 uint32_t cvt_small_in;
1077 } T;
1078 T t;
1079
Ben Murdoch257744e2011-11-30 15:57:28 +00001080 MacroAssembler assm(Isolate::Current(), NULL, 0);
Steve Block44f0eee2011-05-26 01:26:41 +01001081
Ben Murdoch257744e2011-11-30 15:57:28 +00001082 if (CpuFeatures::IsSupported(FPU)) {
Steve Block44f0eee2011-05-26 01:26:41 +01001083 CpuFeatures::Scope scope(FPU);
1084
1085 __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_small_in)));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001086 __ Cvt_d_uw(f10, t0, f22);
Steve Block44f0eee2011-05-26 01:26:41 +01001087 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out)));
1088
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001089 __ Trunc_uw_d(f10, f10, f22);
Steve Block44f0eee2011-05-26 01:26:41 +01001090 __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out)));
1091
1092 __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_big_in)));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001093 __ Cvt_d_uw(f8, t0, f22);
Steve Block44f0eee2011-05-26 01:26:41 +01001094 __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out)));
1095
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001096 __ Trunc_uw_d(f8, f8, f22);
Steve Block44f0eee2011-05-26 01:26:41 +01001097 __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out)));
1098
1099 __ jr(ra);
1100 __ nop();
1101
1102 CodeDesc desc;
1103 assm.GetCode(&desc);
1104 Object* code = HEAP->CreateCode(
1105 desc,
1106 Code::ComputeFlags(Code::STUB),
1107 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
1108 CHECK(code->IsCode());
1109 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1110
1111 t.cvt_big_in = 0xFFFFFFFF;
1112 t.cvt_small_in = 333;
1113
1114 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1115 USE(dummy);
1116
1117 CHECK_EQ(t.cvt_big_out, static_cast<double>(t.cvt_big_in));
1118 CHECK_EQ(t.cvt_small_out, static_cast<double>(t.cvt_small_in));
1119
1120 CHECK_EQ(static_cast<int>(t.trunc_big_out), static_cast<int>(t.cvt_big_in));
1121 CHECK_EQ(static_cast<int>(t.trunc_small_out),
1122 static_cast<int>(t.cvt_small_in));
1123 }
1124}
1125
1126
1127TEST(MIPS14) {
1128 // Test round, floor, ceil, trunc, cvt.
1129 InitializeVM();
1130 v8::HandleScope scope;
1131
1132#define ROUND_STRUCT_ELEMENT(x) \
1133 int32_t x##_up_out; \
1134 int32_t x##_down_out; \
1135 int32_t neg_##x##_up_out; \
1136 int32_t neg_##x##_down_out; \
Ben Murdoch257744e2011-11-30 15:57:28 +00001137 uint32_t x##_err1_out; \
1138 uint32_t x##_err2_out; \
1139 uint32_t x##_err3_out; \
1140 uint32_t x##_err4_out; \
Steve Block44f0eee2011-05-26 01:26:41 +01001141 int32_t x##_invalid_result;
1142
1143 typedef struct {
1144 double round_up_in;
1145 double round_down_in;
1146 double neg_round_up_in;
1147 double neg_round_down_in;
1148 double err1_in;
1149 double err2_in;
1150 double err3_in;
1151 double err4_in;
1152
1153 ROUND_STRUCT_ELEMENT(round)
1154 ROUND_STRUCT_ELEMENT(floor)
1155 ROUND_STRUCT_ELEMENT(ceil)
1156 ROUND_STRUCT_ELEMENT(trunc)
1157 ROUND_STRUCT_ELEMENT(cvt)
1158 } T;
1159 T t;
1160
1161#undef ROUND_STRUCT_ELEMENT
1162
Ben Murdoch257744e2011-11-30 15:57:28 +00001163 MacroAssembler assm(Isolate::Current(), NULL, 0);
Steve Block44f0eee2011-05-26 01:26:41 +01001164
Ben Murdoch257744e2011-11-30 15:57:28 +00001165 if (CpuFeatures::IsSupported(FPU)) {
Steve Block44f0eee2011-05-26 01:26:41 +01001166 CpuFeatures::Scope scope(FPU);
1167
1168 // Save FCSR.
1169 __ cfc1(a1, FCSR);
1170 // Disable FPU exceptions.
1171 __ ctc1(zero_reg, FCSR);
1172#define RUN_ROUND_TEST(x) \
1173 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_up_in))); \
1174 __ x##_w_d(f0, f0); \
1175 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_up_out))); \
1176 \
1177 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_down_in))); \
1178 __ x##_w_d(f0, f0); \
1179 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_down_out))); \
1180 \
1181 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_up_in))); \
1182 __ x##_w_d(f0, f0); \
1183 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_up_out))); \
1184 \
1185 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_down_in))); \
1186 __ x##_w_d(f0, f0); \
1187 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_down_out))); \
1188 \
1189 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err1_in))); \
1190 __ ctc1(zero_reg, FCSR); \
1191 __ x##_w_d(f0, f0); \
1192 __ cfc1(a2, FCSR); \
1193 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err1_out))); \
1194 \
1195 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err2_in))); \
1196 __ ctc1(zero_reg, FCSR); \
1197 __ x##_w_d(f0, f0); \
1198 __ cfc1(a2, FCSR); \
1199 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err2_out))); \
1200 \
1201 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err3_in))); \
1202 __ ctc1(zero_reg, FCSR); \
1203 __ x##_w_d(f0, f0); \
1204 __ cfc1(a2, FCSR); \
1205 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err3_out))); \
1206 \
1207 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err4_in))); \
1208 __ ctc1(zero_reg, FCSR); \
1209 __ x##_w_d(f0, f0); \
1210 __ cfc1(a2, FCSR); \
1211 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err4_out))); \
1212 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_invalid_result)));
1213
1214 RUN_ROUND_TEST(round)
1215 RUN_ROUND_TEST(floor)
1216 RUN_ROUND_TEST(ceil)
1217 RUN_ROUND_TEST(trunc)
1218 RUN_ROUND_TEST(cvt)
1219
1220 // Restore FCSR.
1221 __ ctc1(a1, FCSR);
1222
Steve Block44f0eee2011-05-26 01:26:41 +01001223 __ jr(ra);
1224 __ nop();
1225
1226 CodeDesc desc;
1227 assm.GetCode(&desc);
1228 Object* code = HEAP->CreateCode(
1229 desc,
1230 Code::ComputeFlags(Code::STUB),
1231 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
1232 CHECK(code->IsCode());
1233 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1234
1235 t.round_up_in = 123.51;
1236 t.round_down_in = 123.49;
1237 t.neg_round_up_in = -123.5;
1238 t.neg_round_down_in = -123.49;
1239 t.err1_in = 123.51;
1240 t.err2_in = 1;
1241 t.err3_in = static_cast<double>(1) + 0xFFFFFFFF;
1242 t.err4_in = NAN;
1243
1244 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1245 USE(dummy);
1246
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001247#define GET_FPU_ERR(x) (static_cast<int>(x & kFCSRFlagMask))
1248#define CHECK_ROUND_RESULT(type) \
1249 CHECK(GET_FPU_ERR(t.type##_err1_out) & kFCSRInexactFlagMask); \
1250 CHECK_EQ(0, GET_FPU_ERR(t.type##_err2_out)); \
1251 CHECK(GET_FPU_ERR(t.type##_err3_out) & kFCSRInvalidOpFlagMask); \
1252 CHECK(GET_FPU_ERR(t.type##_err4_out) & kFCSRInvalidOpFlagMask); \
1253 CHECK_EQ(kFPUInvalidResult, t.type##_invalid_result);
Steve Block44f0eee2011-05-26 01:26:41 +01001254
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001255 CHECK_ROUND_RESULT(round);
1256 CHECK_ROUND_RESULT(floor);
1257 CHECK_ROUND_RESULT(ceil);
1258 CHECK_ROUND_RESULT(cvt);
Steve Block44f0eee2011-05-26 01:26:41 +01001259 }
1260}
1261
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001262
1263TEST(MIPS15) {
1264 // Test chaining of label usages within instructions (issue 1644).
1265 InitializeVM();
1266 v8::HandleScope scope;
1267 Assembler assm(Isolate::Current(), NULL, 0);
1268
1269 Label target;
1270 __ beq(v0, v1, &target);
1271 __ bne(v0, v1, &target);
1272 __ bind(&target);
1273 __ nop();
1274}
1275
Andrei Popescu402d9372010-02-26 13:31:12 +00001276#undef __