cd61556a906e933ffc184db30264975ce1a272ac
[platform/upstream/dotnet/runtime.git] / src / coreclr / pal / inc / unixasmmacrosriscv64.inc
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3
4 .macro NESTED_ENTRY Name, Section, Handler
5     LEAF_ENTRY \Name, \Section
6     .ifnc \Handler, NoHandler
7         .cfi_personality 0x1B, C_FUNC(\Handler) // 0x1B == DW_EH_PE_pcrel | DW_EH_PE_sdata4
8     .endif
9 .endm
10
11 .macro NESTED_END Name, Section
12     LEAF_END \Name, \Section
13 .endm
14
15 .macro PATCH_LABEL Name
16     .global C_FUNC(\Name)
17 C_FUNC(\Name):
18 .endm
19
20 .macro LEAF_ENTRY Name, Section
21     .global C_FUNC(\Name)
22     .type \Name, %function
23 C_FUNC(\Name):
24     .cfi_startproc
25 .endm
26
27 .macro LEAF_END Name, Section
28     .size \Name, .-\Name
29     .cfi_endproc
30 .endm
31
32 .macro LEAF_END_MARKED Name, Section
33 C_FUNC(\Name\()_End):
34     .global C_FUNC(\Name\()_End)
35     LEAF_END \Name, \Section
36     // make sure this symbol gets its own address
37     nop
38 .endm
39
40 .macro PREPARE_EXTERNAL_VAR Name, HelperReg
41     lla  \HelperReg, \Name
42 .endm
43
44 .macro PROLOG_STACK_ALLOC Size
45     addi sp, sp, -\Size
46     .cfi_adjust_cfa_offset \Size
47 .endm
48
49 .macro EPILOG_STACK_FREE Size
50     addi sp, sp, \Size
51     .cfi_adjust_cfa_offset -\Size
52 .endm
53
54 .macro EPILOG_STACK_RESTORE
55     ori  sp, fp, 0
56     .cfi_restore sp
57 .endm
58
59 .macro PROLOG_SAVE_REG reg, ofs
60     sd \reg, \ofs(sp)
61     .cfi_rel_offset \reg, \ofs
62 .endm
63
64 .macro PROLOG_SAVE_REG_PAIR reg1, reg2, ofs, __def_cfa_save=0
65     sd \reg1, \ofs(sp)
66     sd \reg2, (\ofs+8)(sp)
67     .cfi_rel_offset \reg1, \ofs
68     .cfi_rel_offset \reg2, \ofs + 8
69     .if (\__def_cfa_save ==  1)
70         addi fp, sp, 0
71         .cfi_def_cfa_register fp
72     .endif
73 .endm
74
75 .macro PROLOG_SAVE_REG_PAIR_INDEXED reg1, reg2, ssize, __def_cfa_save=1
76     addi sp, sp, -\ssize
77     .cfi_adjust_cfa_offset \ssize
78
79     sd \reg1, 0(sp)
80     sd \reg2, 8(sp)
81
82     .cfi_rel_offset \reg1, 0
83     .cfi_rel_offset \reg2, 8
84     .if (\__def_cfa_save ==  1)
85         addi fp, sp, 0
86         .cfi_def_cfa_register fp
87     .endif
88 .endm
89
90 .macro EPILOG_RESTORE_REG reg, ofs
91     ld  \reg, (\ofs)(sp)
92     .cfi_restore \reg
93 .endm
94
95 .macro EPILOG_RESTORE_REG_PAIR reg1, reg2, ofs
96     ld  \reg2, (\ofs+8)(sp)
97     ld  \reg1, (\ofs)(sp)
98     .cfi_restore \reg2
99     .cfi_restore \reg1
100 .endm
101
102 .macro EPILOG_RESTORE_REG_PAIR_INDEXED reg1, reg2, ssize
103     ld  \reg2, 8(sp)
104     ld  \reg1, 0(sp)
105     .cfi_restore \reg2
106     .cfi_restore \reg1
107
108     addi  sp, sp, \ssize
109     .cfi_adjust_cfa_offset -\ssize
110 .endm
111
112 .macro EPILOG_RETURN
113     ret
114 .endm
115
116 .macro EMIT_BREAKPOINT
117     ebreak
118 .endm
119
120 .macro EPILOG_BRANCH Target
121     j \Target
122 .endm
123
124 .macro EPILOG_BRANCH_REG reg
125     jr \reg
126 .endm
127
128 //-----------------------------------------------------------------------------
129 // The Following sets of SAVE_*_REGISTERS expect the memory to be reserved and
130 // base address to be passed in $reg
131 //
132
133 // Reserve 64 bytes of memory before calling  SAVE_CALLEESAVED_REGISTERS
134 .macro SAVE_CALLEESAVED_REGISTERS reg, ofs
135     PROLOG_SAVE_REG_PAIR s1, s2, \ofs + 16
136     PROLOG_SAVE_REG_PAIR s3, s4, \ofs + 32
137     PROLOG_SAVE_REG_PAIR s5, s6, \ofs + 48
138     PROLOG_SAVE_REG_PAIR s7, s8, \ofs + 64
139     PROLOG_SAVE_REG_PAIR s9, s10, \ofs + 80
140     PROLOG_SAVE_REG_PAIR s11, tp  \ofs + 96
141     PROLOG_SAVE_REG      gp,  \ofs + 112
142 .endm
143
144 // Reserve 64 bytes of memory before calling  SAVE_ARGUMENT_REGISTERS
145 .macro SAVE_ARGUMENT_REGISTERS reg, ofs
146     sd  a0, (\ofs)(\reg)
147     sd  a1, (\ofs + 8)(\reg)
148     sd  a2, (\ofs + 16)(\reg)
149     sd  a3, (\ofs + 24)(\reg)
150     sd  a4, (\ofs + 32)(\reg)
151     sd  a5, (\ofs + 40)(\reg)
152     sd  a6, (\ofs + 48)(\reg)
153     sd  a7, (\ofs + 56)(\reg)
154 .endm
155
156 // Reserve 64 bytes of memory before calling  SAVE_FLOAT_ARGUMENT_REGISTERS
157 .macro SAVE_FLOAT_ARGUMENT_REGISTERS reg, ofs
158     fsd  fa0, (\ofs)(\reg)
159     fsd  fa1, (\ofs + 8)(\reg)
160     fsd  fa2, (\ofs + 16)(\reg)
161     fsd  fa3, (\ofs + 24)(\reg)
162     fsd  fa4, (\ofs + 32)(\reg)
163     fsd  fa5, (\ofs + 40)(\reg)
164     fsd  fa6, (\ofs + 48)(\reg)
165     fsd  fa7, (\ofs + 56)(\reg)
166 .endm
167
168 // Reserve 64 bytes of memory before calling  SAVE_FLOAT_CALLEESAVED_REGISTERS
169 .macro SAVE_FLOAT_CALLEESAVED_REGISTERS reg, ofs
170 // TODO RISCV NYI
171     sw  ra, 0(zero)
172 .endm
173
174 .macro RESTORE_CALLEESAVED_REGISTERS reg, ofs
175     EPILOG_RESTORE_REG      gp  \ofs + 112
176     EPILOG_RESTORE_REG_PAIR s11, tp  \ofs + 96
177     EPILOG_RESTORE_REG_PAIR s9, s10, \ofs + 80 
178     EPILOG_RESTORE_REG_PAIR s7, s8,  \ofs + 64
179     EPILOG_RESTORE_REG_PAIR s5, s6,  \ofs + 48
180     EPILOG_RESTORE_REG_PAIR s3, s4,  \ofs + 32
181     EPILOG_RESTORE_REG_PAIR s1, s2,  \ofs + 16
182 .endm
183
184 .macro RESTORE_ARGUMENT_REGISTERS reg, ofs
185     ld  a0, (\ofs)(\reg)
186     ld  a1, (\ofs + 8)(\reg)
187     ld  a2, (\ofs + 16)(\reg)
188     ld  a3, (\ofs + 24)(\reg)
189     ld  a4, (\ofs + 32)(\reg)
190     ld  a5, (\ofs + 40)(\reg)
191     ld  a6, (\ofs + 48)(\reg)
192     ld  a7, (\ofs + 56)(\reg)
193 .endm
194
195 .macro RESTORE_FLOAT_ARGUMENT_REGISTERS reg, ofs
196     fld  fa0, (\ofs)(\reg)
197     fld  fa1, (\ofs + 8)(\reg)
198     fld  fa2, (\ofs + 16)(\reg)
199     fld  fa3, (\ofs + 24)(\reg)
200     fld  fa4, (\ofs + 32)(\reg)
201     fld  fa5, (\ofs + 40)(\reg)
202     fld  fa6, (\ofs + 48)(\reg)
203     fld  fa7, (\ofs + 56)(\reg)
204 .endm
205
206 .macro RESTORE_FLOAT_CALLEESAVED_REGISTERS reg, ofs
207 // TODO RISCV NYI
208     sw  ra, 0(zero)
209 .endm
210
211 //-----------------------------------------------------------------------------
212 // Define the prolog for a TransitionBlock-based method. This macro should be called first in the method and
213 // comprises the entire prolog.The locals must be 8 byte aligned
214 //
215 // Save_argument_registers:
216 //            GPR_a7
217 //            GPR_a6
218 //            GPR_a5
219 //            GPR_a4
220 //            GPR_a3
221 //            GPR_a2
222 //            GPR_a1
223 //            GPR_a0
224 //
225 // General Registers:
226 //            GPR_tp
227 //            GPR_s8
228 //            GPR_s7
229 //            GPR_s6
230 //            GPR_s5
231 //            GPR_s4
232 //            GPR_s3
233 //            GPR_s2
234 //            GPR_s1
235 //            GPR_s0
236 //            GPR_ra
237 //            GPR_fp
238 //
239 // Float Point:
240 //            FPR_f27 / fs11
241 //            FPR_f26 / fs10
242 //            FPR_f25 / fs9
243 //            FPR_f24 / fs8
244 //            FPR_f23 / fs7
245 //            FPR_f22 / fs6
246 //            FPR_f21 / fs5
247 //            FPR_f20 / fs4
248 //            FPR_f19 / fs3
249 //            FPR_f18 / fs2
250 //            FPR_f9 / fs1
251 //            FPR_f8 / fs0
252 // Extra:
253 //
254 .macro PROLOG_WITH_TRANSITION_BLOCK extraParameters = 0, extraLocals = 0, SaveFPRegs = 1
255     __PWTB_SaveFPArgs = \SaveFPRegs
256
257     __PWTB_FloatArgumentRegisters = \extraLocals
258
259     // Note, stack (see __PWTB_StackAlloc variable) must be 16 byte aligned,
260     // SIZEOF__FloatArgumentRegisters (0x40) is 16 byte aligned, that mean initial
261     // __PWTB_FloatArgumentRegisters value must be not 16 byte aligned and
262     // after add (120 + 64) provide 16 byte aligned result.
263     .if ((__PWTB_FloatArgumentRegisters % 16) == 0)
264         __PWTB_FloatArgumentRegisters = __PWTB_FloatArgumentRegisters + 8
265     .endif
266
267     __PWTB_TransitionBlock = __PWTB_FloatArgumentRegisters
268
269     .if (__PWTB_SaveFPArgs == 1)
270         __PWTB_TransitionBlock = __PWTB_TransitionBlock + SIZEOF__FloatArgumentRegisters
271     .endif
272
273
274     __PWTB_CalleeSavedRegisters = __PWTB_TransitionBlock
275     __PWTB_ArgumentRegisters = __PWTB_TransitionBlock + 120
276
277     // Including fp, ra, s1-s11, tp, gp, and (a0-a7)arguments. (1+1+11+1+1)*8 + 8*8.
278     __PWTB_StackAlloc = __PWTB_TransitionBlock + 120 + 64
279     PROLOG_STACK_ALLOC __PWTB_StackAlloc
280     PROLOG_SAVE_REG_PAIR  fp, ra, __PWTB_CalleeSavedRegisters, 1
281
282     // First, Spill argument registers.
283     SAVE_ARGUMENT_REGISTERS        sp, __PWTB_ArgumentRegisters
284
285     // Then, Spill callee saved registers.  sp=r2.
286     SAVE_CALLEESAVED_REGISTERS     sp, __PWTB_CalleeSavedRegisters
287
288     // saving is f10-17.
289     .if (__PWTB_SaveFPArgs == 1)
290         SAVE_FLOAT_ARGUMENT_REGISTERS sp, __PWTB_FloatArgumentRegisters
291     .endif
292
293 .endm
294
295 .macro EPILOG_WITH_TRANSITION_BLOCK_RETURN
296 // TODO RISCV NYI
297     sw  ra, 0(zero)
298 .endm
299
300
301 //-----------------------------------------------------------------------------
302 // Provides a matching epilog to PROLOG_WITH_TRANSITION_BLOCK and ends by preparing for tail-calling.
303 // Since this is a tail call argument registers are restored.
304 //
305 .macro EPILOG_WITH_TRANSITION_BLOCK_TAILCALL
306     .if (__PWTB_SaveFPArgs == 1)
307         RESTORE_FLOAT_ARGUMENT_REGISTERS  sp, __PWTB_FloatArgumentRegisters
308     .endif
309
310     RESTORE_CALLEESAVED_REGISTERS     sp, __PWTB_CalleeSavedRegisters
311
312     RESTORE_ARGUMENT_REGISTERS        sp, __PWTB_ArgumentRegisters
313
314     EPILOG_RESTORE_REG_PAIR fp, ra, __PWTB_CalleeSavedRegisters
315
316     EPILOG_STACK_FREE                 __PWTB_StackAlloc
317 .endm
318
319 // ------------------------------------------------------------------
320 // Macro to generate Redirection Stubs
321 //
322 // $reason : reason for redirection
323 //                     Eg. GCThreadControl
324 // NOTE: If you edit this macro, make sure you update GetCONTEXTFromRedirectedStubStackFrame.
325 // This function is used by both the personality routine and the debugger to retrieve the original CONTEXT.
326 .macro GenerateRedirectedHandledJITCaseStub reason
327 // TODO RISCV NYI
328     sw  ra, 0(zero)
329 .endm
330
331 //-----------------------------------------------------------------------------
332 // Macro used to check (in debug builds only) whether the stack is 16-bytes aligned (a requirement before calling
333 // out into C++/OS code). Invoke this directly after your prolog (if the stack frame size is fixed) or directly
334 // before a call (if you have a frame pointer and a dynamic stack). A breakpoint will be invoked if the stack
335 // is misaligned.
336 //
337 .macro  CHECK_STACK_ALIGNMENT
338
339 #ifdef _DEBUG
340         andi    t4, sp, 0xf
341         beq     t4, zero, 0f
342         EMIT_BREAKPOINT
343 0:
344 #endif
345 .endm