Skip to content

Commit

Permalink
i#3544 core, part 2: Add RISC-V basic definitions
Browse files Browse the repository at this point in the history
Add definitions and structures describing basic architecture specifics
such as registers, scratch registers, SIMD data, TLS, stub sizes,
syscall/signal ABI, ELF section types and calling conventions.

This will serve as a basis for later commits which will enable DynamoRIO
compilation for a RISC-V architecture.

NOTE:
  This code is not validated and may contain stubs as the main point was
  to achieve compilation and estimate the effort required for the port.

Issue: DynamoRIO#3544

Signed-off-by: Stanislaw Kardach <[email protected]>
  • Loading branch information
semihalf-kardach-stanislaw committed Jul 12, 2022
1 parent 6a49439 commit 620fe03
Show file tree
Hide file tree
Showing 18 changed files with 907 additions and 17 deletions.
25 changes: 24 additions & 1 deletion core/arch/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,28 @@ mixed_mode_enabled(void)
# define SCRATCH_REG5_OFFS R5_OFFSET
# define REG_OFFSET(reg) (R0_OFFSET + ((reg)-DR_REG_R0) * sizeof(reg_t))
# define CALL_SCRATCH_REG DR_REG_R11
#endif /* X86/ARM */
#elif defined(RISCV64)
# define REG0_OFFSET ((MC_OFFS) + (offsetof(priv_mcontext_t, t0)))
# define REG1_OFFSET ((MC_OFFS) + (offsetof(priv_mcontext_t, t1)))
# define REG2_OFFSET ((MC_OFFS) + (offsetof(priv_mcontext_t, t2)))
# define REG3_OFFSET ((MC_OFFS) + (offsetof(priv_mcontext_t, t3)))
# define REG4_OFFSET ((MC_OFFS) + (offsetof(priv_mcontext_t, t4)))
# define REG5_OFFSET ((MC_OFFS) + (offsetof(priv_mcontext_t, t5)))
# define SCRATCH_REG0 DR_REG_T0
# define SCRATCH_REG1 DR_REG_T1
# define SCRATCH_REG2 DR_REG_T2
# define SCRATCH_REG3 DR_REG_T3
# define SCRATCH_REG4 DR_REG_T4
# define SCRATCH_REG5 DR_REG_T5
# define SCRATCH_REG0_OFFS REG0_OFFSET
# define SCRATCH_REG1_OFFS REG1_OFFSET
# define SCRATCH_REG2_OFFS REG2_OFFSET
# define SCRATCH_REG3_OFFS REG3_OFFSET
# define SCRATCH_REG4_OFFS REG4_OFFSET
# define SCRATCH_REG5_OFFS REG5_OFFSET
/* FIXME-RISCV: Check is T6 safe to use */
# define CALL_SCRATCH_REG DR_REG_T6
#endif /* X86/ARM/RISCV64 */
#define XSP_OFFSET ((MC_OFFS) + (offsetof(priv_mcontext_t, xsp)))
#define XFLAGS_OFFSET ((MC_OFFS) + (offsetof(priv_mcontext_t, xflags)))
#define PC_OFFSET ((MC_OFFS) + (offsetof(priv_mcontext_t, pc)))
Expand Down Expand Up @@ -592,6 +613,8 @@ mangle_insert_clone_code(dcontext_t *dcontext, instrlist_t *ilist,
# define ABI_STACK_ALIGNMENT 16
#elif defined(ARM)
# define ABI_STACK_ALIGNMENT 8
#elif defined(RISCV64)
# define ABI_STACK_ALIGNMENT 8
#endif

/* Returns the number of bytes the stack pointer has to be aligned to. */
Expand Down
58 changes: 56 additions & 2 deletions core/arch/arch_exports.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ typedef struct _spill_state_t {
/* These are needed for ldex/stex mangling and A64 icache_op_ic_ivau_asm. */
reg_t r4, r5;
reg_t reg_stolen; /* slot for the stolen register */
#elif defined(RISCV64)
/* FIXME-RISCV: Find proper registers to use as scratch. Does it matter? */
reg_t t0, t1, t2, t3;
#endif
/* XXX: move this below the tables to fit more on cache line */
dcontext_t *dcontext;
Expand Down Expand Up @@ -220,6 +223,20 @@ typedef struct _local_state_extended_t {
# define SCRATCH_REG4 DR_REG_R4
# define SCRATCH_REG5 DR_REG_R5
# define SCRATCH_REG_LAST SCRATCH_REG5
#elif defined(RISCV64)
/* FIXME-RISCV: RFC: Are there any requirements on TLS/scratch registers?
* Aarch64 and X86 use a combination of argument, callee-saved and
* caller-saved/temporary regs. Can we use temporary registers or rather leave
* them to client code?
*/
# define TLS_REG0_SLOT ((ushort)offsetof(spill_state_t, t0))
# define TLS_REG1_SLOT ((ushort)offsetof(spill_state_t, t1))
# define TLS_REG2_SLOT ((ushort)offsetof(spill_state_t, t2))
# define TLS_REG3_SLOT ((ushort)offsetof(spill_state_t, t3))
# define SCRATCH_REG0 DR_REG_T0
# define SCRATCH_REG1 DR_REG_T1
# define SCRATCH_REG2 DR_REG_T2
# define SCRATCH_REG3 DR_REG_T3
#endif /* X86/ARM */
#define IBL_TARGET_REG SCRATCH_REG2
#define IBL_TARGET_SLOT TLS_REG2_SLOT
Expand Down Expand Up @@ -542,6 +559,7 @@ enum {
SYSCALL_METHOD_WOW64,
#endif
SYSCALL_METHOD_SVC, /* ARM */
SYSCALL_METHOD_ECALL, /* RISCV64 */
};
#ifdef UNIX
enum { SYSCALL_METHOD_LONGEST_INSTR = 2 }; /* to ensure safe patching */
Expand Down Expand Up @@ -1028,7 +1046,37 @@ fill_with_nops(dr_isa_mode_t isa_mode, byte *addr, size_t size);
/* i#1906: alignment needed for the source address of data to load into the PC */
# define PC_LOAD_ADDR_ALIGN 4

#endif /* ARM */
#elif defined(RISCV64)
/* FIXME-RISCV: This can be 2B in C. */
#define RISCV64_INSTR_SIZE 4
/* FIXME-RISCV: Not implemented */
# define FRAGMENT_BASE_PREFIX_SIZE(flags) RISCV64_INSTR_SIZE
/* FIXME-RISCV: Not implemented */
# define DIRECT_EXIT_STUB_SIZE(flags) \
(10 * RISCV64_INSTR_SIZE) /* see insert_exit_stub_other_flags */
# define FRAG_IS_32(flags) false
# define PC_AS_JMP_TGT(isa_mode, pc) pc
# define PC_AS_LOAD_TGT(isa_mode, pc) pc
/* FIXME-RISCV: Not implemented */
# define DIRECT_EXIT_STUB_DATA_SZ 0
# define STUB_COARSE_DIRECT_SIZE(flags) (ASSERT_NOT_IMPLEMENTED(false), 0)
# define SET_TO_NOPS(isa_mode, addr, size) fill_with_nops(isa_mode, addr, size)
# define SET_TO_DEBUG(addr, size) ASSERT_NOT_IMPLEMENTED(false)
# define IS_SET_TO_DEBUG(addr, size) (ASSERT_NOT_IMPLEMENTED(false), false)

/* offset of the patchable region from the end of a cti */
/* FIXME-RISCV: Not implemented */
# define CTI_PATCH_OFFSET 4
/* offset of the patchable region from the end of a stub */
/* FIXME-RISCV: Not implemented */
# define EXIT_STUB_PATCH_OFFSET 4
/* size of the patch to a stub */
/* FIXME-RISCV: Not implemented */
# define EXIT_STUB_PATCH_SIZE 4
/* the most bytes we'll need to shift a patchable location for -pad_jmps */
/* FIXME-RISCV: Not implemented */
# define MAX_PAD_SIZE 0
#endif /* RISCV64 */
/****************************************************************************/

/* evaluates to true if region crosses at most 1 padding boundary */
Expand Down Expand Up @@ -1238,10 +1286,16 @@ enum {
CBR_SHORT_REWRITE_LENGTH = 6,
SVC_THUMB_LENGTH = THUMB_SHORT_INSTR_SIZE, /* Thumb syscall instr */
SVC_ARM_LENGTH = ARM_INSTR_SIZE, /* ARM syscall instr */
#elif defined(RISCV64)
CBR_LONG_LENGTH = 4,
JMP_LONG_LENGTH = 4,
JMP_SHORT_LENGTH = 4,
CBR_SHORT_REWRITE_LENGTH = 4,
#endif

/* Not under defines so we can have code that is less cluttered */
#ifdef AARCH64
/* FIXME-RISCV: With Compressed ext ecall can be 2 */
#if defined(AARCH64) || defined(RISCV64)
INT_LENGTH = 4,
SYSCALL_LENGTH = 4,
SYSENTER_LENGTH = 4,
Expand Down
84 changes: 84 additions & 0 deletions core/arch/asm_defines.asm
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@
# endif
# ifdef X86
# define HEX(n) 0x##n
# elif defined(RISCV64)
# define HEX(n) 0x##n
# else
# define POUND #
# define HEX(n) POUND 0x##n
Expand Down Expand Up @@ -319,6 +321,44 @@ ASSUME fs:_DATA @N@\
# define REG_R11 x11
# define REG_R12 x12
/* skip [x13..x30], not available on AArch32 */
#elif defined(RISCV64)
# define REG_SP sp
# define REG_R0 x0
# define REG_R1 x1
# define REG_R2 x2
# define REG_R3 x3
# define REG_R4 x4
# define REG_R5 x5
# define REG_R6 x6
# define REG_R7 x7
# define REG_R8 x8
# define REG_R9 x9
# define REG_R10 x10
# define REG_R11 x11
# define REG_R12 x12
# define REG_R13 x13
# define REG_R14 x14
# define REG_R15 x15
# define REG_R16 x16
# define REG_R17 x17
# define REG_R18 x18
# define REG_R19 x19
# define REG_R20 x20
# define REG_R21 x21
# define REG_R22 x22
# define REG_R23 x23
# define REG_R24 x24
# define REG_R25 x25
# define REG_R26 x26
# define REG_R27 x27
# define REG_R28 x28
# define REG_R29 x29
# define REG_R30 x30
# define REG_R31 x31
# define SEG_TLS s11 /* keep in sync w/ {unix,win32}/os_exports.h defines */
# ifdef UNIX
# define LIB_SEG_TLS tp /* keep in sync w/ unix/os_exports.h defines */
# endif
#else /* Intel X86 */
# ifdef X64
# define REG_XAX rax
Expand Down Expand Up @@ -440,6 +480,50 @@ ASSUME fs:_DATA @N@\
# define RESTORE_PRESERVED_REGS ldp REG_PRESERVED_1, LR, [sp], #16
# endif

#elif defined(RISCV64)
/* RISC-V psABI calling convention:
* x0(zero) : Hard-wired zero
* x1(ra) : Return address
* x2(sp) : Stack pointer (callee saved)
* x3(gp) : Global pointer
* x4(tp) : Thread pointer
* x5(t0) : Temporary/alternate link register
* x6..7(t1..2) : Temporaries
* x8(s0/fp) : Calee saved register/frame pointer
* x9(s1) : Calee saved register
* x10..11(a0..1) : Function arguments/return values
* x12..17(a2..7) : Function arguments
* x18..27(s2..11) : Calee saved registers
* x28..31(t3..6) : Temporaries
*
* f0..7(ft0..7) : FP temporaries
* f8..9(fs0..1) : FP callee saved registers
* f10..11(fa0..1) : FP arguments/return values
* f12..17(fa2..7) : FP arguments
* f18..27(fs2..11) : FP callee saved registers
* f28..31(ft8..11) : FP temporaries
*/
# define ARG1 REG_R10
# define ARG2 REG_R11
# define ARG3 REG_R12
# define ARG4 REG_R13
# define ARG5 REG_R14
# define ARG6 REG_R15
# define ARG7 REG_R16
# define ARG8 REG_R17
/* Arguments are passed on stack right-to-left. */
# define ARG9 0(REG_SP) /* no ret addr */
# define ARG10 ARG_SZ(REG_SP)
# define ARG1_NORETADDR ARG1
# define ARG2_NORETADDR ARG2
# define ARG3_NORETADDR ARG3
# define ARG4_NORETADDR ARG4
# define ARG5_NORETADDR ARG5
# define ARG6_NORETADDR ARG6
# define ARG7_NORETADDR ARG7
# define ARG8_NORETADDR ARG8
# define ARG9_NORETADDR ARG9
# define ARG10_NORETADDR ARG10
#else /* Intel X86 */
# ifdef X64
# ifdef WINDOWS
Expand Down
26 changes: 26 additions & 0 deletions core/arch/proc_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@
*/
#ifdef X86
# define DR_FPSTATE_BUF_SIZE 512
#elif defined(RISCV64)
/* FIXME-RISCV: Not implemented */
# define DR_FPSTATE_BUF_SIZE 1
#elif defined(ARM) || defined(AARCH64)
/* On ARM/AArch64 proc_save_fpstate saves nothing, so use the smallest
* legal size for an array.
Expand All @@ -62,6 +65,8 @@
/** The alignment requirements of floating point state buffer. */
#if defined(X86) || defined(AARCH64)
# define DR_FPSTATE_ALIGN 16
#elif defined(RISCV64)
# define DR_FPSTATE_ALIGN 1
#elif defined(ARM)
# define DR_FPSTATE_ALIGN 1
#endif
Expand Down Expand Up @@ -175,6 +180,17 @@ typedef struct {
} features_t;
typedef enum { AA64ISAR0 = 0, AA64ISAR1 = 1, AA64PFR0 = 2 } feature_reg_idx_t;
#endif
#ifdef RISCV64
/* FIXME-RISCV: Not implemented */
/**
* For RISC-V64 there are no features readable from userspace. Hence only a
* dummy flag is there. May be replaced by actual feature flags in the future.
* Used by proc_get_all_feature_bits().
*/
typedef struct {
uint64 dummy; /**< dummy member to keep size non-0. */
} features_t;
#endif

#ifdef X86
/**
Expand Down Expand Up @@ -323,6 +339,16 @@ typedef enum {
FEATURE_SVE = DEF_FEAT(AA64PFR0, 8, 1, 1), /**< Scalable Vectors (AArch64) */
} feature_bit_t;
#endif
#ifdef RISCV64
/* FIXME-RISCV: Not implemented */
/**
* Feature bits passed to proc_has_feature() to determine whether the underlying
* processor has the feature.
*/
typedef enum {
FEATURE_DUMMY = 0, /**< Dummy, non-existent feature. */
} feature_bit_t;
#endif

/* Make sure to keep this in sync with proc_get_cache_size_str() in proc.c. */
/**
Expand Down
5 changes: 5 additions & 0 deletions core/ir/encode_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ typedef enum _dr_isa_mode_t {
DR_ISA_ARM_A32, /**< ARM A32 (AArch32 ARM). */
DR_ISA_ARM_THUMB, /**< Thumb (ARM T32). */
DR_ISA_ARM_A64, /**< ARM A64 (AArch64). */
DR_ISA_RV64IMAFDC, /**< RISC-V (rv64imafdc). */
} dr_isa_mode_t;

DR_API
Expand Down Expand Up @@ -92,6 +93,10 @@ enum {
/* With register lists we can see quite long operand lists. */
MAX_SRC_OPNDS = 33, /* vstm s0-s31 */
MAX_DST_OPNDS = MAX_SRC_OPNDS,
#elif defined(RISCV64)
MAX_INSTR_LENGTH = 4,
MAX_SRC_OPNDS = 3,
MAX_DST_OPNDS = 1,
#endif
};

Expand Down
23 changes: 23 additions & 0 deletions core/ir/instr_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,16 @@ typedef enum _dr_pred_type_t {
DR_PRED_HS = DR_PRED_CS, /**< ARM condition: alias for DR_PRED_CS. */
DR_PRED_LO = DR_PRED_CC, /**< ARM condition: alias for DR_PRED_CC. */
#endif
#ifdef RISCV64
/* FIXME-RISCV: RISC-V does not have compare flag register! */
/* Aliases for XINST_CREATE_jump_cond() and other cross-platform routines. */
DR_PRED_EQ, /**< Condition code: equal. */
DR_PRED_NE, /**< Condition code: not equal. */
DR_PRED_LT, /**< Condition code: signed less than. */
DR_PRED_LE, /**< Condition code: signed less than or equal. */
DR_PRED_GT, /**< Condition code: signed greater than. */
DR_PRED_GE, /**< Condition code: signed greater than or equal. */
#endif
} dr_pred_type_t;

/**
Expand Down Expand Up @@ -2533,6 +2543,19 @@ enum {
# define EFLAGS_MSR_G 0x4
/** The bits in the 4-bit OP_msr immediate that select the nzcvqg status flags. */
# define EFLAGS_MSR_NZCVQG (EFLAGS_MSR_NZCVQ | EFLAGS_MSR_G)
#elif defined(RISCV64)
/* FIXME-RISCV: Not implemented */
/** Platform-independent macro for reads all arithmetic flags. */
# define EFLAGS_READ_ARITH 0
# define EFLAGS_READ_ALL 0 /**< Reads all flags. */
# define EFLAGS_READ_NON_PRED 0 /**< Flags not read by predicates. */
/** Platform-independent macro for writes all arithmetic flags. */
# define EFLAGS_WRITE_ARITH 0
# define EFLAGS_WRITE_ALL 0 /**< Writes all flags. */
/** Converts an EFLAGS_WRITE_* value to the corresponding EFLAGS_READ_* value. */
# define EFLAGS_WRITE_TO_READ(x) (x)
/** Converts an EFLAGS_READ_* value to the corresponding EFLAGS_WRITE_* value. */
# define EFLAGS_READ_TO_WRITE(x) (x)
#endif /* X86 */

#endif /* _DR_IR_INSTR_H_ */
23 changes: 22 additions & 1 deletion core/ir/opnd.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,11 @@ extern const reg_id_t dr_reg_fixer[];
/* We only normally use r0-r5 but we support more in translation code */
# define REG_START_SPILL DR_REG_R0
# define REG_STOP_SPILL DR_REG_R10 /* r10 might be used in syscall mangling */
#endif /* X86/ARM */
#elif defined(RISCV64)
/* We only normally use r0-r5 but we support more in translation code */
# define REG_START_SPILL DR_REG_A0
# define REG_STOP_SPILL DR_REG_A5
#endif /* RISCV64 */
#define REG_SPILL_NUM (REG_STOP_SPILL - REG_START_SPILL + 1)

#ifndef INT8_MIN
Expand Down Expand Up @@ -280,6 +284,20 @@ enum {
REDZONE_SIZE = 0,
REGPARM_MINSTACK = 0,
REGPARM_END_ALIGN = 8,
#elif defined(RISCV64)
DR_SYSNUM_REG = DR_REG_A7,
REGPARM_0 = DR_REG_A0,
REGPARM_1 = DR_REG_A1,
REGPARM_2 = DR_REG_A2,
REGPARM_3 = DR_REG_A3,
REGPARM_4 = DR_REG_A4,
REGPARM_5 = DR_REG_A5,
REGPARM_6 = DR_REG_A6,
REGPARM_7 = DR_REG_A7,
NUM_REGPARM = 6,
REDZONE_SIZE = 0,
REGPARM_MINSTACK = 0,
REGPARM_END_ALIGN = 8,
#endif
};

Expand All @@ -293,6 +311,9 @@ enum {
# else
# define MCXT_FLD_SYSNUM_REG r7
# endif /* 64/32 */
#elif defined(RISCV64)
# define MCXT_FLD_FIRST_REG x0
# define MCXT_FLD_SYSNUM_REG a7
#endif
extern const reg_id_t d_r_regparms[];

Expand Down
Loading

0 comments on commit 620fe03

Please sign in to comment.