mirror of
https://github.com/capstone-engine/capstone
synced 2026-08-11 16:26:07 -04:00
* Add auto-sync updater. * Update Capstone core with auto-sync changes. * Update ARM via auto-sync. * Make changes to arch modules which are introduced by auto-sync. * Update tests for ARM. * Fix build warnings for make * Remove meson.build * Print shift amount in decimal * Patch non LLVM register alias. * Change type of immediate operand to unsiged (due to: #771) * Replace all occurances of a register with its alias. * Fix printing of signed imms * Print rotate amount in decimal * CHange imm type to int64_t to match LLVM imm type. * Fix search for register names, by completing string first. * Print ModImm operands always in decimal * Use number format of previous capstone version. * Correct implicit writes and update_flags according to SBit. * Add missing test for RegImmShift * Reverse incorrect comparision. * Set shift information for move instructions. * Set mem access for all memory operands * Set subtracted flag if offset is negative. * Add flag for post-index memory operands. * Add detail op for BX_RET and MOVPCLR * Use instruction post_index operand. * Add VPOP and VPUSH as unique CS IDs. * Add shifting info for MOVsr. * Add TODOs. * Add in LLVM hardcoded operands to detail. * Move detail editing from InstPrinter to Mapping * Formatting * Add removed check. * Add writeback register and constraints to RFEI instructions. * Translate shift immediate * Print negative immediates * Remove duplicate invalid entry * Add CS groups to instructions * Fix write attriutes of stores. * Add missing names of added instructions * Fix LLVM bug * Add more post_index flags * http -> https * Make generated functions static * Remove tab prefix for alias instructions. * Set ValidateMCOperand to NULL. * Fix AddrMode3Operand operands * Allow getting system and banked register name via API * Add writeback to STC/LDC instructions. * Fix (hopefully) last case where disp is negative and subtracted = true * Remove accidentially introduced regressions
367 lines
8.6 KiB
C
367 lines
8.6 KiB
C
|
|
#ifdef CAPSTONE_HAS_RISCV
|
|
|
|
#include <stdio.h> // debug
|
|
#include <string.h>
|
|
|
|
#include "../../Mapping.h"
|
|
#include "../../utils.h"
|
|
|
|
#include "RISCVMapping.h"
|
|
#include "RISCVInstPrinter.h"
|
|
|
|
#define GET_INSTRINFO_ENUM
|
|
#include "RISCVGenInstrInfo.inc"
|
|
|
|
#ifndef CAPSTONE_DIET
|
|
static const name_map reg_name_maps[] = {
|
|
{ RISCV_REG_INVALID, NULL },
|
|
|
|
{ RISCV_REG_X0, "zero" },
|
|
{ RISCV_REG_X1, "ra" },
|
|
{ RISCV_REG_X2, "sp" },
|
|
{ RISCV_REG_X3, "gp" },
|
|
{ RISCV_REG_X4, "tp" },
|
|
{ RISCV_REG_X5, "t0" },
|
|
{ RISCV_REG_X6, "t1" },
|
|
{ RISCV_REG_X7, "t2" },
|
|
{ RISCV_REG_X8, "s0" },
|
|
{ RISCV_REG_X9, "s1" },
|
|
{ RISCV_REG_X10, "a0" },
|
|
{ RISCV_REG_X11, "a1" },
|
|
{ RISCV_REG_X12, "a2" },
|
|
{ RISCV_REG_X13, "a3" },
|
|
{ RISCV_REG_X14, "a4" },
|
|
{ RISCV_REG_X15, "a5" },
|
|
{ RISCV_REG_X16, "a6" },
|
|
{ RISCV_REG_X17, "a7" },
|
|
{ RISCV_REG_X18, "s2" },
|
|
{ RISCV_REG_X19, "s3" },
|
|
{ RISCV_REG_X20, "s4" },
|
|
{ RISCV_REG_X21, "s5" },
|
|
{ RISCV_REG_X22, "s6" },
|
|
{ RISCV_REG_X23, "s7" },
|
|
{ RISCV_REG_X24, "s8" },
|
|
{ RISCV_REG_X25, "s9" },
|
|
{ RISCV_REG_X26, "s10" },
|
|
{ RISCV_REG_X27, "s11" },
|
|
{ RISCV_REG_X28, "t3" },
|
|
{ RISCV_REG_X29, "t4" },
|
|
{ RISCV_REG_X30, "t5" },
|
|
{ RISCV_REG_X31, "t6" },
|
|
|
|
{ RISCV_REG_F0_32, "ft0" },
|
|
{ RISCV_REG_F0_64, "ft0" },
|
|
{ RISCV_REG_F1_32, "ft1" },
|
|
{ RISCV_REG_F1_64, "ft1" },
|
|
{ RISCV_REG_F2_32, "ft2" },
|
|
{ RISCV_REG_F2_64, "ft2" },
|
|
{ RISCV_REG_F3_32, "ft3" },
|
|
{ RISCV_REG_F3_64, "ft3" },
|
|
{ RISCV_REG_F4_32, "ft4" },
|
|
{ RISCV_REG_F4_64, "ft4" },
|
|
{ RISCV_REG_F5_32, "ft5" },
|
|
{ RISCV_REG_F5_64, "ft5" },
|
|
{ RISCV_REG_F6_32, "ft6" },
|
|
{ RISCV_REG_F6_64, "ft6" },
|
|
{ RISCV_REG_F7_32, "ft7" },
|
|
{ RISCV_REG_F7_64, "ft7" },
|
|
{ RISCV_REG_F8_32, "fs0" },
|
|
{ RISCV_REG_F8_64, "fs0" },
|
|
{ RISCV_REG_F9_32, "fs1" },
|
|
{ RISCV_REG_F9_64, "fs1" },
|
|
{ RISCV_REG_F10_32, "fa0" },
|
|
{ RISCV_REG_F10_64, "fa0" },
|
|
{ RISCV_REG_F11_32, "fa1" },
|
|
{ RISCV_REG_F11_64, "fa1" },
|
|
{ RISCV_REG_F12_32, "fa2" },
|
|
{ RISCV_REG_F12_64, "fa2" },
|
|
{ RISCV_REG_F13_32, "fa3" },
|
|
{ RISCV_REG_F13_64, "fa3" },
|
|
{ RISCV_REG_F14_32, "fa4" },
|
|
{ RISCV_REG_F14_64, "fa4" },
|
|
{ RISCV_REG_F15_32, "fa5" },
|
|
{ RISCV_REG_F15_64, "fa5" },
|
|
{ RISCV_REG_F16_32, "fa6" },
|
|
{ RISCV_REG_F16_64, "fa6" },
|
|
{ RISCV_REG_F17_32, "fa7" },
|
|
{ RISCV_REG_F17_64, "fa7" },
|
|
{ RISCV_REG_F18_32, "fs2" },
|
|
{ RISCV_REG_F18_64, "fs2" },
|
|
{ RISCV_REG_F19_32, "fs3" },
|
|
{ RISCV_REG_F19_64, "fs3" },
|
|
{ RISCV_REG_F20_32, "fs4" },
|
|
{ RISCV_REG_F20_64, "fs4" },
|
|
{ RISCV_REG_F21_32, "fs5" },
|
|
{ RISCV_REG_F21_64, "fs5" },
|
|
{ RISCV_REG_F22_32, "fs6" },
|
|
{ RISCV_REG_F22_64, "fs6" },
|
|
{ RISCV_REG_F23_32, "fs7" },
|
|
{ RISCV_REG_F23_64, "fs7" },
|
|
{ RISCV_REG_F24_32, "fs8" },
|
|
{ RISCV_REG_F24_64, "fs8" },
|
|
{ RISCV_REG_F25_32, "fs9" },
|
|
{ RISCV_REG_F25_64, "fs9" },
|
|
{ RISCV_REG_F26_32, "fs10" },
|
|
{ RISCV_REG_F26_64, "fs10" },
|
|
{ RISCV_REG_F27_32, "fs11" },
|
|
{ RISCV_REG_F27_64, "fs11" },
|
|
{ RISCV_REG_F28_32, "ft8" },
|
|
{ RISCV_REG_F28_64, "ft8" },
|
|
{ RISCV_REG_F29_32, "ft9" },
|
|
{ RISCV_REG_F29_64, "ft9" },
|
|
{ RISCV_REG_F30_32, "ft10" },
|
|
{ RISCV_REG_F30_64, "ft10" },
|
|
{ RISCV_REG_F31_32, "ft11" },
|
|
{ RISCV_REG_F31_64, "ft11" },
|
|
};
|
|
#endif
|
|
|
|
const char *RISCV_reg_name(csh handle, unsigned int reg)
|
|
{
|
|
#ifndef CAPSTONE_DIET
|
|
if (reg >= RISCV_REG_ENDING)
|
|
return NULL;
|
|
return reg_name_maps[reg].name;
|
|
#else
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
static const insn_map insns[] = {
|
|
// dummy item
|
|
{
|
|
0, 0,
|
|
#ifndef CAPSTONE_DIET
|
|
{0}, {0}, {0}, 0, 0
|
|
#endif
|
|
},
|
|
|
|
#include "RISCVMappingInsn.inc"
|
|
};
|
|
|
|
// given internal insn id, return public instruction info
|
|
void RISCV_get_insn_id(cs_struct * h, cs_insn * insn, unsigned int id)
|
|
{
|
|
unsigned int i;
|
|
|
|
i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
|
|
if (i != 0) {
|
|
insn->id = insns[i].mapid;
|
|
|
|
if (h->detail) {
|
|
#ifndef CAPSTONE_DIET
|
|
memcpy(insn->detail->regs_read,
|
|
insns[i].regs_use, sizeof(insns[i].regs_use));
|
|
insn->detail->regs_read_count = (uint8_t)count_positive(insns[i].regs_use);
|
|
|
|
memcpy(insn->detail->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod));
|
|
insn->detail->regs_write_count = (uint8_t)count_positive(insns[i].regs_mod);
|
|
|
|
memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups));
|
|
insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups);
|
|
|
|
if (insns[i].branch || insns[i].indirect_branch) {
|
|
// this insn also belongs to JUMP group. add JUMP group
|
|
insn->detail->groups[insn->detail->groups_count] = RISCV_GRP_JUMP;
|
|
insn->detail->groups_count++;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
static const name_map insn_name_maps[] = {
|
|
{RISCV_INS_INVALID, NULL},
|
|
|
|
#include "RISCVGenInsnNameMaps.inc"
|
|
};
|
|
|
|
const char *RISCV_insn_name(csh handle, unsigned int id)
|
|
{
|
|
#ifndef CAPSTONE_DIET
|
|
if (id >= RISCV_INS_ENDING)
|
|
return NULL;
|
|
|
|
return insn_name_maps[id].name;
|
|
#else
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
#ifndef CAPSTONE_DIET
|
|
static const name_map group_name_maps[] = {
|
|
// generic groups
|
|
{ RISCV_GRP_INVALID, NULL },
|
|
{ RISCV_GRP_JUMP, "jump" },
|
|
{ RISCV_GRP_CALL, "call" },
|
|
{ RISCV_GRP_RET, "ret" },
|
|
{ RISCV_GRP_INT, "int" },
|
|
{ RISCV_GRP_IRET, "iret" },
|
|
{ RISCV_GRP_PRIVILEGE, "privileged" },
|
|
{ RISCV_GRP_BRANCH_RELATIVE, "branch_relative" },
|
|
|
|
// architecture specific
|
|
{ RISCV_GRP_ISRV32, "isrv32" },
|
|
{ RISCV_GRP_ISRV64, "isrv64" },
|
|
{ RISCV_GRP_HASSTDEXTA, "hasStdExtA" },
|
|
{ RISCV_GRP_HASSTDEXTC, "hasStdExtC" },
|
|
{ RISCV_GRP_HASSTDEXTD, "hasStdExtD" },
|
|
{ RISCV_GRP_HASSTDEXTF, "hasStdExtF" },
|
|
{ RISCV_GRP_HASSTDEXTM, "hasStdExtM" },
|
|
|
|
/*
|
|
{ RISCV_GRP_ISRVA, "isrva" },
|
|
{ RISCV_GRP_ISRVC, "isrvc" },
|
|
{ RISCV_GRP_ISRVD, "isrvd" },
|
|
{ RISCV_GRP_ISRVCD, "isrvcd" },
|
|
{ RISCV_GRP_ISRVF, "isrvf" },
|
|
{ RISCV_GRP_ISRV32C, "isrv32c" },
|
|
{ RISCV_GRP_ISRV32CF, "isrv32cf" },
|
|
{ RISCV_GRP_ISRVM, "isrvm" },
|
|
{ RISCV_GRP_ISRV64A, "isrv64a" },
|
|
{ RISCV_GRP_ISRV64C, "isrv64c" },
|
|
{ RISCV_GRP_ISRV64D, "isrv64d" },
|
|
{ RISCV_GRP_ISRV64F, "isrv64f" },
|
|
{ RISCV_GRP_ISRV64M, "isrv64m" }
|
|
*/
|
|
{ RISCV_GRP_ENDING, NULL }
|
|
};
|
|
#endif
|
|
|
|
const char *RISCV_group_name(csh handle, unsigned int id)
|
|
{
|
|
#ifndef CAPSTONE_DIET
|
|
// verify group id
|
|
if (id >= RISCV_GRP_ENDING ||
|
|
(id > RISCV_GRP_BRANCH_RELATIVE && id < RISCV_GRP_ISRV32))
|
|
return NULL;
|
|
return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
|
|
#else
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
// map instruction name to public instruction ID
|
|
riscv_reg RISCV_map_insn(const char *name)
|
|
{
|
|
// handle special alias first
|
|
unsigned int i;
|
|
|
|
// NOTE: skip first NULL name in insn_name_maps
|
|
i = name2id(&insn_name_maps[1], ARR_SIZE(insn_name_maps) - 1, name);
|
|
|
|
return (i != -1) ? i : RISCV_REG_INVALID;
|
|
}
|
|
|
|
// map internal raw register to 'public' register
|
|
riscv_reg RISCV_map_register(unsigned int r)
|
|
{
|
|
static const unsigned int map[] = { 0,
|
|
RISCV_REG_X0,
|
|
RISCV_REG_X1,
|
|
RISCV_REG_X2,
|
|
RISCV_REG_X3,
|
|
RISCV_REG_X4,
|
|
RISCV_REG_X5,
|
|
RISCV_REG_X6,
|
|
RISCV_REG_X7,
|
|
RISCV_REG_X8,
|
|
RISCV_REG_X9,
|
|
RISCV_REG_X10,
|
|
RISCV_REG_X11,
|
|
RISCV_REG_X12,
|
|
RISCV_REG_X13,
|
|
RISCV_REG_X14,
|
|
RISCV_REG_X15,
|
|
RISCV_REG_X16,
|
|
RISCV_REG_X17,
|
|
RISCV_REG_X18,
|
|
RISCV_REG_X19,
|
|
RISCV_REG_X20,
|
|
RISCV_REG_X21,
|
|
RISCV_REG_X22,
|
|
RISCV_REG_X23,
|
|
RISCV_REG_X24,
|
|
RISCV_REG_X25,
|
|
RISCV_REG_X26,
|
|
RISCV_REG_X27,
|
|
RISCV_REG_X28,
|
|
RISCV_REG_X29,
|
|
RISCV_REG_X30,
|
|
RISCV_REG_X31,
|
|
|
|
RISCV_REG_F0_32,
|
|
RISCV_REG_F0_64,
|
|
RISCV_REG_F1_32,
|
|
RISCV_REG_F1_64,
|
|
RISCV_REG_F2_32,
|
|
RISCV_REG_F2_64,
|
|
RISCV_REG_F3_32,
|
|
RISCV_REG_F3_64,
|
|
RISCV_REG_F4_32,
|
|
RISCV_REG_F4_64,
|
|
RISCV_REG_F5_32,
|
|
RISCV_REG_F5_64,
|
|
RISCV_REG_F6_32,
|
|
RISCV_REG_F6_64,
|
|
RISCV_REG_F7_32,
|
|
RISCV_REG_F7_64,
|
|
RISCV_REG_F8_32,
|
|
RISCV_REG_F8_64,
|
|
RISCV_REG_F9_32,
|
|
RISCV_REG_F9_64,
|
|
RISCV_REG_F10_32,
|
|
RISCV_REG_F10_64,
|
|
RISCV_REG_F11_32,
|
|
RISCV_REG_F11_64,
|
|
RISCV_REG_F12_32,
|
|
RISCV_REG_F12_64,
|
|
RISCV_REG_F13_32,
|
|
RISCV_REG_F13_64,
|
|
RISCV_REG_F14_32,
|
|
RISCV_REG_F14_64,
|
|
RISCV_REG_F15_32,
|
|
RISCV_REG_F15_64,
|
|
RISCV_REG_F16_32,
|
|
RISCV_REG_F16_64,
|
|
RISCV_REG_F17_32,
|
|
RISCV_REG_F17_64,
|
|
RISCV_REG_F18_32,
|
|
RISCV_REG_F18_64,
|
|
RISCV_REG_F19_32,
|
|
RISCV_REG_F19_64,
|
|
RISCV_REG_F20_32,
|
|
RISCV_REG_F20_64,
|
|
RISCV_REG_F21_32,
|
|
RISCV_REG_F21_64,
|
|
RISCV_REG_F22_32,
|
|
RISCV_REG_F22_64,
|
|
RISCV_REG_F23_32,
|
|
RISCV_REG_F23_64,
|
|
RISCV_REG_F24_32,
|
|
RISCV_REG_F24_64,
|
|
RISCV_REG_F25_32,
|
|
RISCV_REG_F25_64,
|
|
RISCV_REG_F26_32,
|
|
RISCV_REG_F26_64,
|
|
RISCV_REG_F27_32,
|
|
RISCV_REG_F27_64,
|
|
RISCV_REG_F28_32,
|
|
RISCV_REG_F28_64,
|
|
RISCV_REG_F29_32,
|
|
RISCV_REG_F29_64,
|
|
RISCV_REG_F30_32,
|
|
RISCV_REG_F30_64,
|
|
RISCV_REG_F31_32,
|
|
RISCV_REG_F31_64,
|
|
};
|
|
|
|
if (r < ARR_SIZE(map))
|
|
return map[r];
|
|
|
|
// cannot find this register
|
|
return 0;
|
|
}
|
|
|
|
#endif
|