1(* Capstone Disassembly Engine 2* M680X Backend by Wolfgang Schwotzer <wolfgang.schwotzer@gmx.net> 2017 *) 3 4open Printf 5open Capstone 6open M680x 7open M680x_const 8 9 10let print_char_hex ch = 11 printf " 0x%02X" (Char.code ch) 12 13let print_int_hex_short value = 14 printf "%02X" value 15 16let print_string_hex comment str = 17 printf "%s" comment; 18 String.iter print_char_hex str; 19 printf "\n" 20 21let print_array_hex_short arr = 22 Array.iter print_int_hex_short arr 23 24let s_access = [ 25 "UNCHANGED"; "READ"; "WRITE"; "READ | WRITE" ];; 26 27let _M6800_CODE = "\x01\x09\x36\x64\x7f\x74\x10\x00\x90\x10\xA4\x10\xb6\x10\x00\x39";; 28let _M6801_CODE = "\x04\x05\x3c\x3d\x38\x93\x10\xec\x10\xed\x10\x39";; 29let _M6805_CODE = "\x04\x7f\x00\x17\x22\x28\x00\x2e\x00\x40\x42\x5a\x70\x8e\x97\x9c\xa0\x15\xad\x00\xc3\x10\x00\xda\x12\x34\xe5\x7f\xfe";; 30let _M6808_CODE = "\x31\x22\x00\x35\x22\x45\x10\x00\x4b\x00\x51\x10\x52\x5e\x22\x62\x65\x12\x34\x72\x84\x85\x86\x87\x8a\x8b\x8c\x94\x95\xa7\x10\xaf\x10\x9e\x60\x7f\x9e\x6b\x7f\x00\x9e\xd6\x10\x00\x9e\xe6\x7f";; 31let _HD6301_CODE = "\x6b\x10\x00\x71\x10\x00\x72\x10\x10\x39";; 32let _M6809_CODE = "\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00\x11\xac\x99\x10\x00\x39\xA6\x07\xA6\x27\xA6\x47\xA6\x67\xA6\x0F\xA6\x10\xA6\x80\xA6\x81\xA6\x82\xA6\x83\xA6\x84\xA6\x85\xA6\x86\xA6\x88\x7F\xA6\x88\x80\xA6\x89\x7F\xFF\xA6\x89\x80\x00\xA6\x8B\xA6\x8C\x10\xA6\x8D\x10\x00\xA6\x91\xA6\x93\xA6\x94\xA6\x95\xA6\x96\xA6\x98\x7F\xA6\x98\x80\xA6\x99\x7F\xFF\xA6\x99\x80\x00\xA6\x9B\xA6\x9C\x10\xA6\x9D\x10\x00\xA6\x9F\x10\x00";; 33let _HD6309_CODE = "\x01\x10\x10\x62\x10\x10\x7b\x10\x10\x00\xcd\x49\x96\x02\xd2\x10\x30\x23\x10\x38\x10\x3b\x10\x53\x10\x5d\x11\x30\x43\x10\x11\x37\x25\x10\x11\x38\x12\x11\x39\x23\x11\x3b\x34\x11\x8e\x10\x00\x11\xaf\x10\x11\xab\x10\x11\xf6\x80\x00";; 34let _M6811_CODE = "\x02\x03\x12\x7f\x10\x00\x13\x99\x08\x00\x14\x7f\x02\x15\x7f\x01\x1e\x7f\x20\x00\x8f\xcf\x18\x08\x18\x30\x18\x3c\x18\x67\x18\x8c\x10\x00\x18\x8f\x18\xce\x10\x00\x18\xff\x10\x00\x1a\xa3\x7f\x1a\xac\x1a\xee\x7f\x1a\xef\x7f\xcd\xac\x7f";; 35let _CPU12_CODE = "\x00\x04\x01\x00\x0c\x00\x80\x0e\x00\x80\x00\x11\x1e\x10\x00\x80\x00\x3b\x4a\x10\x00\x04\x4b\x01\x04\x4f\x7f\x80\x00\x8f\x10\x00\xb7\x52\xb7\xb1\xa6\x67\xa6\xfe\xa6\xf7\x18\x02\xe2\x30\x39\xe2\x10\x00\x18\x0c\x30\x39\x10\x00\x18\x11\x18\x12\x10\x00\x18\x19\x00\x18\x1e\x00\x18\x3e\x18\x3f\x00";; 36let _HCS08_CODE = "\x32\x10\x00\x9e\xae\x9e\xce\x7f\x9e\xbe\x10\x00\x9e\xfe\x7f\x3e\x10\x00\x9e\xf3\x7f\x96\x10\x00\x9e\xff\x7f\x82";; 37 38let bit_set value mask = 39 value land mask != 0 40 41let all_tests = [ 42 (CS_ARCH_M680X, [CS_MODE_M680X_6301], _HD6301_CODE, "M680X_HD6301"); 43 (CS_ARCH_M680X, [CS_MODE_M680X_6309], _HD6309_CODE, "M680X_HD6309"); 44 (CS_ARCH_M680X, [CS_MODE_M680X_6800], _M6800_CODE, "M680X_M6800"); 45 (CS_ARCH_M680X, [CS_MODE_M680X_6801], _M6801_CODE, "M680X_M6801"); 46 (CS_ARCH_M680X, [CS_MODE_M680X_6805], _M6805_CODE, "M680X_M68HC05"); 47 (CS_ARCH_M680X, [CS_MODE_M680X_6808], _M6808_CODE, "M680X_M68HC08"); 48 (CS_ARCH_M680X, [CS_MODE_M680X_6809], _M6809_CODE, "M680X_M6809"); 49 (CS_ARCH_M680X, [CS_MODE_M680X_6811], _M6811_CODE, "M680X_M68HC11"); 50 (CS_ARCH_M680X, [CS_MODE_M680X_CPU12], _CPU12_CODE, "M680X_CPU12"); 51 (CS_ARCH_M680X, [CS_MODE_M680X_HCS08], _HCS08_CODE, "M680X_HCS08"); 52];; 53 54let print_inc_dec inc_dec is_post = ( 55 printf "\t\t\t"; 56 if is_post then printf "post" else printf "pre"; 57 if inc_dec > 0 then 58 printf " increment: %d\n" inc_dec 59 else 60 printf " decrement: %d\n" (abs inc_dec); 61 ); 62 ();; 63 64let print_op handle flags i op = 65 ( match op.value with 66 | M680X_OP_INVALID _ -> (); (* this would never happens *) 67 | M680X_OP_REGISTER reg -> ( 68 printf "\t\toperands[%d].type: REGISTER = %s" i (cs_reg_name handle reg); 69 if (((i == 0) && (bit_set flags _M680X_FIRST_OP_IN_MNEM)) || 70 ((i == 1) && (bit_set flags _M680X_SECOND_OP_IN_MNEM))) then 71 printf " (in mnemonic)"; 72 printf "\n"; 73 ); 74 | M680X_OP_IMMEDIATE imm -> 75 printf "\t\toperands[%d].type: IMMEDIATE = #%d\n" i imm; 76 | M680X_OP_DIRECT direct_addr -> 77 printf "\t\toperands[%d].type: DIRECT = 0x%02X\n" i direct_addr; 78 | M680X_OP_EXTENDED ext -> ( 79 printf "\t\toperands[%d].type: EXTENDED " i; 80 if ext.indirect then 81 printf "INDIRECT"; 82 printf " = 0x%04X\n" ext.addr_ext; 83 ); 84 | M680X_OP_RELATIVE rel -> 85 printf "\t\toperands[%d].type: RELATIVE = 0x%04X\n" i rel.addr_rel; 86 | M680X_OP_INDEXED idx -> ( 87 printf "\t\toperands[%d].type: INDEXED" i; 88 if (bit_set idx.flags _M680X_IDX_INDIRECT) then 89 printf " INDIRECT"; 90 printf "\n"; 91 if idx.base_reg != _M680X_REG_INVALID then 92 printf "\t\t\tbase register: %s\n" (cs_reg_name handle idx.base_reg); 93 if idx.offset_reg != _M680X_REG_INVALID then 94 printf "\t\t\toffset register: %s\n" (cs_reg_name handle idx.offset_reg); 95 if idx.offset_bits != 0 && idx.offset_reg == 0 && idx.inc_dec == 0 then begin 96 printf "\t\t\toffset: %d\n" idx.offset; 97 if idx.base_reg == _M680X_REG_PC then 98 printf "\t\t\toffset address: 0x%X\n" idx.offset_addr; 99 printf "\t\t\toffset bits: %u\n" idx.offset_bits; 100 end; 101 if idx.inc_dec != 0 then 102 print_inc_dec idx.inc_dec (bit_set idx.flags _M680X_IDX_POST_INC_DEC); 103 ); 104 | M680X_OP_CONSTANT const_val -> 105 printf "\t\toperands[%d].type: CONSTANT = %d\n" i const_val; 106 ); 107 108 if op.size != 0 then 109 printf "\t\t\tsize: %d\n" op.size; 110 if op.access != _CS_AC_INVALID then 111 printf "\t\t\taccess: %s\n" (List.nth s_access op.access); 112 ();; 113 114 115let print_detail handle insn = 116 match insn.arch with 117 | CS_INFO_M680X m680x -> ( 118 (* print all operands info (type & value) *) 119 if (Array.length m680x.operands) > 0 then ( 120 printf "\top_count: %d\n" (Array.length m680x.operands); 121 Array.iteri (print_op handle m680x.flags) m680x.operands; 122 ); 123 ); 124 | _ -> (); 125 ;; 126 127let print_reg handle reg = 128 printf " %s" (cs_reg_name handle reg) 129 130let print_insn handle insn = 131 printf "0x%04X:\t" insn.address; 132 print_array_hex_short insn.bytes; 133 printf "\t%s\t%s\n" insn.mnemonic insn.op_str; 134 print_detail handle insn; 135 if (Array.length insn.regs_read) > 0 then begin 136 printf "\tRegisters read:"; 137 Array.iter (print_reg handle) insn.regs_read; 138 printf "\n"; 139 end; 140 if (Array.length insn.regs_write) > 0 then begin 141 printf "\tRegisters modified:"; 142 Array.iter (print_reg handle) insn.regs_write; 143 printf "\n"; 144 end; 145 if (Array.length insn.groups) > 0 then 146 printf "\tgroups_count: %d\n" (Array.length insn.groups); 147 printf "\n" 148 149let print_arch x = 150 let (arch, mode, code, comment) = x in 151 let handle = cs_open arch mode in 152 let err = cs_option handle CS_OPT_DETAIL _CS_OPT_ON in 153 match err with 154 | _ -> (); 155 let insns = cs_disasm handle code 0x1000L 0L in 156 printf "********************\n"; 157 printf "Platform: %s\n" comment; 158 print_string_hex "Code: " code; 159 printf "Disasm:\n"; 160 List.iter (print_insn handle) insns; 161 match cs_close handle with 162 | 0 -> (); 163 | _ -> printf "Failed to close handle"; 164 ;; 165 166List.iter print_arch all_tests;; 167 168