Coverage Report

Created: 2025-07-01 07:03

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