xref: /openbmc/qemu/target/arm/tcg/pauth_helper.c (revision 806f71ee)
1 /*
2  * ARM v8.3-PAuth Operations
3  *
4  * Copyright (c) 2019 Linaro, Ltd.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "qemu/osdep.h"
21 #include "cpu.h"
22 #include "internals.h"
23 #include "cpu-features.h"
24 #include "exec/exec-all.h"
25 #include "exec/cpu_ldst.h"
26 #include "exec/helper-proto.h"
27 #include "tcg/tcg-gvec-desc.h"
28 #include "qemu/xxhash.h"
29 
30 
31 static uint64_t pac_cell_shuffle(uint64_t i)
32 {
33     uint64_t o = 0;
34 
35     o |= extract64(i, 52, 4);
36     o |= extract64(i, 24, 4) << 4;
37     o |= extract64(i, 44, 4) << 8;
38     o |= extract64(i,  0, 4) << 12;
39 
40     o |= extract64(i, 28, 4) << 16;
41     o |= extract64(i, 48, 4) << 20;
42     o |= extract64(i,  4, 4) << 24;
43     o |= extract64(i, 40, 4) << 28;
44 
45     o |= extract64(i, 32, 4) << 32;
46     o |= extract64(i, 12, 4) << 36;
47     o |= extract64(i, 56, 4) << 40;
48     o |= extract64(i, 20, 4) << 44;
49 
50     o |= extract64(i,  8, 4) << 48;
51     o |= extract64(i, 36, 4) << 52;
52     o |= extract64(i, 16, 4) << 56;
53     o |= extract64(i, 60, 4) << 60;
54 
55     return o;
56 }
57 
58 static uint64_t pac_cell_inv_shuffle(uint64_t i)
59 {
60     uint64_t o = 0;
61 
62     o |= extract64(i, 12, 4);
63     o |= extract64(i, 24, 4) << 4;
64     o |= extract64(i, 48, 4) << 8;
65     o |= extract64(i, 36, 4) << 12;
66 
67     o |= extract64(i, 56, 4) << 16;
68     o |= extract64(i, 44, 4) << 20;
69     o |= extract64(i,  4, 4) << 24;
70     o |= extract64(i, 16, 4) << 28;
71 
72     o |= i & MAKE_64BIT_MASK(32, 4);
73     o |= extract64(i, 52, 4) << 36;
74     o |= extract64(i, 28, 4) << 40;
75     o |= extract64(i,  8, 4) << 44;
76 
77     o |= extract64(i, 20, 4) << 48;
78     o |= extract64(i,  0, 4) << 52;
79     o |= extract64(i, 40, 4) << 56;
80     o |= i & MAKE_64BIT_MASK(60, 4);
81 
82     return o;
83 }
84 
85 static uint64_t pac_sub(uint64_t i)
86 {
87     static const uint8_t sub[16] = {
88         0xb, 0x6, 0x8, 0xf, 0xc, 0x0, 0x9, 0xe,
89         0x3, 0x7, 0x4, 0x5, 0xd, 0x2, 0x1, 0xa,
90     };
91     uint64_t o = 0;
92     int b;
93 
94     for (b = 0; b < 64; b += 4) {
95         o |= (uint64_t)sub[(i >> b) & 0xf] << b;
96     }
97     return o;
98 }
99 
100 static uint64_t pac_sub1(uint64_t i)
101 {
102     static const uint8_t sub1[16] = {
103         0xa, 0xd, 0xe, 0x6, 0xf, 0x7, 0x3, 0x5,
104         0x9, 0x8, 0x0, 0xc, 0xb, 0x1, 0x2, 0x4,
105     };
106     uint64_t o = 0;
107     int b;
108 
109     for (b = 0; b < 64; b += 4) {
110         o |= (uint64_t)sub1[(i >> b) & 0xf] << b;
111     }
112     return o;
113 }
114 
115 static uint64_t pac_inv_sub(uint64_t i)
116 {
117     static const uint8_t inv_sub[16] = {
118         0x5, 0xe, 0xd, 0x8, 0xa, 0xb, 0x1, 0x9,
119         0x2, 0x6, 0xf, 0x0, 0x4, 0xc, 0x7, 0x3,
120     };
121     uint64_t o = 0;
122     int b;
123 
124     for (b = 0; b < 64; b += 4) {
125         o |= (uint64_t)inv_sub[(i >> b) & 0xf] << b;
126     }
127     return o;
128 }
129 
130 static int rot_cell(int cell, int n)
131 {
132     /* 4-bit rotate left by n.  */
133     cell |= cell << 4;
134     return extract32(cell, 4 - n, 4);
135 }
136 
137 static uint64_t pac_mult(uint64_t i)
138 {
139     uint64_t o = 0;
140     int b;
141 
142     for (b = 0; b < 4 * 4; b += 4) {
143         int i0, i4, i8, ic, t0, t1, t2, t3;
144 
145         i0 = extract64(i, b, 4);
146         i4 = extract64(i, b + 4 * 4, 4);
147         i8 = extract64(i, b + 8 * 4, 4);
148         ic = extract64(i, b + 12 * 4, 4);
149 
150         t0 = rot_cell(i8, 1) ^ rot_cell(i4, 2) ^ rot_cell(i0, 1);
151         t1 = rot_cell(ic, 1) ^ rot_cell(i4, 1) ^ rot_cell(i0, 2);
152         t2 = rot_cell(ic, 2) ^ rot_cell(i8, 1) ^ rot_cell(i0, 1);
153         t3 = rot_cell(ic, 1) ^ rot_cell(i8, 2) ^ rot_cell(i4, 1);
154 
155         o |= (uint64_t)t3 << b;
156         o |= (uint64_t)t2 << (b + 4 * 4);
157         o |= (uint64_t)t1 << (b + 8 * 4);
158         o |= (uint64_t)t0 << (b + 12 * 4);
159     }
160     return o;
161 }
162 
163 static uint64_t tweak_cell_rot(uint64_t cell)
164 {
165     return (cell >> 1) | (((cell ^ (cell >> 1)) & 1) << 3);
166 }
167 
168 static uint64_t tweak_shuffle(uint64_t i)
169 {
170     uint64_t o = 0;
171 
172     o |= extract64(i, 16, 4) << 0;
173     o |= extract64(i, 20, 4) << 4;
174     o |= tweak_cell_rot(extract64(i, 24, 4)) << 8;
175     o |= extract64(i, 28, 4) << 12;
176 
177     o |= tweak_cell_rot(extract64(i, 44, 4)) << 16;
178     o |= extract64(i,  8, 4) << 20;
179     o |= extract64(i, 12, 4) << 24;
180     o |= tweak_cell_rot(extract64(i, 32, 4)) << 28;
181 
182     o |= extract64(i, 48, 4) << 32;
183     o |= extract64(i, 52, 4) << 36;
184     o |= extract64(i, 56, 4) << 40;
185     o |= tweak_cell_rot(extract64(i, 60, 4)) << 44;
186 
187     o |= tweak_cell_rot(extract64(i,  0, 4)) << 48;
188     o |= extract64(i,  4, 4) << 52;
189     o |= tweak_cell_rot(extract64(i, 40, 4)) << 56;
190     o |= tweak_cell_rot(extract64(i, 36, 4)) << 60;
191 
192     return o;
193 }
194 
195 static uint64_t tweak_cell_inv_rot(uint64_t cell)
196 {
197     return ((cell << 1) & 0xf) | ((cell & 1) ^ (cell >> 3));
198 }
199 
200 static uint64_t tweak_inv_shuffle(uint64_t i)
201 {
202     uint64_t o = 0;
203 
204     o |= tweak_cell_inv_rot(extract64(i, 48, 4));
205     o |= extract64(i, 52, 4) << 4;
206     o |= extract64(i, 20, 4) << 8;
207     o |= extract64(i, 24, 4) << 12;
208 
209     o |= extract64(i,  0, 4) << 16;
210     o |= extract64(i,  4, 4) << 20;
211     o |= tweak_cell_inv_rot(extract64(i,  8, 4)) << 24;
212     o |= extract64(i, 12, 4) << 28;
213 
214     o |= tweak_cell_inv_rot(extract64(i, 28, 4)) << 32;
215     o |= tweak_cell_inv_rot(extract64(i, 60, 4)) << 36;
216     o |= tweak_cell_inv_rot(extract64(i, 56, 4)) << 40;
217     o |= tweak_cell_inv_rot(extract64(i, 16, 4)) << 44;
218 
219     o |= extract64(i, 32, 4) << 48;
220     o |= extract64(i, 36, 4) << 52;
221     o |= extract64(i, 40, 4) << 56;
222     o |= tweak_cell_inv_rot(extract64(i, 44, 4)) << 60;
223 
224     return o;
225 }
226 
227 static uint64_t pauth_computepac_architected(uint64_t data, uint64_t modifier,
228                                              ARMPACKey key, bool isqarma3)
229 {
230     static const uint64_t RC[5] = {
231         0x0000000000000000ull,
232         0x13198A2E03707344ull,
233         0xA4093822299F31D0ull,
234         0x082EFA98EC4E6C89ull,
235         0x452821E638D01377ull,
236     };
237     const uint64_t alpha = 0xC0AC29B7C97C50DDull;
238     int iterations = isqarma3 ? 2 : 4;
239     /*
240      * Note that in the ARM pseudocode, key0 contains bits <127:64>
241      * and key1 contains bits <63:0> of the 128-bit key.
242      */
243     uint64_t key0 = key.hi, key1 = key.lo;
244     uint64_t workingval, runningmod, roundkey, modk0;
245     int i;
246 
247     modk0 = (key0 << 63) | ((key0 >> 1) ^ (key0 >> 63));
248     runningmod = modifier;
249     workingval = data ^ key0;
250 
251     for (i = 0; i <= iterations; ++i) {
252         roundkey = key1 ^ runningmod;
253         workingval ^= roundkey;
254         workingval ^= RC[i];
255         if (i > 0) {
256             workingval = pac_cell_shuffle(workingval);
257             workingval = pac_mult(workingval);
258         }
259         if (isqarma3) {
260             workingval = pac_sub1(workingval);
261         } else {
262             workingval = pac_sub(workingval);
263         }
264         runningmod = tweak_shuffle(runningmod);
265     }
266     roundkey = modk0 ^ runningmod;
267     workingval ^= roundkey;
268     workingval = pac_cell_shuffle(workingval);
269     workingval = pac_mult(workingval);
270     if (isqarma3) {
271         workingval = pac_sub1(workingval);
272     } else {
273         workingval = pac_sub(workingval);
274     }
275     workingval = pac_cell_shuffle(workingval);
276     workingval = pac_mult(workingval);
277     workingval ^= key1;
278     workingval = pac_cell_inv_shuffle(workingval);
279     if (isqarma3) {
280         workingval = pac_sub1(workingval);
281     } else {
282         workingval = pac_inv_sub(workingval);
283     }
284     workingval = pac_mult(workingval);
285     workingval = pac_cell_inv_shuffle(workingval);
286     workingval ^= key0;
287     workingval ^= runningmod;
288     for (i = 0; i <= iterations; ++i) {
289         if (isqarma3) {
290             workingval = pac_sub1(workingval);
291         } else {
292             workingval = pac_inv_sub(workingval);
293         }
294         if (i < iterations) {
295             workingval = pac_mult(workingval);
296             workingval = pac_cell_inv_shuffle(workingval);
297         }
298         runningmod = tweak_inv_shuffle(runningmod);
299         roundkey = key1 ^ runningmod;
300         workingval ^= RC[iterations - i];
301         workingval ^= roundkey;
302         workingval ^= alpha;
303     }
304     workingval ^= modk0;
305 
306     return workingval;
307 }
308 
309 static uint64_t pauth_computepac_impdef(uint64_t data, uint64_t modifier,
310                                         ARMPACKey key)
311 {
312     return qemu_xxhash64_4(data, modifier, key.lo, key.hi);
313 }
314 
315 static uint64_t pauth_computepac(CPUARMState *env, uint64_t data,
316                                  uint64_t modifier, ARMPACKey key)
317 {
318     if (cpu_isar_feature(aa64_pauth_qarma5, env_archcpu(env))) {
319         return pauth_computepac_architected(data, modifier, key, false);
320     } else if (cpu_isar_feature(aa64_pauth_qarma3, env_archcpu(env))) {
321         return pauth_computepac_architected(data, modifier, key, true);
322     } else {
323         return pauth_computepac_impdef(data, modifier, key);
324     }
325 }
326 
327 static uint64_t pauth_addpac(CPUARMState *env, uint64_t ptr, uint64_t modifier,
328                              ARMPACKey *key, bool data)
329 {
330     ARMCPU *cpu = env_archcpu(env);
331     ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env);
332     ARMVAParameters param = aa64_va_parameters(env, ptr, mmu_idx, data, false);
333     ARMPauthFeature pauth_feature = cpu_isar_feature(pauth_feature, cpu);
334     uint64_t pac, ext_ptr, ext, test;
335     int bot_bit, top_bit;
336 
337     /* If tagged pointers are in use, use ptr<55>, otherwise ptr<63>.  */
338     if (param.tbi) {
339         ext = sextract64(ptr, 55, 1);
340     } else {
341         ext = sextract64(ptr, 63, 1);
342     }
343 
344     /* Build a pointer with known good extension bits.  */
345     top_bit = 64 - 8 * param.tbi;
346     bot_bit = 64 - param.tsz;
347     ext_ptr = deposit64(ptr, bot_bit, top_bit - bot_bit, ext);
348 
349     pac = pauth_computepac(env, ext_ptr, modifier, *key);
350 
351     /*
352      * Check if the ptr has good extension bits and corrupt the
353      * pointer authentication code if not.
354      */
355     test = sextract64(ptr, bot_bit, top_bit - bot_bit);
356     if (test != 0 && test != -1) {
357         if (pauth_feature >= PauthFeat_2) {
358             /* No action required */
359         } else if (pauth_feature == PauthFeat_EPAC) {
360             pac = 0;
361         } else {
362             /*
363              * Note that our top_bit is one greater than the pseudocode's
364              * version, hence "- 2" here.
365              */
366             pac ^= MAKE_64BIT_MASK(top_bit - 2, 1);
367         }
368     }
369 
370     /*
371      * Preserve the determination between upper and lower at bit 55,
372      * and insert pointer authentication code.
373      */
374     if (pauth_feature >= PauthFeat_2) {
375         pac ^= ptr;
376     }
377     if (param.tbi) {
378         ptr &= ~MAKE_64BIT_MASK(bot_bit, 55 - bot_bit + 1);
379         pac &= MAKE_64BIT_MASK(bot_bit, 54 - bot_bit + 1);
380     } else {
381         ptr &= MAKE_64BIT_MASK(0, bot_bit);
382         pac &= ~(MAKE_64BIT_MASK(55, 1) | MAKE_64BIT_MASK(0, bot_bit));
383     }
384     ext &= MAKE_64BIT_MASK(55, 1);
385     return pac | ext | ptr;
386 }
387 
388 static uint64_t pauth_original_ptr(uint64_t ptr, ARMVAParameters param)
389 {
390     uint64_t mask = pauth_ptr_mask(param);
391 
392     /* Note that bit 55 is used whether or not the regime has 2 ranges. */
393     if (extract64(ptr, 55, 1)) {
394         return ptr | mask;
395     } else {
396         return ptr & ~mask;
397     }
398 }
399 
400 static G_NORETURN
401 void pauth_fail_exception(CPUARMState *env, bool data,
402                           int keynumber, uintptr_t ra)
403 {
404     raise_exception_ra(env, EXCP_UDEF, syn_pacfail(data, keynumber),
405                        exception_target_el(env), ra);
406 }
407 
408 static uint64_t pauth_auth(CPUARMState *env, uint64_t ptr, uint64_t modifier,
409                            ARMPACKey *key, bool data, int keynumber,
410                            uintptr_t ra, bool is_combined)
411 {
412     ARMCPU *cpu = env_archcpu(env);
413     ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env);
414     ARMVAParameters param = aa64_va_parameters(env, ptr, mmu_idx, data, false);
415     ARMPauthFeature pauth_feature = cpu_isar_feature(pauth_feature, cpu);
416     int bot_bit, top_bit;
417     uint64_t pac, orig_ptr, cmp_mask;
418 
419     orig_ptr = pauth_original_ptr(ptr, param);
420     pac = pauth_computepac(env, orig_ptr, modifier, *key);
421     bot_bit = 64 - param.tsz;
422     top_bit = 64 - 8 * param.tbi;
423 
424     cmp_mask = MAKE_64BIT_MASK(bot_bit, top_bit - bot_bit);
425     cmp_mask &= ~MAKE_64BIT_MASK(55, 1);
426 
427     if (pauth_feature >= PauthFeat_2) {
428         ARMPauthFeature fault_feature =
429             is_combined ? PauthFeat_FPACCOMBINED : PauthFeat_FPAC;
430         uint64_t result = ptr ^ (pac & cmp_mask);
431 
432         if (pauth_feature >= fault_feature
433             && ((result ^ sextract64(result, 55, 1)) & cmp_mask)) {
434             pauth_fail_exception(env, data, keynumber, ra);
435         }
436         return result;
437     }
438 
439     if ((pac ^ ptr) & cmp_mask) {
440         int error_code = (keynumber << 1) | (keynumber ^ 1);
441         if (param.tbi) {
442             return deposit64(orig_ptr, 53, 2, error_code);
443         } else {
444             return deposit64(orig_ptr, 61, 2, error_code);
445         }
446     }
447     return orig_ptr;
448 }
449 
450 static uint64_t pauth_strip(CPUARMState *env, uint64_t ptr, bool data)
451 {
452     ARMMMUIdx mmu_idx = arm_stage1_mmu_idx(env);
453     ARMVAParameters param = aa64_va_parameters(env, ptr, mmu_idx, data, false);
454 
455     return pauth_original_ptr(ptr, param);
456 }
457 
458 static G_NORETURN
459 void pauth_trap(CPUARMState *env, int target_el, uintptr_t ra)
460 {
461     raise_exception_ra(env, EXCP_UDEF, syn_pactrap(), target_el, ra);
462 }
463 
464 static void pauth_check_trap(CPUARMState *env, int el, uintptr_t ra)
465 {
466     if (el < 2 && arm_is_el2_enabled(env)) {
467         uint64_t hcr = arm_hcr_el2_eff(env);
468         bool trap = !(hcr & HCR_API);
469         if (el == 0) {
470             /* Trap only applies to EL1&0 regime.  */
471             trap &= (hcr & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE);
472         }
473         /* FIXME: ARMv8.3-NV: HCR_NV trap takes precedence for ERETA[AB].  */
474         if (trap) {
475             pauth_trap(env, 2, ra);
476         }
477     }
478     if (el < 3 && arm_feature(env, ARM_FEATURE_EL3)) {
479         if (!(env->cp15.scr_el3 & SCR_API)) {
480             pauth_trap(env, 3, ra);
481         }
482     }
483 }
484 
485 static bool pauth_key_enabled(CPUARMState *env, int el, uint32_t bit)
486 {
487     return (arm_sctlr(env, el) & bit) != 0;
488 }
489 
490 uint64_t HELPER(pacia)(CPUARMState *env, uint64_t x, uint64_t y)
491 {
492     int el = arm_current_el(env);
493     if (!pauth_key_enabled(env, el, SCTLR_EnIA)) {
494         return x;
495     }
496     pauth_check_trap(env, el, GETPC());
497     return pauth_addpac(env, x, y, &env->keys.apia, false);
498 }
499 
500 uint64_t HELPER(pacib)(CPUARMState *env, uint64_t x, uint64_t y)
501 {
502     int el = arm_current_el(env);
503     if (!pauth_key_enabled(env, el, SCTLR_EnIB)) {
504         return x;
505     }
506     pauth_check_trap(env, el, GETPC());
507     return pauth_addpac(env, x, y, &env->keys.apib, false);
508 }
509 
510 uint64_t HELPER(pacda)(CPUARMState *env, uint64_t x, uint64_t y)
511 {
512     int el = arm_current_el(env);
513     if (!pauth_key_enabled(env, el, SCTLR_EnDA)) {
514         return x;
515     }
516     pauth_check_trap(env, el, GETPC());
517     return pauth_addpac(env, x, y, &env->keys.apda, true);
518 }
519 
520 uint64_t HELPER(pacdb)(CPUARMState *env, uint64_t x, uint64_t y)
521 {
522     int el = arm_current_el(env);
523     if (!pauth_key_enabled(env, el, SCTLR_EnDB)) {
524         return x;
525     }
526     pauth_check_trap(env, el, GETPC());
527     return pauth_addpac(env, x, y, &env->keys.apdb, true);
528 }
529 
530 uint64_t HELPER(pacga)(CPUARMState *env, uint64_t x, uint64_t y)
531 {
532     uint64_t pac;
533 
534     pauth_check_trap(env, arm_current_el(env), GETPC());
535     pac = pauth_computepac(env, x, y, env->keys.apga);
536 
537     return pac & 0xffffffff00000000ull;
538 }
539 
540 static uint64_t pauth_autia(CPUARMState *env, uint64_t x, uint64_t y,
541                             uintptr_t ra, bool is_combined)
542 {
543     int el = arm_current_el(env);
544     if (!pauth_key_enabled(env, el, SCTLR_EnIA)) {
545         return x;
546     }
547     pauth_check_trap(env, el, ra);
548     return pauth_auth(env, x, y, &env->keys.apia, false, 0, ra, is_combined);
549 }
550 
551 uint64_t HELPER(autia)(CPUARMState *env, uint64_t x, uint64_t y)
552 {
553     return pauth_autia(env, x, y, GETPC(), false);
554 }
555 
556 uint64_t HELPER(autia_combined)(CPUARMState *env, uint64_t x, uint64_t y)
557 {
558     return pauth_autia(env, x, y, GETPC(), true);
559 }
560 
561 static uint64_t pauth_autib(CPUARMState *env, uint64_t x, uint64_t y,
562                             uintptr_t ra, bool is_combined)
563 {
564     int el = arm_current_el(env);
565     if (!pauth_key_enabled(env, el, SCTLR_EnIB)) {
566         return x;
567     }
568     pauth_check_trap(env, el, ra);
569     return pauth_auth(env, x, y, &env->keys.apib, false, 1, ra, is_combined);
570 }
571 
572 uint64_t HELPER(autib)(CPUARMState *env, uint64_t x, uint64_t y)
573 {
574     return pauth_autib(env, x, y, GETPC(), false);
575 }
576 
577 uint64_t HELPER(autib_combined)(CPUARMState *env, uint64_t x, uint64_t y)
578 {
579     return pauth_autib(env, x, y, GETPC(), true);
580 }
581 
582 static uint64_t pauth_autda(CPUARMState *env, uint64_t x, uint64_t y,
583                             uintptr_t ra, bool is_combined)
584 {
585     int el = arm_current_el(env);
586     if (!pauth_key_enabled(env, el, SCTLR_EnDA)) {
587         return x;
588     }
589     pauth_check_trap(env, el, ra);
590     return pauth_auth(env, x, y, &env->keys.apda, true, 0, ra, is_combined);
591 }
592 
593 uint64_t HELPER(autda)(CPUARMState *env, uint64_t x, uint64_t y)
594 {
595     return pauth_autda(env, x, y, GETPC(), false);
596 }
597 
598 uint64_t HELPER(autda_combined)(CPUARMState *env, uint64_t x, uint64_t y)
599 {
600     return pauth_autda(env, x, y, GETPC(), true);
601 }
602 
603 static uint64_t pauth_autdb(CPUARMState *env, uint64_t x, uint64_t y,
604                             uintptr_t ra, bool is_combined)
605 {
606     int el = arm_current_el(env);
607     if (!pauth_key_enabled(env, el, SCTLR_EnDB)) {
608         return x;
609     }
610     pauth_check_trap(env, el, ra);
611     return pauth_auth(env, x, y, &env->keys.apdb, true, 1, ra, is_combined);
612 }
613 
614 uint64_t HELPER(autdb)(CPUARMState *env, uint64_t x, uint64_t y)
615 {
616     return pauth_autdb(env, x, y, GETPC(), false);
617 }
618 
619 uint64_t HELPER(autdb_combined)(CPUARMState *env, uint64_t x, uint64_t y)
620 {
621     return pauth_autdb(env, x, y, GETPC(), true);
622 }
623 
624 uint64_t HELPER(xpaci)(CPUARMState *env, uint64_t a)
625 {
626     return pauth_strip(env, a, false);
627 }
628 
629 uint64_t HELPER(xpacd)(CPUARMState *env, uint64_t a)
630 {
631     return pauth_strip(env, a, true);
632 }
633