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

Side by Side Diff: src/arm/simulator-arm.cc

Issue 3107027: Fix incorrect encoding of single and double precision registers for some... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 3 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 | « src/arm/disasm-arm.cc ('k') | test/cctest/test-assembler-arm.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 2263 matching lines...) Expand 10 before | Expand all | Expand 10 after
2274 // Not sign extending, so load as unsigned. 2274 // Not sign extending, so load as unsigned.
2275 uint16_t halfword = ReadH(addr, instr); 2275 uint16_t halfword = ReadH(addr, instr);
2276 set_register(rd, halfword); 2276 set_register(rd, halfword);
2277 } else { 2277 } else {
2278 Debugger dbg(this); 2278 Debugger dbg(this);
2279 dbg.Stop(instr); 2279 dbg.Stop(instr);
2280 } 2280 }
2281 } 2281 }
2282 2282
2283 2283
2284 // Depending on value of last_bit flag glue register code from vm and m values
2285 // (where m is expected to be a single bit).
2286 static int GlueRegCode(bool last_bit, int vm, int m) {
2287 return last_bit ? ((vm << 1) | m) : ((m << 4) | vm);
2288 }
2289
2290
2291 // void Simulator::DecodeTypeVFP(Instr* instr) 2284 // void Simulator::DecodeTypeVFP(Instr* instr)
2292 // The Following ARMv7 VFPv instructions are currently supported. 2285 // The Following ARMv7 VFPv instructions are currently supported.
2293 // vmov :Sn = Rt 2286 // vmov :Sn = Rt
2294 // vmov :Rt = Sn 2287 // vmov :Rt = Sn
2295 // vcvt: Dd = Sm 2288 // vcvt: Dd = Sm
2296 // vcvt: Sd = Dm 2289 // vcvt: Sd = Dm
2297 // Dd = vadd(Dn, Dm) 2290 // Dd = vadd(Dn, Dm)
2298 // Dd = vsub(Dn, Dm) 2291 // Dd = vsub(Dn, Dm)
2299 // Dd = vmul(Dn, Dm) 2292 // Dd = vmul(Dn, Dm)
2300 // Dd = vdiv(Dn, Dm) 2293 // Dd = vdiv(Dn, Dm)
2301 // vcmp(Dd, Dm) 2294 // vcmp(Dd, Dm)
2302 // vmrs 2295 // vmrs
2303 // Dd = vsqrt(Dm) 2296 // Dd = vsqrt(Dm)
2304 void Simulator::DecodeTypeVFP(Instr* instr) { 2297 void Simulator::DecodeTypeVFP(Instr* instr) {
2305 ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) ); 2298 ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) );
2306 ASSERT(instr->Bits(11, 9) == 0x5); 2299 ASSERT(instr->Bits(11, 9) == 0x5);
2307 2300
2308 int vm = instr->VmField(); 2301 // Obtain double precision register codes.
2309 int vd = instr->VdField(); 2302 int vm = instr->VFPMRegCode(kDoublePrecision);
2310 int vn = instr->VnField(); 2303 int vd = instr->VFPDRegCode(kDoublePrecision);
2304 int vn = instr->VFPNRegCode(kDoublePrecision);
2311 2305
2312 if (instr->Bit(4) == 0) { 2306 if (instr->Bit(4) == 0) {
2313 if (instr->Opc1Field() == 0x7) { 2307 if (instr->Opc1Field() == 0x7) {
2314 // Other data processing instructions 2308 // Other data processing instructions
2315 if ((instr->Opc2Field() == 0x0) && (instr->Opc3Field() == 0x1)) { 2309 if ((instr->Opc2Field() == 0x0) && (instr->Opc3Field() == 0x1)) {
2316 // vmov register to register. 2310 // vmov register to register.
2317 if (instr->SzField() == 0x1) { 2311 if (instr->SzField() == 0x1) {
2318 set_d_register_from_double(vd, get_double_from_d_register(vm)); 2312 int m = instr->VFPMRegCode(kDoublePrecision);
2313 int d = instr->VFPDRegCode(kDoublePrecision);
2314 set_d_register_from_double(d, get_double_from_d_register(m));
2319 } else { 2315 } else {
2320 set_s_register_from_float(vd, get_float_from_s_register(vm)); 2316 int m = instr->VFPMRegCode(kSinglePrecision);
2317 int d = instr->VFPDRegCode(kSinglePrecision);
2318 set_s_register_from_float(d, get_float_from_s_register(m));
2321 } 2319 }
2322 } else if ((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)) { 2320 } else if ((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)) {
2323 DecodeVCVTBetweenDoubleAndSingle(instr); 2321 DecodeVCVTBetweenDoubleAndSingle(instr);
2324 } else if ((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) { 2322 } else if ((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) {
2325 DecodeVCVTBetweenFloatingPointAndInteger(instr); 2323 DecodeVCVTBetweenFloatingPointAndInteger(instr);
2326 } else if (((instr->Opc2Field() >> 1) == 0x6) && 2324 } else if (((instr->Opc2Field() >> 1) == 0x6) &&
2327 (instr->Opc3Field() & 0x1)) { 2325 (instr->Opc3Field() & 0x1)) {
2328 DecodeVCVTBetweenFloatingPointAndInteger(instr); 2326 DecodeVCVTBetweenFloatingPointAndInteger(instr);
2329 } else if (((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) && 2327 } else if (((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) &&
2330 (instr->Opc3Field() & 0x1)) { 2328 (instr->Opc3Field() & 0x1)) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
2403 } 2401 }
2404 } 2402 }
2405 } 2403 }
2406 2404
2407 2405
2408 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr) { 2406 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr) {
2409 ASSERT((instr->Bit(4) == 1) && (instr->VCField() == 0x0) && 2407 ASSERT((instr->Bit(4) == 1) && (instr->VCField() == 0x0) &&
2410 (instr->VAField() == 0x0)); 2408 (instr->VAField() == 0x0));
2411 2409
2412 int t = instr->RtField(); 2410 int t = instr->RtField();
2413 int n = GlueRegCode(true, instr->VnField(), instr->NField()); 2411 int n = instr->VFPNRegCode(kSinglePrecision);
2414 bool to_arm_register = (instr->VLField() == 0x1); 2412 bool to_arm_register = (instr->VLField() == 0x1);
2415 2413
2416 if (to_arm_register) { 2414 if (to_arm_register) {
2417 int32_t int_value = get_sinteger_from_s_register(n); 2415 int32_t int_value = get_sinteger_from_s_register(n);
2418 set_register(t, int_value); 2416 set_register(t, int_value);
2419 } else { 2417 } else {
2420 int32_t rs_val = get_register(t); 2418 int32_t rs_val = get_register(t);
2421 set_s_register_from_sinteger(n, rs_val); 2419 set_s_register_from_sinteger(n, rs_val);
2422 } 2420 }
2423 } 2421 }
2424 2422
2425 2423
2426 void Simulator::DecodeVCMP(Instr* instr) { 2424 void Simulator::DecodeVCMP(Instr* instr) {
2427 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); 2425 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7));
2428 ASSERT(((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) && 2426 ASSERT(((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) &&
2429 (instr->Opc3Field() & 0x1)); 2427 (instr->Opc3Field() & 0x1));
2428 // Comparison.
2430 2429
2431 // Comparison. 2430 VFPRegPrecision precision = kSinglePrecision;
2432 bool dp_operation = (instr->SzField() == 1); 2431 if (instr->SzField() == 1) {
2432 precision = kDoublePrecision;
2433 }
2433 2434
2434 if (instr->Bit(7) != 0) { 2435 if (instr->Bit(7) != 0) {
2435 // Raising exceptions for quiet NaNs are not supported. 2436 // Raising exceptions for quiet NaNs are not supported.
2436 UNIMPLEMENTED(); // Not used by V8. 2437 UNIMPLEMENTED(); // Not used by V8.
2437 } 2438 }
2438 2439
2439 int d = GlueRegCode(!dp_operation, instr->VdField(), instr->DField()); 2440 int d = instr->VFPDRegCode(precision);
2440 int m = 0; 2441 int m = 0;
2441 if (instr->Opc2Field() == 0x4) { 2442 if (instr->Opc2Field() == 0x4) {
2442 m = GlueRegCode(!dp_operation, instr->VmField(), instr->MField()); 2443 m = instr->VFPMRegCode(precision);
2443 } 2444 }
2444 2445
2445 if (dp_operation) { 2446 if (precision == kDoublePrecision) {
2446 double dd_value = get_double_from_d_register(d); 2447 double dd_value = get_double_from_d_register(d);
2447 double dm_value = 0.0; 2448 double dm_value = 0.0;
2448 if (instr->Opc2Field() == 0x4) { 2449 if (instr->Opc2Field() == 0x4) {
2449 dm_value = get_double_from_d_register(m); 2450 dm_value = get_double_from_d_register(m);
2450 } 2451 }
2451 2452
2452 Compute_FPSCR_Flags(dd_value, dm_value); 2453 Compute_FPSCR_Flags(dd_value, dm_value);
2453 } else { 2454 } else {
2454 UNIMPLEMENTED(); // Not used by V8. 2455 UNIMPLEMENTED(); // Not used by V8.
2455 } 2456 }
2456 } 2457 }
2457 2458
2458 2459
2459 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instr* instr) { 2460 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instr* instr) {
2460 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); 2461 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7));
2461 ASSERT((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)); 2462 ASSERT((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3));
2462 2463
2463 bool double_to_single = (instr->SzField() == 1); 2464 VFPRegPrecision dst_precision = kDoublePrecision;
2464 int dst = GlueRegCode(double_to_single, instr->VdField(), instr->DField()); 2465 VFPRegPrecision src_precision = kSinglePrecision;
2465 int src = GlueRegCode(!double_to_single, instr->VmField(), instr->MField()); 2466 if (instr->SzField() == 1) {
2467 dst_precision = kSinglePrecision;
2468 src_precision = kDoublePrecision;
2469 }
2466 2470
2467 if (double_to_single) { 2471 int dst = instr->VFPDRegCode(dst_precision);
2472 int src = instr->VFPMRegCode(src_precision);
2473
2474 if (dst_precision == kSinglePrecision) {
2468 double val = get_double_from_d_register(src); 2475 double val = get_double_from_d_register(src);
2469 set_s_register_from_float(dst, static_cast<float>(val)); 2476 set_s_register_from_float(dst, static_cast<float>(val));
2470 } else { 2477 } else {
2471 float val = get_float_from_s_register(src); 2478 float val = get_float_from_s_register(src);
2472 set_d_register_from_double(dst, static_cast<double>(val)); 2479 set_d_register_from_double(dst, static_cast<double>(val));
2473 } 2480 }
2474 } 2481 }
2475 2482
2476 2483
2477 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr) { 2484 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr) {
2478 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); 2485 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7));
2479 ASSERT(((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) || 2486 ASSERT(((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) ||
2480 (((instr->Opc2Field() >> 1) == 0x6) && (instr->Opc3Field() & 0x1))); 2487 (((instr->Opc2Field() >> 1) == 0x6) && (instr->Opc3Field() & 0x1)));
2481 2488
2482 // Conversion between floating-point and integer. 2489 // Conversion between floating-point and integer.
2483 int vd = instr->VdField(); 2490 bool to_integer = (instr->Bit(18) == 1);
2484 int d = instr->DField();
2485 int vm = instr->VmField();
2486 int m = instr->MField();
2487 2491
2488 bool to_integer = (instr->Bit(18) == 1); 2492 VFPRegPrecision src_precision = kSinglePrecision;
2489 bool dp_operation = (instr->SzField() == 1); 2493 if (instr->SzField() == 1) {
2494 src_precision = kDoublePrecision;
2495 }
2496
2490 if (to_integer) { 2497 if (to_integer) {
2491 bool unsigned_integer = (instr->Bit(16) == 0); 2498 bool unsigned_integer = (instr->Bit(16) == 0);
2492 if (instr->Bit(7) != 1) { 2499 if (instr->Bit(7) != 1) {
2493 // Only rounding towards zero supported. 2500 // Only rounding towards zero supported.
2494 UNIMPLEMENTED(); // Not used by V8. 2501 UNIMPLEMENTED(); // Not used by V8.
2495 } 2502 }
2496 2503
2497 int dst = GlueRegCode(true, vd, d); 2504 int dst = instr->VFPDRegCode(kSinglePrecision);
2498 int src = GlueRegCode(!dp_operation, vm, m); 2505 int src = instr->VFPMRegCode(src_precision);
2499 2506
2500 if (dp_operation) { 2507 if (src_precision == kDoublePrecision) {
2501 double val = get_double_from_d_register(src); 2508 double val = get_double_from_d_register(src);
2502 2509
2503 int sint = unsigned_integer ? static_cast<uint32_t>(val) : 2510 int sint = unsigned_integer ? static_cast<uint32_t>(val) :
2504 static_cast<int32_t>(val); 2511 static_cast<int32_t>(val);
2505 2512
2506 set_s_register_from_sinteger(dst, sint); 2513 set_s_register_from_sinteger(dst, sint);
2507 } else { 2514 } else {
2508 float val = get_float_from_s_register(src); 2515 float val = get_float_from_s_register(src);
2509 2516
2510 int sint = unsigned_integer ? static_cast<uint32_t>(val) : 2517 int sint = unsigned_integer ? static_cast<uint32_t>(val) :
2511 static_cast<int32_t>(val); 2518 static_cast<int32_t>(val);
2512 2519
2513 set_s_register_from_sinteger(dst, sint); 2520 set_s_register_from_sinteger(dst, sint);
2514 } 2521 }
2515 } else { 2522 } else {
2516 bool unsigned_integer = (instr->Bit(7) == 0); 2523 bool unsigned_integer = (instr->Bit(7) == 0);
2517 2524
2518 int dst = GlueRegCode(!dp_operation, vd, d); 2525 int dst = instr->VFPDRegCode(src_precision);
2519 int src = GlueRegCode(true, vm, m); 2526 int src = instr->VFPMRegCode(kSinglePrecision);
2520 2527
2521 int val = get_sinteger_from_s_register(src); 2528 int val = get_sinteger_from_s_register(src);
2522 2529
2523 if (dp_operation) { 2530 if (src_precision == kDoublePrecision) {
2524 if (unsigned_integer) { 2531 if (unsigned_integer) {
2525 set_d_register_from_double(dst, 2532 set_d_register_from_double(dst,
2526 static_cast<double>((uint32_t)val)); 2533 static_cast<double>((uint32_t)val));
2527 } else { 2534 } else {
2528 set_d_register_from_double(dst, static_cast<double>(val)); 2535 set_d_register_from_double(dst, static_cast<double>(val));
2529 } 2536 }
2530 } else { 2537 } else {
2531 if (unsigned_integer) { 2538 if (unsigned_integer) {
2532 set_s_register_from_float(dst, 2539 set_s_register_from_float(dst,
2533 static_cast<float>((uint32_t)val)); 2540 static_cast<float>((uint32_t)val));
(...skipping 10 matching lines...) Expand all
2544 // Dm = vmov(Rt, Rt2) 2551 // Dm = vmov(Rt, Rt2)
2545 // <Rt, Rt2> = vmov(Dm) 2552 // <Rt, Rt2> = vmov(Dm)
2546 // Ddst = MEM(Rbase + 4*offset). 2553 // Ddst = MEM(Rbase + 4*offset).
2547 // MEM(Rbase + 4*offset) = Dsrc. 2554 // MEM(Rbase + 4*offset) = Dsrc.
2548 void Simulator::DecodeType6CoprocessorIns(Instr* instr) { 2555 void Simulator::DecodeType6CoprocessorIns(Instr* instr) {
2549 ASSERT((instr->TypeField() == 6)); 2556 ASSERT((instr->TypeField() == 6));
2550 2557
2551 if (instr->CoprocessorField() == 0xA) { 2558 if (instr->CoprocessorField() == 0xA) {
2552 switch (instr->OpcodeField()) { 2559 switch (instr->OpcodeField()) {
2553 case 0x8: 2560 case 0x8:
2554 case 0xC: { // Load and store float to memory. 2561 case 0xA:
2562 case 0xC:
2563 case 0xE: { // Load and store single precision float to memory.
2555 int rn = instr->RnField(); 2564 int rn = instr->RnField();
2556 int vd = instr->VdField(); 2565 int vd = instr->VFPDRegCode(kSinglePrecision);
2557 int offset = instr->Immed8Field(); 2566 int offset = instr->Immed8Field();
2558 if (!instr->HasU()) { 2567 if (!instr->HasU()) {
2559 offset = -offset; 2568 offset = -offset;
2560 } 2569 }
2561 2570
2562 int32_t address = get_register(rn) + 4 * offset; 2571 int32_t address = get_register(rn) + 4 * offset;
2563 if (instr->HasL()) { 2572 if (instr->HasL()) {
2564 // Load double from memory: vldr. 2573 // Load double from memory: vldr.
2565 set_s_register_from_sinteger(vd, ReadW(address, instr)); 2574 set_s_register_from_sinteger(vd, ReadW(address, instr));
2566 } else { 2575 } else {
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
2825 uintptr_t address = *stack_slot; 2834 uintptr_t address = *stack_slot;
2826 set_register(sp, current_sp + sizeof(uintptr_t)); 2835 set_register(sp, current_sp + sizeof(uintptr_t));
2827 return address; 2836 return address;
2828 } 2837 }
2829 2838
2830 } } // namespace assembler::arm 2839 } } // namespace assembler::arm
2831 2840
2832 #endif // __arm__ 2841 #endif // __arm__
2833 2842
2834 #endif // V8_TARGET_ARCH_ARM 2843 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/disasm-arm.cc ('k') | test/cctest/test-assembler-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698