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

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

Issue 651029: Forking disassembler and simulator for Thumb2 support; (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 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 | Annotate | Revision Log
« no previous file with comments | « src/arm/simulator-arm.h ('k') | no next file » | 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 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 break; 233 break;
234 } else { 234 } else {
235 // Use sscanf to parse the individual parts of the command line. At the 235 // Use sscanf to parse the individual parts of the command line. At the
236 // moment no command expects more than two parameters. 236 // moment no command expects more than two parameters.
237 int args = SScanF(line, 237 int args = SScanF(line,
238 "%" XSTR(COMMAND_SIZE) "s " 238 "%" XSTR(COMMAND_SIZE) "s "
239 "%" XSTR(ARG_SIZE) "s " 239 "%" XSTR(ARG_SIZE) "s "
240 "%" XSTR(ARG_SIZE) "s", 240 "%" XSTR(ARG_SIZE) "s",
241 cmd, arg1, arg2); 241 cmd, arg1, arg2);
242 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { 242 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
243 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); 243 sim_->InstructionDecode(sim_->get_pc());
244 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { 244 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
245 // Execute the one instruction we broke at with breakpoints disabled. 245 // Execute the one instruction we broke at with breakpoints disabled.
246 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); 246 sim_->InstructionDecode(sim_->get_pc());
247 // Leave the debugger shell. 247 // Leave the debugger shell.
248 done = true; 248 done = true;
249 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { 249 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
250 if (args == 2) { 250 if (args == 2) {
251 int32_t value; 251 int32_t value;
252 if (strcmp(arg1, "all") == 0) { 252 if (strcmp(arg1, "all") == 0) {
253 for (int i = 0; i < kNumRegisters; i++) { 253 for (int i = 0; i < kNumRegisters; i++) {
254 value = GetRegisterValue(i); 254 value = GetRegisterValue(i);
255 PrintF("%3s: 0x%08x %10d\n", Registers::Name(i), value, value); 255 PrintF("%3s: 0x%08x %10d\n", Registers::Name(i), value, value);
256 } 256 }
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 RedoBreakpoints(); 397 RedoBreakpoints();
398 398
399 #undef COMMAND_SIZE 399 #undef COMMAND_SIZE
400 #undef ARG_SIZE 400 #undef ARG_SIZE
401 401
402 #undef STR 402 #undef STR
403 #undef XSTR 403 #undef XSTR
404 } 404 }
405 405
406 406
407
408 InstrThumb2::InstrThumb2(byte* pc)
409 : pc_(pc) {
410 instr0_ = *reinterpret_cast<uint16_t*>(Address());
411 if (instr0_ > kMax16BitThumbOpcode) {
412 instr1_ = *reinterpret_cast<uint16_t*>(
413 reinterpret_cast<uint32_t>(Address() + 2));
414 size_ = 4;
415 Decode32();
416 } else {
417 size_ = 2;
418 Decode16();
419 }
420 }
421
422 void InstrThumb2::Decode16() {
423 switch (instr0_ & 0xff80) { // bits 15 - 11
424 case B13:
425 Decode16_Rdn3Imm8(OP_CMP, VARIANT_IMMEDIATE);
426 break;
427 case B13 | B12:
428 Decode16_Rdn3Imm8(OP_ADD, VARIANT_IMMEDIATE);
429 break;
430 case B15 | B13 | B11:
431 Decode16_Rdn3Imm8(OP_ADD, VARIANT_SP_PLUS_IMMEDIATE);
432 break;
433 case B15 | B14 | B13:
434 Decode16_Imm11(OP_B, VARIANT_REGISTER);
435 break;
436 case B15 | B14 | B13 | B12 | B11:
437 Decode16_Imm11(OP_BL, VARIANT_IMMEDIATE);
438 break;
439 default:
440 UnsupportedInstruction();
441 }
442 }
443
444 void InstrThumb2::Decode32() {
445 switch (instr0_ & (0xff * B5)) {
446 case B11 | B9: // 01010000 * B5
447 Decode32_SRn4XImm3Rd4Imm2Type2Rm4(OP_AND, VARIANT_REGISTER);
448 DecodeImmShift();
449 break;
450 case B11 | B9 | B8: // 01011000 * B5
451 Decode32_SRn4XImm3Rd4Imm2Type2Rm4(OP_ADD, VARIANT_REGISTER);
452 DecodeImmShift();
453 break;
454 case B12 | B8 | B7 | B5: // 10x01101 * B5;
455 case B12 | B10 | B8 | B7 | B5: // B10 is part of Imm.
456 Decode32_ImmX5SRn4XImm3Rd4Imm8(OP_SUB, VARIANT_IMMEDIATE);
457 ThumbExpandImm();
458 break;
459
460 default:
461 UnsupportedInstruction();
462 }
463 }
464
465 void InstrThumb2::UnsupportedInstruction() {
466 if (size_ == 2) {
467 PrintF("Unsupported 16bit instruction %x\n", instr0_);
468 } else {
469 PrintF("Unsupported 32bit instruction %x:%x\n", instr0_, instr1_);
470 }
471 op_ = OP_UNSUPPORTED;
472 }
473
474 void InstrThumb2::Decode16_Rdn3Imm8(Operation op, OpVariant variant) {
475 op_ = op;
476 variant_ = variant;
477 s_ = AUTO;
478
479 imm_ = Bits0(7, 0);
480 rd_ = rn_ = Bits0(10, 8);
481 }
482
483 void InstrThumb2::Decode16_Imm11(Operation op, OpVariant variant) {
484 op_ = op;
485 variant_ = variant;
486 s_ = AUTO;
487
488 imm_ = Bits0(10, 0);
489 }
490
491 void InstrThumb2::Decode32_SRn4XImm3Rd4Imm2Type2Rm4(Operation op,
492 OpVariant variant) {
493 op_ = op;
494 variant_ = variant;
495
496 s_ = Bit0(4);
497 rn_ = Bits0(3, 0);
498 imm_ = Bits1(14, 12) * B2 | Bits1(7, 6);
499 rd_ = Bits1(11, 8);
500 type_ = Bits1(5, 4);
501 rm_ = Bits1(3, 0);
502 }
503
504 void InstrThumb2::Decode32_ImmX5SRn4XImm3Rd4Imm8(Operation op,
505 OpVariant variant) {
506 op_ = op;
507 variant_ = variant;
508
509 s_ = Bit0(4);
510 imm_ = Bit0(10) * B11 | Bits1(14, 12) * B8 | Bits1(7, 0);
511 rn_ = Bits0(3, 0);
512 rd_ = Bits1(11, 8);
513 }
514
515 void InstrThumb2::DecodeImmShift() {
516 if (imm_ == 0) {
517 switch (type_) {
518 case LSL:
519 type_ = no_shift;
520 break;
521 case ASR:
522 case LSR:
523 imm_ = 32;
524 break;
525 case ROR:
526 type_ = RRX;
527 imm_ = 1;
528 break;
529 default:
530 UnsupportedInstruction();
531 }
532 }
533 }
534
535 void InstrThumb2::ThumbExpandImm() {
536 if (imm_ > 255) {
537 // TODO(haustein) Support thumb2 immediate shift here..
538 UnsupportedInstruction();
539 }
540 }
541
542
407 // Create one simulator per thread and keep it in thread local storage. 543 // Create one simulator per thread and keep it in thread local storage.
408 static v8::internal::Thread::LocalStorageKey simulator_key; 544 static v8::internal::Thread::LocalStorageKey simulator_key;
409 545
410 546
411 bool Simulator::initialized_ = false; 547 bool Simulator::initialized_ = false;
412 548
413 549
414 void Simulator::Initialize() { 550 void Simulator::Initialize() {
415 if (initialized_) return; 551 if (initialized_) return;
416 simulator_key = v8::internal::Thread::CreateThreadLocalKey(); 552 simulator_key = v8::internal::Thread::CreateThreadLocalKey();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 inexact_vfp_flag_ = false; 595 inexact_vfp_flag_ = false;
460 596
461 // The sp is initialized to point to the bottom (high address) of the 597 // The sp is initialized to point to the bottom (high address) of the
462 // allocated stack area. To be safe in potential stack underflows we leave 598 // allocated stack area. To be safe in potential stack underflows we leave
463 // some buffer below. 599 // some buffer below.
464 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64; 600 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64;
465 // The lr and pc are initialized to a known bad value that will cause an 601 // The lr and pc are initialized to a known bad value that will cause an
466 // access violation if the simulator ever tries to execute it. 602 // access violation if the simulator ever tries to execute it.
467 registers_[pc] = bad_lr; 603 registers_[pc] = bad_lr;
468 registers_[lr] = bad_lr; 604 registers_[lr] = bad_lr;
605
469 InitializeCoverage(); 606 InitializeCoverage();
470 } 607 }
471 608
472 609
473 // When the generated code calls an external reference we need to catch that in 610 // When the generated code calls an external reference we need to catch that in
474 // the simulator. The external reference will be a function compiled for the 611 // the simulator. The external reference will be a function compiled for the
475 // host architecture. We need to call that function instead of trying to 612 // host architecture. We need to call that function instead of trying to
476 // execute it with the simulator. We do that by redirecting the external 613 // execute it with the simulator. We do that by redirecting the external
477 // reference to a swi (software-interrupt) instruction that is handled by 614 // reference to a swi (software-interrupt) instruction that is handled by
478 // the simulator. We write the original destination of the jump just at a known 615 // the simulator. We write the original destination of the jump just at a known
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 pc_modified_ = true; 687 pc_modified_ = true;
551 } 688 }
552 registers_[reg] = value; 689 registers_[reg] = value;
553 } 690 }
554 691
555 692
556 // Get the register from the architecture state. This function does handle 693 // Get the register from the architecture state. This function does handle
557 // the special case of accessing the PC register. 694 // the special case of accessing the PC register.
558 int32_t Simulator::get_register(int reg) const { 695 int32_t Simulator::get_register(int reg) const {
559 ASSERT((reg >= 0) && (reg < num_registers)); 696 ASSERT((reg >= 0) && (reg < num_registers));
560 return registers_[reg] + ((reg == pc) ? Instr::kPCReadOffset : 0); 697 if (reg == pc) {
698 return registers_[reg] + (InThumbMode() ? Instr::kPCReadOffsetThumb
699 : Instr::kPCReadOffset);
700 }
701 return registers_[reg];
561 } 702 }
562 703
563 704
564 // Raw access to the PC register. 705 // Raw access to the PC register.
565 void Simulator::set_pc(int32_t value) { 706 void Simulator::set_pc(int32_t value) {
566 pc_modified_ = true; 707 pc_modified_ = true;
567 registers_[pc] = value; 708 registers_[pc] = value;
568 } 709 }
569 710
570 711
(...skipping 1532 matching lines...) Expand 10 before | Expand all | Expand 10 after
2103 break; 2244 break;
2104 } 2245 }
2105 default: 2246 default:
2106 UNIMPLEMENTED(); // Not used by V8. 2247 UNIMPLEMENTED(); // Not used by V8.
2107 break; 2248 break;
2108 } 2249 }
2109 } 2250 }
2110 } 2251 }
2111 2252
2112 2253
2113 // Executes the current instruction. 2254 void Simulator::InstructionDecode(int32_t adr) {
2114 void Simulator::InstructionDecode(Instr* instr) {
2115 pc_modified_ = false;
2116 if (::v8::internal::FLAG_trace_sim) { 2255 if (::v8::internal::FLAG_trace_sim) {
2117 disasm::NameConverter converter; 2256 disasm::NameConverter converter;
2118 disasm::Disassembler dasm(converter); 2257 disasm::Disassembler dasm(converter);
2119 // use a reasonably large buffer 2258 // use a reasonably large buffer
2120 v8::internal::EmbeddedVector<char, 256> buffer; 2259 v8::internal::EmbeddedVector<char, 256> buffer;
2121 dasm.InstructionDecode(buffer, 2260 dasm.InstructionDecode(buffer,
2122 reinterpret_cast<byte*>(instr)); 2261 reinterpret_cast<byte*>(adr));
2123 PrintF(" 0x%08x %s\n", instr, buffer.start()); 2262 PrintF(" 0x%08x %s\n", adr, buffer.start());
2124 } 2263 }
2264 if ((adr & 1) == 1) {
2265 InstructionDecodeThumb2(reinterpret_cast<byte*>(adr));
2266 } else {
2267 InstructionDecodeArm(reinterpret_cast<Instr*>(adr));
2268 }
2269 }
2270
2271 int32_t Simulator::GetOperand2(const InstrThumb2& instr, bool* carry_out) {
2272 switch (instr.Variant()) {
2273 case VARIANT_IMMEDIATE:
2274 return instr.Imm();
2275
2276 case VARIANT_REGISTER:
2277 return GetRmShiftImm(instr, carry_out);
2278
2279 default:
2280 UNIMPLEMENTED();
2281 return -1;
2282 }
2283 }
2284
2285 int32_t Simulator::GetRmShiftImm(const InstrThumb2& instr, bool* carry_out) {
2286 Shift shift = (Shift) instr.Type();
2287 int shift_amount = instr.Imm();
2288 int32_t result = get_register(instr.Rm());
2289
2290 switch (shift) {
2291 case no_shift:
2292 break;
2293
2294 case ASR: {
2295 ASSERT(shift_amount > 0);
2296 result >>= (shift_amount - 1);
2297 *carry_out = (result & 1) == 1;
2298 result >>= 1;
2299 break;
2300 }
2301
2302 case LSL: {
2303 ASSERT(shift_amount > 0);
2304 result <<= (shift_amount - 1);
2305 *carry_out = (result < 0);
2306 result <<= 1;
2307 break;
2308 }
2309
2310 case LSR: {
2311 uint32_t uresult = static_cast<uint32_t>(result);
2312 ASSERT(shift_amount > 0);
2313 uresult >>= (shift_amount - 1);
2314 *carry_out = (uresult & 1) == 1;
2315 uresult >>= 1;
2316 result = static_cast<int32_t>(uresult);
2317 break;
2318 }
2319
2320 case RRX:
2321 case ROR: {
2322 UNIMPLEMENTED();
2323 break;
2324 }
2325
2326 default: {
2327 UNREACHABLE();
2328 break;
2329 }
2330 }
2331 return result;
2332 }
2333
2334
2335
2336 void Simulator::InstructionDecodeThumb2(byte* adr) {
2337 pc_modified_ = false;
2338 InstrThumb2 instr(adr);
2339 bool shifter_carry_out = 0;
2340 int32_t alu_out;
2341 int32_t operand2;
2342
2343 int32_t rn_val = get_register(instr.Rn());
2344 switch (instr.Op()) {
2345 case OP_AND:
2346 alu_out = rn_val & GetOperand2(instr, &shifter_carry_out);
2347 set_register(instr.Rd(), alu_out);
2348 if (instr.HasS()) {
2349 SetNZFlags(alu_out);
2350 SetCFlag(shifter_carry_out);
2351 }
2352 break;
2353 case OP_ADD:
2354 operand2 = GetOperand2(instr, &shifter_carry_out);
2355 alu_out = rn_val + operand2;
2356 set_register(instr.Rd(), alu_out);
2357 if (instr.HasS()) {
2358 SetNZFlags(alu_out);
2359 SetCFlag(CarryFrom(rn_val, operand2));
2360 SetVFlag(OverflowFrom(alu_out, rn_val, operand2, true));
2361 }
2362 break;
2363
2364 case OP_SUB:
2365 operand2 = GetOperand2(instr, &shifter_carry_out);
2366 alu_out = rn_val - operand2;
2367 set_register(instr.Rd(), alu_out);
2368 if (instr.HasS()) {
2369 SetNZFlags(alu_out);
2370 SetCFlag(!BorrowFrom(rn_val, operand2));
2371 SetVFlag(OverflowFrom(alu_out, rn_val, operand2, false));
2372 }
2373 break;
2374
2375 default:
2376 PrintF("Unrecogized Thumb Instruction");
2377 UNIMPLEMENTED();
2378 }
2379 if (!pc_modified_) {
2380 set_register(pc, reinterpret_cast<int32_t>(adr) + instr.Size());
2381 }
2382 }
2383
2384 // Executes the current instruction.
2385 void Simulator::InstructionDecodeArm(Instr* instr) {
2386 pc_modified_ = false;
2125 if (instr->ConditionField() == special_condition) { 2387 if (instr->ConditionField() == special_condition) {
2126 DecodeUnconditional(instr); 2388 DecodeUnconditional(instr);
2127 } else if (ConditionallyExecute(instr)) { 2389 } else if (ConditionallyExecute(instr)) {
2128 switch (instr->TypeField()) { 2390 switch (instr->TypeField()) {
2129 case 0: 2391 case 0:
2130 case 1: { 2392 case 1: {
2131 DecodeType01(instr); 2393 DecodeType01(instr);
2132 break; 2394 break;
2133 } 2395 }
2134 case 2: { 2396 case 2: {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2169 2431
2170 void Simulator::Execute() { 2432 void Simulator::Execute() {
2171 // Get the PC to simulate. Cannot use the accessor here as we need the 2433 // Get the PC to simulate. Cannot use the accessor here as we need the
2172 // raw PC value and not the one used as input to arithmetic instructions. 2434 // raw PC value and not the one used as input to arithmetic instructions.
2173 int program_counter = get_pc(); 2435 int program_counter = get_pc();
2174 2436
2175 if (::v8::internal::FLAG_stop_sim_at == 0) { 2437 if (::v8::internal::FLAG_stop_sim_at == 0) {
2176 // Fast version of the dispatch loop without checking whether the simulator 2438 // Fast version of the dispatch loop without checking whether the simulator
2177 // should be stopping at a particular executed instruction. 2439 // should be stopping at a particular executed instruction.
2178 while (program_counter != end_sim_pc) { 2440 while (program_counter != end_sim_pc) {
2179 Instr* instr = reinterpret_cast<Instr*>(program_counter);
2180 icount_++; 2441 icount_++;
2181 InstructionDecode(instr); 2442 InstructionDecode(program_counter);
2182 program_counter = get_pc(); 2443 program_counter = get_pc();
2183 } 2444 }
2184 } else { 2445 } else {
2185 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when 2446 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
2186 // we reach the particular instuction count. 2447 // we reach the particular instuction count.
2187 while (program_counter != end_sim_pc) { 2448 while (program_counter != end_sim_pc) {
2188 Instr* instr = reinterpret_cast<Instr*>(program_counter);
2189 icount_++; 2449 icount_++;
2190 if (icount_ == ::v8::internal::FLAG_stop_sim_at) { 2450 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
2191 Debugger dbg(this); 2451 Debugger dbg(this);
2192 dbg.Debug(); 2452 dbg.Debug();
2193 } else { 2453 } else {
2194 InstructionDecode(instr); 2454 InstructionDecode(program_counter);
2195 } 2455 }
2196 program_counter = get_pc(); 2456 program_counter = get_pc();
2197 } 2457 }
2198 } 2458 }
2199 } 2459 }
2200 2460
2201 2461
2202 int32_t Simulator::Call(byte* entry, int argument_count, ...) { 2462 int32_t Simulator::Call(byte* entry, int argument_count, ...) {
2203 va_list parameters; 2463 va_list parameters;
2204 va_start(parameters, argument_count); 2464 va_start(parameters, argument_count);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
2303 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); 2563 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
2304 uintptr_t address = *stack_slot; 2564 uintptr_t address = *stack_slot;
2305 set_register(sp, current_sp + sizeof(uintptr_t)); 2565 set_register(sp, current_sp + sizeof(uintptr_t));
2306 return address; 2566 return address;
2307 } 2567 }
2308 2568
2309 2569
2310 } } // namespace assembler::arm 2570 } } // namespace assembler::arm
2311 2571
2312 #endif // !defined(__arm__) 2572 #endif // !defined(__arm__)
OLDNEW
« no previous file with comments | « src/arm/simulator-arm.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698