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

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

Issue 6709022: Re-establish mips basic infrastructure. (Closed) Base URL: git://github.com/v8/v8.git@master
Patch Set: Updated per comments, and rebased on r7312. Created 9 years, 9 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
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 #ifdef DEBUG
81 Code::cast(code)->Print(); 82 Code::cast(code)->Print();
82 #endif 83 #endif
83 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry()); 84 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
84 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0)); 85 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
85 ::printf("f() = %d\n", res); 86 ::printf("f() = %d\n", res);
86 CHECK_EQ(0xabc, res); 87 CHECK_EQ(0xabc, res);
87 } 88 }
88 89
89 90
90 TEST(MIPS1) { 91 TEST(MIPS1) {
91 InitializeVM(); 92 InitializeVM();
92 v8::HandleScope scope; 93 v8::HandleScope scope;
93 94
94 MacroAssembler assm(NULL, 0); 95 MacroAssembler assm(NULL, 0);
95 Label L, C; 96 Label L, C;
96 97
97 __ mov(a1, a0); 98 __ mov(a1, a0);
98 __ li(v0, 0); 99 __ li(v0, 0);
99 __ b(&C); 100 __ b(&C);
100 __ nop(); 101 __ nop();
101 102
102 __ bind(&L); 103 __ bind(&L);
103 __ add(v0, v0, a1); 104 __ addu(v0, v0, a1);
104 __ addiu(a1, a1, -1); 105 __ addiu(a1, a1, -1);
105 106
106 __ bind(&C); 107 __ bind(&C);
107 __ xori(v1, a1, 0); 108 __ xori(v1, a1, 0);
108 __ Branch(ne, &L, v1, Operand(0, RelocInfo::NONE)); 109 __ Branch(&L, ne, v1, Operand(0));
109 __ nop(); 110 __ nop();
110 111
111 __ jr(ra); 112 __ jr(ra);
112 __ nop(); 113 __ nop();
113 114
114 CodeDesc desc; 115 CodeDesc desc;
115 assm.GetCode(&desc); 116 assm.GetCode(&desc);
116 Object* code = Heap::CreateCode(desc, 117 Object* code = HEAP->CreateCode(
117 NULL, 118 desc,
118 Code::ComputeFlags(Code::STUB), 119 Code::ComputeFlags(Code::STUB),
119 Handle<Object>(Heap::undefined_value())); 120 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
120 CHECK(code->IsCode()); 121 CHECK(code->IsCode());
121 #ifdef DEBUG 122 #ifdef DEBUG
122 Code::cast(code)->Print(); 123 Code::cast(code)->Print();
123 #endif 124 #endif
124 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); 125 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
125 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0)); 126 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0));
126 ::printf("f() = %d\n", res); 127 ::printf("f() = %d\n", res);
127 CHECK_EQ(1275, res); 128 CHECK_EQ(1275, res);
128 } 129 }
129 130
(...skipping 29 matching lines...) Expand all
159 __ li(t6, 0xedcba988); 160 __ li(t6, 0xedcba988);
160 __ li(t7, 0x80000000); 161 __ li(t7, 0x80000000);
161 162
162 // SPECIAL class. 163 // SPECIAL class.
163 __ srl(v0, t2, 8); // 0x00123456 164 __ srl(v0, t2, 8); // 0x00123456
164 __ sll(v0, v0, 11); // 0x91a2b000 165 __ sll(v0, v0, 11); // 0x91a2b000
165 __ sra(v0, v0, 3); // 0xf2345600 166 __ sra(v0, v0, 3); // 0xf2345600
166 __ srav(v0, v0, t0); // 0xff234560 167 __ srav(v0, v0, t0); // 0xff234560
167 __ sllv(v0, v0, t0); // 0xf2345600 168 __ sllv(v0, v0, t0); // 0xf2345600
168 __ srlv(v0, v0, t0); // 0x0f234560 169 __ srlv(v0, v0, t0); // 0x0f234560
169 __ Branch(ne, &error, v0, Operand(0x0f234560)); 170 __ Branch(&error, ne, v0, Operand(0x0f234560));
170 __ nop(); 171 __ nop();
171 172
172 __ add(v0, t0, t1); // 0x00001238 173 __ addu(v0, t0, t1); // 0x00001238
173 __ sub(v0, v0, t0); // 0x00001234 174 __ subu(v0, v0, t0); // 0x00001234
174 __ Branch(ne, &error, v0, Operand(0x00001234)); 175 __ Branch(&error, ne, v0, Operand(0x00001234));
175 __ nop(); 176 __ nop();
176 __ addu(v1, t3, t0); 177 __ addu(v1, t3, t0);
177 __ Branch(ne, &error, v1, Operand(0x80000003)); 178 __ Branch(&error, ne, v1, Operand(0x80000003));
178 __ nop(); 179 __ nop();
179 __ subu(v1, t7, t0); // 0x7ffffffc 180 __ subu(v1, t7, t0); // 0x7ffffffc
180 __ Branch(ne, &error, v1, Operand(0x7ffffffc)); 181 __ Branch(&error, ne, v1, Operand(0x7ffffffc));
181 __ nop(); 182 __ nop();
182 183
183 __ and_(v0, t1, t2); // 0x00001230 184 __ and_(v0, t1, t2); // 0x00001230
184 __ or_(v0, v0, t1); // 0x00001234 185 __ or_(v0, v0, t1); // 0x00001234
185 __ xor_(v0, v0, t2); // 0x1234444c 186 __ xor_(v0, v0, t2); // 0x1234444c
186 __ nor(v0, v0, t2); // 0xedcba987 187 __ nor(v0, v0, t2); // 0xedcba987
187 __ Branch(ne, &error, v0, Operand(0xedcba983)); 188 __ Branch(&error, ne, v0, Operand(0xedcba983));
188 __ nop(); 189 __ nop();
189 190
190 __ slt(v0, t7, t3); 191 __ slt(v0, t7, t3);
191 __ Branch(ne, &error, v0, Operand(0x1)); 192 __ Branch(&error, ne, v0, Operand(0x1));
192 __ nop(); 193 __ nop();
193 __ sltu(v0, t7, t3); 194 __ sltu(v0, t7, t3);
194 __ Branch(ne, &error, v0, Operand(0x0)); 195 __ Branch(&error, ne, v0, Operand(0x0));
195 __ nop(); 196 __ nop();
196 // End of SPECIAL class. 197 // End of SPECIAL class.
197 198
198 __ addi(v0, zero_reg, 0x7421); // 0x00007421 199 __ addiu(v0, zero_reg, 0x7421); // 0x00007421
199 __ addi(v0, v0, -0x1); // 0x00007420 200 __ addiu(v0, v0, -0x1); // 0x00007420
200 __ addiu(v0, v0, -0x20); // 0x00007400 201 __ addiu(v0, v0, -0x20); // 0x00007400
201 __ Branch(ne, &error, v0, Operand(0x00007400)); 202 __ Branch(&error, ne, v0, Operand(0x00007400));
202 __ nop(); 203 __ nop();
203 __ addiu(v1, t3, 0x1); // 0x80000000 204 __ addiu(v1, t3, 0x1); // 0x80000000
204 __ Branch(ne, &error, v1, Operand(0x80000000)); 205 __ Branch(&error, ne, v1, Operand(0x80000000));
205 __ nop(); 206 __ nop();
206 207
207 __ slti(v0, t1, 0x00002000); // 0x1 208 __ slti(v0, t1, 0x00002000); // 0x1
208 __ slti(v0, v0, 0xffff8000); // 0x0 209 __ slti(v0, v0, 0xffff8000); // 0x0
209 __ Branch(ne, &error, v0, Operand(0x0)); 210 __ Branch(&error, ne, v0, Operand(0x0));
210 __ nop(); 211 __ nop();
211 __ sltiu(v0, t1, 0x00002000); // 0x1 212 __ sltiu(v0, t1, 0x00002000); // 0x1
212 __ sltiu(v0, v0, 0x00008000); // 0x1 213 __ sltiu(v0, v0, 0x00008000); // 0x1
213 __ Branch(ne, &error, v0, Operand(0x1)); 214 __ Branch(&error, ne, v0, Operand(0x1));
214 __ nop(); 215 __ nop();
215 216
216 __ andi(v0, t1, 0xf0f0); // 0x00001030 217 __ andi(v0, t1, 0xf0f0); // 0x00001030
217 __ ori(v0, v0, 0x8a00); // 0x00009a30 218 __ ori(v0, v0, 0x8a00); // 0x00009a30
218 __ xori(v0, v0, 0x83cc); // 0x000019fc 219 __ xori(v0, v0, 0x83cc); // 0x000019fc
219 __ Branch(ne, &error, v0, Operand(0x000019fc)); 220 __ Branch(&error, ne, v0, Operand(0x000019fc));
220 __ nop(); 221 __ nop();
221 __ lui(v1, 0x8123); // 0x81230000 222 __ lui(v1, 0x8123); // 0x81230000
222 __ Branch(ne, &error, v1, Operand(0x81230000)); 223 __ Branch(&error, ne, v1, Operand(0x81230000));
223 __ nop(); 224 __ nop();
224 225
226 // Bit twiddling instructions & conditional moves.
227 // Uses t0-t7 as set above.
228 __ clz(v0, t0); // 29
229 __ clz(v1, t1); // 19
230 __ addu(v0, v0, v1); // 48
231 __ clz(v1, t2); // 3
232 __ addu(v0, v0, v1); // 51
233 __ clz(v1, t7); // 0
234 __ addu(v0, v0, v1); // 51
235 __ Branch(&error, ne, v0, Operand(51));
236 __ movn(a0, t3, t0); // Move a0<-t3 (t0 is NOT 0).
237 __ Ins(a0, t1, 12, 8); // 0x7ff34fff
238 __ Branch(&error, ne, a0, Operand(0x7ff34fff));
239 __ movz(a0, t6, t7); // a0 not updated (t7 is NOT 0).
240 __ Ext(a1, a0, 8, 12); // 0x34f
241 __ Branch(&error, ne, a1, Operand(0x34f));
242 __ movz(a0, t6, v1); // a0<-t6, v0 is 0, from 8 instr back.
243 __ Branch(&error, ne, a0, Operand(t6));
244
225 // Everything was correctly executed. Load the expected result. 245 // Everything was correctly executed. Load the expected result.
226 __ li(v0, 0x31415926); 246 __ li(v0, 0x31415926);
227 __ b(&exit); 247 __ b(&exit);
228 __ nop(); 248 __ nop();
229 249
230 __ bind(&error); 250 __ bind(&error);
231 // Got an error. Return a wrong result. 251 // Got an error. Return a wrong result.
252 __ li(v0, 666);
232 253
233 __ bind(&exit); 254 __ bind(&exit);
234 __ jr(ra); 255 __ jr(ra);
235 __ nop(); 256 __ nop();
236 257
237 CodeDesc desc; 258 CodeDesc desc;
238 assm.GetCode(&desc); 259 assm.GetCode(&desc);
239 Object* code = Heap::CreateCode(desc, 260 Object* code = HEAP->CreateCode(
240 NULL, 261 desc,
241 Code::ComputeFlags(Code::STUB), 262 Code::ComputeFlags(Code::STUB),
242 Handle<Object>(Heap::undefined_value())); 263 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
243 CHECK(code->IsCode()); 264 CHECK(code->IsCode());
244 #ifdef DEBUG 265 #ifdef DEBUG
245 Code::cast(code)->Print(); 266 Code::cast(code)->Print();
246 #endif 267 #endif
247 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry()); 268 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
248 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0)); 269 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
249 ::printf("f() = %d\n", res); 270 ::printf("f() = %d\n", res);
250 CHECK_EQ(0x31415926, res); 271 CHECK_EQ(0x31415926, res);
251 } 272 }
252 273
274
275 TEST(MIPS3) {
276 // Test floating point instructions.
277 InitializeVM();
278 v8::HandleScope scope;
279
280 typedef struct {
281 double a;
282 double b;
283 double c;
284 double d;
285 double e;
286 double f;
287 double g;
288 } T;
289 T t;
290
291 // Create a function that accepts &t, and loads, manipulates, and stores
292 // the doubles t.a ... t.f.
293 MacroAssembler assm(NULL, 0);
294 Label L, C;
295
296 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
297 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
298 __ add_d(f8, f4, f6);
299 __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, c)) ); // c = a + b.
300
301 __ mov_d(f10, f8); // c
302 __ neg_d(f12, f6); // -b
303 __ sub_d(f10, f10, f12);
304 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, d)) ); // d = c - (-b).
305
306 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) ); // b = a.
307
308 __ li(t0, 120);
309 __ mtc1(t0, f14);
310 __ cvt_d_w(f14, f14); // f14 = 120.0.
311 __ mul_d(f10, f10, f14);
312 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, e)) ); // e = d * 120 = 1.8066e16.
313
314 __ div_d(f12, f10, f4);
315 __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) ); // f = e / a = 120.44.
316
317 __ sqrt_d(f14, f12);
318 __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, g)) );
319 // g = sqrt(f) = 10.97451593465515908537
320
321 __ jr(ra);
322 __ nop();
323
324 CodeDesc desc;
325 assm.GetCode(&desc);
326 Object* code = HEAP->CreateCode(
327 desc,
328 Code::ComputeFlags(Code::STUB),
329 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
330 CHECK(code->IsCode());
331 #ifdef DEBUG
Søren Thygesen Gjesse 2011/03/23 23:38:42 Do you want to have this printing?
Paul Lind 2011/03/26 18:39:17 Not useful now that things are working. Removed fr
332 Code::cast(code)->Print();
333 #endif
334 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
335 t.a = 1.5e14;
336 t.b = 2.75e11;
337 t.c = 0.0;
338 t.d = 0.0;
339 t.e = 0.0;
340 t.f = 0.0;
341 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
342 USE(dummy);
343 CHECK_EQ(1.5e14, t.a);
344 CHECK_EQ(1.5e14, t.b);
345 CHECK_EQ(1.50275e14, t.c);
346 CHECK_EQ(1.50550e14, t.d);
347 CHECK_EQ(1.8066e16, t.e);
348 CHECK_EQ(120.44, t.f);
349 CHECK_EQ(10.97451593465515908537, t.g);
350 }
351
352
353 TEST(MIPS4) {
354 // Test moves between floating point and integer registers.
355 InitializeVM();
356 v8::HandleScope scope;
357
358 typedef struct {
359 double a;
360 double b;
361 double c;
362 } T;
363 T t;
364
365 Assembler assm(NULL, 0);
366 Label L, C;
367
368 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
369 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
370
371 // Swap f4 and f6, by using four integer registers, t0-t3.
372 __ mfc1(t0, f4);
373 __ mfc1(t1, f5);
374 __ mfc1(t2, f6);
375 __ mfc1(t3, f7);
376
377 __ mtc1(t0, f6);
378 __ mtc1(t1, f7);
379 __ mtc1(t2, f4);
380 __ mtc1(t3, f5);
381
382 // Store the swapped f4 and f5 back to memory.
383 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
384 __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, c)) );
385
386 __ jr(ra);
387 __ nop();
388
389 CodeDesc desc;
390 assm.GetCode(&desc);
391 Object* code = HEAP->CreateCode(
392 desc,
393 Code::ComputeFlags(Code::STUB),
394 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
395 CHECK(code->IsCode());
396 #ifdef DEBUG
397 Code::cast(code)->Print();
398 #endif
399 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
400 t.a = 1.5e22;
401 t.b = 2.75e11;
402 t.c = 17.17;
403 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
404 USE(dummy);
405
406 CHECK_EQ(2.75e11, t.a);
407 CHECK_EQ(2.75e11, t.b);
408 CHECK_EQ(1.5e22, t.c);
409 }
410
411
412 TEST(MIPS5) {
413 // Test conversions between doubles and integers.
414 InitializeVM();
415 v8::HandleScope scope;
416
417 typedef struct {
418 double a;
419 double b;
420 int i;
421 int j;
422 } T;
423 T t;
424
425 Assembler assm(NULL, 0);
426 Label L, C;
427
428 // Load all structure elements to registers.
429 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
430 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
431 __ lw(t0, MemOperand(a0, OFFSET_OF(T, i)) );
432 __ lw(t1, MemOperand(a0, OFFSET_OF(T, j)) );
433
434 // Convert double in f4 to int in element i.
435 __ cvt_w_d(f8, f4);
436 __ mfc1(t2, f8);
437 __ sw(t2, MemOperand(a0, OFFSET_OF(T, i)) );
438
439 // Convert double in f6 to int in element j.
440 __ cvt_w_d(f10, f6);
441 __ mfc1(t3, f10);
442 __ sw(t3, MemOperand(a0, OFFSET_OF(T, j)) );
443
444 // Convert int in original i (t0) to double in a.
445 __ mtc1(t0, f12);
446 __ cvt_d_w(f0, f12);
447 __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) );
448
449 // Convert int in original j (t1) to double in b.
450 __ mtc1(t1, f14);
451 __ cvt_d_w(f2, f14);
452 __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) );
453
454 __ jr(ra);
455 __ nop();
456
457 CodeDesc desc;
458 assm.GetCode(&desc);
459 Object* code = HEAP->CreateCode(
460 desc,
461 Code::ComputeFlags(Code::STUB),
462 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
463 CHECK(code->IsCode());
464 #ifdef DEBUG
465 Code::cast(code)->Print();
466 #endif
467 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
468 t.a = 1.5e4;
469 t.b = 2.75e8;
470 t.i = 12345678;
471 t.j = -100000;
472 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
473 USE(dummy);
474
475 CHECK_EQ(12345678.0, t.a);
476 CHECK_EQ(-100000.0, t.b);
477 CHECK_EQ(15000, t.i);
478 CHECK_EQ(275000000, t.j);
479 }
480
481
482 TEST(MIPS6) {
483 // Test simple memory loads and stores.
484 InitializeVM();
485 v8::HandleScope scope;
486
487 typedef struct {
488 uint32_t ui;
489 int32_t si;
490 int32_t r1;
491 int32_t r2;
492 int32_t r3;
493 int32_t r4;
494 int32_t r5;
495 int32_t r6;
496 } T;
497 T t;
498
499 Assembler assm(NULL, 0);
500 Label L, C;
501
502 // Basic word load/store.
503 __ lw(t0, MemOperand(a0, OFFSET_OF(T, ui)) );
504 __ sw(t0, MemOperand(a0, OFFSET_OF(T, r1)) );
505
506 // lh with positive data.
507 __ lh(t1, MemOperand(a0, OFFSET_OF(T, ui)) );
508 __ sw(t1, MemOperand(a0, OFFSET_OF(T, r2)) );
509
510 // lh with negative data.
511 __ lh(t2, MemOperand(a0, OFFSET_OF(T, si)) );
512 __ sw(t2, MemOperand(a0, OFFSET_OF(T, r3)) );
513
514 // lhu with negative data.
515 __ lhu(t3, MemOperand(a0, OFFSET_OF(T, si)) );
516 __ sw(t3, MemOperand(a0, OFFSET_OF(T, r4)) );
517
518 // lb with negative data.
519 __ lb(t4, MemOperand(a0, OFFSET_OF(T, si)) );
520 __ sw(t4, MemOperand(a0, OFFSET_OF(T, r5)) );
521
522 // sh writes only 1/2 of word.
523 __ lui(t5, 0x3333);
524 __ ori(t5, t5, 0x3333);
525 __ sw(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
526 __ lhu(t5, MemOperand(a0, OFFSET_OF(T, si)) );
527 __ sh(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
528
529 __ jr(ra);
530 __ nop();
531
532 CodeDesc desc;
533 assm.GetCode(&desc);
534 Object* code = HEAP->CreateCode(
535 desc,
536 Code::ComputeFlags(Code::STUB),
537 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
538 CHECK(code->IsCode());
539 #ifdef DEBUG
540 Code::cast(code)->Print();
541 #endif
542 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
543 t.ui = 0x11223344;
544 t.si = 0x99aabbcc;
545 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
546 USE(dummy);
547
548 CHECK_EQ(0x11223344, t.r1);
549 CHECK_EQ(0x3344, t.r2);
550 CHECK_EQ(0xffffbbcc, t.r3);
551 CHECK_EQ(0x0000bbcc, t.r4);
552 CHECK_EQ(0xffffffcc, t.r5);
553 CHECK_EQ(0x3333bbcc, t.r6);
554 }
555
556
557 TEST(MIPS7) {
558 // Test floating point compare and branch instructions.
559 InitializeVM();
560 v8::HandleScope scope;
561
562 typedef struct {
563 double a;
564 double b;
565 double c;
566 double d;
567 double e;
568 double f;
569 int32_t result;
570 } T;
571 T t;
572
573 // Create a function that accepts &t, and loads, manipulates, and stores
574 // the doubles t.a ... t.f.
575 MacroAssembler assm(NULL, 0);
576 Label neither_is_nan, less_than, outa_here;
577
578 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
579 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
580 __ c(UN, D, f4, f6);
581 __ bc1f(&neither_is_nan);
582 __ nop();
583 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
584 __ Branch(&outa_here, al);
585
586 __ bind(&neither_is_nan);
587
588 __ c(OLT, D, f6, f4, 2);
589 __ bc1t(&less_than, 2);
590 __ nop();
591 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
592 __ Branch(&outa_here, al);
593
594 __ bind(&less_than);
595 __ Addu(t0, zero_reg, Operand(1));
596 __ sw(t0, MemOperand(a0, OFFSET_OF(T, result)) ); // Set true.
597
598
599 // This test-case should have additional tests.
600
601 __ bind(&outa_here);
602
603 __ jr(ra);
604 __ nop();
605
606 CodeDesc desc;
607 assm.GetCode(&desc);
608 Object* code = HEAP->CreateCode(
609 desc,
610 Code::ComputeFlags(Code::STUB),
611 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
612 CHECK(code->IsCode());
613 #ifdef DEBUG
614 Code::cast(code)->Print();
615 #endif
616 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
617 t.a = 1.5e14;
618 t.b = 2.75e11;
619 t.c = 2.0;
620 t.d = -4.0;
621 t.e = 0.0;
622 t.f = 0.0;
623 t.result = 0;
624 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
625 USE(dummy);
626 CHECK_EQ(1.5e14, t.a);
627 CHECK_EQ(2.75e11, t.b);
628 CHECK_EQ(1, t.result);
629 }
630
631
632 TEST(MIPS8) {
633 // Test ROTR and ROTRV instructions.
634 InitializeVM();
635 v8::HandleScope scope;
636
637 typedef struct {
638 int32_t input;
639 int32_t result_rotr_4;
640 int32_t result_rotr_8;
641 int32_t result_rotr_12;
642 int32_t result_rotr_16;
643 int32_t result_rotr_20;
644 int32_t result_rotr_24;
645 int32_t result_rotr_28;
646 int32_t result_rotrv_4;
647 int32_t result_rotrv_8;
648 int32_t result_rotrv_12;
649 int32_t result_rotrv_16;
650 int32_t result_rotrv_20;
651 int32_t result_rotrv_24;
652 int32_t result_rotrv_28;
653 } T;
654 T t;
655
656 MacroAssembler assm(NULL, 0);
657
658 // Basic word load.
659 __ lw(t0, MemOperand(a0, OFFSET_OF(T, input)) );
660
661 // ROTR instruction (called through the Ror macro).
662 __ Ror(t1, t0, 0x0004);
663 __ Ror(t2, t0, 0x0008);
664 __ Ror(t3, t0, 0x000c);
665 __ Ror(t4, t0, 0x0010);
666 __ Ror(t5, t0, 0x0014);
667 __ Ror(t6, t0, 0x0018);
668 __ Ror(t7, t0, 0x001c);
669
670 // Basic word store.
671 __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotr_4)) );
672 __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotr_8)) );
673 __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotr_12)) );
674 __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotr_16)) );
675 __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotr_20)) );
676 __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotr_24)) );
677 __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotr_28)) );
678
679 // ROTRV instruction (called through the Ror macro).
680 __ li(t7, 0x0004);
681 __ Ror(t1, t0, t7);
682 __ li(t7, 0x0008);
683 __ Ror(t2, t0, t7);
684 __ li(t7, 0x000C);
685 __ Ror(t3, t0, t7);
686 __ li(t7, 0x0010);
687 __ Ror(t4, t0, t7);
688 __ li(t7, 0x0014);
689 __ Ror(t5, t0, t7);
690 __ li(t7, 0x0018);
691 __ Ror(t6, t0, t7);
692 __ li(t7, 0x001C);
693 __ Ror(t7, t0, t7);
694
695 // Basic word store.
696 __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotrv_4)) );
697 __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotrv_8)) );
698 __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotrv_12)) );
699 __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotrv_16)) );
700 __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotrv_20)) );
701 __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotrv_24)) );
702 __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotrv_28)) );
703
704 __ jr(ra);
705 __ nop();
706
707 CodeDesc desc;
708 assm.GetCode(&desc);
709 Object* code = HEAP->CreateCode(
710 desc,
711 Code::ComputeFlags(Code::STUB),
712 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
713 CHECK(code->IsCode());
714 #ifdef DEBUG
715 Code::cast(code)->Print();
716 #endif
717 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
718 t.input = 0x12345678;
719 Object* dummy = CALL_GENERATED_CODE(f, &t, 0x0, 0, 0, 0);
720 USE(dummy);
721 CHECK_EQ(0x81234567, t.result_rotr_4);
722 CHECK_EQ(0x78123456, t.result_rotr_8);
723 CHECK_EQ(0x67812345, t.result_rotr_12);
724 CHECK_EQ(0x56781234, t.result_rotr_16);
725 CHECK_EQ(0x45678123, t.result_rotr_20);
726 CHECK_EQ(0x34567812, t.result_rotr_24);
727 CHECK_EQ(0x23456781, t.result_rotr_28);
728
729 CHECK_EQ(0x81234567, t.result_rotrv_4);
730 CHECK_EQ(0x78123456, t.result_rotrv_8);
731 CHECK_EQ(0x67812345, t.result_rotrv_12);
732 CHECK_EQ(0x56781234, t.result_rotrv_16);
733 CHECK_EQ(0x45678123, t.result_rotrv_20);
734 CHECK_EQ(0x34567812, t.result_rotrv_24);
735 CHECK_EQ(0x23456781, t.result_rotrv_28);
736 }
737
738
739 TEST(MIPS9) {
740 // Test BRANCH improvements.
741 InitializeVM();
742 v8::HandleScope scope;
743
744 MacroAssembler assm(NULL, 0);
745 Label exit, exit2, exit3;
746
747 __ Branch(&exit, ge, a0, Operand(0x00000000));
748 __ Branch(&exit2, ge, a0, Operand(0x00001FFF));
749 __ Branch(&exit3, ge, a0, Operand(0x0001FFFF));
750
751 __ bind(&exit);
752 __ bind(&exit2);
753 __ bind(&exit3);
754 __ jr(ra);
755 __ nop();
756
757 CodeDesc desc;
758 assm.GetCode(&desc);
759 Object* code = HEAP->CreateCode(
760 desc,
761 Code::ComputeFlags(Code::STUB),
762 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
763 CHECK(code->IsCode());
764 #ifdef DEBUG
765 Code::cast(code)->Print();
766 #endif
767 }
768
769
770 TEST(MIPS10) {
771 // Test conversions between doubles and long integers.
772 // Test hos the long ints map to FP regs pairs.
773 InitializeVM();
774 v8::HandleScope scope;
775
776 typedef struct {
777 double a;
778 double b;
779 int32_t dbl_mant;
780 int32_t dbl_exp;
781 int32_t long_hi;
782 int32_t long_lo;
783 int32_t b_long_hi;
784 int32_t b_long_lo;
785 } T;
786 T t;
787
788 Assembler assm(NULL, 0);
789 Label L, C;
790
791 // Load all structure elements to registers.
792 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a)));
793
794 // Save the raw bits of the double.
795 __ mfc1(t0, f0);
796 __ mfc1(t1, f1);
797 __ sw(t0, MemOperand(a0, OFFSET_OF(T, dbl_mant)));
798 __ sw(t1, MemOperand(a0, OFFSET_OF(T, dbl_exp)));
799
800 // Convert double in f0 to long, save hi/lo parts.
801 __ cvt_l_d(f0, f0);
802 __ mfc1(t0, f0); // f0 has LS 32 bits of long.
803 __ mfc1(t1, f1); // f1 has MS 32 bits of long.
804 __ sw(t0, MemOperand(a0, OFFSET_OF(T, long_lo)));
805 __ sw(t1, MemOperand(a0, OFFSET_OF(T, long_hi)));
806
807 // Convert the b long integers to double b.
808 __ lw(t0, MemOperand(a0, OFFSET_OF(T, b_long_lo)));
809 __ lw(t1, MemOperand(a0, OFFSET_OF(T, b_long_hi)));
810 __ mtc1(t0, f8); // f8 has LS 32-bits.
811 __ mtc1(t1, f9); // f9 has MS 32-bits.
812 __ cvt_d_l(f10, f8);
813 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, b)));
814
815 __ jr(ra);
816 __ nop();
817
818 CodeDesc desc;
819 assm.GetCode(&desc);
820 Object* code = HEAP->CreateCode(
821 desc,
822 Code::ComputeFlags(Code::STUB),
823 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
824 CHECK(code->IsCode());
825 #ifdef DEBUG
826 Code::cast(code)->Print();
827 #endif
828 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
829 t.a = 2.147483647e9; // 0x7fffffff -> 0x41DFFFFFFFC00000 as double.
830 t.b_long_hi = 0x000000ff; // 0xFF00FF00FF -> 0x426FE01FE01FE000 as double.
831 t.b_long_lo = 0x00ff00ff;
832 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
833 USE(dummy);
834
835 CHECK_EQ(0x41DFFFFF, t.dbl_exp);
836 CHECK_EQ(0xFFC00000, t.dbl_mant);
837 CHECK_EQ(0, t.long_hi);
838 CHECK_EQ(0x7fffffff, t.long_lo);
839 // 0xFF00FF00FF -> 1.095233372415e12.
840 CHECK_EQ(1.095233372415e12, t.b);
841 }
842
843
844 TEST(MIPS11) {
845 // Test LWL, LWR, SWL and SWR instructions.
846 InitializeVM();
847 v8::HandleScope scope;
848
849 typedef struct {
850 int32_t reg_init;
851 int32_t mem_init;
852 int32_t lwl_0;
853 int32_t lwl_1;
854 int32_t lwl_2;
855 int32_t lwl_3;
856 int32_t lwr_0;
857 int32_t lwr_1;
858 int32_t lwr_2;
859 int32_t lwr_3;
860 int32_t swl_0;
861 int32_t swl_1;
862 int32_t swl_2;
863 int32_t swl_3;
864 int32_t swr_0;
865 int32_t swr_1;
866 int32_t swr_2;
867 int32_t swr_3;
868 } T;
869 T t;
870
871 Assembler assm(NULL, 0);
872
873 // Test all combinations of LWL and vAddr.
874 __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
875 __ lwl(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
876 __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwl_0)) );
877
878 __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
879 __ lwl(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) );
880 __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwl_1)) );
881
882 __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
883 __ lwl(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) );
884 __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwl_2)) );
885
886 __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
887 __ lwl(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) );
888 __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwl_3)) );
889
890 // Test all combinations of LWR and vAddr.
891 __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
892 __ lwr(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
893 __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwr_0)) );
894
895 __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
896 __ lwr(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) );
897 __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwr_1)) );
898
899 __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
900 __ lwr(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) );
901 __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwr_2)) );
902
903 __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
904 __ lwr(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) );
905 __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwr_3)) );
906
907 // Test all combinations of SWL and vAddr.
908 __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
909 __ sw(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) );
910 __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
911 __ swl(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) );
912
913 __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) );
914 __ sw(t1, MemOperand(a0, OFFSET_OF(T, swl_1)) );
915 __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
916 __ swl(t1, MemOperand(a0, OFFSET_OF(T, swl_1) + 1) );
917
918 __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) );
919 __ sw(t2, MemOperand(a0, OFFSET_OF(T, swl_2)) );
920 __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
921 __ swl(t2, MemOperand(a0, OFFSET_OF(T, swl_2) + 2) );
922
923 __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) );
924 __ sw(t3, MemOperand(a0, OFFSET_OF(T, swl_3)) );
925 __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
926 __ swl(t3, MemOperand(a0, OFFSET_OF(T, swl_3) + 3) );
927
928 // Test all combinations of SWR and vAddr.
929 __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
930 __ sw(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) );
931 __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
932 __ swr(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) );
933
934 __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) );
935 __ sw(t1, MemOperand(a0, OFFSET_OF(T, swr_1)) );
936 __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
937 __ swr(t1, MemOperand(a0, OFFSET_OF(T, swr_1) + 1) );
938
939 __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) );
940 __ sw(t2, MemOperand(a0, OFFSET_OF(T, swr_2)) );
941 __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
942 __ swr(t2, MemOperand(a0, OFFSET_OF(T, swr_2) + 2) );
943
944 __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) );
945 __ sw(t3, MemOperand(a0, OFFSET_OF(T, swr_3)) );
946 __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
947 __ swr(t3, MemOperand(a0, OFFSET_OF(T, swr_3) + 3) );
948
949 __ jr(ra);
950 __ nop();
951
952 CodeDesc desc;
953 assm.GetCode(&desc);
954 Object* code = HEAP->CreateCode(
955 desc,
956 Code::ComputeFlags(Code::STUB),
957 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
958 CHECK(code->IsCode());
959 #ifdef DEBUG
960 Code::cast(code)->Print();
961 #endif
962 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
963 t.reg_init = 0xaabbccdd;
964 t.mem_init = 0x11223344;
965
966 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
967 USE(dummy);
968
969 CHECK_EQ(0x44bbccdd, t.lwl_0);
970 CHECK_EQ(0x3344ccdd, t.lwl_1);
971 CHECK_EQ(0x223344dd, t.lwl_2);
972 CHECK_EQ(0x11223344, t.lwl_3);
973
974 CHECK_EQ(0x11223344, t.lwr_0);
975 CHECK_EQ(0xaa112233, t.lwr_1);
976 CHECK_EQ(0xaabb1122, t.lwr_2);
977 CHECK_EQ(0xaabbcc11, t.lwr_3);
978
979 CHECK_EQ(0x112233aa, t.swl_0);
980 CHECK_EQ(0x1122aabb, t.swl_1);
981 CHECK_EQ(0x11aabbcc, t.swl_2);
982 CHECK_EQ(0xaabbccdd, t.swl_3);
983
984 CHECK_EQ(0xaabbccdd, t.swr_0);
985 CHECK_EQ(0xbbccdd44, t.swr_1);
986 CHECK_EQ(0xccdd3344, t.swr_2);
987 CHECK_EQ(0xdd223344, t.swr_3);
988 }
989
990
991 TEST(MIPS12) {
992 InitializeVM();
993 v8::HandleScope scope;
994
995 typedef struct {
996 int32_t x;
997 int32_t y;
998 int32_t y1;
999 int32_t y2;
1000 int32_t y3;
1001 int32_t y4;
1002 } T;
1003 T t;
1004
1005 MacroAssembler assm(NULL, 0);
1006
1007 __ mov(t6, fp); // Save frame pointer.
1008 __ mov(fp, a0); // Access struct T by fp.
1009 __ lw(t0, MemOperand(a0, OFFSET_OF(T, y)) );
1010 __ lw(t3, MemOperand(a0, OFFSET_OF(T, y4)) );
1011
1012 __ addu(t1, t0, t3);
1013 __ subu(t4, t0, t3);
1014 __ nop();
1015 __ Push(t0); // These instructions disappear after opt.
1016 __ Pop();
1017 __ addu(t0, t0, t0);
1018 __ nop();
1019 __ Pop(); // These instructions disappear after opt.
1020 __ Push(t3);
1021 __ nop();
1022 __ Push(t3); // These instructions disappear after opt.
1023 __ Pop(t3);
1024 __ nop();
1025 __ Push(t3);
1026 __ Pop(t4);
1027 __ nop();
1028 __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1029 __ lw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1030 __ nop();
1031 __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1032 __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
1033 __ nop();
1034 __ Push(t1);
1035 __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
1036 __ Pop(t1);
1037 __ nop();
1038 __ Push(t1);
1039 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1040 __ Pop(t1);
1041 __ nop();
1042 __ Push(t1);
1043 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1044 __ Pop(t2);
1045 __ nop();
1046 __ Push(t2);
1047 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1048 __ Pop(t1);
1049 __ nop();
1050 __ Push(t1);
1051 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1052 __ Pop(t3);
1053 __ nop();
1054
1055 __ mov(fp, t6);
1056 __ jr(ra);
1057 __ nop();
1058
1059 CodeDesc desc;
1060 assm.GetCode(&desc);
1061 Object* code = HEAP->CreateCode(
1062 desc,
1063 Code::ComputeFlags(Code::STUB),
1064 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
1065 CHECK(code->IsCode());
1066 #ifdef DEBUG
1067 Code::cast(code)->Print();
1068 #endif
1069 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1070 t.x = 1;
1071 t.y = 2;
1072 t.y1 = 3;
1073 t.y2 = 4;
1074 t.y3 = 0XBABA;
1075 t.y4 = 0xDEDA;
1076
1077 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1078 USE(dummy);
1079
1080 CHECK_EQ(3, t.y1);
1081 }
1082
1083
1084 TEST(MIPS13) {
1085 // Test Cvt_d_uw and Trunc_uw_d macros.
1086 InitializeVM();
1087 v8::HandleScope scope;
1088
1089 typedef struct {
1090 double cvt_big_out;
1091 double cvt_small_out;
1092 uint32_t trunc_big_out;
1093 uint32_t trunc_small_out;
1094 uint32_t cvt_big_in;
1095 uint32_t cvt_small_in;
1096 } T;
1097 T t;
1098
1099 MacroAssembler assm(NULL, 0);
1100
1101 __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_small_in)));
1102 __ Cvt_d_uw(f10, t0);
1103 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out)));
1104
1105 __ Trunc_uw_d(f10, f10);
1106 __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out)));
1107
1108 __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_big_in)));
1109 __ Cvt_d_uw(f8, t0);
1110 __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out)));
1111
1112 __ Trunc_uw_d(f8, f8);
1113 __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out)));
1114
1115 __ jr(ra);
1116 __ nop();
1117
1118 CodeDesc desc;
1119 assm.GetCode(&desc);
1120 Object* code = HEAP->CreateCode(
1121 desc,
1122 Code::ComputeFlags(Code::STUB),
1123 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
1124 CHECK(code->IsCode());
1125 #ifdef DEBUG
1126 Code::cast(code)->Print();
1127 #endif
1128 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1129
1130 t.cvt_big_in = 0xFFFFFFFF;
1131 t.cvt_small_in = 333;
1132
1133 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1134 USE(dummy);
1135
1136 CHECK_EQ(t.cvt_big_out, static_cast<double>(t.cvt_big_in));
1137 CHECK_EQ(t.cvt_small_out, static_cast<double>(t.cvt_small_in));
1138
1139 CHECK_EQ(static_cast<int>(t.trunc_big_out), static_cast<int>(t.cvt_big_in));
1140 CHECK_EQ(static_cast<int>(t.trunc_small_out),
1141 static_cast<int>(t.cvt_small_in));
1142 }
1143
1144
1145 TEST(MIPS14) {
1146 // Test round, floor, ceil, trunc, cvt.
1147 InitializeVM();
1148 v8::HandleScope scope;
1149
1150 #define ROUND_STRUCT_ELEMENT(x) \
1151 int32_t x##_up_out; \
1152 int32_t x##_down_out; \
1153 int32_t neg_##x##_up_out; \
1154 int32_t neg_##x##_down_out; \
1155 int32_t x##_err1_out; \
1156 int32_t x##_err2_out; \
1157 int32_t x##_err3_out; \
1158 int32_t x##_err4_out; \
1159 int32_t x##_invalid_result;
1160
1161 typedef struct {
1162 double round_up_in;
1163 double round_down_in;
1164 double neg_round_up_in;
1165 double neg_round_down_in;
1166 double err1_in;
1167 double err2_in;
1168 double err3_in;
1169 double err4_in;
1170
1171 ROUND_STRUCT_ELEMENT(round)
1172 ROUND_STRUCT_ELEMENT(floor)
1173 ROUND_STRUCT_ELEMENT(ceil)
1174 ROUND_STRUCT_ELEMENT(trunc)
1175 ROUND_STRUCT_ELEMENT(cvt)
1176 } T;
1177 T t;
1178
1179 #undef ROUND_STRUCT_ELEMENT
1180
1181 MacroAssembler assm(NULL, 0);
1182
1183 // Save FCSR.
1184 __ cfc1(a1, FCSR);
1185 // Disable FPU exceptions.
1186 __ ctc1(zero_reg, FCSR);
1187 #define RUN_ROUND_TEST(x) \
1188 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_up_in))); \
1189 __ x##_w_d(f0, f0); \
1190 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_up_out))); \
1191 \
1192 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_down_in))); \
1193 __ x##_w_d(f0, f0); \
1194 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_down_out))); \
1195 \
1196 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_up_in))); \
1197 __ x##_w_d(f0, f0); \
1198 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_up_out))); \
1199 \
1200 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_down_in))); \
1201 __ x##_w_d(f0, f0); \
1202 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_down_out))); \
1203 \
1204 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err1_in))); \
1205 __ ctc1(zero_reg, FCSR); \
1206 __ x##_w_d(f0, f0); \
1207 __ cfc1(a2, FCSR); \
1208 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err1_out))); \
1209 \
1210 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err2_in))); \
1211 __ ctc1(zero_reg, FCSR); \
1212 __ x##_w_d(f0, f0); \
1213 __ cfc1(a2, FCSR); \
1214 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err2_out))); \
1215 \
1216 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err3_in))); \
1217 __ ctc1(zero_reg, FCSR); \
1218 __ x##_w_d(f0, f0); \
1219 __ cfc1(a2, FCSR); \
1220 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err3_out))); \
1221 \
1222 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err4_in))); \
1223 __ ctc1(zero_reg, FCSR); \
1224 __ x##_w_d(f0, f0); \
1225 __ cfc1(a2, FCSR); \
1226 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err4_out))); \
1227 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_invalid_result)));
1228
1229 RUN_ROUND_TEST(round)
1230 RUN_ROUND_TEST(floor)
1231 RUN_ROUND_TEST(ceil)
1232 RUN_ROUND_TEST(trunc)
1233 RUN_ROUND_TEST(cvt)
1234
1235 // Restore FCSR.
1236 __ ctc1(a1, FCSR);
1237
1238 #undef RUN_ROUND_TEST
1239
1240 __ jr(ra);
1241 __ nop();
1242
1243 CodeDesc desc;
1244 assm.GetCode(&desc);
1245 Object* code = HEAP->CreateCode(
1246 desc,
1247 Code::ComputeFlags(Code::STUB),
1248 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
1249 CHECK(code->IsCode());
1250 #ifdef DEBUG
1251 Code::cast(code)->Print();
1252 #endif
1253 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1254
1255 t.round_up_in = 123.51;
1256 t.round_down_in = 123.49;
1257 t.neg_round_up_in = -123.5;
1258 t.neg_round_down_in = -123.49;
1259 t.err1_in = 123.51;
1260 t.err2_in = 1;
1261 t.err3_in = static_cast<double>(1) + 0xFFFFFFFF;
1262 t.err4_in = NAN;
1263
1264 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1265 USE(dummy);
1266
1267 #define GET_FPU_ERR(x) \
1268 ((x >> 2) & (32 - 1))
1269
1270 CHECK_EQ(124, t.round_up_out);
1271 CHECK_EQ(123, t.round_down_out);
1272 CHECK_EQ(-124, t.neg_round_up_out);
1273 CHECK_EQ(-123, t.neg_round_down_out);
1274
1275 // Inaccurate.
1276 CHECK_EQ(1, GET_FPU_ERR(t.round_err1_out));
1277 // No error.
1278 CHECK_EQ(0, GET_FPU_ERR(t.round_err2_out));
1279 // Invalid operation.
1280 CHECK_EQ(16, GET_FPU_ERR(t.round_err3_out));
1281 CHECK_EQ(16, GET_FPU_ERR(t.round_err4_out));
1282 CHECK_EQ(kFPUInvalidResult, t.round_invalid_result);
1283
1284 CHECK_EQ(123, t.floor_up_out);
1285 CHECK_EQ(123, t.floor_down_out);
1286 CHECK_EQ(-124, t.neg_floor_up_out);
1287 CHECK_EQ(-124, t.neg_floor_down_out);
1288
1289 // Inaccurate.
1290 CHECK_EQ(1, GET_FPU_ERR(t.floor_err1_out));
1291 // No error.
1292 CHECK_EQ(0, GET_FPU_ERR(t.floor_err2_out));
1293 // Invalid operation.
1294 CHECK_EQ(16, GET_FPU_ERR(t.floor_err3_out));
1295 CHECK_EQ(16, GET_FPU_ERR(t.floor_err4_out));
1296 CHECK_EQ(kFPUInvalidResult, t.floor_invalid_result);
1297
1298 CHECK_EQ(124, t.ceil_up_out);
1299 CHECK_EQ(124, t.ceil_down_out);
1300 CHECK_EQ(-123, t.neg_ceil_up_out);
1301 CHECK_EQ(-123, t.neg_ceil_down_out);
1302
1303 // Inaccurate.
1304 CHECK_EQ(1, GET_FPU_ERR(t.ceil_err1_out));
1305 // No error.
1306 CHECK_EQ(0, GET_FPU_ERR(t.ceil_err2_out));
1307 // Invalid operation.
1308 CHECK_EQ(16, GET_FPU_ERR(t.ceil_err3_out));
1309 CHECK_EQ(16, GET_FPU_ERR(t.ceil_err4_out));
1310 CHECK_EQ(kFPUInvalidResult, t.ceil_invalid_result);
1311
1312 // In rounding mode 0 cvt should behave like round.
1313 CHECK_EQ(t.round_up_out, t.cvt_up_out);
1314 CHECK_EQ(t.round_down_out, t.cvt_down_out);
1315 CHECK_EQ(t.neg_round_up_out, t.neg_cvt_up_out);
1316 CHECK_EQ(t.neg_round_down_out, t.neg_cvt_down_out);
1317
1318 // Inaccurate.
1319 CHECK_EQ(1, GET_FPU_ERR(t.cvt_err1_out));
1320 // No error.
1321 CHECK_EQ(0, GET_FPU_ERR(t.cvt_err2_out));
1322 // Invalid operation.
1323 CHECK_EQ(16, GET_FPU_ERR(t.cvt_err3_out));
1324 CHECK_EQ(16, GET_FPU_ERR(t.cvt_err4_out));
1325 CHECK_EQ(kFPUInvalidResult, t.cvt_invalid_result);
1326 }
1327
1328
253 #undef __ 1329 #undef __
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698