Arm64 Fix Rtl*Context (#25745)
[platform/upstream/coreclr.git] / src / pal / src / arch / arm64 / context2.S
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 //
5 // Implementation of _CONTEXT_CaptureContext for the ARM platform.
6 // This function is processor dependent.  It is used by exception handling,
7 // and is always apply to the current thread.
8 //
9
10 #include "unixasmmacros.inc"
11 #include "asmconstants.h"
12
13 // Incoming:
14 //  x0: Context*
15 //
16 LEAF_ENTRY CONTEXT_CaptureContext, _TEXT
17     sub sp, sp, #32
18     // save x1, x2 and x3 on stack so we can use them as scratch
19     stp x1, x2, [sp]
20     str x3, [sp, 16]
21     // save the current flags on the stack
22     mrs x1, nzcv
23     str x1, [sp, 24]
24
25     ldr w1, [x0, CONTEXT_ContextFlags]
26     // clangs assembler doesn't seem to support the mov Wx, imm32 yet
27     movz w2, #0x40, lsl #16
28     movk w2, #0x1
29     mov w3, w2
30     and w2, w1, w2
31     cmp w2, w3
32     b.ne LOCAL_LABEL(Done_CONTEXT_CONTROL)
33
34     // save the cpsr
35     ldr x2, [sp, 24]
36     str w2, [x0, CONTEXT_Cpsr]
37     stp fp, lr, [x0, CONTEXT_Fp]
38     add x2, sp, #32
39     stp x2, lr, [x0, CONTEXT_Sp]
40
41 LOCAL_LABEL(Done_CONTEXT_CONTROL): 
42     // we dont clobber x1 in the CONTEXT_CONTROL case
43     // ldr w1, [x0, CONTEXT_ContextFlags]
44     // clangs assembler doesn't seem to support the mov Wx, imm32 yet
45     movz w2, #0x40, lsl #16
46     movk w2, #0x2
47     mov w3, w2
48     and w2, w1, w2
49     cmp w2, w3
50     b.ne LOCAL_LABEL(Done_CONTEXT_INTEGER)
51
52     ldp x1, x2,   [sp]
53     ldr x3,       [sp, 16]
54
55     stp x0, x1,   [x0, CONTEXT_X0]
56     stp x2, x3,   [x0, CONTEXT_X2]
57     stp x4, x5,   [x0, CONTEXT_X4]
58     stp x6, x7,   [x0, CONTEXT_X6]
59     stp x8, x9,   [x0, CONTEXT_X8]
60     stp x10, x11, [x0, CONTEXT_X10]
61     stp x12, x13, [x0, CONTEXT_X12]
62     stp x14, x15, [x0, CONTEXT_X14]
63     stp x16, x17, [x0, CONTEXT_X16]
64     stp x18, x19, [x0, CONTEXT_X18]
65     stp x20, x21, [x0, CONTEXT_X20]
66     stp x22, x23, [x0, CONTEXT_X22]
67     stp x24, x25, [x0, CONTEXT_X24]
68     stp x26, x27, [x0, CONTEXT_X26]
69     str x28,      [x0, CONTEXT_X28]
70
71
72 LOCAL_LABEL(Done_CONTEXT_INTEGER): 
73     ldr w1, [x0, CONTEXT_ContextFlags]
74     // clangs assembler doesn't seem to support the mov Wx, imm32 yet
75     movz w2, #0x40, lsl #16
76     movk w2, #0x4
77     mov w3, w2
78     and w2, w1, w2
79     cmp w2, w3
80     b.ne LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT)
81
82     add x0, x0,   CONTEXT_NEON_OFFSET
83     stp q0, q1,   [x0, CONTEXT_V0]
84     stp q2, q3,   [x0, CONTEXT_V2]
85     stp q4, q5,   [x0, CONTEXT_V4]
86     stp q6, q7,   [x0, CONTEXT_V6]
87     stp q8, q9,   [x0, CONTEXT_V8]
88     stp q10, q11, [x0, CONTEXT_V10]
89     stp q12, q13, [x0, CONTEXT_V12]
90     stp q14, q15, [x0, CONTEXT_V14]
91     stp q16, q17, [x0, CONTEXT_V16]
92     stp q18, q19, [x0, CONTEXT_V18]
93     stp q20, q21, [x0, CONTEXT_V20]
94     stp q22, q23, [x0, CONTEXT_V22]
95     stp q24, q25, [x0, CONTEXT_V24]
96     stp q26, q27, [x0, CONTEXT_V26]
97     stp q28, q29, [x0, CONTEXT_V28]
98     stp q30, q31, [x0, CONTEXT_V30]
99     add x0, x0,   CONTEXT_FLOAT_CONTROL_OFFSET
100     mrs x1, fpcr
101     mrs x2, fpsr
102     stp x1, x2,   [x0, CONTEXT_Fpcr]
103     sub x0, x0,   CONTEXT_FLOAT_CONTROL_OFFSET + CONTEXT_NEON_OFFSET
104
105 LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT):
106     
107     add sp, sp, #32
108     ret
109 LEAF_END CONTEXT_CaptureContext, _TEXT
110
111 // Incoming:
112 //  x0: Context*
113
114 LEAF_ENTRY RtlCaptureContext, _TEXT
115     sub sp, sp, #16
116     str x1, [sp]
117     // same as above, clang doesn't like mov with #imm32
118     // keep this in sync if CONTEXT_FULL changes
119     movz w1, #0x40, lsl #16
120     orr w1, w1, #0x1
121     orr w1, w1, #0x2
122     orr w1, w1, #0x4
123     orr w1, w1, #0x8
124     str w1, [x0, CONTEXT_ContextFlags]
125     ldr x1, [sp]
126     add sp, sp, #16
127     b C_FUNC(CONTEXT_CaptureContext)
128 LEAF_END RtlCaptureContext, _TEXT
129
130 // Incoming:
131 //  x0: Context*
132 //  x1: Exception*
133 //
134 LEAF_ENTRY RtlRestoreContext, _TEXT
135
136 #ifdef HAS_ASAN
137     ldr w17, [x0, #(CONTEXT_ContextFlags)]
138     tbz w17, #CONTEXT_CONTROL_BIT, LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT)
139
140     stp x0, x1, [sp, -16]!
141     bl EXTERNAL_C_FUNC(__asan_handle_no_return)
142     ldp x0, x1, [sp], 16
143
144 LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT):
145 #endif
146     // aarch64 specifies:
147     //   IP0 and IP1, the Intra-Procedure Call temporary registers,
148     //   are available for use by e.g. veneers or branch islands during a procedure call.
149     //   They are otherwise corruptible.
150     // Since we cannot control $pc directly, we're going to corrupt x16 and x17
151     // so that we can restore control
152     // since we potentially clobber x0 below, we'll bank it in x16
153     mov x16, x0
154
155     ldr w17, [x16, CONTEXT_ContextFlags]
156     tbz w17, #CONTEXT_FLOATING_POINT_BIT, LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT)
157
158     add x16, x16,   CONTEXT_NEON_OFFSET
159     ldp q0, q1,   [x16, CONTEXT_V0]
160     ldp q2, q3,   [x16, CONTEXT_V2]
161     ldp q4, q5,   [x16, CONTEXT_V4]
162     ldp q6, q7,   [x16, CONTEXT_V6]
163     ldp q8, q9,   [x16, CONTEXT_V8]
164     ldp q10, q11, [x16, CONTEXT_V10]
165     ldp q12, q13, [x16, CONTEXT_V12]
166     ldp q14, q15, [x16, CONTEXT_V14]
167     ldp q16, q17, [x16, CONTEXT_V16]
168     ldp q18, q19, [x16, CONTEXT_V18]
169     ldp q20, q21, [x16, CONTEXT_V20]
170     ldp q22, q23, [x16, CONTEXT_V22]
171     ldp q24, q25, [x16, CONTEXT_V24]
172     ldp q26, q27, [x16, CONTEXT_V26]
173     ldp q28, q29, [x16, CONTEXT_V28]
174     ldp q30, q31, [x16, CONTEXT_V30]
175     add x16, x16, CONTEXT_FLOAT_CONTROL_OFFSET
176     ldp x1, x2,   [x16, CONTEXT_Fpcr]
177     msr fpcr, x1
178     msr fpsr, x2
179     sub x16, x16,   CONTEXT_FLOAT_CONTROL_OFFSET + CONTEXT_NEON_OFFSET
180
181 LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT):
182     tbz w17, #CONTEXT_INTEGER_BIT, LOCAL_LABEL(No_Restore_CONTEXT_INTEGER)
183
184     ldp x0, x1,   [x16, CONTEXT_X0]
185     ldp x2, x3,   [x16, CONTEXT_X2]
186     ldp x4, x5,   [x16, CONTEXT_X4]
187     ldp x6, x7,   [x16, CONTEXT_X6]
188     ldp x8, x9,   [x16, CONTEXT_X8]
189     ldp x10, x11, [x16, CONTEXT_X10]
190     ldp x12, x13, [x16, CONTEXT_X12]
191     ldp x14, x15, [x16, CONTEXT_X14]
192     ldp x18, x19, [x16, CONTEXT_X18]
193     ldp x20, x21, [x16, CONTEXT_X20]
194     ldp x22, x23, [x16, CONTEXT_X22]
195     ldp x24, x25, [x16, CONTEXT_X24]
196     ldp x26, x27, [x16, CONTEXT_X26]
197     ldr x28,      [x16, CONTEXT_X28]
198
199 LOCAL_LABEL(No_Restore_CONTEXT_INTEGER):
200     tbz w17, #CONTEXT_CONTROL_BIT, LOCAL_LABEL(No_Restore_CONTEXT_CONTROL)
201
202     ldr w17, [x16, CONTEXT_Cpsr]
203     msr nzcv, x17
204     ldp fp, lr, [x16, CONTEXT_Fp]
205     ldr x17, [x16, CONTEXT_Sp]
206     mov sp, x17
207     ldr x17, [x16, CONTEXT_Pc]
208     br x17
209  
210 LOCAL_LABEL(No_Restore_CONTEXT_CONTROL):
211    ret
212
213 LEAF_END RtlRestoreContext, _TEXT