Skip to content

Commit 6f02d7a

Browse files
committed
add frm operands to float/double instructions
1 parent faffeec commit 6f02d7a

12 files changed

Lines changed: 97 additions & 7 deletions

File tree

arch/RISCV/RISCVMapping.c

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "../../cs_simple_types.h"
1212
#include "../../utils.h"
1313

14+
#include "RISCVBaseInfo.h"
1415
#include "RISCVMapping.h"
1516

1617
#define GET_INSTRINFO_ENUM
@@ -53,11 +54,38 @@ void RISCV_add_cs_detail_0(MCInst *MI, riscv_op_group opgroup, unsigned OpNum)
5354
{
5455
if (!detail_is_set(MI))
5556
return;
56-
// are not "true" arguments and has no Capstone equivalent
57+
// Rounding mode: store in detail, not as a regular operand.
5758
if (opgroup == RISCV_OP_GROUP_FRMArg ||
58-
opgroup == RISCV_OP_GROUP_FRMArgLegacy)
59+
opgroup == RISCV_OP_GROUP_FRMArgLegacy) {
60+
unsigned frm = (unsigned)MCInst_getOperand(MI, OpNum)->ImmVal;
61+
riscv_rounding_mode rm;
62+
switch (frm) {
63+
case RISCVFPRndMode_RNE:
64+
rm = RISCV_RM_RNE;
65+
break;
66+
case RISCVFPRndMode_RTZ:
67+
rm = RISCV_RM_RTZ;
68+
break;
69+
case RISCVFPRndMode_RDN:
70+
rm = RISCV_RM_RDN;
71+
break;
72+
case RISCVFPRndMode_RUP:
73+
rm = RISCV_RM_RUP;
74+
break;
75+
case RISCVFPRndMode_RMM:
76+
rm = RISCV_RM_RMM;
77+
break;
78+
case RISCVFPRndMode_DYN:
79+
rm = RISCV_RM_DYN;
80+
break;
81+
default:
82+
rm = RISCV_RM_INVALID;
83+
break;
84+
}
85+
RISCV_get_detail(MI)->rounding_mode = rm;
5986
return;
60-
87+
}
88+
6189
// unmasked instructions, the mask register is not real
6290
if (opgroup == RISCV_OP_GROUP_VMaskReg) {
6391
MCOperand *mask = MCInst_getOperand(MI, OpNum);

bindings/python/capstone/__init__.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,9 +1325,11 @@ def __gen_detail(self):
13251325
elif arch == CS_ARCH_BPF:
13261326
(self.operands) = bpf.get_arch_info(self._raw.detail.contents.arch.bpf)
13271327
elif arch == CS_ARCH_RISCV:
1328-
(self.need_effective_addr, self.operands) = riscv.get_arch_info(
1329-
self._raw.detail.contents.arch.riscv
1330-
)
1328+
(
1329+
self.need_effective_addr,
1330+
self.operands,
1331+
self.rounding_mode,
1332+
) = riscv.get_arch_info(self._raw.detail.contents.arch.riscv)
13311333
elif arch == CS_ARCH_SH:
13321334
(self.sh_insn, self.sh_size, self.operands) = sh.get_arch_info(
13331335
self._raw.detail.contents.arch.sh

bindings/python/capstone/riscv.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,13 @@ class CsRISCV(ctypes.Structure):
5757
("need_effective_addr", ctypes.c_bool),
5858
("op_count", ctypes.c_uint8),
5959
("operands", RISCVOp * 8),
60+
("rounding_mode", ctypes.c_uint),
6061
)
6162

6263

6364
def get_arch_info(a):
64-
return (a.need_effective_addr, copy_ctypes_list(a.operands[: a.op_count]))
65+
return (
66+
a.need_effective_addr,
67+
copy_ctypes_list(a.operands[: a.op_count]),
68+
a.rounding_mode,
69+
)

bindings/python/capstone/riscv_const.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@
2222
RISCV_OP_FP = CS_OP_FP
2323
RISCV_OP_CSR = CS_OP_SPECIAL
2424

25+
# Floating-point rounding mode for RISC-V FP instructions
26+
RISCV_RM_INVALID = 0
27+
RISCV_RM_RNE = 1
28+
RISCV_RM_RTZ = 2
29+
RISCV_RM_RDN = 3
30+
RISCV_RM_RUP = 4
31+
RISCV_RM_RMM = 5
32+
RISCV_RM_DYN = 6
33+
2534
# RISCV registers
2635

2736
RISCV_REG_INVALID = 0

bindings/python/cstest_py/src/cstest_py/details.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,6 +1329,11 @@ def test_expected_hppa(actual: CsInsn, expected: dict) -> bool:
13291329

13301330

13311331
def test_expected_riscv(actual: CsInsn, expected: dict) -> bool:
1332+
if "rounding_mode" in expected and not compare_enum(
1333+
actual.rounding_mode, expected.get("rounding_mode"), "rounding_mode"
1334+
):
1335+
return False
1336+
13321337
if "operands" not in expected:
13331338
return True
13341339
elif not compare_uint32(

cstool/cstool_riscv.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,5 +68,14 @@ void print_insn_detail_riscv(csh handle, cs_insn *ins)
6868
}
6969
}
7070

71+
if (riscv->rounding_mode != RISCV_RM_INVALID) {
72+
static const char *const rm_str[] = {
73+
[RISCV_RM_RNE] = "rne", [RISCV_RM_RTZ] = "rtz",
74+
[RISCV_RM_RDN] = "rdn", [RISCV_RM_RUP] = "rup",
75+
[RISCV_RM_RMM] = "rmm", [RISCV_RM_DYN] = "dyn",
76+
};
77+
printf("\trounding_mode: %s\n", rm_str[riscv->rounding_mode]);
78+
}
79+
7180
printf("\n");
7281
}

docs/cs_v6_release_guide.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ Nonetheless, we hope this additional information is useful to you.
253253
- Added `reg_access` capstone callback to return all read and written registers for the instructions, including registers used as part of memory operands.
254254
* Note that `reg_access` does NOT treat CSRs as registers, detailed reasons for why can be found in [the PR implementing the feature](https://github.com/capstone-engine/capstone/pull/2895)
255255
* Note that `reg_access` does NOT treat reading the PC's value as reading a register, detailed reasons for why can be found in [the PR implementing the feature](https://github.com/capstone-engine/capstone/pull/2895)
256+
- Added `rounding_mode`field to `cs_riscv` struct inside details struct (`insn->detail->riscv->rounding_mode`) for float and double instructions.
256257

257258
> [!NOTE]
258259
> All `CS_MODE_RISCV_*` extensions above are disabled by default unless enabled by their option name or the corresponding command line flag in cstool. Any other extension is always enabled and can't be disabled.

include/capstone/riscv.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,17 @@ extern "C" {
2424
#pragma warning(disable : 4201)
2525
#endif
2626

27+
//> Floating-point rounding mode for RISC-V FP instructions
28+
typedef enum riscv_rounding_mode {
29+
RISCV_RM_INVALID = 0, ///< not applicable (no rounding mode)
30+
RISCV_RM_RNE, ///< round to nearest, ties to even
31+
RISCV_RM_RTZ, ///< round towards zero
32+
RISCV_RM_RDN, ///< round down (towards -infinity)
33+
RISCV_RM_RUP, ///< round up (towards +infinity)
34+
RISCV_RM_RMM, ///< round to nearest, ties to max magnitude
35+
RISCV_RM_DYN, ///< dynamic rounding mode (use frm CSR)
36+
} riscv_rounding_mode;
37+
2738
//> Operand type for instruction's operands
2839
typedef enum riscv_op_type {
2940
RISCV_OP_INVALID = CS_OP_INVALID, ///< = CS_OP_INVALID (Uninitialized).
@@ -65,6 +76,8 @@ typedef struct cs_riscv {
6576
// or 0 when instruction has no operand.
6677
uint8_t op_count;
6778
cs_riscv_op operands[NUM_RISCV_OPS]; // operands for this instruction.
79+
// FP rounding mode, or RISCV_RM_INVALID.
80+
riscv_rounding_mode rounding_mode;
6881
} cs_riscv;
6982

7083
//> RISCV registers

suite/cstest/include/test_detail_riscv.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,17 @@ static const cyaml_schema_value_t test_detail_riscv_op_schema = {
4848
typedef struct {
4949
TestDetailRISCVOp **operands;
5050
uint32_t operands_count;
51+
char *rounding_mode;
5152
} TestDetailRISCV;
5253

5354
static const cyaml_schema_field_t test_detail_riscv_mapping_schema[] = {
5455
CYAML_FIELD_SEQUENCE(
5556
"operands", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL,
5657
TestDetailRISCV, operands, &test_detail_riscv_op_schema, 0,
5758
CYAML_UNLIMITED), // 0-MAX options
59+
CYAML_FIELD_STRING_PTR(
60+
"rounding_mode", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL,
61+
TestDetailRISCV, rounding_mode, 0, CYAML_UNLIMITED),
5862
CYAML_FIELD_END
5963
};
6064

suite/cstest/include/test_mapping.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,6 +1493,13 @@ static const cs_enum_id_map cs_enum_map[] = {
14931493
{ .str = "RISCV_OP_IMM", .val = RISCV_OP_IMM },
14941494
{ .str = "RISCV_OP_MEM", .val = RISCV_OP_MEM },
14951495
{ .str = "RISCV_OP_REG", .val = RISCV_OP_REG },
1496+
{ .str = "RISCV_RM_DYN", .val = RISCV_RM_DYN },
1497+
{ .str = "RISCV_RM_INVALID", .val = RISCV_RM_INVALID },
1498+
{ .str = "RISCV_RM_RDN", .val = RISCV_RM_RDN },
1499+
{ .str = "RISCV_RM_RMM", .val = RISCV_RM_RMM },
1500+
{ .str = "RISCV_RM_RNE", .val = RISCV_RM_RNE },
1501+
{ .str = "RISCV_RM_RTZ", .val = RISCV_RM_RTZ },
1502+
{ .str = "RISCV_RM_RUP", .val = RISCV_RM_RUP },
14961503
{ .str = "SH_GRP_BRANCH_RELATIVE", .val = SH_GRP_BRANCH_RELATIVE },
14971504
{ .str = "SH_GRP_CALL", .val = SH_GRP_CALL },
14981505
{ .str = "SH_GRP_INT", .val = SH_GRP_INT },

0 commit comments

Comments
 (0)