diff options
author | Andrew Turner <andrew@FreeBSD.org> | 2020-06-15 11:30:04 +0000 |
---|---|---|
committer | Andrew Turner <andrew@FreeBSD.org> | 2020-06-15 11:30:04 +0000 |
commit | d7aa8d0a1f110421252d79f5acfb72d89187ad1f (patch) | |
tree | 8b0efac880d3949a9d25ab9bb34792eac605eee6 /decoder/source/i_dec | |
parent | cf98ba14dc260458f757fa46419575cf69f45a44 (diff) |
Notes
Diffstat (limited to 'decoder/source/i_dec')
-rw-r--r-- | decoder/source/i_dec/trc_i_decode.cpp | 51 | ||||
-rw-r--r-- | decoder/source/i_dec/trc_idec_arminst.cpp | 137 |
2 files changed, 76 insertions, 112 deletions
diff --git a/decoder/source/i_dec/trc_i_decode.cpp b/decoder/source/i_dec/trc_i_decode.cpp index ab93284848bb..614fc1d8b45c 100644 --- a/decoder/source/i_dec/trc_i_decode.cpp +++ b/decoder/source/i_dec/trc_i_decode.cpp @@ -39,21 +39,23 @@ ocsd_err_t TrcIDecode::DecodeInstruction(ocsd_instr_info *instr_info) { ocsd_err_t err = OCSD_OK; - clear_instr_subtype(); - SetArchVersion(instr_info); + struct decode_info info; + + info.instr_sub_type = OCSD_S_INSTR_NONE; + info.arch_version = (uint16_t)(instr_info->pe_type.arch); switch(instr_info->isa) { case ocsd_isa_arm: - err = DecodeA32(instr_info); + err = DecodeA32(instr_info, &info); break; case ocsd_isa_thumb2: - err = DecodeT32(instr_info); + err = DecodeT32(instr_info, &info); break; case ocsd_isa_aarch64: - err = DecodeA64(instr_info); + err = DecodeA64(instr_info, &info); break; case ocsd_isa_tee: @@ -63,27 +65,11 @@ ocsd_err_t TrcIDecode::DecodeInstruction(ocsd_instr_info *instr_info) err = OCSD_ERR_UNSUPPORTED_ISA; break; } - instr_info->sub_type = get_instr_subtype(); + instr_info->sub_type = info.instr_sub_type; return err; } -void TrcIDecode::SetArchVersion(ocsd_instr_info *instr_info) -{ - uint16_t arch = 0x0700; - - switch (instr_info->pe_type.arch) - { - case ARCH_V8: arch = 0x0800; break; - case ARCH_V8r3: arch = 0x0803; break; - case ARCH_V7: - default: - break; - } - set_arch_version(arch); -} - - -ocsd_err_t TrcIDecode::DecodeA32(ocsd_instr_info *instr_info) +ocsd_err_t TrcIDecode::DecodeA32(ocsd_instr_info *instr_info, struct decode_info *info) { uint32_t branchAddr = 0; arm_barrier_t barrier; @@ -93,10 +79,10 @@ ocsd_err_t TrcIDecode::DecodeA32(ocsd_instr_info *instr_info) instr_info->next_isa = instr_info->isa; // assume same ISA instr_info->is_link = 0; - if(inst_ARM_is_indirect_branch(instr_info->opcode)) + if(inst_ARM_is_indirect_branch(instr_info->opcode, info)) { instr_info->type = OCSD_INSTR_BR_INDIRECT; - instr_info->is_link = inst_ARM_is_branch_and_link(instr_info->opcode); + instr_info->is_link = inst_ARM_is_branch_and_link(instr_info->opcode, info); } else if(inst_ARM_is_direct_branch(instr_info->opcode)) { @@ -108,7 +94,7 @@ ocsd_err_t TrcIDecode::DecodeA32(ocsd_instr_info *instr_info) branchAddr &= ~0x1; } instr_info->branch_addr = (ocsd_vaddr_t)branchAddr; - instr_info->is_link = inst_ARM_is_branch_and_link(instr_info->opcode); + instr_info->is_link = inst_ARM_is_branch_and_link(instr_info->opcode, info); } else if((barrier = inst_ARM_barrier(instr_info->opcode)) != ARM_BARRIER_NONE) { @@ -137,7 +123,7 @@ ocsd_err_t TrcIDecode::DecodeA32(ocsd_instr_info *instr_info) return OCSD_OK; } -ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info) +ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info, struct decode_info *info) { uint64_t branchAddr = 0; arm_barrier_t barrier; @@ -147,12 +133,12 @@ ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info) instr_info->next_isa = instr_info->isa; // assume same ISA instr_info->is_link = 0; - if(inst_A64_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link)) + if(inst_A64_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link, info)) { instr_info->type = OCSD_INSTR_BR_INDIRECT; // instr_info->is_link = inst_A64_is_branch_and_link(instr_info->opcode); } - else if(inst_A64_is_direct_branch_link(instr_info->opcode, &instr_info->is_link)) + else if(inst_A64_is_direct_branch_link(instr_info->opcode, &instr_info->is_link, info)) { inst_A64_branch_destination(instr_info->instr_addr,instr_info->opcode,&branchAddr); instr_info->type = OCSD_INSTR_BR; @@ -187,7 +173,7 @@ ocsd_err_t TrcIDecode::DecodeA64(ocsd_instr_info *instr_info) return OCSD_OK; } -ocsd_err_t TrcIDecode::DecodeT32(ocsd_instr_info *instr_info) +ocsd_err_t TrcIDecode::DecodeT32(ocsd_instr_info *instr_info, struct decode_info *info) { uint32_t branchAddr = 0; arm_barrier_t barrier; @@ -206,7 +192,7 @@ ocsd_err_t TrcIDecode::DecodeT32(ocsd_instr_info *instr_info) instr_info->is_conditional = 0; - if(inst_Thumb_is_direct_branch_link(instr_info->opcode,&instr_info->is_link, &instr_info->is_conditional)) + if(inst_Thumb_is_direct_branch_link(instr_info->opcode,&instr_info->is_link, &instr_info->is_conditional, info)) { inst_Thumb_branch_destination((uint32_t)instr_info->instr_addr,instr_info->opcode,&branchAddr); instr_info->type = OCSD_INSTR_BR; @@ -214,7 +200,7 @@ ocsd_err_t TrcIDecode::DecodeT32(ocsd_instr_info *instr_info) if((branchAddr & 0x1) == 0) instr_info->next_isa = ocsd_isa_arm; } - else if (inst_Thumb_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link)) + else if (inst_Thumb_is_indirect_branch_link(instr_info->opcode, &instr_info->is_link, info)) { instr_info->type = OCSD_INSTR_BR_INDIRECT; } @@ -246,5 +232,4 @@ ocsd_err_t TrcIDecode::DecodeT32(ocsd_instr_info *instr_info) return OCSD_OK; } - /* End of File trc_i_decode.cpp */ diff --git a/decoder/source/i_dec/trc_idec_arminst.cpp b/decoder/source/i_dec/trc_idec_arminst.cpp index 09964a15e7b3..3652e84921f3 100644 --- a/decoder/source/i_dec/trc_idec_arminst.cpp +++ b/decoder/source/i_dec/trc_idec_arminst.cpp @@ -42,27 +42,6 @@ block identification and trace decode. #include <stddef.h> /* for NULL */ #include <assert.h> - -static ocsd_instr_subtype instr_sub_type = OCSD_S_INSTR_NONE; - -/* need to spot the architecture version for certain instructions */ -static uint16_t arch_version = 0x70; - -ocsd_instr_subtype get_instr_subtype() -{ - return instr_sub_type; -} - -void clear_instr_subtype() -{ - instr_sub_type = OCSD_S_INSTR_NONE; -} - -void set_arch_version(uint16_t version) -{ - arch_version = version; -} - int inst_ARM_is_direct_branch(uint32_t inst) { int is_direct_branch = 1; @@ -91,7 +70,7 @@ int inst_ARM_wfiwfe(uint32_t inst) return 0; } -int inst_ARM_is_indirect_branch(uint32_t inst) +int inst_ARM_is_indirect_branch(uint32_t inst, struct decode_info *info) { int is_indirect_branch = 1; if ((inst & 0xf0000000) == 0xf0000000) { @@ -104,23 +83,23 @@ int inst_ARM_is_indirect_branch(uint32_t inst) } else if ((inst & 0x0ff000d0) == 0x01200010) { /* BLX (register), BX */ if ((inst & 0xFF) == 0x1E) - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* BX LR */ + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* BX LR */ } else if ((inst & 0x0ff000f0) == 0x01200020) { /* BXJ: in v8 this behaves like BX */ } else if ((inst & 0x0e108000) == 0x08108000) { /* POP {...,pc} or LDMxx {...,pc} */ if ((inst & 0x0FFFA000) == 0x08BD8000) /* LDMIA SP!,{...,pc} */ - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; } else if ((inst & 0x0e50f000) == 0x0410f000) { /* LDR PC,imm... inc. POP {PC} */ if ( (inst & 0x01ff0000) == 0x009D0000) - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* LDR PC, [SP], #imm */ + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* LDR PC, [SP], #imm */ } else if ((inst & 0x0e50f010) == 0x0610f000) { /* LDR PC,reg */ } else if ((inst & 0x0fe0f000) == 0x01a0f000) { /* MOV PC,rx */ if ((inst & 0x00100FFF) == 0x00E) /* ensure the S=0, LSL #0 variant - i.e plain MOV */ - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* MOV PC, R14 */ + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* MOV PC, R14 */ } else if ((inst & 0x0f900080) == 0x01000000) { /* "Miscellaneous instructions" - in DP space */ is_indirect_branch = 0; @@ -144,13 +123,13 @@ int inst_ARM_is_indirect_branch(uint32_t inst) return is_indirect_branch; } -int inst_Thumb_is_direct_branch(uint32_t inst) +int inst_Thumb_is_direct_branch(uint32_t inst, struct decode_info *info) { uint8_t link, cond; - return inst_Thumb_is_direct_branch_link(inst, &link, &cond); + return inst_Thumb_is_direct_branch_link(inst, &link, &cond, info); } -int inst_Thumb_is_direct_branch_link(uint32_t inst, uint8_t *is_link, uint8_t *is_cond) +int inst_Thumb_is_direct_branch_link(uint32_t inst, uint8_t *is_link, uint8_t *is_cond, struct decode_info *info) { int is_direct_branch = 1; @@ -166,12 +145,12 @@ int inst_Thumb_is_direct_branch_link(uint32_t inst, uint8_t *is_link, uint8_t *i /* B (encoding T4); BL (encoding T1) */ if (inst & 0x00004000) { *is_link = 1; - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } } else if ((inst & 0xf800d001) == 0xf000c000) { /* BLX (imm) (encoding T2) */ *is_link = 1; - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } else if ((inst & 0xf5000000) == 0xb1000000) { /* CB(NZ) */ *is_cond = 1; @@ -197,13 +176,13 @@ int inst_Thumb_wfiwfe(uint32_t inst) return is_wfiwfe; } -int inst_Thumb_is_indirect_branch(uint32_t inst) +int inst_Thumb_is_indirect_branch(uint32_t inst, struct decode_info *info) { uint8_t link; - return inst_Thumb_is_indirect_branch_link(inst, &link); + return inst_Thumb_is_indirect_branch_link(inst, &link, info); } -int inst_Thumb_is_indirect_branch_link(uint32_t inst, uint8_t *is_link) +int inst_Thumb_is_indirect_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info) { /* See e.g. PFT Table 2-3 and Table 2-5 */ int is_branch = 1; @@ -212,20 +191,20 @@ int inst_Thumb_is_indirect_branch_link(uint32_t inst, uint8_t *is_link) /* BX, BLX (reg) [v8M includes BXNS, BLXNS] */ if (inst & 0x00800000) { *is_link = 1; - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } else if ((inst & 0x00780000) == 0x00700000) { - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* BX LR */ + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* BX LR */ } } else if ((inst & 0xfff0d000) == 0xf3c08000) { /* BXJ: in v8 this behaves like BX */ } else if ((inst & 0xff000000) == 0xbd000000) { /* POP {pc} */ - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; } else if ((inst & 0xfd870000) == 0x44870000) { /* MOV PC,reg or ADD PC,reg */ - if ((inst & 0xffff0000) == 0x46f700000) - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* MOV PC,LR */ + if ((inst & 0xffff0000) == 0x46f70000) + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* MOV PC,LR */ } else if ((inst & 0xfff0ffe0) == 0xe8d0f000) { /* TBB/TBH */ } else if ((inst & 0xffd00000) == 0xe8100000) { @@ -241,26 +220,26 @@ int inst_Thumb_is_indirect_branch_link(uint32_t inst, uint8_t *is_link) } else if ((inst & 0xfff0f800) == 0xf850f800) { /* LDR PC,imm (T4) */ if((inst & 0x000f0f00) == 0x000d0b00) - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* LDR PC, [SP], #imm*/ + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* LDR PC, [SP], #imm*/ } else if ((inst & 0xfff0ffc0) == 0xf850f000) { /* LDR PC,reg (T2) */ } else if ((inst & 0xfe508000) == 0xe8108000) { /* LDM PC */ if ((inst & 0x0FFF0000) == 0x08BD0000) /* LDMIA [SP]!, */ - instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* POP {...,pc} */ + info->instr_sub_type = OCSD_S_INSTR_V7_IMPLIED_RET; /* POP {...,pc} */ } else { is_branch = 0; } return is_branch; } -int inst_A64_is_direct_branch(uint32_t inst) +int inst_A64_is_direct_branch(uint32_t inst, struct decode_info *info) { uint8_t link = 0; - return inst_A64_is_direct_branch_link(inst, &link); + return inst_A64_is_direct_branch_link(inst, &link, info); } -int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link) +int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info) { int is_direct_branch = 1; if ((inst & 0x7c000000) == 0x34000000) { @@ -271,7 +250,7 @@ int inst_A64_is_direct_branch_link(uint32_t inst, uint8_t *is_link) /* B, BL imm */ if (inst & 0x80000000) { *is_link = 1; - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } } else { is_direct_branch = 0; @@ -287,13 +266,13 @@ int inst_A64_wfiwfe(uint32_t inst) return 0; } -int inst_A64_is_indirect_branch(uint32_t inst) +int inst_A64_is_indirect_branch(uint32_t inst, struct decode_info *info) { uint8_t link = 0; - return inst_A64_is_indirect_branch_link(inst, &link); + return inst_A64_is_indirect_branch_link(inst, &link, info); } -int inst_A64_is_indirect_branch_link(uint32_t inst, uint8_t *is_link) +int inst_A64_is_indirect_branch_link(uint32_t inst, uint8_t *is_link, struct decode_info *info) { int is_indirect_branch = 1; @@ -301,34 +280,34 @@ int inst_A64_is_indirect_branch_link(uint32_t inst, uint8_t *is_link) /* BR, BLR */ if (inst & 0x00200000) { *is_link = 1; - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } } else if ((inst & 0xfffffc1f) == 0xd65f0000) { - instr_sub_type = OCSD_S_INSTR_V8_RET; + info->instr_sub_type = OCSD_S_INSTR_V8_RET; /* RET */ } else if ((inst & 0xffffffff) == 0xd69f03e0) { /* ERET */ - instr_sub_type = OCSD_S_INSTR_V8_ERET; - } else if (arch_version >= 0x0803) { + info->instr_sub_type = OCSD_S_INSTR_V8_ERET; + } else if (info->arch_version >= 0x0803) { /* new pointer auth instr for v8.3 arch */ - if ((inst & 0xffdff800) == 0xd61f0800) { + if ((inst & 0xffdff800) == 0xd71f0800) { /* BRAA, BRAB, BLRAA, BLRBB */ if (inst & 0x00200000) { *is_link = 1; - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } - } else if ((inst & 0xffdff81F) == 0xd71f081F) { + } else if ((inst & 0xffdff81F) == 0xd61f081F) { /* BRAAZ, BRABZ, BLRAAZ, BLRBBZ */ if (inst & 0x00200000) { *is_link = 1; - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } } else if ((inst & 0xfffffbff) == 0xd69f0bff) { /* ERETAA, ERETAB */ - instr_sub_type = OCSD_S_INSTR_V8_ERET; + info->instr_sub_type = OCSD_S_INSTR_V8_ERET; } else if ((inst & 0xfffffbff) == 0xd65f0bff) { /* RETAA, RETAB */ - instr_sub_type = OCSD_S_INSTR_V8_RET; + info->instr_sub_type = OCSD_S_INSTR_V8_RET; } else { is_indirect_branch = 0; } @@ -441,39 +420,39 @@ int inst_A64_branch_destination(uint64_t addr, uint32_t inst, uint64_t *pnpc) return is_direct_branch; } -int inst_ARM_is_branch(uint32_t inst) +int inst_ARM_is_branch(uint32_t inst, struct decode_info *info) { - return inst_ARM_is_indirect_branch(inst) || + return inst_ARM_is_indirect_branch(inst, info) || inst_ARM_is_direct_branch(inst); } -int inst_Thumb_is_branch(uint32_t inst) +int inst_Thumb_is_branch(uint32_t inst, struct decode_info *info) { - return inst_Thumb_is_indirect_branch(inst) || - inst_Thumb_is_direct_branch(inst); + return inst_Thumb_is_indirect_branch(inst, info) || + inst_Thumb_is_direct_branch(inst, info); } -int inst_A64_is_branch(uint32_t inst) +int inst_A64_is_branch(uint32_t inst, struct decode_info *info) { - return inst_A64_is_indirect_branch(inst) || - inst_A64_is_direct_branch(inst); + return inst_A64_is_indirect_branch(inst, info) || + inst_A64_is_direct_branch(inst, info); } -int inst_ARM_is_branch_and_link(uint32_t inst) +int inst_ARM_is_branch_and_link(uint32_t inst, struct decode_info *info) { int is_branch = 1; if ((inst & 0xf0000000) == 0xf0000000) { if ((inst & 0xfe000000) == 0xfa000000){ - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; /* BLX (imm) */ } else { is_branch = 0; } } else if ((inst & 0x0f000000) == 0x0b000000) { - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; /* BL */ } else if ((inst & 0x0ff000f0) == 0x01200030) { - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; /* BLX (reg) */ } else { is_branch = 0; @@ -481,14 +460,14 @@ int inst_ARM_is_branch_and_link(uint32_t inst) return is_branch; } -int inst_Thumb_is_branch_and_link(uint32_t inst) +int inst_Thumb_is_branch_and_link(uint32_t inst, struct decode_info *info) { int is_branch = 1; if ((inst & 0xff800000) == 0x47800000) { - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; /* BLX (reg) */ } else if ((inst & 0xf800c000) == 0xf000c000) { - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; /* BL, BLX (imm) */ } else { is_branch = 0; @@ -496,23 +475,23 @@ int inst_Thumb_is_branch_and_link(uint32_t inst) return is_branch; } -int inst_A64_is_branch_and_link(uint32_t inst) +int inst_A64_is_branch_and_link(uint32_t inst, struct decode_info *info) { int is_branch = 1; if ((inst & 0xfffffc1f) == 0xd63f0000) { /* BLR */ - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } else if ((inst & 0xfc000000) == 0x94000000) { /* BL */ - instr_sub_type = OCSD_S_INSTR_BR_LINK; - } else if (arch_version >= 0x0803) { + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; + } else if (info->arch_version >= 0x0803) { /* new pointer auth instr for v8.3 arch */ if ((inst & 0xfffff800) == 0xd73f0800) { /* BLRAA, BLRBB */ - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } else if ((inst & 0xfffff81F) == 0xd63f081F) { /* BLRAAZ, BLRBBZ */ - instr_sub_type = OCSD_S_INSTR_BR_LINK; + info->instr_sub_type = OCSD_S_INSTR_BR_LINK; } else { is_branch = 0; } |