xref: /aosp_15_r20/external/capstone/bindings/ocaml/test_m680x.ml (revision 9a0e4156d50a75a99ec4f1653a0e9602a5d45c18)
1*9a0e4156SSadaf Ebrahimi(* Capstone Disassembly Engine
2*9a0e4156SSadaf Ebrahimi* M680X Backend by Wolfgang Schwotzer <[email protected]> 2017 *)
3*9a0e4156SSadaf Ebrahimi
4*9a0e4156SSadaf Ebrahimiopen Printf
5*9a0e4156SSadaf Ebrahimiopen Capstone
6*9a0e4156SSadaf Ebrahimiopen M680x
7*9a0e4156SSadaf Ebrahimiopen M680x_const
8*9a0e4156SSadaf Ebrahimi
9*9a0e4156SSadaf Ebrahimi
10*9a0e4156SSadaf Ebrahimilet print_char_hex ch =
11*9a0e4156SSadaf Ebrahimi	printf " 0x%02X" (Char.code ch)
12*9a0e4156SSadaf Ebrahimi
13*9a0e4156SSadaf Ebrahimilet print_int_hex_short value =
14*9a0e4156SSadaf Ebrahimi	printf "%02X" value
15*9a0e4156SSadaf Ebrahimi
16*9a0e4156SSadaf Ebrahimilet print_string_hex comment str =
17*9a0e4156SSadaf Ebrahimi	printf "%s" comment;
18*9a0e4156SSadaf Ebrahimi	String.iter print_char_hex str;
19*9a0e4156SSadaf Ebrahimi	printf "\n"
20*9a0e4156SSadaf Ebrahimi
21*9a0e4156SSadaf Ebrahimilet print_array_hex_short arr =
22*9a0e4156SSadaf Ebrahimi	Array.iter print_int_hex_short arr
23*9a0e4156SSadaf Ebrahimi
24*9a0e4156SSadaf Ebrahimilet s_access = [
25*9a0e4156SSadaf Ebrahimi	"UNCHANGED"; "READ"; "WRITE"; "READ | WRITE" ];;
26*9a0e4156SSadaf Ebrahimi
27*9a0e4156SSadaf Ebrahimilet _M6800_CODE = "\x01\x09\x36\x64\x7f\x74\x10\x00\x90\x10\xA4\x10\xb6\x10\x00\x39";;
28*9a0e4156SSadaf Ebrahimilet _M6801_CODE = "\x04\x05\x3c\x3d\x38\x93\x10\xec\x10\xed\x10\x39";;
29*9a0e4156SSadaf Ebrahimilet _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";;
30*9a0e4156SSadaf Ebrahimilet _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";;
31*9a0e4156SSadaf Ebrahimilet _HD6301_CODE = "\x6b\x10\x00\x71\x10\x00\x72\x10\x10\x39";;
32*9a0e4156SSadaf Ebrahimilet _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";;
33*9a0e4156SSadaf Ebrahimilet _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";;
34*9a0e4156SSadaf Ebrahimilet _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";;
35*9a0e4156SSadaf Ebrahimilet _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";;
36*9a0e4156SSadaf Ebrahimilet _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*9a0e4156SSadaf Ebrahimi
38*9a0e4156SSadaf Ebrahimilet bit_set value mask =
39*9a0e4156SSadaf Ebrahimi	value land mask != 0
40*9a0e4156SSadaf Ebrahimi
41*9a0e4156SSadaf Ebrahimilet all_tests = [
42*9a0e4156SSadaf Ebrahimi        (CS_ARCH_M680X, [CS_MODE_M680X_6301], _HD6301_CODE, "M680X_HD6301");
43*9a0e4156SSadaf Ebrahimi        (CS_ARCH_M680X, [CS_MODE_M680X_6309], _HD6309_CODE, "M680X_HD6309");
44*9a0e4156SSadaf Ebrahimi        (CS_ARCH_M680X, [CS_MODE_M680X_6800], _M6800_CODE, "M680X_M6800");
45*9a0e4156SSadaf Ebrahimi        (CS_ARCH_M680X, [CS_MODE_M680X_6801], _M6801_CODE, "M680X_M6801");
46*9a0e4156SSadaf Ebrahimi        (CS_ARCH_M680X, [CS_MODE_M680X_6805], _M6805_CODE, "M680X_M68HC05");
47*9a0e4156SSadaf Ebrahimi        (CS_ARCH_M680X, [CS_MODE_M680X_6808], _M6808_CODE, "M680X_M68HC08");
48*9a0e4156SSadaf Ebrahimi        (CS_ARCH_M680X, [CS_MODE_M680X_6809], _M6809_CODE, "M680X_M6809");
49*9a0e4156SSadaf Ebrahimi        (CS_ARCH_M680X, [CS_MODE_M680X_6811], _M6811_CODE, "M680X_M68HC11");
50*9a0e4156SSadaf Ebrahimi        (CS_ARCH_M680X, [CS_MODE_M680X_CPU12], _CPU12_CODE, "M680X_CPU12");
51*9a0e4156SSadaf Ebrahimi        (CS_ARCH_M680X, [CS_MODE_M680X_HCS08], _HCS08_CODE, "M680X_HCS08");
52*9a0e4156SSadaf Ebrahimi];;
53*9a0e4156SSadaf Ebrahimi
54*9a0e4156SSadaf Ebrahimilet print_inc_dec inc_dec is_post = (
55*9a0e4156SSadaf Ebrahimi	printf "\t\t\t";
56*9a0e4156SSadaf Ebrahimi	if is_post then printf "post" else printf "pre";
57*9a0e4156SSadaf Ebrahimi	if inc_dec > 0 then
58*9a0e4156SSadaf Ebrahimi		printf " increment: %d\n" inc_dec
59*9a0e4156SSadaf Ebrahimi	else
60*9a0e4156SSadaf Ebrahimi		printf " decrement: %d\n" (abs inc_dec);
61*9a0e4156SSadaf Ebrahimi	);
62*9a0e4156SSadaf Ebrahimi	();;
63*9a0e4156SSadaf Ebrahimi
64*9a0e4156SSadaf Ebrahimilet print_op handle flags i op =
65*9a0e4156SSadaf Ebrahimi	( match op.value with
66*9a0e4156SSadaf Ebrahimi	| M680X_OP_INVALID _ -> ();	(* this would never happens *)
67*9a0e4156SSadaf Ebrahimi	| M680X_OP_REGISTER reg -> (
68*9a0e4156SSadaf Ebrahimi		printf "\t\toperands[%d].type: REGISTER = %s" i (cs_reg_name handle reg);
69*9a0e4156SSadaf Ebrahimi		if (((i == 0) && (bit_set flags _M680X_FIRST_OP_IN_MNEM)) ||
70*9a0e4156SSadaf Ebrahimi		    ((i == 1) && (bit_set flags _M680X_SECOND_OP_IN_MNEM))) then
71*9a0e4156SSadaf Ebrahimi			printf " (in mnemonic)";
72*9a0e4156SSadaf Ebrahimi		printf "\n";
73*9a0e4156SSadaf Ebrahimi		);
74*9a0e4156SSadaf Ebrahimi	| M680X_OP_IMMEDIATE imm ->
75*9a0e4156SSadaf Ebrahimi		printf "\t\toperands[%d].type: IMMEDIATE = #%d\n" i imm;
76*9a0e4156SSadaf Ebrahimi	| M680X_OP_DIRECT direct_addr ->
77*9a0e4156SSadaf Ebrahimi		printf "\t\toperands[%d].type: DIRECT = 0x%02X\n" i direct_addr;
78*9a0e4156SSadaf Ebrahimi	| M680X_OP_EXTENDED ext -> (
79*9a0e4156SSadaf Ebrahimi		printf "\t\toperands[%d].type: EXTENDED " i;
80*9a0e4156SSadaf Ebrahimi		if ext.indirect then
81*9a0e4156SSadaf Ebrahimi			printf "INDIRECT";
82*9a0e4156SSadaf Ebrahimi		printf " = 0x%04X\n" ext.addr_ext;
83*9a0e4156SSadaf Ebrahimi		);
84*9a0e4156SSadaf Ebrahimi	| M680X_OP_RELATIVE rel ->
85*9a0e4156SSadaf Ebrahimi		printf "\t\toperands[%d].type: RELATIVE = 0x%04X\n" i rel.addr_rel;
86*9a0e4156SSadaf Ebrahimi	| M680X_OP_INDEXED idx -> (
87*9a0e4156SSadaf Ebrahimi		printf "\t\toperands[%d].type: INDEXED" i;
88*9a0e4156SSadaf Ebrahimi		if (bit_set idx.flags _M680X_IDX_INDIRECT) then
89*9a0e4156SSadaf Ebrahimi			printf " INDIRECT";
90*9a0e4156SSadaf Ebrahimi		printf "\n";
91*9a0e4156SSadaf Ebrahimi		if idx.base_reg != _M680X_REG_INVALID then
92*9a0e4156SSadaf Ebrahimi			printf "\t\t\tbase register: %s\n" (cs_reg_name handle idx.base_reg);
93*9a0e4156SSadaf Ebrahimi		if idx.offset_reg != _M680X_REG_INVALID then
94*9a0e4156SSadaf Ebrahimi			printf "\t\t\toffset register: %s\n" (cs_reg_name handle idx.offset_reg);
95*9a0e4156SSadaf Ebrahimi		if idx.offset_bits != 0 && idx.offset_reg == 0 && idx.inc_dec == 0 then begin
96*9a0e4156SSadaf Ebrahimi			printf "\t\t\toffset: %d\n" idx.offset;
97*9a0e4156SSadaf Ebrahimi			if idx.base_reg == _M680X_REG_PC then
98*9a0e4156SSadaf Ebrahimi				printf "\t\t\toffset address: 0x%X\n" idx.offset_addr;
99*9a0e4156SSadaf Ebrahimi			printf "\t\t\toffset bits: %u\n" idx.offset_bits;
100*9a0e4156SSadaf Ebrahimi		end;
101*9a0e4156SSadaf Ebrahimi		if idx.inc_dec != 0 then
102*9a0e4156SSadaf Ebrahimi			print_inc_dec idx.inc_dec (bit_set idx.flags _M680X_IDX_POST_INC_DEC);
103*9a0e4156SSadaf Ebrahimi		);
104*9a0e4156SSadaf Ebrahimi	| M680X_OP_CONSTANT const_val ->
105*9a0e4156SSadaf Ebrahimi		printf "\t\toperands[%d].type: CONSTANT = %d\n" i const_val;
106*9a0e4156SSadaf Ebrahimi	);
107*9a0e4156SSadaf Ebrahimi
108*9a0e4156SSadaf Ebrahimi	if op.size != 0 then
109*9a0e4156SSadaf Ebrahimi		printf "\t\t\tsize: %d\n" op.size;
110*9a0e4156SSadaf Ebrahimi	if op.access != _CS_AC_INVALID then
111*9a0e4156SSadaf Ebrahimi		printf "\t\t\taccess: %s\n" (List.nth s_access op.access);
112*9a0e4156SSadaf Ebrahimi	();;
113*9a0e4156SSadaf Ebrahimi
114*9a0e4156SSadaf Ebrahimi
115*9a0e4156SSadaf Ebrahimilet print_detail handle insn =
116*9a0e4156SSadaf Ebrahimi	match insn.arch with
117*9a0e4156SSadaf Ebrahimi	| CS_INFO_M680X m680x -> (
118*9a0e4156SSadaf Ebrahimi			(* print all operands info (type & value) *)
119*9a0e4156SSadaf Ebrahimi			if (Array.length m680x.operands) > 0 then (
120*9a0e4156SSadaf Ebrahimi				printf "\top_count: %d\n" (Array.length m680x.operands);
121*9a0e4156SSadaf Ebrahimi				Array.iteri (print_op handle m680x.flags) m680x.operands;
122*9a0e4156SSadaf Ebrahimi			);
123*9a0e4156SSadaf Ebrahimi			);
124*9a0e4156SSadaf Ebrahimi	| _ -> ();
125*9a0e4156SSadaf Ebrahimi	;;
126*9a0e4156SSadaf Ebrahimi
127*9a0e4156SSadaf Ebrahimilet print_reg handle reg =
128*9a0e4156SSadaf Ebrahimi	printf " %s" (cs_reg_name handle reg)
129*9a0e4156SSadaf Ebrahimi
130*9a0e4156SSadaf Ebrahimilet print_insn handle insn =
131*9a0e4156SSadaf Ebrahimi	printf "0x%04X:\t" insn.address;
132*9a0e4156SSadaf Ebrahimi	print_array_hex_short insn.bytes;
133*9a0e4156SSadaf Ebrahimi	printf "\t%s\t%s\n" insn.mnemonic insn.op_str;
134*9a0e4156SSadaf Ebrahimi	print_detail handle insn;
135*9a0e4156SSadaf Ebrahimi	if (Array.length insn.regs_read) > 0 then begin
136*9a0e4156SSadaf Ebrahimi		printf "\tRegisters read:";
137*9a0e4156SSadaf Ebrahimi		Array.iter (print_reg handle) insn.regs_read;
138*9a0e4156SSadaf Ebrahimi		printf "\n";
139*9a0e4156SSadaf Ebrahimi	end;
140*9a0e4156SSadaf Ebrahimi	if (Array.length insn.regs_write) > 0 then begin
141*9a0e4156SSadaf Ebrahimi		printf "\tRegisters modified:";
142*9a0e4156SSadaf Ebrahimi		Array.iter (print_reg handle) insn.regs_write;
143*9a0e4156SSadaf Ebrahimi		printf "\n";
144*9a0e4156SSadaf Ebrahimi	end;
145*9a0e4156SSadaf Ebrahimi	if (Array.length insn.groups) > 0 then
146*9a0e4156SSadaf Ebrahimi		printf "\tgroups_count: %d\n" (Array.length insn.groups);
147*9a0e4156SSadaf Ebrahimi	printf "\n"
148*9a0e4156SSadaf Ebrahimi
149*9a0e4156SSadaf Ebrahimilet print_arch x =
150*9a0e4156SSadaf Ebrahimi	let (arch, mode, code, comment) = x in
151*9a0e4156SSadaf Ebrahimi		let handle = cs_open arch mode in
152*9a0e4156SSadaf Ebrahimi		let err = cs_option handle CS_OPT_DETAIL _CS_OPT_ON in
153*9a0e4156SSadaf Ebrahimi		match err with
154*9a0e4156SSadaf Ebrahimi		| _ -> ();
155*9a0e4156SSadaf Ebrahimi		let insns = cs_disasm handle code 0x1000L 0L in
156*9a0e4156SSadaf Ebrahimi			printf "********************\n";
157*9a0e4156SSadaf Ebrahimi			printf "Platform: %s\n" comment;
158*9a0e4156SSadaf Ebrahimi			print_string_hex "Code: " code;
159*9a0e4156SSadaf Ebrahimi			printf "Disasm:\n";
160*9a0e4156SSadaf Ebrahimi			List.iter (print_insn handle) insns;
161*9a0e4156SSadaf Ebrahimi		match cs_close handle with
162*9a0e4156SSadaf Ebrahimi		| 0 -> ();
163*9a0e4156SSadaf Ebrahimi		| _ -> printf "Failed to close handle";
164*9a0e4156SSadaf Ebrahimi		;;
165*9a0e4156SSadaf Ebrahimi
166*9a0e4156SSadaf EbrahimiList.iter print_arch all_tests;;
167*9a0e4156SSadaf Ebrahimi
168