| OLD | NEW |
| 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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 | 97 |
| 98 MacroAssembler assm(NULL, 0); | 98 MacroAssembler assm(NULL, 0); |
| 99 Label L, C; | 99 Label L, C; |
| 100 | 100 |
| 101 __ mov(a1, a0); | 101 __ mov(a1, a0); |
| 102 __ li(v0, 0); | 102 __ li(v0, 0); |
| 103 __ b(&C); | 103 __ b(&C); |
| 104 __ nop(); | 104 __ nop(); |
| 105 | 105 |
| 106 __ bind(&L); | 106 __ bind(&L); |
| 107 __ add(v0, v0, a1); | 107 __ addu(v0, v0, a1); |
| 108 __ addiu(a1, a1, -1); | 108 __ addiu(a1, a1, -1); |
| 109 | 109 |
| 110 __ bind(&C); | 110 __ bind(&C); |
| 111 __ xori(v1, a1, 0); | 111 __ xori(v1, a1, 0); |
| 112 __ Branch(ne, &L, v1, Operand(0)); | 112 __ Branch(&L, ne, v1, Operand(0)); |
| 113 __ nop(); | 113 __ nop(); |
| 114 | 114 |
| 115 __ jr(ra); | 115 __ jr(ra); |
| 116 __ nop(); | 116 __ nop(); |
| 117 | 117 |
| 118 CodeDesc desc; | 118 CodeDesc desc; |
| 119 assm.GetCode(&desc); | 119 assm.GetCode(&desc); |
| 120 Object* code = Heap::CreateCode(desc, | 120 Object* code = Heap::CreateCode(desc, |
| 121 NULL, | 121 NULL, |
| 122 Code::ComputeFlags(Code::STUB), | 122 Code::ComputeFlags(Code::STUB), |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 __ li(t6, 0xedcba988); | 163 __ li(t6, 0xedcba988); |
| 164 __ li(t7, 0x80000000); | 164 __ li(t7, 0x80000000); |
| 165 | 165 |
| 166 // SPECIAL class. | 166 // SPECIAL class. |
| 167 __ srl(v0, t2, 8); // 0x00123456 | 167 __ srl(v0, t2, 8); // 0x00123456 |
| 168 __ sll(v0, v0, 11); // 0x91a2b000 | 168 __ sll(v0, v0, 11); // 0x91a2b000 |
| 169 __ sra(v0, v0, 3); // 0xf2345600 | 169 __ sra(v0, v0, 3); // 0xf2345600 |
| 170 __ srav(v0, v0, t0); // 0xff234560 | 170 __ srav(v0, v0, t0); // 0xff234560 |
| 171 __ sllv(v0, v0, t0); // 0xf2345600 | 171 __ sllv(v0, v0, t0); // 0xf2345600 |
| 172 __ srlv(v0, v0, t0); // 0x0f234560 | 172 __ srlv(v0, v0, t0); // 0x0f234560 |
| 173 __ Branch(ne, &error, v0, Operand(0x0f234560)); | 173 __ Branch(&error, ne, v0, Operand(0x0f234560)); |
| 174 __ nop(); | 174 __ nop(); |
| 175 | 175 |
| 176 __ add(v0, t0, t1); // 0x00001238 | 176 __ addu(v0, t0, t1); // 0x00001238 |
| 177 __ sub(v0, v0, t0); // 0x00001234 | 177 __ subu(v0, v0, t0); // 0x00001234 |
| 178 __ Branch(ne, &error, v0, Operand(0x00001234)); | 178 __ Branch(&error, ne, v0, Operand(0x00001234)); |
| 179 __ nop(); | 179 __ nop(); |
| 180 __ addu(v1, t3, t0); | 180 __ addu(v1, t3, t0); |
| 181 __ Branch(ne, &error, v1, Operand(0x80000003)); | 181 __ Branch(&error, ne, v1, Operand(0x80000003)); |
| 182 __ nop(); | 182 __ nop(); |
| 183 __ subu(v1, t7, t0); // 0x7ffffffc | 183 __ subu(v1, t7, t0); // 0x7ffffffc |
| 184 __ Branch(ne, &error, v1, Operand(0x7ffffffc)); | 184 __ Branch(&error, ne, v1, Operand(0x7ffffffc)); |
| 185 __ nop(); | 185 __ nop(); |
| 186 | 186 |
| 187 __ and_(v0, t1, t2); // 0x00001230 | 187 __ and_(v0, t1, t2); // 0x00001230 |
| 188 __ or_(v0, v0, t1); // 0x00001234 | 188 __ or_(v0, v0, t1); // 0x00001234 |
| 189 __ xor_(v0, v0, t2); // 0x1234444c | 189 __ xor_(v0, v0, t2); // 0x1234444c |
| 190 __ nor(v0, v0, t2); // 0xedcba987 | 190 __ nor(v0, v0, t2); // 0xedcba987 |
| 191 __ Branch(ne, &error, v0, Operand(0xedcba983)); | 191 __ Branch(&error, ne, v0, Operand(0xedcba983)); |
| 192 __ nop(); | 192 __ nop(); |
| 193 | 193 |
| 194 __ slt(v0, t7, t3); | 194 __ slt(v0, t7, t3); |
| 195 __ Branch(ne, &error, v0, Operand(0x1)); | 195 __ Branch(&error, ne, v0, Operand(0x1)); |
| 196 __ nop(); | 196 __ nop(); |
| 197 __ sltu(v0, t7, t3); | 197 __ sltu(v0, t7, t3); |
| 198 __ Branch(ne, &error, v0, Operand(0x0)); | 198 __ Branch(&error, ne, v0, Operand(0x0)); |
| 199 __ nop(); | 199 __ nop(); |
| 200 // End of SPECIAL class. | 200 // End of SPECIAL class. |
| 201 | 201 |
| 202 __ addi(v0, zero_reg, 0x7421); // 0x00007421 | 202 __ addiu(v0, zero_reg, 0x7421); // 0x00007421 |
| 203 __ addi(v0, v0, -0x1); // 0x00007420 | 203 __ addiu(v0, v0, -0x1); // 0x00007420 |
| 204 __ addiu(v0, v0, -0x20); // 0x00007400 | 204 __ addiu(v0, v0, -0x20); // 0x00007400 |
| 205 __ Branch(ne, &error, v0, Operand(0x00007400)); | 205 __ Branch(&error, ne, v0, Operand(0x00007400)); |
| 206 __ nop(); | 206 __ nop(); |
| 207 __ addiu(v1, t3, 0x1); // 0x80000000 | 207 __ addiu(v1, t3, 0x1); // 0x80000000 |
| 208 __ Branch(ne, &error, v1, Operand(0x80000000)); | 208 __ Branch(&error, ne, v1, Operand(0x80000000)); |
| 209 __ nop(); | 209 __ nop(); |
| 210 | 210 |
| 211 __ slti(v0, t1, 0x00002000); // 0x1 | 211 __ slti(v0, t1, 0x00002000); // 0x1 |
| 212 __ slti(v0, v0, 0xffff8000); // 0x0 | 212 __ slti(v0, v0, 0xffff8000); // 0x0 |
| 213 __ Branch(ne, &error, v0, Operand(0x0)); | 213 __ Branch(&error, ne, v0, Operand(0x0)); |
| 214 __ nop(); | 214 __ nop(); |
| 215 __ sltiu(v0, t1, 0x00002000); // 0x1 | 215 __ sltiu(v0, t1, 0x00002000); // 0x1 |
| 216 __ sltiu(v0, v0, 0x00008000); // 0x1 | 216 __ sltiu(v0, v0, 0x00008000); // 0x1 |
| 217 __ Branch(ne, &error, v0, Operand(0x1)); | 217 __ Branch(&error, ne, v0, Operand(0x1)); |
| 218 __ nop(); | 218 __ nop(); |
| 219 | 219 |
| 220 __ andi(v0, t1, 0xf0f0); // 0x00001030 | 220 __ andi(v0, t1, 0xf0f0); // 0x00001030 |
| 221 __ ori(v0, v0, 0x8a00); // 0x00009a30 | 221 __ ori(v0, v0, 0x8a00); // 0x00009a30 |
| 222 __ xori(v0, v0, 0x83cc); // 0x000019fc | 222 __ xori(v0, v0, 0x83cc); // 0x000019fc |
| 223 __ Branch(ne, &error, v0, Operand(0x000019fc)); | 223 __ Branch(&error, ne, v0, Operand(0x000019fc)); |
| 224 __ nop(); | 224 __ nop(); |
| 225 __ lui(v1, 0x8123); // 0x81230000 | 225 __ lui(v1, 0x8123); // 0x81230000 |
| 226 __ Branch(ne, &error, v1, Operand(0x81230000)); | 226 __ Branch(&error, ne, v1, Operand(0x81230000)); |
| 227 __ nop(); | 227 __ nop(); |
| 228 | 228 |
| 229 // Bit twiddling instructions & conditional moves. |
| 230 // Uses t0-t7 as set above. |
| 231 __ clz(v0, t0); // 29 |
| 232 __ clz(v1, t1); // 19 |
| 233 __ addu(v0, v0, v1); // 48 |
| 234 __ clz(v1, t2); // 3 |
| 235 __ addu(v0, v0, v1); // 51 |
| 236 __ clz(v1, t7); // 0 |
| 237 __ addu(v0, v0, v1); // 51 |
| 238 __ Branch(&error, ne, v0, Operand(51)); |
| 239 __ movn(a0, t3, t0); // move a0<-t3 (t0 is NOT 0) |
| 240 __ ins(a0, t1, 12, 8); // 0x7ff34fff |
| 241 __ Branch(&error, ne, a0, Operand(0x7ff34fff)); |
| 242 __ movz(a0, t6, t7); // a0 not updated (t7 is NOT 0) |
| 243 __ ext(a1, a0, 8, 12); // 0x34f |
| 244 __ Branch(&error, ne, a1, Operand(0x34f)); |
| 245 __ movz(a0, t6, v1); // a0<-t6, v0 is 0, from 8 instr back |
| 246 __ Branch(&error, ne, a0, Operand(t6)); |
| 247 |
| 229 // Everything was correctly executed. Load the expected result. | 248 // Everything was correctly executed. Load the expected result. |
| 230 __ li(v0, 0x31415926); | 249 __ li(v0, 0x31415926); |
| 231 __ b(&exit); | 250 __ b(&exit); |
| 232 __ nop(); | 251 __ nop(); |
| 233 | 252 |
| 234 __ bind(&error); | 253 __ bind(&error); |
| 235 // Got an error. Return a wrong result. | 254 // Got an error. Return a wrong result. |
| 255 __ li(v0, 666); |
| 236 | 256 |
| 237 __ bind(&exit); | 257 __ bind(&exit); |
| 238 __ jr(ra); | 258 __ jr(ra); |
| 239 __ nop(); | 259 __ nop(); |
| 240 | 260 |
| 241 CodeDesc desc; | 261 CodeDesc desc; |
| 242 assm.GetCode(&desc); | 262 assm.GetCode(&desc); |
| 243 Object* code = Heap::CreateCode(desc, | 263 Object* code = Heap::CreateCode(desc, |
| 244 NULL, | 264 NULL, |
| 245 Code::ComputeFlags(Code::STUB), | 265 Code::ComputeFlags(Code::STUB), |
| 246 Handle<Object>(Heap::undefined_value())); | 266 Handle<Object>(Heap::undefined_value())); |
| 247 CHECK(code->IsCode()); | 267 CHECK(code->IsCode()); |
| 248 #ifdef DEBUG | 268 #ifdef DEBUG |
| 249 Code::cast(code)->Print(); | 269 Code::cast(code)->Print(); |
| 250 #endif | 270 #endif |
| 251 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry()); | 271 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry()); |
| 252 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0)); | 272 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0)); |
| 253 ::printf("f() = %d\n", res); | 273 ::printf("f() = %d\n", res); |
| 254 CHECK_EQ(0x31415926, res); | 274 CHECK_EQ(0x31415926, res); |
| 255 } | 275 } |
| 256 | 276 |
| 277 |
| 278 TEST(MIPS3) { |
| 279 // Test floating point instructions. |
| 280 InitializeVM(); |
| 281 v8::HandleScope scope; |
| 282 |
| 283 typedef struct { |
| 284 double a; |
| 285 double b; |
| 286 double c; |
| 287 double d; |
| 288 double e; |
| 289 double f; |
| 290 } T; |
| 291 T t; |
| 292 |
| 293 // Create a function that accepts &t, and loads, manipulates, and stores |
| 294 // the doubles t.a ... t.f. |
| 295 MacroAssembler assm(NULL, 0); |
| 296 Label L, C; |
| 297 |
| 298 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); |
| 299 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); |
| 300 __ add_d(f8, f4, f6); |
| 301 __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, c)) ); // c = a + b |
| 302 |
| 303 __ mov_d(f10, f8); // c |
| 304 __ neg_d(f12, f6); // -b |
| 305 __ sub_d(f10, f10, f12); |
| 306 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, d)) ); // d = c - (-b) |
| 307 |
| 308 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) ); // b = a |
| 309 |
| 310 __ li(t0, 120); |
| 311 __ mtc1(t0, f14); |
| 312 __ cvt_d_w(f14, f14); // f14 = 120.0 |
| 313 __ mul_d(f10, f10, f14); |
| 314 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, e)) ); // e = d * 120 = 1.8066e16 |
| 315 |
| 316 __ div_d(f12, f10, f4); |
| 317 __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) ); // f = e / a = 120.44 |
| 318 |
| 319 __ jr(ra); |
| 320 __ nop(); |
| 321 |
| 322 CodeDesc desc; |
| 323 assm.GetCode(&desc); |
| 324 Object* code = Heap::CreateCode(desc, |
| 325 NULL, |
| 326 Code::ComputeFlags(Code::STUB), |
| 327 Handle<Object>(Heap::undefined_value())); |
| 328 CHECK(code->IsCode()); |
| 329 #ifdef DEBUG |
| 330 Code::cast(code)->Print(); |
| 331 #endif |
| 332 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
| 333 t.a = 1.5e14; |
| 334 t.b = 2.75e11; |
| 335 t.c = 0.0; |
| 336 t.d = 0.0; |
| 337 t.e = 0.0; |
| 338 t.f = 0.0; |
| 339 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
| 340 USE(dummy); |
| 341 CHECK_EQ(1.5e14, t.a); |
| 342 CHECK_EQ(1.5e14, t.b); |
| 343 CHECK_EQ(1.50275e14, t.c); |
| 344 CHECK_EQ(1.50550e14, t.d); |
| 345 CHECK_EQ(1.8066e16, t.e); |
| 346 CHECK_EQ(120.44, t.f); |
| 347 } |
| 348 |
| 349 |
| 350 TEST(MIPS4) { |
| 351 // Test moves between floating point and integer registers. |
| 352 InitializeVM(); |
| 353 v8::HandleScope scope; |
| 354 |
| 355 typedef struct { |
| 356 double a; |
| 357 double b; |
| 358 double c; |
| 359 } T; |
| 360 T t; |
| 361 |
| 362 Assembler assm(NULL, 0); |
| 363 Label L, C; |
| 364 |
| 365 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); |
| 366 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); |
| 367 |
| 368 // swap f4 and f6, by using four integer registers, t0-t3 |
| 369 __ mfc1(t0, f4); |
| 370 __ mfc1(t1, f5); |
| 371 __ mfc1(t2, f6); |
| 372 __ mfc1(t3, f7); |
| 373 |
| 374 __ mtc1(t0, f6); |
| 375 __ mtc1(t1, f7); |
| 376 __ mtc1(t2, f4); |
| 377 __ mtc1(t3, f5); |
| 378 |
| 379 // store the swapped f4 and f5 back to memory |
| 380 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); |
| 381 __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, c)) ); |
| 382 |
| 383 __ jr(ra); |
| 384 __ nop(); |
| 385 |
| 386 CodeDesc desc; |
| 387 assm.GetCode(&desc); |
| 388 Object* code = Heap::CreateCode(desc, |
| 389 NULL, |
| 390 Code::ComputeFlags(Code::STUB), |
| 391 Handle<Object>(Heap::undefined_value())); |
| 392 CHECK(code->IsCode()); |
| 393 #ifdef DEBUG |
| 394 Code::cast(code)->Print(); |
| 395 #endif |
| 396 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
| 397 t.a = 1.5e22; |
| 398 t.b = 2.75e11; |
| 399 t.c = 17.17; |
| 400 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
| 401 USE(dummy); |
| 402 |
| 403 CHECK_EQ(2.75e11, t.a); |
| 404 CHECK_EQ(2.75e11, t.b); |
| 405 CHECK_EQ(1.5e22, t.c); |
| 406 } |
| 407 |
| 408 |
| 409 TEST(MIPS5) { |
| 410 // Test conversions between doubles and integers |
| 411 InitializeVM(); |
| 412 v8::HandleScope scope; |
| 413 |
| 414 typedef struct { |
| 415 double a; |
| 416 double b; |
| 417 int i; |
| 418 int j; |
| 419 } T; |
| 420 T t; |
| 421 |
| 422 Assembler assm(NULL, 0); |
| 423 Label L, C; |
| 424 |
| 425 // load all structure elements to registers |
| 426 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); |
| 427 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); |
| 428 __ lw(t0, MemOperand(a0, OFFSET_OF(T, i)) ); |
| 429 __ lw(t1, MemOperand(a0, OFFSET_OF(T, j)) ); |
| 430 |
| 431 // convert double in f4 to int in element i |
| 432 __ cvt_w_d(f8, f4); |
| 433 __ mfc1(t2, f8); |
| 434 __ sw(t2, MemOperand(a0, OFFSET_OF(T, i)) ); |
| 435 |
| 436 // convert double in f6 to int in element j |
| 437 __ cvt_w_d(f10, f6); |
| 438 __ mfc1(t3, f10); |
| 439 __ sw(t3, MemOperand(a0, OFFSET_OF(T, j)) ); |
| 440 |
| 441 // convert int in original i (t0) to double in a |
| 442 __ mtc1(t0, f12); |
| 443 __ cvt_d_w(f0, f12); |
| 444 __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) ); |
| 445 |
| 446 // convert int in original j (t1) to double in b |
| 447 __ mtc1(t1, f14); |
| 448 __ cvt_d_w(f2, f14); |
| 449 __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) ); |
| 450 |
| 451 __ jr(ra); |
| 452 __ nop(); |
| 453 |
| 454 CodeDesc desc; |
| 455 assm.GetCode(&desc); |
| 456 Object* code = Heap::CreateCode(desc, |
| 457 NULL, |
| 458 Code::ComputeFlags(Code::STUB), |
| 459 Handle<Object>(Heap::undefined_value())); |
| 460 CHECK(code->IsCode()); |
| 461 #ifdef DEBUG |
| 462 Code::cast(code)->Print(); |
| 463 #endif |
| 464 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
| 465 t.a = 1.5e4; |
| 466 t.b = 2.75e8; |
| 467 t.i = 12345678; |
| 468 t.j = -100000; |
| 469 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
| 470 USE(dummy); |
| 471 |
| 472 CHECK_EQ(12345678.0, t.a); |
| 473 CHECK_EQ(-100000.0, t.b); |
| 474 CHECK_EQ(15000, t.i); |
| 475 CHECK_EQ(275000000, t.j); |
| 476 } |
| 477 |
| 478 |
| 479 TEST(MIPS6) { |
| 480 // Test simple memory loads and stores |
| 481 InitializeVM(); |
| 482 v8::HandleScope scope; |
| 483 |
| 484 typedef struct { |
| 485 uint32_t ui; |
| 486 int32_t si; |
| 487 int32_t r1; |
| 488 int32_t r2; |
| 489 int32_t r3; |
| 490 int32_t r4; |
| 491 int32_t r5; |
| 492 int32_t r6; |
| 493 } T; |
| 494 T t; |
| 495 |
| 496 Assembler assm(NULL, 0); |
| 497 Label L, C; |
| 498 |
| 499 // basic word load/store |
| 500 __ lw(t0, MemOperand(a0, OFFSET_OF(T, ui)) ); |
| 501 __ sw(t0, MemOperand(a0, OFFSET_OF(T, r1)) ); |
| 502 |
| 503 // lh with positive data |
| 504 __ lh(t1, MemOperand(a0, OFFSET_OF(T, ui)) ); |
| 505 __ sw(t1, MemOperand(a0, OFFSET_OF(T, r2)) ); |
| 506 |
| 507 // lh with negative data |
| 508 __ lh(t2, MemOperand(a0, OFFSET_OF(T, si)) ); |
| 509 __ sw(t2, MemOperand(a0, OFFSET_OF(T, r3)) ); |
| 510 |
| 511 // lhu with negative data |
| 512 __ lhu(t3, MemOperand(a0, OFFSET_OF(T, si)) ); |
| 513 __ sw(t3, MemOperand(a0, OFFSET_OF(T, r4)) ); |
| 514 |
| 515 // lb with negative data |
| 516 __ lb(t4, MemOperand(a0, OFFSET_OF(T, si)) ); |
| 517 __ sw(t4, MemOperand(a0, OFFSET_OF(T, r5)) ); |
| 518 |
| 519 // sh writes only 1/2 of word |
| 520 __ lui(t5, 0x3333); |
| 521 __ ori(t5, t5, 0x3333); |
| 522 __ sw(t5, MemOperand(a0, OFFSET_OF(T, r6)) ); |
| 523 __ lhu(t5, MemOperand(a0, OFFSET_OF(T, si)) ); |
| 524 __ sh(t5, MemOperand(a0, OFFSET_OF(T, r6)) ); |
| 525 |
| 526 |
| 527 __ jr(ra); |
| 528 __ nop(); |
| 529 |
| 530 CodeDesc desc; |
| 531 assm.GetCode(&desc); |
| 532 Object* code = Heap::CreateCode(desc, |
| 533 NULL, |
| 534 Code::ComputeFlags(Code::STUB), |
| 535 Handle<Object>(Heap::undefined_value())); |
| 536 CHECK(code->IsCode()); |
| 537 #ifdef DEBUG |
| 538 Code::cast(code)->Print(); |
| 539 #endif |
| 540 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
| 541 t.ui = 0x11223344; |
| 542 t.si = 0x99aabbcc; |
| 543 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
| 544 USE(dummy); |
| 545 |
| 546 CHECK_EQ(0x11223344, t.r1); |
| 547 CHECK_EQ(0x3344, t.r2); |
| 548 CHECK_EQ(0xffffbbcc, t.r3); |
| 549 CHECK_EQ(0x0000bbcc, t.r4); |
| 550 CHECK_EQ(0xffffffcc, t.r5); |
| 551 CHECK_EQ(0x3333bbcc, t.r6); |
| 552 } |
| 553 |
| 554 |
| 555 TEST(MIPS7) { |
| 556 // Test floating point compare and branch instructions. |
| 557 InitializeVM(); |
| 558 v8::HandleScope scope; |
| 559 |
| 560 typedef struct { |
| 561 double a; |
| 562 double b; |
| 563 double c; |
| 564 double d; |
| 565 double e; |
| 566 double f; |
| 567 int32_t result; |
| 568 } T; |
| 569 T t; |
| 570 |
| 571 // Create a function that accepts &t, and loads, manipulates, and stores |
| 572 // the doubles t.a ... t.f. |
| 573 MacroAssembler assm(NULL, 0); |
| 574 Label neither_is_nan, less_than, outa_here; |
| 575 |
| 576 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); |
| 577 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); |
| 578 __ c(UN, D, f4, f6); |
| 579 __ bc1f(&neither_is_nan); |
| 580 __ nop(); |
| 581 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) ); |
| 582 __ Branch(&outa_here, al); |
| 583 |
| 584 __ bind(&neither_is_nan); |
| 585 |
| 586 __ c(OLT, D, f6, f4, 2); |
| 587 __ bc1t(&less_than, 2); |
| 588 __ nop(); |
| 589 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) ); |
| 590 __ Branch(&outa_here, al); |
| 591 |
| 592 __ bind(&less_than); |
| 593 __ Addu(t0, zero_reg, Operand(1)); |
| 594 __ sw(t0, MemOperand(a0, OFFSET_OF(T, result)) ); // Set true. |
| 595 |
| 596 |
| 597 // This test-case needs additional tests, this is not quite sufficient. |
| 598 |
| 599 __ bind(&outa_here); |
| 600 |
| 601 __ jr(ra); |
| 602 __ nop(); |
| 603 |
| 604 CodeDesc desc; |
| 605 assm.GetCode(&desc); |
| 606 Object* code = Heap::CreateCode(desc, |
| 607 NULL, |
| 608 Code::ComputeFlags(Code::STUB), |
| 609 Handle<Object>(Heap::undefined_value())); |
| 610 CHECK(code->IsCode()); |
| 611 #ifdef DEBUG |
| 612 Code::cast(code)->Print(); |
| 613 #endif |
| 614 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
| 615 t.a = 1.5e14; |
| 616 t.b = 2.75e11; |
| 617 t.c = 2.0; |
| 618 t.d = -4.0; |
| 619 t.e = 0.0; |
| 620 t.f = 0.0; |
| 621 t.result = 0; |
| 622 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
| 623 USE(dummy); |
| 624 CHECK_EQ(1.5e14, t.a); |
| 625 CHECK_EQ(2.75e11, t.b); |
| 626 CHECK_EQ(1, t.result); |
| 627 } |
| 628 |
| 629 |
| 630 |
| 257 #undef __ | 631 #undef __ |
| OLD | NEW |