Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: test/cctest/test-assembler-mips.cc

Issue 6759025: Version 3.2.6 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « test/cctest/cctest.status ('k') | test/cctest/test-heap-profiler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 FLAG_disable_native_files = true; 52 FLAG_disable_native_files = true;
53 53
54 if (env.IsEmpty()) { 54 if (env.IsEmpty()) {
55 env = v8::Context::New(); 55 env = v8::Context::New();
56 } 56 }
57 } 57 }
58 58
59 59
60 #define __ assm. 60 #define __ assm.
61 61
62
62 TEST(MIPS0) { 63 TEST(MIPS0) {
63 InitializeVM(); 64 InitializeVM();
64 v8::HandleScope scope; 65 v8::HandleScope scope;
65 66
66 MacroAssembler assm(NULL, 0); 67 MacroAssembler assm(NULL, 0);
67 68
68 // Addition. 69 // Addition.
69 __ addu(v0, a0, a1); 70 __ addu(v0, a0, a1);
70 __ jr(ra); 71 __ jr(ra);
71 __ nop(); 72 __ nop();
72 73
73 CodeDesc desc; 74 CodeDesc desc;
74 assm.GetCode(&desc); 75 assm.GetCode(&desc);
75 Object* code = Heap::CreateCode(desc, 76 Object* code = HEAP->CreateCode(
76 NULL, 77 desc,
77 Code::ComputeFlags(Code::STUB), 78 Code::ComputeFlags(Code::STUB),
78 Handle<Object>(Heap::undefined_value())); 79 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
79 CHECK(code->IsCode()); 80 CHECK(code->IsCode());
80 #ifdef DEBUG
81 Code::cast(code)->Print();
82 #endif
83 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry()); 81 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
84 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0)); 82 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
85 ::printf("f() = %d\n", res); 83 ::printf("f() = %d\n", res);
86 CHECK_EQ(0xabc, res); 84 CHECK_EQ(0xabc, res);
87 } 85 }
88 86
89 87
90 TEST(MIPS1) { 88 TEST(MIPS1) {
91 InitializeVM(); 89 InitializeVM();
92 v8::HandleScope scope; 90 v8::HandleScope scope;
93 91
94 MacroAssembler assm(NULL, 0); 92 MacroAssembler assm(NULL, 0);
95 Label L, C; 93 Label L, C;
96 94
97 __ mov(a1, a0); 95 __ mov(a1, a0);
98 __ li(v0, 0); 96 __ li(v0, 0);
99 __ b(&C); 97 __ b(&C);
100 __ nop(); 98 __ nop();
101 99
102 __ bind(&L); 100 __ bind(&L);
103 __ add(v0, v0, a1); 101 __ addu(v0, v0, a1);
104 __ addiu(a1, a1, -1); 102 __ addiu(a1, a1, -1);
105 103
106 __ bind(&C); 104 __ bind(&C);
107 __ xori(v1, a1, 0); 105 __ xori(v1, a1, 0);
108 __ Branch(ne, &L, v1, Operand(0, RelocInfo::NONE)); 106 __ Branch(&L, ne, v1, Operand(0));
109 __ nop(); 107 __ nop();
110 108
111 __ jr(ra); 109 __ jr(ra);
112 __ nop(); 110 __ nop();
113 111
114 CodeDesc desc; 112 CodeDesc desc;
115 assm.GetCode(&desc); 113 assm.GetCode(&desc);
116 Object* code = Heap::CreateCode(desc, 114 Object* code = HEAP->CreateCode(
117 NULL, 115 desc,
118 Code::ComputeFlags(Code::STUB), 116 Code::ComputeFlags(Code::STUB),
119 Handle<Object>(Heap::undefined_value())); 117 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
120 CHECK(code->IsCode()); 118 CHECK(code->IsCode());
121 #ifdef DEBUG
122 Code::cast(code)->Print();
123 #endif
124 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); 119 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
125 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0)); 120 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0));
126 ::printf("f() = %d\n", res); 121 ::printf("f() = %d\n", res);
127 CHECK_EQ(1275, res); 122 CHECK_EQ(1275, res);
128 } 123 }
129 124
130 125
131 TEST(MIPS2) { 126 TEST(MIPS2) {
132 InitializeVM(); 127 InitializeVM();
133 v8::HandleScope scope; 128 v8::HandleScope scope;
(...skipping 25 matching lines...) Expand all
159 __ li(t6, 0xedcba988); 154 __ li(t6, 0xedcba988);
160 __ li(t7, 0x80000000); 155 __ li(t7, 0x80000000);
161 156
162 // SPECIAL class. 157 // SPECIAL class.
163 __ srl(v0, t2, 8); // 0x00123456 158 __ srl(v0, t2, 8); // 0x00123456
164 __ sll(v0, v0, 11); // 0x91a2b000 159 __ sll(v0, v0, 11); // 0x91a2b000
165 __ sra(v0, v0, 3); // 0xf2345600 160 __ sra(v0, v0, 3); // 0xf2345600
166 __ srav(v0, v0, t0); // 0xff234560 161 __ srav(v0, v0, t0); // 0xff234560
167 __ sllv(v0, v0, t0); // 0xf2345600 162 __ sllv(v0, v0, t0); // 0xf2345600
168 __ srlv(v0, v0, t0); // 0x0f234560 163 __ srlv(v0, v0, t0); // 0x0f234560
169 __ Branch(ne, &error, v0, Operand(0x0f234560)); 164 __ Branch(&error, ne, v0, Operand(0x0f234560));
170 __ nop(); 165 __ nop();
171 166
172 __ add(v0, t0, t1); // 0x00001238 167 __ addu(v0, t0, t1); // 0x00001238
173 __ sub(v0, v0, t0); // 0x00001234 168 __ subu(v0, v0, t0); // 0x00001234
174 __ Branch(ne, &error, v0, Operand(0x00001234)); 169 __ Branch(&error, ne, v0, Operand(0x00001234));
175 __ nop(); 170 __ nop();
176 __ addu(v1, t3, t0); 171 __ addu(v1, t3, t0);
177 __ Branch(ne, &error, v1, Operand(0x80000003)); 172 __ Branch(&error, ne, v1, Operand(0x80000003));
178 __ nop(); 173 __ nop();
179 __ subu(v1, t7, t0); // 0x7ffffffc 174 __ subu(v1, t7, t0); // 0x7ffffffc
180 __ Branch(ne, &error, v1, Operand(0x7ffffffc)); 175 __ Branch(&error, ne, v1, Operand(0x7ffffffc));
181 __ nop(); 176 __ nop();
182 177
183 __ and_(v0, t1, t2); // 0x00001230 178 __ and_(v0, t1, t2); // 0x00001230
184 __ or_(v0, v0, t1); // 0x00001234 179 __ or_(v0, v0, t1); // 0x00001234
185 __ xor_(v0, v0, t2); // 0x1234444c 180 __ xor_(v0, v0, t2); // 0x1234444c
186 __ nor(v0, v0, t2); // 0xedcba987 181 __ nor(v0, v0, t2); // 0xedcba987
187 __ Branch(ne, &error, v0, Operand(0xedcba983)); 182 __ Branch(&error, ne, v0, Operand(0xedcba983));
188 __ nop(); 183 __ nop();
189 184
190 __ slt(v0, t7, t3); 185 __ slt(v0, t7, t3);
191 __ Branch(ne, &error, v0, Operand(0x1)); 186 __ Branch(&error, ne, v0, Operand(0x1));
192 __ nop(); 187 __ nop();
193 __ sltu(v0, t7, t3); 188 __ sltu(v0, t7, t3);
194 __ Branch(ne, &error, v0, Operand(0x0)); 189 __ Branch(&error, ne, v0, Operand(0x0));
195 __ nop(); 190 __ nop();
196 // End of SPECIAL class. 191 // End of SPECIAL class.
197 192
198 __ addi(v0, zero_reg, 0x7421); // 0x00007421 193 __ addiu(v0, zero_reg, 0x7421); // 0x00007421
199 __ addi(v0, v0, -0x1); // 0x00007420 194 __ addiu(v0, v0, -0x1); // 0x00007420
200 __ addiu(v0, v0, -0x20); // 0x00007400 195 __ addiu(v0, v0, -0x20); // 0x00007400
201 __ Branch(ne, &error, v0, Operand(0x00007400)); 196 __ Branch(&error, ne, v0, Operand(0x00007400));
202 __ nop(); 197 __ nop();
203 __ addiu(v1, t3, 0x1); // 0x80000000 198 __ addiu(v1, t3, 0x1); // 0x80000000
204 __ Branch(ne, &error, v1, Operand(0x80000000)); 199 __ Branch(&error, ne, v1, Operand(0x80000000));
205 __ nop(); 200 __ nop();
206 201
207 __ slti(v0, t1, 0x00002000); // 0x1 202 __ slti(v0, t1, 0x00002000); // 0x1
208 __ slti(v0, v0, 0xffff8000); // 0x0 203 __ slti(v0, v0, 0xffff8000); // 0x0
209 __ Branch(ne, &error, v0, Operand(0x0)); 204 __ Branch(&error, ne, v0, Operand(0x0));
210 __ nop(); 205 __ nop();
211 __ sltiu(v0, t1, 0x00002000); // 0x1 206 __ sltiu(v0, t1, 0x00002000); // 0x1
212 __ sltiu(v0, v0, 0x00008000); // 0x1 207 __ sltiu(v0, v0, 0x00008000); // 0x1
213 __ Branch(ne, &error, v0, Operand(0x1)); 208 __ Branch(&error, ne, v0, Operand(0x1));
214 __ nop(); 209 __ nop();
215 210
216 __ andi(v0, t1, 0xf0f0); // 0x00001030 211 __ andi(v0, t1, 0xf0f0); // 0x00001030
217 __ ori(v0, v0, 0x8a00); // 0x00009a30 212 __ ori(v0, v0, 0x8a00); // 0x00009a30
218 __ xori(v0, v0, 0x83cc); // 0x000019fc 213 __ xori(v0, v0, 0x83cc); // 0x000019fc
219 __ Branch(ne, &error, v0, Operand(0x000019fc)); 214 __ Branch(&error, ne, v0, Operand(0x000019fc));
220 __ nop(); 215 __ nop();
221 __ lui(v1, 0x8123); // 0x81230000 216 __ lui(v1, 0x8123); // 0x81230000
222 __ Branch(ne, &error, v1, Operand(0x81230000)); 217 __ Branch(&error, ne, v1, Operand(0x81230000));
223 __ nop(); 218 __ nop();
224 219
220 // 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
225 // Everything was correctly executed. Load the expected result. 239 // Everything was correctly executed. Load the expected result.
226 __ li(v0, 0x31415926); 240 __ li(v0, 0x31415926);
227 __ b(&exit); 241 __ b(&exit);
228 __ nop(); 242 __ nop();
229 243
230 __ bind(&error); 244 __ bind(&error);
231 // Got an error. Return a wrong result. 245 // Got an error. Return a wrong result.
246 __ li(v0, 666);
232 247
233 __ bind(&exit); 248 __ bind(&exit);
234 __ jr(ra); 249 __ jr(ra);
235 __ nop(); 250 __ nop();
236 251
237 CodeDesc desc; 252 CodeDesc desc;
238 assm.GetCode(&desc); 253 assm.GetCode(&desc);
239 Object* code = Heap::CreateCode(desc, 254 Object* code = HEAP->CreateCode(
240 NULL, 255 desc,
241 Code::ComputeFlags(Code::STUB), 256 Code::ComputeFlags(Code::STUB),
242 Handle<Object>(Heap::undefined_value())); 257 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
243 CHECK(code->IsCode()); 258 CHECK(code->IsCode());
244 #ifdef DEBUG
245 Code::cast(code)->Print();
246 #endif
247 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry()); 259 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
248 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0)); 260 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
249 ::printf("f() = %d\n", res); 261 ::printf("f() = %d\n", res);
250 CHECK_EQ(0x31415926, res); 262 CHECK_EQ(0x31415926, res);
251 } 263 }
252 264
265
266 TEST(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.
284 MacroAssembler assm(NULL, 0);
285 Label L, C;
286
287 if (Isolate::Current()->cpu_features()->IsSupported(FPU)) {
288 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
345 TEST(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
357 Assembler assm(NULL, 0);
358 Label L, C;
359
360 if (Isolate::Current()->cpu_features()->IsSupported(FPU)) {
361 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
405 TEST(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
418 Assembler assm(NULL, 0);
419 Label L, C;
420
421 if (Isolate::Current()->cpu_features()->IsSupported(FPU)) {
422 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
476 TEST(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
493 Assembler assm(NULL, 0);
494 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
548 TEST(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.
566 MacroAssembler assm(NULL, 0);
567 Label neither_is_nan, less_than, outa_here;
568
569 if (Isolate::Current()->cpu_features()->IsSupported(FPU)) {
570 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
624 TEST(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
648 MacroAssembler assm(NULL, 0);
649
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
728 TEST(MIPS9) {
729 // Test BRANCH improvements.
730 InitializeVM();
731 v8::HandleScope scope;
732
733 MacroAssembler assm(NULL, 0);
734 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
756 TEST(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
774 Assembler assm(NULL, 0);
775 Label L, C;
776
777 if (Isolate::Current()->cpu_features()->IsSupported(FPU)) {
778 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
831 TEST(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
858 Assembler assm(NULL, 0);
859
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
975 TEST(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
989 MacroAssembler assm(NULL, 0);
990
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();
999 __ Push(t0); // These instructions disappear after opt.
1000 __ Pop();
1001 __ addu(t0, t0, t0);
1002 __ nop();
1003 __ Pop(); // These instructions disappear after opt.
1004 __ Push(t3);
1005 __ nop();
1006 __ Push(t3); // These instructions disappear after opt.
1007 __ Pop(t3);
1008 __ nop();
1009 __ Push(t3);
1010 __ Pop(t4);
1011 __ 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();
1018 __ Push(t1);
1019 __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
1020 __ Pop(t1);
1021 __ nop();
1022 __ Push(t1);
1023 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1024 __ Pop(t1);
1025 __ nop();
1026 __ Push(t1);
1027 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1028 __ Pop(t2);
1029 __ nop();
1030 __ Push(t2);
1031 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1032 __ Pop(t1);
1033 __ nop();
1034 __ Push(t1);
1035 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1036 __ Pop(t3);
1037 __ 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
1065 TEST(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
1080 MacroAssembler assm(NULL, 0);
1081
1082 if (Isolate::Current()->cpu_features()->IsSupported(FPU)) {
1083 CpuFeatures::Scope scope(FPU);
1084
1085 __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_small_in)));
1086 __ Cvt_d_uw(f10, t0);
1087 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out)));
1088
1089 __ Trunc_uw_d(f10, f10);
1090 __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out)));
1091
1092 __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_big_in)));
1093 __ Cvt_d_uw(f8, t0);
1094 __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out)));
1095
1096 __ Trunc_uw_d(f8, f8);
1097 __ 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
1127 TEST(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; \
1137 int32_t x##_err1_out; \
1138 int32_t x##_err2_out; \
1139 int32_t x##_err3_out; \
1140 int32_t x##_err4_out; \
1141 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
1163 MacroAssembler assm(NULL, 0);
1164
1165 if (Isolate::Current()->cpu_features()->IsSupported(FPU)) {
1166 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
1223 #undef RUN_ROUND_TEST
1224
1225 __ jr(ra);
1226 __ nop();
1227
1228 CodeDesc desc;
1229 assm.GetCode(&desc);
1230 Object* code = HEAP->CreateCode(
1231 desc,
1232 Code::ComputeFlags(Code::STUB),
1233 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
1234 CHECK(code->IsCode());
1235 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1236
1237 t.round_up_in = 123.51;
1238 t.round_down_in = 123.49;
1239 t.neg_round_up_in = -123.5;
1240 t.neg_round_down_in = -123.49;
1241 t.err1_in = 123.51;
1242 t.err2_in = 1;
1243 t.err3_in = static_cast<double>(1) + 0xFFFFFFFF;
1244 t.err4_in = NAN;
1245
1246 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1247 USE(dummy);
1248
1249 #define GET_FPU_ERR(x) ((x >> 2) & (32 - 1))
1250
1251 CHECK_EQ(124, t.round_up_out);
1252 CHECK_EQ(123, t.round_down_out);
1253 CHECK_EQ(-124, t.neg_round_up_out);
1254 CHECK_EQ(-123, t.neg_round_down_out);
1255
1256 // Inaccurate.
1257 CHECK_EQ(1, GET_FPU_ERR(t.round_err1_out));
1258 // No error.
1259 CHECK_EQ(0, GET_FPU_ERR(t.round_err2_out));
1260 // Invalid operation.
1261 CHECK_EQ(16, GET_FPU_ERR(t.round_err3_out));
1262 CHECK_EQ(16, GET_FPU_ERR(t.round_err4_out));
1263 CHECK_EQ(kFPUInvalidResult, t.round_invalid_result);
1264
1265 CHECK_EQ(123, t.floor_up_out);
1266 CHECK_EQ(123, t.floor_down_out);
1267 CHECK_EQ(-124, t.neg_floor_up_out);
1268 CHECK_EQ(-124, t.neg_floor_down_out);
1269
1270 // Inaccurate.
1271 CHECK_EQ(1, GET_FPU_ERR(t.floor_err1_out));
1272 // No error.
1273 CHECK_EQ(0, GET_FPU_ERR(t.floor_err2_out));
1274 // Invalid operation.
1275 CHECK_EQ(16, GET_FPU_ERR(t.floor_err3_out));
1276 CHECK_EQ(16, GET_FPU_ERR(t.floor_err4_out));
1277 CHECK_EQ(kFPUInvalidResult, t.floor_invalid_result);
1278
1279 CHECK_EQ(124, t.ceil_up_out);
1280 CHECK_EQ(124, t.ceil_down_out);
1281 CHECK_EQ(-123, t.neg_ceil_up_out);
1282 CHECK_EQ(-123, t.neg_ceil_down_out);
1283
1284 // Inaccurate.
1285 CHECK_EQ(1, GET_FPU_ERR(t.ceil_err1_out));
1286 // No error.
1287 CHECK_EQ(0, GET_FPU_ERR(t.ceil_err2_out));
1288 // Invalid operation.
1289 CHECK_EQ(16, GET_FPU_ERR(t.ceil_err3_out));
1290 CHECK_EQ(16, GET_FPU_ERR(t.ceil_err4_out));
1291 CHECK_EQ(kFPUInvalidResult, t.ceil_invalid_result);
1292
1293 // In rounding mode 0 cvt should behave like round.
1294 CHECK_EQ(t.round_up_out, t.cvt_up_out);
1295 CHECK_EQ(t.round_down_out, t.cvt_down_out);
1296 CHECK_EQ(t.neg_round_up_out, t.neg_cvt_up_out);
1297 CHECK_EQ(t.neg_round_down_out, t.neg_cvt_down_out);
1298
1299 // Inaccurate.
1300 CHECK_EQ(1, GET_FPU_ERR(t.cvt_err1_out));
1301 // No error.
1302 CHECK_EQ(0, GET_FPU_ERR(t.cvt_err2_out));
1303 // Invalid operation.
1304 CHECK_EQ(16, GET_FPU_ERR(t.cvt_err3_out));
1305 CHECK_EQ(16, GET_FPU_ERR(t.cvt_err4_out));
1306 CHECK_EQ(kFPUInvalidResult, t.cvt_invalid_result);
1307 }
1308 }
1309
1310
253 #undef __ 1311 #undef __
OLDNEW
« no previous file with comments | « test/cctest/cctest.status ('k') | test/cctest/test-heap-profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698