Skip to content

Commit

Permalink
i#3544 RV64: Added a new immediate format for AUIPC (#6208)
Browse files Browse the repository at this point in the history
AUIPC is a PC-relative instruction, which needs to be mangled before
going into fcache, so the src opnd needs to be a PC or instr. This patch
added a new immediate type called `u_immpc` for AUIPC to achieve this.

Issue: #3544
  • Loading branch information
ksco authored Jul 27, 2023
1 parent 0554225 commit a0cbec6
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 56 deletions.
46 changes: 46 additions & 0 deletions core/ir/riscv64/codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,24 @@ decode_u_imm_opnd(dcontext_t *dc, uint32_t inst, int op_sz, byte *pc, byte *orig
return true;
}

/* Decode the immediate field of the U-type format (PC-relative):
* |31 12|11 7|6 0|
* | imm[31:12] | rd | opcode |
* ^----------^
* Into:
* |31 12|11 0|
* | imm[31:12] | 0 |
*/
static bool
decode_u_immpc_opnd(dcontext_t *dc, uint32_t inst, int op_sz, byte *pc, byte *orig_pc,
int idx, instr_t *out)
{
uint uimm = GET_FIELD(inst, 31, 12);
opnd_t opnd = opnd_create_pc(orig_pc + (uimm << 12));
instr_set_src(out, idx, opnd);
return true;
}

/* Decode the immediate field of the J-type format as a pc-relative offset:
* | 31 |30 21| 20 |19 12|11 7|6 0|
* | imm[20] | imm[10:1] | imm[11] | imm[19:12] | rd | opcode |
Expand Down Expand Up @@ -1088,6 +1106,7 @@ opnd_dec_func_t opnd_decoders[] = {
[RISCV64_FLD_S_IMM] = decode_s_imm_opnd,
[RISCV64_FLD_B_IMM] = decode_b_imm_opnd,
[RISCV64_FLD_U_IMM] = decode_u_imm_opnd,
[RISCV64_FLD_U_IMMPC] = decode_u_immpc_opnd,
[RISCV64_FLD_J_IMM] = decode_j_imm_opnd,
[RISCV64_FLD_CRD] = decode_crd_opnd,
[RISCV64_FLD_CRDFP] = decode_crdfp_opnd,
Expand Down Expand Up @@ -1777,6 +1796,32 @@ encode_u_imm_opnd(instr_t *instr, byte *pc, int idx, uint32_t *out)
return true;
}

/* Encode the immediate field of the U-type format (PC-relative):
* |31 12|11 7|6 0|
* | imm[31:12] | rd | opcode |
* ^----------^
* From:
* |31 12|11 0|
* | imm[31:12] | 0 |
*/
static bool
encode_u_immpc_opnd(instr_t *instr, byte *pc, int idx, uint32_t *out)
{
opnd_t opnd = instr_get_src(instr, idx);
uint32_t imm;
if (opnd.kind == PC_kind)
imm = opnd_get_pc(opnd) - pc;
else if (opnd.kind == INSTR_kind)
imm = (byte *)opnd_get_instr(opnd)->offset - (byte *)instr->offset;
else
return false;
/* FIXME i#3544: Add an assertion here to ensure that the lower 12 bits of imm are all
* 0. Assert only if decode_info_t.check_reachable is true. We should mark it as false
* to skip the check in get_encoding_info(), as we did for AARCHXX. */
*out |= SET_FIELD(imm >> 12, 31, 12);
return true;
}

/* Encode the immediate field of the J-type format as a pc-relative offset:
* | 31 |30 21| 20 |19 12|11 7|6 0|
* | imm[20] | imm[10:1] | imm[11] | imm[19:12] | rd | opcode |
Expand Down Expand Up @@ -2348,6 +2393,7 @@ opnd_enc_func_t opnd_encoders[] = {
[RISCV64_FLD_S_IMM] = encode_s_imm_opnd,
[RISCV64_FLD_B_IMM] = encode_b_imm_opnd,
[RISCV64_FLD_U_IMM] = encode_u_imm_opnd,
[RISCV64_FLD_U_IMMPC] = encode_u_immpc_opnd,
[RISCV64_FLD_J_IMM] = encode_j_imm_opnd,
[RISCV64_FLD_CRD] = encode_crd_opnd,
[RISCV64_FLD_CRDFP] = encode_crdfp_opnd,
Expand Down
1 change: 1 addition & 0 deletions core/ir/riscv64/codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ typedef enum {
RISCV64_FLD_S_IMM,
RISCV64_FLD_B_IMM,
RISCV64_FLD_U_IMM,
RISCV64_FLD_U_IMMPC,
RISCV64_FLD_J_IMM,
/* Compressed instruction fields */
RISCV64_FLD_CRD,
Expand Down
69 changes: 38 additions & 31 deletions core/ir/riscv64/codec.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,204 +269,211 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool,
'',
'The 20-bit immediate field in the U-type format.'
)
J_IMM = (22,
U_IMMPC = (22,
'imm',
False,
'OPSZ_20b',
'',
'The 20-bit immediate field in the U-type format (PC-relative).'
)
J_IMM = (23,
'pc_rel',
False,
'OPSZ_2',
'',
'The immediate field in the J-type format.'
)
IMM = (23, # Used only for parsing ISA files. Concatenated into V_RS1_DISP.
IMM = (24, # Used only for parsing ISA files. Concatenated into V_RS1_DISP.
'imm',
False,
'OPSZ_12b',
'',
'The immediate field in PREFETCH instructions.'
)
CRD = (24,
CRD = (25,
'rd',
True,
'OPSZ_PTR',
'',
'The output register in `CR`, `CI` RVC formats (inst[11:7])'
)
CRDFP = (25,
CRDFP = (26,
'rd',
True,
'OPSZ_PTR',
'',
'The output floating-point register in `CR`, `CI` RVC formats (inst[11:7])'
)
CRS1 = (26,
CRS1 = (27,
'rs1',
False,
'OPSZ_PTR',
'',
'The first input register in `CR`, `CI` RVC formats (inst[11:7]).'
)
CRS2 = (27,
CRS2 = (28,
'rs2',
False,
'OPSZ_PTR',
'',
'The second input register in `CR`, `CSS` RVC formats (inst[6:2]).'
)
CRS2FP = (28,
CRS2FP = (29,
'rs2',
False,
'OPSZ_PTR',
'',
'The second input floating-point register in `CR`, `CSS` RVC formats (inst[6:2]).'
)
# Fields in compressed instructions.
CRD_ = (29,
CRD_ = (30,
'rd',
True,
'OPSZ_PTR',
'',
'The output register in `CIW`, `CL` RVC formats (inst[4:2])'
)
CRD_FP = (30,
CRD_FP = (31,
'rd',
True,
'OPSZ_PTR',
'',
'The output floating-point register in `CIW`, `CL` RVC formats (inst[4:2])'
)
CRS1_ = (31,
CRS1_ = (32,
'rs1',
False,
'OPSZ_PTR',
'',
'The first input register in `CL`, `CS`, `CA`, `CB` RVC formats (inst[9:7]).'
)
CRS2_ = (32,
CRS2_ = (33,
'rs2',
False,
'OPSZ_PTR',
'',
'The second input register in `CS`, `CA` RVC formats (inst[4:2]).'
)
CRS2_FP = (33,
CRS2_FP = (34,
'rs2',
False,
'OPSZ_PTR',
'',
'The second input floating-point register in `CS`, `CA` RVC formats (inst[4:2]).'
)
CRD__ = (34,
CRD__ = (35,
'rd',
True,
'OPSZ_PTR',
'',
'The output register in `CA` RVC format (inst[9:7])'
)
CSHAMT = (35,
CSHAMT = (36,
'shamt',
False,
'OPSZ_6b',
'',
'The `shamt` field in the RVC format.'
)
CSR_IMM = (36,
CSR_IMM = (37,
'imm',
False,
'OPSZ_5b',
'',
'The immediate field in a CSR instruction.'
)
CADDI16SP_IMM = (37,
CADDI16SP_IMM = (38,
'imm',
False,
'OPSZ_10b',
'',
'The immediate field in a C.ADDI16SP instruction.'
)
CLWSP_IMM = (38,
CLWSP_IMM = (39,
'sp_offset',
False,
'OPSZ_1',
'',
'The SP-relative memory location (sp+imm: imm & 0x3 == 0).'
)
CLDSP_IMM = (39,
CLDSP_IMM = (40,
'sp_offset',
False,
'OPSZ_9b',
'',
'The SP-relative memory location (sp+imm: imm & 0x7 == 0).'
)
CLUI_IMM = (40,
CLUI_IMM = (41,
'imm',
False,
'OPSZ_6b',
'',
'The immediate field in a C.LUI instruction.'
)
CSWSP_IMM = (41,
CSWSP_IMM = (42,
'sp_offset',
True,
'OPSZ_1',
'',
'The SP-relative memory location (sp+imm: imm & 0x3 == 0).'
)
CSDSP_IMM = (42,
CSDSP_IMM = (43,
'sp_offset',
True,
'OPSZ_9b',
'',
'The SP-relative memory location (sp+imm: imm & 0x7 == 0).'
)
CIW_IMM = (43,
CIW_IMM = (44,
'imm',
False,
'OPSZ_10b',
'',
'The immediate field in a CIW format instruction.'
)
CLW_IMM = (44,
CLW_IMM = (45,
'mem',
False,
'OPSZ_7b',
'im(rs1)', 'The register-relative memory location (reg+imm: imm & 0x3 == 0).')
CLD_IMM = (45,
CLD_IMM = (46,
'mem',
False,
'OPSZ_1',
'im(rs1)', 'The register-relative memory location (reg+imm: imm & 0x7 == 0).')
CSW_IMM = (46,
CSW_IMM = (47,
'mem',
True,
'OPSZ_7b',
'im(rs1)', 'The register-relative memory location (reg+imm: imm & 0x3 == 0).')
CSD_IMM = (47,
CSD_IMM = (48,
'mem',
True,
'OPSZ_1',
'im(rs1)', 'The register-relative memory location (reg+imm: imm & 0x7 == 0).')
CIMM5 = (48,
CIMM5 = (49,
'imm',
False,
'OPSZ_6b',
'',
'The immediate field in a C.ADDI, C.ADDIW, C.LI, and C.ANDI instruction.'
)
CB_IMM = (49,
CB_IMM = (50,
'pc_rel',
False,
'OPSZ_2',
'',
'The immediate field in a a CB format instruction (C.BEQZ and C.BNEZ).'
)
CJ_IMM = (50,
CJ_IMM = (51,
'pc_rel',
False,
'OPSZ_2',
'',
'The immediate field in a CJ format instruction.'
)
# Virtual fields en/decoding special cases.
V_L_RS1_DISP = (51,
V_L_RS1_DISP = (52,
'mem',
False,
{
Expand All @@ -479,7 +486,7 @@ def __new__(cls, value: int, arg_name: str, is_dest: bool,
'im(rs1)',
'The register-relative memory source location (reg+imm).'
)
V_S_RS1_DISP = (52,
V_S_RS1_DISP = (53,
'mem',
True,
{
Expand Down
6 changes: 1 addition & 5 deletions core/ir/riscv64/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,7 @@ decode(void *drcontext, byte *pc, instr_t *instr)
byte *
decode_from_copy(void *drcontext, byte *copy_pc, byte *orig_pc, instr_t *instr)
{
/* FIXME i#3544: Not implemented */
ASSERT_NOT_IMPLEMENTED(false);
return NULL;
return decode_common(drcontext, copy_pc, orig_pc, instr);
}

byte *
Expand Down Expand Up @@ -255,8 +253,6 @@ decode_debug_checks_arch(void)
int
main()
{
/* FIXME i#3544: Add decoder tests. */

bool res = true;
standalone_init();
standalone_exit();
Expand Down
2 changes: 1 addition & 1 deletion core/ir/riscv64/isl/rv32i.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Version 2.1

lui | u | u_imm rd | .........................0110111
auipc | u | u_imm rd | .........................0010111
auipc | u | u_immpc rd | .........................0010111
jal | j | j_imm rd | .........................1101111
jalr | i | i_imm rs1 rd | .................000.....1100111
beq | b | b_imm rs2 rs1 | .................000.....1100011
Expand Down
Loading

0 comments on commit a0cbec6

Please sign in to comment.