1 #include "arm_thumb.h"
2 #include "arm_common.h"
3 
4 namespace REDasm {
5 
ARMThumbAssembler()6 ARMThumbAssembler::ARMThumbAssembler(): ARMCommonAssembler<CS_ARCH_ARM, CS_MODE_THUMB>() { }
7 
pc(const InstructionPtr & instruction) const8 u64 ARMThumbAssembler::pc(const InstructionPtr &instruction) const
9 {
10     /*
11      * https://stackoverflow.com/questions/24091566/why-does-the-arm-pc-register-point-to-the-instruction-after-the-next-one-to-be-e
12      *
13      * In Thumb state:
14      *  - For B, BL, CBNZ, and CBZ instructions, the value of the PC is the address
15      *    of the current instruction plus 4 bytes.
16      *
17      *  - For all other instructions that use labels, the value of the PC is the address
18      *    of the current instruction plus 4 bytes, with bit[1] of the result cleared
19      *    to 0 to make it word-aligned.
20      */
21 
22     switch(instruction->id)
23     {
24         case ARM_INS_B:
25         case ARM_INS_BL:
26         case ARM_INS_CBNZ:
27         case ARM_INS_CBZ:
28             return instruction->address + 4;
29 
30         default:
31             break;
32     }
33 
34     return (instruction->address + 4) & 0xFFFFFFFE;
35 }
36 
37 } // namespace REDasm
38