1 //===------------------------ UnwindRegistersSave.S -----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
17 # extern int unw_getcontext(unw_context_t* thread_state)
21 # +-----------------------+
22 # + thread_state pointer +
23 # +-----------------------+
25 # +-----------------------+ <-- SP
28 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
39 movl %edx, 28(%eax) # store what sp was at call site as esp
43 movl %edx, 40(%eax) # store return address as eip
50 movl %edx, (%eax) # store original eax
52 xorl %eax, %eax # return UNW_ESUCCESS
55 #elif defined(__x86_64__)
58 # extern int unw_getcontext(unw_context_t* thread_state)
61 # thread_state pointer is in rdi
63 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
82 movq %rsi,128(%rdi) # store return address as rip
87 xorl %eax, %eax # return UNW_ESUCCESS
90 # elif defined(__mips__)
93 # extern int unw_getcontext(unw_context_t* thread_state)
95 # Just trap for the time being.
96 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
99 #elif defined(__ppc__)
102 ; extern int unw_getcontext(unw_context_t* thread_state)
105 ; thread_state pointer is in r3
107 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
110 stw r0, 0(r3) ; store lr as ssr0
143 ; save VRSave register
153 ; save float registers
188 ; save vector registers
191 rlwinm r4,r4,0,0,27 ; mask low 4-bits
192 ; r4 is now a 16-byte aligned pointer into the red zone
194 #define SAVE_VECTOR_UNALIGNED(_vec, _offset) \
197 stw r5, _offset(r3) @\
199 stw r5, _offset+4(r3) @\
201 stw r5, _offset+8(r3) @\
203 stw r5, _offset+12(r3)
205 SAVE_VECTOR_UNALIGNED( v0, 424+0x000)
206 SAVE_VECTOR_UNALIGNED( v1, 424+0x010)
207 SAVE_VECTOR_UNALIGNED( v2, 424+0x020)
208 SAVE_VECTOR_UNALIGNED( v3, 424+0x030)
209 SAVE_VECTOR_UNALIGNED( v4, 424+0x040)
210 SAVE_VECTOR_UNALIGNED( v5, 424+0x050)
211 SAVE_VECTOR_UNALIGNED( v6, 424+0x060)
212 SAVE_VECTOR_UNALIGNED( v7, 424+0x070)
213 SAVE_VECTOR_UNALIGNED( v8, 424+0x080)
214 SAVE_VECTOR_UNALIGNED( v9, 424+0x090)
215 SAVE_VECTOR_UNALIGNED(v10, 424+0x0A0)
216 SAVE_VECTOR_UNALIGNED(v11, 424+0x0B0)
217 SAVE_VECTOR_UNALIGNED(v12, 424+0x0C0)
218 SAVE_VECTOR_UNALIGNED(v13, 424+0x0D0)
219 SAVE_VECTOR_UNALIGNED(v14, 424+0x0E0)
220 SAVE_VECTOR_UNALIGNED(v15, 424+0x0F0)
221 SAVE_VECTOR_UNALIGNED(v16, 424+0x100)
222 SAVE_VECTOR_UNALIGNED(v17, 424+0x110)
223 SAVE_VECTOR_UNALIGNED(v18, 424+0x120)
224 SAVE_VECTOR_UNALIGNED(v19, 424+0x130)
225 SAVE_VECTOR_UNALIGNED(v20, 424+0x140)
226 SAVE_VECTOR_UNALIGNED(v21, 424+0x150)
227 SAVE_VECTOR_UNALIGNED(v22, 424+0x160)
228 SAVE_VECTOR_UNALIGNED(v23, 424+0x170)
229 SAVE_VECTOR_UNALIGNED(v24, 424+0x180)
230 SAVE_VECTOR_UNALIGNED(v25, 424+0x190)
231 SAVE_VECTOR_UNALIGNED(v26, 424+0x1A0)
232 SAVE_VECTOR_UNALIGNED(v27, 424+0x1B0)
233 SAVE_VECTOR_UNALIGNED(v28, 424+0x1C0)
234 SAVE_VECTOR_UNALIGNED(v29, 424+0x1D0)
235 SAVE_VECTOR_UNALIGNED(v30, 424+0x1E0)
236 SAVE_VECTOR_UNALIGNED(v31, 424+0x1F0)
238 li r3, 0 ; return UNW_ESUCCESS
242 #elif defined(__arm64__) || defined(__aarch64__)
245 // extern int unw_getcontext(unw_context_t* thread_state)
248 // thread_state pointer is in x0
251 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
252 stp x0, x1, [x0, #0x000]
253 stp x2, x3, [x0, #0x010]
254 stp x4, x5, [x0, #0x020]
255 stp x6, x7, [x0, #0x030]
256 stp x8, x9, [x0, #0x040]
257 stp x10,x11, [x0, #0x050]
258 stp x12,x13, [x0, #0x060]
259 stp x14,x15, [x0, #0x070]
260 stp x16,x17, [x0, #0x080]
261 stp x18,x19, [x0, #0x090]
262 stp x20,x21, [x0, #0x0A0]
263 stp x22,x23, [x0, #0x0B0]
264 stp x24,x25, [x0, #0x0C0]
265 stp x26,x27, [x0, #0x0D0]
266 stp x28,x29, [x0, #0x0E0]
267 str x30, [x0, #0x0F0]
270 str x30, [x0, #0x100] // store return address as pc
272 stp d0, d1, [x0, #0x110]
273 stp d2, d3, [x0, #0x120]
274 stp d4, d5, [x0, #0x130]
275 stp d6, d7, [x0, #0x140]
276 stp d8, d9, [x0, #0x150]
277 stp d10,d11, [x0, #0x160]
278 stp d12,d13, [x0, #0x170]
279 stp d14,d15, [x0, #0x180]
280 stp d16,d17, [x0, #0x190]
281 stp d18,d19, [x0, #0x1A0]
282 stp d20,d21, [x0, #0x1B0]
283 stp d22,d23, [x0, #0x1C0]
284 stp d24,d25, [x0, #0x1D0]
285 stp d26,d27, [x0, #0x1E0]
286 stp d28,d29, [x0, #0x1F0]
287 str d30, [x0, #0x200]
288 str d31, [x0, #0x208]
289 mov x0, #0 // return UNW_ESUCCESS
292 #elif defined(__arm__) && !defined(__APPLE__)
294 #if !defined(__ARM_ARCH_ISA_ARM)
299 @ extern int unw_getcontext(unw_context_t* thread_state)
302 @ thread_state pointer is in r0
304 @ Per EHABI #4.7 this only saves the core integer registers.
305 @ EHABI #7.4.5 notes that in general all VRS registers should be restored
306 @ however this is very hard to do for VFP registers because it is unknown
307 @ to the library how many registers are implemented by the architecture.
308 @ Instead, VFP registers are demand saved by logic external to unw_getcontext.
311 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
312 #if !defined(__ARM_ARCH_ISA_ARM)
318 str r3, [r0, #60] @ store return address as pc
320 @ 32bit thumb-2 restrictions for stm:
321 @ . the sp (r13) cannot be in the list
322 @ . the pc (r15) cannot be in the list in an STM instruction
326 str lr, [r0, #60] @ store return address as pc
328 #if __ARM_ARCH_ISA_THUMB == 1
329 @ T1 does not have a non-cpsr-clobbering register-zeroing instruction.
330 @ It is safe to use here though because we are about to return, and cpsr is
331 @ not expected to be preserved.
332 movs r0, #0 @ return UNW_ESUCCESS
334 mov r0, #0 @ return UNW_ESUCCESS
339 @ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values)
342 @ values pointer is in r0
346 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy)
351 @ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values)
354 @ values pointer is in r0
358 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy)
359 vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia
363 @ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values)
366 @ values pointer is in r0
370 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy)
371 @ VFP and iwMMX instructions are only available when compiling with the flags
372 @ that enable them. We do not want to do that in the library (because we do not
373 @ want the compiler to generate instructions that access those) but this is
374 @ only accessed if the personality routine needs these registers. Use of
375 @ these registers implies they are, actually, available on the target, so
376 @ it's ok to execute.
377 @ So, generate the instructions using the corresponding coprocessor mnemonic.
382 @ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)
385 @ values pointer is in r0
388 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy)
389 #if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
390 stcl p1, cr0, [r0], #8 @ wstrd wR0, [r0], #8
391 stcl p1, cr1, [r0], #8 @ wstrd wR1, [r0], #8
392 stcl p1, cr2, [r0], #8 @ wstrd wR2, [r0], #8
393 stcl p1, cr3, [r0], #8 @ wstrd wR3, [r0], #8
394 stcl p1, cr4, [r0], #8 @ wstrd wR4, [r0], #8
395 stcl p1, cr5, [r0], #8 @ wstrd wR5, [r0], #8
396 stcl p1, cr6, [r0], #8 @ wstrd wR6, [r0], #8
397 stcl p1, cr7, [r0], #8 @ wstrd wR7, [r0], #8
398 stcl p1, cr8, [r0], #8 @ wstrd wR8, [r0], #8
399 stcl p1, cr9, [r0], #8 @ wstrd wR9, [r0], #8
400 stcl p1, cr10, [r0], #8 @ wstrd wR10, [r0], #8
401 stcl p1, cr11, [r0], #8 @ wstrd wR11, [r0], #8
402 stcl p1, cr12, [r0], #8 @ wstrd wR12, [r0], #8
403 stcl p1, cr13, [r0], #8 @ wstrd wR13, [r0], #8
404 stcl p1, cr14, [r0], #8 @ wstrd wR14, [r0], #8
405 stcl p1, cr15, [r0], #8 @ wstrd wR15, [r0], #8
410 @ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values)
413 @ values pointer is in r0
416 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)
417 #if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
418 stc2 p1, cr8, [r0], #4 @ wstrw wCGR0, [r0], #4
419 stc2 p1, cr9, [r0], #4 @ wstrw wCGR1, [r0], #4
420 stc2 p1, cr10, [r0], #4 @ wstrw wCGR2, [r0], #4
421 stc2 p1, cr11, [r0], #4 @ wstrw wCGR3, [r0], #4
425 #elif defined(__or1k__)
428 # extern int unw_getcontext(unw_context_t* thread_state)
431 # thread_state pointer is in r3
433 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
467 #elif defined(__riscv__)