Rizin
unix-like reverse engineering framework and cli tools
disassembler.c File Reference
#include "disassembler.h"
#include "common.h"
#include "regs.h"

Go to the source code of this file.

Functions

static SHParam sh_op_get_param (ut16 opcode, SHParamBuilder shb)
 Get SHParam from opcode Make sure the opcode is passed in little-endian form. More...
 
static SHParam sh_op_get_param_movl (ut16 opcode, bool m)
 Get params for mov.l instruction (0001NMD) A special function is required because the nibbles for the second param (@(disp:Rn)) (i.e. N and D) are separated by the nibble for the first param (Rm) (i.e. M), so sh_op_get_param cannot be used. More...
 
RZ_IPI RZ_OWN SHOpsh_disassembler (ut16 opcode)
 Disassemble opcode and return a SHOp. More...
 
RZ_IPI RZ_OWN char * sh_op_param_to_str (SHParam param, SHScaling scaling, ut64 pc)
 Return string representation of disassembled param. More...
 
RZ_IPI RZ_OWN char * sh_op_to_str (RZ_NONNULL const SHOp *op, ut64 pc)
 Return string representation of disassembled op. More...
 

Variables

const SHOpRaw sh_op_lookup []
 
const ut32 OPCODE_NUM
 

Function Documentation

◆ sh_disassembler()

RZ_IPI RZ_OWN SHOp* sh_disassembler ( ut16  opcode)

Disassemble opcode and return a SHOp.

Parameters
opcode16 bit wide opcode
Returns
SHOp object corresponding to the opcode

Definition at line 130 of file disassembler.c.

130  {
131  for (ut16 i = 0; i < OPCODE_NUM; i++) {
132  if ((opcode | sh_op_lookup[i].mask) != sh_op_lookup[i].opcode) {
133  continue;
134  }
135 
136  SHOpRaw raw = sh_op_lookup[i];
137  SHOp *op = RZ_NEW(SHOp);
138  op->opcode = opcode;
139  op->mnemonic = raw.mnemonic;
140  op->scaling = raw.scaling;
141  op->str_mnem = raw.str_mnem;
142  // check for "weird" mov.l
143  if (raw.opcode == MOVL) {
144  op->param[0] = sh_op_get_param_movl(opcode, true);
145  op->param[1] = sh_op_get_param_movl(opcode, false);
146  return op;
147  }
148  op->param[0] = sh_op_get_param(opcode, raw.param_builder[0]);
149  op->param[1] = sh_op_get_param(opcode, raw.param_builder[1]);
150  return op;
151  }
152 
153  RZ_LOG_DEBUG("SuperH: Invalid opcode encountered by disassembler: 0x%06x\n", opcode);
154  return NULL;
155 }
ut8 op
Definition: 6502dis.c:13
#define mask()
lzma_index ** i
Definition: index.h:629
#define NULL
Definition: cris-opc.c:27
uint16_t ut16
#define MOVL
Definition: common.h:70
#define RZ_LOG_DEBUG(fmtstr,...)
Definition: rz_log.h:49
#define RZ_NEW(x)
Definition: rz_types.h:285
static SHParam sh_op_get_param(ut16 opcode, SHParamBuilder shb)
Get SHParam from opcode Make sure the opcode is passed in little-endian form.
Definition: disassembler.c:18
const SHOpRaw sh_op_lookup[]
Definition: lookup.c:7
static SHParam sh_op_get_param_movl(ut16 opcode, bool m)
Get params for mov.l instruction (0001NMD) A special function is required because the nibbles for the...
Definition: disassembler.c:110
const ut32 OPCODE_NUM
Definition: lookup.c:195
const char * str_mnem
string mnemonic
Definition: common.h:25
SHScaling scaling
scaling for the opcode
Definition: common.h:29
SHOpMnem mnemonic
enum mnemonic
Definition: common.h:26
SHParamBuilder param_builder[2]
param builders for the params
Definition: common.h:30
ut16 opcode
opcode
Definition: common.h:27
Definition: dis.c:32

References i, mask, sh_op_raw_t::mnemonic, MOVL, NULL, op, sh_op_raw_t::opcode, OPCODE_NUM, sh_op_raw_t::param_builder, RZ_LOG_DEBUG, RZ_NEW, sh_op_raw_t::scaling, sh_op_get_param(), sh_op_get_param_movl(), sh_op_lookup, and sh_op_raw_t::str_mnem.

Referenced by disassemble(), and sh_op().

◆ sh_op_get_param()

static SHParam sh_op_get_param ( ut16  opcode,
SHParamBuilder  shb 
)
static

Get SHParam from opcode Make sure the opcode is passed in little-endian form.

Parameters
opcodeinstruction opcode (assumed to be in little-endian)
shbSHParamBuilder instance which contains the necessary info to find the param

Definition at line 18 of file disassembler.c.

18  {
19  if (shb.is_param) {
20  return shb.param;
21  }
22  if (shb.addr.mode == SH_ADDR_INVALID) {
23  SHParam invalid;
24  invalid.mode = SH_ADDR_INVALID;
25  return invalid;
26  }
27 
28  ut16 nibble = opcode >> shb.addr.start;
29  ut8 len = 0;
30 
31  if (shb.addr.bits != -1) {
32  // do not infer the bit length from mode
33  len = shb.addr.bits;
34  goto extract;
35  }
36 
37  switch (shb.addr.mode) {
38  case SH_REG_DIRECT:
39  case SH_REG_INDIRECT:
40  case SH_REG_INDIRECT_I:
41  case SH_REG_INDIRECT_D:
43  case SH_PC_RELATIVE_REG:
44  len = 4;
45  break;
49  case SH_PC_RELATIVE8:
50  case SH_IMM_S:
51  case SH_IMM_U:
52  len = 8;
53  break;
54  case SH_PC_RELATIVE12:
55  len = 12;
56  break;
57  default:
58  break;
59  }
60 
61 extract:
62 
63  nibble &= 0xffff >> (16 - len);
64 
65  SHParam ret_param;
66  ret_param.mode = shb.addr.mode;
67  switch (shb.addr.mode) {
68  case SH_REG_DIRECT:
69  case SH_REG_INDIRECT:
70  case SH_REG_INDIRECT_I:
71  case SH_REG_INDIRECT_D:
75  case SH_PC_RELATIVE8:
76  case SH_PC_RELATIVE12:
77  case SH_PC_RELATIVE_REG:
78  case SH_IMM_S:
79  case SH_IMM_U:
80  ret_param.param[0] = nibble;
81  break;
83  ret_param.param[0] = nibble >> 4;
84  ret_param.param[1] = nibble & 0xf;
85  break;
87  break;
88  default:
89  break;
90  }
91 
92  /* For the special case of banked registers in `LDC` and `STC`, the bit length is 3
93  In such case, we can modify the param found to correspond to its banked counterpart */
94  if (len == 3) {
95  ret_param.param[0] += SH_REG_IND_R0B;
96  }
97 
98  return ret_param;
99 }
size_t len
Definition: 6502dis.c:15
@ extract
Definition: aarch64.h:496
uint8_t ut8
Definition: lh5801.h:11
@ SH_REG_IND_R0B
Definition: disassembler.h:139
@ SH_PC_RELATIVE8
Definition: disassembler.h:28
@ SH_IMM_S
8-bit immediate value (sign-extended)
Definition: disassembler.h:32
@ SH_REG_INDIRECT_DISP
register indirect with displacement
Definition: disassembler.h:23
@ SH_PC_RELATIVE_DISP
Definition: disassembler.h:27
@ SH_REG_DIRECT
Definition: disassembler.h:19
@ SH_PC_RELATIVE_REG
Definition: disassembler.h:30
@ SH_PC_RELATIVE12
Definition: disassembler.h:29
@ SH_REG_INDIRECT_INDEXED
indexed register indirect
Definition: disassembler.h:24
@ SH_ADDR_INVALID
Definition: disassembler.h:18
@ SH_REG_INDIRECT_I
register indirect with post-increment
Definition: disassembler.h:21
@ SH_REG_INDIRECT
Definition: disassembler.h:20
@ SH_IMM_U
8-bit immediate value (zero-extended)
Definition: disassembler.h:31
@ SH_REG_INDIRECT_D
register indirect with pre-decrement
Definition: disassembler.h:22
@ SH_GBR_INDIRECT_DISP
Definition: disassembler.h:25
@ SH_GBR_INDIRECT_INDEXED
Definition: disassembler.h:26
ut8 start
start bit of the param (assuming little-endian)
Definition: common.h:10
SHAddrMode mode
addressing mode being used
Definition: common.h:12
st8 bits
bits to be read (-1, if you want this to be inferred from mode)
Definition: common.h:11
SHParam param
Definition: common.h:19
struct sh_param_builder_addr_t addr
Definition: common.h:18
bool is_param
whether a param was directly passed
Definition: common.h:21
ut16 param[2]
Definition: disassembler.h:238
SHAddrMode mode
Definition: disassembler.h:239

References sh_param_builder_t::addr, sh_param_builder_addr_t::bits, extract, sh_param_builder_t::is_param, len, sh_param_builder_addr_t::mode, sh_param_t::mode, sh_param_builder_t::param, sh_param_t::param, SH_ADDR_INVALID, SH_GBR_INDIRECT_DISP, SH_GBR_INDIRECT_INDEXED, SH_IMM_S, SH_IMM_U, SH_PC_RELATIVE12, SH_PC_RELATIVE8, SH_PC_RELATIVE_DISP, SH_PC_RELATIVE_REG, SH_REG_DIRECT, SH_REG_IND_R0B, SH_REG_INDIRECT, SH_REG_INDIRECT_D, SH_REG_INDIRECT_DISP, SH_REG_INDIRECT_I, SH_REG_INDIRECT_INDEXED, and sh_param_builder_addr_t::start.

Referenced by sh_disassembler().

◆ sh_op_get_param_movl()

static SHParam sh_op_get_param_movl ( ut16  opcode,
bool  m 
)
static

Get params for mov.l instruction (0001NMD) A special function is required because the nibbles for the second param (@(disp:Rn)) (i.e. N and D) are separated by the nibble for the first param (Rm) (i.e. M), so sh_op_get_param cannot be used.

Parameters
opcodeopcode
mif true, get Rm ; otherwise get @(disp:Rn)
Returns
SHParam return appropriate param

Definition at line 110 of file disassembler.c.

110  {
111  if (m) {
112  ut16 reg = (opcode >> 4) & 0xf;
113  return (SHParam){ .param = {
114  reg,
115  },
116  .mode = SH_REG_DIRECT };
117  } else {
118  ut16 d = opcode & 0xf;
119  ut16 n = (opcode >> 8) & 0xf;
120  return (SHParam){ .param = { n, d }, .mode = SH_REG_INDIRECT_DISP };
121  }
122 }
#define reg(n)
int n
Definition: mipsasm.c:19
#define d(i)
Definition: sha256.c:44

References d, regress::m, n, reg, SH_REG_DIRECT, and SH_REG_INDIRECT_DISP.

Referenced by sh_disassembler().

◆ sh_op_param_to_str()

RZ_IPI RZ_OWN char* sh_op_param_to_str ( SHParam  param,
SHScaling  scaling,
ut64  pc 
)

Return string representation of disassembled param.

Parameters
SHParamto be disassembled
SHScalingof the instruction associated with the param
Returns
char *, owned by the caller

Definition at line 166 of file disassembler.c.

166  {
167  if (param.mode == SH_ADDR_INVALID) {
168  return NULL;
169  }
170 
172  switch (param.mode) {
173  case SH_REG_DIRECT:
174  rz_strbuf_appendf(buf, "%s", sh_registers[param.param[0]]);
175  break;
176  case SH_REG_INDIRECT:
177  rz_strbuf_appendf(buf, "@%s", sh_registers[param.param[0]]);
178  break;
179  case SH_REG_INDIRECT_I:
180  rz_strbuf_appendf(buf, "@%s+", sh_registers[param.param[0]]);
181  break;
182  case SH_REG_INDIRECT_D:
183  rz_strbuf_appendf(buf, "@-%s", sh_registers[param.param[0]]);
184  break;
186  rz_strbuf_appendf(buf, "@(0x%02x,%s)", param.param[1] * sh_scaling_size[scaling], sh_registers[param.param[0]]);
187  break;
189  rz_strbuf_appendf(buf, "@(r0,%s)", sh_registers[param.param[0]]);
190  break;
192  rz_strbuf_appendf(buf, "@(0x%03x,gbr)", param.param[0] * sh_scaling_size[scaling]);
193  break;
195  rz_strbuf_append(buf, "@(r0,gbr)");
196  break;
197  case SH_PC_RELATIVE_DISP:
198  rz_strbuf_appendf(buf, "@(0x%03x,pc)", param.param[0] * sh_scaling_size[scaling]);
199  break;
200  case SH_PC_RELATIVE8:
201  case SH_PC_RELATIVE12:
202  rz_strbuf_appendf(buf, "0x%08x", (ut32)pc + 4 + (st32)((st8)param.param[0]) * 2);
203  break;
204  case SH_PC_RELATIVE_REG:
205  rz_strbuf_appendf(buf, "%s", sh_registers[param.param[0]]);
206  break;
207  case SH_IMM_U:
208  case SH_IMM_S:
209  rz_strbuf_appendf(buf, "0x%02x", param.param[0]);
210  break;
211  default:
213  }
214 
215  return rz_strbuf_drain(buf);
216 }
uint32_t ut32
voidpf void * buf
Definition: ioapi.h:138
static const char * sh_registers[]
Definition: regs.h:10
#define rz_warn_if_reached()
Definition: rz_assert.h:29
RZ_API RZ_OWN char * rz_strbuf_drain(RzStrBuf *sb)
Definition: strbuf.c:342
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
RZ_API RzStrBuf * rz_strbuf_new(const char *s)
Definition: strbuf.c:8
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
#define st8
Definition: rz_types_base.h:16
#define st32
Definition: rz_types_base.h:12
static const ut8 sh_scaling_size[]
Definition: disassembler.h:43

References sh_param_t::mode, NULL, sh_param_t::param, pc, rz_strbuf_append(), rz_strbuf_appendf(), rz_strbuf_drain(), rz_strbuf_new(), rz_warn_if_reached, SH_ADDR_INVALID, SH_GBR_INDIRECT_DISP, SH_GBR_INDIRECT_INDEXED, SH_IMM_S, SH_IMM_U, SH_PC_RELATIVE12, SH_PC_RELATIVE8, SH_PC_RELATIVE_DISP, SH_PC_RELATIVE_REG, SH_REG_DIRECT, SH_REG_INDIRECT, SH_REG_INDIRECT_D, SH_REG_INDIRECT_DISP, SH_REG_INDIRECT_I, SH_REG_INDIRECT_INDEXED, sh_registers, sh_scaling_size, st32, and st8.

Referenced by sh_op_to_str().

◆ sh_op_to_str()

RZ_IPI RZ_OWN char* sh_op_to_str ( RZ_NONNULL const SHOp op,
ut64  pc 
)

Return string representation of disassembled op.

Parameters
SHOpto be disassembled
Returns
char *, owned by the caller

Definition at line 224 of file disassembler.c.

224  {
226  if (!op->str_mnem) {
227  return NULL;
228  }
229  RzStrBuf *buf = rz_strbuf_new(op->str_mnem);
230 
231  char *param = NULL;
232  if ((param = sh_op_param_to_str(op->param[0], op->scaling, pc))) {
233  rz_strbuf_appendf(buf, " %s", param);
234  free(param);
235  if ((param = sh_op_param_to_str(op->param[1], op->scaling, pc))) {
236  rz_strbuf_appendf(buf, ", %s", param);
237  free(param);
238  }
239  }
240 
241  return rz_strbuf_drain(buf);
242 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_IPI RZ_OWN char * sh_op_param_to_str(SHParam param, SHScaling scaling, ut64 pc)
Return string representation of disassembled param.
Definition: disassembler.c:166

References free(), NULL, pc, rz_return_val_if_fail, rz_strbuf_appendf(), rz_strbuf_drain(), rz_strbuf_new(), and sh_op_param_to_str().

Referenced by disassemble().

Variable Documentation

◆ OPCODE_NUM

const ut32 OPCODE_NUM
extern

Definition at line 195 of file lookup.c.

Referenced by sh_disassembler().

◆ sh_op_lookup

const SHOpRaw sh_op_lookup[]
extern

Definition at line 7 of file lookup.c.

Referenced by sh_disassembler().