Coverage Report

Created: 2025-10-12 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonenext/arch/Mips/MipsMapping.c
Line
Count
Source
1
/* Capstone Disassembly Engine */
2
/* By Giovanni Dante Grazioli, deroad <wargio@libero.it>, 2024 */
3
4
#ifdef CAPSTONE_HAS_MIPS
5
6
#include <stdio.h>
7
#include <string.h>
8
9
#include <capstone/capstone.h>
10
#include <capstone/mips.h>
11
12
#include "../../Mapping.h"
13
#include "../../MCDisassembler.h"
14
#include "../../cs_priv.h"
15
#include "../../cs_simple_types.h"
16
17
#include "MipsMapping.h"
18
#include "MipsLinkage.h"
19
#include "MipsDisassembler.h"
20
21
#define GET_REGINFO_ENUM
22
#define GET_REGINFO_MC_DESC
23
#include "MipsGenRegisterInfo.inc"
24
25
#define GET_INSTRINFO_ENUM
26
#include "MipsGenInstrInfo.inc"
27
28
void Mips_init_mri(MCRegisterInfo *MRI)
29
2.87k
{
30
2.87k
  MCRegisterInfo_InitMCRegisterInfo(MRI, MipsRegDesc, sizeof(MipsRegDesc),
31
2.87k
            0, 0, MipsMCRegisterClasses,
32
2.87k
            ARR_SIZE(MipsMCRegisterClasses), 0, 0,
33
2.87k
            MipsRegDiffLists, 0,
34
2.87k
            MipsSubRegIdxLists,
35
2.87k
            ARR_SIZE(MipsSubRegIdxLists), 0);
36
2.87k
}
37
38
const char *Mips_reg_name(csh handle, unsigned int reg)
39
22.1k
{
40
22.1k
  int syntax_opt = ((cs_struct *)(uintptr_t)handle)->syntax;
41
22.1k
  return Mips_LLVM_getRegisterName(reg,
42
22.1k
           syntax_opt & CS_OPT_SYNTAX_NOREGNAME);
43
22.1k
}
44
45
void Mips_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
46
87.3k
{
47
  // Not used by Mips. Information is set after disassembly.
48
87.3k
}
49
50
static const char *const insn_name_maps[] = {
51
#include "MipsGenCSMappingInsnName.inc"
52
};
53
54
#ifndef CAPSTONE_DIET
55
static const name_map insn_alias_mnem_map[] = {
56
#include "MipsGenCSAliasMnemMap.inc"
57
  // The followings aliases are not generated by LLVM table gen.
58
  { MIPS_INS_ALIAS_B, "b" }, // beq
59
  { MIPS_INS_ALIAS_BEQZ, "beqz" }, // beq
60
  { MIPS_INS_ALIAS_BNEZ, "bnez" }, // bne
61
  { MIPS_INS_ALIAS_LI, "li" }, // addiu
62
  { MIPS_INS_ALIAS_END, NULL },
63
};
64
#endif
65
const char *Mips_insn_name(csh handle, unsigned int id)
66
87.3k
{
67
87.3k
#ifndef CAPSTONE_DIET
68
87.3k
  if (id < MIPS_INS_ALIAS_END && id > MIPS_INS_ALIAS_BEGIN) {
69
0
    if (id - MIPS_INS_ALIAS_BEGIN >= ARR_SIZE(insn_alias_mnem_map))
70
0
      return NULL;
71
72
0
    return insn_alias_mnem_map[id - MIPS_INS_ALIAS_BEGIN - 1].name;
73
0
  }
74
87.3k
  if (id >= MIPS_INS_ENDING)
75
0
    return NULL;
76
77
87.3k
  if (id < ARR_SIZE(insn_name_maps))
78
87.3k
    return insn_name_maps[id];
79
  // not found
80
0
  return NULL;
81
#else
82
  return NULL;
83
#endif
84
87.3k
}
85
86
#ifndef CAPSTONE_DIET
87
static const name_map group_name_maps[] = {
88
  { MIPS_GRP_INVALID, NULL },
89
90
  { MIPS_GRP_JUMP, "jump" },
91
  { MIPS_GRP_CALL, "call" },
92
  { MIPS_GRP_RET, "return" },
93
  { MIPS_GRP_INT, "int" },
94
  { MIPS_GRP_IRET, "iret" },
95
  { MIPS_GRP_PRIVILEGE, "privilege" },
96
  { MIPS_GRP_BRANCH_RELATIVE, "branch_relative" },
97
98
// architecture-specific groups
99
#include "MipsGenCSFeatureName.inc"
100
};
101
#endif
102
103
const char *Mips_group_name(csh handle, unsigned int id)
104
444k
{
105
444k
#ifndef CAPSTONE_DIET
106
444k
  return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
107
#else
108
  return NULL;
109
#endif
110
444k
}
111
112
const insn_map mips_insns[] = {
113
#include "MipsGenCSMappingInsn.inc"
114
};
115
116
void Mips_reg_access(const cs_insn *insn, cs_regs regs_read,
117
         uint8_t *regs_read_count, cs_regs regs_write,
118
         uint8_t *regs_write_count)
119
0
{
120
0
  uint8_t i;
121
0
  uint8_t read_count, write_count;
122
0
  cs_mips *mips = &(insn->detail->mips);
123
124
0
  read_count = insn->detail->regs_read_count;
125
0
  write_count = insn->detail->regs_write_count;
126
127
  // implicit registers
128
0
  memcpy(regs_read, insn->detail->regs_read,
129
0
         read_count * sizeof(insn->detail->regs_read[0]));
130
0
  memcpy(regs_write, insn->detail->regs_write,
131
0
         write_count * sizeof(insn->detail->regs_write[0]));
132
133
  // explicit registers
134
0
  for (i = 0; i < mips->op_count; i++) {
135
0
    cs_mips_op *op = &(mips->operands[i]);
136
0
    switch ((int)op->type) {
137
0
    case MIPS_OP_REG:
138
0
      if ((op->access & CS_AC_READ) &&
139
0
          !arr_exist(regs_read, read_count, op->reg)) {
140
0
        regs_read[read_count] = (uint16_t)op->reg;
141
0
        read_count++;
142
0
      }
143
0
      if ((op->access & CS_AC_WRITE) &&
144
0
          !arr_exist(regs_write, write_count, op->reg)) {
145
0
        regs_write[write_count] = (uint16_t)op->reg;
146
0
        write_count++;
147
0
      }
148
0
      break;
149
0
    case MIPS_OP_MEM:
150
      // registers appeared in memory references always being read
151
0
      if ((op->mem.base != MIPS_REG_INVALID) &&
152
0
          !arr_exist(regs_read, read_count, op->mem.base)) {
153
0
        regs_read[read_count] = (uint16_t)op->mem.base;
154
0
        read_count++;
155
0
      }
156
0
      if ((insn->detail->writeback) &&
157
0
          (op->mem.base != MIPS_REG_INVALID) &&
158
0
          !arr_exist(regs_write, write_count, op->mem.base)) {
159
0
        regs_write[write_count] =
160
0
          (uint16_t)op->mem.base;
161
0
        write_count++;
162
0
      }
163
0
    default:
164
0
      break;
165
0
    }
166
0
  }
167
168
0
  *regs_read_count = read_count;
169
0
  *regs_write_count = write_count;
170
0
}
171
172
void Mips_set_instr_map_data(MCInst *MI)
173
87.3k
{
174
  // Fixes for missing groups.
175
87.3k
  if (MCInst_getOpcode(MI) == Mips_JR) {
176
23
    unsigned Reg = MCInst_getOpVal(MI, 0);
177
23
    switch (Reg) {
178
10
    case MIPS_REG_RA:
179
10
    case MIPS_REG_RA_64:
180
10
      add_group(MI, MIPS_GRP_RET);
181
10
      break;
182
23
    }
183
23
  }
184
185
87.3k
  map_cs_id(MI, mips_insns, ARR_SIZE(mips_insns));
186
87.3k
  map_implicit_reads(MI, mips_insns);
187
87.3k
  map_implicit_writes(MI, mips_insns);
188
87.3k
  map_groups(MI, mips_insns);
189
87.3k
}
190
191
bool Mips_getInstruction(csh handle, const uint8_t *code, size_t code_len,
192
       MCInst *instr, uint16_t *size, uint64_t address,
193
       void *info)
194
89.1k
{
195
89.1k
  uint64_t size64;
196
89.1k
  Mips_init_cs_detail(instr);
197
89.1k
  instr->MRI = (MCRegisterInfo *)info;
198
89.1k
  map_set_fill_detail_ops(instr, true);
199
200
89.1k
  DecodeStatus Result = Mips_LLVM_getInstruction(instr, &size64, code,
201
89.1k
                   code_len, address, info);
202
89.1k
  *size = size64;
203
89.1k
  if (Result != MCDisassembler_Fail) {
204
87.3k
    Mips_set_instr_map_data(instr);
205
87.3k
  }
206
89.1k
  if (Result == MCDisassembler_SoftFail) {
207
0
    MCInst_setSoftFail(instr);
208
0
  }
209
89.1k
  return Result != MCDisassembler_Fail;
210
89.1k
}
211
212
void Mips_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info)
213
87.3k
{
214
87.3k
  MCRegisterInfo *MRI = (MCRegisterInfo *)info;
215
87.3k
  MI->MRI = MRI;
216
217
87.3k
  Mips_LLVM_printInst(MI, MI->address, O);
218
87.3k
#ifndef CAPSTONE_DIET
219
87.3k
  map_set_alias_id(MI, O, insn_alias_mnem_map,
220
87.3k
       ARR_SIZE(insn_alias_mnem_map));
221
87.3k
#endif
222
87.3k
}
223
224
static void Mips_setup_op(cs_mips_op *op)
225
1.42M
{
226
1.42M
  memset(op, 0, sizeof(cs_mips_op));
227
1.42M
  op->type = MIPS_OP_INVALID;
228
1.42M
}
229
230
void Mips_init_cs_detail(MCInst *MI)
231
89.1k
{
232
89.1k
  if (detail_is_set(MI)) {
233
89.1k
    unsigned int i;
234
235
89.1k
    memset(get_detail(MI), 0,
236
89.1k
           offsetof(cs_detail, mips) + sizeof(cs_mips));
237
238
1.51M
    for (i = 0; i < ARR_SIZE(Mips_get_detail(MI)->operands); i++)
239
1.42M
      Mips_setup_op(&Mips_get_detail(MI)->operands[i]);
240
89.1k
  }
241
89.1k
}
242
243
static const map_insn_ops insn_operands[] = {
244
#include "MipsGenCSMappingInsnOp.inc"
245
};
246
247
static void Mips_set_detail_op_mem_reg(MCInst *MI, unsigned OpNum, mips_reg Reg)
248
21.5k
{
249
21.5k
  Mips_get_detail_op(MI, 0)->type = MIPS_OP_MEM;
250
21.5k
  Mips_get_detail_op(MI, 0)->mem.base = Reg;
251
21.5k
  Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
252
21.5k
}
253
254
static void Mips_set_detail_op_mem_disp(MCInst *MI, unsigned OpNum, int64_t Imm)
255
22.1k
{
256
22.1k
  Mips_get_detail_op(MI, 0)->type = MIPS_OP_MEM;
257
22.1k
  Mips_get_detail_op(MI, 0)->mem.disp = Imm;
258
22.1k
  Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
259
22.1k
}
260
261
static void Mips_set_detail_op_imm(MCInst *MI, unsigned OpNum, int64_t Imm)
262
34.4k
{
263
34.4k
  if (!detail_is_set(MI))
264
0
    return;
265
266
34.4k
  if (doing_mem(MI)) {
267
22.1k
    Mips_set_detail_op_mem_disp(MI, OpNum, Imm);
268
22.1k
    return;
269
22.1k
  }
270
271
12.3k
  Mips_get_detail_op(MI, 0)->type = MIPS_OP_IMM;
272
12.3k
  Mips_get_detail_op(MI, 0)->imm = Imm;
273
12.3k
  Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
274
12.3k
  Mips_inc_op_count(MI);
275
12.3k
}
276
277
static void Mips_set_detail_op_uimm(MCInst *MI, unsigned OpNum, uint64_t Imm)
278
33.7k
{
279
33.7k
  if (!detail_is_set(MI))
280
0
    return;
281
282
33.7k
  if (doing_mem(MI)) {
283
0
    Mips_set_detail_op_mem_disp(MI, OpNum, Imm);
284
0
    return;
285
0
  }
286
287
33.7k
  Mips_get_detail_op(MI, 0)->type = MIPS_OP_IMM;
288
33.7k
  Mips_get_detail_op(MI, 0)->uimm = Imm;
289
33.7k
  Mips_get_detail_op(MI, 0)->is_unsigned = true;
290
33.7k
  Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
291
33.7k
  Mips_inc_op_count(MI);
292
33.7k
}
293
294
static void Mips_set_detail_op_reg(MCInst *MI, unsigned OpNum, mips_reg Reg,
295
           bool is_reglist)
296
154k
{
297
154k
  if (!detail_is_set(MI))
298
0
    return;
299
300
154k
  if (doing_mem(MI)) {
301
21.5k
    Mips_set_detail_op_mem_reg(MI, OpNum, Reg);
302
21.5k
    return;
303
21.5k
  }
304
305
133k
  CS_ASSERT(is_reglist ||
306
133k
      (map_get_op_type(MI, OpNum) & ~CS_OP_MEM) == CS_OP_REG);
307
133k
  Mips_get_detail_op(MI, 0)->type = MIPS_OP_REG;
308
133k
  Mips_get_detail_op(MI, 0)->reg = Reg;
309
133k
  Mips_get_detail_op(MI, 0)->is_reglist = is_reglist;
310
133k
  Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
311
133k
  Mips_inc_op_count(MI);
312
133k
}
313
314
static void Mips_set_detail_op_operand(MCInst *MI, unsigned OpNum)
315
186k
{
316
186k
  cs_op_type op_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM;
317
186k
  int64_t value = MCInst_getOpVal(MI, OpNum);
318
186k
  if (op_type == CS_OP_IMM) {
319
34.4k
    Mips_set_detail_op_imm(MI, OpNum, value);
320
152k
  } else if (op_type == CS_OP_REG) {
321
150k
    Mips_set_detail_op_reg(MI, OpNum, value, false);
322
150k
  } else {
323
    // Register list which ends with a memory operand
324
    // Gives very large MCInst operand numbers but don't
325
    // have the respective Capstone type in the mapping table.
326
1.18k
    if (MCOperand_isImm(MCInst_getOperand(MI, OpNum))) {
327
862
      Mips_get_detail_op(MI, 0)->type = MIPS_OP_MEM;
328
862
      Mips_get_detail_op(MI, 0)->mem.disp = value;
329
862
    } else if (MCOperand_isReg(MCInst_getOperand(MI, OpNum))) {
330
319
      Mips_get_detail_op(MI, 0)->mem.base = value;
331
319
    } else {
332
0
      printf("Operand type %d not handled!\n", op_type);
333
0
    }
334
1.18k
  }
335
186k
}
336
337
static void Mips_set_detail_op_jump(MCInst *MI, unsigned OpNum)
338
2.48k
{
339
2.48k
  cs_op_type op_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM;
340
2.48k
  if (op_type == CS_OP_IMM) {
341
2.48k
    uint64_t Base = MI->address & ~0x0fffffffull;
342
2.48k
    uint64_t Target = Base | (uint64_t)MCInst_getOpVal(MI, OpNum);
343
2.48k
    Mips_set_detail_op_uimm(MI, OpNum, Target);
344
2.48k
  } else if (op_type == CS_OP_REG) {
345
0
    Mips_set_detail_op_reg(MI, OpNum, MCInst_getOpVal(MI, OpNum),
346
0
               false);
347
0
  } else
348
0
    printf("Operand type %d not handled!\n", op_type);
349
2.48k
}
350
351
static void Mips_set_detail_op_branch(MCInst *MI, unsigned OpNum)
352
17.1k
{
353
17.1k
  cs_op_type op_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM;
354
17.1k
  if (op_type == CS_OP_IMM) {
355
16.4k
    uint64_t Target = MI->address + MCInst_getOpVal(MI, OpNum);
356
16.4k
    Mips_set_detail_op_uimm(MI, OpNum, Target);
357
16.4k
  } else if (op_type == CS_OP_REG) {
358
705
    Mips_set_detail_op_reg(MI, OpNum, MCInst_getOpVal(MI, OpNum),
359
705
               false);
360
705
  } else
361
0
    printf("Operand type %d not handled!\n", op_type);
362
17.1k
}
363
364
static void Mips_set_detail_op_unsigned(MCInst *MI, unsigned OpNum)
365
0
{
366
0
  Mips_set_detail_op_uimm(MI, OpNum, MCInst_getOpVal(MI, OpNum));
367
0
}
368
369
static void Mips_set_detail_op_unsigned_offset(MCInst *MI, unsigned OpNum,
370
                 unsigned Bits, uint64_t Offset)
371
14.7k
{
372
14.7k
  uint64_t Imm = MCInst_getOpVal(MI, OpNum);
373
14.7k
  Imm -= Offset;
374
14.7k
  Imm &= (((uint64_t)1) << Bits) - 1;
375
14.7k
  Imm += Offset;
376
14.7k
  Mips_set_detail_op_uimm(MI, OpNum, Imm);
377
14.7k
}
378
379
static void Mips_set_detail_op_mem_nanomips(MCInst *MI, unsigned OpNum)
380
0
{
381
0
  CS_ASSERT(doing_mem(MI));
382
383
0
  MCOperand *Op = MCInst_getOperand(MI, OpNum);
384
0
  Mips_get_detail_op(MI, 0)->type = MIPS_OP_MEM;
385
  // Base is a register, but nanoMips uses the Imm value as register.
386
0
  Mips_get_detail_op(MI, 0)->mem.base = MCOperand_getImm(Op);
387
0
  Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
388
0
}
389
390
static void Mips_set_detail_op_reglist(MCInst *MI, unsigned OpNum,
391
               bool isNanoMips)
392
935
{
393
935
  if (isNanoMips) {
394
0
    for (unsigned i = OpNum; i < MCInst_getNumOperands(MI); i++) {
395
0
      Mips_set_detail_op_reg(MI, i, MCInst_getOpVal(MI, i),
396
0
                 true);
397
0
    }
398
0
    return;
399
0
  }
400
  // -2 because register List is always first operand of instruction
401
  // and it is always followed by memory operand (base + offset).
402
4.00k
  for (unsigned i = OpNum, e = MCInst_getNumOperands(MI) - 2; i != e;
403
3.06k
       ++i) {
404
3.06k
    Mips_set_detail_op_reg(MI, i, MCInst_getOpVal(MI, i), true);
405
3.06k
  }
406
935
}
407
408
static void Mips_set_detail_op_unsigned_address(MCInst *MI, unsigned OpNum)
409
0
{
410
0
  uint64_t Target = MI->address + (uint64_t)MCInst_getOpVal(MI, OpNum);
411
0
  Mips_set_detail_op_imm(MI, OpNum, Target);
412
0
}
413
414
void Mips_add_cs_detail(MCInst *MI, mips_op_group op_group, va_list args)
415
221k
{
416
221k
  if (!detail_is_set(MI) || !map_fill_detail_ops(MI))
417
0
    return;
418
419
221k
  unsigned OpNum = va_arg(args, unsigned);
420
421
221k
  switch (op_group) {
422
0
  default:
423
0
    printf("Operand group %d not handled!\n", op_group);
424
0
    return;
425
0
  case Mips_OP_GROUP_MemOperand:
426
    // this is only used by nanoMips.
427
0
    return Mips_set_detail_op_mem_nanomips(MI, OpNum);
428
17.1k
  case Mips_OP_GROUP_BranchOperand:
429
17.1k
    return Mips_set_detail_op_branch(MI, OpNum);
430
2.48k
  case Mips_OP_GROUP_JumpOperand:
431
2.48k
    return Mips_set_detail_op_jump(MI, OpNum);
432
186k
  case Mips_OP_GROUP_Operand:
433
186k
    return Mips_set_detail_op_operand(MI, OpNum);
434
699
  case Mips_OP_GROUP_UImm_1_0:
435
699
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 1, 0);
436
1.14k
  case Mips_OP_GROUP_UImm_2_0:
437
1.14k
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 2, 0);
438
2.16k
  case Mips_OP_GROUP_UImm_3_0:
439
2.16k
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 3, 0);
440
0
  case Mips_OP_GROUP_UImm_32_0:
441
0
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 32, 0);
442
3.11k
  case Mips_OP_GROUP_UImm_16_0:
443
3.11k
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 16, 0);
444
1.00k
  case Mips_OP_GROUP_UImm_8_0:
445
1.00k
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 8, 0);
446
2.45k
  case Mips_OP_GROUP_UImm_5_0:
447
2.45k
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 5, 0);
448
319
  case Mips_OP_GROUP_UImm_6_0:
449
319
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 6, 0);
450
2.02k
  case Mips_OP_GROUP_UImm_4_0:
451
2.02k
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 4, 0);
452
47
  case Mips_OP_GROUP_UImm_7_0:
453
47
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 7, 0);
454
1.29k
  case Mips_OP_GROUP_UImm_10_0:
455
1.29k
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 10, 0);
456
0
  case Mips_OP_GROUP_UImm_6_1:
457
0
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 6, 1);
458
111
  case Mips_OP_GROUP_UImm_5_1:
459
111
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 5, 1);
460
0
  case Mips_OP_GROUP_UImm_5_33:
461
0
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 5, 33);
462
0
  case Mips_OP_GROUP_UImm_5_32:
463
0
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 5, 32);
464
0
  case Mips_OP_GROUP_UImm_6_2:
465
0
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 6, 2);
466
173
  case Mips_OP_GROUP_UImm_2_1:
467
173
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 2, 1);
468
163
  case Mips_OP_GROUP_UImm_0_0:
469
163
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 0, 0);
470
0
  case Mips_OP_GROUP_UImm_26_0:
471
0
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 26, 0);
472
0
  case Mips_OP_GROUP_UImm_12_0:
473
0
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 12, 0);
474
96
  case Mips_OP_GROUP_UImm_20_0:
475
96
    return Mips_set_detail_op_unsigned_offset(MI, OpNum, 20, 0);
476
935
  case Mips_OP_GROUP_RegisterList:
477
935
    return Mips_set_detail_op_reglist(MI, OpNum, false);
478
0
  case Mips_OP_GROUP_NanoMipsRegisterList:
479
0
    return Mips_set_detail_op_reglist(MI, OpNum, true);
480
0
  case Mips_OP_GROUP_PCRel:
481
    /* fall-thru */
482
0
  case Mips_OP_GROUP_Hi20PCRel:
483
0
    return Mips_set_detail_op_unsigned_address(MI, OpNum);
484
0
  case Mips_OP_GROUP_Hi20:
485
0
    return Mips_set_detail_op_unsigned(MI, OpNum);
486
221k
  }
487
221k
}
488
489
void Mips_set_mem_access(MCInst *MI, bool status)
490
44.9k
{
491
44.9k
  if (!detail_is_set(MI))
492
0
    return;
493
44.9k
  set_doing_mem(MI, status);
494
44.9k
  if (status) {
495
22.4k
    if (Mips_get_detail(MI)->op_count > 0 &&
496
22.1k
        Mips_get_detail_op(MI, -1)->type == MIPS_OP_MEM &&
497
0
        Mips_get_detail_op(MI, -1)->mem.disp == 0) {
498
      // Previous memory operand not done yet. Select it.
499
0
      Mips_dec_op_count(MI);
500
0
      return;
501
0
    }
502
503
    // Init a new one.
504
22.4k
    Mips_get_detail_op(MI, 0)->type = MIPS_OP_MEM;
505
22.4k
    Mips_get_detail_op(MI, 0)->mem.base = MIPS_REG_INVALID;
506
22.4k
    Mips_get_detail_op(MI, 0)->mem.disp = 0;
507
508
22.4k
#ifndef CAPSTONE_DIET
509
22.4k
    uint8_t access =
510
22.4k
      map_get_op_access(MI, Mips_get_detail(MI)->op_count);
511
22.4k
    Mips_get_detail_op(MI, 0)->access = access;
512
22.4k
#endif
513
22.4k
  } else {
514
    // done, select the next operand slot
515
22.4k
    Mips_inc_op_count(MI);
516
22.4k
  }
517
44.9k
}
518
519
#endif