Path: blob/main/contrib/arm-optimized-routines/string/arm/asmdefs.h
39556 views
/*1* Macros for asm code. Arm version.2*3* Copyright (c) 2019-2022, Arm Limited.4* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception5*/67#ifndef _ASMDEFS_H8#define _ASMDEFS_H910/* Check whether leaf function PAC signing has been requested in the11-mbranch-protect compile-time option. */12#define LEAF_PROTECT_BIT 21314#ifdef __ARM_FEATURE_PAC_DEFAULT15# define HAVE_PAC_LEAF \16((__ARM_FEATURE_PAC_DEFAULT & (1 << LEAF_PROTECT_BIT)) && 1)17#else18# define HAVE_PAC_LEAF 019#endif2021/* Provide default parameters for PAC-code handling in leaf-functions. */22#if HAVE_PAC_LEAF23# ifndef PAC_LEAF_PUSH_IP24# define PAC_LEAF_PUSH_IP 125# endif26#else /* !HAVE_PAC_LEAF */27# undef PAC_LEAF_PUSH_IP28# define PAC_LEAF_PUSH_IP 029#endif /* HAVE_PAC_LEAF */3031#define STACK_ALIGN_ENFORCE 03233/******************************************************************************34* Implementation of the prologue and epilogue assembler macros and their35* associated helper functions.36*37* These functions add support for the following:38*39* - M-profile branch target identification (BTI) landing-pads when compiled40* with `-mbranch-protection=bti'.41* - PAC-signing and verification instructions, depending on hardware support42* and whether the PAC-signing of leaf functions has been requested via the43* `-mbranch-protection=pac-ret+leaf' compiler argument.44* - 8-byte stack alignment preservation at function entry, defaulting to the45* value of STACK_ALIGN_ENFORCE.46*47* Notes:48* - Prologue stack alignment is implemented by detecting a push with an odd49* number of registers and prepending a dummy register to the list.50* - If alignment is attempted on a list containing r0, compilation will result51* in an error.52* - If alignment is attempted in a list containing r1, r0 will be prepended to53* the register list and r0 will be restored prior to function return. for54* functions with non-void return types, this will result in the corruption of55* the result register.56* - Stack alignment is enforced via the following helper macro call-chain:57*58* {prologue|epilogue} ->_align8 -> _preprocess_reglist ->59* _preprocess_reglist1 -> {_prologue|_epilogue}60*61* - Debug CFI directives are automatically added to prologues and epilogues,62* assisted by `cfisavelist' and `cfirestorelist', respectively.63*64* Arguments:65* prologue66* --------67* - first - If `last' specified, this serves as start of general-purpose68* register (GPR) range to push onto stack, otherwise represents69* single GPR to push onto stack. If omitted, no GPRs pushed70* onto stack at prologue.71* - last - If given, specifies inclusive upper-bound of GPR range.72* - push_ip - Determines whether IP register is to be pushed to stack at73* prologue. When pac-signing is requested, this holds the74* the pac-key. Either 1 or 0 to push or not push, respectively.75* Default behavior: Set to value of PAC_LEAF_PUSH_IP macro.76* - push_lr - Determines whether to push lr to the stack on function entry.77* Either 1 or 0 to push or not push, respectively.78* - align8 - Whether to enforce alignment. Either 1 or 0, with 1 requesting79* alignment.80*81* epilogue82* --------83* The epilogue should be called passing the same arguments as those passed to84* the prologue to ensure the stack is not corrupted on function return.85*86* Usage examples:87*88* prologue push_ip=1 -> push {ip}89* epilogue push_ip=1, align8=1 -> pop {r2, ip}90* prologue push_ip=1, push_lr=1 -> push {ip, lr}91* epilogue 1 -> pop {r1}92* prologue 1, align8=1 -> push {r0, r1}93* epilogue 1, push_ip=1 -> pop {r1, ip}94* prologue 1, 4 -> push {r1-r4}95* epilogue 1, 4 push_ip=1 -> pop {r1-r4, ip}96*97******************************************************************************/9899/* Emit .cfi_restore directives for a consecutive sequence of registers. */100.macro cfirestorelist first, last101.cfi_restore \last102.if \last-\first103cfirestorelist \first, \last-1104.endif105.endm106107/* Emit .cfi_offset directives for a consecutive sequence of registers. */108.macro cfisavelist first, last, index=1109.cfi_offset \last, -4*(\index)110.if \last-\first111cfisavelist \first, \last-1, \index+1112.endif113.endm114115.macro _prologue first=-1, last=-1, push_ip=PAC_LEAF_PUSH_IP, push_lr=0116.if \push_ip & 1 != \push_ip117.error "push_ip may be either 0 or 1"118.endif119.if \push_lr & 1 != \push_lr120.error "push_lr may be either 0 or 1"121.endif122.if \first != -1123.if \last == -1124/* Upper-bound not provided: Set upper = lower. */125_prologue \first, \first, \push_ip, \push_lr126.exitm127.endif128.endif129#if HAVE_PAC_LEAF130# if __ARM_FEATURE_BTI_DEFAULT131pacbti ip, lr, sp132# else133pac ip, lr, sp134# endif /* __ARM_FEATURE_BTI_DEFAULT */135.cfi_register 143, 12136#else137# if __ARM_FEATURE_BTI_DEFAULT138bti139# endif /* __ARM_FEATURE_BTI_DEFAULT */140#endif /* HAVE_PAC_LEAF */141.if \first != -1142.if \last != \first143.if \last >= 13144.error "SP cannot be in the save list"145.endif146.if \push_ip147.if \push_lr148/* Case 1: push register range, ip and lr registers. */149push {r\first-r\last, ip, lr}150.cfi_adjust_cfa_offset ((\last-\first)+3)*4151.cfi_offset 14, -4152.cfi_offset 143, -8153cfisavelist \first, \last, 3154.else // !\push_lr155/* Case 2: push register range and ip register. */156push {r\first-r\last, ip}157.cfi_adjust_cfa_offset ((\last-\first)+2)*4158.cfi_offset 143, -4159cfisavelist \first, \last, 2160.endif161.else // !\push_ip162.if \push_lr163/* Case 3: push register range and lr register. */164push {r\first-r\last, lr}165.cfi_adjust_cfa_offset ((\last-\first)+2)*4166.cfi_offset 14, -4167cfisavelist \first, \last, 2168.else // !\push_lr169/* Case 4: push register range. */170push {r\first-r\last}171.cfi_adjust_cfa_offset ((\last-\first)+1)*4172cfisavelist \first, \last, 1173.endif174.endif175.else // \last == \first176.if \push_ip177.if \push_lr178/* Case 5: push single GP register plus ip and lr registers. */179push {r\first, ip, lr}180.cfi_adjust_cfa_offset 12181.cfi_offset 14, -4182.cfi_offset 143, -8183cfisavelist \first, \first, 3184.else // !\push_lr185/* Case 6: push single GP register plus ip register. */186push {r\first, ip}187.cfi_adjust_cfa_offset 8188.cfi_offset 143, -4189cfisavelist \first, \first, 2190.endif191.else // !\push_ip192.if \push_lr193/* Case 7: push single GP register plus lr register. */194push {r\first, lr}195.cfi_adjust_cfa_offset 8196.cfi_offset 14, -4197cfisavelist \first, \first, 2198.else // !\push_lr199/* Case 8: push single GP register. */200push {r\first}201.cfi_adjust_cfa_offset 4202cfisavelist \first, \first, 1203.endif204.endif205.endif206.else // \first == -1207.if \push_ip208.if \push_lr209/* Case 9: push ip and lr registers. */210push {ip, lr}211.cfi_adjust_cfa_offset 8212.cfi_offset 14, -4213.cfi_offset 143, -8214.else // !\push_lr215/* Case 10: push ip register. */216push {ip}217.cfi_adjust_cfa_offset 4218.cfi_offset 143, -4219.endif220.else // !\push_ip221.if \push_lr222/* Case 11: push lr register. */223push {lr}224.cfi_adjust_cfa_offset 4225.cfi_offset 14, -4226.endif227.endif228.endif229.endm230231.macro _epilogue first=-1, last=-1, push_ip=PAC_LEAF_PUSH_IP, push_lr=0232.if \push_ip & 1 != \push_ip233.error "push_ip may be either 0 or 1"234.endif235.if \push_lr & 1 != \push_lr236.error "push_lr may be either 0 or 1"237.endif238.if \first != -1239.if \last == -1240/* Upper-bound not provided: Set upper = lower. */241_epilogue \first, \first, \push_ip, \push_lr242.exitm243.endif244.if \last != \first245.if \last >= 13246.error "SP cannot be in the save list"247.endif248.if \push_ip249.if \push_lr250/* Case 1: pop register range, ip and lr registers. */251pop {r\first-r\last, ip, lr}252.cfi_restore 14253.cfi_register 143, 12254cfirestorelist \first, \last255.else // !\push_lr256/* Case 2: pop register range and ip register. */257pop {r\first-r\last, ip}258.cfi_register 143, 12259cfirestorelist \first, \last260.endif261.else // !\push_ip262.if \push_lr263/* Case 3: pop register range and lr register. */264pop {r\first-r\last, lr}265.cfi_restore 14266cfirestorelist \first, \last267.else // !\push_lr268/* Case 4: pop register range. */269pop {r\first-r\last}270cfirestorelist \first, \last271.endif272.endif273.else // \last == \first274.if \push_ip275.if \push_lr276/* Case 5: pop single GP register plus ip and lr registers. */277pop {r\first, ip, lr}278.cfi_restore 14279.cfi_register 143, 12280cfirestorelist \first, \first281.else // !\push_lr282/* Case 6: pop single GP register plus ip register. */283pop {r\first, ip}284.cfi_register 143, 12285cfirestorelist \first, \first286.endif287.else // !\push_ip288.if \push_lr289/* Case 7: pop single GP register plus lr register. */290pop {r\first, lr}291.cfi_restore 14292cfirestorelist \first, \first293.else // !\push_lr294/* Case 8: pop single GP register. */295pop {r\first}296cfirestorelist \first, \first297.endif298.endif299.endif300.else // \first == -1301.if \push_ip302.if \push_lr303/* Case 9: pop ip and lr registers. */304pop {ip, lr}305.cfi_restore 14306.cfi_register 143, 12307.else // !\push_lr308/* Case 10: pop ip register. */309pop {ip}310.cfi_register 143, 12311.endif312.else // !\push_ip313.if \push_lr314/* Case 11: pop lr register. */315pop {lr}316.cfi_restore 14317.endif318.endif319.endif320#if HAVE_PAC_LEAF321aut ip, lr, sp322#endif /* HAVE_PAC_LEAF */323bx lr324.endm325326/* Clean up expressions in 'last'. */327.macro _preprocess_reglist1 first:req, last:req, push_ip:req, push_lr:req, reglist_op:req328.if \last == 0329\reglist_op \first, 0, \push_ip, \push_lr330.elseif \last == 1331\reglist_op \first, 1, \push_ip, \push_lr332.elseif \last == 2333\reglist_op \first, 2, \push_ip, \push_lr334.elseif \last == 3335\reglist_op \first, 3, \push_ip, \push_lr336.elseif \last == 4337\reglist_op \first, 4, \push_ip, \push_lr338.elseif \last == 5339\reglist_op \first, 5, \push_ip, \push_lr340.elseif \last == 6341\reglist_op \first, 6, \push_ip, \push_lr342.elseif \last == 7343\reglist_op \first, 7, \push_ip, \push_lr344.elseif \last == 8345\reglist_op \first, 8, \push_ip, \push_lr346.elseif \last == 9347\reglist_op \first, 9, \push_ip, \push_lr348.elseif \last == 10349\reglist_op \first, 10, \push_ip, \push_lr350.elseif \last == 11351\reglist_op \first, 11, \push_ip, \push_lr352.else353.error "last (\last) out of range"354.endif355.endm356357/* Clean up expressions in 'first'. */358.macro _preprocess_reglist first:req, last, push_ip=0, push_lr=0, reglist_op:req359.ifb \last360_preprocess_reglist \first \first \push_ip \push_lr361.else362.if \first > \last363.error "last (\last) must be at least as great as first (\first)"364.endif365.if \first == 0366_preprocess_reglist1 0, \last, \push_ip, \push_lr, \reglist_op367.elseif \first == 1368_preprocess_reglist1 1, \last, \push_ip, \push_lr, \reglist_op369.elseif \first == 2370_preprocess_reglist1 2, \last, \push_ip, \push_lr, \reglist_op371.elseif \first == 3372_preprocess_reglist1 3, \last, \push_ip, \push_lr, \reglist_op373.elseif \first == 4374_preprocess_reglist1 4, \last, \push_ip, \push_lr, \reglist_op375.elseif \first == 5376_preprocess_reglist1 5, \last, \push_ip, \push_lr, \reglist_op377.elseif \first == 6378_preprocess_reglist1 6, \last, \push_ip, \push_lr, \reglist_op379.elseif \first == 7380_preprocess_reglist1 7, \last, \push_ip, \push_lr, \reglist_op381.elseif \first == 8382_preprocess_reglist1 8, \last, \push_ip, \push_lr, \reglist_op383.elseif \first == 9384_preprocess_reglist1 9, \last, \push_ip, \push_lr, \reglist_op385.elseif \first == 10386_preprocess_reglist1 10, \last, \push_ip, \push_lr, \reglist_op387.elseif \first == 11388_preprocess_reglist1 11, \last, \push_ip, \push_lr, \reglist_op389.else390.error "first (\first) out of range"391.endif392.endif393.endm394395.macro _align8 first, last, push_ip=0, push_lr=0, reglist_op=_prologue396.ifb \first397.ifnb \last398.error "can't have last (\last) without specifying first"399.else // \last not blank400.if ((\push_ip + \push_lr) % 2) == 0401\reglist_op first=-1, last=-1, push_ip=\push_ip, push_lr=\push_lr402.exitm403.else // ((\push_ip + \push_lr) % 2) odd404_align8 2, 2, \push_ip, \push_lr, \reglist_op405.exitm406.endif // ((\push_ip + \push_lr) % 2) == 0407.endif // .ifnb \last408.endif // .ifb \first409410.ifb \last411_align8 \first, \first, \push_ip, \push_lr, \reglist_op412.else413.if \push_ip & 1 <> \push_ip414.error "push_ip may be 0 or 1"415.endif416.if \push_lr & 1 <> \push_lr417.error "push_lr may be 0 or 1"418.endif419.ifeq (\last - \first + \push_ip + \push_lr) % 2420.if \first == 0421.error "Alignment required and first register is r0"422.exitm423.endif424_preprocess_reglist \first-1, \last, \push_ip, \push_lr, \reglist_op425.else426_preprocess_reglist \first \last, \push_ip, \push_lr, \reglist_op427.endif428.endif429.endm430431.macro prologue first, last, push_ip=PAC_LEAF_PUSH_IP, push_lr=0, align8=STACK_ALIGN_ENFORCE432.if \align8433_align8 \first, \last, \push_ip, \push_lr, _prologue434.else435_prologue first=\first, last=\last, push_ip=\push_ip, push_lr=\push_lr436.endif437.endm438439.macro epilogue first, last, push_ip=PAC_LEAF_PUSH_IP, push_lr=0, align8=STACK_ALIGN_ENFORCE440.if \align8441_align8 \first, \last, \push_ip, \push_lr, reglist_op=_epilogue442.else443_epilogue first=\first, last=\last, push_ip=\push_ip, push_lr=\push_lr444.endif445.endm446447#define ENTRY_ALIGN(name, alignment) \448.global name; \449.type name,%function; \450.align alignment; \451name: \452.fnstart; \453.cfi_startproc;454455#define ENTRY(name) ENTRY_ALIGN(name, 6)456457#define ENTRY_ALIAS(name) \458.global name; \459.type name,%function; \460name:461462#if defined (IS_LEAF)463# define END_UNWIND .cantunwind;464#else465# define END_UNWIND466#endif467468#define END(name) \469.cfi_endproc; \470END_UNWIND \471.fnend; \472.size name, .-name;473474#define L(l) .L ## l475476#endif477478479