diff --git a/core/ir/riscv64/codec.c b/core/ir/riscv64/codec.c index 6263e0b7719..ee23b5de187 100644 --- a/core/ir/riscv64/codec.c +++ b/core/ir/riscv64/codec.c @@ -1078,6 +1078,116 @@ decode_v_s_rs1_disp_opnd(dcontext_t *dc, uint32_t inst, int op_sz, byte *pc, return true; } +/* Decode the implicit rs1 field which is always sp. + */ +static bool +decode_irs1_sp_opnd(dcontext_t *dc, uint32_t inst, int op_sz, byte *pc, byte *orig_pc, + int idx, instr_t *out) +{ + ASSERT(idx == 0); + opnd_t opnd = opnd_create_reg(DR_REG_SP); + instr_set_src(out, idx, opnd); + return true; +} + +/* Decode the implicit rs1 field which is always zero. + */ +static bool +decode_irs1_zero_opnd(dcontext_t *dc, uint32_t inst, int op_sz, byte *pc, byte *orig_pc, + int idx, instr_t *out) +{ + ASSERT(idx == 0); + opnd_t opnd = opnd_create_reg(DR_REG_ZERO); + instr_set_src(out, idx, opnd); + return true; +} + +/* Decode the implicit rs2 field which is always zero. + */ +static bool +decode_irs2_zero_opnd(dcontext_t *dc, uint32_t inst, int op_sz, byte *pc, byte *orig_pc, + int idx, instr_t *out) +{ + ASSERT(idx == 1); + opnd_t opnd = opnd_create_reg(DR_REG_ZERO); + instr_set_src(out, idx, opnd); + return true; +} + +/* Decode the implicit rd field which is always zero. + */ +static bool +decode_ird_zero_opnd(dcontext_t *dc, uint32_t inst, int op_sz, byte *pc, byte *orig_pc, + int idx, instr_t *out) +{ + ASSERT(idx == 0); + opnd_t opnd = opnd_create_reg(DR_REG_ZERO); + instr_set_dst(out, idx, opnd); + return true; +} + +/* Decode the implicit rd field which is always ra. + */ +static bool +decode_ird_ra_opnd(dcontext_t *dc, uint32_t inst, int op_sz, byte *pc, byte *orig_pc, + int idx, instr_t *out) +{ + ASSERT(idx == 0); + opnd_t opnd = opnd_create_reg(DR_REG_RA); + instr_set_dst(out, idx, opnd); + return true; +} + +/* Decode the implicit rd field which is always sp. + */ +static bool +decode_ird_sp_opnd(dcontext_t *dc, uint32_t inst, int op_sz, byte *pc, byte *orig_pc, + int idx, instr_t *out) +{ + ASSERT(idx == 0); + opnd_t opnd = opnd_create_reg(DR_REG_SP); + instr_set_dst(out, idx, opnd); + return true; +} + +/* Decode the implicit immediate field which is always 0. + */ +static bool +decode_iimm_0_opnd(dcontext_t *dc, uint32_t inst, int op_sz, byte *pc, byte *orig_pc, + int idx, instr_t *out) +{ + ASSERT(idx == 1); + opnd_t opnd = opnd_create_immed_int(0, op_sz); + instr_set_src(out, idx, opnd); + return true; +} + +/* Decode the implicit rd field which is same as crd. + */ +static bool +decode_icrs1_opnd(dcontext_t *dc, uint32_t inst, int op_sz, byte *pc, byte *orig_pc, + int idx, instr_t *out) +{ + ASSERT(idx == 0); + reg_t reg = DR_REG_X0 + GET_FIELD(inst, 11, 7); + opnd_t opnd = opnd_create_reg(reg); + instr_set_src(out, idx, opnd); + return true; +} + +/* Decode the implicit rd field which is same as crd__. + */ +static bool +decode_icrs1___opnd(dcontext_t *dc, uint32_t inst, int op_sz, byte *pc, byte *orig_pc, + int idx, instr_t *out) +{ + ASSERT(idx == 0); + reg_t reg = DR_REG_X8 + GET_FIELD(inst, 9, 7); + opnd_t opnd = opnd_create_reg(reg); + instr_set_src(out, idx, opnd); + return true; +} + /* Array of operand decode functions indexed by riscv64_fld_t. * * NOTE: After benchmarking, perhaps this could be placed in the same section as @@ -1137,6 +1247,15 @@ opnd_dec_func_t opnd_decoders[] = { [RISCV64_FLD_CJ_IMM] = decode_cj_imm_opnd, [RISCV64_FLD_V_L_RS1_DISP] = decode_v_l_rs1_disp_opnd, [RISCV64_FLD_V_S_RS1_DISP] = decode_v_s_rs1_disp_opnd, + [RISCV64_FLD_IRS1_SP] = decode_irs1_sp_opnd, + [RISCV64_FLD_IRS1_ZERO] = decode_irs1_zero_opnd, + [RISCV64_FLD_IRS2_ZERO] = decode_irs2_zero_opnd, + [RISCV64_FLD_IRD_ZERO] = decode_ird_zero_opnd, + [RISCV64_FLD_IRD_RA] = decode_ird_ra_opnd, + [RISCV64_FLD_IRD_SP] = decode_ird_sp_opnd, + [RISCV64_FLD_IIMM_0] = decode_iimm_0_opnd, + [RISCV64_FLD_ICRS1] = decode_icrs1_opnd, + [RISCV64_FLD_ICRS1__] = decode_icrs1___opnd, }; /* Decode RVC quadrant 0. @@ -1467,6 +1586,14 @@ encode_none_opnd(instr_t *instr, byte *pc, int idx, uint32_t *out, decode_info_t return false; } +/* Encodes an implicit opnd, no need to do anything. + */ +static bool +encode_implicit_opnd(instr_t *instr, byte *pc, int idx, uint32_t *out, decode_info_t *di) +{ + return true; +} + /* Encode the destination fixed-point register field: * |31 12|11 7|6 0| * | ... | rd | opcode | @@ -2428,6 +2555,15 @@ opnd_enc_func_t opnd_encoders[] = { [RISCV64_FLD_CJ_IMM] = encode_cj_imm_opnd, [RISCV64_FLD_V_L_RS1_DISP] = encode_v_l_rs1_disp_opnd, [RISCV64_FLD_V_S_RS1_DISP] = encode_v_s_rs1_disp_opnd, + [RISCV64_FLD_IRS1_SP] = encode_implicit_opnd, + [RISCV64_FLD_IRS1_ZERO] = encode_implicit_opnd, + [RISCV64_FLD_IRS2_ZERO] = encode_implicit_opnd, + [RISCV64_FLD_IRD_ZERO] = encode_implicit_opnd, + [RISCV64_FLD_IRD_RA] = encode_implicit_opnd, + [RISCV64_FLD_IRD_SP] = encode_implicit_opnd, + [RISCV64_FLD_IIMM_0] = encode_implicit_opnd, + [RISCV64_FLD_ICRS1] = encode_implicit_opnd, + [RISCV64_FLD_ICRS1__] = encode_implicit_opnd, }; uint diff --git a/core/ir/riscv64/codec.h b/core/ir/riscv64/codec.h index 1e9befc35de..1eff41a14a6 100644 --- a/core/ir/riscv64/codec.h +++ b/core/ir/riscv64/codec.h @@ -243,6 +243,16 @@ typedef enum { /* Virtual fields - en/decode special cases, i.e. base+disp combination */ RISCV64_FLD_V_L_RS1_DISP, RISCV64_FLD_V_S_RS1_DISP, + /* Implicit fields - encode is nop. */ + RISCV64_FLD_IRS1_SP, + RISCV64_FLD_IRS1_ZERO, + RISCV64_FLD_IRS2_ZERO, + RISCV64_FLD_IRD_ZERO, + RISCV64_FLD_IRD_RA, + RISCV64_FLD_IRD_SP, + RISCV64_FLD_IIMM_0, + RISCV64_FLD_ICRS1, + RISCV64_FLD_ICRS1__, RISCV64_FLD_CNT, /* Keep this last */ } riscv64_fld_t; diff --git a/core/ir/riscv64/codec.py b/core/ir/riscv64/codec.py index 47ebc2af222..dbad205dc5d 100755 --- a/core/ir/riscv64/codec.py +++ b/core/ir/riscv64/codec.py @@ -113,8 +113,9 @@ class Field(str, Enum): # dictionary. opsz_def: dict[str, str] | str is_dest: bool + is_implicit: bool - def __new__(cls, value: int, arg_name: str, is_dest: bool, + def __new__(cls, value: int, arg_name: str, is_dest: bool, is_implicit: bool, opsz_def: dict[str, str] | str, asm_name: str, arg_cmt: str): # Take str as a base object because we need a concrete class. It won't @@ -126,12 +127,14 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, obj._asm_name = asm_name if asm_name != '' else obj.arg_name obj.arg_cmt = arg_cmt obj.is_dest = is_dest + obj.is_implicit = is_implicit return obj # Fields in uncompressed instructions. RD = (1, 'rd', True, + False, 'OPSZ_PTR', '', 'The output register (inst[11:7]).' @@ -139,6 +142,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, RDFP = (2, 'rd', True, + False, 'OPSZ_PTR', '', 'The output floating-point register (inst[11:7]).' @@ -146,6 +150,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, RS1 = (3, 'rs1', False, + False, 'OPSZ_PTR', '', 'The first input register (inst[19:15]).' @@ -153,6 +158,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, RS1FP = (4, 'rs1', False, + False, 'OPSZ_PTR', '', 'The first input floating-point register (inst[19:15]).' @@ -160,6 +166,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, BASE = (5, 'base', False, + False, 'OPSZ_0', '', 'The `base` field in RISC-V Base Cache Management Operation ISA Extensions (inst[19:15]).' @@ -167,6 +174,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, RS2 = (6, 'rs2', False, + False, 'OPSZ_PTR', '', 'The second input register (inst[24:20]).' @@ -174,6 +182,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, RS2FP = (7, 'rs2', False, + False, 'OPSZ_PTR', '', 'The second input floating-point register (inst[24:20]).' @@ -181,6 +190,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, RS3FP = (8, 'rs3', False, + False, 'OPSZ_PTR', '', 'The third input register (inst[31:27]).' @@ -188,6 +198,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, FM = (9, 'fm', False, + False, 'OPSZ_4b', '', 'The fence semantics (inst[31:28]).' @@ -195,6 +206,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, PRED = (10, 'pred', False, + False, 'OPSZ_4b', '', 'The bitmap with predecessor constraints for FENCE (inst[27:24]).' @@ -202,6 +214,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, SUCC = (11, 'succ', False, + False, 'OPSZ_4b', '', 'The bitmap with successor constraints for FENCE (inst[23:20]).' @@ -209,6 +222,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, AQRL = (12, 'aqrl', False, + False, 'OPSZ_2b', '', 'The acquire-release constraint field (inst[26:25]).' @@ -216,6 +230,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CSR = (13, 'csr', False, + False, 'OPSZ_PTR', '', 'The configuration/status register id (inst[31:20]).' @@ -223,6 +238,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, RM = (14, 'rm', False, + False, 'OPSZ_3b', '', 'The rounding-mode (inst[14:12]).' @@ -230,6 +246,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, SHAMT = (15, 'shamt', False, + False, 'OPSZ_5b', '', 'The `shamt` field (bit range is determined by XLEN).' @@ -237,6 +254,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, SHAMT5 = (16, 'shamt', False, + False, 'OPSZ_6b', '', 'The `shamt` field that uses only 5 bits.' @@ -244,6 +262,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, SHAMT6 = (17, 'shamt', False, + False, 'OPSZ_7b', '', 'The `shamt` field that uses only 6 bits.' @@ -251,6 +270,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, I_IMM = (18, 'imm', False, + False, 'OPSZ_12b', '', 'The immediate field in the I-type format.' @@ -258,6 +278,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, S_IMM = (19, 'imm', False, + False, 'OPSZ_12b', '', 'The immediate field in the S-type format.' @@ -265,6 +286,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, B_IMM = (20, 'pc_rel', False, + False, 'OPSZ_2', '', 'The immediate field in the B-type format.' @@ -272,6 +294,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, U_IMM = (21, 'imm', False, + False, 'OPSZ_20b', '', 'The 20-bit immediate field in the U-type format.' @@ -279,6 +302,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, U_IMMPC = (22, 'imm', False, + False, 'OPSZ_20b', '', 'The 20-bit immediate field in the U-type format (PC-relative).' @@ -286,6 +310,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, J_IMM = (23, 'pc_rel', False, + False, 'OPSZ_2', '', 'The immediate field in the J-type format.' @@ -293,6 +318,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, IMM = (24, # Used only for parsing ISA files. Concatenated into V_RS1_DISP. 'imm', False, + False, 'OPSZ_12b', '', 'The immediate field in PREFETCH instructions.' @@ -300,6 +326,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CRD = (25, 'rd', True, + False, 'OPSZ_PTR', '', 'The output register in `CR`, `CI` RVC formats (inst[11:7])' @@ -307,6 +334,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CRDFP = (26, 'rd', True, + False, 'OPSZ_PTR', '', 'The output floating-point register in `CR`, `CI` RVC formats (inst[11:7])' @@ -314,6 +342,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CRS1 = (27, 'rs1', False, + False, 'OPSZ_PTR', '', 'The first input register in `CR`, `CI` RVC formats (inst[11:7]).' @@ -321,6 +350,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CRS2 = (28, 'rs2', False, + False, 'OPSZ_PTR', '', 'The second input register in `CR`, `CSS` RVC formats (inst[6:2]).' @@ -328,6 +358,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CRS2FP = (29, 'rs2', False, + False, 'OPSZ_PTR', '', 'The second input floating-point register in `CR`, `CSS` RVC formats (inst[6:2]).' @@ -336,6 +367,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CRD_ = (30, 'rd', True, + False, 'OPSZ_PTR', '', 'The output register in `CIW`, `CL` RVC formats (inst[4:2])' @@ -343,6 +375,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CRD_FP = (31, 'rd', True, + False, 'OPSZ_PTR', '', 'The output floating-point register in `CIW`, `CL` RVC formats (inst[4:2])' @@ -350,6 +383,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CRS1_ = (32, 'rs1', False, + False, 'OPSZ_PTR', '', 'The first input register in `CL`, `CS`, `CA`, `CB` RVC formats (inst[9:7]).' @@ -357,6 +391,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CRS2_ = (33, 'rs2', False, + False, 'OPSZ_PTR', '', 'The second input register in `CS`, `CA` RVC formats (inst[4:2]).' @@ -364,6 +399,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CRS2_FP = (34, 'rs2', False, + False, 'OPSZ_PTR', '', 'The second input floating-point register in `CS`, `CA` RVC formats (inst[4:2]).' @@ -371,6 +407,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CRD__ = (35, 'rd', True, + False, 'OPSZ_PTR', '', 'The output register in `CA` RVC format (inst[9:7])' @@ -378,6 +415,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CSHAMT = (36, 'shamt', False, + False, 'OPSZ_6b', '', 'The `shamt` field in the RVC format.' @@ -385,6 +423,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CSR_IMM = (37, 'imm', False, + False, 'OPSZ_5b', '', 'The immediate field in a CSR instruction.' @@ -392,6 +431,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CADDI16SP_IMM = (38, 'imm', False, + False, 'OPSZ_10b', '', 'The immediate field in a C.ADDI16SP instruction.' @@ -399,6 +439,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CLWSP_IMM = (39, 'sp_offset', False, + False, 'OPSZ_1', '', 'The SP-relative memory location (sp+imm: imm & 0x3 == 0).' @@ -406,6 +447,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CLDSP_IMM = (40, 'sp_offset', False, + False, 'OPSZ_9b', '', 'The SP-relative memory location (sp+imm: imm & 0x7 == 0).' @@ -413,6 +455,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CLUI_IMM = (41, 'imm', False, + False, 'OPSZ_6b', '', 'The immediate field in a C.LUI instruction.' @@ -420,6 +463,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CSWSP_IMM = (42, 'sp_offset', True, + False, 'OPSZ_1', '', 'The SP-relative memory location (sp+imm: imm & 0x3 == 0).' @@ -427,6 +471,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CSDSP_IMM = (43, 'sp_offset', True, + False, 'OPSZ_9b', '', 'The SP-relative memory location (sp+imm: imm & 0x7 == 0).' @@ -434,6 +479,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CIW_IMM = (44, 'imm', False, + False, 'OPSZ_10b', '', 'The immediate field in a CIW format instruction.' @@ -441,26 +487,31 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CLW_IMM = (45, 'mem', False, + False, 'OPSZ_7b', 'im(rs1)', 'The register-relative memory location (reg+imm: imm & 0x3 == 0).') CLD_IMM = (46, 'mem', False, + False, 'OPSZ_1', 'im(rs1)', 'The register-relative memory location (reg+imm: imm & 0x7 == 0).') CSW_IMM = (47, 'mem', True, + False, 'OPSZ_7b', 'im(rs1)', 'The register-relative memory location (reg+imm: imm & 0x3 == 0).') CSD_IMM = (48, 'mem', True, + False, 'OPSZ_1', 'im(rs1)', 'The register-relative memory location (reg+imm: imm & 0x7 == 0).') CIMM5 = (49, 'imm', False, + False, 'OPSZ_6b', '', 'The immediate field in a C.ADDI, C.ADDIW, C.LI, and C.ANDI instruction.' @@ -468,6 +519,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CB_IMM = (50, 'pc_rel', False, + False, 'OPSZ_2', '', 'The immediate field in a a CB format instruction (C.BEQZ and C.BNEZ).' @@ -475,6 +527,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, CJ_IMM = (51, 'pc_rel', False, + False, 'OPSZ_2', '', 'The immediate field in a CJ format instruction.' @@ -483,6 +536,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, V_L_RS1_DISP = (52, 'mem', False, + False, { '': 'OPSZ_0', 'lb': 'OPSZ_1', 'lh': 'OPSZ_2', 'lw': 'OPSZ_4', 'ld': 'OPSZ_8', 'lbu': 'OPSZ_1', 'lhu': 'OPSZ_2', 'lwu': 'OPSZ_4', @@ -496,6 +550,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, V_S_RS1_DISP = (53, 'mem', True, + False, { '': 'OPSZ_0', 'lb': 'OPSZ_1', 'lh': 'OPSZ_2', 'lw': 'OPSZ_4', 'ld': 'OPSZ_8', 'lbu': 'OPSZ_1', 'lhu': 'OPSZ_2', 'lwu': 'OPSZ_4', @@ -506,6 +561,78 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool, 'im(rs1)', 'The register-relative memory target location (reg+imm).' ) + IRS1_SP = (54, + 'opnd_create_reg(DR_REG_SP)', + False, + True, + 'OPSZ_PTR', + 'rs1', + 'Implicit rs1, always be sp.' + ) + IRS1_ZERO = (55, + 'opnd_create_reg(DR_REG_ZERO)', + False, + True, + 'OPSZ_PTR', + 'rs1', + 'Implicit rs1, always be zero.' + ) + IRS2_ZERO = (56, + 'opnd_create_reg(DR_REG_ZERO)', + False, + True, + 'OPSZ_PTR', + 'rs2', + 'Implicit rs2, always be zero.' + ) + IRD_ZERO = (57, + 'opnd_create_reg(DR_REG_ZERO)', + True, + True, + 'OPSZ_PTR', + 'rd', + 'Implicit rd, always be zero.' + ) + IRD_RA = (58, + 'opnd_create_reg(DR_REG_RA)', + True, + True, + 'OPSZ_PTR', + 'rd', + 'Implicit rd, always be ra.' + ) + IRD_SP = (59, + 'opnd_create_reg(DR_REG_SP)', + True, + True, + 'OPSZ_PTR', + 'rd', + 'Implicit rd, always be sp.' + ) + IIMM_0 = (60, + 'opnd_create_immed_int(0, OPSZ_1)', + False, + True, + 'OPSZ_1', + 'imm', + 'Implicit imm, always be 0.' + ) + ICRS1 = (61, + 'Rd', + False, + True, + 'OPSZ_PTR', + 'rs1', + 'Implicit rs1, same as CRD.' + ) + ICRS1__ = (62, + 'Rd', + False, + True, + 'OPSZ_PTR', + 'rs1', + 'Implicit rs1, same as CRD__.', + ) def __str__(self) -> str: return self.name.lower().replace("fp", "(fp)") @@ -514,7 +641,7 @@ def asm_name(self) -> str: return self._asm_name if self._asm_name != '' else self.arg_name def formatted_name(self) -> str: - return self.arg_name.capitalize() + return self.arg_name if self.is_implicit else self.arg_name.capitalize() def from_str(fld: str): return Field[fld.upper().replace("(FP)", "FP")] @@ -837,9 +964,12 @@ def generate_instr_macros(self, template_file, out_file) -> bool: # #define INSTR_CREATE_(dc, ) \ # instr_create_dst_src(dc, OP_, ) for i in self.instructions: - flds = [f for f in i.flds] + flds = [f for f in i.flds if not f.is_implicit] + all_flds = [f for f in i.flds] flds.reverse() + all_flds.reverse() args = '' + body_args = '' arg_comments = '' if len(flds) > 0: args += ', ' @@ -848,8 +978,12 @@ def generate_instr_macros(self, template_file, out_file) -> bool: arg_comments += '\n' arg_comments += '\n'.join( [f' * \param {f.formatted_name():6} {f.arg_cmt}' for f in flds]) - nd = len([f for f in flds if f.is_dest]) - ns = len(flds) - nd + if len(all_flds) > 0: + body_args += ', ' + body_args += ', '.join([f.formatted_name() + for f in all_flds]) + nd = len([f for f in all_flds if f.is_dest]) + ns = len(all_flds) - nd lines.append( f'''/** * Creates a(n) {i.name} instruction. @@ -857,7 +991,7 @@ def generate_instr_macros(self, template_file, out_file) -> bool: * \param dc The void * dcontext used to allocate memory for the instr_t.{arg_comments} */ #define INSTR_CREATE_{i.formatted_name()}(dc{args}) \\ - instr_create_{nd}dst_{ns}src(dc, OP_{i.formatted_name()}{args})\n''') + instr_create_{nd}dst_{ns}src(dc, OP_{i.formatted_name()}{body_args})\n''') line = line.replace(tmpl_fld, '\n'.join(lines)) buf.write(line) write_if_changed(out_file, buf.getvalue()) diff --git a/core/ir/riscv64/isl/README.md b/core/ir/riscv64/isl/README.md index 3d9e9b18c67..b7b7d0114a0 100644 --- a/core/ir/riscv64/isl/README.md +++ b/core/ir/riscv64/isl/README.md @@ -111,6 +111,19 @@ For compressed instructions: - cb_imm - cj_imm +DynamoRIO requires the decoder to decode all implicit operands. These operands +start with i, which means implicit. + +- irs1_sp +- irs1_zero +- irs2_zero +- ird_zero +- ird_ra +- ird_sp +- iimm_0 +- icrs1 +- icrs1__ + This maps into `riscv64_fld_t` enum in `codec.h` and `Field` enum in `codec.py` generator. @@ -125,6 +138,7 @@ If you want to add a new field: `codec.h`). - `arg_name`: Name to use in instruction creation macros. - `is_dest`: True if it is a destination operand. + - `is_implicit`: True if it is an implicit operand. - `opsz_def`: Operand size (`OPSZ_*` value) or if this field decodes into an operand of a different size depending on instruction - dictionary indexed by instruction mnemonic with operand size values. diff --git a/core/ir/riscv64/isl/rv32c.txt b/core/ir/riscv64/isl/rv32c.txt index 0b04ddbe926..fc06c2e014e 100644 --- a/core/ir/riscv64/isl/rv32c.txt +++ b/core/ir/riscv64/isl/rv32c.txt @@ -5,4 +5,4 @@ c.flwsp | ci | clwsp_imm crd(fp) | 011...........10 c.fswsp | css | cswsp_imm crs2(fp) | 111...........10 c.flw | cl | clw_imm crs1_ crd_(fp) | 011...........00 c.fsw | cs | csw_imm crs1_ crs2_(fp) | 111...........00 -c.jal | cj | cj_imm | 001...........01 +c.jal | cj | cj_imm ird_ra | 001...........01 diff --git a/core/ir/riscv64/isl/rv64c.txt b/core/ir/riscv64/isl/rv64c.txt index b8ce502b563..8f6f2f01289 100644 --- a/core/ir/riscv64/isl/rv64c.txt +++ b/core/ir/riscv64/isl/rv64c.txt @@ -5,6 +5,6 @@ c.ldsp | ci | cldsp_imm crd | 011...........10 c.sdsp | css | csdsp_imm crs2 | 111...........10 c.ld | cl | cld_imm crs1_ crd_ | 011...........00 c.sd | cs | csd_imm crs1_ crs2_ | 111...........00 -c.addiw | ci | cimm5 crd | 001...........01 -c.addw | ca | crd__ crs2_ | 100111...01...01 -c.subw | ca | crd__ crs2_ | 100111...00...01 +c.addiw | ci | cimm5 icrs1 crd | 001...........01 +c.addw | ca | crs2_ icrs1__ crd__ | 100111...01...01 +c.subw | ca | crs2_ icrs1__ crd__ | 100111...00...01 diff --git a/core/ir/riscv64/isl/rvc.txt b/core/ir/riscv64/isl/rvc.txt index 4a3f4a7b428..ca11e4cbc18 100644 --- a/core/ir/riscv64/isl/rvc.txt +++ b/core/ir/riscv64/isl/rvc.txt @@ -1,36 +1,36 @@ # "C" Standard Extension for Compressed Instructions. # Version 2.0 -c.lwsp | ci | clwsp_imm crd | 010...........10 -c.fldsp | ci | cldsp_imm crd(fp) | 001...........10 -c.swsp | css | cswsp_imm crs2 | 110...........10 -c.fsdsp | css | csdsp_imm crs2(fp) | 101...........10 -c.lw | cl | clw_imm crs1_ crd_ | 010...........00 -c.fld | cl | cld_imm crs1_ crd_(fp) | 001...........00 -c.sw | cs | csw_imm crs1_ crs2_ | 110...........00 -c.fsd | cs | csd_imm crs1_ crs2_(fp) | 101...........00 -c.j | cj | cj_imm | 101...........01 -c.jr | cr | crs1 | 1000.....0000010 -c.jalr | cr | crs1 | 1001.....0000010 -c.beqz | cb | cb_imm crs1_ | 110...........01 -c.bnez | cb | cb_imm crs1_ | 111...........01 -c.li | ci | cimm5 crd | 010...........01 -c.lui | ci | clui_imm crd | 011...........01 -c.addi | ci | cimm5 crd | 000...........01 -c.addi16sp | ci | caddi16sp_imm | 011.00010.....01 -c.addi4spn | ciw | ciw_imm crd_ | 000...........00 -c.slli | ci | cshamt crd | 000...........10 -c.srli | cb | cshamt crd__ | 100.00........01 -c.srai | cb | cshamt crd__ | 100.01........01 -c.andi | cb | cimm5 crd__ | 100.10........01 -c.mv | cr | crd crs2 | 1000..........10 -c.add | cr | crd crs2 | 1001..........10 -c.and | ca | crd__ crs2_ | 100011...11...01 -c.or | ca | crd__ crs2_ | 100011...10...01 -c.xor | ca | crd__ crs2_ | 100011...01...01 -c.sub | ca | crd__ crs2_ | 100011...00...01 -c.nop | ci | | 0000000000000001 -c.ebreak | cr | | 1001000000000010 +c.lwsp | ci | clwsp_imm crd | 010...........10 +c.fldsp | ci | cldsp_imm crd(fp) | 001...........10 +c.swsp | css | cswsp_imm crs2 | 110...........10 +c.fsdsp | css | csdsp_imm crs2(fp) | 101...........10 +c.lw | cl | clw_imm crs1_ crd_ | 010...........00 +c.fld | cl | cld_imm crs1_ crd_(fp) | 001...........00 +c.sw | cs | csw_imm crs1_ crs2_ | 110...........00 +c.fsd | cs | csd_imm crs1_ crs2_(fp) | 101...........00 +c.j | cj | cj_imm ird_zero | 101...........01 +c.jr | cr | iimm_0 crs1 ird_zero | 1000.....0000010 +c.jalr | cr | iimm_0 crs1 ird_ra | 1001.....0000010 +c.beqz | cb | cb_imm crs1_ irs2_zero | 110...........01 +c.bnez | cb | cb_imm crs1_ irs2_zero | 111...........01 +c.li | ci | cimm5 irs1_zero crd | 010...........01 +c.lui | ci | clui_imm crd | 011...........01 +c.addi | ci | cimm5 icrs1 crd | 000...........01 +c.addi16sp | ci | caddi16sp_imm irs1_sp ird_sp | 011.00010.....01 +c.addi4spn | ciw | ciw_imm irs1_sp crd_ | 000...........00 +c.slli | ci | cshamt icrs1 crd | 000...........10 +c.srli | cb | cshamt icrs1__ crd__ | 100.00........01 +c.srai | cb | cshamt icrs1__ crd__ | 100.01........01 +c.andi | cb | cimm5 icrs1__ crd__ | 100.10........01 +c.mv | cr | crs2 irs1_zero crd | 1000..........10 +c.add | cr | crs2 icrs1 crd | 1001..........10 +c.and | ca | crs2_ icrs1__ crd__ | 100011...11...01 +c.or | ca | crs2_ icrs1__ crd__ | 100011...10...01 +c.xor | ca | crs2_ icrs1__ crd__ | 100011...01...01 +c.sub | ca | crs2_ icrs1__ crd__ | 100011...00...01 +c.nop | ci | | 0000000000000001 +c.ebreak | cr | | 1001000000000010 # 0x0 is an illegal instruction by ISA specification. However it is often used # as a canary after non-reachable code therefore it's included here. diff --git a/suite/tests/api/ir_riscv64.expect b/suite/tests/api/ir_riscv64.expect index 3106ff9b8bd..3bd9cf309f1 100644 --- a/suite/tests/api/ir_riscv64.expect +++ b/suite/tests/api/ir_riscv64.expect @@ -206,28 +206,28 @@ rem a1 a1 -> a0 remw a1 a1 -> a0 remu a1 a1 -> a0 remuw a1 a1 -> a0 -c.addiw 31 -> a0 -c.addw a1 -> a0 -c.subw a1 -> a0 -c.slli 63 -> a1 -c.srli 63 -> a1 -c.srai 63 -> a1 -c.andi -1 -> a1 -c.mv a1 -> a1 -c.add a1 -> a1 -c.and a5 -> fp -c.or a5 -> fp -c.xor a5 -> fp -c.sub a5 -> fp +c.addiw a0 31 -> a0 +c.addw a0 a1 -> a0 +c.subw a0 a1 -> a0 +c.slli a1 63 -> a1 +c.srli a1 63 -> a1 +c.srai a1 63 -> a1 +c.andi a1 -1 -> a1 +c.mv zero a1 -> a1 +c.add a1 a1 -> a1 +c.and fp a5 -> fp +c.or fp a5 -> fp +c.xor fp a5 -> fp +c.sub fp a5 -> fp test_integer_arith complete lui 0x2a -> a0 - a0'> + a0'> jalr a1 0x2a -> a0 -c.li 31 -> a1 +c.li zero 31 -> a1 c.lui 1 -> a1 -c.addi 31 -> a1 -c.addi16sp 16 -c.addi4spn 4 -> fp +c.addi a1 31 -> a1 +c.addi16sp sp 16 -> sp +c.addi4spn sp 4 -> fp test_jump_and_branch complete csrrw a1 0x42 -> a0 csrrs a1 0x42 -> a0