Coverage Report

Created: 2026-07-16 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonev5/arch/SH/SHDisassembler.c
Line
Count
Source
1
/* Capstone Disassembly Engine */
2
/* By Yoshinori Sato, 2022 */
3
4
#include <string.h>
5
#include <stdarg.h>
6
#include "../../cs_priv.h"
7
#include "../../MCInst.h"
8
#include "../../MCDisassembler.h"
9
#include "../../utils.h"
10
#include "SHDisassembler.h"
11
#include "capstone/sh.h"
12
13
#define regs_read(_detail, _reg)          \
14
0
  if (_detail)             \
15
0
    _detail->regs_read[_detail->regs_read_count++] = _reg
16
#define regs_write(_detail, _reg)         \
17
0
  if (_detail)             \
18
0
    _detail->regs_write[_detail->regs_write_count++] = _reg
19
20
enum direction {read, write};
21
22
static void regs_rw(cs_detail *detail, enum direction rw, sh_reg reg)
23
0
{
24
0
  switch(rw) {
25
0
  case read:
26
0
    regs_read(detail, reg);
27
0
    break;
28
0
  case write:
29
0
    regs_write(detail, reg);
30
0
    break;
31
0
  }
32
0
}
33
34
static bool set_reg_n(sh_info *info, sh_reg reg, int pos, enum direction rw,
35
          cs_detail *detail)
36
0
{
37
0
  if (pos >= ARR_SIZE(info->op.operands)) {
38
0
    return false;
39
0
  }
40
0
  info->op.operands[pos].type = SH_OP_REG;
41
0
  info->op.operands[pos].reg = reg;
42
0
  regs_rw(detail, rw, reg);
43
0
  return true;
44
0
}
45
46
static void set_reg(sh_info *info, sh_reg reg, enum direction rw,
47
        cs_detail *detail)
48
0
{
49
0
  if (!set_reg_n(info, reg, info->op.op_count, rw, detail)) {
50
0
    return;
51
0
  }
52
0
  info->op.op_count++;
53
0
}
54
55
static bool set_mem_n(sh_info *info, sh_op_mem_type address, sh_reg reg,
56
          uint32_t disp, int sz, int pos, cs_detail *detail)
57
0
{
58
0
  if (pos >= ARR_SIZE(info->op.operands)) {
59
0
    return false;
60
0
  }
61
0
  info->op.operands[pos].type = SH_OP_MEM;
62
0
  info->op.operands[pos].mem.address = address;
63
0
  info->op.operands[pos].mem.reg = reg;
64
0
  info->op.operands[pos].mem.disp = disp;
65
0
  if (sz > 0)
66
0
    info->op.size = sz;
67
0
  switch (address) {
68
0
  case SH_OP_MEM_REG_POST:
69
0
  case SH_OP_MEM_REG_PRE:
70
0
    regs_write(detail, reg);
71
0
    break;
72
0
  case SH_OP_MEM_GBR_R0:
73
0
    regs_read(detail, SH_REG_GBR);
74
0
    regs_read(detail, SH_REG_R0);
75
0
    break;
76
0
  case SH_OP_MEM_REG_R0:
77
0
    regs_read(detail, SH_REG_R0);
78
0
    regs_read(detail, reg);
79
0
    break;
80
0
  case SH_OP_MEM_PCR:
81
0
    break;
82
0
  default:
83
0
    regs_read(detail, reg);
84
0
    break;
85
0
  }
86
0
  return true;
87
0
}
88
89
static void set_mem(sh_info *info, sh_op_mem_type address,
90
        sh_reg reg, uint32_t disp, int sz, cs_detail *detail)
91
0
{
92
0
  if (!set_mem_n(info, address, reg, disp, sz, info->op.op_count,
93
0
           detail)) {
94
0
    return;
95
0
  }
96
0
  info->op.op_count++;
97
0
}
98
99
static void set_imm(sh_info *info, int sign, uint64_t imm)
100
0
{
101
0
  info->op.operands[info->op.op_count].type = SH_OP_IMM;
102
0
  if (sign && imm >= 128)
103
0
    imm = -256 + imm;
104
0
  info->op.operands[info->op.op_count].imm = imm;
105
0
  info->op.op_count++;
106
0
}
107
108
static void set_groups(cs_detail *detail, int n, ...)
109
0
{
110
0
  va_list g;
111
0
  va_start(g, n);
112
0
  while (n > 0) {
113
0
    sh_insn_group grp;
114
0
    grp = va_arg(g, sh_insn_group);
115
0
    if (detail) {
116
0
      detail->groups[detail->groups_count] = grp;
117
0
      detail->groups_count++;
118
0
    }
119
0
    n--;
120
0
  }
121
0
  va_end(g);
122
0
}
123
124
enum {
125
  ISA_ALL = 1,
126
  ISA_SH2 = 2,
127
  ISA_SH2A = 3,
128
  ISA_SH3 = 4,
129
  ISA_SH4 = 5,
130
  ISA_SH4A = 6,
131
  ISA_MAX = 7,
132
};
133
134
static int isalevel(cs_mode mode)
135
0
{
136
0
  int level;
137
0
  mode >>= 1; /* skip endian */
138
0
  for (level = 2; level < ISA_MAX; level++) {
139
0
    if (mode & 1)
140
0
      return level;
141
0
    mode >>= 1;
142
0
  }
143
0
  return ISA_ALL;
144
0
}
145
146
enum co_processor {none, shfpu, shdsp};
147
typedef union reg_insn {
148
  sh_reg reg;
149
  sh_insn insn;
150
} reg_insn;
151
struct ri_list {
152
  int no;
153
  int /* reg_insn */ri;
154
  int level;
155
  enum co_processor cp;
156
};
157
158
static const struct ri_list ldc_stc_regs[] = {
159
    {0, SH_REG_SR, ISA_ALL, none},
160
    {1, SH_REG_GBR, ISA_ALL, none},
161
    {2, SH_REG_VBR, ISA_ALL, none},
162
    {3, SH_REG_SSR, ISA_SH3, none},
163
    {4, SH_REG_SPC, ISA_SH3, none},
164
    {5, SH_REG_MOD, ISA_ALL, shdsp},
165
    {6, SH_REG_RS, ISA_ALL, shdsp},
166
    {7, SH_REG_RE, ISA_ALL, shdsp},
167
    {8, SH_REG_R0_BANK, ISA_SH3, none},
168
    {9, SH_REG_R1_BANK, ISA_SH3, none},
169
    {10, SH_REG_R2_BANK, ISA_SH3, none},
170
    {11, SH_REG_R3_BANK, ISA_SH3, none},
171
    {12, SH_REG_R4_BANK, ISA_SH3, none},
172
    {13, SH_REG_R5_BANK, ISA_SH3, none},
173
    {14, SH_REG_R6_BANK, ISA_SH3, none},
174
    {15, SH_REG_R7_BANK, ISA_SH3, none},
175
    {-1, SH_REG_INVALID, ISA_ALL, none},
176
};
177
178
static sh_insn lookup_insn(const struct ri_list *list,
179
           int no, cs_mode mode)
180
0
{
181
0
  int level = isalevel(mode);
182
0
  sh_insn error = SH_INS_INVALID;
183
0
  for(; list->no >= 0; list++) {
184
0
    if (no != list->no)
185
0
      continue;
186
0
    if (((level >= 0) && (level < list->level)) ||
187
0
        ((level < 0) && (-(level) != list->level)))
188
0
      continue;
189
0
    if ((list->cp == none) ||
190
0
        ((list->cp == shfpu) && (mode & CS_MODE_SHFPU)) ||
191
0
        ((list->cp == shdsp) && (mode & CS_MODE_SHDSP))) {
192
0
      return list->ri;
193
0
    }
194
0
  }
195
0
  return error;
196
0
}
197
198
static sh_reg lookup_regs(const struct ri_list *list,
199
           int no, cs_mode mode)
200
0
{
201
0
  int level = isalevel(mode);
202
0
  sh_reg error = SH_REG_INVALID;
203
0
  for(; list->no >= 0; list++) {
204
0
    if (no != list->no)
205
0
      continue;
206
0
    if (((level >= 0) && (level < list->level)) ||
207
0
        ((level < 0) && (-(level) != list->level)))
208
0
      continue;
209
0
    if ((list->cp == none) ||
210
0
        ((list->cp == shfpu) && (mode & CS_MODE_SHFPU)) ||
211
0
        ((list->cp == shdsp) && (mode & CS_MODE_SHDSP))) {
212
0
      return list->ri;
213
0
    }
214
0
  }
215
0
  return error;
216
0
}
217
218
// #define lookup_regs(list, no, mode) ((reg_insn)(lookup(reg, list, no, mode).reg))
219
// #define lookup_insn(list, no, mode) ((sh_insn)(lookup(insn, list, no, mode).insn))
220
221
static sh_reg opSTCsrc(uint16_t code, MCInst *MI, cs_mode mode,
222
           sh_info *info, cs_detail *detail)
223
0
{
224
0
  int s = (code >> 4) & 0x0f;
225
0
  int d = (code >> 8) & 0x0f;
226
0
  sh_reg sreg;
227
0
  MCInst_setOpcode(MI, SH_INS_STC);
228
0
  sreg = lookup_regs(ldc_stc_regs, s, mode);
229
0
  if (sreg != SH_REG_INVALID) {
230
0
    set_reg(info, sreg, read, detail);
231
0
    return SH_REG_R0 + d;
232
0
  } else {
233
0
    return SH_REG_INVALID;
234
0
  }
235
0
}
236
237
static bool opSTC(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
238
      sh_info *info, cs_detail *detail)
239
0
{
240
0
  sh_reg d;
241
0
  d = opSTCsrc(code, MI, mode, info, detail);
242
0
  if (d != SH_REG_INVALID) {
243
0
    set_reg(info, d, write, detail);
244
0
    return MCDisassembler_Success;
245
0
  } else {
246
0
    return MCDisassembler_Fail;
247
0
  }    
248
0
}
249
250
static bool op0xx3(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
251
       sh_info *info, cs_detail *detail)
252
0
{
253
0
  int r = (code >> 8) & 0x0f;
254
0
  int insn_code = (code >> 4) & 0x0f;
255
0
  static const struct ri_list list[] = {
256
0
    {0, SH_INS_BSRF, ISA_SH2, none},
257
0
    {2, SH_INS_BRAF, ISA_SH2, none},
258
0
    {6, SH_INS_MOVLI, ISA_SH4A, none},
259
0
    {7, SH_INS_MOVCO, ISA_SH4A, none},
260
0
    {8, SH_INS_PREF, ISA_SH2A, none},
261
0
    {9, SH_INS_OCBI, ISA_SH4, none},
262
0
    {10, SH_INS_OCBP, ISA_SH4, none},
263
0
    {11, SH_INS_OCBWB, ISA_SH4, none},
264
0
    {12, SH_INS_MOVCA, ISA_SH4, none},
265
0
    {13, SH_INS_PREFI, ISA_SH4A, none},
266
0
    {14, SH_INS_ICBI, ISA_SH4A, none},
267
0
    {-1, SH_INS_INVALID, ISA_ALL, none},
268
0
  };
269
0
  sh_insn insn = lookup_insn(list, insn_code, mode);
270
271
0
  if (insn != SH_INS_INVALID) {
272
0
    MCInst_setOpcode(MI, insn);
273
0
    switch (insn_code) {
274
0
    case 0: /// bsrf Rn
275
0
    case 2: /// braf Rn
276
0
      set_reg(info, SH_REG_R0 + r, read, detail);
277
0
      if (detail)
278
0
        set_groups(detail, 2,
279
0
             SH_GRP_JUMP,
280
0
             SH_GRP_BRANCH_RELATIVE);
281
0
      break;
282
0
    case 8: /// pref @Rn
283
0
    case 9: /// ocbi @Rn
284
0
    case 10: /// ocbp @Rn
285
0
    case 11: /// ocbwb @Rn
286
0
    case 13: /// prefi @Rn
287
0
    case 14: /// icbi @Rn
288
0
      set_mem(info, SH_OP_MEM_REG_IND,
289
0
        SH_REG_R0 + r, 0, 0, detail);
290
0
      break;
291
0
    case 6: /// movli @Rn, R0
292
0
      set_mem(info, SH_OP_MEM_REG_IND,
293
0
        SH_REG_R0 + r, 0, 32, detail);
294
0
      set_reg(info, SH_REG_R0, write, detail);
295
0
      break;
296
0
    case 7: /// movco R0,@Rn
297
0
    case 12: /// movca R0,@Rn
298
0
      set_reg(info, SH_REG_R0, read, detail);
299
0
      set_mem(info, SH_OP_MEM_REG_IND,
300
0
        SH_REG_R0 + r, 0, 32, detail);
301
0
      break;
302
0
    }
303
0
    return MCDisassembler_Success;
304
0
  } else {
305
0
    return MCDisassembler_Fail;
306
0
  }    
307
0
}
308
309
#define nm(code, dir)       \
310
0
  int m, n;       \
311
0
  m = (code >> (4 * (dir + 1))) & 0x0f; \
312
0
  n = (code >> (8 - 4 * dir)) & 0x0f
313
314
static bool opMOVx(uint16_t code, uint64_t address, MCInst *MI,
315
       cs_mode mode, int size, sh_info *info, cs_detail *detail)
316
0
{
317
0
  int ad = ((code >> 10) & 0x3c) | ((code >> 2) & 0x03);
318
0
  enum direction rw;
319
0
  MCInst_setOpcode(MI, SH_INS_MOV);
320
0
  switch (ad) {
321
0
  case 0x01: /// mov.X Rs,@(R0, Rd)
322
0
  case 0x03: /// mov.X @(R0, Rs), Rd
323
0
    rw = (ad >> 1);
324
0
    {
325
0
      nm(code, rw);
326
0
      if (!set_reg_n(info, SH_REG_R0 + m, rw, rw, detail)) {
327
0
        return false;
328
0
      }
329
0
      info->op.op_count++;
330
0
      if (!set_mem_n(info, SH_OP_MEM_REG_R0, SH_REG_R0 + n, 0,
331
0
               size, 1 - rw, detail)) {
332
0
        return false;
333
0
      }
334
0
      info->op.op_count++;
335
0
    }
336
0
    break;
337
0
  case 0x20: /// mov.X Rs,@-Rd
338
0
  case 0x60: /// mov.X @Rs+,Rd
339
0
    rw = (ad >> 6) & 1;
340
0
    {
341
0
      nm(code, rw);
342
0
      if (!set_reg_n(info, SH_REG_R0 + m, rw, rw, detail)) {
343
0
        return false;
344
0
      }
345
0
      info->op.op_count++;
346
0
      if (!set_mem_n(info, SH_OP_MEM_REG_PRE, SH_REG_R0 + n,
347
0
               0, size, 1 - rw, detail)) {
348
0
        return false;
349
0
      }
350
0
      info->op.op_count++;
351
0
    }
352
0
    break;
353
0
  default:
354
0
    return MCDisassembler_Fail;
355
0
  }
356
0
  return MCDisassembler_Success;
357
0
}
358
359
static bool opMOV_B(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
360
        sh_info *info, cs_detail *detail)
361
0
{
362
0
  return opMOVx(code, address, MI, mode, 8, info, detail);
363
0
}
364
365
static bool opMOV_W(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
366
        sh_info *info, cs_detail *detail)
367
0
{
368
0
  return opMOVx(code, address, MI, mode, 16, info, detail);
369
0
}
370
371
static bool opMOV_L(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
372
        sh_info *info, cs_detail *detail)
373
0
{
374
0
  return opMOVx(code, address, MI, mode, 32, info, detail);
375
0
}
376
377
static bool opRRfn(uint16_t code, MCInst *MI, sh_insn insn, cs_mode mode,
378
       int size, int level, sh_info *info, cs_detail *detail)
379
0
{
380
0
  int m = (code >> 4) & 0x0f;
381
0
  int n = (code >> 8) & 0x0f;
382
0
  if (level > isalevel(mode))
383
0
    return MCDisassembler_Fail;
384
0
  MCInst_setOpcode(MI, insn);
385
0
  set_reg(info, SH_REG_R0 + m, read, detail);
386
0
  set_reg(info, SH_REG_R0 + n, write, detail);
387
0
  info->op.size = size;
388
0
  return MCDisassembler_Success;
389
0
}
390
391
#define opRR(level, __insn, __size)         \
392
static bool op##__insn(uint16_t code, uint64_t address, MCInst *MI, \
393
0
           cs_mode mode, sh_info *info, cs_detail *detail)  \
394
0
{                 \
395
0
  return opRRfn(code, MI, SH_INS_##__insn, mode, __size, level,  \
396
0
          info, detail);          \
397
0
}
Unexecuted instantiation: SHDisassembler.c:opMUL_L
Unexecuted instantiation: SHDisassembler.c:opDIV0S
Unexecuted instantiation: SHDisassembler.c:opTST
Unexecuted instantiation: SHDisassembler.c:opAND
Unexecuted instantiation: SHDisassembler.c:opXOR
Unexecuted instantiation: SHDisassembler.c:opOR
Unexecuted instantiation: SHDisassembler.c:opCMP_STR
Unexecuted instantiation: SHDisassembler.c:opXTRCT
Unexecuted instantiation: SHDisassembler.c:opMULU_W
Unexecuted instantiation: SHDisassembler.c:opMULS_W
Unexecuted instantiation: SHDisassembler.c:opCMP_EQ
Unexecuted instantiation: SHDisassembler.c:opCMP_HS
Unexecuted instantiation: SHDisassembler.c:opCMP_GE
Unexecuted instantiation: SHDisassembler.c:opDIV1
Unexecuted instantiation: SHDisassembler.c:opDMULU_L
Unexecuted instantiation: SHDisassembler.c:opCMP_HI
Unexecuted instantiation: SHDisassembler.c:opCMP_GT
Unexecuted instantiation: SHDisassembler.c:opSUB
Unexecuted instantiation: SHDisassembler.c:opSUBC
Unexecuted instantiation: SHDisassembler.c:opSUBV
Unexecuted instantiation: SHDisassembler.c:opADD_r
Unexecuted instantiation: SHDisassembler.c:opDMULS_L
Unexecuted instantiation: SHDisassembler.c:opADDC
Unexecuted instantiation: SHDisassembler.c:opADDV
Unexecuted instantiation: SHDisassembler.c:opSHAD
Unexecuted instantiation: SHDisassembler.c:opSHLD
Unexecuted instantiation: SHDisassembler.c:opMOV
Unexecuted instantiation: SHDisassembler.c:opNOT
Unexecuted instantiation: SHDisassembler.c:opSWAP_B
Unexecuted instantiation: SHDisassembler.c:opSWAP_W
Unexecuted instantiation: SHDisassembler.c:opNEGC
Unexecuted instantiation: SHDisassembler.c:opNEG
Unexecuted instantiation: SHDisassembler.c:opEXTU_B
Unexecuted instantiation: SHDisassembler.c:opEXTU_W
Unexecuted instantiation: SHDisassembler.c:opEXTS_B
Unexecuted instantiation: SHDisassembler.c:opEXTS_W
398
399
/* mul.l - SH2 */
400
opRR(ISA_SH2, MUL_L, 0)
401
402
static bool op0xx8(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
403
       sh_info *info, cs_detail *detail)
404
0
{
405
0
  int insn_code = (code >> 4) & 0xf;
406
0
  static const struct ri_list list[] = {
407
0
    {0, SH_INS_CLRT, ISA_ALL, none},
408
0
    {1, SH_INS_SETT, ISA_ALL, none},
409
0
    {2, SH_INS_CLRMAC, ISA_ALL, none},
410
0
    {3, SH_INS_LDTLB, ISA_SH3, none},
411
0
    {4, SH_INS_CLRS, ISA_SH3, none},
412
0
    {5, SH_INS_SETS, ISA_SH3, none},
413
0
    {6, SH_INS_NOTT, -(ISA_SH2A), none},
414
0
    {8, SH_INS_CLRDMXY, ISA_SH4A, shdsp},
415
0
    {9, SH_INS_SETDMX, ISA_SH4A, shdsp},
416
0
    {12, SH_INS_SETDMY, ISA_SH4A, shdsp},
417
0
    {-1, SH_INS_INVALID, ISA_ALL, none},
418
0
  };
419
  
420
0
  sh_insn insn = lookup_insn(list, insn_code, mode);
421
0
  if (code & 0x0f00)
422
0
    return MCDisassembler_Fail;
423
    
424
0
  if (insn != SH_INS_INVALID) {
425
0
    MCInst_setOpcode(MI, insn);
426
0
    return MCDisassembler_Success;
427
0
  } else {
428
0
    return MCDisassembler_Fail;
429
0
  }
430
0
}
431
432
static bool op0xx9(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
433
       sh_info *info, cs_detail *detail)
434
0
{
435
0
  int insn_code = (code >> 4) & 0x0f;
436
0
  int r = (code >> 8) & 0x0f;
437
0
  static const struct ri_list list[] = {
438
0
    {0, SH_INS_NOP, ISA_ALL, none},
439
0
    {1, SH_INS_DIV0U, ISA_ALL, none},
440
0
    {2, SH_INS_MOVT, ISA_ALL, none},
441
0
    {3, SH_INS_MOVRT, -(ISA_SH2A), none},
442
0
    {-1, SH_INS_INVALID, ISA_ALL, none},
443
0
  };
444
0
  sh_insn insn = lookup_insn(list, insn_code, mode);
445
0
  if (insn != SH_INS_INVALID) {
446
0
    if (insn_code >= 2) {
447
      /// movt / movrt Rn
448
0
      set_reg(info, SH_REG_R0 + r, write, detail);
449
0
    } else if (r > 0) {
450
0
      insn = SH_INS_INVALID;
451
0
    }
452
0
  }
453
0
  if (insn != SH_INS_INVALID) {
454
0
    MCInst_setOpcode(MI, insn);
455
0
    return MCDisassembler_Success;
456
0
  } else {
457
0
    return MCDisassembler_Fail;
458
0
  }
459
0
}
460
461
static const struct ri_list sts_lds_regs[] = {
462
  {0, SH_REG_MACH, ISA_ALL, none},
463
  {1, SH_REG_MACL, ISA_ALL, none},
464
  {2, SH_REG_PR, ISA_ALL, none},
465
  {3, SH_REG_SGR, ISA_SH4, none},
466
  {4, SH_REG_TBR, -(ISA_SH2A), none},
467
  {5, SH_REG_FPUL, ISA_ALL, shfpu},
468
  {6, SH_REG_FPSCR, ISA_ALL, shfpu},
469
  {6, SH_REG_DSP_DSR, ISA_ALL, shdsp},
470
  {7, SH_REG_DSP_A0, ISA_ALL, shdsp},
471
  {8, SH_REG_DSP_X0, ISA_ALL, shdsp},
472
  {9, SH_REG_DSP_X1, ISA_ALL, shdsp},
473
  {10, SH_REG_DSP_Y0, ISA_ALL, shdsp},
474
  {11, SH_REG_DSP_Y1, ISA_ALL, shdsp},
475
  {15, SH_REG_DBR, ISA_SH4, none},
476
  {-1, SH_REG_INVALID, ISA_ALL, none},
477
};
478
479
static sh_reg opSTCSTS(uint16_t code, MCInst *MI, cs_mode mode, sh_info *info,
480
           cs_detail *detail)
481
0
{
482
0
  int s = (code >> 4) & 0x0f;
483
0
  int d = (code >> 8) & 0x0f;
484
0
  sh_reg reg;
485
0
  sh_insn insn;
486
487
0
  reg = lookup_regs(sts_lds_regs, s, mode);
488
0
  if (reg != SH_REG_INVALID) {
489
0
    if (s == 3 || s == 4 || s == 15) {
490
0
      insn = SH_INS_STC;
491
0
    } else {
492
0
      insn = SH_INS_STS;
493
0
    }
494
0
    MCInst_setOpcode(MI, insn);
495
0
    set_reg(info, reg, read, detail);
496
0
    return SH_REG_R0 + d;
497
0
  } else {
498
0
    return SH_REG_INVALID;
499
0
  }
500
0
}
501
502
static bool op0xxa(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
503
       sh_info *info, cs_detail *detail)
504
0
{
505
0
  sh_reg r = opSTCSTS(code, MI, mode, info, detail);
506
0
  if (r != SH_REG_INVALID) {
507
0
    set_reg(info, r, write, detail);
508
0
    return MCDisassembler_Success;
509
0
  } else
510
0
    return MCDisassembler_Fail;
511
0
}
512
513
static bool op0xxb(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
514
       sh_info *info, cs_detail *detail)
515
0
{
516
0
  int insn_code = (code >> 4) & 0x0f;
517
0
  int r = (code >> 8) & 0x0f;
518
0
  static const struct ri_list list[] = {
519
0
    {0, SH_INS_RTS, ISA_ALL, none},
520
0
    {1, SH_INS_SLEEP, ISA_ALL, none},
521
0
    {2, SH_INS_RTE, ISA_ALL, none},
522
0
    {5, SH_INS_RESBANK, -(ISA_SH2A), none},
523
0
    {6, SH_INS_RTS_N, -(ISA_SH2A), none},
524
0
    {7, SH_INS_RTV_N, -(ISA_SH2A), none},
525
0
    {10, SH_INS_SYNCO, -(ISA_SH4A), none},
526
0
    {-1, SH_INS_INVALID, ISA_ALL, none},
527
0
  };
528
529
0
  sh_insn insn = lookup_insn(list, insn_code, mode);
530
0
  if (insn_code == 7) {
531
0
    set_reg(info, SH_REG_R0 + r, read, detail);
532
0
    regs_write(detail, SH_REG_R0);
533
0
  } else if (r > 0) {
534
0
    insn = SH_INS_INVALID;
535
0
  }
536
0
  if (insn != SH_INS_INVALID) {
537
0
    MCInst_setOpcode(MI, insn);
538
0
    return MCDisassembler_Success;
539
0
  } else {
540
0
    return MCDisassembler_Fail;
541
0
  }    
542
0
}
543
544
static bool opMAC(uint16_t code, sh_insn op, MCInst *MI, sh_info *info,
545
      cs_detail *detail)
546
0
{
547
0
  nm(code, 0);
548
0
  MCInst_setOpcode(MI, op);
549
0
  set_mem(info, SH_OP_MEM_REG_POST, SH_REG_R0 + m, 0, 0, detail);
550
0
  set_mem(info, SH_OP_MEM_REG_POST, SH_REG_R0 + n, 0, 0, detail);
551
0
  return MCDisassembler_Success;
552
0
}
553
554
/// mac.l - sh2+
555
static bool opMAC_L(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
556
        sh_info *info, cs_detail *detail)
557
0
{
558
0
  if (isalevel(mode) < ISA_SH2)
559
0
    return MCDisassembler_Fail;
560
0
  return opMAC(code, SH_INS_MAC_L, MI, info, detail);
561
0
}
562
563
static bool opMAC_W(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
564
        sh_info *info, cs_detail *detail)
565
0
{
566
0
  return opMAC(code, SH_INS_MAC_W, MI, info, detail);
567
0
}
568
569
static bool opMOV_L_dsp(uint16_t code, uint64_t address, MCInst *MI,
570
      cs_mode mode, sh_info *info, cs_detail *detail)
571
0
{
572
0
  int dsp = (code & 0x0f) * 4;
573
0
  int rw = (code >> 14) & 1;
574
0
  nm(code, rw);
575
0
  MCInst_setOpcode(MI, SH_INS_MOV);
576
0
  if (!set_mem_n(info, SH_OP_MEM_REG_DISP, SH_REG_R0 + n, dsp, 32, 1 - rw,
577
0
           detail)) {
578
0
    return false;
579
0
  }
580
0
  info->op.op_count++;
581
582
0
  if (!set_reg_n(info, SH_REG_R0 + m, rw, rw, detail)) {
583
0
    return false;
584
0
  }
585
0
  info->op.op_count++;
586
0
  return MCDisassembler_Success;
587
0
}
588
589
static bool opMOV_rind(uint16_t code, uint64_t address, MCInst *MI,
590
           cs_mode mode, sh_info *info, cs_detail *detail)
591
0
{
592
0
  int sz = (code & 0x03);
593
0
  int rw = (code >> 14) & 1;
594
0
  nm(code, rw);
595
0
  MCInst_setOpcode(MI, SH_INS_MOV);
596
0
  sz = 8 << sz;
597
0
  if (!set_mem_n(info, SH_OP_MEM_REG_IND, SH_REG_R0 + n, 0, sz, 1 - rw,
598
0
           detail)) {
599
0
    return false;
600
0
  }
601
602
0
  if (!set_reg_n(info, SH_REG_R0 + m, rw, rw, detail)) {
603
0
    return false;
604
0
  }
605
0
  info->op.op_count = 2;
606
0
  return MCDisassembler_Success;
607
0
}
608
609
static bool opMOV_rpd(uint16_t code, uint64_t address, MCInst *MI,
610
          cs_mode mode, sh_info *info, cs_detail *detail)
611
0
{
612
0
  nm(code, 0);
613
0
  int sz = (code & 0x03);
614
0
  MCInst_setOpcode(MI, SH_INS_MOV);
615
0
  set_reg(info, SH_REG_R0 + m, read, detail);
616
0
  set_mem(info, SH_OP_MEM_REG_PRE, SH_REG_R0 + n, 0, 8 << sz, detail);
617
0
  return MCDisassembler_Success;
618
0
}
619
620
opRR(ISA_ALL, TST, 0)
621
opRR(ISA_ALL, AND, 0)
622
opRR(ISA_ALL, XOR, 0)
623
opRR(ISA_ALL, OR, 0)
624
opRR(ISA_ALL, CMP_STR, 0)
625
opRR(ISA_ALL, XTRCT, 0)
626
opRR(ISA_ALL, MULU_W, 16)
627
opRR(ISA_ALL, MULS_W, 16)
628
opRR(ISA_ALL, CMP_EQ, 0)
629
opRR(ISA_ALL, CMP_HI, 0)
630
opRR(ISA_ALL, CMP_HS, 0)
631
opRR(ISA_ALL, CMP_GE, 0)
632
opRR(ISA_ALL, CMP_GT, 0)
633
opRR(ISA_ALL, SUB, 0)
634
opRR(ISA_ALL, SUBC, 0)
635
opRR(ISA_ALL, SUBV, 0)
636
opRR(ISA_ALL, ADD_r, 0)
637
opRR(ISA_ALL, ADDC, 0)
638
opRR(ISA_ALL, ADDV, 0)
639
opRR(ISA_ALL, DIV0S, 0)
640
opRR(ISA_ALL, DIV1, 0)
641
/// DMULS / DMULU - SH2
642
opRR(ISA_SH2, DMULS_L, 0)
643
opRR(ISA_SH2, DMULU_L, 0)
644
645
static bool op4xx0(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
646
       sh_info *info, cs_detail *detail)
647
0
{
648
0
  int insn_code = (code >> 4) & 0x0f;
649
0
  int r = (code >> 8) & 0x0f;
650
0
  static const struct ri_list list[] = {
651
0
    {0, SH_INS_SHLL, ISA_ALL, none},
652
0
    {1, SH_INS_DT, ISA_SH2, none},
653
0
    {2, SH_INS_SHAL, ISA_ALL, none},
654
0
    {8, SH_INS_MULR, -(ISA_SH2A), none},
655
0
    {15, SH_INS_MOVMU, -(ISA_SH2A), none},
656
0
    {-1, SH_INS_INVALID, ISA_ALL, none},
657
0
  };
658
0
  sh_insn insn = lookup_insn(list, insn_code,mode);
659
0
  if (insn != SH_INS_INVALID) {
660
0
    MCInst_setOpcode(MI, insn);
661
0
    if (insn_code < 8) {
662
0
      set_reg(info, SH_REG_R0 + r, write, detail);
663
0
    } else {
664
0
      switch(insn_code) {
665
0
      case 0x08:
666
0
        set_reg(info, SH_REG_R0, read, detail);
667
0
        set_reg(info, SH_REG_R0 + r, write, detail);
668
0
        break;
669
0
      case 0x0f:
670
0
        set_reg(info, SH_REG_R0 + r, read, detail);
671
0
        set_mem(info, SH_OP_MEM_REG_PRE, SH_REG_R15, 0, 32, detail);
672
0
        break;
673
0
      }
674
0
    }
675
0
    return MCDisassembler_Success;
676
0
  } else {
677
0
    return MCDisassembler_Fail;
678
0
  }
679
0
}
680
681
static bool op4xx1(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
682
       sh_info *info, cs_detail *detail)
683
0
{
684
0
  int insn_code = (code >> 4) & 0x0f;
685
0
  int r = (code >> 8) & 0x0f;
686
0
  static const struct ri_list list[] = {
687
0
    {0, SH_INS_SHLR, ISA_ALL, none},
688
0
    {1, SH_INS_CMP_PZ, ISA_ALL, none},
689
0
    {2, SH_INS_SHAR, ISA_ALL, none},
690
0
    {8, SH_INS_CLIPU, -(ISA_SH2A), none},
691
0
    {9, SH_INS_CLIPS, -(ISA_SH2A), none},
692
0
    {14, SH_INS_STBANK, -(ISA_SH2A), none},
693
0
    {15, SH_INS_MOVML, -(ISA_SH2A), none},
694
0
    {-1, SH_INS_INVALID, ISA_ALL, none},
695
0
  };
696
0
  sh_insn insn = lookup_insn(list, insn_code,mode);
697
0
  if (insn != SH_INS_INVALID) {
698
0
    MCInst_setOpcode(MI, insn);
699
0
    switch(insn_code) {
700
0
    case 14:
701
0
      set_reg(info, SH_REG_R0, read, detail);
702
0
      set_mem(info, SH_OP_MEM_REG_IND, SH_REG_R0 + r, 0,
703
0
        0, detail);
704
0
      break;
705
0
    case 15:
706
0
      set_reg(info, SH_REG_R0 + r, read, detail);
707
0
      set_mem(info, SH_OP_MEM_REG_PRE, SH_REG_R15, 0,
708
0
        32, detail);
709
0
      break;
710
0
    default:
711
0
      set_reg(info, SH_REG_R0 + r, write, detail);
712
0
      if (insn_code >= 8)
713
0
        info->op.size = 8;
714
0
      break;
715
0
    }
716
0
    return MCDisassembler_Success;
717
0
  } else {
718
0
    return MCDisassembler_Fail;
719
0
  }
720
0
}
721
722
static bool op4xx2(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
723
       sh_info *info, cs_detail *detail)
724
0
{
725
0
  sh_reg r = opSTCSTS(code, MI, mode, info, detail);
726
0
  if (r != SH_REG_INVALID) {
727
0
    set_mem(info, SH_OP_MEM_REG_PRE, r, 0, 32, detail);
728
0
    return MCDisassembler_Success;
729
0
  } else {
730
0
    return MCDisassembler_Fail;
731
0
  }
732
0
}
733
734
static bool opSTC_L(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
735
        sh_info *info, cs_detail *detail)
736
0
{
737
0
  sh_reg r = opSTCsrc(code, MI, mode, info, detail);
738
0
  if (r != SH_REG_INVALID) {
739
0
    set_mem(info, SH_OP_MEM_REG_PRE, r, 0, 32, detail);
740
0
    return MCDisassembler_Success;
741
0
  } else {
742
0
    return MCDisassembler_Fail;
743
0
  }    
744
0
}
745
746
static bool op4xx4(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
747
       sh_info *info, cs_detail *detail)
748
0
{
749
0
  int r = (code >> 8) & 0x0f;
750
0
  int insn_code = (code >> 4) & 0x0f;
751
0
  static const struct ri_list list[] = {
752
0
    {0, SH_INS_ROTL, ISA_ALL, none},
753
0
    {1, SH_INS_SETRC, ISA_ALL, shdsp},
754
0
    {2, SH_INS_ROTCL, ISA_ALL, none},
755
0
    {3, SH_INS_LDRC, ISA_ALL, shdsp},
756
0
    {8, SH_INS_DIVU, -(ISA_SH2A), none},
757
0
    {9, SH_INS_DIVS, -(ISA_SH2A), none},
758
0
    {15, SH_INS_MOVMU, -(ISA_SH2A), none},
759
0
    {-1, SH_INS_INVALID, ISA_ALL, none},
760
0
  };
761
0
  sh_insn insn = lookup_insn(list, insn_code, mode);
762
0
  if (insn != SH_INS_INVALID) {
763
0
    MCInst_setOpcode(MI, insn);
764
0
    switch(insn_code) {
765
0
    case 8:
766
0
    case 9:
767
0
      set_reg(info, SH_REG_R0, read, detail);
768
0
      break;
769
0
    case 15:
770
0
      set_mem(info, SH_OP_MEM_REG_POST, SH_REG_R15, 0,
771
0
        32, detail);
772
0
      set_reg(info, SH_REG_R0 + r, read, detail);
773
0
      return MCDisassembler_Success;
774
0
    }
775
0
    set_reg(info, SH_REG_R0 + r, write, detail);
776
0
    return MCDisassembler_Success;
777
0
  } else {
778
0
    return MCDisassembler_Fail;
779
0
  }
780
0
}
781
782
static bool op4xx5(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
783
       sh_info *info, cs_detail *detail)
784
0
{
785
0
  int r = (code >> 8) & 0x0f;
786
0
  enum direction rw = read;
787
0
  static const struct ri_list list[] = {
788
0
    {0, SH_INS_ROTR, ISA_ALL, none},
789
0
    {1, SH_INS_CMP_PL, ISA_ALL, none},
790
0
    {2, SH_INS_ROTCR, ISA_ALL, none},
791
0
    {8, SH_INS_CLIPU, -(ISA_SH2A), none},
792
0
    {9, SH_INS_CLIPS, -(ISA_SH2A), none},
793
0
    {14, SH_INS_LDBANK, -(ISA_SH2A), none},
794
0
    {15, SH_INS_MOVML, -(ISA_SH2A), none},
795
0
    {-1, SH_INS_INVALID, ISA_ALL, none},
796
0
  };
797
0
  int insn_code = (code >> 4) & 0x0f;
798
0
  sh_insn insn = lookup_insn(list, insn_code,mode);
799
0
  if (insn != SH_INS_INVALID) {
800
0
    MCInst_setOpcode(MI, insn);
801
0
    switch (insn_code) {
802
0
    case 0:
803
0
    case 2:
804
0
      rw = write;
805
0
      break;
806
0
    case 1:
807
0
      rw = read;
808
0
      break;
809
0
    case 8:
810
0
    case 9:
811
0
      info->op.size = 16;
812
0
      rw = write;
813
0
      break;
814
0
    case 0x0e:
815
0
      set_mem(info, SH_OP_MEM_REG_IND, SH_REG_R0 + r, 0,
816
0
        0, detail);
817
0
      set_reg(info, SH_REG_R0, write, detail);
818
0
      return MCDisassembler_Success;
819
0
    case 0x0f:
820
0
      set_mem(info, SH_OP_MEM_REG_POST, SH_REG_R15, 0,
821
0
        32, detail);
822
0
      set_reg(info, SH_REG_R0 + r, write, detail);
823
0
      return MCDisassembler_Success;
824
0
    }
825
0
    set_reg(info, SH_REG_R0 + r, rw, detail);
826
0
    return MCDisassembler_Success;
827
0
  } else {
828
0
    return MCDisassembler_Fail;
829
0
  }
830
0
}
831
832
static bool opLDCLDS(uint16_t code, MCInst *MI, cs_mode mode,
833
         sh_info *info, cs_detail *detail)
834
0
{
835
0
  int d = (code >> 4) & 0x0f;
836
0
  sh_reg reg = lookup_regs(sts_lds_regs, d, mode);
837
0
  sh_insn insn;
838
0
  if (reg != SH_REG_INVALID) {
839
0
    if (d == 3 || d == 4 || d == 15) {
840
0
      insn = SH_INS_LDC;
841
0
    } else {
842
0
      insn = SH_INS_LDS;
843
0
    }
844
0
    MCInst_setOpcode(MI, insn);
845
0
    set_reg(info, reg, write, detail);
846
0
    return MCDisassembler_Success;
847
0
  } else {
848
0
    return MCDisassembler_Fail;
849
0
  }
850
0
}
851
852
static bool op4xx6(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
853
       sh_info *info, cs_detail *detail)
854
0
{
855
0
  int r = (code >> 8) & 0x0f;
856
0
  set_mem(info, SH_OP_MEM_REG_POST, SH_REG_R0 + r, 0, 32, detail);
857
0
  return opLDCLDS(code, MI, mode, info, detail);
858
0
}
859
860
static bool opLDCdst(uint16_t code, MCInst *MI, cs_mode mode,
861
         sh_info *info, cs_detail *detail)
862
0
{
863
0
  int d = (code >> 4) & 0x0f;
864
0
  sh_reg dreg = lookup_regs(ldc_stc_regs, d, mode);
865
0
  if (dreg == SH_REG_INVALID)
866
0
    return MCDisassembler_Fail;
867
0
  MCInst_setOpcode(MI, SH_INS_LDC);
868
0
  set_reg(info, dreg, write, detail);
869
0
  return MCDisassembler_Success;
870
0
}
871
872
static bool opLDC_L(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
873
        sh_info *info, cs_detail *detail)
874
0
{
875
0
  int s = (code >> 8) & 0x0f;
876
0
  set_mem(info,  SH_OP_MEM_REG_POST, SH_REG_R0 + s, 0, 32, detail);
877
0
  return opLDCdst(code, MI, mode, info, detail);
878
  
879
0
}
880
881
static bool op4xx8(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
882
       sh_info *info, cs_detail *detail)
883
0
{
884
0
  int r = (code >> 8) & 0x0f;
885
0
  sh_insn insn[] = { SH_INS_SHLL2, SH_INS_SHLL8, SH_INS_SHLL16};
886
0
  int size = (code >> 4) & 0x0f;
887
0
  if (size >= ARR_SIZE(insn)) {
888
0
    return MCDisassembler_Fail;
889
0
  }
890
0
  MCInst_setOpcode(MI, insn[size]);
891
0
  set_reg(info, SH_REG_R0 + r, write, detail);
892
0
  return MCDisassembler_Success;
893
0
}
894
895
static bool op4xx9(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
896
       sh_info *info, cs_detail *detail)
897
0
{
898
0
  int r = (code >> 8) & 0x0f;
899
0
  static const struct ri_list list[] = {
900
0
    {0, SH_INS_SHLR2, ISA_ALL, none},
901
0
    {1, SH_INS_SHLR8, ISA_ALL, none},
902
0
    {2, SH_INS_SHLR16, ISA_ALL, none},
903
0
    {10, SH_INS_MOVUA, -(ISA_SH4A), none},
904
0
    {14, SH_INS_MOVUA, -(ISA_SH4A), none},
905
0
    {-1, SH_INS_INVALID, ISA_ALL, none},
906
0
  };
907
0
  int op = (code >> 4) & 0x0f;
908
0
  sh_insn insn = lookup_insn(list, op, mode);
909
0
  sh_op_mem_type memop = SH_OP_MEM_INVALID;
910
0
  if (insn != SH_INS_INVALID) {
911
0
    MCInst_setOpcode(MI, insn);
912
0
    if (op < 8) {
913
0
      set_reg(info, SH_REG_R0 + r, write, detail);
914
0
    } else {
915
0
      memop = (op&4)?SH_OP_MEM_REG_POST:SH_OP_MEM_REG_IND;
916
0
      set_mem(info, memop, SH_REG_R0 + r, 0, 32, detail);
917
0
      set_reg(info, SH_REG_R0, write, detail);
918
0
    }
919
0
    return MCDisassembler_Success;
920
0
  } else {
921
0
    return MCDisassembler_Fail;
922
0
  }
923
0
}
924
925
static bool op4xxa(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
926
       sh_info *info, cs_detail *detail)
927
0
{
928
0
  int r = (code >> 8) & 0x0f;
929
0
  set_reg(info, SH_REG_R0 + r, read, detail);
930
0
  return opLDCLDS(code, MI, mode, info, detail);
931
0
}
932
933
static bool op4xxb(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
934
       sh_info *info, cs_detail *detail)
935
0
{
936
0
  int r = (code >> 8) & 0x0f;
937
0
  int insn_code = (code >> 4) & 0x0f;
938
0
  int sz = 0;
939
0
  int grp = SH_GRP_INVALID;
940
0
  sh_op_mem_type memop = SH_OP_MEM_INVALID;
941
0
  enum direction rw = read;
942
0
  static const struct ri_list list[] = {
943
0
    {0, SH_INS_JSR, ISA_ALL, none},
944
0
    {1, SH_INS_TAS, ISA_ALL, none},
945
0
    {2, SH_INS_JMP, ISA_ALL, none},
946
0
    {4, SH_INS_JSR_N, -(ISA_SH2A), none},
947
0
    {8, SH_INS_MOV, -(ISA_SH2A), none},
948
0
    {9, SH_INS_MOV, -(ISA_SH2A), none},
949
0
    {10, SH_INS_MOV, -(ISA_SH2A), none},
950
0
    {12, SH_INS_MOV, -(ISA_SH2A), none},
951
0
    {13, SH_INS_MOV, -(ISA_SH2A), none},
952
0
    {14, SH_INS_MOV, -(ISA_SH2A), none},
953
0
    {-1, SH_INS_INVALID, ISA_ALL, none},
954
0
  };
955
0
  sh_insn insn = lookup_insn(list, insn_code, mode);
956
0
  if (insn != SH_INS_INVALID) {
957
0
    MCInst_setOpcode(MI, insn);
958
0
    sz = 8 << ((code >> 4) & 3);
959
0
    switch (insn_code) {
960
0
    case 0:
961
0
    case 4:
962
0
      memop = SH_OP_MEM_REG_IND;
963
0
      grp = SH_GRP_CALL;
964
0
      break;
965
0
    case 1:
966
0
      memop = SH_OP_MEM_REG_IND;
967
0
      sz = 8;
968
0
      rw = write;
969
0
      break;
970
0
    case 2:
971
0
      insn = SH_INS_JMP;
972
0
      grp = SH_GRP_JUMP;
973
0
      break;
974
0
    case 8:
975
0
    case 9:
976
0
    case 10:
977
0
      memop = SH_OP_MEM_REG_POST;
978
0
      rw = read;
979
0
      break;
980
0
    case 12:
981
0
    case 13:
982
0
    case 14:
983
0
      memop = SH_OP_MEM_REG_PRE;
984
0
      rw = write;
985
0
      break;
986
0
    }
987
0
    if (grp != SH_GRP_INVALID) {
988
0
      set_mem(info, SH_OP_MEM_REG_IND, SH_REG_R0 + r, 0,
989
0
        0, detail);
990
0
      if (detail)
991
0
        set_groups(detail, 1, grp);
992
0
    } else {
993
0
      if (insn_code != 1) {
994
0
        if (!set_reg_n(info, SH_REG_R0, rw, rw,
995
0
                 detail)) {
996
0
          return false;
997
0
        }
998
0
        info->op.op_count++;
999
0
      }
1000
0
      if (!set_mem_n(info, memop, SH_REG_R0 + r, 0, sz,
1001
0
               1 - rw, detail)) {
1002
0
        return false;
1003
0
      }
1004
1005
0
      info->op.op_count++;
1006
0
    }
1007
0
    return MCDisassembler_Success;
1008
0
  } else {
1009
0
    return MCDisassembler_Fail;
1010
0
  }
1011
0
}
1012
1013
/* SHAD / SHLD - SH2A */
1014
opRR(ISA_SH2A, SHAD, 0)
1015
opRR(ISA_SH2A, SHLD, 0)
1016
  
1017
static bool opLDC(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1018
      sh_info *info, cs_detail *detail)
1019
0
{
1020
0
  int s = (code >> 8) & 0x0f;
1021
0
  set_reg(info, SH_REG_R0 + s, read, detail);
1022
0
  return opLDCdst(code, MI, mode, info, detail);
1023
0
}
1024
1025
opRR(ISA_ALL, MOV, 0)
1026
1027
static bool opMOV_rpi(uint16_t code, uint64_t address, MCInst *MI,
1028
          cs_mode mode, sh_info *info, cs_detail *detail)
1029
0
{
1030
0
  int sz = (code & 0x03);
1031
0
  nm(code, 0);
1032
0
  MCInst_setOpcode(MI, SH_INS_MOV);
1033
0
  set_mem(info, SH_OP_MEM_REG_POST, SH_REG_R0 + m, 0, 8 << sz, detail);
1034
0
  set_reg(info, SH_REG_R0 + n, write, detail);
1035
0
  return MCDisassembler_Success;
1036
0
}
1037
1038
opRR(ISA_ALL, NOT, 0)
1039
opRR(ISA_ALL, SWAP_B, 8)
1040
opRR(ISA_ALL, SWAP_W, 16)
1041
opRR(ISA_ALL, NEGC, 0)
1042
opRR(ISA_ALL, NEG, 0)
1043
opRR(ISA_ALL, EXTU_B, 8)
1044
opRR(ISA_ALL, EXTU_W, 16)
1045
opRR(ISA_ALL, EXTS_B, 8)
1046
opRR(ISA_ALL, EXTS_W, 16)
1047
1048
static bool opADD_i(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1049
        sh_info *info, cs_detail *detail)
1050
0
{
1051
0
  int r = (code >> 8) & 0x0f;
1052
0
  MCInst_setOpcode(MI, SH_INS_ADD);
1053
0
  set_imm(info, 1, code & 0xff);
1054
0
  set_reg(info, SH_REG_R0 + r, write, detail);
1055
0
  return MCDisassembler_Success;
1056
  
1057
0
}
1058
  
1059
static bool opMOV_BW_dsp(uint16_t code, uint64_t address, MCInst *MI,
1060
       cs_mode mode, sh_info *info, cs_detail *detail)
1061
0
{
1062
0
  int dsp = (code & 0x0f);
1063
0
  int r = (code >> 4) & 0x0f;
1064
0
  int size = 1 + ((code >> 8) & 1);
1065
0
  int rw = (code >> 10) & 1;
1066
0
  MCInst_setOpcode(MI, SH_INS_MOV);
1067
0
  if (!set_mem_n(info, SH_OP_MEM_REG_DISP, SH_REG_R0 + r, dsp * size,
1068
0
           8 * size, 1 - rw, detail)) {
1069
0
    return false;
1070
0
  }
1071
0
  info->op.op_count++;
1072
1073
0
  if (!set_reg_n(info, SH_REG_R0, rw, rw, detail)) {
1074
0
    return false;
1075
0
  }
1076
1077
0
  info->op.op_count++;
1078
0
  return MCDisassembler_Success;
1079
0
}
1080
1081
static bool opSETRC(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1082
        sh_info *info, cs_detail *detail)
1083
0
{
1084
0
  int imm = code & 0xff;
1085
0
  if (!(mode & CS_MODE_SHDSP))
1086
0
    return MCDisassembler_Fail;
1087
0
  MCInst_setOpcode(MI, SH_INS_SETRC);
1088
0
  set_imm(info, 0, imm);
1089
0
  return MCDisassembler_Success;
1090
0
}
1091
1092
static bool opJSR_N(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1093
        sh_info *info, cs_detail *detail)
1094
0
{
1095
0
  int dsp = code & 0xff;
1096
0
  if (isalevel(mode) != ISA_SH2A)
1097
0
    return MCDisassembler_Fail;
1098
0
  MCInst_setOpcode(MI, SH_INS_JSR_N);
1099
0
  set_mem(info, SH_OP_MEM_TBR_DISP, SH_REG_INVALID, dsp * 4, 0, detail);
1100
0
  return MCDisassembler_Success;
1101
0
}
1102
1103
#define boperand(_code, _op, _imm, _reg)    \
1104
0
  int _op = (code >> 3) & 1;      \
1105
0
  int _imm = code & 7;        \
1106
0
  int _reg = (code >> 4) & 0x0f
1107
1108
static bool op86xx(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1109
       sh_info *info, cs_detail *detail)
1110
0
{
1111
0
  static const sh_insn bop[] = {SH_INS_BCLR, SH_INS_BSET};
1112
0
  boperand(code, op, imm, reg);
1113
0
  if (isalevel(mode) != ISA_SH2A)
1114
0
    return MCDisassembler_Fail;
1115
0
  MCInst_setOpcode(MI, bop[op]);
1116
0
  set_imm(info, 0, imm);
1117
0
  set_reg(info, SH_REG_R0 + reg, write, detail);
1118
0
  return MCDisassembler_Success;
1119
0
}
1120
1121
static bool op87xx(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1122
       sh_info *info, cs_detail *detail)
1123
0
{
1124
0
  static const sh_insn bop[] = {SH_INS_BST, SH_INS_BLD};
1125
0
  boperand(code, op, imm, reg);
1126
0
  if (isalevel(mode) != ISA_SH2A)
1127
0
    return MCDisassembler_Fail;
1128
0
  MCInst_setOpcode(MI, bop[op]);
1129
0
  set_imm(info, 0, imm);
1130
0
  set_reg(info, SH_REG_R0 + reg, op?read:write, detail);
1131
0
  return MCDisassembler_Success;
1132
0
}
1133
1134
static bool opCMP_EQi(uint16_t code, uint64_t address, MCInst *MI,
1135
          cs_mode mode, sh_info *info, cs_detail *detail)
1136
0
{
1137
0
  MCInst_setOpcode(MI, SH_INS_CMP_EQ);
1138
0
  set_imm(info, 1, code & 0x00ff);
1139
0
  set_reg(info, SH_REG_R0, read, detail);
1140
0
  return MCDisassembler_Success;
1141
0
}
1142
1143
#define opBranch(level, insn)           \
1144
static bool op##insn(uint16_t code, uint64_t address, MCInst *MI, \
1145
0
         cs_mode mode, sh_info *info, cs_detail *detail)  \
1146
0
{                 \
1147
0
  int dsp = code & 0x00ff;          \
1148
0
  if (level > isalevel(mode))         \
1149
0
    return MCDisassembler_Fail;       \
1150
0
  if (dsp >= 0x80)           \
1151
0
    dsp = -256 + dsp;         \
1152
0
  MCInst_setOpcode(MI, SH_INS_##insn);        \
1153
0
  set_mem(info, SH_OP_MEM_PCR, SH_REG_INVALID, address + 4 + dsp * 2, \
1154
0
    0, detail);           \
1155
0
  if (detail)             \
1156
0
    set_groups(detail, 2, SH_GRP_JUMP, SH_GRP_BRANCH_RELATIVE); \
1157
0
  return MCDisassembler_Success;          \
1158
0
}
Unexecuted instantiation: SHDisassembler.c:opBT
Unexecuted instantiation: SHDisassembler.c:opBF
Unexecuted instantiation: SHDisassembler.c:opBT_S
Unexecuted instantiation: SHDisassembler.c:opBF_S
1159
1160
opBranch(ISA_ALL, BT)
1161
opBranch(ISA_ALL, BF)
1162
/* bt/s / bf/s - SH2 */
1163
opBranch(ISA_SH2, BT_S)
1164
opBranch(ISA_SH2, BF_S)
1165
1166
#define opLDRSE(insn)             \
1167
static bool op##insn(uint16_t code, uint64_t address, MCInst *MI, \
1168
0
         cs_mode mode, sh_info *info, cs_detail *detail)  \
1169
0
{                 \
1170
0
  int dsp = code & 0xff;            \
1171
0
  if (!(mode & CS_MODE_SHDSP))         \
1172
0
    return MCDisassembler_Fail;       \
1173
0
  MCInst_setOpcode(MI, SH_INS_##insn);        \
1174
0
  set_mem(info, SH_OP_MEM_PCR, SH_REG_INVALID, address + 4 + dsp * 2, \
1175
0
    0, detail);           \
1176
0
  return MCDisassembler_Success;\
1177
0
}
Unexecuted instantiation: SHDisassembler.c:opLDRS
Unexecuted instantiation: SHDisassembler.c:opLDRE
1178
1179
static bool opLDRC(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1180
       sh_info *info, cs_detail *detail)
1181
0
{
1182
0
  int imm = code & 0xff;
1183
0
  if (!(mode & CS_MODE_SHDSP) || isalevel(mode) != ISA_SH4A)
1184
0
    return MCDisassembler_Fail;
1185
0
  MCInst_setOpcode(MI, SH_INS_LDRC);
1186
0
  set_imm(info, 0, imm);
1187
0
  return MCDisassembler_Success;
1188
0
}
1189
1190
opLDRSE(LDRS)
1191
opLDRSE(LDRE)
1192
  
1193
#define opImmR0(insn) \
1194
static bool op##insn##_i(uint16_t code, uint64_t address, MCInst *MI, \
1195
0
       cs_mode mode, sh_info *info, cs_detail *detail) \
1196
0
{                 \
1197
0
  MCInst_setOpcode(MI, SH_INS_##insn);        \
1198
0
  set_imm(info, 0, code & 0xff);          \
1199
0
  set_reg(info, SH_REG_R0, write, detail);      \
1200
0
  return MCDisassembler_Success;          \
1201
0
}
Unexecuted instantiation: SHDisassembler.c:opTST_i
Unexecuted instantiation: SHDisassembler.c:opAND_i
Unexecuted instantiation: SHDisassembler.c:opXOR_i
Unexecuted instantiation: SHDisassembler.c:opOR_i
1202
1203
opImmR0(TST)
1204
opImmR0(AND)
1205
opImmR0(XOR)
1206
opImmR0(OR)
1207
  
1208
#define opImmMem(insn) \
1209
static bool op##insn##_B(uint16_t code, uint64_t address, MCInst *MI, \
1210
0
       cs_mode mode, sh_info *info, cs_detail *detail) \
1211
0
{                 \
1212
0
  MCInst_setOpcode(MI, SH_INS_##insn);        \
1213
0
  set_imm(info, 0, code & 0xff);          \
1214
0
  set_mem(info, SH_OP_MEM_GBR_R0, SH_REG_R0, 0, 8, detail); \
1215
0
  return MCDisassembler_Success;          \
1216
0
}
Unexecuted instantiation: SHDisassembler.c:opTST_B
Unexecuted instantiation: SHDisassembler.c:opAND_B
Unexecuted instantiation: SHDisassembler.c:opXOR_B
Unexecuted instantiation: SHDisassembler.c:opOR_B
1217
1218
opImmMem(TST)
1219
opImmMem(AND)
1220
opImmMem(XOR)
1221
opImmMem(OR)
1222
  
1223
static bool opMOV_pc(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1224
         sh_info *info, cs_detail *detail)
1225
0
{
1226
0
  int sz = 16 << ((code >> 14) & 1);
1227
0
  int dsp = (code & 0x00ff) * (sz / 8);
1228
0
  int r = (code >> 8) & 0x0f;
1229
0
  MCInst_setOpcode(MI, SH_INS_MOV);
1230
0
  if (sz == 32)
1231
0
    address &= ~3;
1232
0
  set_mem(info, SH_OP_MEM_PCR, SH_REG_INVALID, address + 4 + dsp,
1233
0
    sz, detail);
1234
0
  set_reg(info, SH_REG_R0 + r, write, detail);
1235
0
  return MCDisassembler_Success;
1236
0
}
1237
1238
#define opBxx(insn, grp)            \
1239
static bool op##insn(uint16_t code, uint64_t address, MCInst *MI, \
1240
0
         cs_mode mode, sh_info *info, cs_detail *detail)  \
1241
0
{                 \
1242
0
  int dsp = (code & 0x0fff);          \
1243
0
  if (dsp >= 0x800)           \
1244
0
    dsp = -0x1000 + dsp;         \
1245
0
  MCInst_setOpcode(MI, SH_INS_##insn);        \
1246
0
  set_mem(info, SH_OP_MEM_PCR, SH_REG_INVALID, address + 4 + dsp * 2, \
1247
0
    0, detail);           \
1248
0
  if (detail)             \
1249
0
    set_groups(detail, 2, grp, SH_GRP_BRANCH_RELATIVE); \
1250
0
  return MCDisassembler_Success;          \
1251
0
}
Unexecuted instantiation: SHDisassembler.c:opBRA
Unexecuted instantiation: SHDisassembler.c:opBSR
1252
1253
opBxx(BRA, SH_GRP_JUMP)
1254
opBxx(BSR, SH_GRP_CALL)
1255
1256
static bool opMOV_gbr(uint16_t code, uint64_t address, MCInst *MI,
1257
          cs_mode mode, sh_info *info, cs_detail *detail)
1258
0
{
1259
0
  int sz = 8 << ((code >> 8) & 0x03);
1260
0
  int dsp = (code & 0x00ff) * (sz / 8);
1261
0
  int rw = (code >> 10) & 1;
1262
0
  MCInst_setOpcode(MI, SH_INS_MOV);
1263
0
  if (!set_mem_n(info, SH_OP_MEM_GBR_DISP, SH_REG_GBR, dsp, sz, 1 - rw,
1264
0
           detail)) {
1265
0
    return false;
1266
0
  }
1267
0
  info->op.op_count++;
1268
1269
0
  if (!set_reg_n(info, SH_REG_R0, rw, rw, detail)) {
1270
0
    return false;
1271
0
  }
1272
0
  info->op.op_count++;
1273
0
  return MCDisassembler_Success;
1274
0
}
1275
1276
static bool opTRAPA(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1277
        sh_info *info, cs_detail *detail)
1278
0
{
1279
0
  MCInst_setOpcode(MI, SH_INS_TRAPA);
1280
0
  set_imm(info, 0, code & 0xff);
1281
0
  if (detail)
1282
0
    set_groups(detail, 1,  SH_GRP_INT);
1283
0
  return MCDisassembler_Success;
1284
0
}
1285
1286
static bool opMOVA(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1287
       sh_info *info, cs_detail *detail)
1288
0
{
1289
0
  int dsp = (code & 0x00ff) * 4;
1290
0
  MCInst_setOpcode(MI, SH_INS_MOVA);
1291
0
  set_mem(info, SH_OP_MEM_PCR, SH_REG_INVALID, (address & ~3) + 4 + dsp,
1292
0
    0, detail);
1293
0
  set_reg(info, SH_REG_R0, write, detail);
1294
0
  return MCDisassembler_Success;
1295
0
}
1296
1297
static bool opMOV_i(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1298
        sh_info *info, cs_detail *detail)
1299
0
{
1300
0
  int imm = (code & 0x00ff);
1301
0
  int r = (code >> 8) & 0x0f;
1302
0
  MCInst_setOpcode(MI, SH_INS_MOV);
1303
0
  set_imm(info, 1, imm);
1304
0
  set_reg(info, SH_REG_R0 + r, write, detail);
1305
0
  return MCDisassembler_Success;
1306
0
}
1307
1308
/* FPU instructions */
1309
#define opFRR(insn)             \
1310
static bool op##insn(uint16_t code, uint64_t address, MCInst *MI, \
1311
0
         cs_mode mode, sh_info *info, cs_detail *detail)  \
1312
0
{                 \
1313
0
  int m = (code >> 4) & 0x0f;         \
1314
0
  int n = (code >> 8) & 0x0f;         \
1315
0
  MCInst_setOpcode(MI, SH_INS_##insn);        \
1316
0
  set_reg(info, SH_REG_FR0 + m, read, detail);      \
1317
0
  set_reg(info, SH_REG_FR0 + n, write, detail);     \
1318
0
  return MCDisassembler_Success;          \
1319
0
}
Unexecuted instantiation: SHDisassembler.c:opFADD
Unexecuted instantiation: SHDisassembler.c:opFSUB
Unexecuted instantiation: SHDisassembler.c:opFMUL
Unexecuted instantiation: SHDisassembler.c:opFDIV
1320
1321
#define opFRRcmp(insn)              \
1322
static bool op##insn(uint16_t code, uint64_t address, MCInst *MI, \
1323
0
         cs_mode mode, sh_info *info, cs_detail *detail)  \
1324
0
{                 \
1325
0
  int m = (code >> 4) & 0x0f;         \
1326
0
  int n = (code >> 8) & 0x0f;         \
1327
0
  MCInst_setOpcode(MI, SH_INS_##insn);        \
1328
0
  set_reg(info, SH_REG_FR0 + m, read, detail);      \
1329
0
  set_reg(info, SH_REG_FR0 + n, read, detail);      \
1330
0
  return MCDisassembler_Success;          \
1331
0
}
Unexecuted instantiation: SHDisassembler.c:opFCMP_EQ
Unexecuted instantiation: SHDisassembler.c:opFCMP_GT
1332
1333
opFRR(FADD)
1334
opFRR(FSUB)
1335
opFRR(FMUL)
1336
opFRR(FDIV)
1337
opFRRcmp(FCMP_EQ)
1338
opFRRcmp(FCMP_GT)
1339
1340
static bool opFMOVm(MCInst *MI, enum direction rw, uint16_t code,
1341
        sh_op_mem_type address, sh_info *info, cs_detail *detail)
1342
0
{
1343
0
  nm(code, (1 - rw));
1344
0
  MCInst_setOpcode(MI, SH_INS_FMOV);
1345
0
  if (!set_mem_n(info, address, SH_REG_R0 + m, 0, 0, 1 - rw, detail)) {
1346
0
    return false;
1347
0
  }
1348
0
  info->op.op_count++;
1349
1350
0
  if (!set_reg_n(info, SH_REG_FR0 + n, rw, rw, detail)) {
1351
0
    return false;
1352
0
  }
1353
0
  info->op.op_count++;
1354
1355
0
  return MCDisassembler_Success;
1356
0
}
1357
1358
static bool opfxx6(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1359
       sh_info *info, cs_detail *detail)
1360
0
{
1361
0
  return opFMOVm(MI, write, code, SH_OP_MEM_REG_R0, info, detail);
1362
0
}
1363
  
1364
static bool opfxx7(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1365
       sh_info *info, cs_detail *detail)
1366
0
{
1367
0
  return opFMOVm(MI, read, code, SH_OP_MEM_REG_R0, info, detail);
1368
0
}
1369
  
1370
static bool opfxx8(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1371
       sh_info *info, cs_detail *detail)
1372
0
{
1373
0
  return opFMOVm(MI, write, code, SH_OP_MEM_REG_IND, info, detail);
1374
0
}
1375
  
1376
static bool opfxx9(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1377
       sh_info *info, cs_detail *detail)
1378
0
{
1379
0
  return opFMOVm(MI, write, code, SH_OP_MEM_REG_POST, info, detail);
1380
0
}
1381
  
1382
static bool opfxxa(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1383
       sh_info *info, cs_detail *detail)
1384
0
{
1385
0
  return opFMOVm(MI, read, code, SH_OP_MEM_REG_IND, info, detail);
1386
0
}
1387
  
1388
static bool opfxxb(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1389
       sh_info *info, cs_detail *detail)
1390
0
{
1391
0
  return opFMOVm(MI, read, code, SH_OP_MEM_REG_PRE, info, detail);
1392
0
}
1393
  
1394
static bool opFMOV(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1395
       sh_info *info, cs_detail *detail)
1396
0
{
1397
0
  nm(code, 0);
1398
0
  MCInst_setOpcode(MI, SH_INS_FMOV);
1399
0
  set_reg(info, SH_REG_FR0 + m, read, detail);
1400
0
  set_reg(info, SH_REG_FR0 + n, write, detail);
1401
0
  return MCDisassembler_Success;
1402
0
}
1403
  
1404
static bool opfxxd(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1405
       sh_info *info, cs_detail *detail)
1406
0
{
1407
0
  int fr = (code >> 8) & 0x0f;
1408
0
  int dr = (code >> 9) & 0x07;
1409
0
  int fvn = (code >> 10) & 0x03;
1410
0
  int fvm = (code >> 8) & 0x03;
1411
0
  sh_insn insn = SH_INS_INVALID;
1412
0
  sh_reg s, d;
1413
0
  static const struct ri_list list[] = {
1414
0
    {0, SH_INS_FSTS, ISA_ALL, shfpu},
1415
0
    {1, SH_INS_FLDS, ISA_ALL, shfpu},
1416
0
    {2, SH_INS_FLOAT, ISA_ALL, shfpu},
1417
0
    {3, SH_INS_FTRC, ISA_ALL, shfpu},
1418
0
    {4, SH_INS_FNEG, ISA_ALL, shfpu},
1419
0
    {5, SH_INS_FABS, ISA_ALL, shfpu},
1420
0
    {6, SH_INS_FSQRT, ISA_ALL, shfpu},
1421
0
    {7, SH_INS_FSRRA, ISA_ALL, shfpu},
1422
0
    {8, SH_INS_FLDI0, ISA_ALL, shfpu},
1423
0
    {9, SH_INS_FLDI1, ISA_ALL, shfpu},
1424
0
    {10, SH_INS_FCNVSD, ISA_SH4A, shfpu},
1425
0
    {11, SH_INS_FCNVDS, ISA_SH4A, shfpu},
1426
0
    {14, SH_INS_FIPR, ISA_SH4A, shfpu},
1427
0
    {-1, SH_INS_INVALID, ISA_ALL, none},
1428
0
  };
1429
0
  static const sh_insn chg[] = {
1430
0
    SH_INS_FSCHG, SH_INS_FPCHG, SH_INS_FRCHG, SH_INS_INVALID
1431
0
  };
1432
0
  insn = lookup_insn(list, (code >> 4) & 0x0f, mode);
1433
0
  s = d = SH_REG_FPUL;
1434
0
  if (insn != SH_INS_INVALID) {
1435
0
    switch((code >> 4) & 0x0f) {
1436
0
    case 0:
1437
0
    case 2:
1438
0
      d = SH_REG_FR0 + fr;
1439
0
      break;
1440
0
    case 1:
1441
0
    case 3:
1442
0
      s = SH_REG_FR0 + fr;
1443
0
      break;
1444
0
    case 10:
1445
0
      d = SH_REG_DR0 + dr;
1446
0
      break;
1447
0
    case 11:
1448
0
      s = SH_REG_DR0 + dr;
1449
0
      break;
1450
0
    case 14:
1451
0
      s = SH_REG_FV0 + fvm;
1452
0
      d = SH_REG_FV0 + fvn;
1453
0
      break;
1454
0
    default:
1455
0
      s = SH_REG_FR0 + fr;
1456
0
      d = SH_REG_INVALID;
1457
0
      break;
1458
0
    }
1459
0
  } else if ((code & 0x00f0) == 0x00f0) {
1460
0
    if ((code & 0x01ff) == 0x00fd) {
1461
0
      insn = SH_INS_FSCA;
1462
0
      d = SH_REG_DR0 + dr;
1463
0
    }
1464
0
    if ((code & 0x03ff) == 0x01fd) {
1465
0
      insn = SH_INS_FTRV;
1466
0
      s = SH_REG_XMATRX;
1467
0
      d = SH_REG_FV0 + fvn;
1468
0
    }
1469
0
    if ((code & 0x03ff) == 0x03fd) {
1470
0
      insn = chg[(code >> 10) & 3];
1471
0
      s = d = SH_REG_INVALID;
1472
0
    }
1473
0
  }
1474
0
  if (insn == SH_INS_INVALID) {
1475
0
    return MCDisassembler_Fail;
1476
0
  }
1477
0
  MCInst_setOpcode(MI, insn);
1478
0
  if (s != SH_REG_INVALID) {
1479
0
    set_reg(info, s, read, detail);
1480
0
  }
1481
0
  if (d != SH_REG_INVALID) {
1482
0
    set_reg(info, d, write, detail);
1483
0
  }
1484
0
  return MCDisassembler_Success;
1485
0
}
1486
1487
static bool opFMAC(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
1488
       sh_info *info, cs_detail *detail)
1489
0
{
1490
0
  int m = (code >> 4) & 0x0f;
1491
0
  int n = (code >> 8) & 0x0f;
1492
0
  MCInst_setOpcode(MI, SH_INS_FMAC);
1493
0
  set_reg(info, SH_REG_FR0, read, detail);
1494
0
  set_reg(info, SH_REG_FR0 + m, read, detail);
1495
0
  set_reg(info, SH_REG_FR0 + n, write, detail);
1496
0
  return MCDisassembler_Success;
1497
0
}
1498
1499
#include "SHInsnTable.inc"
1500
1501
static bool decode_long(uint32_t code, uint64_t address, MCInst *MI,
1502
      sh_info *info, cs_detail *detail)
1503
0
{
1504
0
  uint32_t imm;
1505
0
  sh_insn insn = SH_INS_INVALID;
1506
0
  int m,n;
1507
0
  int dsp;
1508
0
  int sz;
1509
0
  static const sh_insn bop[] = {
1510
0
    SH_INS_BCLR, SH_INS_BSET, SH_INS_BST, SH_INS_BLD,
1511
0
    SH_INS_BAND, SH_INS_BOR, SH_INS_BXOR, SH_INS_INVALID,
1512
0
    SH_INS_INVALID, SH_INS_INVALID, SH_INS_INVALID, SH_INS_BLDNOT,
1513
0
    SH_INS_BANDNOT, SH_INS_BORNOT, SH_INS_INVALID, SH_INS_INVALID,
1514
0
  };
1515
0
  switch (code >> 28) {
1516
0
  case 0x0:
1517
0
    imm = ((code >> 4) & 0x000f0000) | (code & 0xffff);
1518
0
    n = (code >> 24) & 0x0f;
1519
0
    if (code & 0x00010000) {
1520
      // movi20s #imm,
1521
0
      imm <<= 8;
1522
0
      if (imm & (1 << (28 - 1)))
1523
0
        imm |= ~((1 << 28) - 1);
1524
0
      insn = SH_INS_MOVI20S;
1525
0
    } else {
1526
      // MOVI20
1527
0
      if (imm & (1 << (28 - 1)))
1528
0
        imm |= ~((1 << 20) - 1);
1529
0
      insn = SH_INS_MOVI20;
1530
0
    }
1531
0
    set_imm(info, 0, imm);
1532
0
    set_reg(info, SH_REG_R0 + n, write, detail);
1533
0
    break;
1534
0
  case 0x3:
1535
0
    n = (code >> 24) & 0x0f;
1536
0
    m = (code >> 20) & 0x0f;
1537
0
    sz = (code >> 12) & 0x03;
1538
0
    dsp = code & 0xfff;
1539
0
    if (!(code & 0x80000)) {
1540
0
      dsp <<= sz;
1541
0
      switch((code >> 14) & 0x3) {
1542
0
      case 0: // mov.[bwl] Rm,@(disp,Rn)
1543
        // fmov.s DRm,@(disp,Rn)
1544
0
        if (sz < 3) {
1545
0
          insn = SH_INS_MOV;
1546
0
          set_reg(info, SH_REG_R0 + m,
1547
0
            read, detail);
1548
0
        } else {
1549
0
          insn = SH_INS_FMOV;
1550
0
          set_reg(info, SH_REG_DR0 + (m >> 1),
1551
0
            read, detail);
1552
0
        }
1553
0
        set_mem(info, SH_OP_MEM_REG_DISP,
1554
0
          SH_REG_R0 + n, dsp, 8 << sz, detail);
1555
0
        break;
1556
0
      case 1: // mov.[bwl] @(disp,Rm),Rn
1557
        // fmov.s @(disp,Rm),DRn
1558
0
        set_mem(info, SH_OP_MEM_REG_DISP,
1559
0
          SH_REG_R0 + m, dsp, 8 << sz, detail);
1560
0
        if (sz < 3) {
1561
0
          insn = SH_INS_MOV;
1562
0
          set_reg(info, SH_REG_R0 + n,
1563
0
            write, detail);
1564
0
        } else {
1565
0
          insn = SH_INS_FMOV;
1566
0
          set_reg(info, SH_REG_DR0 + (n >> 1),
1567
0
            write, detail);
1568
0
        }
1569
0
        break;
1570
0
      case 2: // movu.[bwl] @(disp,Rm),Rn
1571
0
        if (sz < 2) {
1572
0
          insn = SH_INS_MOVU;
1573
0
          set_mem(info, SH_OP_MEM_REG_DISP,
1574
0
            SH_REG_R0 + m, dsp,
1575
0
            8 << sz, detail);
1576
0
          set_reg(info, SH_REG_R0 + n,
1577
0
            write, detail);
1578
0
        }
1579
0
        break;
1580
0
      }
1581
0
    } else {
1582
      // bitop #imm,@(disp,Rn)
1583
0
      insn = bop[(code >> 12) & 0x0f];
1584
0
      set_imm(info, 0, m & 7);
1585
0
      set_mem(info, SH_OP_MEM_REG_DISP, SH_REG_R0 + n,
1586
0
        dsp, 8, detail);
1587
0
    }
1588
0
  }
1589
0
  if (insn != SH_INS_INVALID) {
1590
0
    MCInst_setOpcode(MI, insn);
1591
0
    return MCDisassembler_Success;
1592
0
  } else {
1593
0
    return MCDisassembler_Fail;
1594
0
  }
1595
0
}
1596
1597
static const sh_reg dsp_areg[2][4] = {
1598
  {SH_REG_R4, SH_REG_R0, SH_REG_R5, SH_REG_R1},
1599
  {SH_REG_R6, SH_REG_R7, SH_REG_R2, SH_REG_R3},
1600
};
1601
1602
static bool decode_dsp_xy(sh_info *info, int xy, uint16_t code,
1603
        cs_detail *detail)
1604
0
{
1605
0
  int a = (code >> 8) & 3;
1606
0
  int d = (code >> 6) & 3;
1607
0
  int dir;
1608
0
  int sz;
1609
0
  int op;
1610
1611
0
  static const sh_reg dreg[4][4] = {
1612
0
    {SH_REG_DSP_A0, SH_REG_DSP_X0, SH_REG_DSP_A1, SH_REG_DSP_X1},
1613
0
    {SH_REG_DSP_A0, SH_REG_DSP_A1, SH_REG_DSP_Y0, SH_REG_DSP_Y1},
1614
0
    {SH_REG_DSP_X0, SH_REG_DSP_Y0, SH_REG_DSP_X1, SH_REG_DSP_Y1},
1615
0
    {SH_REG_DSP_Y0, SH_REG_DSP_Y1, SH_REG_DSP_X0, SH_REG_DSP_X1},
1616
0
  };
1617
  
1618
0
  if (xy) {
1619
0
    op = code & 3;
1620
0
    dir = 1 - ((code >> 4) & 1);
1621
0
    sz = (code >> 5) & 1;
1622
0
    if (code & 0x0c) {
1623
0
      info->op.operands[xy].dsp.insn = SH_INS_DSP_NOP;
1624
0
      return MCDisassembler_Success;
1625
0
    }
1626
0
  } else {
1627
0
    op = (code >> 2) & 3;
1628
0
    dir = 1 - ((code >> 5) & 1);
1629
0
    sz = (code >> 4) & 1;
1630
0
    if (code & 0x03) {
1631
0
      info->op.operands[xy].dsp.insn = SH_INS_DSP_NOP;
1632
0
      return MCDisassembler_Success;
1633
0
    }
1634
0
  }
1635
0
  info->op.operands[xy].dsp.size = 16 << sz;
1636
0
  info->op.operands[xy].dsp.insn = SH_INS_DSP_MOV;
1637
0
  info->op.operands[xy].dsp.operand[1 - dir] =
1638
0
    SH_OP_DSP_REG_IND + (op - 1);
1639
0
  info->op.operands[xy].dsp.operand[dir] = SH_OP_DSP_REG;
1640
0
  info->op.operands[xy].dsp.r[1 - dir] = dsp_areg[xy][a];
1641
0
  info->op.operands[xy].dsp.size = 16 << sz;
1642
0
  regs_rw(detail, dir,
1643
0
    info->op.operands[xy].dsp.r[dir] = dreg[xy * 2 + dir][d]);
1644
0
  switch(op) {
1645
0
  case 0x03:
1646
0
    regs_read(detail, SH_REG_R8 + xy);
1647
    // Fail through
1648
0
  case 0x02:
1649
0
    regs_write(detail, dsp_areg[xy][a]);
1650
0
    break;
1651
0
  case 0x01:
1652
0
    regs_read(detail, dsp_areg[xy][a]);
1653
0
    break;
1654
0
  default:
1655
0
    return MCDisassembler_Fail;
1656
0
  }
1657
0
  return MCDisassembler_Success;
1658
0
}
1659
1660
static bool set_dsp_move_d(sh_info *info, int xy, uint16_t code, cs_mode mode, cs_detail *detail)
1661
0
{
1662
0
  int a;
1663
0
  int d;
1664
0
  int dir;
1665
0
  int op;
1666
0
  static const sh_reg base[] = {SH_REG_DSP_A0, SH_REG_DSP_X0};
1667
0
  switch (xy) {
1668
0
  case 0:
1669
0
    op = (code >> 2) & 3;
1670
0
    dir = 1 - ((code >> 5) & 1);
1671
0
    d = (code >> 7) & 1;
1672
0
    a = (code >> 9) & 1;
1673
0
    break;
1674
0
  case 1:
1675
0
    op = (code >> 0) & 3;
1676
0
    dir = 1 - ((code >> 4) & 1);
1677
0
    d = (code >> 6) & 1;
1678
0
    a = (code >> 8) & 1;
1679
0
    break;
1680
0
  }
1681
0
  if (op == 0x00) {
1682
0
    if ((a || d || dir) && !(code & 0x0f))
1683
0
      return MCDisassembler_Fail;
1684
0
    info->op.operands[xy].dsp.insn = SH_INS_DSP_NOP;
1685
0
  } else {
1686
0
    info->op.operands[xy].dsp.insn = SH_INS_DSP_MOV;
1687
0
    info->op.operands[xy].dsp.operand[1 - dir] =
1688
0
      SH_OP_DSP_REG_IND + (op - 1);
1689
0
    info->op.operands[xy].dsp.operand[dir] = SH_OP_DSP_REG;
1690
0
    info->op.operands[xy].dsp.r[1 - dir] = SH_REG_R4 + xy * 2 + a;
1691
0
    info->op.operands[xy].dsp.size = 16;
1692
0
    regs_rw(detail, dir,
1693
0
      info->op.operands[xy].dsp.r[dir] =
1694
0
      base[dir] + d + dir?(xy * 2):0);
1695
0
    switch(op) {
1696
0
    case 0x03:
1697
0
      regs_read(detail, SH_REG_R8 + a);
1698
      // Fail through
1699
0
    case 0x02:
1700
0
      regs_write(detail, SH_REG_R4 + xy * 2 + a);
1701
0
      break;
1702
0
    case 0x01:
1703
0
      regs_read(detail, SH_REG_R4 + xy * 2 + a);
1704
0
      break;
1705
0
    }
1706
0
  }
1707
0
  return MCDisassembler_Success;
1708
0
}
1709
1710
static bool decode_dsp_d(const uint16_t code, MCInst *MI, cs_mode mode,
1711
       sh_info *info, cs_detail *detail)
1712
0
{
1713
0
  bool ret, dsp_long;
1714
0
  MCInst_setOpcode(MI, SH_INS_DSP);
1715
0
  if ((code & 0x3ff) == 0) {
1716
0
    info->op.operands[0].dsp.insn = 
1717
0
      info->op.operands[1].dsp.insn = SH_INS_DSP_NOP;
1718
0
    info->op.op_count = 2;
1719
0
    return MCDisassembler_Success;
1720
0
  }
1721
0
  dsp_long = false;
1722
0
  if (isalevel(mode) == ISA_SH4A) {
1723
0
    if (!(code & 0x03) && (code & 0x0f) >= 0x04) {
1724
0
      ret = decode_dsp_xy(info, 0, code, detail);
1725
0
      ret &= set_dsp_move_d(info, 1, code, mode, detail);
1726
0
      dsp_long |= true;
1727
0
    }
1728
0
    if ((code & 0x0f) <= 0x03 && (code & 0xff)) {
1729
0
      ret = decode_dsp_xy(info, 1, code, detail);
1730
0
      ret &= set_dsp_move_d(info, 0, code, mode, detail);
1731
0
      dsp_long |= true;
1732
0
    }
1733
0
  }
1734
0
  if (!dsp_long) {
1735
    /* X op */
1736
0
    ret = set_dsp_move_d(info, 0, code, mode, detail);
1737
    /* Y op */
1738
0
    ret &= set_dsp_move_d(info, 1, code, mode, detail);
1739
0
  }
1740
1741
0
  info->op.op_count = 2;
1742
0
  return ret;
1743
0
}
1744
1745
static bool decode_dsp_s(const uint16_t code, MCInst *MI,
1746
       sh_info *info, cs_detail *detail)
1747
0
{
1748
0
  int d = code & 1;
1749
0
  int s = (code >> 1) & 1;
1750
0
  int opr = (code >> 2) & 3;
1751
0
  int as = (code >> 8) & 3;
1752
0
  int ds = (code >> 4) & 0x0f;
1753
0
  static const sh_reg regs[] = {
1754
0
    SH_REG_DSP_RSV0, SH_REG_DSP_RSV1, SH_REG_DSP_RSV2,
1755
0
    SH_REG_DSP_RSV3,
1756
0
    SH_REG_DSP_RSV4, SH_REG_DSP_A1, SH_REG_DSP_RSV6, SH_REG_DSP_A0,
1757
0
    SH_REG_DSP_X0, SH_REG_DSP_X1, SH_REG_DSP_Y0, SH_REG_DSP_Y1,
1758
0
    SH_REG_DSP_M0, SH_REG_DSP_A1G, SH_REG_DSP_M1, SH_REG_DSP_A0G,
1759
0
  };
1760
1761
0
  if (regs[ds] == SH_REG_INVALID)
1762
0
    return MCDisassembler_Fail;
1763
    
1764
0
  MCInst_setOpcode(MI, SH_INS_DSP);
1765
0
  info->op.operands[0].dsp.insn = SH_INS_DSP_MOV;
1766
0
  info->op.operands[0].dsp.operand[1 - d] = SH_OP_DSP_REG;
1767
0
  info->op.operands[0].dsp.operand[d] = SH_OP_DSP_REG_PRE + opr;
1768
0
  info->op.operands[0].dsp.r[1 - d] = regs[ds];
1769
0
  info->op.operands[0].dsp.r[d] = SH_REG_R2 + ((as < 2)?(as+2):(as-2));
1770
0
  switch (opr) {
1771
0
  case 3:
1772
0
    regs_read(detail, SH_REG_R8);
1773
    /* Fail through */
1774
0
  case 1:
1775
0
    regs_read(detail, info->op.operands[0].dsp.r[d]);
1776
0
    break;
1777
0
  case 0:
1778
0
  case 2:
1779
0
    regs_write(detail,  info->op.operands[0].dsp.r[d]);
1780
0
  }
1781
0
  regs_rw(detail, d, regs[ds]);
1782
0
  info->op.operands[0].dsp.size = 16 << s;
1783
0
  info->op.op_count = 1;
1784
0
  return MCDisassembler_Success;
1785
0
}
1786
1787
static const sh_reg dsp_reg_sd[6][4] = {
1788
  {SH_REG_DSP_X0, SH_REG_DSP_X1, SH_REG_DSP_Y0, SH_REG_DSP_A1},
1789
  {SH_REG_DSP_Y0, SH_REG_DSP_Y1, SH_REG_DSP_X0, SH_REG_DSP_A1},
1790
  {SH_REG_DSP_X0, SH_REG_DSP_X1, SH_REG_DSP_A0, SH_REG_DSP_A1},
1791
  {SH_REG_DSP_Y0, SH_REG_DSP_Y1, SH_REG_DSP_M0, SH_REG_DSP_M1},
1792
  {SH_REG_DSP_M0, SH_REG_DSP_M1, SH_REG_DSP_A0, SH_REG_DSP_A1},
1793
  {SH_REG_DSP_X0, SH_REG_DSP_Y0, SH_REG_DSP_A0, SH_REG_DSP_A1},
1794
};
1795
typedef enum {f_se, f_sf, f_sx, f_sy, f_dg, f_du} dsp_reg_opr;
1796
static void set_reg_dsp_read(sh_info *info, int pos, dsp_reg_opr f, int r,
1797
           cs_detail *detail)
1798
0
{
1799
0
  info->op.operands[2].dsp.r[pos] = dsp_reg_sd[f][r];
1800
0
  regs_read(detail, dsp_reg_sd[f][r]);
1801
0
}  
1802
1803
static void set_reg_dsp_write_gu(sh_info *info, int pos, dsp_reg_opr f, int r,
1804
         cs_detail *detail)
1805
0
{
1806
0
  info->op.operands[2].dsp.r[pos] = dsp_reg_sd[f][r];
1807
0
  regs_write(detail, dsp_reg_sd[f][r]);
1808
0
}  
1809
1810
static const sh_reg regs_dz[] = {
1811
  SH_REG_DSP_RSV0, SH_REG_DSP_RSV1, SH_REG_DSP_RSV2, SH_REG_DSP_RSV3,
1812
  SH_REG_DSP_RSV4, SH_REG_DSP_A1, SH_REG_DSP_RSV6, SH_REG_DSP_A0,
1813
  SH_REG_DSP_X0, SH_REG_DSP_X1, SH_REG_DSP_Y0, SH_REG_DSP_Y1,
1814
  SH_REG_DSP_M0, SH_REG_DSP_A1G, SH_REG_DSP_M1, SH_REG_DSP_A0G,
1815
};
1816
1817
static void set_reg_dsp_write_z(sh_info *info, int pos, int r,
1818
        cs_detail *detail)
1819
0
{
1820
0
  info->op.operands[2].dsp.r[pos] = regs_dz[r];
1821
0
  regs_write(detail, regs_dz[r]);
1822
0
}  
1823
1824
static bool dsp_op_cc_3opr(uint32_t code, sh_info *info, sh_dsp_insn insn,
1825
         sh_dsp_insn_type insn2, cs_detail *detail)
1826
0
{
1827
0
  info->op.operands[2].dsp.cc = (code >> 8) & 3;
1828
0
  if (info->op.operands[2].dsp.cc > 0) {
1829
0
    info->op.operands[2].dsp.insn = insn;
1830
0
  } else {
1831
0
    if (insn2 != SH_INS_DSP_INVALID)
1832
0
      info->op.operands[2].dsp.insn = (sh_dsp_insn) insn2;
1833
0
    else
1834
0
      return MCDisassembler_Fail;
1835
0
  }
1836
0
  if (info->op.operands[2].dsp.insn != SH_INS_DSP_PSUBr) {
1837
0
    set_reg_dsp_read(info, 0, f_sx, (code >> 6) & 3, detail);
1838
0
    set_reg_dsp_read(info, 1, f_sy, (code >> 4) & 3, detail);
1839
0
  } else {
1840
0
    set_reg_dsp_read(info, 1, f_sx, (code >> 6) & 3, detail);
1841
0
    set_reg_dsp_read(info, 0, f_sy, (code >> 4) & 3, detail);
1842
0
  }
1843
0
  set_reg_dsp_write_z(info, 2, code & 0x0f, detail);
1844
0
  info->op.op_count = 3;
1845
0
  return MCDisassembler_Success;
1846
0
}
1847
1848
static bool dsp_op_cc_2opr(uint32_t code, sh_info *info, sh_dsp_insn insn,
1849
         int xy, int b, cs_detail *detail)
1850
0
{
1851
0
  if (((code >> 8) & 3) == 0)
1852
0
    return MCDisassembler_Fail;
1853
0
  info->op.operands[2].dsp.insn = (sh_dsp_insn) insn;
1854
0
  set_reg_dsp_read(info, 0, xy, (code >> b) & 3, detail);
1855
0
  set_reg_dsp_write_z(info, 2, code & 0x0f, detail);
1856
0
  info->op.operands[2].dsp.cc = (code >> 8) & 3;
1857
0
  info->op.op_count = 3;
1858
0
  return MCDisassembler_Success;
1859
0
}
1860
  
1861
static bool dsp_op_cc0_2opr(uint32_t code, sh_info *info, sh_dsp_insn insn,
1862
          int xy, int b, cs_detail *detail)
1863
0
{
1864
0
  info->op.operands[2].dsp.insn = (sh_dsp_insn) insn;
1865
0
  set_reg_dsp_read(info, 0, xy, (code >> b) & 3, detail);
1866
0
  set_reg_dsp_write_z(info, 2, code & 0x0f, detail);
1867
0
  info->op.operands[2].dsp.cc = (code >> 8) & 3;  
1868
0
  if (info->op.operands[2].dsp.cc == 1)
1869
0
    return MCDisassembler_Fail;
1870
0
  if (info->op.operands[2].dsp.cc == 0)
1871
0
    info->op.operands[2].dsp.cc = SH_DSP_CC_NONE;
1872
0
  info->op.op_count = 3;
1873
0
  return MCDisassembler_Success;
1874
0
}
1875
  
1876
static bool decode_dsp_3op(const uint32_t code, sh_info *info,
1877
         cs_detail *detail)
1878
0
{
1879
0
  int cc = (code >> 8) & 3;
1880
0
  int sx = (code >> 6) & 3;
1881
0
  int sy = (code >> 4) & 3;
1882
0
  int dz = (code >> 0) & 0x0f;
1883
1884
0
  if ((code & 0xef00) == 0x8000)
1885
0
    return MCDisassembler_Fail;
1886
0
  switch((code >> 10) & 0x1f) {
1887
0
  case 0x00:
1888
0
    return dsp_op_cc_3opr(code, info,
1889
0
              SH_INS_DSP_PSHL, SH_INS_DSP_INVALID,
1890
0
              detail);
1891
0
  case 0x01:
1892
0
    if (cc == 0) {
1893
0
      info->op.operands[2].dsp.insn = SH_INS_DSP_PCMP;
1894
0
      set_reg_dsp_read(info, 0, f_sx, sx, detail);
1895
0
      set_reg_dsp_read(info, 1, f_sy, sy, detail);
1896
0
      info->op.op_count = 3;
1897
0
      return MCDisassembler_Success;
1898
0
    } else {
1899
0
      return dsp_op_cc_3opr(code, info,
1900
0
                SH_INS_DSP_PSUBr,
1901
0
                SH_INS_DSP_INVALID, detail);
1902
0
    }
1903
0
  case 0x02:
1904
0
    switch (sy) {
1905
0
    case 0:
1906
0
      if(cc == 0) {
1907
0
        info->op.operands[2].dsp.insn = SH_INS_DSP_PABS;
1908
0
        set_reg_dsp_read(info, 0, f_sx, sx, detail);
1909
0
        set_reg_dsp_write_z(info, 1, dz, detail);
1910
0
        info->op.op_count = 3;
1911
0
        return MCDisassembler_Success;
1912
0
      } else {
1913
0
        return dsp_op_cc_2opr(code, info,
1914
0
                  SH_INS_DSP_PDEC,
1915
0
                  f_sx, 6, detail);
1916
0
      }
1917
0
    case 1:
1918
0
      return dsp_op_cc0_2opr(code, info,
1919
0
                 SH_INS_DSP_PABS,
1920
0
                 f_sx, 6, detail);
1921
0
    default:
1922
0
      return MCDisassembler_Fail;
1923
0
    }     
1924
0
  case 0x03:
1925
0
    if (cc != 0) {
1926
0
      info->op.operands[2].dsp.insn = SH_INS_DSP_PCLR;
1927
0
      info->op.operands[2].dsp.cc = cc;
1928
0
      set_reg_dsp_write_z(info, 0, dz, detail);
1929
0
      info->op.op_count = 3;
1930
0
      return MCDisassembler_Success;
1931
0
    } else
1932
0
      return MCDisassembler_Fail;
1933
0
  case 0x04:
1934
0
    return dsp_op_cc_3opr(code, info,
1935
0
              SH_INS_DSP_PSHA, SH_INS_DSP_INVALID,
1936
0
              detail);
1937
0
  case 0x05:
1938
0
    return dsp_op_cc_3opr(code, info,
1939
0
              SH_INS_DSP_PAND, SH_INS_DSP_INVALID,
1940
0
              detail);
1941
0
  case 0x06:
1942
0
    switch (sy) {
1943
0
    case 0:
1944
0
      if (cc == 0) {
1945
0
        info->op.operands[2].dsp.insn = SH_INS_DSP_PRND;
1946
0
        set_reg_dsp_read(info, 0, f_sx, sx, detail);
1947
0
        set_reg_dsp_write_z(info, 1, dz, detail);
1948
0
        info->op.op_count = 3;
1949
0
        return MCDisassembler_Success;
1950
0
      } else {
1951
0
        return dsp_op_cc_2opr(code, info,
1952
0
                  SH_INS_DSP_PINC,
1953
0
                  f_sx, 6, detail);
1954
0
      }
1955
0
    case 1:
1956
0
      return dsp_op_cc0_2opr(code, info,
1957
0
                 SH_INS_DSP_PRND,
1958
0
                 f_sx, 6, detail);
1959
0
    default:
1960
0
      return MCDisassembler_Fail;
1961
0
    }
1962
0
  case 0x07:
1963
0
    switch(sy) {
1964
0
    case 0:
1965
0
      return dsp_op_cc_2opr(code, info,
1966
0
                SH_INS_DSP_PDMSB,
1967
0
                f_sx, 6, detail);
1968
0
    case 1:
1969
0
      return dsp_op_cc_2opr(code, info,
1970
0
                SH_INS_DSP_PSWAP,
1971
0
                f_sx, 6, detail);
1972
0
    default:
1973
0
      return MCDisassembler_Fail;
1974
0
    }
1975
0
  case 0x08:
1976
0
    return dsp_op_cc_3opr(code, info,
1977
0
              SH_INS_DSP_PSUB, (sh_dsp_insn_type) SH_INS_DSP_PSUBC,
1978
0
              detail);
1979
0
  case 0x09:
1980
0
    return dsp_op_cc_3opr(code, info,
1981
0
              SH_INS_DSP_PXOR, (sh_dsp_insn_type) SH_INS_DSP_PWSB,
1982
0
              detail);
1983
0
  case 0x0a:
1984
0
    switch(sx) {
1985
0
    case 0:
1986
0
      if (cc == 0) {
1987
0
        info->op.operands[2].dsp.insn = SH_INS_DSP_PABS;
1988
0
        set_reg_dsp_read(info, 0, f_sy, sy, detail);
1989
0
        set_reg_dsp_write_z(info, 1, dz, detail);
1990
0
        info->op.op_count = 3;
1991
0
        return MCDisassembler_Success;
1992
0
      } else {
1993
0
        return dsp_op_cc_2opr(code, info,
1994
0
                  SH_INS_DSP_PDEC,
1995
0
                  f_sy, 4, detail);
1996
0
      }
1997
0
    case 1:
1998
0
      return dsp_op_cc_2opr(code, info,
1999
0
                SH_INS_DSP_PABS,
2000
0
                f_sy, 4, detail);
2001
0
    default:
2002
0
      return MCDisassembler_Fail;
2003
0
    }
2004
0
  case 0x0c:
2005
0
    if (cc == 0) {
2006
0
        info->op.operands[2].dsp.insn
2007
0
          = SH_INS_DSP_PADDC;
2008
0
        set_reg_dsp_read(info, 0, f_sx, sx, detail);
2009
0
        set_reg_dsp_read(info, 1, f_sy, sy, detail);
2010
0
        set_reg_dsp_write_z(info, 2, dz, detail);
2011
0
        info->op.op_count = 3;
2012
0
        return MCDisassembler_Success;
2013
0
    } else {
2014
0
      return dsp_op_cc_3opr(code, info,
2015
0
                SH_INS_DSP_PADD,
2016
0
                SH_INS_DSP_INVALID, detail);
2017
0
    }
2018
0
  case 0x0d:
2019
0
    return dsp_op_cc_3opr(code, info,
2020
0
                SH_INS_DSP_POR,
2021
0
                (sh_dsp_insn_type) SH_INS_DSP_PWAD,
2022
0
                detail);
2023
0
  case 0x0e:
2024
0
    if (cc == 0) {
2025
0
      if (sx != 0)
2026
0
        return MCDisassembler_Fail;
2027
0
      info->op.operands[2].dsp.insn = SH_INS_DSP_PRND;
2028
0
      set_reg_dsp_read(info, 0, f_sy, sy, detail);
2029
0
      set_reg_dsp_write_z(info, 1, dz, detail);
2030
0
      info->op.op_count = 3;
2031
0
      return MCDisassembler_Success;
2032
0
    } else {
2033
0
      switch(sx) {
2034
0
      case 0:
2035
0
        return dsp_op_cc_2opr(code, info,
2036
0
                  SH_INS_DSP_PINC,
2037
0
                  f_sy, 4, detail);
2038
0
      case 1:
2039
0
        return dsp_op_cc_2opr(code, info,
2040
0
                  SH_INS_DSP_PRND,
2041
0
                  f_sy, 4, detail);
2042
0
      default:
2043
0
        return MCDisassembler_Fail;
2044
0
      }
2045
0
    }
2046
0
  case 0x0f:
2047
0
    switch(sx) {
2048
0
    case 0:
2049
0
      return dsp_op_cc_2opr(code, info,
2050
0
                SH_INS_DSP_PDMSB,
2051
0
                f_sy, 4, detail);
2052
0
    case 1:
2053
0
      return dsp_op_cc_2opr(code, info,
2054
0
                SH_INS_DSP_PSWAP,
2055
0
                f_sy, 4, detail);
2056
0
    default:
2057
0
      return MCDisassembler_Fail;
2058
0
    }
2059
0
  case 0x12:
2060
0
    return dsp_op_cc_2opr(code, info,
2061
0
              SH_INS_DSP_PNEG, f_sx, 6, detail);
2062
0
  case 0x13:
2063
0
  case 0x17:
2064
0
    if (cc > 0) {
2065
0
      info->op.operands[2].dsp.insn = SH_INS_DSP_PSTS;
2066
0
      info->op.operands[2].dsp.cc = cc;
2067
0
      regs_read(detail, 
2068
0
          info->op.operands[2].dsp.r[0]
2069
0
          = SH_REG_MACH + ((code >> 12) & 1));
2070
0
      set_reg_dsp_write_z(info, 1, dz, detail);
2071
0
      info->op.op_count = 3;
2072
0
      return MCDisassembler_Success;
2073
0
    } else {
2074
0
      return MCDisassembler_Fail;
2075
0
    }
2076
0
  case 0x16:
2077
0
    return dsp_op_cc_2opr(code, info,
2078
0
              SH_INS_DSP_PCOPY, f_sx, 6, detail);
2079
0
  case 0x1a:
2080
0
    return dsp_op_cc_2opr(code, info,
2081
0
              SH_INS_DSP_PNEG, f_sy, 4, detail);
2082
0
  case 0x1b:
2083
0
  case 0x1f:
2084
0
    if (cc > 0) {
2085
0
      info->op.operands[2].dsp.insn = SH_INS_DSP_PLDS;
2086
0
      info->op.operands[2].dsp.cc = cc;
2087
0
      info->op.operands[2].dsp.r[0] = regs_dz[dz];
2088
0
      regs_read(detail, regs_dz[dz]);
2089
0
      regs_write(detail, 
2090
0
           info->op.operands[2].dsp.r[1]
2091
0
           = SH_REG_MACH + ((code >> 12) & 1));
2092
0
      info->op.op_count = 3;
2093
0
      return MCDisassembler_Success;
2094
0
    } else {
2095
0
      return MCDisassembler_Fail;
2096
0
    }
2097
0
  case 0x1e:
2098
0
    return dsp_op_cc_2opr(code, info, SH_INS_DSP_PCOPY, f_sy, 4, detail);
2099
0
  default:
2100
0
    return MCDisassembler_Fail;
2101
0
  }   
2102
0
}
2103
2104
static bool decode_dsp_p(const uint32_t code, MCInst *MI, cs_mode mode,
2105
       sh_info *info, cs_detail *detail)
2106
0
{
2107
0
  int dz = code & 0x0f;
2108
0
  MCInst_setOpcode(MI, SH_INS_DSP);
2109
0
  if (!decode_dsp_d(code >> 16, MI, mode, info, detail))
2110
0
    return MCDisassembler_Fail;
2111
    
2112
0
  switch((code >> 12) & 0x0f) {
2113
0
  case 0x00:
2114
0
  case 0x01:
2115
0
    if ((code >> 11) & 1)
2116
0
      return MCDisassembler_Fail;
2117
0
    info->op.operands[2].dsp.insn
2118
0
      = SH_INS_DSP_PSHL + ((code >> 12) & 1);
2119
0
    info->op.operands[2].dsp.imm = (code >> 4) & 0x7f;
2120
0
    set_reg_dsp_write_z(info, 1, dz, detail);
2121
0
    info->op.op_count = 3;
2122
0
    return MCDisassembler_Success;
2123
0
  case 0x04:
2124
0
    if ((((code >> 4) & 1) && isalevel(mode) != ISA_SH4A) ||
2125
0
        (!((code >> 4) & 1) && (code &3)) ||
2126
0
        ((code >> 4) & 0x0f) >= 2)
2127
0
      return MCDisassembler_Fail;
2128
      
2129
0
    info->op.operands[2].dsp.insn
2130
0
      = SH_INS_DSP_PMULS + ((code >> 4) & 1);
2131
0
    set_reg_dsp_read(info, 0, f_se, (code >> 10) & 3, detail);
2132
0
    set_reg_dsp_read(info, 1, f_sf, (code >> 8) & 3, detail);
2133
0
    set_reg_dsp_write_gu(info, 2, f_dg, (code >> 2) & 3, detail);
2134
0
    if ((code >> 4) & 1)
2135
0
      set_reg_dsp_write_gu(info, 3, f_du,
2136
0
               (code >> 0) & 3, detail);
2137
0
    info->op.op_count = 3;
2138
0
    return MCDisassembler_Success;
2139
0
  case 0x06:
2140
0
  case 0x07:
2141
0
    info->op.operands[2].dsp.insn
2142
0
      = SH_INS_DSP_PSUB_PMULS + ((code >> 12) & 1);
2143
0
    set_reg_dsp_read(info, 0, f_sx, (code >> 6) & 3, detail);
2144
0
    set_reg_dsp_read(info, 1, f_sy, (code >> 4) & 3, detail);
2145
0
    set_reg_dsp_write_gu(info, 2, f_du, (code >> 0) & 3, detail);
2146
0
    set_reg_dsp_read(info, 3, f_se, (code >> 10) & 3, detail);
2147
0
    set_reg_dsp_read(info, 4, f_sf, (code >> 8) & 3, detail);
2148
0
    set_reg_dsp_write_gu(info, 5, f_dg, (code >> 2) & 3, detail);
2149
0
    info->op.op_count = 3;
2150
0
    return MCDisassembler_Success;
2151
0
  default:
2152
0
    if ((code >> 15) & 1)
2153
0
      return decode_dsp_3op(code, info, detail);
2154
0
  }
2155
0
  return MCDisassembler_Fail;
2156
0
}
2157
2158
static bool sh_disassemble(const uint8_t *code, MCInst *MI, uint64_t address,
2159
         cs_mode mode, uint16_t *size, int code_len,
2160
         sh_info *info, cs_detail *detail)
2161
0
{
2162
0
  int idx;
2163
0
  uint32_t insn;
2164
0
  bool dsp_result;
2165
0
  if (MODE_IS_BIG_ENDIAN(mode)) {
2166
0
    insn = code[0] << 8 | code[1];
2167
0
  } else {
2168
0
    insn = code[1] << 8 | code[0];
2169
0
  }
2170
0
  if (mode & CS_MODE_SH2A) {
2171
    /* SH2A 32bit instrcution test */
2172
0
    if (((insn & 0xf007) == 0x3001 ||
2173
0
         (insn & 0xf00e) == 0x0000)) {
2174
0
      if (code_len < 4)
2175
0
        return MCDisassembler_Fail;
2176
0
      *size = 4;
2177
      // SH2A is only BIG ENDIAN.
2178
0
      insn <<= 16;
2179
0
      insn |= code[2] << 8 | code[3];
2180
0
      if (decode_long(insn, address,  MI, info, detail))
2181
0
        return MCDisassembler_Success;
2182
0
    }
2183
0
  }
2184
  /* Co-processor instructions */
2185
0
  if ((insn & 0xf000) == 0xf000) {
2186
0
    if (mode & CS_MODE_SHDSP) {
2187
0
      dsp_result = MCDisassembler_Fail;
2188
0
      switch(insn >> 10 & 3) {
2189
0
      case 0:
2190
0
        *size = 2;
2191
0
        dsp_result = decode_dsp_d(insn, MI, mode,
2192
0
                info, detail);
2193
0
        break;
2194
0
      case 1:
2195
0
        *size = 2;
2196
0
        dsp_result = decode_dsp_s(insn, MI,
2197
0
                info, detail);
2198
0
        break;
2199
0
      case 2:
2200
0
        if (code_len < 4)
2201
0
          return MCDisassembler_Fail;
2202
0
        *size = 4;
2203
0
        if (MODE_IS_BIG_ENDIAN(mode)) {
2204
0
          insn <<= 16;
2205
0
          insn |= code[2] << 8 | code[3];
2206
0
        } else
2207
0
          insn |= (code[3] << 24)
2208
0
            | (code[2] << 16);
2209
0
        dsp_result = decode_dsp_p(insn, MI, mode,
2210
0
                info, detail);
2211
0
        break;
2212
0
      }
2213
0
      return dsp_result;
2214
0
    }
2215
0
    if ((mode & CS_MODE_SHFPU) == 0)
2216
0
      return MCDisassembler_Fail;
2217
0
  }
2218
  
2219
0
  *size = 2;
2220
0
  if ((insn & 0xf000) >= 0x8000 && (insn & 0xf000) < 0xf000) {
2221
0
    idx = insn >> 8;
2222
0
  } else {
2223
0
    idx = ((insn >> 8) & 0xf0) | (insn & 0x000f);
2224
0
  }
2225
0
  if (idx >= ARR_SIZE(decode)) {
2226
0
    return MCDisassembler_Fail;
2227
0
  }
2228
2229
0
  if (decode[idx]) {
2230
0
    return decode[idx](insn, address, MI, mode, info, detail);
2231
0
  } else {
2232
0
    return MCDisassembler_Fail;
2233
0
  }
2234
0
}
2235
      
2236
bool SH_getInstruction(csh ud, const uint8_t *code, size_t code_len,
2237
  MCInst *MI, uint16_t *size, uint64_t address, void *inst_info)
2238
0
{
2239
  
2240
0
  cs_struct* handle = (cs_struct *)ud;
2241
0
  sh_info *info = (sh_info *)handle->printer_info;
2242
0
  cs_detail *detail = MI->flat_insn->detail;
2243
2244
0
  if (code_len < 2) {
2245
0
    *size = 0;
2246
0
    return MCDisassembler_Fail;
2247
0
  }
2248
2249
0
  if (detail) {
2250
0
    memset(detail, 0, offsetof(cs_detail, sh)+sizeof(cs_sh));
2251
0
  }
2252
0
  memset(info, 0, sizeof(sh_info));
2253
0
  if (sh_disassemble(code, MI, address, handle->mode,
2254
0
         size, code_len, info, detail) == MCDisassembler_Fail) {
2255
0
    *size = 0;
2256
0
    return MCDisassembler_Fail;
2257
0
  } else {
2258
0
    if (detail)
2259
0
      detail->sh = info->op;
2260
0
    return MCDisassembler_Success;
2261
0
  }   
2262
0
}
2263
2264
#ifndef CAPSTONE_DIET
2265
void SH_reg_access(const cs_insn *insn,
2266
       cs_regs regs_read, uint8_t *regs_read_count,
2267
       cs_regs regs_write, uint8_t *regs_write_count)
2268
0
{
2269
0
        if (insn->detail == NULL) {
2270
0
                *regs_read_count = 0;
2271
0
                *regs_write_count = 0;
2272
0
        }
2273
0
        else {
2274
0
                *regs_read_count = insn->detail->regs_read_count;
2275
0
                *regs_write_count = insn->detail->regs_write_count;
2276
2277
0
                memcpy(regs_read, insn->detail->regs_read,
2278
0
                        *regs_read_count * sizeof(insn->detail->regs_read[0]));
2279
0
                memcpy(regs_write, insn->detail->regs_write,
2280
0
                        *regs_write_count *
2281
0
                        sizeof(insn->detail->regs_write[0]));
2282
0
        }
2283
0
}
2284
#endif
2285
2286