Rizin
unix-like reverse engineering framework and cli tools
M680XInstPrinter.c
Go to the documentation of this file.
1 /* Capstone Disassembly Engine */
2 /* M680X Backend by Wolfgang Schwotzer <wolfgang.schwotzer@gmx.net> 2017 */
3 
4 #ifdef CAPSTONE_HAS_M680X
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <capstone/platform.h>
9 
10 #include "../../cs_priv.h"
11 #include "../../MCInst.h"
12 #include "../../SStream.h"
13 #include "../../MCRegisterInfo.h"
14 #include "../../utils.h"
15 #include "M680XInstPrinter.h"
16 #include "M680XDisassembler.h"
18 
19 #ifndef CAPSTONE_DIET
20 static const char s_reg_names[][10] = {
21  "<invalid>", "a", "b", "e", "f", "0", "d", "w", "cc", "dp", "md",
22  "hx", "h", "x", "y", "s", "u", "v", "q", "pc", "tmp2", "tmp3",
23 };
24 
25 static const char s_instruction_names[][6] = {
26  "invld", "aba", "abx", "aby", "adc", "adca", "adcb", "adcd", "adcr",
27  "add", "adda", "addb", "addd", "adde", "addf", "addr", "addw",
28  "aim", "ais", "aix", "and", "anda", "andb", "andcc", "andd", "andr",
29  "asl", "asla", "aslb", "asld",
30  "asr", "asra", "asrb", "asrd", "asrx",
31  "band",
32  "bcc", "bclr", "bcs", "beor", "beq", "bge", "bgnd", "bgt", "bhcc",
33  "bhcs", "bhi",
34  "biand", "bieor", "bih", "bil",
35  "bior", "bit", "bita", "bitb", "bitd", "bitmd", "ble", "bls", "blt",
36  "bmc",
37  "bmi", "bms",
38  "bne", "bor", "bpl", "brclr", "brset", "bra", "brn", "bset", "bsr",
39  "bvc", "bvs",
40  "call", "cba", "cbeq", "cbeqa", "cbeqx", "clc", "cli",
41  "clr", "clra", "clrb", "clrd", "clre", "clrf", "clrh", "clrw", "clrx",
42  "clv", "cmp",
43  "cmpa", "cmpb", "cmpd", "cmpe", "cmpf", "cmpr", "cmps", "cmpu", "cmpw",
44  "cmpx", "cmpy",
45  "com", "coma", "comb", "comd", "come", "comf", "comw", "comx", "cpd",
46  "cphx", "cps", "cpx", "cpy",
47  "cwai", "daa", "dbeq", "dbne", "dbnz", "dbnza", "dbnzx",
48  "dec", "deca", "decb", "decd", "dece", "decf", "decw",
49  "decx", "des", "dex", "dey",
50  "div", "divd", "divq", "ediv", "edivs", "eim", "emacs", "emaxd",
51  "emaxm", "emind", "eminm", "emul", "emuls",
52  "eor", "eora", "eorb", "eord", "eorr", "etbl",
53  "exg", "fdiv", "ibeq", "ibne", "idiv", "idivs", "illgl",
54  "inc", "inca", "incb", "incd", "ince", "incf", "incw", "incx",
55  "ins", "inx", "iny",
56  "jmp", "jsr",
57  "lbcc", "lbcs", "lbeq", "lbge", "lbgt", "lbhi", "lble", "lbls", "lblt",
58  "lbmi", "lbne", "lbpl", "lbra", "lbrn", "lbsr", "lbvc", "lbvs",
59  "lda", "ldaa", "ldab", "ldb", "ldbt", "ldd", "lde", "ldf", "ldhx",
60  "ldmd",
61  "ldq", "lds", "ldu", "ldw", "ldx", "ldy",
62  "leas", "leau", "leax", "leay",
63  "lsl", "lsla", "lslb", "lsld", "lslx",
64  "lsr", "lsra", "lsrb", "lsrd", "lsrw", "lsrx",
65  "maxa", "maxm", "mem", "mina", "minm", "mov", "movb", "movw", "mul",
66  "muld",
67  "neg", "nega", "negb", "negd", "negx",
68  "nop", "nsa", "oim", "ora", "oraa", "orab", "orb", "orcc", "ord", "orr",
69  "psha", "pshb", "pshc", "pshd", "pshh", "pshs", "pshsw", "pshu",
70  "pshuw", "pshx", "pshy",
71  "pula", "pulb", "pulc", "puld", "pulh", "puls", "pulsw", "pulu",
72  "puluw", "pulx", "puly", "rev", "revw",
73  "rol", "rola", "rolb", "rold", "rolw", "rolx",
74  "ror", "rora", "rorb", "rord", "rorw", "rorx",
75  "rsp", "rtc", "rti", "rts", "sba", "sbc", "sbca", "sbcb", "sbcd",
76  "sbcr",
77  "sec", "sei", "sev", "sex", "sexw", "slp", "sta", "staa", "stab", "stb",
78  "stbt", "std", "ste", "stf", "stop", "sthx",
79  "stq", "sts", "stu", "stw", "stx", "sty",
80  "sub", "suba", "subb", "subd", "sube", "subf", "subr", "subw",
81  "swi", "swi2", "swi3",
82  "sync", "tab", "tap", "tax", "tba", "tbeq", "tbl", "tbne", "test",
83  "tfm", "tfr",
84  "tim", "tpa",
85  "tst", "tsta", "tstb", "tstd", "tste", "tstf", "tstw", "tstx",
86  "tsx", "tsy", "txa", "txs", "tys", "wai", "wait", "wav", "wavr",
87  "xgdx", "xgdy",
88 };
89 
90 static name_map s_group_names[] = {
91  { M680X_GRP_INVALID, "<invalid>" },
92  { M680X_GRP_JUMP, "jump" },
93  { M680X_GRP_CALL, "call" },
94  { M680X_GRP_RET, "return" },
95  { M680X_GRP_INT, "interrupt" },
96  { M680X_GRP_IRET, "interrupt_return" },
97  { M680X_GRP_PRIV, "privileged" },
98  { M680X_GRP_BRAREL, "branch_relative" },
99 };
100 #endif
101 
102 static void printRegName(cs_struct *handle, SStream *OS, unsigned int reg)
103 {
104 #ifndef CAPSTONE_DIET
105  SStream_concat(OS, handle->reg_name((csh)handle, reg));
106 #endif
107 }
108 
109 static void printInstructionName(cs_struct *handle, SStream *OS,
110  unsigned int insn)
111 {
112 #ifndef CAPSTONE_DIET
113  SStream_concat(OS, handle->insn_name((csh)handle, insn));
114 #endif
115 }
116 
117 static uint32_t get_unsigned(int32_t value, int byte_size)
118 {
119  switch (byte_size) {
120  case 1:
121  return (uint32_t)(value & 0xff);
122 
123  case 2:
124  return (uint32_t)(value & 0xffff);
125 
126  default:
127  case 4:
128  return (uint32_t)value;
129  }
130 }
131 
132 static void printIncDec(bool isPost, SStream *O, m680x_info *info,
133  cs_m680x_op *op)
134 {
135  static const char s_inc_dec[][3] = { "--", "-", "", "+", "++" };
136 
137  if (!op->idx.inc_dec)
138  return;
139 
140  if ((!isPost && !(op->idx.flags & M680X_IDX_POST_INC_DEC)) ||
141  (isPost && (op->idx.flags & M680X_IDX_POST_INC_DEC))) {
142  const char *prePostfix = "";
143 
144  if (info->cpu_type == M680X_CPU_TYPE_CPU12)
145  prePostfix = (op->idx.inc_dec < 0) ? "-" : "+";
146  else if (op->idx.inc_dec >= -2 && (op->idx.inc_dec <= 2)) {
147  prePostfix = (char *)s_inc_dec[op->idx.inc_dec + 2];
148  }
149 
150  SStream_concat(O, prePostfix);
151  }
152 }
153 
154 static void printOperand(MCInst *MI, SStream *O, m680x_info *info,
155  cs_m680x_op *op)
156 {
157  switch (op->type) {
158  case M680X_OP_REGISTER:
159  printRegName(MI->csh, O, op->reg);
160  break;
161 
162  case M680X_OP_CONSTANT:
163  SStream_concat(O, "%u", op->const_val);
164  break;
165 
166  case M680X_OP_IMMEDIATE:
167  if (MI->csh->imm_unsigned)
168  SStream_concat(O, "#%u",
169  get_unsigned(op->imm, op->size));
170  else
171  SStream_concat(O, "#%d", op->imm);
172 
173  break;
174 
175  case M680X_OP_INDEXED:
176  if (op->idx.flags & M680X_IDX_INDIRECT)
177  SStream_concat(O, "[");
178 
179  if (op->idx.offset_reg != M680X_REG_INVALID)
180  printRegName(MI->csh, O, op->idx.offset_reg);
181  else if (op->idx.offset_bits > 0) {
182  if (op->idx.base_reg == M680X_REG_PC)
183  SStream_concat(O, "$%04x", op->idx.offset_addr);
184  else
185  SStream_concat(O, "%d", op->idx.offset);
186  }
187  else if (op->idx.inc_dec != 0 &&
188  info->cpu_type == M680X_CPU_TYPE_CPU12)
189  SStream_concat(O, "%d", abs(op->idx.inc_dec));
190 
191  if (!(op->idx.flags & M680X_IDX_NO_COMMA))
192  SStream_concat(O, ", ");
193 
194  printIncDec(false, O, info, op);
195 
196  printRegName(MI->csh, O, op->idx.base_reg);
197 
198  if (op->idx.base_reg == M680X_REG_PC &&
199  (op->idx.offset_bits > 0))
200  SStream_concat(O, "r");
201 
202  printIncDec(true, O, info, op);
203 
204  if (op->idx.flags & M680X_IDX_INDIRECT)
205  SStream_concat(O, "]");
206 
207  break;
208 
209  case M680X_OP_RELATIVE:
210  SStream_concat(O, "$%04x", op->rel.address);
211  break;
212 
213  case M680X_OP_DIRECT:
214  SStream_concat(O, "$%02x", op->direct_addr);
215  break;
216 
217  case M680X_OP_EXTENDED:
218  if (op->ext.indirect)
219  SStream_concat(O, "[$%04x]", op->ext.address);
220  else {
221  if (op->ext.address < 256) {
222  SStream_concat(O, ">$%04x", op->ext.address);
223  }
224  else {
225  SStream_concat(O, "$%04x", op->ext.address);
226  }
227  }
228 
229  break;
230 
231  default:
232  SStream_concat(O, "<invalid_operand>");
233  break;
234  }
235 }
236 
237 static const char *getDelimiter(m680x_info *info, cs_m680x *m680x)
238 {
239  bool indexed = false;
240  int count = 0;
241  int i;
242 
243  if (info->insn == M680X_INS_TFM)
244  return ", ";
245 
246  if (m680x->op_count > 1) {
247  for (i = 0; i < m680x->op_count; ++i) {
248  if (m680x->operands[i].type == M680X_OP_INDEXED)
249  indexed = true;
250 
251  if (m680x->operands[i].type != M680X_OP_REGISTER)
252  count++;
253  }
254  }
255 
256  return (indexed && (count >= 1)) ? "; " : ", ";
257 };
258 
259 void M680X_printInst(MCInst *MI, SStream *O, void *PrinterInfo)
260 {
261  m680x_info *info = (m680x_info *)PrinterInfo;
262  cs_m680x *m680x = &info->m680x;
263  cs_detail *detail = MI->flat_insn->detail;
264  int suppress_operands = 0;
265  const char *delimiter = getDelimiter(info, m680x);
266  int i;
267 
268  if (detail != NULL)
269  memcpy(&detail->m680x, m680x, sizeof(cs_m680x));
270 
271  if (info->insn == M680X_INS_INVLD || info->insn == M680X_INS_ILLGL) {
272  if (m680x->op_count)
273  SStream_concat(O, "fcb $%02x", m680x->operands[0].imm);
274  else
275  SStream_concat(O, "fcb $<unknown>");
276 
277  return;
278  }
279 
280  printInstructionName(MI->csh, O, info->insn);
281  SStream_concat(O, " ");
282 
283  if ((m680x->flags & M680X_FIRST_OP_IN_MNEM) != 0)
284  suppress_operands++;
285 
286  if ((m680x->flags & M680X_SECOND_OP_IN_MNEM) != 0)
287  suppress_operands++;
288 
289  for (i = 0; i < m680x->op_count; ++i) {
290  if (i >= suppress_operands) {
291  printOperand(MI, O, info, &m680x->operands[i]);
292 
293  if ((i + 1) != m680x->op_count)
294  SStream_concat(O, delimiter);
295  }
296  }
297 }
298 
299 const char *M680X_reg_name(csh handle, unsigned int reg)
300 {
301 #ifndef CAPSTONE_DIET
302 
303  if (reg >= ARR_SIZE(s_reg_names))
304  return NULL;
305 
306  return s_reg_names[(int)reg];
307 #else
308  return NULL;
309 #endif
310 }
311 
312 const char *M680X_insn_name(csh handle, unsigned int id)
313 {
314 #ifndef CAPSTONE_DIET
315 
316  if (id >= ARR_SIZE(s_instruction_names))
317  return NULL;
318  else
319  return s_instruction_names[(int)id];
320 
321 #else
322  return NULL;
323 #endif
324 }
325 
326 const char *M680X_group_name(csh handle, unsigned int id)
327 {
328 #ifndef CAPSTONE_DIET
329  return id2name(s_group_names, ARR_SIZE(s_group_names), id);
330 #else
331  return NULL;
332 #endif
333 }
334 
336 {
337 #ifndef CAPSTONE_DIET
338 
341  return CS_ERR_MODE;
342  }
343 
346  return CS_ERR_MODE;
347  }
348 
349  if (M680X_GRP_ENDING != ARR_SIZE(s_group_names)) {
350  CS_ASSERT(M680X_GRP_ENDING == ARR_SIZE(s_group_names));
351  return CS_ERR_MODE;
352  }
353 
354 #endif
355 
356  return CS_ERR_OK;
357 }
358 
359 #endif
360 
cs_err M680X_instprinter_init(cs_struct *ud)
@ M680X_CPU_TYPE_CPU12
const char * M680X_reg_name(csh handle, unsigned int reg)
const char * M680X_insn_name(csh handle, unsigned int id)
const char * M680X_group_name(csh handle, unsigned int id)
void M680X_printInst(MCInst *MI, struct SStream *O, void *Info)
static const char * s_instruction_names[]
static const char * s_reg_names[]
void SStream_concat(SStream *ss, const char *fmt,...)
Definition: SStream.c:45
lzma_index ** i
Definition: index.h:629
static mcore_handle handle
Definition: asm_mcore.c:8
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
size_t csh
Definition: capstone.h:71
static int value
Definition: cmd_api.c:93
#define NULL
Definition: cris-opc.c:27
#define CS_ASSERT(expr)
Definition: cs_priv.h:97
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
@ OS
Definition: inflate.h:24
#define reg(n)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
#define M680X_IDX_INDIRECT
Definition: m680x.h:76
@ M680X_INS_TFM
Definition: m680x.h:507
@ M680X_INS_ILLGL
Definition: m680x.h:332
@ M680X_INS_INVLD
Definition: m680x.h:173
@ M680X_INS_ENDING
Definition: m680x.h:530
#define M680X_IDX_NO_COMMA
Definition: m680x.h:77
#define M680X_FIRST_OP_IN_MNEM
Definition: m680x.h:159
@ M680X_REG_ENDING
<– mark the end of the list of registers
Definition: m680x.h:51
@ M680X_REG_INVALID
Definition: m680x.h:21
@ M680X_REG_PC
M6800/1/2/3/9, M6301/9.
Definition: m680x.h:46
#define M680X_IDX_POST_INC_DEC
Definition: m680x.h:78
@ M680X_OP_EXTENDED
= Extended addressing operand.
Definition: m680x.h:60
@ M680X_OP_INDEXED
= Indexed addressing operand.
Definition: m680x.h:59
@ M680X_OP_CONSTANT
Used e.g. for a bit index or page number.
Definition: m680x.h:63
@ M680X_OP_IMMEDIATE
= Immediate operand.
Definition: m680x.h:58
@ M680X_OP_REGISTER
= Register operand.
Definition: m680x.h:57
@ M680X_OP_RELATIVE
= Relative addressing operand.
Definition: m680x.h:62
@ M680X_OP_DIRECT
= Direct addressing operand.
Definition: m680x.h:61
#define M680X_SECOND_OP_IN_MNEM
Definition: m680x.h:162
@ M680X_GRP_PRIV
= CS_GRP_PRIVILEDGE; not used
Definition: m680x.h:147
@ M680X_GRP_BRAREL
= CS_GRP_BRANCH_RELATIVE
Definition: m680x.h:149
@ M680X_GRP_ENDING
Definition: m680x.h:152
@ M680X_GRP_IRET
= CS_GRP_IRET
Definition: m680x.h:145
@ M680X_GRP_RET
= CS_GRP_RET
Definition: m680x.h:141
@ M680X_GRP_INVALID
Definition: m680x.h:134
@ M680X_GRP_INT
= CS_GRP_INT
Definition: m680x.h:143
@ M680X_GRP_JUMP
= CS_GRP_INVALID
Definition: m680x.h:137
@ M680X_GRP_CALL
= CS_GRP_CALL
Definition: m680x.h:139
int CS_ERR_OK
Definition: __init__.py:235
int CS_ERR_MODE
Definition: __init__.py:240
#define ARR_SIZE(a)
Definition: ocaml.c:13
#define O
Definition: rcond.c:14
static int
Definition: sfsocketcall.h:114
int int32_t
Definition: sftypes.h:33
unsigned int uint32_t
Definition: sftypes.h:29
Definition: MCInst.h:88
cs_insn * flat_insn
Definition: MCInst.h:95
cs_struct * csh
Definition: MCInst.h:97
Definition: SStream.h:9
Instruction operand.
Definition: m680x.h:114
m680x_op_type type
Definition: m680x.h:115
int32_t imm
immediate value for IMM operand
Definition: m680x.h:117
The M680X instruction and it's operands.
Definition: m680x.h:165
uint8_t flags
See: M680X instruction flags.
Definition: m680x.h:166
cs_m680x_op operands[M680X_OPERAND_COUNT]
operands for this insn.
Definition: m680x.h:168
uint8_t op_count
number of operands for the instruction or 0
Definition: m680x.h:167
cs_opt_value imm_unsigned
Definition: cs_priv.h:68
Definition: utils.h:36
const char * id2name(const name_map *map, int max, const unsigned int id)
Definition: utils.c:56
Definition: dis.c:32
static int indexed
Definition: z80asm.c:70