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
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
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
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 ldr x0, #0 ; return UNW_ESUCCESS
283 #elif __arm__ && !__APPLE__
286 @ extern int unw_getcontext(unw_context_t* thread_state)
289 @ thread_state pointer is in r0
291 @ Per EHABI #4.7 this only saves the core integer registers.
292 @ EHABI #7.4.5 notes that in general all VRS registers should be restored
293 @ however this is very hard to do for VFP registers because it is unknown
294 @ to the lbirary how many registers are implemented by the architecture.
295 @ Instead, VFP registers are demand saved by logic external to unw_getcontext.
298 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
299 @ 32bit thumb-2 restrictions for stm:
300 @ . the sp (r13) cannot be in the list
301 @ . the pc (r15) cannot be in the list in an STM instruction
305 str lr, [r0, #60] @ store return address as pc
306 mov r0, #0 @ return UNW_ESUCCESS
314 @ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values)
317 @ values pointer is in r0
320 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy)
321 stc p11, cr0, [r0], {#0x20} @ fstmiad r0, {d0-d15}
325 @ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values)
328 @ values pointer is in r0
331 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy)
332 stc p11, cr0, [r0], {#0x21} @ fstmiax r0, {d0-d15}
336 @ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values)
339 @ values pointer is in r0
342 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy)
343 @ VFP and iwMMX instructions are only available when compiling with the flags
344 @ that enable them. We don't want to do that in the library (because we don't
345 @ want the compiler to generate instructions that access those) but this is
346 @ only accessed if the personality routine needs these registers. Use of
347 @ these registers implies they are, actually, available on the target, so
348 @ it's ok to execute.
349 @ So, generate the instructions using the corresponding coprocessor mnemonic.
350 stcl p11, cr0, [r0], {#0x20} @ vldm r0, {d16-d31}
354 @ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)
357 @ values pointer is in r0
360 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy)
361 stcl p1, cr0, [r0], #8 @ wstrd wR0, [r0], #8
362 stcl p1, cr1, [r0], #8 @ wstrd wR1, [r0], #8
363 stcl p1, cr2, [r0], #8 @ wstrd wR2, [r0], #8
364 stcl p1, cr3, [r0], #8 @ wstrd wR3, [r0], #8
365 stcl p1, cr4, [r0], #8 @ wstrd wR4, [r0], #8
366 stcl p1, cr5, [r0], #8 @ wstrd wR5, [r0], #8
367 stcl p1, cr6, [r0], #8 @ wstrd wR6, [r0], #8
368 stcl p1, cr7, [r0], #8 @ wstrd wR7, [r0], #8
369 stcl p1, cr8, [r0], #8 @ wstrd wR8, [r0], #8
370 stcl p1, cr9, [r0], #8 @ wstrd wR9, [r0], #8
371 stcl p1, cr10, [r0], #8 @ wstrd wR10, [r0], #8
372 stcl p1, cr11, [r0], #8 @ wstrd wR11, [r0], #8
373 stcl p1, cr12, [r0], #8 @ wstrd wR12, [r0], #8
374 stcl p1, cr13, [r0], #8 @ wstrd wR13, [r0], #8
375 stcl p1, cr14, [r0], #8 @ wstrd wR14, [r0], #8
376 stcl p1, cr15, [r0], #8 @ wstrd wR15, [r0], #8
380 @ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values)
383 @ values pointer is in r0
386 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)
387 stc2 p1, cr8, [r0], #4 @ wstrw wCGR0, [r0], #4
388 stc2 p1, cr9, [r0], #4 @ wstrw wCGR1, [r0], #4
389 stc2 p1, cr10, [r0], #4 @ wstrw wCGR2, [r0], #4
390 stc2 p1, cr11, [r0], #4 @ wstrw wCGR3, [r0], #4