Coverage Report

Created: 2024-08-21 06:24

/src/capstonenext/arch/TriCore/TriCoreInstPrinter.c
Line
Count
Source (jump to first uncovered line)
1
//===- TriCoreInstPrinter.cpp - Convert TriCore MCInst to assembly syntax -===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
// This class prints an TriCore MCInst to a .s file.
11
//
12
//===----------------------------------------------------------------------===//
13
14
/* Capstone Disassembly Engine */
15
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
16
17
#ifdef CAPSTONE_HAS_TRICORE
18
19
#include <platform.h>
20
21
#include "../../MCInst.h"
22
#include "../../Mapping.h"
23
#include "../../MathExtras.h"
24
25
#include "TriCoreMapping.h"
26
#include "TriCoreLinkage.h"
27
28
static const char *getRegisterName(unsigned RegNo);
29
30
static void printInstruction(MCInst *, uint64_t, SStream *);
31
32
static void printOperand(MCInst *MI, int OpNum, SStream *O);
33
34
#define GET_INSTRINFO_ENUM
35
36
#include "TriCoreGenInstrInfo.inc"
37
38
#define GET_REGINFO_ENUM
39
40
#include "TriCoreGenRegisterInfo.inc"
41
42
static uint32_t wrapping_u32(int64_t x)
43
0
{
44
0
  x %= (int64_t)(UINT32_MAX);
45
0
  return (uint32_t)x;
46
0
}
47
48
static bool fill_mem(MCInst *MI, unsigned int reg, int64_t disp);
49
50
static inline void set_mem(cs_tricore_op *op, uint8_t base, int64_t disp)
51
0
{
52
0
  op->type |= TRICORE_OP_MEM;
53
0
  op->mem.base = base;
54
0
  op->mem.disp = disp;
55
0
}
56
57
static inline void fill_reg(MCInst *MI, uint32_t reg)
58
0
{
59
0
  if (!detail_is_set(MI))
60
0
    return;
61
0
  cs_tricore_op *op = TriCore_get_detail_op(MI, 0);
62
0
  op->type = TRICORE_OP_REG;
63
0
  op->reg = reg;
64
0
  TriCore_inc_op_count(MI);
65
0
}
66
67
static inline void fill_imm(MCInst *MI, int64_t imm)
68
0
{
69
0
  if (!detail_is_set(MI))
70
0
    return;
71
0
  cs_tricore *tricore = TriCore_get_detail(MI);
72
0
  if (tricore->op_count >= 1) {
73
0
    cs_tricore_op *op = TriCore_get_detail_op(MI, -1);
74
0
    if (op->type == TRICORE_OP_REG && fill_mem(MI, op->reg, imm))
75
0
      return;
76
0
  }
77
78
0
  cs_tricore_op *op = TriCore_get_detail_op(MI, 0);
79
0
  op->type = TRICORE_OP_IMM;
80
0
  op->imm = imm;
81
0
  tricore->op_count++;
82
0
}
83
84
static bool fill_mem(MCInst *MI, unsigned int reg, int64_t disp)
85
0
{
86
0
  if (!detail_is_set(MI))
87
0
    return false;
88
0
  switch (MI->flat_insn->id) {
89
0
  case TRICORE_INS_LDMST:
90
0
  case TRICORE_INS_LDLCX:
91
0
  case TRICORE_INS_LD_A:
92
0
  case TRICORE_INS_LD_B:
93
0
  case TRICORE_INS_LD_BU:
94
0
  case TRICORE_INS_LD_H:
95
0
  case TRICORE_INS_LD_HU:
96
0
  case TRICORE_INS_LD_D:
97
0
  case TRICORE_INS_LD_DA:
98
0
  case TRICORE_INS_LD_W:
99
0
  case TRICORE_INS_LD_Q:
100
0
  case TRICORE_INS_STLCX:
101
0
  case TRICORE_INS_STUCX:
102
0
  case TRICORE_INS_ST_A:
103
0
  case TRICORE_INS_ST_B:
104
0
  case TRICORE_INS_ST_H:
105
0
  case TRICORE_INS_ST_D:
106
0
  case TRICORE_INS_ST_DA:
107
0
  case TRICORE_INS_ST_W:
108
0
  case TRICORE_INS_ST_Q:
109
0
  case TRICORE_INS_CACHEI_I:
110
0
  case TRICORE_INS_CACHEI_W:
111
0
  case TRICORE_INS_CACHEI_WI:
112
0
  case TRICORE_INS_CACHEA_I:
113
0
  case TRICORE_INS_CACHEA_W:
114
0
  case TRICORE_INS_CACHEA_WI:
115
0
  case TRICORE_INS_CMPSWAP_W:
116
0
  case TRICORE_INS_SWAP_A:
117
0
  case TRICORE_INS_SWAP_W:
118
0
  case TRICORE_INS_SWAPMSK_W:
119
0
  case TRICORE_INS_LEA:
120
0
  case TRICORE_INS_LHA: {
121
0
    switch (MCInst_getOpcode(MI)) {
122
0
    case TRICORE_LDMST_abs:
123
0
    case TRICORE_LDLCX_abs:
124
0
    case TRICORE_LD_A_abs:
125
0
    case TRICORE_LD_B_abs:
126
0
    case TRICORE_LD_BU_abs:
127
0
    case TRICORE_LD_H_abs:
128
0
    case TRICORE_LD_HU_abs:
129
0
    case TRICORE_LD_D_abs:
130
0
    case TRICORE_LD_DA_abs:
131
0
    case TRICORE_LD_W_abs:
132
0
    case TRICORE_LD_Q_abs:
133
0
    case TRICORE_STLCX_abs:
134
0
    case TRICORE_STUCX_abs:
135
0
    case TRICORE_ST_A_abs:
136
0
    case TRICORE_ST_B_abs:
137
0
    case TRICORE_ST_H_abs:
138
0
    case TRICORE_ST_D_abs:
139
0
    case TRICORE_ST_DA_abs:
140
0
    case TRICORE_ST_W_abs:
141
0
    case TRICORE_ST_Q_abs:
142
0
    case TRICORE_SWAP_A_abs:
143
0
    case TRICORE_SWAP_W_abs:
144
0
    case TRICORE_LEA_abs:
145
0
    case TRICORE_LHA_abs: {
146
0
      return false;
147
0
    }
148
0
    }
149
0
    cs_tricore_op *op = TriCore_get_detail_op(MI, -1);
150
0
    op->type = 0;
151
0
    set_mem(op, reg, disp);
152
0
    return true;
153
0
  }
154
0
  }
155
0
  return false;
156
0
}
157
158
static void printOperand(MCInst *MI, int OpNum, SStream *O)
159
0
{
160
0
  if (OpNum >= MI->size)
161
0
    return;
162
163
0
  MCOperand *Op = MCInst_getOperand(MI, OpNum);
164
0
  if (MCOperand_isReg(Op)) {
165
0
    unsigned reg = MCOperand_getReg(Op);
166
0
    SStream_concat0(O, getRegisterName(reg));
167
0
    fill_reg(MI, reg);
168
0
  } else if (MCOperand_isImm(Op)) {
169
0
    int64_t Imm = MCOperand_getImm(Op);
170
0
    printUInt32Bang(O, wrapping_u32(Imm));
171
0
    fill_imm(MI, Imm);
172
0
  }
173
0
}
174
175
static void print_sign_ext(MCInst *MI, int OpNum, SStream *O, unsigned n)
176
0
{
177
0
  MCOperand *MO = MCInst_getOperand(MI, OpNum);
178
0
  if (MCOperand_isImm(MO)) {
179
0
    int64_t imm = MCOperand_getImm(MO);
180
0
    int32_t res = SignExtend32(wrapping_u32(imm), n);
181
0
    printInt32Bang(O, res);
182
0
    fill_imm(MI, res);
183
0
  } else
184
0
    printOperand(MI, OpNum, O);
185
0
}
186
187
static void off4_fixup(MCInst *MI, int64_t *off4)
188
0
{
189
0
  switch (MCInst_getOpcode(MI)) {
190
0
  case TRICORE_LD_A_slro:
191
0
  case TRICORE_LD_A_sro:
192
0
  case TRICORE_LD_W_slro:
193
0
  case TRICORE_LD_W_sro:
194
0
  case TRICORE_ST_A_sro:
195
0
  case TRICORE_ST_A_ssro:
196
0
  case TRICORE_ST_W_sro:
197
0
  case TRICORE_ST_W_ssro: {
198
0
    *off4 = *off4 * 4;
199
0
    break;
200
0
  }
201
0
  case TRICORE_LD_H_sro:
202
0
  case TRICORE_LD_H_slro:
203
0
  case TRICORE_ST_H_sro:
204
0
  case TRICORE_ST_H_ssro: {
205
0
    *off4 = *off4 * 2;
206
0
    break;
207
0
  }
208
0
  }
209
0
}
210
211
static void const8_fixup(MCInst *MI, int64_t *const8)
212
0
{
213
0
  switch (MCInst_getOpcode(MI)) {
214
0
  case TRICORE_LD_A_sc:
215
0
  case TRICORE_ST_A_sc:
216
0
  case TRICORE_ST_W_sc:
217
0
  case TRICORE_LD_W_sc: {
218
0
    *const8 = *const8 * 4;
219
0
    break;
220
0
  }
221
0
  }
222
0
}
223
224
static void print_zero_ext(MCInst *MI, int OpNum, SStream *O, unsigned n)
225
0
{
226
0
  MCOperand *MO = MCInst_getOperand(MI, OpNum);
227
0
  if (MCOperand_isImm(MO)) {
228
0
    int64_t imm = MCOperand_getImm(MO);
229
0
    for (unsigned i = n + 1; i < 32; ++i) {
230
0
      imm &= ~(1LL << i);
231
0
    }
232
0
    if (n == 4) {
233
0
      off4_fixup(MI, &imm);
234
0
    }
235
0
    if (n == 8) {
236
0
      const8_fixup(MI, &imm);
237
0
    }
238
239
0
    printUInt32Bang(O, wrapping_u32(imm));
240
0
    fill_imm(MI, imm);
241
0
  } else
242
0
    printOperand(MI, OpNum, O);
243
0
}
244
245
static void printOff18Imm(MCInst *MI, int OpNum, SStream *O)
246
0
{
247
0
  MCOperand *MO = MCInst_getOperand(MI, OpNum);
248
0
  if (MCOperand_isImm(MO)) {
249
0
    int64_t imm = MCOperand_getImm(MO);
250
0
    imm = ((wrapping_u32(imm) & 0x3C000) << 14) |
251
0
          (wrapping_u32(imm) & 0x3fff);
252
0
    printUInt32Bang(O, wrapping_u32(imm));
253
0
    fill_imm(MI, imm);
254
0
  } else
255
0
    printOperand(MI, OpNum, O);
256
0
}
257
258
// PC + sext(2 * disp)
259
0
#define DISP1(N) ((int64_t)(MI->address) + SignExtend64(disp * 2, N))
260
// PC + sext(disp) * 2
261
0
#define DISP2(N) ((int64_t)(MI->address) + SignExtend64(disp, N) * 2)
262
263
static void printDisp24Imm(MCInst *MI, int OpNum, SStream *O)
264
0
{
265
0
  MCOperand *MO = MCInst_getOperand(MI, OpNum);
266
0
  if (MCOperand_isImm(MO)) {
267
0
    int64_t disp = MCOperand_getImm(MO);
268
0
    int64_t res = 0;
269
0
    switch (MCInst_getOpcode(MI)) {
270
0
    case TRICORE_CALL_b:
271
0
    case TRICORE_FCALL_b: {
272
0
      res = DISP1(24);
273
0
      break;
274
0
    }
275
0
    case TRICORE_CALLA_b:
276
0
    case TRICORE_FCALLA_b:
277
0
    case TRICORE_JA_b:
278
0
    case TRICORE_JLA_b:
279
      // = {disp24[23:20], 7’b0000000, disp24[19:0], 1’b0};
280
0
      res = ((wrapping_u32(disp) & 0xf00000) << 28) |
281
0
            ((wrapping_u32(disp) & 0xfffff) << 1);
282
0
      break;
283
0
    case TRICORE_J_b:
284
0
    case TRICORE_JL_b:
285
0
      res = DISP2(24);
286
0
      break;
287
0
    }
288
289
0
    printUInt32Bang(O, wrapping_u32(res));
290
0
    fill_imm(MI, res);
291
0
  } else
292
0
    printOperand(MI, OpNum, O);
293
0
}
294
295
static void printDisp15Imm(MCInst *MI, int OpNum, SStream *O)
296
0
{
297
0
  MCOperand *MO = MCInst_getOperand(MI, OpNum);
298
0
  if (MCOperand_isImm(MO)) {
299
0
    int64_t disp = MCOperand_getImm(MO);
300
0
    int64_t res = 0;
301
0
    switch (MCInst_getOpcode(MI)) {
302
0
    case TRICORE_LOOP_brr:
303
0
    case TRICORE_LOOPU_brr:
304
0
      res = DISP1(15);
305
0
      break;
306
0
    case TRICORE_JEQ_brc:
307
0
    case TRICORE_JEQ_brr:
308
0
    case TRICORE_JEQ_A_brr:
309
0
    case TRICORE_JGE_brc:
310
0
    case TRICORE_JGE_brr:
311
0
    case TRICORE_JGE_U_brc:
312
0
    case TRICORE_JGE_U_brr:
313
0
    case TRICORE_JLT_brc:
314
0
    case TRICORE_JLT_brr:
315
0
    case TRICORE_JLT_U_brc:
316
0
    case TRICORE_JLT_U_brr:
317
0
    case TRICORE_JNE_brc:
318
0
    case TRICORE_JNE_brr:
319
0
    case TRICORE_JNE_A_brr:
320
0
    case TRICORE_JNED_brc:
321
0
    case TRICORE_JNED_brr:
322
0
    case TRICORE_JNEI_brc:
323
0
    case TRICORE_JNEI_brr:
324
0
    case TRICORE_JNZ_A_brr:
325
0
    case TRICORE_JNZ_T_brn:
326
0
    case TRICORE_JZ_A_brr:
327
0
    case TRICORE_JZ_T_brn:
328
0
      res = DISP2(15);
329
0
      break;
330
0
    default:
331
      // handle other cases, if any
332
0
      break;
333
0
    }
334
335
0
    printUInt32Bang(O, wrapping_u32(res));
336
0
    fill_imm(MI, res);
337
0
  } else
338
0
    printOperand(MI, OpNum, O);
339
0
}
340
341
static void printDisp8Imm(MCInst *MI, int OpNum, SStream *O)
342
0
{
343
0
  MCOperand *MO = MCInst_getOperand(MI, OpNum);
344
0
  if (MCOperand_isImm(MO)) {
345
0
    int64_t disp = MCOperand_getImm(MO);
346
0
    int64_t res = 0;
347
0
    switch (MCInst_getOpcode(MI)) {
348
0
    case TRICORE_CALL_sb:
349
0
      disp = DISP1(8);
350
0
      break;
351
0
    case TRICORE_J_sb:
352
0
    case TRICORE_JNZ_sb:
353
0
    case TRICORE_JZ_sb:
354
0
      res = DISP2(8);
355
0
      break;
356
0
    default:
357
      // handle other cases, if any
358
0
      break;
359
0
    }
360
361
0
    printUInt32Bang(O, wrapping_u32(res));
362
0
    fill_imm(MI, res);
363
0
  } else
364
0
    printOperand(MI, OpNum, O);
365
0
}
366
367
static void printDisp4Imm(MCInst *MI, int OpNum, SStream *O)
368
0
{
369
0
  MCOperand *MO = MCInst_getOperand(MI, OpNum);
370
0
  if (MCOperand_isImm(MO)) {
371
0
    int64_t disp = MCOperand_getImm(MO);
372
0
    int64_t res = 0;
373
0
    switch (MCInst_getOpcode(MI)) {
374
0
    case TRICORE_JEQ_sbc1:
375
0
    case TRICORE_JEQ_sbr1:
376
0
    case TRICORE_JGEZ_sbr:
377
0
    case TRICORE_JGTZ_sbr:
378
0
    case TRICORE_JLEZ_sbr:
379
0
    case TRICORE_JLTZ_sbr:
380
0
    case TRICORE_JNE_sbc1:
381
0
    case TRICORE_JNE_sbr1:
382
0
    case TRICORE_JNZ_sbr:
383
0
    case TRICORE_JNZ_A_sbr:
384
0
    case TRICORE_JNZ_T_sbrn:
385
0
    case TRICORE_JZ_sbr:
386
0
    case TRICORE_JZ_A_sbr:
387
0
    case TRICORE_JZ_T_sbrn:
388
      // PC + zero_ext(disp4) * 2;
389
0
      res = (int64_t)(MI->address) + disp * 2;
390
0
      break;
391
0
    case TRICORE_JEQ_sbc2:
392
0
    case TRICORE_JEQ_sbr2:
393
0
    case TRICORE_JNE_sbc2:
394
0
    case TRICORE_JNE_sbr2:
395
      // PC + zero_ext(disp4 + 16) * 2;
396
0
      res = (int64_t)(MI->address) + ((disp + 16) * 2);
397
0
      break;
398
0
    case TRICORE_LOOP_sbr:
399
      // PC + {27b’111111111111111111111111111, disp4, 0};
400
0
      res = (int64_t)MI->address +
401
0
            OneExtend32(wrapping_u32(disp) << 1, 5);
402
0
      break;
403
0
    default:
404
      // handle other cases, if any
405
0
      break;
406
0
    }
407
408
0
    printUInt32Bang(O, wrapping_u32(res));
409
0
    fill_imm(MI, res);
410
0
  } else
411
0
    printOperand(MI, OpNum, O);
412
0
}
413
414
#define printSExtImm_(n) \
415
  static void printSExtImm_##n(MCInst *MI, int OpNum, SStream *O) \
416
0
  { \
417
0
    print_sign_ext(MI, OpNum, O, n); \
418
0
  }
Unexecuted instantiation: TriCoreInstPrinter.c:printSExtImm_9
Unexecuted instantiation: TriCoreInstPrinter.c:printSExtImm_4
Unexecuted instantiation: TriCoreInstPrinter.c:printSExtImm_16
Unexecuted instantiation: TriCoreInstPrinter.c:printSExtImm_10
419
420
#define printZExtImm_(n) \
421
  static void printZExtImm_##n(MCInst *MI, int OpNum, SStream *O) \
422
0
  { \
423
0
    print_zero_ext(MI, OpNum, O, n); \
424
0
  }
Unexecuted instantiation: TriCoreInstPrinter.c:printZExtImm_8
Unexecuted instantiation: TriCoreInstPrinter.c:printZExtImm_4
Unexecuted instantiation: TriCoreInstPrinter.c:printZExtImm_16
Unexecuted instantiation: TriCoreInstPrinter.c:printZExtImm_2
Unexecuted instantiation: TriCoreInstPrinter.c:printZExtImm_9
425
426
// clang-format off
427
428
printSExtImm_(16)
429
430
printSExtImm_(10)
431
432
printSExtImm_(9)
433
434
printSExtImm_(4)
435
436
printZExtImm_(16)
437
438
printZExtImm_(9)
439
440
printZExtImm_(8)
441
442
printZExtImm_(4)
443
444
printZExtImm_(2);
445
446
// clang-format on
447
448
static void printOExtImm_4(MCInst *MI, int OpNum, SStream *O)
449
0
{
450
0
  MCOperand *MO = MCInst_getOperand(MI, OpNum);
451
0
  if (MCOperand_isImm(MO)) {
452
0
    int64_t disp = MCOperand_getImm(MO);
453
0
    int64_t res = (int64_t)MI->address +
454
0
            (int64_t)OneExtend64(disp << 1, 5);
455
0
    printUInt32Bang(O, wrapping_u32(res));
456
0
    fill_imm(MI, res);
457
0
  } else
458
0
    printOperand(MI, OpNum, O);
459
0
}
460
461
/// Returned by getMnemonic() of the AsmPrinters.
462
typedef struct {
463
  const char *first; // Mnemonic
464
  uint64_t second;   // Bits
465
} MnemonicBitsInfo;
466
467
static void set_mem_access(MCInst *MI, unsigned int access)
468
0
{
469
  // TODO: TriCore
470
0
}
471
472
#include "TriCoreGenAsmWriter.inc"
473
474
const char *TriCore_LLVM_getRegisterName(unsigned int id)
475
0
{
476
0
#ifndef CAPSTONE_DIET
477
0
  return getRegisterName(id);
478
#else
479
  return NULL;
480
#endif
481
0
}
482
483
void TriCore_LLVM_printInst(MCInst *MI, uint64_t Address, SStream *O)
484
0
{
485
0
  printInstruction(MI, Address, O);
486
0
  TriCore_set_access(MI);
487
0
}
488
489
#endif // CAPSTONE_HAS_TRICORE