librz/arch: add analysis plugin for MCS96 (#5622)
This commit is contained in:
parent
b58e9a6a4a
commit
0321748674
7 changed files with 1714 additions and 243 deletions
|
|
@ -12,6 +12,9 @@
|
|||
* https://archive.org/details/manualzilla-id-5702485/page/n469/mode/2up
|
||||
*/
|
||||
|
||||
#ifndef MCS96_H
|
||||
#define MCS96_H
|
||||
|
||||
#include <rz_util.h>
|
||||
#include <rz_types.h>
|
||||
|
||||
|
|
@ -327,5 +330,407 @@ static Mcs96Op mcs96_op[] = {
|
|||
{ "rst", MCS96_1B, MCS96_SUPPORT_SINCE_8096 }
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
MCS96_SKIP_00,
|
||||
MCS96_CLR_01,
|
||||
MCS96_NOT_02,
|
||||
MCS96_NEG_03,
|
||||
MCS96_XCH_04,
|
||||
MCS96_DEC_05,
|
||||
MCS96_EXT_06,
|
||||
MCS96_INC_07,
|
||||
MCS96_SHR_08,
|
||||
MCS96_SHL_09,
|
||||
MCS96_SHRA_0A,
|
||||
MCS96_XCH_0B,
|
||||
MCS96_SHRL_0C,
|
||||
MCS96_SHLL_0D,
|
||||
MCS96_SHRAL_0E,
|
||||
MCS96_NORML_0F,
|
||||
MCS96_INVALID_10,
|
||||
MCS96_CLRB_11,
|
||||
MCS96_NOTB_12,
|
||||
MCS96_NEGB_13,
|
||||
MCS96_XCHB_14,
|
||||
MCS96_DECB_15,
|
||||
MCS96_EXTB_16,
|
||||
MCS96_INCB_17,
|
||||
MCS96_SHRB_18,
|
||||
MCS96_SHLB_19,
|
||||
MCS96_SHRAB_1A,
|
||||
MCS96_XCHB_1B,
|
||||
MCS96_EST_1C,
|
||||
MCS96_EST_1D,
|
||||
MCS96_ESTB_1E,
|
||||
MCS96_ESTB_1F,
|
||||
MCS96_SJMP_20,
|
||||
MCS96_SJMP_21,
|
||||
MCS96_SJMP_22,
|
||||
MCS96_SJMP_23,
|
||||
MCS96_SJMP_24,
|
||||
MCS96_SJMP_25,
|
||||
MCS96_SJMP_26,
|
||||
MCS96_SJMP_27,
|
||||
MCS96_SCALL_28,
|
||||
MCS96_SCALL_29,
|
||||
MCS96_SCALL_2A,
|
||||
MCS96_SCALL_2B,
|
||||
MCS96_SCALL_2C,
|
||||
MCS96_SCALL_2D,
|
||||
MCS96_SCALL_2E,
|
||||
MCS96_SCALL_2F,
|
||||
MCS96_JBC_30,
|
||||
MCS96_JBC_31,
|
||||
MCS96_JBC_32,
|
||||
MCS96_JBC_33,
|
||||
MCS96_JBC_34,
|
||||
MCS96_JBC_35,
|
||||
MCS96_JBC_36,
|
||||
MCS96_JBC_37,
|
||||
MCS96_JBS_38,
|
||||
MCS96_JBS_39,
|
||||
MCS96_JBS_3A,
|
||||
MCS96_JBS_3B,
|
||||
MCS96_JBS_3C,
|
||||
MCS96_JBS_3D,
|
||||
MCS96_JBS_3E,
|
||||
MCS96_JBS_3F,
|
||||
MCS96_AND_40,
|
||||
MCS96_AND_41,
|
||||
MCS96_AND_42,
|
||||
MCS96_AND_43,
|
||||
MCS96_ADD_44,
|
||||
MCS96_ADD_45,
|
||||
MCS96_ADD_46,
|
||||
MCS96_ADD_47,
|
||||
MCS96_SUB_48,
|
||||
MCS96_SUB_49,
|
||||
MCS96_SUB_4A,
|
||||
MCS96_SUB_4B,
|
||||
MCS96_MULU_4C,
|
||||
MCS96_MULU_4D,
|
||||
MCS96_MULU_4E,
|
||||
MCS96_MULU_4F,
|
||||
MCS96_ANDB_50,
|
||||
MCS96_ANDB_51,
|
||||
MCS96_ANDB_52,
|
||||
MCS96_ANDB_53,
|
||||
MCS96_ADDB_54,
|
||||
MCS96_ADDB_55,
|
||||
MCS96_ADDB_56,
|
||||
MCS96_ADDB_57,
|
||||
MCS96_SUBB_58,
|
||||
MCS96_SUBB_59,
|
||||
MCS96_SUBB_5A,
|
||||
MCS96_SUBB_5B,
|
||||
MCS96_MULUB_5C,
|
||||
MCS96_MULUB_5D,
|
||||
MCS96_MULUB_5E,
|
||||
MCS96_MULUB_5F,
|
||||
MCS96_AND_60,
|
||||
MCS96_AND_61,
|
||||
MCS96_AND_62,
|
||||
MCS96_AND_63,
|
||||
MCS96_ADD_64,
|
||||
MCS96_ADD_65,
|
||||
MCS96_ADD_66,
|
||||
MCS96_ADD_67,
|
||||
MCS96_SUB_68,
|
||||
MCS96_SUB_69,
|
||||
MCS96_SUB_6A,
|
||||
MCS96_SUB_6B,
|
||||
MCS96_MULU_6C,
|
||||
MCS96_MULU_6D,
|
||||
MCS96_MULU_6E,
|
||||
MCS96_MULU_6F,
|
||||
MCS96_ANDB_70,
|
||||
MCS96_ANDB_71,
|
||||
MCS96_ANDB_72,
|
||||
MCS96_ANDB_73,
|
||||
MCS96_ADDB_74,
|
||||
MCS96_ADDB_75,
|
||||
MCS96_ADDB_76,
|
||||
MCS96_ADDB_77,
|
||||
MCS96_SUBB_78,
|
||||
MCS96_SUBB_79,
|
||||
MCS96_SUBB_7A,
|
||||
MCS96_SUBB_7B,
|
||||
MCS96_MULUB_7C,
|
||||
MCS96_MULUB_7D,
|
||||
MCS96_MULUB_7E,
|
||||
MCS96_MULUB_7F,
|
||||
MCS96_OR_80,
|
||||
MCS96_OR_81,
|
||||
MCS96_OR_82,
|
||||
MCS96_OR_83,
|
||||
MCS96_XOR_84,
|
||||
MCS96_XOR_85,
|
||||
MCS96_XOR_86,
|
||||
MCS96_XOR_87,
|
||||
MCS96_CMP_88,
|
||||
MCS96_CMP_89,
|
||||
MCS96_CMP_8A,
|
||||
MCS96_CMP_8B,
|
||||
MCS96_DIVU_8C,
|
||||
MCS96_DIVU_8D,
|
||||
MCS96_DIVU_8E,
|
||||
MCS96_DIVU_8F,
|
||||
MCS96_ORB_90,
|
||||
MCS96_ORB_91,
|
||||
MCS96_ORB_92,
|
||||
MCS96_ORB_93,
|
||||
MCS96_XORB_94,
|
||||
MCS96_XORB_95,
|
||||
MCS96_XORB_96,
|
||||
MCS96_XORB_97,
|
||||
MCS96_CMPB_98,
|
||||
MCS96_CMPB_99,
|
||||
MCS96_CMPB_9A,
|
||||
MCS96_CMPB_9B,
|
||||
MCS96_DIVUB_9C,
|
||||
MCS96_DIVUB_9D,
|
||||
MCS96_DIVUB_9E,
|
||||
MCS96_DIVUB_9F,
|
||||
MCS96_LD_A0,
|
||||
MCS96_LD_A1,
|
||||
MCS96_LD_A2,
|
||||
MCS96_LD_A3,
|
||||
MCS96_ADDC_A4,
|
||||
MCS96_ADDC_A5,
|
||||
MCS96_ADDC_A6,
|
||||
MCS96_ADDC_A7,
|
||||
MCS96_SUBC_A8,
|
||||
MCS96_SUBC_A9,
|
||||
MCS96_SUBC_AA,
|
||||
MCS96_SUBC_AB,
|
||||
MCS96_LDBZE_AC,
|
||||
MCS96_LDBZE_AD,
|
||||
MCS96_LDBZE_AE,
|
||||
MCS96_LDBZE_AF,
|
||||
MCS96_LDB_B0,
|
||||
MCS96_LDB_B1,
|
||||
MCS96_LDB_B2,
|
||||
MCS96_LDB_B3,
|
||||
MCS96_ADDCB_B4,
|
||||
MCS96_ADDCB_B5,
|
||||
MCS96_ADDCB_B6,
|
||||
MCS96_ADDCB_B7,
|
||||
MCS96_SUBCB_B8,
|
||||
MCS96_SUBCB_B9,
|
||||
MCS96_SUBCB_BA,
|
||||
MCS96_SUBCB_BB,
|
||||
MCS96_LDBSE_BC,
|
||||
MCS96_LDBSE_BD,
|
||||
MCS96_LDBSE_BE,
|
||||
MCS96_LDBSE_BF,
|
||||
MCS96_ST_C0,
|
||||
MCS96_BMOV_C1,
|
||||
MCS96_ST_C2,
|
||||
MCS96_ST_C3,
|
||||
MCS96_STB_C4,
|
||||
MCS96_CMPL_C5,
|
||||
MCS96_STB_C6,
|
||||
MCS96_STB_C7,
|
||||
MCS96_PUSH_C8,
|
||||
MCS96_PUSH_C9,
|
||||
MCS96_PUSH_CA,
|
||||
MCS96_PUSH_CB,
|
||||
MCS96_POP_CC,
|
||||
MCS96_BMOVI_CD,
|
||||
MCS96_POP_CE,
|
||||
MCS96_POP_CF,
|
||||
MCS96_JNST_D0,
|
||||
MCS96_JNH_D1,
|
||||
MCS96_JGT_D2,
|
||||
MCS96_JNC_D3,
|
||||
MCS96_JNVT_D4,
|
||||
MCS96_JNV_D5,
|
||||
MCS96_JGE_D6,
|
||||
MCS96_JNE_D7,
|
||||
MCS96_JST_D8,
|
||||
MCS96_JH_D9,
|
||||
MCS96_JLE_DA,
|
||||
MCS96_JC_DB,
|
||||
MCS96_JVT_DC,
|
||||
MCS96_JV_DD,
|
||||
MCS96_JLT_DE,
|
||||
MCS96_JE_DF,
|
||||
MCS96_DJNZ_E0,
|
||||
MCS96_DJNZW_E1,
|
||||
MCS96_TIJMP_E2,
|
||||
MCS96_BR_E3,
|
||||
MCS96_EBMOVI_E4,
|
||||
MCS96_RETI_E5,
|
||||
MCS96_EJMP_E6,
|
||||
MCS96_LJMP_E7,
|
||||
MCS96_ELD_E8,
|
||||
MCS96_ELD_E9,
|
||||
MCS96_ELDB_EA,
|
||||
MCS96_ELDB_EB,
|
||||
MCS96_DPTS_EC,
|
||||
MCS96_EPTS_ED,
|
||||
MCS96_INVALID_EE,
|
||||
MCS96_LCALL_EF,
|
||||
MCS96_RET_F0,
|
||||
MCS96_ECALL_F1,
|
||||
MCS96_PUSHF_F2,
|
||||
MCS96_POPF_F3,
|
||||
MCS96_PUSHA_F4,
|
||||
MCS96_POPA_F5,
|
||||
MCS96_IDLPD_F6,
|
||||
MCS96_TRAP_F7,
|
||||
MCS96_CLRC_F8,
|
||||
MCS96_SETC_F9,
|
||||
MCS96_DI_FA,
|
||||
MCS96_EI_FB,
|
||||
MCS96_CLRVT_FC,
|
||||
MCS96_NOP_FD,
|
||||
MCS96_MUL_DIV_FE,
|
||||
MCS96_RST_FF,
|
||||
} Mcs96Instructions;
|
||||
|
||||
static const char *mcs96_fe_op[] = { "mul", "mulb", "mul", "mulb", "div", "divb", "invalid", "invalid" };
|
||||
// in theory these invalids can never happen
|
||||
|
||||
typedef enum {
|
||||
MCS96_ADDRESSING_REG_DIRECT = 0,
|
||||
MCS96_ADDRESSING_IMMEDIATE = 1,
|
||||
MCS96_ADDRESSING_INDIRECT = 2,
|
||||
MCS96_ADDRESSING_INDEXED = 3,
|
||||
} Mcs96AddressingMode;
|
||||
|
||||
static inline ut32 compute_fe_index(ut8 byte) {
|
||||
return ((byte & 0x70) >> 4) ^ 0x4;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief computes the length of an instruction.
|
||||
* \return int the length of the instruction. returns -1 when invalid.
|
||||
*/
|
||||
static int mcs96_len(ut32 isa_bit, const ut8 *buf, int len) {
|
||||
if (len < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(mcs96_op[buf[0]].isa & isa_bit)) { // unsupported instruction
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = 1;
|
||||
if (buf[0] == 0xfe) {
|
||||
if (isa_bit == MCS96_80296) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len < 2) {
|
||||
return 0;
|
||||
}
|
||||
if (mcs96_op[buf[1]].type & MCS96_FE) {
|
||||
if (mcs96_op[buf[1]].type & MCS96_5B_OR_6B) {
|
||||
if (len < 3) {
|
||||
return 0;
|
||||
}
|
||||
ret = 6 + (buf[2] & 0x1);
|
||||
}
|
||||
if (mcs96_op[buf[1]].type & MCS96_4B_OR_5B) {
|
||||
if (len < 3) {
|
||||
return 0;
|
||||
}
|
||||
ret = 5 + (buf[2] & 0x1);
|
||||
}
|
||||
if (mcs96_op[buf[1]].type & MCS96_3B_OR_4B) {
|
||||
if (len < 3) {
|
||||
return 0;
|
||||
}
|
||||
ret = 4 + (buf[1] & 0x1);
|
||||
}
|
||||
if (mcs96_op[buf[1]].type & MCS96_5B) {
|
||||
ret = 6;
|
||||
}
|
||||
if (mcs96_op[buf[1]].type & MCS96_4B) {
|
||||
ret = 5;
|
||||
}
|
||||
if (mcs96_op[buf[1]].type & MCS96_3B) {
|
||||
ret = 4;
|
||||
}
|
||||
if (mcs96_op[buf[1]].type & MCS96_2B) {
|
||||
ret = 3;
|
||||
}
|
||||
if (ret > len) {
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (mcs96_op[buf[0]].type & MCS96_5B_OR_6B) {
|
||||
if (len < 2) {
|
||||
return 0;
|
||||
}
|
||||
ret = 5 + (buf[1] & 0x1);
|
||||
}
|
||||
if (mcs96_op[buf[0]].type & MCS96_4B_OR_5B) {
|
||||
if (len < 2) {
|
||||
return 0;
|
||||
}
|
||||
ret = 4 + (buf[1] & 0x1);
|
||||
}
|
||||
if (mcs96_op[buf[0]].type & MCS96_3B_OR_4B) {
|
||||
if (len < 2) {
|
||||
return 0;
|
||||
}
|
||||
ret = 3 + (buf[1] & 0x1);
|
||||
}
|
||||
if (mcs96_op[buf[0]].type & MCS96_6B) {
|
||||
ret = 6;
|
||||
}
|
||||
if (mcs96_op[buf[0]].type & MCS96_5B) {
|
||||
ret = 5;
|
||||
}
|
||||
if (mcs96_op[buf[0]].type & MCS96_4B) {
|
||||
ret = 4;
|
||||
}
|
||||
if (mcs96_op[buf[0]].type & MCS96_3B) {
|
||||
ret = 3;
|
||||
}
|
||||
if (mcs96_op[buf[0]].type & MCS96_2B) {
|
||||
ret = 2;
|
||||
}
|
||||
if (ret > len) {
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract addressing mode from MCS-96 instruction opcode.
|
||||
* The lower 2 bits (aa) encode the addressing mode for many instructions.
|
||||
* Format: (xxxxxxaa)
|
||||
*
|
||||
* \param opcode The instruction opcode byte
|
||||
* \return Addressing mode (0-3)
|
||||
*/
|
||||
static inline Mcs96AddressingMode extract_addressing_mode(ut8 opcode) {
|
||||
return (Mcs96AddressingMode)(opcode & 0x03);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract 11-bit signed displacement from sjmp/scall instruction.
|
||||
* Format: (instr|xxx)(disp-low)
|
||||
*
|
||||
* \param opcode First byte of the instruction, containing upper 3 bits of the displacement
|
||||
* \param disp_low Second byte of the instruction, containing lower 8 bits of the displacement
|
||||
* \return Sign-extended 16-bit displacement (-1024 to +1023)
|
||||
*/
|
||||
static inline st16 extract_disp11(ut8 opcode, ut8 disp_low) {
|
||||
st16 upper3bits = (st16)(opcode & 0x07); // 0b00000111
|
||||
st16 disp = (upper3bits << 8) | disp_low;
|
||||
|
||||
// Sign-extend from 11 bits to 16 bits
|
||||
if (disp & 0x400) { // Check if bit 10 (sign bit) is set
|
||||
disp |= 0xF800; // Set bits 15-11 to extend the sign
|
||||
}
|
||||
|
||||
return disp;
|
||||
}
|
||||
|
||||
#endif /* MCS96_H */
|
||||
|
|
|
|||
1098
librz/arch/p/analysis/analysis_mcs96.c
Normal file
1098
librz/arch/p/analysis/analysis_mcs96.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -5,5 +5,6 @@
|
|||
#include <deprecated_arch_helper.h>
|
||||
|
||||
#include "asm/asm_mcs96.c"
|
||||
#include "analysis/analysis_mcs96.c"
|
||||
|
||||
RZ_ARCH_ASM_ONLY_PLUGIN_DEFINE_DEPRECATED(mcs96);
|
||||
RZ_ARCH_PLUGIN_DEFINE_DEPRECATED(mcs96);
|
||||
|
|
|
|||
|
|
@ -10,13 +10,6 @@
|
|||
#include "rz_analysis.h"
|
||||
#include "rz_util/rz_pj.h"
|
||||
|
||||
typedef enum {
|
||||
MCS96_ADDRESSING_REG_DIRECT = 0, // 2 reg
|
||||
MCS96_ADDRESSING_IMMEDIATE = 1, // 1 reg + 1 imm
|
||||
MCS96_ADDRESSING_INDIRECT = 2, //
|
||||
MCS96_ADDRESSING_INDEXED = 3,
|
||||
} MCS96_ADDRESSING_MODE;
|
||||
|
||||
typedef struct {
|
||||
RzPVector /*<RzAsmTokenPattern *>*/ *token_patterns;
|
||||
} Mcs96Context;
|
||||
|
|
@ -44,235 +37,6 @@ static RZ_OWN RzPVector /*<RzAsmTokenPattern *>*/ *get_token_patterns() {
|
|||
return pvec;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief computes the length of an instruction.
|
||||
* @return int the length of the instruction. returns -1 when invalid.
|
||||
*/
|
||||
static int mcs96_len(ut32 isa_bit, const ut8 *buf, int len) {
|
||||
if (len < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(mcs96_op[buf[0]].isa & isa_bit)) { // unsupported instruction
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = 1;
|
||||
if (buf[0] == 0xfe) {
|
||||
if (isa_bit == MCS96_80296) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len < 2) {
|
||||
return 0;
|
||||
}
|
||||
if (mcs96_op[buf[1]].type & MCS96_FE) {
|
||||
if (mcs96_op[buf[1]].type & MCS96_5B_OR_6B) {
|
||||
if (len < 3) {
|
||||
return 0;
|
||||
}
|
||||
ret = 6 + (buf[2] & 0x1);
|
||||
}
|
||||
if (mcs96_op[buf[1]].type & MCS96_4B_OR_5B) {
|
||||
if (len < 3) {
|
||||
return 0;
|
||||
}
|
||||
ret = 5 + (buf[2] & 0x1);
|
||||
}
|
||||
if (mcs96_op[buf[1]].type & MCS96_3B_OR_4B) {
|
||||
if (len < 3) {
|
||||
return 0;
|
||||
}
|
||||
ret = 4 + (buf[1] & 0x1);
|
||||
}
|
||||
if (mcs96_op[buf[1]].type & MCS96_5B) {
|
||||
ret = 6;
|
||||
}
|
||||
if (mcs96_op[buf[1]].type & MCS96_4B) {
|
||||
ret = 5;
|
||||
}
|
||||
if (mcs96_op[buf[1]].type & MCS96_3B) {
|
||||
ret = 4;
|
||||
}
|
||||
if (mcs96_op[buf[1]].type & MCS96_2B) {
|
||||
ret = 3;
|
||||
}
|
||||
if (ret > len) {
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (mcs96_op[buf[0]].type & MCS96_5B_OR_6B) {
|
||||
if (len < 2) {
|
||||
return 0;
|
||||
}
|
||||
ret = 5 + (buf[1] & 0x1);
|
||||
}
|
||||
if (mcs96_op[buf[0]].type & MCS96_4B_OR_5B) {
|
||||
if (len < 2) {
|
||||
return 0;
|
||||
}
|
||||
ret = 4 + (buf[1] & 0x1);
|
||||
}
|
||||
if (mcs96_op[buf[0]].type & MCS96_3B_OR_4B) {
|
||||
if (len < 2) {
|
||||
return 0;
|
||||
}
|
||||
ret = 3 + (buf[1] & 0x1);
|
||||
}
|
||||
if (mcs96_op[buf[0]].type & MCS96_6B) {
|
||||
ret = 6;
|
||||
}
|
||||
if (mcs96_op[buf[0]].type & MCS96_5B) {
|
||||
ret = 5;
|
||||
}
|
||||
if (mcs96_op[buf[0]].type & MCS96_4B) {
|
||||
ret = 4;
|
||||
}
|
||||
if (mcs96_op[buf[0]].type & MCS96_3B) {
|
||||
ret = 3;
|
||||
}
|
||||
if (mcs96_op[buf[0]].type & MCS96_2B) {
|
||||
ret = 2;
|
||||
}
|
||||
if (ret > len) {
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char *decode_mnemonic(const ut8 *buf, int size, ut32 isa_bit) {
|
||||
if (size <= 0) {
|
||||
return "invalid";
|
||||
}
|
||||
|
||||
if (buf[0] == 0x0d && isa_bit == MCS96_80296 && size == 3) { // SHLL/MVAC/MSAC
|
||||
ut8 lreg_bits = buf[2] & 0x3;
|
||||
// lreg.1 lreg.0 Execute
|
||||
// 0 0 SHLL
|
||||
// 0 1 MVAC
|
||||
// 1 0 Reserved
|
||||
// 1 1 MSAC
|
||||
switch (lreg_bits) {
|
||||
case 0x0:
|
||||
return "shll";
|
||||
case 0x1:
|
||||
return "mvac";
|
||||
case 0x3:
|
||||
return "msac";
|
||||
default:
|
||||
return "invalid";
|
||||
}
|
||||
} else if (buf[0] == 0x40 && isa_bit == MCS96_80296 && buf[size - 1] == 0x04 && size == 4) { // AND/RPT/RPTxxx/RPTI/RPTIxxx
|
||||
// RPT waop
|
||||
// (010000aa) (waop) (00) (04)
|
||||
// RPTxxx
|
||||
// (010000aa) (waop) (10 - 1F) (04)
|
||||
// RPTI
|
||||
// (010000aa) (waop) (20) (04)
|
||||
// RPTIxxx
|
||||
// (010000aa) (waop) (30 - 3F) (04)
|
||||
switch (buf[size - 2]) {
|
||||
case 0x00:
|
||||
return "rpt";
|
||||
case 0x10:
|
||||
return "rptnst";
|
||||
case 0x11:
|
||||
return "rptnh";
|
||||
case 0x12:
|
||||
return "rptgt";
|
||||
case 0x13:
|
||||
return "rptnc";
|
||||
case 0x14:
|
||||
return "rptnvt";
|
||||
case 0x15:
|
||||
return "rptnv";
|
||||
case 0x16:
|
||||
return "rptge";
|
||||
case 0x17:
|
||||
return "rptne";
|
||||
case 0x18:
|
||||
return "rptst";
|
||||
case 0x19:
|
||||
return "rpth";
|
||||
case 0x1a:
|
||||
return "rptle";
|
||||
case 0x1b:
|
||||
return "rptc";
|
||||
case 0x1c:
|
||||
return "rptvt";
|
||||
case 0x1d:
|
||||
return "rptv";
|
||||
case 0x1e:
|
||||
return "rptlt";
|
||||
case 0x1f:
|
||||
return "rpte";
|
||||
case 0x20:
|
||||
return "rpti";
|
||||
case 0x30:
|
||||
return "rptinst";
|
||||
case 0x31:
|
||||
return "rptinh";
|
||||
case 0x32:
|
||||
return "rptigt";
|
||||
case 0x33:
|
||||
return "rptinc";
|
||||
case 0x34:
|
||||
return "rptinvt";
|
||||
case 0x35:
|
||||
return "rptinv";
|
||||
case 0x36:
|
||||
return "rptige";
|
||||
case 0x37:
|
||||
return "rptine";
|
||||
case 0x38:
|
||||
return "rptist";
|
||||
case 0x39:
|
||||
return "rptih";
|
||||
case 0x3a:
|
||||
return "rptile";
|
||||
case 0x3b:
|
||||
return "rptic";
|
||||
case 0x3c:
|
||||
return "rptivt";
|
||||
case 0x3d:
|
||||
return "rptiv";
|
||||
case 0x3e:
|
||||
return "rptilt";
|
||||
case 0x3f:
|
||||
return "rptie";
|
||||
default:
|
||||
return "and";
|
||||
}
|
||||
} else if (mcs96_op[buf[1]].type & MCS96_FE && size > 2) {
|
||||
const ut32 fe_idx = ((buf[1] & 0x70) >> 4) ^ 0x4;
|
||||
return mcs96_fe_op[fe_idx];
|
||||
} else {
|
||||
return mcs96_op[buf[0]].ins;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract 11-bit signed displacement from sjmp/scall instruction.
|
||||
* Format: (instr|xxx)(disp-low)
|
||||
*
|
||||
* \param opcode First byte of the instruction, containing upper 3 bits of the displacement
|
||||
* \param disp_low Second byte of the instruction, containing lower 8 bits of the displacement
|
||||
* \return Sign-extended 16-bit displacement (-1024 to +1023)
|
||||
*/
|
||||
static st16 extract_disp11(ut8 opcode, ut8 disp_low) {
|
||||
st16 upper3bits = (st16)(opcode & 0x07); // 0b00000111
|
||||
st16 disp = (upper3bits << 8) | disp_low;
|
||||
|
||||
// Sign-extend from 11 bits to 16 bits
|
||||
if (disp & 0x400) { // Check if bit 10 (sign bit) is set
|
||||
disp |= 0xF800; // Set bits 15-11 to extend the sign
|
||||
}
|
||||
|
||||
return disp;
|
||||
}
|
||||
|
||||
static void decode_operands(RzAsmOp *op, const char *mnemonic, const ut8 *buf, int size, ut32 isa_bit) {
|
||||
if (size < 1) {
|
||||
return;
|
||||
|
|
@ -415,6 +179,117 @@ static void decode_operands(RzAsmOp *op, const char *mnemonic, const ut8 *buf, i
|
|||
}
|
||||
}
|
||||
|
||||
static const char *decode_mnemonic(const ut8 *buf, int size, ut32 isa_bit) {
|
||||
if (size <= 0) {
|
||||
return "invalid";
|
||||
}
|
||||
|
||||
if (buf[0] == 0x0d && isa_bit == MCS96_80296 && size == 3) { // SHLL/MVAC/MSAC
|
||||
ut8 lreg_bits = buf[2] & 0x3;
|
||||
// lreg.1 lreg.0 Execute
|
||||
// 0 0 SHLL
|
||||
// 0 1 MVAC
|
||||
// 1 0 Reserved
|
||||
// 1 1 MSAC
|
||||
switch (lreg_bits) {
|
||||
case 0x0:
|
||||
return "shll";
|
||||
case 0x1:
|
||||
return "mvac";
|
||||
case 0x3:
|
||||
return "msac";
|
||||
default:
|
||||
return "invalid";
|
||||
}
|
||||
} else if (buf[0] == 0x40 && isa_bit == MCS96_80296 && size == 4 && buf[size - 1] == 0x04) { // AND/RPT/RPTxxx/RPTI/RPTIxxx
|
||||
// RPT waop
|
||||
// (010000aa) (waop) (00) (04)
|
||||
// RPTxxx
|
||||
// (010000aa) (waop) (10 - 1F) (04)
|
||||
// RPTI
|
||||
// (010000aa) (waop) (20) (04)
|
||||
// RPTIxxx
|
||||
// (010000aa) (waop) (30 - 3F) (04)
|
||||
switch (buf[size - 2]) {
|
||||
case 0x00:
|
||||
return "rpt";
|
||||
case 0x10:
|
||||
return "rptnst";
|
||||
case 0x11:
|
||||
return "rptnh";
|
||||
case 0x12:
|
||||
return "rptgt";
|
||||
case 0x13:
|
||||
return "rptnc";
|
||||
case 0x14:
|
||||
return "rptnvt";
|
||||
case 0x15:
|
||||
return "rptnv";
|
||||
case 0x16:
|
||||
return "rptge";
|
||||
case 0x17:
|
||||
return "rptne";
|
||||
case 0x18:
|
||||
return "rptst";
|
||||
case 0x19:
|
||||
return "rpth";
|
||||
case 0x1a:
|
||||
return "rptle";
|
||||
case 0x1b:
|
||||
return "rptc";
|
||||
case 0x1c:
|
||||
return "rptvt";
|
||||
case 0x1d:
|
||||
return "rptv";
|
||||
case 0x1e:
|
||||
return "rptlt";
|
||||
case 0x1f:
|
||||
return "rpte";
|
||||
case 0x20:
|
||||
return "rpti";
|
||||
case 0x30:
|
||||
return "rptinst";
|
||||
case 0x31:
|
||||
return "rptinh";
|
||||
case 0x32:
|
||||
return "rptigt";
|
||||
case 0x33:
|
||||
return "rptinc";
|
||||
case 0x34:
|
||||
return "rptinvt";
|
||||
case 0x35:
|
||||
return "rptinv";
|
||||
case 0x36:
|
||||
return "rptige";
|
||||
case 0x37:
|
||||
return "rptine";
|
||||
case 0x38:
|
||||
return "rptist";
|
||||
case 0x39:
|
||||
return "rptih";
|
||||
case 0x3a:
|
||||
return "rptile";
|
||||
case 0x3b:
|
||||
return "rptic";
|
||||
case 0x3c:
|
||||
return "rptivt";
|
||||
case 0x3d:
|
||||
return "rptiv";
|
||||
case 0x3e:
|
||||
return "rptilt";
|
||||
case 0x3f:
|
||||
return "rptie";
|
||||
default:
|
||||
return "and";
|
||||
}
|
||||
} else if (size > 2 && mcs96_op[buf[1]].type & MCS96_FE) {
|
||||
const ut32 fe_idx = ((buf[1] & 0x70) >> 4) ^ 0x4;
|
||||
return mcs96_fe_op[fe_idx];
|
||||
} else {
|
||||
return mcs96_op[buf[0]].ins;
|
||||
}
|
||||
}
|
||||
|
||||
static bool init(void **u) {
|
||||
if (!u) {
|
||||
return false;
|
||||
|
|
@ -480,7 +355,7 @@ RzAsmPlugin rz_asm_plugin_mcs96 = {
|
|||
.license = "LGPL3",
|
||||
.author = "condret",
|
||||
.bits = 16,
|
||||
.endian = RZ_SYS_ENDIAN_NONE,
|
||||
.endian = RZ_SYS_ENDIAN_LITTLE,
|
||||
.init = &init,
|
||||
.fini = &fini,
|
||||
.disassemble = &disassemble
|
||||
|
|
|
|||
92
test/db/analysis/mcs96
Normal file
92
test/db/analysis/mcs96
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
NAME=mcs96 byte tests
|
||||
FILE=malloc://4096
|
||||
CMDS=<<EOF
|
||||
e asm.arch=mcs96
|
||||
e asm.cpu=8096
|
||||
ar
|
||||
echo ----
|
||||
wx 2010
|
||||
ao 1~type,jump
|
||||
echo ----
|
||||
wx f0
|
||||
ao 1~type,stackptr
|
||||
echo ----
|
||||
wx cc10
|
||||
ao 1~type,stackptr
|
||||
echo ----
|
||||
wx a0010203
|
||||
ao 1~type,ptr
|
||||
echo ----
|
||||
wx a1123412
|
||||
ao 1~type,val
|
||||
echo ----
|
||||
wx 65123401
|
||||
ao 1~type,val
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
pc = 0x0000
|
||||
sp = 0x0000
|
||||
psw = 0x0000
|
||||
garbage = 0x0000
|
||||
garbage = 0x0000
|
||||
garbage = 0x0000
|
||||
----
|
||||
type: jmp
|
||||
jump: 0x00000012
|
||||
----
|
||||
type: ret
|
||||
stackptr: 2
|
||||
----
|
||||
type: pop
|
||||
stackptr: 2
|
||||
----
|
||||
ptr: 0x00000201
|
||||
refptr: 2
|
||||
type: load
|
||||
----
|
||||
val: 0x00003412
|
||||
type: load
|
||||
----
|
||||
val: 0x00003412
|
||||
type: add
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=mcs96 fib.bin tests
|
||||
FILE=bins/mcs96/fib.bin
|
||||
ARGS=-m 0x2080
|
||||
CMDS=<<EOF
|
||||
e asm.arch=mcs96
|
||||
e asm.cpu=8096
|
||||
aaa
|
||||
pdf
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
; CALL XREFS from fcn.00002080 @ 0x2098, 0x20a7
|
||||
/ fcn.00002080();
|
||||
| 0x00002080 push 0x1a ; [0xa31a:2]=0xffff
|
||||
| 0x00002082 ld 0x1a 0x04[0x18]
|
||||
| 0x00002086 cmp 0x1a 0x0001
|
||||
| ,=< 0x0000208a jgt 0x05
|
||||
| | 0x0000208c ld 0x1c 0x1a ; [0x1c1a:2]=0xffff
|
||||
| ,==< 0x0000208f sjmp 0x0026
|
||||
| |`-> 0x00002091 ld 0x1c 0x1a ; [0x1c1a:2]=0xffff
|
||||
| | 0x00002094 dec 0x1c
|
||||
| | 0x00002096 push 0x1c ; [0x2f1c:2]=0xffff
|
||||
| | 0x00002098 scall 0xffe6
|
||||
| | 0x0000209a add 0x18 0x0002
|
||||
| | 0x0000209e push 0x1c ; [0x491c:2]=0xffff
|
||||
| | 0x000020a0 sub 0x1c 0x1a 0x0002
|
||||
| | 0x000020a5 push 0x1c ; [0x2f1c:2]=0xffff
|
||||
| | 0x000020a7 scall 0xffd7
|
||||
| | 0x000020a9 add 0x18 0x0002
|
||||
| | 0x000020ad pop 0x1e
|
||||
| | 0x000020af add 0x1e 0x1c ; [0x1e1c:2]=0xffff
|
||||
| | 0x000020b2 ld 0x1c 0x1e ; [0x1c1e:2]=0xffff
|
||||
| |,=< 0x000020b5 sjmp 0x0000
|
||||
| || ; CODE XREFS from fcn.00002080 @ 0x208f, 0x20b5
|
||||
| ``-> 0x000020b7 pop 0x1a
|
||||
\ 0x000020b9 ret
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ _dA__ 8 32 m680x BSD Motorola 680X Capstone-based disassembler
|
|||
_dA__ 32 m68k BSD Motorola 68K Capstone-based disassembler
|
||||
_dA__ 32 malbolge LGPL3 Malbolge Ternary VM bytecode disassembler (by condret)
|
||||
_dA__ 32 mcore LGPL3 Motorola MCORE disassembler
|
||||
_d___ 16 mcs96 LGPL3 Intel MCS-96 disassembler (by condret)
|
||||
_dA__ 16 mcs96 LGPL3 Intel MCS-96 disassembler (by condret)
|
||||
adAeI 16 32 64 mips BSD MIPS Capstone-based disassembler
|
||||
_dA_I 16 msp430 LGPL3 Texas Instruments MSP430 disassembler
|
||||
adA__ 16 32 64 null MIT NULL (empty) disassembler (by pancake) v1.0.0
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue