summaryrefslogtreecommitdiff
path: root/decoder/source/i_dec
diff options
context:
space:
mode:
authorAndrew Turner <andrew@FreeBSD.org>2020-06-15 11:30:04 +0000
committerAndrew Turner <andrew@FreeBSD.org>2020-06-15 11:30:04 +0000
commitd7aa8d0a1f110421252d79f5acfb72d89187ad1f (patch)
tree8b0efac880d3949a9d25ab9bb34792eac605eee6 /decoder/source/i_dec
parentcf98ba14dc260458f757fa46419575cf69f45a44 (diff)
Notes
Diffstat (limited to 'decoder/source/i_dec')
-rw-r--r--decoder/source/i_dec/trc_i_decode.cpp51
-rw-r--r--decoder/source/i_dec/trc_idec_arminst.cpp137
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;
}