Rizin
unix-like reverse engineering framework and cli tools
analysis_or1k.c File Reference
#include <rz_asm.h>
#include <rz_analysis.h>
#include <rz_lib.h>
#include <or1k_disas.h>

Go to the source code of this file.

Classes

struct  operands
 

Functions

static ut64 n_oper_to_addr (ut32 n, ut32 mask, ut64 addr)
 Convert raw N operand to complete address. More...
 
static int insn_to_op (RzAnalysis *a, RzAnalysisOp *op, ut64 addr, insn_t *descr, insn_extra_t *extra, ut32 insn)
 
static int or1k_op (RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask)
 

Variables

static ut32 cpu [32] = { 0 }
 
static ut32 cpu_enable
 
RzAnalysisPlugin rz_analysis_plugin_or1k
 
RZ_API RzLibStruct rizin_plugin
 

Function Documentation

◆ insn_to_op()

static int insn_to_op ( RzAnalysis a,
RzAnalysisOp op,
ut64  addr,
insn_t descr,
insn_extra_t extra,
ut32  insn 
)
static

Definition at line 41 of file analysis_or1k.c.

41  {
42  struct operands o = { 0 };
43  insn_type_t type = type_of_opcode(descr, extra);
44  insn_type_descr_t *type_descr = &types[INSN_X];
45 
46  /* only use type descriptor if it has some useful data */
48  type_descr = &types[type];
49  }
50 
51  if (extra == NULL) {
52  op->type = descr->insn_type;
53  } else {
54  op->type = extra->insn_type;
55  }
56 
57  switch ((insn & INSN_OPCODE_MASK) >> INSN_OPCODE_SHIFT) {
58  case 0x00: /* l.j */
59  o.n = get_operand_value(insn, type_descr, INSN_OPER_N);
60  op->eob = true;
61  op->jump = n_oper_to_addr(o.n, get_operand_mask(type_descr, INSN_OPER_N),
62  addr);
63  op->delay = 1;
64  break;
65  case 0x01: /* l.jal */
66  o.n = get_operand_value(insn, type_descr, INSN_OPER_N);
67  op->eob = true;
68  op->jump = n_oper_to_addr(o.n, get_operand_mask(type_descr, INSN_OPER_N),
69  addr);
70  op->delay = 1;
71  break;
72  case 0x03: /* l.bnf */
73  o.n = get_operand_value(insn, type_descr, INSN_OPER_N);
74  op->cond = RZ_TYPE_COND_NE;
75  op->jump = n_oper_to_addr(o.n, get_operand_mask(type_descr, INSN_OPER_N),
76  addr);
77  op->fail = addr + 8;
78  op->delay = 1;
79  break;
80  case 0x04: /* l.bf */
81  o.n = get_operand_value(insn, type_descr, INSN_OPER_N);
82  op->cond = RZ_TYPE_COND_EQ;
83  op->jump = n_oper_to_addr(o.n, get_operand_mask(type_descr, INSN_OPER_N),
84  addr);
85  op->fail = addr + 8;
86  op->delay = 1;
87  break;
88  case 0x11: /* l.jr */
89  o.rb = get_operand_value(insn, type_descr, INSN_OPER_B);
90  op->eob = true;
91  if (cpu_enable & (1 << o.rb)) {
92  op->jump = cpu[o.rb];
93  }
94  op->delay = 1;
95  break;
96  case 0x12: /* l.jalr */
97  o.rb = get_operand_value(insn, type_descr, INSN_OPER_B);
98  op->eob = true;
99  if (cpu_enable & (1 << o.rb)) {
100  op->jump = cpu[o.rb];
101  }
102  op->delay = 1;
103  break;
104  case 0x06: /* extended */
105  switch (insn & (1 << 16)) {
106  case 0: /* l.movhi */
107  o.rd = get_operand_value(insn, type_descr, INSN_OPER_D);
108  o.k = get_operand_value(insn, type_descr, INSN_OPER_K);
109  cpu[o.rd] = o.k << 16;
110  cpu_enable |= (1 << o.rd);
111  break;
112  case 1: /* l.macrc */
113  break;
114  }
115  break;
116  case 0x27: /* l.addi */
117  o.rd = get_operand_value(insn, type_descr, INSN_OPER_D);
118  o.ra = get_operand_value(insn, type_descr, INSN_OPER_A);
119  o.i = get_operand_value(insn, type_descr, INSN_OPER_I);
120  if (cpu_enable & (1 << o.ra) & cpu_enable & (1 << o.rd)) {
121  cpu[o.rd] = cpu[o.ra] | o.i;
122  cpu_enable |= (1 << o.rd);
123  op->ptr = cpu[o.rd];
124  op->direction = 8; /* reference */
125  }
126  break;
127  case 0x2a: /* l.ori */
128  o.rd = get_operand_value(insn, type_descr, INSN_OPER_D);
129  o.ra = get_operand_value(insn, type_descr, INSN_OPER_A);
130  o.i = get_operand_value(insn, type_descr, INSN_OPER_I);
131  if (cpu_enable & (1 << o.ra)) {
132  cpu[o.rd] = cpu[o.ra] | o.i;
133  cpu_enable |= (1 << o.rd);
134  op->ptr = cpu[o.rd];
135  op->direction = 8; /* reference */
136  }
137  break;
138  default:
139  /* if unknown instruction encountered, better forget state */
140  cpu_enable = 0;
141  }
142 
143  /* temporary solution to prevent using wrong register values */
145  /* FIXME: handle delay slot after branches */
146  cpu_enable = 0;
147  }
148  return 4;
149 }
static ut32 cpu[32]
Definition: analysis_or1k.c:21
static ut32 cpu_enable
Definition: analysis_or1k.c:22
static ut64 n_oper_to_addr(ut32 n, ut32 mask, ut64 addr)
Convert raw N operand to complete address.
Definition: analysis_or1k.c:34
#define NULL
Definition: cris-opc.c:27
int type
Definition: mipsasm.c:17
insn_type_descr_t types[]
Definition: or1k_disas.c:7
static ut32 get_operand_mask(insn_type_descr_t *type_descr, insn_oper_t operand)
Definition: or1k_disas.h:152
static int is_type_descriptor_defined(insn_type_t type)
Definition: or1k_disas.h:168
static int has_type_descriptor(insn_type_t type)
Definition: or1k_disas.h:164
@ INSN_X
Definition: or1k_disas.h:55
static ut32 get_operand_value(ut32 insn, insn_type_descr_t *type_descr, insn_oper_t operand)
Definition: or1k_disas.h:160
@ INSN_OPER_A
Definition: or1k_disas.h:83
@ INSN_OPER_B
Definition: or1k_disas.h:84
@ INSN_OPER_I
Definition: or1k_disas.h:88
@ INSN_OPER_N
Definition: or1k_disas.h:85
@ INSN_OPER_K
Definition: or1k_disas.h:86
@ INSN_OPER_D
Definition: or1k_disas.h:87
static insn_type_t type_of_opcode(insn_t *descr, insn_extra_t *extra_descr)
Definition: or1k_disas.h:172
#define INSN_OPCODE_MASK
Definition: or1k_disas.h:10
#define INSN_OPCODE_SHIFT
Definition: or1k_disas.h:11
enum insn_type insn_type_t
@ RZ_ANALYSIS_OP_TYPE_JMP
Definition: rz_analysis.h:368
@ RZ_TYPE_COND_EQ
Equal.
Definition: rz_type.h:184
@ RZ_TYPE_COND_NE
Not equal.
Definition: rz_type.h:185
int insn_type
Definition: or1k_disas.h:117
Definition: dis.c:32
static int addr
Definition: z80asm.c:58

References addr, cpu, cpu_enable, get_operand_mask(), get_operand_value(), has_type_descriptor(), operands::i, INSN_OPCODE_MASK, INSN_OPCODE_SHIFT, INSN_OPER_A, INSN_OPER_B, INSN_OPER_D, INSN_OPER_I, INSN_OPER_K, INSN_OPER_N, insn_extra_t::insn_type, insn_t::insn_type, INSN_X, is_type_descriptor_defined(), operands::k, operands::n, n_oper_to_addr(), NULL, operands::ra, operands::rb, operands::rd, RZ_ANALYSIS_OP_TYPE_JMP, RZ_TYPE_COND_EQ, RZ_TYPE_COND_NE, type, type_of_opcode(), and types.

Referenced by or1k_op().

◆ n_oper_to_addr()

static ut64 n_oper_to_addr ( ut32  n,
ut32  mask,
ut64  addr 
)
static

Convert raw N operand to complete address.

Parameters
nimmediate, as appearing in instruction
maskn operand mask
addraddress of current instruction
Returns
64-bit address

Definition at line 34 of file analysis_or1k.c.

34  {
35  /* sign extension returns 32b unsigned N, then it is multiplied by 4, made
36  * signed to support negative offsets, added to address and made unsigned
37  * again */
38  return (ut64)((st64)((st32)(sign_extend(n, mask) << 2)) + addr);
39 }
#define mask()
static void sign_extend(st32 *value, ut8 bit)
int n
Definition: mipsasm.c:19
#define st64
Definition: rz_types_base.h:10
#define st32
Definition: rz_types_base.h:12
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References addr, mask, n, sign_extend(), st32, st64, and ut64().

Referenced by insn_to_op().

◆ or1k_op()

static int or1k_op ( RzAnalysis a,
RzAnalysisOp op,
ut64  addr,
const ut8 data,
int  len,
RzAnalysisOpMask  mask 
)
static

Definition at line 151 of file analysis_or1k.c.

151  {
152  ut32 insn, opcode;
153  ut8 opcode_idx;
154  insn_t *insn_descr;
155  insn_extra_t *extra_descr;
156 
157  /* read instruction and basic opcode value */
158  insn = rz_read_be32(data);
159  op->size = 4;
160  opcode = (insn & INSN_OPCODE_MASK);
161  opcode_idx = opcode >> INSN_OPCODE_SHIFT;
162 
163  /* make sure instruction descriptor table is not overflowed */
164  if (opcode_idx >= insns_count) {
165  return op->size;
166  }
167 
168  /* if instruction is marked as invalid finish processing now */
169  insn_descr = &or1k_insns[opcode_idx];
170  if (insn_descr->type == INSN_INVAL) {
171  return op->size;
172  }
173 
174  /* if name is null, but extra is present, it means 6 most significant bits
175  * are not enough to decode instruction */
176  if ((insn_descr->name == NULL) && (insn_descr->extra != NULL)) {
177  extra_descr = find_extra_descriptor(insn_descr->extra, insn);
178  if (extra_descr != NULL) {
179  insn_to_op(a, op, addr, insn_descr, extra_descr, insn);
180  }
181  } else {
182  /* otherwise basic descriptor is enough */
183  insn_to_op(a, op, addr, insn_descr, NULL, insn);
184  }
185 
186  return op->size;
187 }
static int insn_to_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, insn_t *descr, insn_extra_t *extra, ut32 insn)
Definition: analysis_or1k.c:41
uint32_t ut32
uint8_t ut8
Definition: lh5801.h:11
insn_t or1k_insns[]
Definition: or1k_disas.c:219
size_t insns_count
Definition: or1k_disas.c:286
insn_extra_t * find_extra_descriptor(insn_extra_t *extra_descr, ut32 insn)
Definition: or1k_disas.c:288
@ INSN_INVAL
Definition: or1k_disas.h:54
static ut32 rz_read_be32(const void *src)
Definition: rz_endian.h:87
#define a(i)
Definition: sha256.c:41
insn_extra_t * extra
Definition: or1k_disas.h:118
char * name
Definition: or1k_disas.h:115
int type
Definition: or1k_disas.h:116

References a, addr, insn_t::extra, find_extra_descriptor(), INSN_INVAL, INSN_OPCODE_MASK, INSN_OPCODE_SHIFT, insn_to_op(), insns_count, insn_t::name, NULL, or1k_insns, rz_read_be32(), and insn_t::type.

Variable Documentation

◆ cpu

◆ cpu_enable

ut32 cpu_enable
static

Definition at line 22 of file analysis_or1k.c.

Referenced by insn_to_op().

◆ rizin_plugin

RZ_API RzLibStruct rizin_plugin
Initial value:
= {
}
RzAnalysisPlugin rz_analysis_plugin_or1k
@ RZ_LIB_TYPE_ANALYSIS
Definition: rz_lib.h:73
#define RZ_VERSION
Definition: rz_version.h:8
const char * version
Definition: rz_analysis.h:1239

Definition at line 200 of file analysis_or1k.c.

◆ rz_analysis_plugin_or1k

RzAnalysisPlugin rz_analysis_plugin_or1k
Initial value:
= {
.name = "or1k",
.desc = "OpenRISC 1000",
.license = "LGPL3",
.bits = 32,
.arch = "or1k",
.esil = false,
.op = &or1k_op,
}
static int or1k_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask)

Definition at line 189 of file analysis_or1k.c.