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


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:17