1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
4 #if defined(TARGET_RISCV64)
6 // The RISCV64 instructions are all 32 bits in size.
7 // we use an unsigned int to hold the encoded instructions.
8 // This typedef defines the type that we use to hold encoded instructions.
10 typedef unsigned int code_t;
12 /************************************************************************/
13 /* Routines that compute the size of / encode instructions */
14 /************************************************************************/
24 /************************************************************************/
25 /* Debug-only routines to display instructions */
26 /************************************************************************/
28 const char* emitFPregName(unsigned reg, bool varName = true);
29 const char* emitVectorRegName(regNumber reg);
31 void emitDisInsName(code_t code, const BYTE* addr, instrDesc* id);
34 void emitIns_J_cond_la(instruction ins, BasicBlock* dst, regNumber reg1 = REG_R0, regNumber reg2 = REG_R0);
36 void emitLoadImmediate(emitAttr attr, regNumber reg, ssize_t imm);
38 /************************************************************************/
39 /* Private members that deal with target-dependent instr. descriptors */
40 /************************************************************************/
43 instrDesc* emitNewInstrCallDir(int argCnt,
44 VARSET_VALARG_TP GCvars,
47 emitAttr retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize));
49 instrDesc* emitNewInstrCallInd(int argCnt,
51 VARSET_VALARG_TP GCvars,
54 emitAttr retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize));
56 /************************************************************************/
57 /* Private helpers for instruction output */
58 /************************************************************************/
61 bool emitInsIsLoad(instruction ins);
62 bool emitInsIsStore(instruction ins);
63 bool emitInsIsLoadOrStore(instruction ins);
65 emitter::code_t emitInsCode(instruction ins /*, insFormat fmt*/);
67 // Generate code for a load or store operation and handle the case of contained GT_LEA op1 with [base + offset]
68 void emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir);
70 // Emit the 32-bit RISCV64 instruction 'code' into the 'dst' buffer
71 unsigned emitOutput_Instr(BYTE* dst, code_t code);
73 // Method to do check if mov is redundant with respect to the last instruction.
74 // If yes, the caller of this method can choose to omit current mov instruction.
75 static bool IsMovInstruction(instruction ins);
76 bool IsRedundantMov(instruction ins, emitAttr size, regNumber dst, regNumber src, bool canSkip);
77 bool IsRedundantLdStr(
78 instruction ins, regNumber reg1, regNumber reg2, ssize_t imm, emitAttr size, insFormat fmt); // New functions end.
80 /************************************************************************/
81 /* Public inline informational methods */
82 /************************************************************************/
85 // Returns true if 'value' is a legal signed immediate 13 bit encoding.
86 static bool isValidSimm13(ssize_t value)
88 return -(((int)1) << 12) <= value && value < (((int)1) << 12);
91 // Returns true if 'value' is a legal signed immediate 12 bit encoding.
92 static bool isValidSimm12(ssize_t value)
94 return -(((int)1) << 11) <= value && value < (((int)1) << 11);
97 // Returns true if 'value' is a legal unsigned immediate 12 bit encoding.
98 static bool isValidUimm12(ssize_t value)
100 return (0 == (value >> 12));
103 // Returns true if 'value' is a legal unsigned immediate 11 bit encoding.
104 static bool isValidUimm11(ssize_t value)
106 return (0 == (value >> 11));
109 // Returns true if 'value' is a legal signed immediate 20 bit encoding.
110 static bool isValidSimm20(ssize_t value)
112 return -(((int)1) << 19) <= value && value < (((int)1) << 19);
115 // Returns true if 'value' is a legal unsigned immediate 20 bit encoding.
116 static bool isValidUimm20(ssize_t value)
118 return (0 == (value >> 20));
121 // Returns true if 'value' is a legal signed immediate 21 bit encoding.
122 static bool isValidSimm21(ssize_t value)
124 return -(((int)1) << 20) <= value && value < (((int)1) << 20);
127 // Returns true if 'value' is a legal signed immediate 32 bit encoding.
128 static bool isValidSimm32(ssize_t value)
130 return -(((ssize_t)1) << 31) <= value && value < (((ssize_t)1) << 31);
133 // Returns the number of bits used by the given 'size'.
134 inline static unsigned getBitWidth(emitAttr size)
136 assert(size <= EA_8BYTE);
137 return (unsigned)size * BITS_PER_BYTE;
140 inline static bool isGeneralRegister(regNumber reg)
142 return (reg >= REG_INT_FIRST) && (reg <= REG_INT_LAST);
145 inline static bool isGeneralRegisterOrR0(regNumber reg)
147 return (reg >= REG_FIRST) && (reg <= REG_INT_LAST);
150 inline static bool isFloatReg(regNumber reg)
152 return (reg >= REG_FP_FIRST && reg <= REG_FP_LAST);
155 /************************************************************************/
156 /* Output target-independent instructions */
157 /************************************************************************/
159 void emitIns_J(instruction ins, BasicBlock* dst, int instrCount = 0);
161 /************************************************************************/
162 /* The public entry points to output instructions */
163 /************************************************************************/
166 void emitIns(instruction ins);
168 void emitIns_S_R(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs);
169 void emitIns_S_R_R(instruction ins, emitAttr attr, regNumber ireg, regNumber tmpReg, int varx, int offs);
170 void emitIns_R_S(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs);
172 void emitIns_I(instruction ins, emitAttr attr, ssize_t imm);
173 void emitIns_I_I(instruction ins, emitAttr attr, ssize_t cc, ssize_t offs);
175 void emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, insOpts opt = INS_OPTS_NONE);
178 instruction ins, emitAttr attr, regNumber dstReg, regNumber srcReg, bool canSkip, insOpts opt = INS_OPTS_NONE);
180 void emitIns_Mov(emitAttr attr, regNumber dstReg, regNumber srcReg, bool canSkip = false);
182 void emitIns_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insOpts opt = INS_OPTS_NONE);
184 void emitIns_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insFlags flags)
186 _ASSERTE(!"RISCV64: NYI");
190 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt = INS_OPTS_NONE);
193 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt = INS_OPTS_NONE);
195 void emitIns_R_R_R_I(instruction ins,
201 insOpts opt = INS_OPTS_NONE,
202 emitAttr attrReg2 = EA_UNKNOWN);
204 void emitIns_R_R_I_I(
205 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2, insOpts opt = INS_OPTS_NONE);
207 void emitIns_R_R_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4);
210 instruction ins, emitAttr attr, regNumber reg, regNumber tmpReg, CORINFO_FIELD_HANDLE fldHnd, int offs);
212 void emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg);
214 void emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg);
216 void emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs);
218 void emitIns_R_AI(instruction ins,
221 ssize_t disp DEBUGARG(size_t targetHandle = 0) DEBUGARG(GenTreeFlags gtFlags = GTF_EMPTY));
226 // I have included here, but commented out, all the values used by the x86 emitter.
227 // However, RISCV64 has a much reduced instruction set, and so the RISCV64 emitter only
228 // supports a subset of the x86 variants. By leaving them commented out, it becomes
229 // a compile time error if code tries to use them (and hopefully see this comment
230 // and know why they are unavailable on RISCV64), while making it easier to stay
231 // in-sync with x86 and possibly add them back in if needed.
233 EC_FUNC_TOKEN, // Direct call to a helper/static/nonvirtual/global method
234 // EC_FUNC_TOKEN_INDIR, // Indirect call to a helper/static/nonvirtual/global method
235 // EC_FUNC_ADDR, // Direct call to an absolute address
237 // EC_FUNC_VIRTUAL, // Call to a virtual method (using the vtable)
238 EC_INDIR_R, // Indirect call via register
239 // EC_INDIR_SR, // Indirect call via stack-reference (local var)
240 // EC_INDIR_C, // Indirect call via static class var
241 // EC_INDIR_ARD, // Indirect call via an addressing mode
246 void emitIns_Call(EmitCallType callType,
247 CORINFO_METHOD_HANDLE methHnd,
248 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
251 emitAttr retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize),
252 VARSET_VALARG_TP ptrVars,
256 regNumber ireg = REG_NA,
257 regNumber xreg = REG_NA,
260 bool isJump = false);
262 unsigned emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code);
264 unsigned get_curTotalCodeSize(); // bytes of code
266 #endif // TARGET_RISCV64