Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / libc++abi / trunk / src / Unwind / UnwindRegistersSave.S
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 __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 #
28 DEFINE_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 __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 #
63 DEFINE_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 __ppc__
91
92 ;
93 ; extern int unw_getcontext(unw_context_t* thread_state)
94 ;
95 ; On entry:
96 ;  thread_state pointer is in r3
97 ;
98 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
99   stw    r0,  8(r3)
100   mflr  r0
101   stw    r0,  0(r3)  ; store lr as ssr0
102   stw    r1, 12(r3)
103   stw    r2, 16(r3)
104   stw    r3, 20(r3)
105   stw    r4, 24(r3)
106   stw    r5, 28(r3)
107   stw    r6, 32(r3)
108   stw    r7, 36(r3)
109   stw    r8, 40(r3)
110   stw    r9, 44(r3)
111   stw     r10, 48(r3)
112   stw     r11, 52(r3)
113   stw     r12, 56(r3)
114   stw     r13, 60(r3)
115   stw     r14, 64(r3)
116   stw     r15, 68(r3)
117   stw     r16, 72(r3)
118   stw     r17, 76(r3)
119   stw     r18, 80(r3)
120   stw     r19, 84(r3)
121   stw     r20, 88(r3)
122   stw     r21, 92(r3)
123   stw     r22, 96(r3)
124   stw     r23,100(r3)
125   stw     r24,104(r3)
126   stw     r25,108(r3)
127   stw     r26,112(r3)
128   stw     r27,116(r3)
129   stw     r28,120(r3)
130   stw     r29,124(r3)
131   stw     r30,128(r3)
132   stw     r31,132(r3)
133
134   ; save VRSave register
135   mfspr  r0,256
136   stw    r0,156(r3)
137   ; save CR registers
138   mfcr  r0
139   stw    r0,136(r3)
140   ; save CTR register
141   mfctr  r0
142   stw    r0,148(r3)
143
144   ; save float registers
145   stfd    f0, 160(r3)
146   stfd    f1, 168(r3)
147   stfd    f2, 176(r3)
148   stfd    f3, 184(r3)
149   stfd    f4, 192(r3)
150   stfd    f5, 200(r3)
151   stfd    f6, 208(r3)
152   stfd    f7, 216(r3)
153   stfd    f8, 224(r3)
154   stfd    f9, 232(r3)
155   stfd    f10,240(r3)
156   stfd    f11,248(r3)
157   stfd    f12,256(r3)
158   stfd    f13,264(r3)
159   stfd    f14,272(r3)
160   stfd    f15,280(r3)
161   stfd    f16,288(r3)
162   stfd    f17,296(r3)
163   stfd    f18,304(r3)
164   stfd    f19,312(r3)
165   stfd    f20,320(r3)
166   stfd    f21,328(r3)
167   stfd    f22,336(r3)
168   stfd    f23,344(r3)
169   stfd    f24,352(r3)
170   stfd    f25,360(r3)
171   stfd    f26,368(r3)
172   stfd    f27,376(r3)
173   stfd    f28,384(r3)
174   stfd    f29,392(r3)
175   stfd    f30,400(r3)
176   stfd    f31,408(r3)
177
178
179   ; save vector registers
180
181   subi  r4,r1,16
182   rlwinm  r4,r4,0,0,27  ; mask low 4-bits
183   ; r4 is now a 16-byte aligned pointer into the red zone
184
185 #define SAVE_VECTOR_UNALIGNED(_vec, _offset) \
186   stvx  _vec,0,r4           @\
187   lwz    r5, 0(r4)          @\
188   stw    r5, _offset(r3)    @\
189   lwz    r5, 4(r4)          @\
190   stw    r5, _offset+4(r3)  @\
191   lwz    r5, 8(r4)          @\
192   stw    r5, _offset+8(r3)  @\
193   lwz    r5, 12(r4)         @\
194   stw    r5, _offset+12(r3)
195
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)
228
229   li  r3, 0    ; return UNW_ESUCCESS
230   blr
231
232
233 #elif __arm64__
234
235 ;
236 ; extern int unw_getcontext(unw_context_t* thread_state)
237 ;
238 ; On entry:
239 ;  thread_state pointer is in x0
240 ;
241   .p2align 2
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]
258   str    lr,      [x0, #0x0F0]
259   mov    x1,sp
260   str    x1,      [x0, #0x0F8]
261   str    lr,      [x0, #0x100]    ; store return address as pc
262   ; skip cpsr
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
281   ret
282
283 #elif __arm__ && !__APPLE__
284
285 @
286 @ extern int unw_getcontext(unw_context_t* thread_state)
287 @
288 @ On entry:
289 @  thread_state pointer is in r0
290
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.
296 @
297   .p2align 2
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
302   stm r0, {r0-r12}
303   str sp, [r0, #52]
304   str lr, [r0, #56]
305   str lr, [r0, #60]  @ store return address as pc
306   mov r0, #0         @ return UNW_ESUCCESS
307 #if _ARM_ARCH > 4
308   bx lr
309 #else
310   mov pc, lr
311 #endif
312
313 @
314 @ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values)
315 @
316 @ On entry:
317 @  values pointer is in r0
318 @
319   .p2align 2
320 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy)
321   stc p11, cr0, [r0], {#0x20}  @ fstmiad r0, {d0-d15}
322   mov pc, lr
323
324 @
325 @ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values)
326 @
327 @ On entry:
328 @  values pointer is in r0
329 @
330   .p2align 2
331 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy)
332   stc p11, cr0, [r0], {#0x21}  @ fstmiax r0, {d0-d15}
333   mov pc, lr
334
335 @
336 @ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values)
337 @
338 @ On entry:
339 @  values pointer is in r0
340 @
341   .p2align 2
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}
351   mov pc, lr
352
353 @
354 @ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)
355 @
356 @ On entry:
357 @  values pointer is in r0
358 @
359   .p2align 2
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
377   mov pc, lr
378
379 @
380 @ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values)
381 @
382 @ On entry:
383 @  values pointer is in r0
384 @
385   .p2align 2
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
391   mov pc, lr
392
393 #endif