1238384Sjkim/* 2238384Sjkim * __mtag_tag_region - tag memory 3238384Sjkim * 4238384Sjkim * Copyright (c) 2021-2022, Arm Limited. 5238384Sjkim * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception 6238384Sjkim */ 7238384Sjkim 8238384Sjkim/* Assumptions: 9238384Sjkim * 10238384Sjkim * ARMv8-a, AArch64, MTE, LP64 ABI. 11238384Sjkim * 12238384Sjkim * Interface contract: 13238384Sjkim * Address is 16 byte aligned and size is multiple of 16. 14238384Sjkim * Returns the passed pointer. 15238384Sjkim * The memory region may remain untagged if tagging is not enabled. 16238384Sjkim */ 17238384Sjkim 18238384Sjkim#include "asmdefs.h" 19238384Sjkim 20238384Sjkim#if __ARM_FEATURE_MEMORY_TAGGING 21238384Sjkim 22238384Sjkim#define dstin x0 23238384Sjkim#define count x1 24238384Sjkim#define dst x2 25238384Sjkim#define dstend x3 26238384Sjkim#define tmp x4 27238384Sjkim#define zva_val x4 28238384Sjkim 29238384SjkimENTRY (__mtag_tag_region) 30238384Sjkim PTR_ARG (0) 31238384Sjkim SIZE_ARG (1) 32238384Sjkim 33238384Sjkim add dstend, dstin, count 34238384Sjkim 35238384Sjkim cmp count, 96 36238384Sjkim b.hi L(set_long) 37238384Sjkim 38238384Sjkim tbnz count, 6, L(set96) 39238384Sjkim 40238384Sjkim /* Set 0, 16, 32, or 48 bytes. */ 41238384Sjkim lsr tmp, count, 5 42238384Sjkim add tmp, dstin, tmp, lsl 4 43238384Sjkim cbz count, L(end) 44238384Sjkim stg dstin, [dstin] 45238384Sjkim stg dstin, [tmp] 46238384Sjkim stg dstin, [dstend, -16] 47238384SjkimL(end): 48238384Sjkim ret 49238384Sjkim 50238384Sjkim .p2align 4 51238384Sjkim /* Set 64..96 bytes. Write 64 bytes from the start and 52238384Sjkim 32 bytes from the end. */ 53238384SjkimL(set96): 54238384Sjkim st2g dstin, [dstin] 55238384Sjkim st2g dstin, [dstin, 32] 56238384Sjkim st2g dstin, [dstend, -32] 57238384Sjkim ret 58238384Sjkim 59238384Sjkim .p2align 4 60238384Sjkim /* Size is > 96 bytes. */ 61238384SjkimL(set_long): 62238384Sjkim cmp count, 160 63238384Sjkim b.lo L(no_zva) 64238384Sjkim 65238384Sjkim#ifndef SKIP_ZVA_CHECK 66238384Sjkim mrs zva_val, dczid_el0 67238384Sjkim and zva_val, zva_val, 31 68238384Sjkim cmp zva_val, 4 /* ZVA size is 64 bytes. */ 69238384Sjkim b.ne L(no_zva) 70238384Sjkim#endif 71238384Sjkim st2g dstin, [dstin] 72238384Sjkim st2g dstin, [dstin, 32] 73238384Sjkim bic dst, dstin, 63 74238384Sjkim sub count, dstend, dst /* Count is now 64 too large. */ 75238384Sjkim sub count, count, 128 /* Adjust count and bias for loop. */ 76238384Sjkim 77238384Sjkim .p2align 4 78238384SjkimL(zva_loop): 79238384Sjkim add dst, dst, 64 80238384Sjkim dc gva, dst 81238384Sjkim subs count, count, 64 82238384Sjkim b.hi L(zva_loop) 83238384Sjkim st2g dstin, [dstend, -64] 84238384Sjkim st2g dstin, [dstend, -32] 85238384Sjkim ret 86238384Sjkim 87238384SjkimL(no_zva): 88238384Sjkim sub dst, dstin, 32 /* Dst is biased by -32. */ 89238384Sjkim sub count, count, 64 /* Adjust count for loop. */ 90238384SjkimL(no_zva_loop): 91238384Sjkim st2g dstin, [dst, 32] 92238384Sjkim st2g dstin, [dst, 64]! 93238384Sjkim subs count, count, 64 94238384Sjkim b.hi L(no_zva_loop) 95238384Sjkim st2g dstin, [dstend, -64] 96238384Sjkim st2g dstin, [dstend, -32] 97238384Sjkim ret 98238384Sjkim 99238384SjkimEND (__mtag_tag_region) 100238384Sjkim#endif 101238384Sjkim