343 // Determine the mode |
343 // Determine the mode |
344 ReturnIfError(CurrentArchMode(cpsr,mode)); |
344 ReturnIfError(CurrentArchMode(cpsr,mode)); |
345 |
345 |
346 // Decode instruction based on current CPU mode |
346 // Decode instruction based on current CPU mode |
347 switch(mode) |
347 switch(mode) |
348 { |
348 { |
349 case Debug::EArmMode: |
349 case Debug::EArmMode: |
350 { |
350 { |
351 // Obtain the current instruction bit pattern |
351 // Obtain the current instruction bit pattern |
352 TUint32 inst; |
352 TUint32 inst; |
353 ReturnIfError(CurrentInstruction(aThread,inst)); |
353 ReturnIfError(CurrentInstruction(aThread,inst)); |
354 |
354 |
355 LOG_MSG2("Current instruction: %x", inst); |
355 LOG_MSG2("Current instruction: %x", inst); |
356 |
356 |
357 // check the conditions to see if this will actually get executed |
357 // check the conditions to see if this will actually get executed |
358 if (IsExecuted(((inst>>28) & 0x0000000F), aStatusRegister)) |
358 if (IsExecuted(((inst>>28) & 0x0000000F), aStatusRegister)) |
359 { |
359 { |
360 switch(arm_opcode(inst)) // bits 27-25 |
360 switch(arm_opcode(inst)) // bits 27-25 |
361 { |
361 { |
362 case 0: |
362 case 0: |
363 { |
363 { |
364 switch((inst & 0x00000010) >> 4) // bit 4 |
364 switch((inst & 0x00000010) >> 4) // bit 4 |
365 { |
365 { |
366 case 0: |
366 case 0: |
367 { |
367 { |
368 switch((inst & 0x01800000) >> 23) // bits 24-23 |
368 switch((inst & 0x01800000) >> 23) // bits 24-23 |
369 { |
369 { |
370 case 2: |
370 case 2: |
371 { |
371 { |
372 // move to/from status register. pc updates not allowed |
372 // move to/from status register. pc updates not allowed |
373 // or TST, TEQ, CMP, CMN which don't modify the PC |
373 // or TST, TEQ, CMP, CMN which don't modify the PC |
374 break; |
374 break; |
375 } |
375 } |
376 default: |
376 default: |
377 { |
377 { |
378 // Data processing immediate shift |
378 // Data processing immediate shift |
379 if (arm_rd(inst) == PC_REGISTER) |
379 if (arm_rd(inst) == PC_REGISTER) |
380 { |
380 { |
381 TUint32 rn = aCurrentPC + 8; |
381 TUint32 rn = aCurrentPC + 8; |
382 if (arm_rn(inst) != PC_REGISTER) // bits 19-16 |
382 if (arm_rn(inst) != PC_REGISTER) // bits 19-16 |
383 { |
383 { |
384 err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), rn); |
384 err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), rn); |
385 if(err != KErrNone) |
385 if(err != KErrNone) |
|
386 { |
|
387 LOG_MSG2("Non-zero error code discarded: %d", err); |
|
388 } |
|
389 } |
|
390 |
|
391 TUint32 shifter = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister); |
|
392 |
|
393 DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress); |
|
394 } |
|
395 break; |
|
396 } |
|
397 } |
|
398 break; |
|
399 } |
|
400 case 1: |
|
401 { |
|
402 switch((inst & 0x00000080) >> 7) // bit 7 |
|
403 { |
|
404 case 0: |
|
405 { |
|
406 switch((inst & 0x01900000) >> 20) // bits 24-23 and bit 20 |
|
407 { |
|
408 case 0x10: |
386 { |
409 { |
387 LOG_MSG2("Non-zero error code discarded: %d", err); |
|
388 } |
|
389 } |
|
390 |
|
391 TUint32 shifter = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister); |
|
392 |
|
393 DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress); |
|
394 } |
|
395 break; |
|
396 } |
|
397 } |
|
398 break; |
|
399 } |
|
400 case 1: |
|
401 { |
|
402 switch((inst & 0x00000080) >> 7) // bit 7 |
|
403 { |
|
404 case 0: |
|
405 { |
|
406 switch((inst & 0x01900000) >> 20) // bits 24-23 and bit 20 |
|
407 { |
|
408 case 0x10: |
|
409 { |
|
410 // from figure 3-3 |
410 // from figure 3-3 |
411 switch((inst & 0x000000F0) >> 4) // bits 7-4 |
411 switch((inst & 0x000000F0) >> 4) // bits 7-4 |
412 { |
412 { |
413 case 1: |
413 case 1: |
414 { |
414 { |
415 if (((inst & 0x00400000) >> 22) == 0) // bit 22 |
415 if (((inst & 0x00400000) >> 22) == 0) // bit 22 |
416 { |
416 { |
417 // BX |
417 // BX |
418 // this is a strange case. normally this is used in the epilogue to branch the the link |
418 // this is a strange case. normally this is used in the epilogue to branch the the link |
419 // register. sometimes it is used to call a function, and the LR is stored in the previous |
419 // register. sometimes it is used to call a function, and the LR is stored in the previous |
420 // instruction. since what we want to do is different for the two cases when stepping over, |
420 // instruction. since what we want to do is different for the two cases when stepping over, |
421 // we need to read the previous instruction to see what we should do |
421 // we need to read the previous instruction to see what we should do |
422 err = iChannel->ReadKernelRegisterValue(aThread, (inst & 0x0000000F), breakAddress); |
422 err = iChannel->ReadKernelRegisterValue(aThread, (inst & 0x0000000F), breakAddress); |
423 if(err != KErrNone) |
423 if(err != KErrNone) |
|
424 { |
|
425 LOG_MSG2("Non-zero error code discarded: %d", err); |
|
426 } |
|
427 |
|
428 if ((breakAddress & 0x00000001) == 1) |
|
429 { |
|
430 aChangingModes = ETrue; |
|
431 } |
|
432 |
|
433 breakAddress &= 0xFFFFFFFE; |
|
434 } |
|
435 break; |
|
436 } |
|
437 case 3: |
|
438 { |
|
439 // BLX |
424 { |
440 { |
425 LOG_MSG2("Non-zero error code discarded: %d", err); |
|
426 } |
|
427 |
|
428 if ((breakAddress & 0x00000001) == 1) |
|
429 { |
|
430 aChangingModes = ETrue; |
|
431 } |
|
432 |
|
433 breakAddress &= 0xFFFFFFFE; |
|
434 } |
|
435 break; |
|
436 } |
|
437 case 3: |
|
438 { |
|
439 // BLX |
|
440 { |
|
441 err = iChannel->ReadKernelRegisterValue(aThread, (inst & 0x0000000F), breakAddress); |
441 err = iChannel->ReadKernelRegisterValue(aThread, (inst & 0x0000000F), breakAddress); |
442 if(err != KErrNone) |
442 if(err != KErrNone) |
443 { |
443 { |
444 LOG_MSG2("Non-zero error code discarded: %d", err); |
444 LOG_MSG2("Non-zero error code discarded: %d", err); |
445 } |
445 } |
446 |
446 |
447 if ((breakAddress & 0x00000001) == 1) |
447 if ((breakAddress & 0x00000001) == 1) |
448 { |
448 { |
449 aChangingModes = ETrue; |
449 aChangingModes = ETrue; |
450 } |
450 } |
451 |
451 |
452 breakAddress &= 0xFFFFFFFE; |
452 breakAddress &= 0xFFFFFFFE; |
|
453 } |
|
454 break; |
453 } |
455 } |
454 break; |
|
455 } |
|
456 default: |
456 default: |
457 { |
457 { |
458 // either doesn't modify the PC or it is illegal to |
458 // either doesn't modify the PC or it is illegal to |
459 break; |
459 break; |
|
460 } |
460 } |
461 } |
|
462 break; |
461 } |
463 } |
462 break; |
|
463 } |
|
464 default: |
464 default: |
465 { |
465 { |
466 // Data processing register shift |
466 // Data processing register shift |
467 if (((inst & 0x01800000) >> 23) == 2) // bits 24-23 |
467 if (((inst & 0x01800000) >> 23) == 2) // bits 24-23 |
468 { |
468 { |
469 // TST, TEQ, CMP, CMN don't modify the PC |
469 // TST, TEQ, CMP, CMN don't modify the PC |
470 } |
470 } |
471 else if (arm_rd(inst) == PC_REGISTER) |
471 else if (arm_rd(inst) == PC_REGISTER) |
472 { |
472 { |
473 // destination register is the PC |
473 // destination register is the PC |
474 TUint32 rn = aCurrentPC + 8; |
474 TUint32 rn = aCurrentPC + 8; |
475 if (arm_rn(inst) != PC_REGISTER) // bits 19-16 |
475 if (arm_rn(inst) != PC_REGISTER) // bits 19-16 |
476 { |
476 { |
477 err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), rn); |
477 err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), rn); |
478 if(err != KErrNone) |
478 if(err != KErrNone) |
479 { |
479 { |
480 LOG_MSG2("Non-zero error code discarded: %d", err); |
480 LOG_MSG2("Non-zero error code discarded: %d", err); |
|
481 } |
481 } |
482 } |
482 } |
|
483 |
483 |
484 TUint32 shifter = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister); |
484 TUint32 shifter = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister); |
485 |
485 |
486 DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress); |
486 DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress); |
|
487 } |
|
488 break; |
487 } |
489 } |
488 break; |
|
489 } |
490 } |
|
491 break; |
490 } |
492 } |
491 break; |
|
492 } |
|
493 default: |
493 default: |
494 { |
494 { |
495 // from figure 3-2, updates to the PC illegal |
495 // from figure 3-2, updates to the PC illegal |
496 break; |
496 break; |
|
497 } |
497 } |
498 } |
|
499 break; |
498 } |
500 } |
499 break; |
501 } |
500 } |
|
501 } |
|
502 break; |
502 break; |
503 } |
503 } |
504 case 1: |
504 case 1: |
505 { |
505 { |
506 if (((inst & 0x01800000) >> 23) == 2) // bits 24-23 |
506 if (((inst & 0x01800000) >> 23) == 2) // bits 24-23 |
507 { |
507 { |
508 // cannot modify the PC |
508 // cannot modify the PC |
509 break; |
509 break; |
510 } |
510 } |
511 else if (arm_rd(inst) == PC_REGISTER) |
511 else if (arm_rd(inst) == PC_REGISTER) |
512 { |
512 { |
513 // destination register is the PC |
513 // destination register is the PC |
514 TUint32 rn; |
514 TUint32 rn; |
515 err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), rn); // bits 19-16 |
515 err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), rn); // bits 19-16 |
516 if(err != KErrNone) |
516 if(err != KErrNone) |
517 { |
517 { |
518 LOG_MSG2("Non-zero error code discarded: %d", err); |
518 LOG_MSG2("Non-zero error code discarded: %d", err); |
519 } |
519 } |
520 TUint32 shifter = ((arm_data_imm(inst) >> arm_data_rot(inst)) | (arm_data_imm(inst) << (32 - arm_data_rot(inst)))) & 0xffffffff; |
520 TUint32 shifter = ((arm_data_imm(inst) >> arm_data_rot(inst)) | (arm_data_imm(inst) << (32 - arm_data_rot(inst)))) & 0xffffffff; |
521 |
521 |
522 DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress); |
522 DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress); |
523 } |
523 } |
524 break; |
524 break; |
525 } |
525 } |
526 case 2: |
526 case 2: |
527 { |
527 { |
528 // load/store immediate offset |
528 // load/store immediate offset |
529 if (arm_load(inst)) // bit 20 |
529 if (arm_load(inst)) // bit 20 |
530 { |
530 { |
531 // loading a register from memory |
531 // loading a register from memory |
532 if (arm_rd(inst) == PC_REGISTER) |
532 if (arm_rd(inst) == PC_REGISTER) |
533 { |
533 { |
534 // loading the PC register |
534 // loading the PC register |
535 TUint32 base; |
535 TUint32 base; |
536 err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), base); |
536 err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), base); |
537 if(err != KErrNone) |
537 if(err != KErrNone) |
538 { |
538 { |
539 LOG_MSG2("Non-zero error code discarded: %d", err); |
539 LOG_MSG2("Non-zero error code discarded: %d", err); |
540 } |
540 } |
541 |
541 |
542 /* Note: At runtime the PC would be 8 further on |
542 /* Note: At runtime the PC would be 8 further on |
543 */ |
543 */ |
544 if (arm_rn(inst) == PC_REGISTER) |
544 if (arm_rn(inst) == PC_REGISTER) |
545 { |
545 { |
546 base = aCurrentPC + 8; |
546 base = aCurrentPC + 8; |
547 } |
547 } |
548 |
548 |
549 TUint32 offset = 0; |
549 TUint32 offset = 0; |
550 |
550 |
551 if (arm_single_pre(inst)) |
551 if (arm_single_pre(inst)) |
552 { |
552 { |
553 // Pre-indexing |
553 // Pre-indexing |
554 offset = arm_single_imm(inst); |
554 offset = arm_single_imm(inst); |
555 |
555 |
556 if (arm_single_u(inst)) |
556 if (arm_single_u(inst)) |
557 { |
557 { |
558 base += offset; |
558 base += offset; |
|
559 } |
|
560 else |
|
561 { |
|
562 base -= offset; |
|
563 } |
559 } |
564 } |
560 else |
|
561 { |
|
562 base -= offset; |
|
563 } |
|
564 } |
|
565 |
565 |
566 TBuf8<4> destination; |
566 TBuf8<4> destination; |
567 err = iChannel->DoReadMemory(aThread, base, 4, destination); |
567 err = iChannel->DoReadMemory(aThread, base, 4, destination); |
568 |
568 |
569 if (KErrNone == err) |
569 if (KErrNone == err) |
570 { |
570 { |
571 breakAddress = *(TUint32 *)destination.Ptr(); |
571 breakAddress = *(TUint32 *)destination.Ptr(); |
572 |
572 |
573 if ((breakAddress & 0x00000001) == 1) |
573 if ((breakAddress & 0x00000001) == 1) |
|
574 { |
|
575 aChangingModes = ETrue; |
|
576 } |
|
577 breakAddress &= 0xFFFFFFFE; |
|
578 } |
|
579 else |
574 { |
580 { |
575 aChangingModes = ETrue; |
581 LOG_MSG("Error reading memory in decoding step instruction"); |
576 } |
582 } |
577 breakAddress &= 0xFFFFFFFE; |
|
578 } |
583 } |
579 else |
584 } |
580 { |
|
581 LOG_MSG("Error reading memory in decoding step instruction"); |
|
582 } |
|
583 } |
|
584 } |
|
585 break; |
585 break; |
586 } |
586 } |
587 case 3: |
587 case 3: |
588 { |
588 { |
589 if (((inst & 0xF0000000) != 0xF0000000) && ((inst & 0x00000010) == 0)) |
589 if (((inst & 0xF0000000) != 0xF0000000) && ((inst & 0x00000010) == 0)) |
590 { |
590 { |
591 // load/store register offset |
591 // load/store register offset |
592 if (arm_load(inst)) // bit 20 |
592 if (arm_load(inst)) // bit 20 |
593 { |
593 { |
594 // loading a register from memory |
594 // loading a register from memory |
595 if (arm_rd(inst) == PC_REGISTER) |
595 if (arm_rd(inst) == PC_REGISTER) |
596 { |
596 { |
597 // loading the PC register |
597 // loading the PC register |
598 TUint32 base = 0; |
598 TUint32 base = 0; |
599 if(arm_rn(inst) == PC_REGISTER) |
599 if(arm_rn(inst) == PC_REGISTER) |
600 { |
600 { |
601 base = aCurrentPC + 8; |
601 base = aCurrentPC + 8; |
602 } |
602 } |
603 else |
603 else |
604 { |
604 { |
605 err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), base); |
605 err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), base); |
606 if(err != KErrNone) |
606 if(err != KErrNone) |
|
607 { |
|
608 LOG_MSG2("Non-zero error code discarded: %d", err); |
|
609 } |
|
610 } |
|
611 |
|
612 TUint32 offset = 0; |
|
613 |
|
614 if (arm_single_pre(inst)) |
607 { |
615 { |
608 LOG_MSG2("Non-zero error code discarded: %d", err); |
616 offset = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister); |
|
617 |
|
618 if (arm_single_u(inst)) |
|
619 { |
|
620 base += offset; |
|
621 } |
|
622 else |
|
623 { |
|
624 base -= offset; |
|
625 } |
|
626 } |
|
627 |
|
628 TBuf8<4> destination; |
|
629 err = iChannel->DoReadMemory(aThread, base, 4, destination); |
|
630 |
|
631 if (KErrNone == err) |
|
632 { |
|
633 breakAddress = *(TUint32 *)destination.Ptr(); |
|
634 |
|
635 if ((breakAddress & 0x00000001) == 1) |
|
636 { |
|
637 aChangingModes = ETrue; |
|
638 } |
|
639 breakAddress &= 0xFFFFFFFE; |
|
640 } |
|
641 else |
|
642 { |
|
643 LOG_MSG("Error reading memory in decoding step instruction"); |
609 } |
644 } |
610 } |
645 } |
611 |
|
612 TUint32 offset = 0; |
|
613 |
|
614 if (arm_single_pre(inst)) |
|
615 { |
|
616 offset = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister); |
|
617 |
|
618 if (arm_single_u(inst)) |
|
619 { |
|
620 base += offset; |
|
621 } |
|
622 else |
|
623 { |
|
624 base -= offset; |
|
625 } |
|
626 } |
|
627 |
|
628 TBuf8<4> destination; |
|
629 err = iChannel->DoReadMemory(aThread, base, 4, destination); |
|
630 |
|
631 if (KErrNone == err) |
|
632 { |
|
633 breakAddress = *(TUint32 *)destination.Ptr(); |
|
634 |
|
635 if ((breakAddress & 0x00000001) == 1) |
|
636 { |
|
637 aChangingModes = ETrue; |
|
638 } |
|
639 breakAddress &= 0xFFFFFFFE; |
|
640 } |
|
641 else |
|
642 { |
|
643 LOG_MSG("Error reading memory in decoding step instruction"); |
|
644 } |
|
645 } |
646 } |
646 } |
647 } |
647 } |
|
648 break; |
648 break; |
649 } |
649 } |
650 case 4: |
650 case 4: |
651 { |
651 { |
652 if ((inst & 0xF0000000) != 0xF0000000) |
652 if ((inst & 0xF0000000) != 0xF0000000) |
653 { |
653 { |
654 // load/store multiple |
654 // load/store multiple |
655 if (arm_load(inst)) // bit 20 |
655 if (arm_load(inst)) // bit 20 |
656 { |
656 { |
657 // loading a register from memory |
657 // loading a register from memory |
658 if (((inst & 0x00008000) >> 15)) |
658 if (((inst & 0x00008000) >> 15)) |
659 { |
659 { |
660 // loading the PC register |
660 // loading the PC register |
661 TInt offset = 0; |
661 TInt offset = 0; |
662 if (arm_block_u(inst)) |
662 if (arm_block_u(inst)) |
663 { |
663 { |
664 TUint32 reglist = arm_block_reglist(inst); |
664 TUint32 reglist = arm_block_reglist(inst); |
665 offset = iChannel->Bitcount(reglist) * 4 - 4; |
665 offset = iChannel->Bitcount(reglist) * 4 - 4; |
666 if (arm_block_pre(inst)) |
666 if (arm_block_pre(inst)) |
667 offset += 4; |
667 offset += 4; |
668 } |
668 } |
669 else if (arm_block_pre(inst)) |
669 else if (arm_block_pre(inst)) |
670 { |
670 { |
671 offset = -4; |
671 offset = -4; |
672 } |
672 } |
673 |
673 |
674 TUint32 temp = 0; |
674 TUint32 temp = 0; |
675 err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), temp); |
675 err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), temp); |
676 if(err != KErrNone) |
676 if(err != KErrNone) |
677 { |
677 { |
678 LOG_MSG2("Non-zero error code discarded: %d", err); |
678 LOG_MSG2("Non-zero error code discarded: %d", err); |
679 } |
679 } |
680 |
680 |
681 temp += offset; |
681 temp += offset; |
682 |
682 |
683 TBuf8<4> destination; |
683 TBuf8<4> destination; |
684 err = iChannel->DoReadMemory(aThread, temp, 4, destination); |
684 err = iChannel->DoReadMemory(aThread, temp, 4, destination); |
685 |
685 |
686 if (KErrNone == err) |
686 if (KErrNone == err) |
687 { |
687 { |
688 breakAddress = *(TUint32 *)destination.Ptr(); |
688 breakAddress = *(TUint32 *)destination.Ptr(); |
689 if ((breakAddress & 0x00000001) == 1) |
689 if ((breakAddress & 0x00000001) == 1) |
|
690 { |
|
691 aChangingModes = ETrue; |
|
692 } |
|
693 breakAddress &= 0xFFFFFFFE; |
|
694 } |
|
695 else |
690 { |
696 { |
691 aChangingModes = ETrue; |
697 LOG_MSG("Error reading memory in decoding step instruction"); |
692 } |
698 } |
693 breakAddress &= 0xFFFFFFFE; |
|
694 } |
|
695 else |
|
696 { |
|
697 LOG_MSG("Error reading memory in decoding step instruction"); |
|
698 } |
699 } |
699 } |
700 } |
700 } |
701 } |
701 } |
|
702 break; |
702 break; |
703 } |
703 } |
704 case 5: |
704 case 5: |
705 { |
705 { |
706 if ((inst & 0xF0000000) == 0xF0000000) |
706 if ((inst & 0xF0000000) == 0xF0000000) |
707 { |
707 { |
708 // BLX |
708 // BLX |
709 { |
709 breakAddress = (TUint32)arm_instr_b_dest(inst, aCurrentPC); |
710 breakAddress = (TUint32)arm_instr_b_dest(inst, aCurrentPC); |
710 |
711 |
711 // Unconditionally change into Thumb mode |
712 // Unconditionally change into Thumb mode |
712 aChangingModes = ETrue; |
713 aChangingModes = ETrue; |
713 breakAddress &= 0xFFFFFFFE; |
714 |
714 } |
715 breakAddress &= 0xFFFFFFFE; |
|
716 } |
|
717 } |
|
718 else |
715 else |
719 { |
716 { |
720 if ((inst & 0x01000000)) // bit 24 |
717 if ((inst & 0x01000000)) // bit 24 |
721 { |
718 { |
722 // BL |
719 // BL |
723 { |
|
724 breakAddress = (TUint32)arm_instr_b_dest(inst, aCurrentPC); |
720 breakAddress = (TUint32)arm_instr_b_dest(inst, aCurrentPC); |
725 } |
721 } |
726 } |
|
727 else |
722 else |
728 { |
723 { |
729 // B |
724 // B |
730 breakAddress = (TUint32)arm_instr_b_dest(inst, aCurrentPC); |
725 breakAddress = (TUint32)arm_instr_b_dest(inst, aCurrentPC); |
731 } |
726 } |
732 } |
727 } |
733 break; |
728 break; |
734 } |
729 } // case 5 |
735 } |
730 } //switch(arm_opcode(inst)) // bits 27-25 |
736 } |
731 } // if (IsExecuted(((inst>>28) & 0x0000000F), aStatusRegister)) |
737 } |
732 } // case Debug::EArmMode: |
738 break; |
733 break; |
739 |
734 |
740 case Debug::EThumbMode: |
735 case Debug::EThumbMode: |
741 { |
736 { |
742 // Thumb Mode |
737 // Thumb Mode |
743 // |
738 // |
744 // Notes: This now includes the extra code |
739 // Notes: This now includes the extra code |
745 // required to decode V6T2 instructions |
740 // required to decode V6T2 instructions |
746 |
741 |
1020 |
1013 |
1021 //TBool wback = (W == 1); // not needed for this encoding |
1014 //TBool wback = (W == 1); // not needed for this encoding |
1022 |
1015 |
1023 // Unpredictable? |
1016 // Unpredictable? |
1024 if (Rn == 15 || BitCount(registers) < 2 || ((P == 1) && (M==1))) |
1017 if (Rn == 15 || BitCount(registers) < 2 || ((P == 1) && (M==1))) |
1025 { |
1018 { |
1026 LOG_MSG("ARM ARM DDI0406 - section A8.6.55 LDMDB Encoding T1 - Unpredictable"); |
1019 LOG_MSG("ARM ARM DDI0406 - section A8.6.55 LDMDB Encoding T1 - Unpredictable"); |
1027 break; |
1020 break; |
1028 } |
1021 } |
1029 |
1022 |
1030 TUint32 address; |
1023 TUint32 address; |
1031 ReturnIfError(RegisterValue(aThread,Rn,address)); |
1024 ReturnIfError(RegisterValue(aThread,Rn,address)); |
1032 |
1025 |
1033 address -= 4*BitCount(registers); |
1026 address -= 4*BitCount(registers); |
1034 |
1027 |
1035 for(TInt i=0; i<15; i++) |
1028 for(TInt i=0; i<15; i++) |
1036 { |
1029 { |
1037 if (IsBitSet(registers,i)) |
1030 if (IsBitSet(registers,i)) |
1038 { |
1031 { |
1039 address +=4; |
1032 address +=4; |
1040 } |
1033 } |
1041 } |
1034 } |
1042 |
1035 |
1043 if (IsBitSet(registers,15)) |
1036 if (IsBitSet(registers,15)) |
1044 { |
1037 { |
1045 TUint32 RnVal = 0; |
1038 TUint32 RnVal = 0; |
1046 ReturnIfError(ReadMem32(aThread,address,RnVal)); |
1039 ReturnIfError(ReadMem32(aThread,address,RnVal)); |
1047 |
1040 |
1048 breakAddress = RnVal; |
1041 breakAddress = RnVal; |
1049 } |
1042 } |
1050 break; |
1043 break; |
1051 } |
1044 } |
1052 |
1045 |
1053 // ARM ARM DDI0406A - section A8.6.121 POP |
1046 // ARM ARM DDI0406A - section A8.6.121 POP |
1054 // |
1047 // |
1055 // POP.W Encoding T2 |
1048 // POP.W Encoding T2 |
1056 if (inst32 & 0xFFFF2000 == 0xE8BD0000) |
1049 if (inst32 & 0xFFFF2000 == 0xE8BD0000) |
1057 { |
1050 { |
1058 LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T2"); |
1051 LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T2"); |
1059 |
1052 |
1060 // Decoding as per ARM ARM description |
1053 // Decoding as per ARM ARM description |
1061 TUint32 registers = inst32 & 0x00001FFF; |
1054 TUint32 registers = inst32 & 0x00001FFF; |
1062 TUint32 P = inst32 & 0x00008000; |
1055 TUint32 P = inst32 & 0x00008000; |
1063 TUint32 M = inst32 & 0x00004000; |
1056 TUint32 M = inst32 & 0x00004000; |
1064 |
1057 |
1065 // Unpredictable? |
1058 // Unpredictable? |
1066 if ( (BitCount(registers)<2) || ((P == 1)&&(M == 1)) ) |
1059 if ( (BitCount(registers)<2) || ((P == 1)&&(M == 1)) ) |
1067 { |
1060 { |
1068 LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T2 - Unpredictable"); |
1061 LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T2 - Unpredictable"); |
1069 break; |
1062 break; |
1070 } |
1063 } |
1071 |
1064 |
1072 TUint32 address; |
1065 TUint32 address; |
1073 ReturnIfError(RegisterValue(aThread,13,address)); |
1066 ReturnIfError(RegisterValue(aThread,13,address)); |
1074 |
1067 |
1075 for(TInt i=0; i< 15; i++) |
1068 for(TInt i=0; i< 15; i++) |
1076 { |
1069 { |
1077 if (IsBitSet(registers,i)) |
1070 if (IsBitSet(registers,i)) |
1078 { |
1071 { |
1079 address += 4; |
1072 address += 4; |
1080 } |
1073 } |
1081 } |
1074 } |
1082 |
1075 |
1083 // Is the PC written? |
1076 // Is the PC written? |
1084 if (IsBitSet(registers,15)) |
1077 if (IsBitSet(registers,15)) |
1085 { |
1078 { |
1086 // Yes |
1079 // Yes |
1087 ReturnIfError(ReadMem32(aThread,address,breakAddress)); |
1080 ReturnIfError(ReadMem32(aThread,address,breakAddress)); |
1088 } |
1081 } |
1089 } |
1082 } |
1090 |
1083 |
1091 // POP Encoding T3 |
1084 // POP Encoding T3 |
1092 if (inst32 & 0xFFFF0FFFF == 0xF85D0B04) |
1085 if (inst32 & 0xFFFF0FFFF == 0xF85D0B04) |
1093 { |
1086 { |
1094 LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T3"); |
1087 LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T3"); |
1095 |
1088 |
1096 // Decoding as per ARM ARM description |
1089 // Decoding as per ARM ARM description |
1097 TUint32 Rt = inst32 & 0x0000F000 >> 12; |
1090 TUint32 Rt = inst32 & 0x0000F000 >> 12; |
1098 TUint32 registers = 1 << Rt; |
1091 TUint32 registers = 1 << Rt; |
1099 |
1092 |
1100 // Unpredictable? |
1093 // Unpredictable? |
1101 if (Rt == 13 || Rt == 15) |
1094 if (Rt == 13 || Rt == 15) |
1102 { |
1095 { |
1103 LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T3 - Unpredictable"); |
1096 LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T3 - Unpredictable"); |
1104 break; |
1097 break; |
1105 } |
1098 } |
1106 |
1099 |
1107 TUint32 address; |
1100 TUint32 address; |
1108 ReturnIfError(RegisterValue(aThread,13,address)); |
1101 ReturnIfError(RegisterValue(aThread,13,address)); |
1109 |
1102 |
1110 for(TInt i=0; i< 15; i++) |
1103 for(TInt i=0; i< 15; i++) |
1111 { |
1104 { |
1112 if (IsBitSet(registers,i)) |
1105 if (IsBitSet(registers,i)) |
1113 { |
1106 { |
1114 address += 4; |
1107 address += 4; |
1115 } |
1108 } |
1116 } |
1109 } |
1117 |
1110 |
1118 // Is the PC written? |
1111 // Is the PC written? |
1119 if (IsBitSet(registers,15)) |
1112 if (IsBitSet(registers,15)) |
1120 { |
1113 { |
1121 // Yes |
1114 // Yes |
1122 ReturnIfError(ReadMem32(aThread,address,breakAddress)); |
1115 ReturnIfError(ReadMem32(aThread,address,breakAddress)); |
1123 } |
1116 } |
1124 |
1117 |
1125 break; |
1118 break; |
1126 } |
1119 } |
1127 |
1120 |
1128 // ARM ARM DDI0406A - section A8.6.53 LDM |
1121 // ARM ARM DDI0406A - section A8.6.53 LDM |
1129 // |
1122 // |
1130 // Load Multiple Encoding T2 |
1123 // Load Multiple Encoding T2 |
1131 if ((inst32 & 0xFFD02000) == 0xE8900000) |
1124 if ((inst32 & 0xFFD02000) == 0xE8900000) |
1132 { |
1125 { |
1133 LOG_MSG("ARM ARM DDI0406A - section A8.6.53 LDM Encoding T2"); |
1126 LOG_MSG("ARM ARM DDI0406A - section A8.6.53 LDM Encoding T2"); |
1134 |
1127 |
1135 // Decoding as per ARM ARM description |
1128 // Decoding as per ARM ARM description |
1136 TUint32 W = inst32 & 0x0020000 >> 21; |
1129 TUint32 W = inst32 & 0x0020000 >> 21; |
1137 TUint32 Rn = inst32 & 0x000F0000 >> 16; |
1130 TUint32 Rn = inst32 & 0x000F0000 >> 16; |
1277 TBool increment = (U == 1); |
1270 TBool increment = (U == 1); |
1278 TBool wordhigher = (P == U); |
1271 TBool wordhigher = (P == U); |
1279 |
1272 |
1280 // Do calculation |
1273 // Do calculation |
1281 if (Rn == 15) |
1274 if (Rn == 15) |
1282 { |
1275 { |
1283 // Unpredictable |
1276 // Unpredictable |
1284 LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding A1 - Unpredictable"); |
1277 LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding A1 - Unpredictable"); |
1285 break; |
1278 break; |
1286 } |
1279 } |
1287 |
1280 |
1288 TUint32 RnVal = 0; |
1281 TUint32 RnVal = 0; |
1289 ReturnIfError(RegisterValue(aThread,Rn,RnVal)); |
1282 ReturnIfError(RegisterValue(aThread,Rn,RnVal)); |
1290 |
1283 |
1291 TUint32 address = 0; |
1284 TUint32 address = 0; |
1292 ReturnIfError(ReadMem32(aThread,RnVal,address)); |
1285 ReturnIfError(ReadMem32(aThread,RnVal,address)); |
1293 |
1286 |
1294 if (increment) |
1287 if (increment) |
1295 { |
1288 { |
1296 address -= 8; |
1289 address -= 8; |
1297 } |
1290 } |
1298 |
1291 |
1299 if (wordhigher) |
1292 if (wordhigher) |
1300 { |
1293 { |
1301 address += 4; |
1294 address += 4; |
1302 } |
1295 } |
1303 |
1296 |
1304 breakAddress = address; |
1297 breakAddress = address; |
1305 break; |
1298 break; |
|
1299 } |
1306 } |
1300 } |
1307 } |
|
1308 |
1301 |
1309 // v4T/v5T/v6T instructions |
1302 // v4T/v5T/v6T instructions |
1310 switch(thumb_opcode(inst)) |
1303 switch(thumb_opcode(inst)) |
1311 { |
1304 { |
1312 case 0x08: |
1305 case 0x08: |
1313 { |
1306 { |
1314 // Data-processing. See ARM ARM DDI0406A, section A6-8, A6.2.2. |
1307 // Data-processing. See ARM ARM DDI0406A, section A6-8, A6.2.2. |
1315 |
1308 |
1316 if ((thumb_inst_7_15(inst) == 0x08F)) |
1309 if ((thumb_inst_7_15(inst) == 0x08F)) |
1317 { |
1310 { |
1318 // BLX(2) |
1311 // BLX(2) |
1319 err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress); |
1312 err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress); |
1320 if(err != KErrNone) |
1313 if(err != KErrNone) |
1321 { |
1314 { |
1322 LOG_MSG2("Non-zero error code discarded: %d", err); |
1315 LOG_MSG2("Non-zero error code discarded: %d", err); |
1323 } |
1316 } |
1324 |
1317 |
1325 if ((breakAddress & 0x00000001) == 0) |
1318 if ((breakAddress & 0x00000001) == 0) |
1326 { |
1319 { |
1327 aChangingModes = ETrue; |
1320 aChangingModes = ETrue; |
1328 } |
1321 } |
1329 |
1322 |
1330 breakAddress &= 0xFFFFFFFE; |
1323 breakAddress &= 0xFFFFFFFE; |
1331 |
1324 |
1332 // Report how we decoded this instruction |
1325 // Report how we decoded this instruction |
1333 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BLX (2)"); |
1326 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BLX (2)"); |
1334 } |
1327 } |
1335 else if (thumb_inst_7_15(inst) == 0x08E) |
1328 else if (thumb_inst_7_15(inst) == 0x08E) |
1336 { |
1329 { |
1337 // BX |
1330 // BX |
1338 err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress); |
1331 err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress); |
1339 if(err != KErrNone) |
1332 if(err != KErrNone) |
1340 { |
1333 { |
1341 LOG_MSG2("Non-zero error code discarded: %d", err); |
1334 LOG_MSG2("Non-zero error code discarded: %d", err); |
1342 } |
1335 } |
1343 |
1336 |
1344 if ((breakAddress & 0x00000001) == 0) |
1337 if ((breakAddress & 0x00000001) == 0) |
1345 { |
1338 { |
1346 aChangingModes = ETrue; |
1339 aChangingModes = ETrue; |
1347 } |
1340 } |
1348 |
1341 |
1349 breakAddress &= 0xFFFFFFFE; |
1342 breakAddress &= 0xFFFFFFFE; |
1350 |
1343 |
1351 // Report how we decoded this instruction |
1344 // Report how we decoded this instruction |
1352 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BX"); |
1345 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BX"); |
1353 } |
1346 } |
1354 else if ((thumb_inst_8_15(inst) == 0x46) && ((inst & 0x87) == 0x87)) |
1347 else if ((thumb_inst_8_15(inst) == 0x46) && ((inst & 0x87) == 0x87)) |
1355 { |
1348 { |
1356 // MOV with PC as the destination |
1349 // MOV with PC as the destination |
1357 err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress); |
1350 err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress); |
1358 if(err != KErrNone) |
1351 if(err != KErrNone) |
1359 { |
1352 { |
1360 LOG_MSG2("Non-zero error code discarded: %d", err); |
1353 LOG_MSG2("Non-zero error code discarded: %d", err); |
1361 } |
1354 } |
1362 |
1355 |
1363 // Report how we decoded this instruction |
1356 // Report how we decoded this instruction |
1364 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as MOV with PC as the destination"); |
1357 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as MOV with PC as the destination"); |
1365 } |
1358 } |
1366 else if ((thumb_inst_8_15(inst) == 0x44) && ((inst & 0x87) == 0x87)) |
1359 else if ((thumb_inst_8_15(inst) == 0x44) && ((inst & 0x87) == 0x87)) |
1367 { |
1360 { |
1368 // ADD with PC as the destination |
1361 // ADD with PC as the destination |
1369 err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress); |
1362 err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress); |
1370 if(err != KErrNone) |
1363 if(err != KErrNone) |
1371 { |
1364 { |
1372 LOG_MSG2("Non-zero error code discarded: %d", err); |
1365 LOG_MSG2("Non-zero error code discarded: %d", err); |
1373 } |
1366 } |
1374 breakAddress += aCurrentPC + 4; // +4 because we need to use the PC+4 according to ARM ARM DDI0406A, section A6.1.2. |
1367 breakAddress += aCurrentPC + 4; // +4 because we need to use the PC+4 according to ARM ARM DDI0406A, section A6.1.2. |
1375 |
1368 |
1376 // Report how we decoded this instruction |
1369 // Report how we decoded this instruction |
1377 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as ADD with PC as the destination"); |
1370 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as ADD with PC as the destination"); |
1378 } |
1371 } |
1379 break; |
1372 break; |
1380 } |
1373 } |
1381 case 0x13: |
1374 case 0x13: |
1382 { |
1375 { |
1383 // Load/Store single data item. See ARM ARM DDI0406A, section A6-10 |
1376 // Load/Store single data item. See ARM ARM DDI0406A, section A6-10 |
1384 |
1377 |
1385 //This instruction doesn't modify the PC. |
1378 //This instruction doesn't modify the PC. |
1386 |
1379 |
1387 //if (thumb_inst_8_15(inst) == 0x9F) |
1380 //if (thumb_inst_8_15(inst) == 0x9F) |
1391 //} |
1384 //} |
1392 |
1385 |
1393 // Report how we decoded this instruction |
1386 // Report how we decoded this instruction |
1394 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as This instruction doesn't modify the PC."); |
1387 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as This instruction doesn't modify the PC."); |
1395 break; |
1388 break; |
1396 } |
1389 } |
1397 case 0x17: |
1390 case 0x17: |
1398 { |
1391 { |
1399 // Misc 16-bit instruction. See ARM ARM DDI0406A, section A6-11 |
1392 // Misc 16-bit instruction. See ARM ARM DDI0406A, section A6-11 |
1400 |
1393 |
1401 if (thumb_inst_8_15(inst) == 0xBD) |
1394 if (thumb_inst_8_15(inst) == 0xBD) |
1402 { |
1395 { |
1403 // POP with the PC in the list |
1396 // POP with the PC in the list |
1404 TUint32 regList = (inst & 0x00FF); |
1397 TUint32 regList = (inst & 0x00FF); |
1405 TInt offset = 0; |
1398 TInt offset = 0; |
1406 err = iChannel->ReadKernelRegisterValue(aThread, SP_REGISTER, (T4ByteRegisterValue&)offset); |
1399 err = iChannel->ReadKernelRegisterValue(aThread, SP_REGISTER, (T4ByteRegisterValue&)offset); |
1407 if(err != KErrNone) |
1400 if(err != KErrNone) |
1408 { |
1401 { |
1409 LOG_MSG2("Non-zero error code discarded: %d", err); |
1402 LOG_MSG2("Non-zero error code discarded: %d", err); |
1410 } |
1403 } |
1411 offset += (iChannel->Bitcount(regList) * 4); |
1404 offset += (iChannel->Bitcount(regList) * 4); |
1412 |
1405 |
1413 TBuf8<4> destination; |
1406 TBuf8<4> destination; |
1414 err = iChannel->DoReadMemory(aThread, offset, 4, destination); |
1407 err = iChannel->DoReadMemory(aThread, offset, 4, destination); |
1415 |
1408 |
1416 if (KErrNone == err) |
1409 if (KErrNone == err) |
1417 { |
1410 { |
1418 breakAddress = *(TUint32 *)destination.Ptr(); |
1411 breakAddress = *(TUint32 *)destination.Ptr(); |
1419 |
1412 |
1420 if ((breakAddress & 0x00000001) == 0) |
1413 if ((breakAddress & 0x00000001) == 0) |
1421 { |
1414 { |
1422 aChangingModes = ETrue; |
1415 aChangingModes = ETrue; |
1423 } |
1416 } |
1424 |
1417 |
1425 breakAddress &= 0xFFFFFFFE; |
1418 breakAddress &= 0xFFFFFFFE; |
1426 } |
1419 } |
1427 else |
1420 else |
1428 { |
1421 { |
1429 LOG_MSG("Error reading memory in decoding step instruction"); |
1422 LOG_MSG("Error reading memory in decoding step instruction"); |
1430 } |
1423 } |
1431 |
1424 |
1432 // Report how we decoded this instruction |
1425 // Report how we decoded this instruction |
1433 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as POP with the PC in the list"); |
1426 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as POP with the PC in the list"); |
1434 } |
1427 } |
1435 break; |
1428 break; |
1436 } |
1429 } |
1437 case 0x1A: |
1430 case 0x1A: |
1438 case 0x1B: |
1431 case 0x1B: |
1439 { |
1432 { |
1440 // Conditional branch, and supervisor call. See ARM ARM DDI0406A, section A6-13 |
1433 // Conditional branch, and supervisor call. See ARM ARM DDI0406A, section A6-13 |
1441 |
1434 |
1442 if (thumb_inst_8_15(inst) < 0xDE) |
1435 if (thumb_inst_8_15(inst) < 0xDE) |
1443 { |
1436 { |
1444 // B(1) conditional branch |
1437 // B(1) conditional branch |
1445 if (IsExecuted(((inst & 0x0F00) >> 8), aStatusRegister)) |
1438 if (IsExecuted(((inst & 0x0F00) >> 8), aStatusRegister)) |
1446 { |
1439 { |
1447 TUint32 offset = ((inst & 0x000000FF) << 1); |
1440 TUint32 offset = ((inst & 0x000000FF) << 1); |
1448 if (offset & 0x00000100) |
1441 if (offset & 0x00000100) |
1449 { |
1442 { |
1450 offset |= 0xFFFFFF00; |
1443 offset |= 0xFFFFFF00; |
1451 } |
1444 } |
1452 |
1445 |
1453 breakAddress = aCurrentPC + 4 + offset; |
1446 breakAddress = aCurrentPC + 4 + offset; |
1454 |
1447 |
1455 // Report how we decoded this instruction |
1448 // Report how we decoded this instruction |
1456 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as B(1) conditional branch"); |
1449 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as B(1) conditional branch"); |
1457 } |
1450 } |
1458 } |
1451 } |
1459 break; |
1452 break; |
1460 } |
1453 } |
1461 case 0x1C: |
1454 case 0x1C: |
1462 { |
1455 { |
1463 // Unconditional branch, See ARM ARM DDI0406A, section A8-44. |
1456 // Unconditional branch, See ARM ARM DDI0406A, section A8-44. |
1464 |
1457 |
1465 // B(2) unconditional branch |
1458 // B(2) unconditional branch |
1466 TUint32 offset = (inst & 0x000007FF) << 1; |
1459 TUint32 offset = (inst & 0x000007FF) << 1; |
1467 if (offset & 0x00000800) |
1460 if (offset & 0x00000800) |
1468 { |
1461 { |
1469 offset |= 0xFFFFF800; |
1462 offset |= 0xFFFFF800; |
1470 } |
1463 } |
1471 |
1464 |
1472 breakAddress = aCurrentPC + 4 + offset; |
1465 breakAddress = aCurrentPC + 4 + offset; |
1473 |
1466 |
1474 // Report how we decoded this instruction |
1467 // Report how we decoded this instruction |
1475 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as B(2) unconditional branch"); |
1468 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as B(2) unconditional branch"); |
1476 |
1469 |
1477 break; |
1470 break; |
1478 } |
1471 } |
1479 case 0x1D: |
1472 case 0x1D: |
1480 { |
1473 { |
1481 if (!(inst & 0x0001)) |
1474 if (!(inst & 0x0001)) |
1482 { |
1475 { |
1483 // BLX(1) |
1476 // BLX(1) |
1484 err = iChannel->ReadKernelRegisterValue(aThread, LINK_REGISTER, breakAddress); |
1477 err = iChannel->ReadKernelRegisterValue(aThread, LINK_REGISTER, breakAddress); |
1485 if(err != KErrNone) |
1478 if(err != KErrNone) |
1486 { |
1479 { |
1487 LOG_MSG2("Non-zero error code discarded: %d", err); |
1480 LOG_MSG2("Non-zero error code discarded: %d", err); |
1488 } |
1481 } |
1489 breakAddress += ((inst & 0x07FF) << 1); |
1482 breakAddress += ((inst & 0x07FF) << 1); |
1490 if ((breakAddress & 0x00000001) == 0) |
1483 if ((breakAddress & 0x00000001) == 0) |
1491 { |
1484 { |
1492 aChangingModes = ETrue; |
1485 aChangingModes = ETrue; |
1493 } |
1486 } |
1494 |
1487 |
1495 breakAddress &= 0xFFFFFFFC; |
1488 breakAddress &= 0xFFFFFFFC; |
1496 |
1489 |
1497 // Report how we decoded this instruction |
1490 // Report how we decoded this instruction |
1498 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BLX(1)"); |
1491 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BLX(1)"); |
1499 |
1492 |
1500 } |
1493 } |
1501 break; |
1494 break; |
1502 } |
1495 } |
1503 case 0x1E: |
1496 case 0x1E: |
1504 { |
1497 { |
1505 // Check for ARMv7 CPU |
1498 // Check for ARMv7 CPU |
1506 if(cpuid == 0xC0) |
1499 if(cpuid == 0xC0) |
1507 { |
1500 { |
1508 // BL/BLX 32-bit instruction |
1501 // BL/BLX 32-bit instruction |
1509 aNewRangeEnd += 4; |
1502 aNewRangeEnd += 4; |
1510 |
1503 |
1511 breakAddress = (TUint32)thumb_instr_b_dest(inst32, aCurrentPC); |
1504 breakAddress = (TUint32)thumb_instr_b_dest(inst32, aCurrentPC); |
1512 |
1505 |
1513 if((inst32 >> 27) == 0x1D) |
1506 if((inst32 >> 27) == 0x1D) |
1514 { |
1507 { |
1515 // BLX(1) |
1508 // BLX(1) |
1516 if ((breakAddress & 0x00000001) == 0) |
1509 if ((breakAddress & 0x00000001) == 0) |
1517 { |
1510 { |
1518 aChangingModes = ETrue; |
1511 aChangingModes = ETrue; |
1519 } |
1512 } |
1520 |
1513 |
1521 breakAddress &= 0xFFFFFFFC; |
1514 breakAddress &= 0xFFFFFFFC; |
1522 |
1515 |
1523 // Report how we decoded this instruction |
1516 // Report how we decoded this instruction |
1524 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as 32-bit BLX(1)"); |
1517 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as 32-bit BLX(1)"); |
1525 } |
1518 } |
1526 else |
1519 else |
1527 { |
1520 { |
1528 // Report how we decoded this instruction |
1521 // Report how we decoded this instruction |
1529 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: 32-bit BL instruction"); |
1522 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: 32-bit BL instruction"); |
1530 } |
1523 } |
1531 LOG_MSG2(" 32-bit BL/BLX instruction: breakAddress = 0x%X", breakAddress); |
1524 LOG_MSG2(" 32-bit BL/BLX instruction: breakAddress = 0x%X", breakAddress); |
1532 } |
1525 } // if(cpuid == 0xC0) |
1533 else |
1526 else |
1534 { |
1527 { |
1535 // BL/BLX prefix - destination is encoded in this and the next instruction |
1528 // BL/BLX prefix - destination is encoded in this and the next instruction |
1536 aNewRangeEnd += 2; |
1529 aNewRangeEnd += 2; |
1537 |
1530 |
1538 // Report how we decoded this instruction |
1531 // Report how we decoded this instruction |
1539 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: BL/BLX prefix - destination is encoded in this and the next instruction"); |
1532 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: BL/BLX prefix - destination is encoded in this and the next instruction"); |
1540 } |
1533 } |
1541 |
|
1542 |
1534 |
1543 break; |
1535 break; |
1544 } |
1536 } |
1545 case 0x1F: |
1537 case 0x1F: |
1546 { |
1538 { |
1547 { |
1539 // BL |
1548 // BL |
1540 err = iChannel->ReadKernelRegisterValue(aThread, LINK_REGISTER, breakAddress); |
1549 err = iChannel->ReadKernelRegisterValue(aThread, LINK_REGISTER, breakAddress); |
1541 if(err != KErrNone) |
1550 if(err != KErrNone) |
1542 { |
1551 { |
1543 LOG_MSG2("Non-zero error code discarded: %d", err); |
1552 LOG_MSG2("Non-zero error code discarded: %d", err); |
1544 } |
1553 } |
1545 breakAddress += ((inst & 0x07FF) << 1); |
1554 breakAddress += ((inst & 0x07FF) << 1); |
1546 |
1555 |
1547 // Report how we decoded this instruction |
1556 // Report how we decoded this instruction |
1548 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BL"); |
1557 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BL"); |
|
1558 } |
|
1559 break; |
1549 break; |
1560 } |
1550 } |
1561 default: |
1551 default: |
1562 { |
1552 { |
1563 // Don't know any better at this point! |
1553 // Don't know any better at this point! |
1564 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes:- default to next instruction"); |
1554 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes:- default to next instruction"); |
1565 } |
1555 } |
1566 break; |
1556 break; |
1567 } |
1557 } // switch(thumb_opcode(inst)) |
1568 } |
1558 } // case Debug::EThumbMode: |
1569 break; |
1559 break; |
1570 |
1560 |
1571 case Debug::EThumb2EEMode: |
1561 case Debug::EThumb2EEMode: |
1572 { |
1562 { |
1573 // Not yet supported |
1563 // Not yet supported |
1574 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes - Debug::EThumb2Mode is not supported"); |
1564 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes - Debug::EThumb2Mode is not supported"); |
1575 |
1565 |
1576 } |
1566 } |
1577 break; |
1567 break; |
1578 |
1568 |
1579 default: |
1569 default: |
1580 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes - Cannot determine CPU mode architecture"); |
1570 LOG_MSG("DRMDStepping::PCAfterInstructionExecutes - Cannot determine CPU mode architecture"); |
1581 } |
1571 } // switch(mode) |
1582 |
1572 |
1583 LOG_MSG2("DRMDStepping::PCAfterInstructionExecutes : return 0x%08x",breakAddress); |
1573 LOG_MSG2("DRMDStepping::PCAfterInstructionExecutes : return 0x%08x",breakAddress); |
1584 return breakAddress; |
1574 return breakAddress; |
1585 } |
1575 } |
1586 |
1576 |
1587 // Obtain a 32-bit memory value with minimum fuss |
1577 // Obtain a 32-bit memory value with minimum fuss |
1588 TInt DRMDStepping::ReadMem32(DThread* aThread, const TUint32 aAddress, TUint32& aValue) |
1578 TInt DRMDStepping::ReadMem32(DThread* aThread, const TUint32 aAddress, TUint32& aValue) |
1589 { |
1579 { |
1590 TBuf8<4> valBuf; |
1580 TBuf8<4> valBuf; |
1644 } |
1634 } |
1645 |
1635 |
1646 |
1636 |
1647 // Encodings from ARM ARM DDI0406A, section 9.2.1 |
1637 // Encodings from ARM ARM DDI0406A, section 9.2.1 |
1648 enum TThumb2EEOpcode |
1638 enum TThumb2EEOpcode |
1649 { |
1639 { |
1650 EThumb2HDP, // Handler Branch with Parameter |
1640 EThumb2HDP, // Handler Branch with Parameter |
1651 EThumb2UNDEF, // UNDEFINED |
1641 EThumb2UNDEF, // UNDEFINED |
1652 EThumb2HB, // Handler Branch, Handler Branch with Link |
1642 EThumb2HB, // Handler Branch, Handler Branch with Link |
1653 EThumb2HBLP, // Handle Branch with Link and Parameter |
1643 EThumb2HBLP, // Handle Branch with Link and Parameter |
1654 EThumb2LDRF, // Load Register from a frame |
1644 EThumb2LDRF, // Load Register from a frame |
1655 EThumb2CHKA, // Check Array |
1645 EThumb2CHKA, // Check Array |
1656 EThumb2LDRL, // Load Register from a literal pool |
1646 EThumb2LDRL, // Load Register from a literal pool |
1657 EThumb2LDRA, // Load Register (array operations) |
1647 EThumb2LDRA, // Load Register (array operations) |
1658 EThumb2STR // Store Register to a frame |
1648 EThumb2STR // Store Register to a frame |
1659 }; |
1649 }; |
1660 |
1650 |
1661 // |
1651 // |
1662 // DRMDStepping::ShiftedRegValue |
1652 // DRMDStepping::ShiftedRegValue |
1663 // |
1653 // |
1664 TUint32 DRMDStepping::ShiftedRegValue(DThread *aThread, TUint32 aInstruction, TUint32 aCurrentPC, TUint32 aStatusRegister) |
1654 TUint32 DRMDStepping::ShiftedRegValue(DThread *aThread, TUint32 aInstruction, TUint32 aCurrentPC, TUint32 aStatusRegister) |
1665 { |
1655 { |
1666 LOG_MSG("DRM_DebugChannel::ShiftedRegValue()"); |
1656 LOG_MSG("DRMDStepping::ShiftedRegValue()"); |
1667 |
1657 |
1668 TUint32 shift = 0; |
1658 TUint32 shift = 0; |
1669 if (aInstruction & 0x10) // bit 4 |
1659 if (aInstruction & 0x10) // bit 4 |
1670 { |
1660 { |
1671 shift = (arm_rs(aInstruction) == PC_REGISTER ? aCurrentPC + 8 : aStatusRegister) & 0xFF; |
1661 shift = (arm_rs(aInstruction) == PC_REGISTER ? aCurrentPC + 8 : aStatusRegister) & 0xFF; |
1672 } |
1662 } |
1673 else |
1663 else |
1674 { |
1664 { |
1675 shift = arm_data_c(aInstruction); |
1665 shift = arm_data_c(aInstruction); |
1676 } |
1666 } |
1677 |
1667 |
1678 TInt rm = arm_rm(aInstruction); |
1668 TInt rm = arm_rm(aInstruction); |
1679 |
1669 |
1680 TUint32 res = 0; |
1670 TUint32 res = 0; |
1681 if(rm == PC_REGISTER) |
1671 if(rm == PC_REGISTER) |
1682 { |
1672 { |
1683 res = aCurrentPC + ((aInstruction & 0x10) ? 12 : 8); |
1673 res = aCurrentPC + ((aInstruction & 0x10) ? 12 : 8); |
1684 } |
1674 } |
1685 else |
1675 else |
1686 { |
1676 { |
1687 TInt err = iChannel->ReadKernelRegisterValue(aThread, rm, res); |
1677 TInt err = iChannel->ReadKernelRegisterValue(aThread, rm, res); |
1688 if(err != KErrNone) |
1678 if(err != KErrNone) |
1689 { |
1679 { |
1690 LOG_MSG2("DRMDStepping::ShiftedRegValue - Non-zero error code discarded: %d", err); |
1680 LOG_MSG2("DRMDStepping::ShiftedRegValue - Non-zero error code discarded: %d", err); |
1691 } |
1681 } |
1692 } |
1682 } |
1693 |
1683 |
1694 switch(arm_data_shift(aInstruction)) |
1684 switch(arm_data_shift(aInstruction)) |
1695 { |
1685 { |
1696 case 0: // LSL |
1686 case 0: // LSL |
1697 { |
1687 { |
1698 res = shift >= 32 ? 0 : res << shift; |
1688 res = shift >= 32 ? 0 : res << shift; |
1699 break; |
1689 break; |
1700 } |
1690 } |
1701 case 1: // LSR |
1691 case 1: // LSR |
1702 { |
1692 { |
1703 res = shift >= 32 ? 0 : res >> shift; |
1693 res = shift >= 32 ? 0 : res >> shift; |
1704 break; |
1694 break; |
1705 } |
1695 } |
1706 case 2: // ASR |
1696 case 2: // ASR |
1707 { |
1697 { |
1708 if (shift >= 32) |
1698 if (shift >= 32) |
1709 shift = 31; |
1699 shift = 31; |
1710 res = ((res & 0x80000000L) ? ~((~res) >> shift) : res >> shift); |
1700 res = ((res & 0x80000000L) ? ~((~res) >> shift) : res >> shift); |
1711 break; |
1701 break; |
1712 } |
1702 } |
1713 case 3: // ROR/RRX |
1703 case 3: // ROR/RRX |
1714 { |
1704 { |
1715 shift &= 31; |
1705 shift &= 31; |
1716 if (shift == 0) |
1706 if (shift == 0) |
1717 { |
1707 { |
1718 res = (res >> 1) | ((aStatusRegister & arm_carry_bit()) ? 0x80000000L : 0); |
1708 res = (res >> 1) | ((aStatusRegister & arm_carry_bit()) ? 0x80000000L : 0); |
1719 } |
1709 } |
1720 else |
1710 else |
1721 { |
1711 { |
1722 res = (res >> shift) | (res << (32 - shift)); |
1712 res = (res >> shift) | (res << (32 - shift)); |
1723 } |
1713 } |
1724 break; |
1714 break; |
1725 } |
1715 } |
1726 } |
1716 } |
1727 |
1717 |
1728 return res & 0xFFFFFFFF; |
1718 return res & 0xFFFFFFFF; |
1729 } |
1719 } |
1730 |
1720 |
1731 // |
1721 // |
1732 // DRMDStepping::CurrentPC |
1722 // DRMDStepping::CurrentPC |
1733 // |
1723 // |