Coverage Report

Created: 2023-12-08 06:05

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