1//===------------------------ UnwindRegistersSave.S -----------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is dual licensed under the MIT and the University of Illinois Open 6// Source Licenses. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "assembly.h" 11 12 .text 13 14#if defined(__i386__) 15 16# 17# extern int unw_getcontext(unw_context_t* thread_state) 18# 19# On entry: 20# + + 21# +-----------------------+ 22# + thread_state pointer + 23# +-----------------------+ 24# + return address + 25# +-----------------------+ <-- SP 26# + + 27# 28DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) 29 push %eax 30 movl 8(%esp), %eax 31 movl %ebx, 4(%eax) 32 movl %ecx, 8(%eax) 33 movl %edx, 12(%eax) 34 movl %edi, 16(%eax) 35 movl %esi, 20(%eax) 36 movl %ebp, 24(%eax) 37 movl %esp, %edx 38 addl $8, %edx 39 movl %edx, 28(%eax) # store what sp was at call site as esp 40 # skip ss 41 # skip eflags 42 movl 4(%esp), %edx 43 movl %edx, 40(%eax) # store return address as eip 44 # skip cs 45 # skip ds 46 # skip es 47 # skip fs 48 # skip gs 49 movl (%esp), %edx 50 movl %edx, (%eax) # store original eax 51 popl %eax 52 xorl %eax, %eax # return UNW_ESUCCESS 53 ret 54 55#elif defined(__x86_64__) 56 57# 58# extern int unw_getcontext(unw_context_t* thread_state) 59# 60# On entry: 61# thread_state pointer is in rdi 62# 63DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) 64 movq %rax, (%rdi) 65 movq %rbx, 8(%rdi) 66 movq %rcx, 16(%rdi) 67 movq %rdx, 24(%rdi) 68 movq %rdi, 32(%rdi) 69 movq %rsi, 40(%rdi) 70 movq %rbp, 48(%rdi) 71 movq %rsp, 56(%rdi) 72 addq $8, 56(%rdi) 73 movq %r8, 64(%rdi) 74 movq %r9, 72(%rdi) 75 movq %r10, 80(%rdi) 76 movq %r11, 88(%rdi) 77 movq %r12, 96(%rdi) 78 movq %r13,104(%rdi) 79 movq %r14,112(%rdi) 80 movq %r15,120(%rdi) 81 movq (%rsp),%rsi 82 movq %rsi,128(%rdi) # store return address as rip 83 # skip rflags 84 # skip cs 85 # skip fs 86 # skip gs 87 xorl %eax, %eax # return UNW_ESUCCESS 88 ret 89 90# elif defined(__mips__) 91 92# 93# extern int unw_getcontext(unw_context_t* thread_state) 94# 95# Just trap for the time being. 96DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) 97 teq $0, $0 98 99#elif defined(__ppc__) 100 101; 102; extern int unw_getcontext(unw_context_t* thread_state) 103; 104; On entry: 105; thread_state pointer is in r3 106; 107DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) 108 stw r0, 8(r3) 109 mflr r0 110 stw r0, 0(r3) ; store lr as ssr0 111 stw r1, 12(r3) 112 stw r2, 16(r3) 113 stw r3, 20(r3) 114 stw r4, 24(r3) 115 stw r5, 28(r3) 116 stw r6, 32(r3) 117 stw r7, 36(r3) 118 stw r8, 40(r3) 119 stw r9, 44(r3) 120 stw r10, 48(r3) 121 stw r11, 52(r3) 122 stw r12, 56(r3) 123 stw r13, 60(r3) 124 stw r14, 64(r3) 125 stw r15, 68(r3) 126 stw r16, 72(r3) 127 stw r17, 76(r3) 128 stw r18, 80(r3) 129 stw r19, 84(r3) 130 stw r20, 88(r3) 131 stw r21, 92(r3) 132 stw r22, 96(r3) 133 stw r23,100(r3) 134 stw r24,104(r3) 135 stw r25,108(r3) 136 stw r26,112(r3) 137 stw r27,116(r3) 138 stw r28,120(r3) 139 stw r29,124(r3) 140 stw r30,128(r3) 141 stw r31,132(r3) 142 143 ; save VRSave register 144 mfspr r0,256 145 stw r0,156(r3) 146 ; save CR registers 147 mfcr r0 148 stw r0,136(r3) 149 ; save CTR register 150 mfctr r0 151 stw r0,148(r3) 152 153 ; save float registers 154 stfd f0, 160(r3) 155 stfd f1, 168(r3) 156 stfd f2, 176(r3) 157 stfd f3, 184(r3) 158 stfd f4, 192(r3) 159 stfd f5, 200(r3) 160 stfd f6, 208(r3) 161 stfd f7, 216(r3) 162 stfd f8, 224(r3) 163 stfd f9, 232(r3) 164 stfd f10,240(r3) 165 stfd f11,248(r3) 166 stfd f12,256(r3) 167 stfd f13,264(r3) 168 stfd f14,272(r3) 169 stfd f15,280(r3) 170 stfd f16,288(r3) 171 stfd f17,296(r3) 172 stfd f18,304(r3) 173 stfd f19,312(r3) 174 stfd f20,320(r3) 175 stfd f21,328(r3) 176 stfd f22,336(r3) 177 stfd f23,344(r3) 178 stfd f24,352(r3) 179 stfd f25,360(r3) 180 stfd f26,368(r3) 181 stfd f27,376(r3) 182 stfd f28,384(r3) 183 stfd f29,392(r3) 184 stfd f30,400(r3) 185 stfd f31,408(r3) 186 187 188 ; save vector registers 189 190 subi r4,r1,16 191 rlwinm r4,r4,0,0,27 ; mask low 4-bits 192 ; r4 is now a 16-byte aligned pointer into the red zone 193 194#define SAVE_VECTOR_UNALIGNED(_vec, _offset) \ 195 stvx _vec,0,r4 @\ 196 lwz r5, 0(r4) @\ 197 stw r5, _offset(r3) @\ 198 lwz r5, 4(r4) @\ 199 stw r5, _offset+4(r3) @\ 200 lwz r5, 8(r4) @\ 201 stw r5, _offset+8(r3) @\ 202 lwz r5, 12(r4) @\ 203 stw r5, _offset+12(r3) 204 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) 237 238 li r3, 0 ; return UNW_ESUCCESS 239 blr 240 241 242#elif defined(__arm64__) || defined(__aarch64__) 243 244// 245// extern int unw_getcontext(unw_context_t* thread_state) 246// 247// On entry: 248// thread_state pointer is in x0 249// 250 .p2align 2 251DEFINE_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,fp, [x0, #0x0E0] 267 str lr, [x0, #0x0F0] 268 mov x1,sp 269 str x1, [x0, #0x0F8] 270 str lr, [x0, #0x100] // store return address as pc 271 // skip cpsr 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 290 ret 291 292#elif defined(__arm__) && !defined(__APPLE__) 293 294#if !defined(__ARM_ARCH_ISA_ARM) 295 .thumb 296#endif 297 298@ 299@ extern int unw_getcontext(unw_context_t* thread_state) 300@ 301@ On entry: 302@ thread_state pointer is in r0 303@ 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. 309@ 310 .p2align 2 311DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) 312#if !defined(__ARM_ARCH_ISA_ARM) 313 stm r0, {r0-r7} 314 mov r2, sp 315 mov r3, lr 316 str r2, [r0, #52] 317 str r3, [r0, #56] 318 str r3, [r0, #60] @ store return address as pc 319#else 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 323 stm r0, {r0-r12} 324 str sp, [r0, #52] 325 str lr, [r0, #56] 326 str lr, [r0, #60] @ store return address as pc 327#endif 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 333#else 334 mov r0, #0 @ return UNW_ESUCCESS 335#endif 336 JMP(lr) 337 338@ 339@ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values) 340@ 341@ On entry: 342@ values pointer is in r0 343@ 344 .p2align 2 345 .fpu vfpv3-d16 346DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy) 347 vstmia r0, {d0-d15} 348 JMP(lr) 349 350@ 351@ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values) 352@ 353@ On entry: 354@ values pointer is in r0 355@ 356 .p2align 2 357 .fpu vfpv3-d16 358DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy) 359 vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia 360 JMP(lr) 361 362@ 363@ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values) 364@ 365@ On entry: 366@ values pointer is in r0 367@ 368 .p2align 2 369 .fpu vfpv3 370DEFINE_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. 378 vstmia r0, {d16-d31} 379 JMP(lr) 380 381@ 382@ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values) 383@ 384@ On entry: 385@ values pointer is in r0 386@ 387 .p2align 2 388DEFINE_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 406#endif 407 JMP(lr) 408 409@ 410@ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values) 411@ 412@ On entry: 413@ values pointer is in r0 414@ 415 .p2align 2 416DEFINE_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 422#endif 423 JMP(lr) 424 425#elif defined(__or1k__) 426 427# 428# extern int unw_getcontext(unw_context_t* thread_state) 429# 430# On entry: 431# thread_state pointer is in r3 432# 433DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) 434 l.sw 0(r3), r0 435 l.sw 4(r3), r1 436 l.sw 8(r3), r2 437 l.sw 12(r3), r3 438 l.sw 16(r3), r4 439 l.sw 20(r3), r5 440 l.sw 24(r3), r6 441 l.sw 28(r3), r7 442 l.sw 32(r3), r8 443 l.sw 36(r3), r9 444 l.sw 40(r3), r10 445 l.sw 44(r3), r11 446 l.sw 48(r3), r12 447 l.sw 52(r3), r13 448 l.sw 56(r3), r14 449 l.sw 60(r3), r15 450 l.sw 64(r3), r16 451 l.sw 68(r3), r17 452 l.sw 72(r3), r18 453 l.sw 76(r3), r19 454 l.sw 80(r3), r20 455 l.sw 84(r3), r21 456 l.sw 88(r3), r22 457 l.sw 92(r3), r23 458 l.sw 96(r3), r24 459 l.sw 100(r3), r25 460 l.sw 104(r3), r26 461 l.sw 108(r3), r27 462 l.sw 112(r3), r28 463 l.sw 116(r3), r29 464 l.sw 120(r3), r30 465 l.sw 124(r3), r31 466#endif 467