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(__ppc__)
93 ; extern int unw_getcontext(unw_context_t* thread_state)
96 ; thread_state pointer is in r3
98 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
101 stw r0, 0(r3) ; store lr as ssr0
134 ; save VRSave register
144 ; save float registers
179 ; save vector registers
182 rlwinm r4,r4,0,0,27 ; mask low 4-bits
183 ; r4 is now a 16-byte aligned pointer into the red zone
185 #define SAVE_VECTOR_UNALIGNED(_vec, _offset) \
188 stw r5, _offset(r3) @\
190 stw r5, _offset+4(r3) @\
192 stw r5, _offset+8(r3) @\
194 stw r5, _offset+12(r3)
196 SAVE_VECTOR_UNALIGNED( v0, 424+0x000)
197 SAVE_VECTOR_UNALIGNED( v1, 424+0x010)
198 SAVE_VECTOR_UNALIGNED( v2, 424+0x020)
199 SAVE_VECTOR_UNALIGNED( v3, 424+0x030)
200 SAVE_VECTOR_UNALIGNED( v4, 424+0x040)
201 SAVE_VECTOR_UNALIGNED( v5, 424+0x050)
202 SAVE_VECTOR_UNALIGNED( v6, 424+0x060)
203 SAVE_VECTOR_UNALIGNED( v7, 424+0x070)
204 SAVE_VECTOR_UNALIGNED( v8, 424+0x080)
205 SAVE_VECTOR_UNALIGNED( v9, 424+0x090)
206 SAVE_VECTOR_UNALIGNED(v10, 424+0x0A0)
207 SAVE_VECTOR_UNALIGNED(v11, 424+0x0B0)
208 SAVE_VECTOR_UNALIGNED(v12, 424+0x0C0)
209 SAVE_VECTOR_UNALIGNED(v13, 424+0x0D0)
210 SAVE_VECTOR_UNALIGNED(v14, 424+0x0E0)
211 SAVE_VECTOR_UNALIGNED(v15, 424+0x0F0)
212 SAVE_VECTOR_UNALIGNED(v16, 424+0x100)
213 SAVE_VECTOR_UNALIGNED(v17, 424+0x110)
214 SAVE_VECTOR_UNALIGNED(v18, 424+0x120)
215 SAVE_VECTOR_UNALIGNED(v19, 424+0x130)
216 SAVE_VECTOR_UNALIGNED(v20, 424+0x140)
217 SAVE_VECTOR_UNALIGNED(v21, 424+0x150)
218 SAVE_VECTOR_UNALIGNED(v22, 424+0x160)
219 SAVE_VECTOR_UNALIGNED(v23, 424+0x170)
220 SAVE_VECTOR_UNALIGNED(v24, 424+0x180)
221 SAVE_VECTOR_UNALIGNED(v25, 424+0x190)
222 SAVE_VECTOR_UNALIGNED(v26, 424+0x1A0)
223 SAVE_VECTOR_UNALIGNED(v27, 424+0x1B0)
224 SAVE_VECTOR_UNALIGNED(v28, 424+0x1C0)
225 SAVE_VECTOR_UNALIGNED(v29, 424+0x1D0)
226 SAVE_VECTOR_UNALIGNED(v30, 424+0x1E0)
227 SAVE_VECTOR_UNALIGNED(v31, 424+0x1F0)
229 li r3, 0 ; return UNW_ESUCCESS
233 #elif defined(__arm64__) || defined(__aarch64__)
236 // extern int unw_getcontext(unw_context_t* thread_state)
239 // thread_state pointer is in x0
242 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
243 stp x0, x1, [x0, #0x000]
244 stp x2, x3, [x0, #0x010]
245 stp x4, x5, [x0, #0x020]
246 stp x6, x7, [x0, #0x030]
247 stp x8, x9, [x0, #0x040]
248 stp x10,x11, [x0, #0x050]
249 stp x12,x13, [x0, #0x060]
250 stp x14,x15, [x0, #0x070]
251 stp x16,x17, [x0, #0x080]
252 stp x18,x19, [x0, #0x090]
253 stp x20,x21, [x0, #0x0A0]
254 stp x22,x23, [x0, #0x0B0]
255 stp x24,x25, [x0, #0x0C0]
256 stp x26,x27, [x0, #0x0D0]
257 stp x28,fp, [x0, #0x0E0]
261 str lr, [x0, #0x100] // store return address as pc
263 stp d0, d1, [x0, #0x110]
264 stp d2, d3, [x0, #0x120]
265 stp d4, d5, [x0, #0x130]
266 stp d6, d7, [x0, #0x140]
267 stp d8, d9, [x0, #0x150]
268 stp d10,d11, [x0, #0x160]
269 stp d12,d13, [x0, #0x170]
270 stp d14,d15, [x0, #0x180]
271 stp d16,d17, [x0, #0x190]
272 stp d18,d19, [x0, #0x1A0]
273 stp d20,d21, [x0, #0x1B0]
274 stp d22,d23, [x0, #0x1C0]
275 stp d24,d25, [x0, #0x1D0]
276 stp d26,d27, [x0, #0x1E0]
277 stp d28,d29, [x0, #0x1F0]
278 str d30, [x0, #0x200]
279 str d31, [x0, #0x208]
280 mov x0, #0 // return UNW_ESUCCESS
283 #elif defined(__arm__) && !defined(__APPLE__)
285 #if !defined(__ARM_ARCH_ISA_ARM)
290 @ extern int unw_getcontext(unw_context_t* thread_state)
293 @ thread_state pointer is in r0
295 @ Per EHABI #4.7 this only saves the core integer registers.
296 @ EHABI #7.4.5 notes that in general all VRS registers should be restored
297 @ however this is very hard to do for VFP registers because it is unknown
298 @ to the library how many registers are implemented by the architecture.
299 @ Instead, VFP registers are demand saved by logic external to unw_getcontext.
302 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
303 #if !defined(__ARM_ARCH_ISA_ARM)
309 str r3, [r0, #60] @ store return address as pc
311 @ 32bit thumb-2 restrictions for stm:
312 @ . the sp (r13) cannot be in the list
313 @ . the pc (r15) cannot be in the list in an STM instruction
317 str lr, [r0, #60] @ store return address as pc
319 #if __ARM_ARCH_ISA_THUMB == 1
320 @ T1 does not have a non-cpsr-clobbering register-zeroing instruction.
321 @ It is safe to use here though because we are about to return, and cpsr is
322 @ not expected to be preserved.
323 movs r0, #0 @ return UNW_ESUCCESS
325 mov r0, #0 @ return UNW_ESUCCESS
330 @ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values)
333 @ values pointer is in r0
337 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy)
342 @ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values)
345 @ values pointer is in r0
349 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy)
350 vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia
354 @ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values)
357 @ values pointer is in r0
361 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy)
362 @ VFP and iwMMX instructions are only available when compiling with the flags
363 @ that enable them. We do not want to do that in the library (because we do not
364 @ want the compiler to generate instructions that access those) but this is
365 @ only accessed if the personality routine needs these registers. Use of
366 @ these registers implies they are, actually, available on the target, so
367 @ it's ok to execute.
368 @ So, generate the instructions using the corresponding coprocessor mnemonic.
373 @ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)
376 @ values pointer is in r0
379 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy)
380 #if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
381 stcl p1, cr0, [r0], #8 @ wstrd wR0, [r0], #8
382 stcl p1, cr1, [r0], #8 @ wstrd wR1, [r0], #8
383 stcl p1, cr2, [r0], #8 @ wstrd wR2, [r0], #8
384 stcl p1, cr3, [r0], #8 @ wstrd wR3, [r0], #8
385 stcl p1, cr4, [r0], #8 @ wstrd wR4, [r0], #8
386 stcl p1, cr5, [r0], #8 @ wstrd wR5, [r0], #8
387 stcl p1, cr6, [r0], #8 @ wstrd wR6, [r0], #8
388 stcl p1, cr7, [r0], #8 @ wstrd wR7, [r0], #8
389 stcl p1, cr8, [r0], #8 @ wstrd wR8, [r0], #8
390 stcl p1, cr9, [r0], #8 @ wstrd wR9, [r0], #8
391 stcl p1, cr10, [r0], #8 @ wstrd wR10, [r0], #8
392 stcl p1, cr11, [r0], #8 @ wstrd wR11, [r0], #8
393 stcl p1, cr12, [r0], #8 @ wstrd wR12, [r0], #8
394 stcl p1, cr13, [r0], #8 @ wstrd wR13, [r0], #8
395 stcl p1, cr14, [r0], #8 @ wstrd wR14, [r0], #8
396 stcl p1, cr15, [r0], #8 @ wstrd wR15, [r0], #8
401 @ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values)
404 @ values pointer is in r0
407 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)
408 #if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
409 stc2 p1, cr8, [r0], #4 @ wstrw wCGR0, [r0], #4
410 stc2 p1, cr9, [r0], #4 @ wstrw wCGR1, [r0], #4
411 stc2 p1, cr10, [r0], #4 @ wstrw wCGR2, [r0], #4
412 stc2 p1, cr11, [r0], #4 @ wstrw wCGR3, [r0], #4
416 #elif defined(__or1k__)
419 # extern int unw_getcontext(unw_context_t* thread_state)
422 # thread_state pointer is in r3
424 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)