Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/libunwind/src/UnwindRegistersRestore.S
96309 views
1
//===----------------------------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "assembly.h"
10
11
#define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
12
#define FROM_16_TO_31 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
13
14
#define FROM_0_TO_31 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
15
#define FROM_32_TO_63 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63
16
17
#if defined(_AIX)
18
.toc
19
#else
20
.text
21
#endif
22
23
#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__)
24
25
#if defined(__i386__)
26
DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto)
27
#
28
# extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *);
29
#
30
# On entry:
31
# + +
32
# +-----------------------+
33
# + thread_state pointer +
34
# +-----------------------+
35
# + return address +
36
# +-----------------------+ <-- SP
37
# + +
38
39
_LIBUNWIND_CET_ENDBR
40
movl 4(%esp), %eax
41
# set up eax and ret on new stack location
42
movl 28(%eax), %edx # edx holds new stack pointer
43
subl $8,%edx
44
movl %edx, 28(%eax)
45
movl 0(%eax), %ebx
46
movl %ebx, 0(%edx)
47
movl 40(%eax), %ebx
48
movl %ebx, 4(%edx)
49
# we now have ret and eax pushed onto where new stack will be
50
# restore all registers
51
movl 4(%eax), %ebx
52
movl 8(%eax), %ecx
53
movl 12(%eax), %edx
54
movl 16(%eax), %edi
55
movl 20(%eax), %esi
56
movl 24(%eax), %ebp
57
movl 28(%eax), %esp
58
# skip ss
59
# skip eflags
60
pop %eax # eax was already pushed on new stack
61
pop %ecx
62
jmp *%ecx
63
# skip cs
64
# skip ds
65
# skip es
66
# skip fs
67
# skip gs
68
69
#elif defined(__x86_64__)
70
71
DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto)
72
#
73
# extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *);
74
#
75
#if defined(_WIN64)
76
# On entry, thread_state pointer is in rcx; move it into rdi
77
# to share restore code below. Since this routine restores and
78
# overwrites all registers, we can use the same registers for
79
# pointers and temporaries as on unix even though win64 normally
80
# mustn't clobber some of them.
81
movq %rcx, %rdi
82
#else
83
# On entry, thread_state pointer is in rdi
84
#endif
85
86
_LIBUNWIND_CET_ENDBR
87
movq 56(%rdi), %rax # rax holds new stack pointer
88
subq $16, %rax
89
movq %rax, 56(%rdi)
90
movq 32(%rdi), %rbx # store new rdi on new stack
91
movq %rbx, 0(%rax)
92
movq 128(%rdi), %rbx # store new rip on new stack
93
movq %rbx, 8(%rax)
94
# restore all registers
95
movq 0(%rdi), %rax
96
movq 8(%rdi), %rbx
97
movq 16(%rdi), %rcx
98
movq 24(%rdi), %rdx
99
# restore rdi later
100
movq 40(%rdi), %rsi
101
movq 48(%rdi), %rbp
102
# restore rsp later
103
movq 64(%rdi), %r8
104
movq 72(%rdi), %r9
105
movq 80(%rdi), %r10
106
movq 88(%rdi), %r11
107
movq 96(%rdi), %r12
108
movq 104(%rdi), %r13
109
movq 112(%rdi), %r14
110
movq 120(%rdi), %r15
111
# skip rflags
112
# skip cs
113
# skip fs
114
# skip gs
115
116
#if defined(_WIN64)
117
movdqu 176(%rdi),%xmm0
118
movdqu 192(%rdi),%xmm1
119
movdqu 208(%rdi),%xmm2
120
movdqu 224(%rdi),%xmm3
121
movdqu 240(%rdi),%xmm4
122
movdqu 256(%rdi),%xmm5
123
movdqu 272(%rdi),%xmm6
124
movdqu 288(%rdi),%xmm7
125
movdqu 304(%rdi),%xmm8
126
movdqu 320(%rdi),%xmm9
127
movdqu 336(%rdi),%xmm10
128
movdqu 352(%rdi),%xmm11
129
movdqu 368(%rdi),%xmm12
130
movdqu 384(%rdi),%xmm13
131
movdqu 400(%rdi),%xmm14
132
movdqu 416(%rdi),%xmm15
133
#endif
134
movq 56(%rdi), %rsp # cut back rsp to new location
135
pop %rdi # rdi was saved here earlier
136
pop %rcx
137
jmpq *%rcx
138
139
140
#elif defined(__powerpc64__)
141
142
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)
143
//
144
// void libunwind::Registers_ppc64::jumpto()
145
//
146
// On entry:
147
// thread_state pointer is in r3
148
//
149
150
// load register (GPR)
151
#define PPC64_LR(n) \
152
ld n, (8 * (n + 2))(3)
153
154
// restore integral registers
155
// skip r0 for now
156
// skip r1 for now
157
PPC64_LR(2)
158
// skip r3 for now
159
// skip r4 for now
160
// skip r5 for now
161
PPC64_LR(6)
162
PPC64_LR(7)
163
PPC64_LR(8)
164
PPC64_LR(9)
165
PPC64_LR(10)
166
PPC64_LR(11)
167
PPC64_LR(12)
168
PPC64_LR(13)
169
PPC64_LR(14)
170
PPC64_LR(15)
171
PPC64_LR(16)
172
PPC64_LR(17)
173
PPC64_LR(18)
174
PPC64_LR(19)
175
PPC64_LR(20)
176
PPC64_LR(21)
177
PPC64_LR(22)
178
PPC64_LR(23)
179
PPC64_LR(24)
180
PPC64_LR(25)
181
PPC64_LR(26)
182
PPC64_LR(27)
183
PPC64_LR(28)
184
PPC64_LR(29)
185
PPC64_LR(30)
186
PPC64_LR(31)
187
188
#if defined(__VSX__)
189
190
// restore VS registers
191
// (note that this also restores floating point registers and V registers,
192
// because part of VS is mapped to these registers)
193
194
addi 4, 3, PPC64_OFFS_FP
195
196
// load VS register
197
#ifdef __LITTLE_ENDIAN__
198
// For little-endian targets, we need a swap since lxvd2x will load the register
199
// in the incorrect doubleword order.
200
// FIXME: when supporting targets older than Power9 on LE is no longer required,
201
// this can be changed to simply `lxv n, (16 * n)(4)`.
202
#define PPC64_LVS(n) \
203
lxvd2x n, 0, 4 ;\
204
xxswapd n, n ;\
205
addi 4, 4, 16
206
#else
207
#define PPC64_LVS(n) \
208
lxvd2x n, 0, 4 ;\
209
addi 4, 4, 16
210
#endif
211
212
// restore the first 32 VS regs (and also all floating point regs)
213
PPC64_LVS(0)
214
PPC64_LVS(1)
215
PPC64_LVS(2)
216
PPC64_LVS(3)
217
PPC64_LVS(4)
218
PPC64_LVS(5)
219
PPC64_LVS(6)
220
PPC64_LVS(7)
221
PPC64_LVS(8)
222
PPC64_LVS(9)
223
PPC64_LVS(10)
224
PPC64_LVS(11)
225
PPC64_LVS(12)
226
PPC64_LVS(13)
227
PPC64_LVS(14)
228
PPC64_LVS(15)
229
PPC64_LVS(16)
230
PPC64_LVS(17)
231
PPC64_LVS(18)
232
PPC64_LVS(19)
233
PPC64_LVS(20)
234
PPC64_LVS(21)
235
PPC64_LVS(22)
236
PPC64_LVS(23)
237
PPC64_LVS(24)
238
PPC64_LVS(25)
239
PPC64_LVS(26)
240
PPC64_LVS(27)
241
PPC64_LVS(28)
242
PPC64_LVS(29)
243
PPC64_LVS(30)
244
PPC64_LVS(31)
245
246
#ifdef __LITTLE_ENDIAN__
247
#define PPC64_CLVS_RESTORE(n) \
248
addi 4, 3, PPC64_OFFS_FP + n * 16 ;\
249
lxvd2x n, 0, 4 ;\
250
xxswapd n, n
251
#else
252
#define PPC64_CLVS_RESTORE(n) \
253
addi 4, 3, PPC64_OFFS_FP + n * 16 ;\
254
lxvd2x n, 0, 4
255
#endif
256
257
#if !defined(_AIX)
258
// use VRSAVE to conditionally restore the remaining VS regs, that are
259
// where the V regs are mapped. In the AIX ABI, VRSAVE is not used.
260
ld 5, PPC64_OFFS_VRSAVE(3) // test VRsave
261
cmpwi 5, 0
262
beq Lnovec
263
264
// conditionally load VS
265
#define PPC64_CLVSl(n) \
266
andis. 0, 5, (1 PPC_LEFT_SHIFT(47-n)) ;\
267
beq Ldone##n ;\
268
PPC64_CLVS_RESTORE(n) ;\
269
Ldone##n:
270
271
#define PPC64_CLVSh(n) \
272
andi. 0, 5, (1 PPC_LEFT_SHIFT(63-n)) ;\
273
beq Ldone##n ;\
274
PPC64_CLVS_RESTORE(n) ;\
275
Ldone##n:
276
277
#else
278
279
#define PPC64_CLVSl(n) PPC64_CLVS_RESTORE(n)
280
#define PPC64_CLVSh(n) PPC64_CLVS_RESTORE(n)
281
282
#endif // !defined(_AIX)
283
284
PPC64_CLVSl(32)
285
PPC64_CLVSl(33)
286
PPC64_CLVSl(34)
287
PPC64_CLVSl(35)
288
PPC64_CLVSl(36)
289
PPC64_CLVSl(37)
290
PPC64_CLVSl(38)
291
PPC64_CLVSl(39)
292
PPC64_CLVSl(40)
293
PPC64_CLVSl(41)
294
PPC64_CLVSl(42)
295
PPC64_CLVSl(43)
296
PPC64_CLVSl(44)
297
PPC64_CLVSl(45)
298
PPC64_CLVSl(46)
299
PPC64_CLVSl(47)
300
PPC64_CLVSh(48)
301
PPC64_CLVSh(49)
302
PPC64_CLVSh(50)
303
PPC64_CLVSh(51)
304
PPC64_CLVSh(52)
305
PPC64_CLVSh(53)
306
PPC64_CLVSh(54)
307
PPC64_CLVSh(55)
308
PPC64_CLVSh(56)
309
PPC64_CLVSh(57)
310
PPC64_CLVSh(58)
311
PPC64_CLVSh(59)
312
PPC64_CLVSh(60)
313
PPC64_CLVSh(61)
314
PPC64_CLVSh(62)
315
PPC64_CLVSh(63)
316
317
#else
318
319
// load FP register
320
#define PPC64_LF(n) \
321
lfd n, (PPC64_OFFS_FP + n * 16)(3)
322
323
// restore float registers
324
PPC64_LF(0)
325
PPC64_LF(1)
326
PPC64_LF(2)
327
PPC64_LF(3)
328
PPC64_LF(4)
329
PPC64_LF(5)
330
PPC64_LF(6)
331
PPC64_LF(7)
332
PPC64_LF(8)
333
PPC64_LF(9)
334
PPC64_LF(10)
335
PPC64_LF(11)
336
PPC64_LF(12)
337
PPC64_LF(13)
338
PPC64_LF(14)
339
PPC64_LF(15)
340
PPC64_LF(16)
341
PPC64_LF(17)
342
PPC64_LF(18)
343
PPC64_LF(19)
344
PPC64_LF(20)
345
PPC64_LF(21)
346
PPC64_LF(22)
347
PPC64_LF(23)
348
PPC64_LF(24)
349
PPC64_LF(25)
350
PPC64_LF(26)
351
PPC64_LF(27)
352
PPC64_LF(28)
353
PPC64_LF(29)
354
PPC64_LF(30)
355
PPC64_LF(31)
356
357
#if defined(__ALTIVEC__)
358
359
#define PPC64_CLV_UNALIGNED_RESTORE(n) \
360
ld 0, (PPC64_OFFS_V + n * 16)(3) ;\
361
std 0, 0(4) ;\
362
ld 0, (PPC64_OFFS_V + n * 16 + 8)(3) ;\
363
std 0, 8(4) ;\
364
lvx n, 0, 4
365
366
#if !defined(_AIX)
367
// restore vector registers if any are in use. In the AIX ABI, VRSAVE is
368
// not used.
369
ld 5, PPC64_OFFS_VRSAVE(3) // test VRsave
370
cmpwi 5, 0
371
beq Lnovec
372
373
#define PPC64_CLV_UNALIGNEDl(n) \
374
andis. 0, 5, (1 PPC_LEFT_SHIFT(15-n)) ;\
375
beq Ldone##n ;\
376
PPC64_CLV_UNALIGNED_RESTORE(n) ;\
377
Ldone ## n:
378
379
#define PPC64_CLV_UNALIGNEDh(n) \
380
andi. 0, 5, (1 PPC_LEFT_SHIFT(31-n)) ;\
381
beq Ldone##n ;\
382
PPC64_CLV_UNALIGNED_RESTORE(n) ;\
383
Ldone ## n:
384
385
#else
386
387
#define PPC64_CLV_UNALIGNEDl(n) PPC64_CLV_UNALIGNED_RESTORE(n)
388
#define PPC64_CLV_UNALIGNEDh(n) PPC64_CLV_UNALIGNED_RESTORE(n)
389
390
#endif // !defined(_AIX)
391
392
subi 4, 1, 16
393
// r4 is now a 16-byte aligned pointer into the red zone
394
// the _vectorScalarRegisters may not be 16-byte aligned
395
// so copy via red zone temp buffer
396
397
PPC64_CLV_UNALIGNEDl(0)
398
PPC64_CLV_UNALIGNEDl(1)
399
PPC64_CLV_UNALIGNEDl(2)
400
PPC64_CLV_UNALIGNEDl(3)
401
PPC64_CLV_UNALIGNEDl(4)
402
PPC64_CLV_UNALIGNEDl(5)
403
PPC64_CLV_UNALIGNEDl(6)
404
PPC64_CLV_UNALIGNEDl(7)
405
PPC64_CLV_UNALIGNEDl(8)
406
PPC64_CLV_UNALIGNEDl(9)
407
PPC64_CLV_UNALIGNEDl(10)
408
PPC64_CLV_UNALIGNEDl(11)
409
PPC64_CLV_UNALIGNEDl(12)
410
PPC64_CLV_UNALIGNEDl(13)
411
PPC64_CLV_UNALIGNEDl(14)
412
PPC64_CLV_UNALIGNEDl(15)
413
PPC64_CLV_UNALIGNEDh(16)
414
PPC64_CLV_UNALIGNEDh(17)
415
PPC64_CLV_UNALIGNEDh(18)
416
PPC64_CLV_UNALIGNEDh(19)
417
PPC64_CLV_UNALIGNEDh(20)
418
PPC64_CLV_UNALIGNEDh(21)
419
PPC64_CLV_UNALIGNEDh(22)
420
PPC64_CLV_UNALIGNEDh(23)
421
PPC64_CLV_UNALIGNEDh(24)
422
PPC64_CLV_UNALIGNEDh(25)
423
PPC64_CLV_UNALIGNEDh(26)
424
PPC64_CLV_UNALIGNEDh(27)
425
PPC64_CLV_UNALIGNEDh(28)
426
PPC64_CLV_UNALIGNEDh(29)
427
PPC64_CLV_UNALIGNEDh(30)
428
PPC64_CLV_UNALIGNEDh(31)
429
430
#endif
431
#endif
432
433
Lnovec:
434
ld 0, PPC64_OFFS_CR(3)
435
mtcr 0
436
ld 0, PPC64_OFFS_SRR0(3)
437
mtctr 0
438
439
#if defined(_AIX)
440
// After setting GPR1 to a higher address, AIX wipes out the original
441
// stack space below that address invalidated by the new GPR1 value. Use
442
// GPR0 to save the value of GPR3 in the context before it is wiped out.
443
// This compromises the content of GPR0 which is a volatile register.
444
ld 0, (8 * (3 + 2))(3)
445
#else
446
PPC64_LR(0)
447
#endif
448
PPC64_LR(5)
449
PPC64_LR(4)
450
PPC64_LR(1)
451
#if defined(_AIX)
452
mr 3, 0
453
#else
454
PPC64_LR(3)
455
#endif
456
bctr
457
458
#elif defined(__powerpc__)
459
460
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv)
461
//
462
// void libunwind::Registers_ppc::jumpto()
463
//
464
// On entry:
465
// thread_state pointer is in r3
466
//
467
468
// restore integral registers
469
// skip r0 for now
470
// skip r1 for now
471
lwz 2, 16(3)
472
// skip r3 for now
473
// skip r4 for now
474
// skip r5 for now
475
lwz 6, 32(3)
476
lwz 7, 36(3)
477
lwz 8, 40(3)
478
lwz 9, 44(3)
479
lwz 10, 48(3)
480
lwz 11, 52(3)
481
lwz 12, 56(3)
482
lwz 13, 60(3)
483
lwz 14, 64(3)
484
lwz 15, 68(3)
485
lwz 16, 72(3)
486
lwz 17, 76(3)
487
lwz 18, 80(3)
488
lwz 19, 84(3)
489
lwz 20, 88(3)
490
lwz 21, 92(3)
491
lwz 22, 96(3)
492
lwz 23,100(3)
493
lwz 24,104(3)
494
lwz 25,108(3)
495
lwz 26,112(3)
496
lwz 27,116(3)
497
lwz 28,120(3)
498
lwz 29,124(3)
499
lwz 30,128(3)
500
lwz 31,132(3)
501
502
#ifndef __NO_FPRS__
503
// restore float registers
504
lfd 0, 160(3)
505
lfd 1, 168(3)
506
lfd 2, 176(3)
507
lfd 3, 184(3)
508
lfd 4, 192(3)
509
lfd 5, 200(3)
510
lfd 6, 208(3)
511
lfd 7, 216(3)
512
lfd 8, 224(3)
513
lfd 9, 232(3)
514
lfd 10,240(3)
515
lfd 11,248(3)
516
lfd 12,256(3)
517
lfd 13,264(3)
518
lfd 14,272(3)
519
lfd 15,280(3)
520
lfd 16,288(3)
521
lfd 17,296(3)
522
lfd 18,304(3)
523
lfd 19,312(3)
524
lfd 20,320(3)
525
lfd 21,328(3)
526
lfd 22,336(3)
527
lfd 23,344(3)
528
lfd 24,352(3)
529
lfd 25,360(3)
530
lfd 26,368(3)
531
lfd 27,376(3)
532
lfd 28,384(3)
533
lfd 29,392(3)
534
lfd 30,400(3)
535
lfd 31,408(3)
536
#endif
537
538
#if defined(__ALTIVEC__)
539
540
#define LOAD_VECTOR_RESTORE(_index) \
541
lwz 0, 424+_index*16(3) SEPARATOR \
542
stw 0, 0(4) SEPARATOR \
543
lwz 0, 424+_index*16+4(3) SEPARATOR \
544
stw 0, 4(4) SEPARATOR \
545
lwz 0, 424+_index*16+8(3) SEPARATOR \
546
stw 0, 8(4) SEPARATOR \
547
lwz 0, 424+_index*16+12(3) SEPARATOR \
548
stw 0, 12(4) SEPARATOR \
549
lvx _index, 0, 4
550
551
#if !defined(_AIX)
552
// restore vector registers if any are in use. In the AIX ABI, VRSAVE
553
// is not used.
554
lwz 5, 156(3) // test VRsave
555
cmpwi 5, 0
556
beq Lnovec
557
558
#define LOAD_VECTOR_UNALIGNEDl(_index) \
559
andis. 0, 5, (1 PPC_LEFT_SHIFT(15-_index)) SEPARATOR \
560
beq Ldone ## _index SEPARATOR \
561
LOAD_VECTOR_RESTORE(_index) SEPARATOR \
562
Ldone ## _index:
563
564
#define LOAD_VECTOR_UNALIGNEDh(_index) \
565
andi. 0, 5, (1 PPC_LEFT_SHIFT(31-_index)) SEPARATOR \
566
beq Ldone ## _index SEPARATOR \
567
LOAD_VECTOR_RESTORE(_index) SEPARATOR \
568
Ldone ## _index:
569
570
#else
571
572
#define LOAD_VECTOR_UNALIGNEDl(_index) LOAD_VECTOR_RESTORE(_index)
573
#define LOAD_VECTOR_UNALIGNEDh(_index) LOAD_VECTOR_RESTORE(_index)
574
575
#endif // !defined(_AIX)
576
577
subi 4, 1, 16
578
rlwinm 4, 4, 0, 0, 27 // mask low 4-bits
579
// r4 is now a 16-byte aligned pointer into the red zone
580
// the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer
581
582
LOAD_VECTOR_UNALIGNEDl(0)
583
LOAD_VECTOR_UNALIGNEDl(1)
584
LOAD_VECTOR_UNALIGNEDl(2)
585
LOAD_VECTOR_UNALIGNEDl(3)
586
LOAD_VECTOR_UNALIGNEDl(4)
587
LOAD_VECTOR_UNALIGNEDl(5)
588
LOAD_VECTOR_UNALIGNEDl(6)
589
LOAD_VECTOR_UNALIGNEDl(7)
590
LOAD_VECTOR_UNALIGNEDl(8)
591
LOAD_VECTOR_UNALIGNEDl(9)
592
LOAD_VECTOR_UNALIGNEDl(10)
593
LOAD_VECTOR_UNALIGNEDl(11)
594
LOAD_VECTOR_UNALIGNEDl(12)
595
LOAD_VECTOR_UNALIGNEDl(13)
596
LOAD_VECTOR_UNALIGNEDl(14)
597
LOAD_VECTOR_UNALIGNEDl(15)
598
LOAD_VECTOR_UNALIGNEDh(16)
599
LOAD_VECTOR_UNALIGNEDh(17)
600
LOAD_VECTOR_UNALIGNEDh(18)
601
LOAD_VECTOR_UNALIGNEDh(19)
602
LOAD_VECTOR_UNALIGNEDh(20)
603
LOAD_VECTOR_UNALIGNEDh(21)
604
LOAD_VECTOR_UNALIGNEDh(22)
605
LOAD_VECTOR_UNALIGNEDh(23)
606
LOAD_VECTOR_UNALIGNEDh(24)
607
LOAD_VECTOR_UNALIGNEDh(25)
608
LOAD_VECTOR_UNALIGNEDh(26)
609
LOAD_VECTOR_UNALIGNEDh(27)
610
LOAD_VECTOR_UNALIGNEDh(28)
611
LOAD_VECTOR_UNALIGNEDh(29)
612
LOAD_VECTOR_UNALIGNEDh(30)
613
LOAD_VECTOR_UNALIGNEDh(31)
614
#endif
615
616
Lnovec:
617
lwz 0, 136(3) // __cr
618
mtcr 0
619
lwz 0, 148(3) // __ctr
620
mtctr 0
621
lwz 0, 0(3) // __ssr0
622
mtctr 0
623
lwz 0, 8(3) // do r0 now
624
lwz 5, 28(3) // do r5 now
625
lwz 4, 24(3) // do r4 now
626
lwz 1, 12(3) // do sp now
627
lwz 3, 20(3) // do r3 last
628
bctr
629
630
#elif defined(__aarch64__)
631
632
#if defined(__ARM_FEATURE_GCS_DEFAULT)
633
.arch_extension gcs
634
#endif
635
636
//
637
// extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
638
//
639
// On entry:
640
// thread_state pointer is in x0
641
//
642
.p2align 2
643
DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
644
// skip restore of x0,x1 for now
645
ldp x2, x3, [x0, #0x010]
646
ldp x4, x5, [x0, #0x020]
647
ldp x6, x7, [x0, #0x030]
648
ldp x8, x9, [x0, #0x040]
649
ldp x10,x11, [x0, #0x050]
650
ldp x12,x13, [x0, #0x060]
651
ldp x14,x15, [x0, #0x070]
652
// x16 and x17 were clobbered by the call into the unwinder, so no point in
653
// restoring them.
654
ldp x18,x19, [x0, #0x090]
655
ldp x20,x21, [x0, #0x0A0]
656
ldp x22,x23, [x0, #0x0B0]
657
ldp x24,x25, [x0, #0x0C0]
658
ldp x26,x27, [x0, #0x0D0]
659
ldp x28,x29, [x0, #0x0E0]
660
ldr x30, [x0, #0x100] // restore pc into lr
661
662
ldp d0, d1, [x0, #0x110]
663
ldp d2, d3, [x0, #0x120]
664
ldp d4, d5, [x0, #0x130]
665
ldp d6, d7, [x0, #0x140]
666
ldp d8, d9, [x0, #0x150]
667
ldp d10,d11, [x0, #0x160]
668
ldp d12,d13, [x0, #0x170]
669
ldp d14,d15, [x0, #0x180]
670
ldp d16,d17, [x0, #0x190]
671
ldp d18,d19, [x0, #0x1A0]
672
ldp d20,d21, [x0, #0x1B0]
673
ldp d22,d23, [x0, #0x1C0]
674
ldp d24,d25, [x0, #0x1D0]
675
ldp d26,d27, [x0, #0x1E0]
676
ldp d28,d29, [x0, #0x1F0]
677
ldr d30, [x0, #0x200]
678
ldr d31, [x0, #0x208]
679
680
// Finally, restore sp. This must be done after the last read from the
681
// context struct, because it is allocated on the stack, and an exception
682
// could clobber the de-allocated portion of the stack after sp has been
683
// restored.
684
ldr x16, [x0, #0x0F8]
685
ldp x0, x1, [x0, #0x000] // restore x0,x1
686
mov sp,x16 // restore sp
687
#if defined(__ARM_FEATURE_GCS_DEFAULT)
688
// If GCS is enabled we need to push the address we're returning to onto the
689
// GCS stack. We can't just return using br, as there won't be a BTI landing
690
// pad instruction at the destination.
691
mov x16, #1
692
chkfeat x16
693
cbnz x16, Lnogcs
694
gcspushm x30
695
Lnogcs:
696
#endif
697
ret x30 // jump to pc
698
699
#elif defined(__arm__) && !defined(__APPLE__)
700
701
#if !defined(__ARM_ARCH_ISA_ARM)
702
#if (__ARM_ARCH_ISA_THUMB == 2)
703
.syntax unified
704
#endif
705
.thumb
706
#endif
707
708
@
709
@ void libunwind::Registers_arm::restoreCoreAndJumpTo()
710
@
711
@ On entry:
712
@ thread_state pointer is in r0
713
@
714
.p2align 2
715
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJumpToEv)
716
#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1
717
@ r8-r11: ldm into r1-r4, then mov to r8-r11
718
adds r0, #0x20
719
ldm r0!, {r1-r4}
720
subs r0, #0x30
721
mov r8, r1
722
mov r9, r2
723
mov r10, r3
724
mov r11, r4
725
@ r12 does not need loading, it it the intra-procedure-call scratch register
726
ldr r2, [r0, #0x34]
727
ldr r3, [r0, #0x3c]
728
mov sp, r2
729
mov lr, r3 @ restore pc into lr
730
ldm r0, {r0-r7}
731
#else
732
@ Use lr as base so that r0 can be restored.
733
mov lr, r0
734
@ 32bit thumb-2 restrictions for ldm:
735
@ . the sp (r13) cannot be in the list
736
@ . the pc (r15) and lr (r14) cannot both be in the list in an LDM instruction
737
ldm lr, {r0-r12}
738
ldr sp, [lr, #52]
739
ldr lr, [lr, #60] @ restore pc into lr
740
#endif
741
#if defined(__ARM_FEATURE_BTI_DEFAULT) && !defined(__ARM_ARCH_ISA_ARM)
742
// 'bx' is not BTI setting when used with lr, therefore r12 is used instead
743
mov r12, lr
744
JMP(r12)
745
#else
746
JMP(lr)
747
#endif
748
749
@
750
@ static void libunwind::Registers_arm::restoreVFPWithFLDMD(unw_fpreg_t* values)
751
@
752
@ On entry:
753
@ values pointer is in r0
754
@
755
.p2align 2
756
#if defined(__ELF__)
757
.fpu vfpv3-d16
758
#endif
759
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPv)
760
@ VFP and iwMMX instructions are only available when compiling with the flags
761
@ that enable them. We do not want to do that in the library (because we do not
762
@ want the compiler to generate instructions that access those) but this is
763
@ only accessed if the personality routine needs these registers. Use of
764
@ these registers implies they are, actually, available on the target, so
765
@ it's ok to execute.
766
@ So, generate the instruction using the corresponding coprocessor mnemonic.
767
vldmia r0, {d0-d15}
768
JMP(lr)
769
770
@
771
@ static void libunwind::Registers_arm::restoreVFPWithFLDMX(unw_fpreg_t* values)
772
@
773
@ On entry:
774
@ values pointer is in r0
775
@
776
.p2align 2
777
#if defined(__ELF__)
778
.fpu vfpv3-d16
779
#endif
780
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPv)
781
vldmia r0, {d0-d15} @ fldmiax is deprecated in ARMv7+ and now behaves like vldmia
782
JMP(lr)
783
784
@
785
@ static void libunwind::Registers_arm::restoreVFPv3(unw_fpreg_t* values)
786
@
787
@ On entry:
788
@ values pointer is in r0
789
@
790
.p2align 2
791
#if defined(__ELF__)
792
.fpu vfpv3
793
#endif
794
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPv)
795
vldmia r0, {d16-d31}
796
JMP(lr)
797
798
#if defined(__ARM_WMMX)
799
800
@
801
@ static void libunwind::Registers_arm::restoreiWMMX(unw_fpreg_t* values)
802
@
803
@ On entry:
804
@ values pointer is in r0
805
@
806
.p2align 2
807
#if defined(__ELF__)
808
.arch armv5te
809
#endif
810
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPv)
811
ldcl p1, cr0, [r0], #8 @ wldrd wR0, [r0], #8
812
ldcl p1, cr1, [r0], #8 @ wldrd wR1, [r0], #8
813
ldcl p1, cr2, [r0], #8 @ wldrd wR2, [r0], #8
814
ldcl p1, cr3, [r0], #8 @ wldrd wR3, [r0], #8
815
ldcl p1, cr4, [r0], #8 @ wldrd wR4, [r0], #8
816
ldcl p1, cr5, [r0], #8 @ wldrd wR5, [r0], #8
817
ldcl p1, cr6, [r0], #8 @ wldrd wR6, [r0], #8
818
ldcl p1, cr7, [r0], #8 @ wldrd wR7, [r0], #8
819
ldcl p1, cr8, [r0], #8 @ wldrd wR8, [r0], #8
820
ldcl p1, cr9, [r0], #8 @ wldrd wR9, [r0], #8
821
ldcl p1, cr10, [r0], #8 @ wldrd wR10, [r0], #8
822
ldcl p1, cr11, [r0], #8 @ wldrd wR11, [r0], #8
823
ldcl p1, cr12, [r0], #8 @ wldrd wR12, [r0], #8
824
ldcl p1, cr13, [r0], #8 @ wldrd wR13, [r0], #8
825
ldcl p1, cr14, [r0], #8 @ wldrd wR14, [r0], #8
826
ldcl p1, cr15, [r0], #8 @ wldrd wR15, [r0], #8
827
JMP(lr)
828
829
@
830
@ static void libunwind::Registers_arm::restoreiWMMXControl(unw_uint32_t* values)
831
@
832
@ On entry:
833
@ values pointer is in r0
834
@
835
.p2align 2
836
#if defined(__ELF__)
837
.arch armv5te
838
#endif
839
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXControlEPj)
840
ldc2 p1, cr8, [r0], #4 @ wldrw wCGR0, [r0], #4
841
ldc2 p1, cr9, [r0], #4 @ wldrw wCGR1, [r0], #4
842
ldc2 p1, cr10, [r0], #4 @ wldrw wCGR2, [r0], #4
843
ldc2 p1, cr11, [r0], #4 @ wldrw wCGR3, [r0], #4
844
JMP(lr)
845
846
#endif
847
848
#elif defined(__or1k__)
849
850
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
851
#
852
# void libunwind::Registers_or1k::jumpto()
853
#
854
# On entry:
855
# thread_state pointer is in r3
856
#
857
858
# restore integral registers
859
l.lwz r0, 0(r3)
860
l.lwz r1, 4(r3)
861
l.lwz r2, 8(r3)
862
# skip r3 for now
863
l.lwz r4, 16(r3)
864
l.lwz r5, 20(r3)
865
l.lwz r6, 24(r3)
866
l.lwz r7, 28(r3)
867
l.lwz r8, 32(r3)
868
# skip r9
869
l.lwz r10, 40(r3)
870
l.lwz r11, 44(r3)
871
l.lwz r12, 48(r3)
872
l.lwz r13, 52(r3)
873
l.lwz r14, 56(r3)
874
l.lwz r15, 60(r3)
875
l.lwz r16, 64(r3)
876
l.lwz r17, 68(r3)
877
l.lwz r18, 72(r3)
878
l.lwz r19, 76(r3)
879
l.lwz r20, 80(r3)
880
l.lwz r21, 84(r3)
881
l.lwz r22, 88(r3)
882
l.lwz r23, 92(r3)
883
l.lwz r24, 96(r3)
884
l.lwz r25,100(r3)
885
l.lwz r26,104(r3)
886
l.lwz r27,108(r3)
887
l.lwz r28,112(r3)
888
l.lwz r29,116(r3)
889
l.lwz r30,120(r3)
890
l.lwz r31,124(r3)
891
892
# load new pc into ra
893
l.lwz r9, 128(r3)
894
895
# at last, restore r3
896
l.lwz r3, 12(r3)
897
898
# jump to pc
899
l.jr r9
900
l.nop
901
902
#elif defined(__hexagon__)
903
# On entry:
904
# thread_state pointer is in r2
905
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind17Registers_hexagon6jumptoEv)
906
#
907
# void libunwind::Registers_hexagon::jumpto()
908
#
909
r8 = memw(r0+#32)
910
r9 = memw(r0+#36)
911
r10 = memw(r0+#40)
912
r11 = memw(r0+#44)
913
914
r12 = memw(r0+#48)
915
r13 = memw(r0+#52)
916
r14 = memw(r0+#56)
917
r15 = memw(r0+#60)
918
919
r16 = memw(r0+#64)
920
r17 = memw(r0+#68)
921
r18 = memw(r0+#72)
922
r19 = memw(r0+#76)
923
924
r20 = memw(r0+#80)
925
r21 = memw(r0+#84)
926
r22 = memw(r0+#88)
927
r23 = memw(r0+#92)
928
929
r24 = memw(r0+#96)
930
r25 = memw(r0+#100)
931
r26 = memw(r0+#104)
932
r27 = memw(r0+#108)
933
934
r28 = memw(r0+#112)
935
r29 = memw(r0+#116)
936
r30 = memw(r0+#120)
937
r31 = memw(r0+#132)
938
939
r1 = memw(r0+#128)
940
c4 = r1 // Predicate register
941
r1 = memw(r0+#4)
942
r0 = memw(r0)
943
jumpr r31
944
#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
945
946
//
947
// void libunwind::Registers_mips_o32::jumpto()
948
//
949
// On entry:
950
// thread state pointer is in a0 ($4)
951
//
952
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv)
953
.set push
954
.set noat
955
.set noreorder
956
.set nomacro
957
#ifdef __mips_hard_float
958
#if __mips_fpr != 64
959
ldc1 $f0, (4 * 36 + 8 * 0)($4)
960
ldc1 $f2, (4 * 36 + 8 * 2)($4)
961
ldc1 $f4, (4 * 36 + 8 * 4)($4)
962
ldc1 $f6, (4 * 36 + 8 * 6)($4)
963
ldc1 $f8, (4 * 36 + 8 * 8)($4)
964
ldc1 $f10, (4 * 36 + 8 * 10)($4)
965
ldc1 $f12, (4 * 36 + 8 * 12)($4)
966
ldc1 $f14, (4 * 36 + 8 * 14)($4)
967
ldc1 $f16, (4 * 36 + 8 * 16)($4)
968
ldc1 $f18, (4 * 36 + 8 * 18)($4)
969
ldc1 $f20, (4 * 36 + 8 * 20)($4)
970
ldc1 $f22, (4 * 36 + 8 * 22)($4)
971
ldc1 $f24, (4 * 36 + 8 * 24)($4)
972
ldc1 $f26, (4 * 36 + 8 * 26)($4)
973
ldc1 $f28, (4 * 36 + 8 * 28)($4)
974
ldc1 $f30, (4 * 36 + 8 * 30)($4)
975
#else
976
ldc1 $f0, (4 * 36 + 8 * 0)($4)
977
ldc1 $f1, (4 * 36 + 8 * 1)($4)
978
ldc1 $f2, (4 * 36 + 8 * 2)($4)
979
ldc1 $f3, (4 * 36 + 8 * 3)($4)
980
ldc1 $f4, (4 * 36 + 8 * 4)($4)
981
ldc1 $f5, (4 * 36 + 8 * 5)($4)
982
ldc1 $f6, (4 * 36 + 8 * 6)($4)
983
ldc1 $f7, (4 * 36 + 8 * 7)($4)
984
ldc1 $f8, (4 * 36 + 8 * 8)($4)
985
ldc1 $f9, (4 * 36 + 8 * 9)($4)
986
ldc1 $f10, (4 * 36 + 8 * 10)($4)
987
ldc1 $f11, (4 * 36 + 8 * 11)($4)
988
ldc1 $f12, (4 * 36 + 8 * 12)($4)
989
ldc1 $f13, (4 * 36 + 8 * 13)($4)
990
ldc1 $f14, (4 * 36 + 8 * 14)($4)
991
ldc1 $f15, (4 * 36 + 8 * 15)($4)
992
ldc1 $f16, (4 * 36 + 8 * 16)($4)
993
ldc1 $f17, (4 * 36 + 8 * 17)($4)
994
ldc1 $f18, (4 * 36 + 8 * 18)($4)
995
ldc1 $f19, (4 * 36 + 8 * 19)($4)
996
ldc1 $f20, (4 * 36 + 8 * 20)($4)
997
ldc1 $f21, (4 * 36 + 8 * 21)($4)
998
ldc1 $f22, (4 * 36 + 8 * 22)($4)
999
ldc1 $f23, (4 * 36 + 8 * 23)($4)
1000
ldc1 $f24, (4 * 36 + 8 * 24)($4)
1001
ldc1 $f25, (4 * 36 + 8 * 25)($4)
1002
ldc1 $f26, (4 * 36 + 8 * 26)($4)
1003
ldc1 $f27, (4 * 36 + 8 * 27)($4)
1004
ldc1 $f28, (4 * 36 + 8 * 28)($4)
1005
ldc1 $f29, (4 * 36 + 8 * 29)($4)
1006
ldc1 $f30, (4 * 36 + 8 * 30)($4)
1007
ldc1 $f31, (4 * 36 + 8 * 31)($4)
1008
#endif
1009
#endif
1010
#if __mips_isa_rev < 6
1011
// restore hi and lo
1012
lw $8, (4 * 33)($4)
1013
mthi $8
1014
lw $8, (4 * 34)($4)
1015
mtlo $8
1016
#endif
1017
// r0 is zero
1018
lw $1, (4 * 1)($4)
1019
lw $2, (4 * 2)($4)
1020
lw $3, (4 * 3)($4)
1021
// skip a0 for now
1022
lw $5, (4 * 5)($4)
1023
lw $6, (4 * 6)($4)
1024
lw $7, (4 * 7)($4)
1025
lw $8, (4 * 8)($4)
1026
lw $9, (4 * 9)($4)
1027
lw $10, (4 * 10)($4)
1028
lw $11, (4 * 11)($4)
1029
lw $12, (4 * 12)($4)
1030
lw $13, (4 * 13)($4)
1031
lw $14, (4 * 14)($4)
1032
lw $15, (4 * 15)($4)
1033
lw $16, (4 * 16)($4)
1034
lw $17, (4 * 17)($4)
1035
lw $18, (4 * 18)($4)
1036
lw $19, (4 * 19)($4)
1037
lw $20, (4 * 20)($4)
1038
lw $21, (4 * 21)($4)
1039
lw $22, (4 * 22)($4)
1040
lw $23, (4 * 23)($4)
1041
lw $24, (4 * 24)($4)
1042
lw $25, (4 * 25)($4)
1043
lw $26, (4 * 26)($4)
1044
lw $27, (4 * 27)($4)
1045
lw $28, (4 * 28)($4)
1046
lw $29, (4 * 29)($4)
1047
lw $30, (4 * 30)($4)
1048
// load new pc into ra
1049
lw $31, (4 * 32)($4)
1050
// jump to ra, load a0 in the delay slot
1051
jr $31
1052
lw $4, (4 * 4)($4)
1053
.set pop
1054
1055
#elif defined(__mips64)
1056
1057
//
1058
// void libunwind::Registers_mips_newabi::jumpto()
1059
//
1060
// On entry:
1061
// thread state pointer is in a0 ($4)
1062
//
1063
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv)
1064
.set push
1065
.set noat
1066
.set noreorder
1067
.set nomacro
1068
#ifdef __mips_hard_float
1069
.irp i,FROM_0_TO_31
1070
ldc1 $f\i, (280+8*\i)($4)
1071
.endr
1072
#endif
1073
#if __mips_isa_rev < 6
1074
// restore hi and lo
1075
ld $8, (8 * 33)($4)
1076
mthi $8
1077
ld $8, (8 * 34)($4)
1078
mtlo $8
1079
#endif
1080
// r0 is zero
1081
ld $1, (8 * 1)($4)
1082
ld $2, (8 * 2)($4)
1083
ld $3, (8 * 3)($4)
1084
// skip a0 for now
1085
.irp i,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
1086
ld $\i, (8 * \i)($4)
1087
.endr
1088
// load new pc into ra
1089
ld $31, (8 * 32)($4)
1090
// jump to ra, load a0 in the delay slot
1091
jr $31
1092
ld $4, (8 * 4)($4)
1093
.set pop
1094
1095
#elif defined(__sparc__) && defined(__arch64__)
1096
1097
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind17Registers_sparc646jumptoEv)
1098
//
1099
// void libunwind::Registers_sparc64::jumpto()
1100
//
1101
// On entry:
1102
// thread_state pointer is in %o0
1103
//
1104
.register %g2, #scratch
1105
.register %g3, #scratch
1106
.register %g6, #scratch
1107
.register %g7, #scratch
1108
flushw
1109
ldx [%o0 + 0x08], %g1
1110
ldx [%o0 + 0x10], %g2
1111
ldx [%o0 + 0x18], %g3
1112
ldx [%o0 + 0x20], %g4
1113
ldx [%o0 + 0x28], %g5
1114
ldx [%o0 + 0x30], %g6
1115
ldx [%o0 + 0x38], %g7
1116
ldx [%o0 + 0x48], %o1
1117
ldx [%o0 + 0x50], %o2
1118
ldx [%o0 + 0x58], %o3
1119
ldx [%o0 + 0x60], %o4
1120
ldx [%o0 + 0x68], %o5
1121
ldx [%o0 + 0x70], %o6
1122
ldx [%o0 + 0x78], %o7
1123
ldx [%o0 + 0x80], %l0
1124
ldx [%o0 + 0x88], %l1
1125
ldx [%o0 + 0x90], %l2
1126
ldx [%o0 + 0x98], %l3
1127
ldx [%o0 + 0xa0], %l4
1128
ldx [%o0 + 0xa8], %l5
1129
ldx [%o0 + 0xb0], %l6
1130
ldx [%o0 + 0xb8], %l7
1131
ldx [%o0 + 0xc0], %i0
1132
ldx [%o0 + 0xc8], %i1
1133
ldx [%o0 + 0xd0], %i2
1134
ldx [%o0 + 0xd8], %i3
1135
ldx [%o0 + 0xe0], %i4
1136
ldx [%o0 + 0xe8], %i5
1137
ldx [%o0 + 0xf0], %i6
1138
ldx [%o0 + 0xf8], %i7
1139
jmp %o7
1140
ldx [%o0 + 0x40], %o0
1141
1142
#elif defined(__sparc__)
1143
1144
//
1145
// void libunwind::Registers_sparc_o32::jumpto()
1146
//
1147
// On entry:
1148
// thread_state pointer is in o0
1149
//
1150
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv)
1151
ta 3
1152
ldd [%o0 + 64], %l0
1153
ldd [%o0 + 72], %l2
1154
ldd [%o0 + 80], %l4
1155
ldd [%o0 + 88], %l6
1156
ldd [%o0 + 96], %i0
1157
ldd [%o0 + 104], %i2
1158
ldd [%o0 + 112], %i4
1159
ldd [%o0 + 120], %i6
1160
ld [%o0 + 60], %o7
1161
jmp %o7
1162
nop
1163
1164
#elif defined(__riscv)
1165
1166
//
1167
// void libunwind::Registers_riscv::jumpto()
1168
//
1169
// On entry:
1170
// thread_state pointer is in a0
1171
//
1172
.p2align 2
1173
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv)
1174
# if defined(__riscv_flen)
1175
.irp i,FROM_0_TO_31
1176
FLOAD f\i, (RISCV_FOFFSET + RISCV_FSIZE * \i)(a0)
1177
.endr
1178
# endif
1179
1180
// x0 is zero
1181
ILOAD x1, (RISCV_ISIZE * 0)(a0) // restore pc into ra
1182
.irp i,2,3,4,5,6,7,8,9
1183
ILOAD x\i, (RISCV_ISIZE * \i)(a0)
1184
.endr
1185
// skip a0 for now
1186
.irp i,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
1187
ILOAD x\i, (RISCV_ISIZE * \i)(a0)
1188
.endr
1189
ILOAD x10, (RISCV_ISIZE * 10)(a0) // restore a0
1190
1191
ret // jump to ra
1192
1193
#elif defined(__s390x__)
1194
1195
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_s390x6jumptoEv)
1196
//
1197
// void libunwind::Registers_s390x::jumpto()
1198
//
1199
// On entry:
1200
// thread_state pointer is in r2
1201
//
1202
1203
// Skip PSWM, but load PSWA into r1
1204
lg %r1, 8(%r2)
1205
1206
// Restore FPRs
1207
.irp i,FROM_0_TO_15
1208
ld %f\i, (144+8*\i)(%r2)
1209
.endr
1210
1211
// Restore GPRs - skipping %r0 and %r1
1212
lmg %r2, %r15, 32(%r2)
1213
1214
// Return to PSWA (was loaded into %r1 above)
1215
br %r1
1216
1217
#elif defined(__loongarch__) && __loongarch_grlen == 64
1218
1219
//
1220
// void libunwind::Registers_loongarch::jumpto()
1221
//
1222
// On entry:
1223
// thread_state pointer is in $a0($r4)
1224
//
1225
.p2align 2
1226
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv)
1227
# if __loongarch_frlen == 64
1228
.irp i,FROM_0_TO_31
1229
fld.d $f\i, $a0, (8 * 33 + 8 * \i)
1230
.endr
1231
# endif
1232
1233
// $r0 is zero
1234
.irp i,1,2,3
1235
ld.d $r\i, $a0, (8 * \i)
1236
.endr
1237
// skip $a0 for now
1238
.irp i,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
1239
ld.d $r\i, $a0, (8 * \i)
1240
.endr
1241
1242
ld.d $ra, $a0, (8 * 32) // load new pc into $ra
1243
ld.d $a0, $a0, (8 * 4) // restore $a0 last
1244
1245
jr $ra
1246
1247
#endif
1248
1249
#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */
1250
1251
NO_EXEC_STACK_DIRECTIVE
1252
1253
1254