1*072a4ba8SAndrew Turner /* 2*072a4ba8SAndrew Turner * Macros for asm code. Arm version. 3*072a4ba8SAndrew Turner * 4*072a4ba8SAndrew Turner * Copyright (c) 2019-2022, Arm Limited. 5*072a4ba8SAndrew Turner * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception 6*072a4ba8SAndrew Turner */ 7*072a4ba8SAndrew Turner 8*072a4ba8SAndrew Turner #ifndef _ASMDEFS_H 9*072a4ba8SAndrew Turner #define _ASMDEFS_H 10*072a4ba8SAndrew Turner 11*072a4ba8SAndrew Turner /* Check whether leaf function PAC signing has been requested in the 12*072a4ba8SAndrew Turner -mbranch-protect compile-time option. */ 13*072a4ba8SAndrew Turner #define LEAF_PROTECT_BIT 2 14*072a4ba8SAndrew Turner 15*072a4ba8SAndrew Turner #ifdef __ARM_FEATURE_PAC_DEFAULT 16*072a4ba8SAndrew Turner # define HAVE_PAC_LEAF \ 17*072a4ba8SAndrew Turner ((__ARM_FEATURE_PAC_DEFAULT & (1 << LEAF_PROTECT_BIT)) && 1) 18*072a4ba8SAndrew Turner #else 19*072a4ba8SAndrew Turner # define HAVE_PAC_LEAF 0 20*072a4ba8SAndrew Turner #endif 21*072a4ba8SAndrew Turner 22*072a4ba8SAndrew Turner /* Provide default parameters for PAC-code handling in leaf-functions. */ 23*072a4ba8SAndrew Turner #if HAVE_PAC_LEAF 24*072a4ba8SAndrew Turner # ifndef PAC_LEAF_PUSH_IP 25*072a4ba8SAndrew Turner # define PAC_LEAF_PUSH_IP 1 26*072a4ba8SAndrew Turner # endif 27*072a4ba8SAndrew Turner #else /* !HAVE_PAC_LEAF */ 28*072a4ba8SAndrew Turner # undef PAC_LEAF_PUSH_IP 29*072a4ba8SAndrew Turner # define PAC_LEAF_PUSH_IP 0 30*072a4ba8SAndrew Turner #endif /* HAVE_PAC_LEAF */ 31*072a4ba8SAndrew Turner 32*072a4ba8SAndrew Turner #define STACK_ALIGN_ENFORCE 0 33*072a4ba8SAndrew Turner 34*072a4ba8SAndrew Turner /****************************************************************************** 35*072a4ba8SAndrew Turner * Implementation of the prologue and epilogue assembler macros and their 36*072a4ba8SAndrew Turner * associated helper functions. 37*072a4ba8SAndrew Turner * 38*072a4ba8SAndrew Turner * These functions add support for the following: 39*072a4ba8SAndrew Turner * 40*072a4ba8SAndrew Turner * - M-profile branch target identification (BTI) landing-pads when compiled 41*072a4ba8SAndrew Turner * with `-mbranch-protection=bti'. 42*072a4ba8SAndrew Turner * - PAC-signing and verification instructions, depending on hardware support 43*072a4ba8SAndrew Turner * and whether the PAC-signing of leaf functions has been requested via the 44*072a4ba8SAndrew Turner * `-mbranch-protection=pac-ret+leaf' compiler argument. 45*072a4ba8SAndrew Turner * - 8-byte stack alignment preservation at function entry, defaulting to the 46*072a4ba8SAndrew Turner * value of STACK_ALIGN_ENFORCE. 47*072a4ba8SAndrew Turner * 48*072a4ba8SAndrew Turner * Notes: 49*072a4ba8SAndrew Turner * - Prologue stack alignment is implemented by detecting a push with an odd 50*072a4ba8SAndrew Turner * number of registers and prepending a dummy register to the list. 51*072a4ba8SAndrew Turner * - If alignment is attempted on a list containing r0, compilation will result 52*072a4ba8SAndrew Turner * in an error. 53*072a4ba8SAndrew Turner * - If alignment is attempted in a list containing r1, r0 will be prepended to 54*072a4ba8SAndrew Turner * the register list and r0 will be restored prior to function return. for 55*072a4ba8SAndrew Turner * functions with non-void return types, this will result in the corruption of 56*072a4ba8SAndrew Turner * the result register. 57*072a4ba8SAndrew Turner * - Stack alignment is enforced via the following helper macro call-chain: 58*072a4ba8SAndrew Turner * 59*072a4ba8SAndrew Turner * {prologue|epilogue} ->_align8 -> _preprocess_reglist -> 60*072a4ba8SAndrew Turner * _preprocess_reglist1 -> {_prologue|_epilogue} 61*072a4ba8SAndrew Turner * 62*072a4ba8SAndrew Turner * - Debug CFI directives are automatically added to prologues and epilogues, 63*072a4ba8SAndrew Turner * assisted by `cfisavelist' and `cfirestorelist', respectively. 64*072a4ba8SAndrew Turner * 65*072a4ba8SAndrew Turner * Arguments: 66*072a4ba8SAndrew Turner * prologue 67*072a4ba8SAndrew Turner * -------- 68*072a4ba8SAndrew Turner * - first - If `last' specified, this serves as start of general-purpose 69*072a4ba8SAndrew Turner * register (GPR) range to push onto stack, otherwise represents 70*072a4ba8SAndrew Turner * single GPR to push onto stack. If omitted, no GPRs pushed 71*072a4ba8SAndrew Turner * onto stack at prologue. 72*072a4ba8SAndrew Turner * - last - If given, specifies inclusive upper-bound of GPR range. 73*072a4ba8SAndrew Turner * - push_ip - Determines whether IP register is to be pushed to stack at 74*072a4ba8SAndrew Turner * prologue. When pac-signing is requested, this holds the 75*072a4ba8SAndrew Turner * the pac-key. Either 1 or 0 to push or not push, respectively. 76*072a4ba8SAndrew Turner * Default behavior: Set to value of PAC_LEAF_PUSH_IP macro. 77*072a4ba8SAndrew Turner * - push_lr - Determines whether to push lr to the stack on function entry. 78*072a4ba8SAndrew Turner * Either 1 or 0 to push or not push, respectively. 79*072a4ba8SAndrew Turner * - align8 - Whether to enforce alignment. Either 1 or 0, with 1 requesting 80*072a4ba8SAndrew Turner * alignment. 81*072a4ba8SAndrew Turner * 82*072a4ba8SAndrew Turner * epilogue 83*072a4ba8SAndrew Turner * -------- 84*072a4ba8SAndrew Turner * The epilogue should be called passing the same arguments as those passed to 85*072a4ba8SAndrew Turner * the prologue to ensure the stack is not corrupted on function return. 86*072a4ba8SAndrew Turner * 87*072a4ba8SAndrew Turner * Usage examples: 88*072a4ba8SAndrew Turner * 89*072a4ba8SAndrew Turner * prologue push_ip=1 -> push {ip} 90*072a4ba8SAndrew Turner * epilogue push_ip=1, align8=1 -> pop {r2, ip} 91*072a4ba8SAndrew Turner * prologue push_ip=1, push_lr=1 -> push {ip, lr} 92*072a4ba8SAndrew Turner * epilogue 1 -> pop {r1} 93*072a4ba8SAndrew Turner * prologue 1, align8=1 -> push {r0, r1} 94*072a4ba8SAndrew Turner * epilogue 1, push_ip=1 -> pop {r1, ip} 95*072a4ba8SAndrew Turner * prologue 1, 4 -> push {r1-r4} 96*072a4ba8SAndrew Turner * epilogue 1, 4 push_ip=1 -> pop {r1-r4, ip} 97*072a4ba8SAndrew Turner * 98*072a4ba8SAndrew Turner ******************************************************************************/ 99*072a4ba8SAndrew Turner 100*072a4ba8SAndrew Turner /* Emit .cfi_restore directives for a consecutive sequence of registers. */ 101*072a4ba8SAndrew Turner .macro cfirestorelist first, last 102*072a4ba8SAndrew Turner .cfi_restore \last 103*072a4ba8SAndrew Turner .if \last-\first 104*072a4ba8SAndrew Turner cfirestorelist \first, \last-1 105*072a4ba8SAndrew Turner .endif 106*072a4ba8SAndrew Turner .endm 107*072a4ba8SAndrew Turner 108*072a4ba8SAndrew Turner /* Emit .cfi_offset directives for a consecutive sequence of registers. */ 109*072a4ba8SAndrew Turner .macro cfisavelist first, last, index=1 110*072a4ba8SAndrew Turner .cfi_offset \last, -4*(\index) 111*072a4ba8SAndrew Turner .if \last-\first 112*072a4ba8SAndrew Turner cfisavelist \first, \last-1, \index+1 113*072a4ba8SAndrew Turner .endif 114*072a4ba8SAndrew Turner .endm 115*072a4ba8SAndrew Turner 116*072a4ba8SAndrew Turner .macro _prologue first=-1, last=-1, push_ip=PAC_LEAF_PUSH_IP, push_lr=0 117*072a4ba8SAndrew Turner .if \push_ip & 1 != \push_ip 118*072a4ba8SAndrew Turner .error "push_ip may be either 0 or 1" 119*072a4ba8SAndrew Turner .endif 120*072a4ba8SAndrew Turner .if \push_lr & 1 != \push_lr 121*072a4ba8SAndrew Turner .error "push_lr may be either 0 or 1" 122*072a4ba8SAndrew Turner .endif 123*072a4ba8SAndrew Turner .if \first != -1 124*072a4ba8SAndrew Turner .if \last == -1 125*072a4ba8SAndrew Turner /* Upper-bound not provided: Set upper = lower. */ 126*072a4ba8SAndrew Turner _prologue \first, \first, \push_ip, \push_lr 127*072a4ba8SAndrew Turner .exitm 128*072a4ba8SAndrew Turner .endif 129*072a4ba8SAndrew Turner .endif 130*072a4ba8SAndrew Turner #if HAVE_PAC_LEAF 131*072a4ba8SAndrew Turner # if __ARM_FEATURE_BTI_DEFAULT 132*072a4ba8SAndrew Turner pacbti ip, lr, sp 133*072a4ba8SAndrew Turner # else 134*072a4ba8SAndrew Turner pac ip, lr, sp 135*072a4ba8SAndrew Turner # endif /* __ARM_FEATURE_BTI_DEFAULT */ 136*072a4ba8SAndrew Turner .cfi_register 143, 12 137*072a4ba8SAndrew Turner #else 138*072a4ba8SAndrew Turner # if __ARM_FEATURE_BTI_DEFAULT 139*072a4ba8SAndrew Turner bti 140*072a4ba8SAndrew Turner # endif /* __ARM_FEATURE_BTI_DEFAULT */ 141*072a4ba8SAndrew Turner #endif /* HAVE_PAC_LEAF */ 142*072a4ba8SAndrew Turner .if \first != -1 143*072a4ba8SAndrew Turner .if \last != \first 144*072a4ba8SAndrew Turner .if \last >= 13 145*072a4ba8SAndrew Turner .error "SP cannot be in the save list" 146*072a4ba8SAndrew Turner .endif 147*072a4ba8SAndrew Turner .if \push_ip 148*072a4ba8SAndrew Turner .if \push_lr 149*072a4ba8SAndrew Turner /* Case 1: push register range, ip and lr registers. */ 150*072a4ba8SAndrew Turner push {r\first-r\last, ip, lr} 151*072a4ba8SAndrew Turner .cfi_adjust_cfa_offset ((\last-\first)+3)*4 152*072a4ba8SAndrew Turner .cfi_offset 14, -4 153*072a4ba8SAndrew Turner .cfi_offset 143, -8 154*072a4ba8SAndrew Turner cfisavelist \first, \last, 3 155*072a4ba8SAndrew Turner .else // !\push_lr 156*072a4ba8SAndrew Turner /* Case 2: push register range and ip register. */ 157*072a4ba8SAndrew Turner push {r\first-r\last, ip} 158*072a4ba8SAndrew Turner .cfi_adjust_cfa_offset ((\last-\first)+2)*4 159*072a4ba8SAndrew Turner .cfi_offset 143, -4 160*072a4ba8SAndrew Turner cfisavelist \first, \last, 2 161*072a4ba8SAndrew Turner .endif 162*072a4ba8SAndrew Turner .else // !\push_ip 163*072a4ba8SAndrew Turner .if \push_lr 164*072a4ba8SAndrew Turner /* Case 3: push register range and lr register. */ 165*072a4ba8SAndrew Turner push {r\first-r\last, lr} 166*072a4ba8SAndrew Turner .cfi_adjust_cfa_offset ((\last-\first)+2)*4 167*072a4ba8SAndrew Turner .cfi_offset 14, -4 168*072a4ba8SAndrew Turner cfisavelist \first, \last, 2 169*072a4ba8SAndrew Turner .else // !\push_lr 170*072a4ba8SAndrew Turner /* Case 4: push register range. */ 171*072a4ba8SAndrew Turner push {r\first-r\last} 172*072a4ba8SAndrew Turner .cfi_adjust_cfa_offset ((\last-\first)+1)*4 173*072a4ba8SAndrew Turner cfisavelist \first, \last, 1 174*072a4ba8SAndrew Turner .endif 175*072a4ba8SAndrew Turner .endif 176*072a4ba8SAndrew Turner .else // \last == \first 177*072a4ba8SAndrew Turner .if \push_ip 178*072a4ba8SAndrew Turner .if \push_lr 179*072a4ba8SAndrew Turner /* Case 5: push single GP register plus ip and lr registers. */ 180*072a4ba8SAndrew Turner push {r\first, ip, lr} 181*072a4ba8SAndrew Turner .cfi_adjust_cfa_offset 12 182*072a4ba8SAndrew Turner .cfi_offset 14, -4 183*072a4ba8SAndrew Turner .cfi_offset 143, -8 184*072a4ba8SAndrew Turner cfisavelist \first, \first, 3 185*072a4ba8SAndrew Turner .else // !\push_lr 186*072a4ba8SAndrew Turner /* Case 6: push single GP register plus ip register. */ 187*072a4ba8SAndrew Turner push {r\first, ip} 188*072a4ba8SAndrew Turner .cfi_adjust_cfa_offset 8 189*072a4ba8SAndrew Turner .cfi_offset 143, -4 190*072a4ba8SAndrew Turner cfisavelist \first, \first, 2 191*072a4ba8SAndrew Turner .endif 192*072a4ba8SAndrew Turner .else // !\push_ip 193*072a4ba8SAndrew Turner .if \push_lr 194*072a4ba8SAndrew Turner /* Case 7: push single GP register plus lr register. */ 195*072a4ba8SAndrew Turner push {r\first, lr} 196*072a4ba8SAndrew Turner .cfi_adjust_cfa_offset 8 197*072a4ba8SAndrew Turner .cfi_offset 14, -4 198*072a4ba8SAndrew Turner cfisavelist \first, \first, 2 199*072a4ba8SAndrew Turner .else // !\push_lr 200*072a4ba8SAndrew Turner /* Case 8: push single GP register. */ 201*072a4ba8SAndrew Turner push {r\first} 202*072a4ba8SAndrew Turner .cfi_adjust_cfa_offset 4 203*072a4ba8SAndrew Turner cfisavelist \first, \first, 1 204*072a4ba8SAndrew Turner .endif 205*072a4ba8SAndrew Turner .endif 206*072a4ba8SAndrew Turner .endif 207*072a4ba8SAndrew Turner .else // \first == -1 208*072a4ba8SAndrew Turner .if \push_ip 209*072a4ba8SAndrew Turner .if \push_lr 210*072a4ba8SAndrew Turner /* Case 9: push ip and lr registers. */ 211*072a4ba8SAndrew Turner push {ip, lr} 212*072a4ba8SAndrew Turner .cfi_adjust_cfa_offset 8 213*072a4ba8SAndrew Turner .cfi_offset 14, -4 214*072a4ba8SAndrew Turner .cfi_offset 143, -8 215*072a4ba8SAndrew Turner .else // !\push_lr 216*072a4ba8SAndrew Turner /* Case 10: push ip register. */ 217*072a4ba8SAndrew Turner push {ip} 218*072a4ba8SAndrew Turner .cfi_adjust_cfa_offset 4 219*072a4ba8SAndrew Turner .cfi_offset 143, -4 220*072a4ba8SAndrew Turner .endif 221*072a4ba8SAndrew Turner .else // !\push_ip 222*072a4ba8SAndrew Turner .if \push_lr 223*072a4ba8SAndrew Turner /* Case 11: push lr register. */ 224*072a4ba8SAndrew Turner push {lr} 225*072a4ba8SAndrew Turner .cfi_adjust_cfa_offset 4 226*072a4ba8SAndrew Turner .cfi_offset 14, -4 227*072a4ba8SAndrew Turner .endif 228*072a4ba8SAndrew Turner .endif 229*072a4ba8SAndrew Turner .endif 230*072a4ba8SAndrew Turner .endm 231*072a4ba8SAndrew Turner 232*072a4ba8SAndrew Turner .macro _epilogue first=-1, last=-1, push_ip=PAC_LEAF_PUSH_IP, push_lr=0 233*072a4ba8SAndrew Turner .if \push_ip & 1 != \push_ip 234*072a4ba8SAndrew Turner .error "push_ip may be either 0 or 1" 235*072a4ba8SAndrew Turner .endif 236*072a4ba8SAndrew Turner .if \push_lr & 1 != \push_lr 237*072a4ba8SAndrew Turner .error "push_lr may be either 0 or 1" 238*072a4ba8SAndrew Turner .endif 239*072a4ba8SAndrew Turner .if \first != -1 240*072a4ba8SAndrew Turner .if \last == -1 241*072a4ba8SAndrew Turner /* Upper-bound not provided: Set upper = lower. */ 242*072a4ba8SAndrew Turner _epilogue \first, \first, \push_ip, \push_lr 243*072a4ba8SAndrew Turner .exitm 244*072a4ba8SAndrew Turner .endif 245*072a4ba8SAndrew Turner .if \last != \first 246*072a4ba8SAndrew Turner .if \last >= 13 247*072a4ba8SAndrew Turner .error "SP cannot be in the save list" 248*072a4ba8SAndrew Turner .endif 249*072a4ba8SAndrew Turner .if \push_ip 250*072a4ba8SAndrew Turner .if \push_lr 251*072a4ba8SAndrew Turner /* Case 1: pop register range, ip and lr registers. */ 252*072a4ba8SAndrew Turner pop {r\first-r\last, ip, lr} 253*072a4ba8SAndrew Turner .cfi_restore 14 254*072a4ba8SAndrew Turner .cfi_register 143, 12 255*072a4ba8SAndrew Turner cfirestorelist \first, \last 256*072a4ba8SAndrew Turner .else // !\push_lr 257*072a4ba8SAndrew Turner /* Case 2: pop register range and ip register. */ 258*072a4ba8SAndrew Turner pop {r\first-r\last, ip} 259*072a4ba8SAndrew Turner .cfi_register 143, 12 260*072a4ba8SAndrew Turner cfirestorelist \first, \last 261*072a4ba8SAndrew Turner .endif 262*072a4ba8SAndrew Turner .else // !\push_ip 263*072a4ba8SAndrew Turner .if \push_lr 264*072a4ba8SAndrew Turner /* Case 3: pop register range and lr register. */ 265*072a4ba8SAndrew Turner pop {r\first-r\last, lr} 266*072a4ba8SAndrew Turner .cfi_restore 14 267*072a4ba8SAndrew Turner cfirestorelist \first, \last 268*072a4ba8SAndrew Turner .else // !\push_lr 269*072a4ba8SAndrew Turner /* Case 4: pop register range. */ 270*072a4ba8SAndrew Turner pop {r\first-r\last} 271*072a4ba8SAndrew Turner cfirestorelist \first, \last 272*072a4ba8SAndrew Turner .endif 273*072a4ba8SAndrew Turner .endif 274*072a4ba8SAndrew Turner .else // \last == \first 275*072a4ba8SAndrew Turner .if \push_ip 276*072a4ba8SAndrew Turner .if \push_lr 277*072a4ba8SAndrew Turner /* Case 5: pop single GP register plus ip and lr registers. */ 278*072a4ba8SAndrew Turner pop {r\first, ip, lr} 279*072a4ba8SAndrew Turner .cfi_restore 14 280*072a4ba8SAndrew Turner .cfi_register 143, 12 281*072a4ba8SAndrew Turner cfirestorelist \first, \first 282*072a4ba8SAndrew Turner .else // !\push_lr 283*072a4ba8SAndrew Turner /* Case 6: pop single GP register plus ip register. */ 284*072a4ba8SAndrew Turner pop {r\first, ip} 285*072a4ba8SAndrew Turner .cfi_register 143, 12 286*072a4ba8SAndrew Turner cfirestorelist \first, \first 287*072a4ba8SAndrew Turner .endif 288*072a4ba8SAndrew Turner .else // !\push_ip 289*072a4ba8SAndrew Turner .if \push_lr 290*072a4ba8SAndrew Turner /* Case 7: pop single GP register plus lr register. */ 291*072a4ba8SAndrew Turner pop {r\first, lr} 292*072a4ba8SAndrew Turner .cfi_restore 14 293*072a4ba8SAndrew Turner cfirestorelist \first, \first 294*072a4ba8SAndrew Turner .else // !\push_lr 295*072a4ba8SAndrew Turner /* Case 8: pop single GP register. */ 296*072a4ba8SAndrew Turner pop {r\first} 297*072a4ba8SAndrew Turner cfirestorelist \first, \first 298*072a4ba8SAndrew Turner .endif 299*072a4ba8SAndrew Turner .endif 300*072a4ba8SAndrew Turner .endif 301*072a4ba8SAndrew Turner .else // \first == -1 302*072a4ba8SAndrew Turner .if \push_ip 303*072a4ba8SAndrew Turner .if \push_lr 304*072a4ba8SAndrew Turner /* Case 9: pop ip and lr registers. */ 305*072a4ba8SAndrew Turner pop {ip, lr} 306*072a4ba8SAndrew Turner .cfi_restore 14 307*072a4ba8SAndrew Turner .cfi_register 143, 12 308*072a4ba8SAndrew Turner .else // !\push_lr 309*072a4ba8SAndrew Turner /* Case 10: pop ip register. */ 310*072a4ba8SAndrew Turner pop {ip} 311*072a4ba8SAndrew Turner .cfi_register 143, 12 312*072a4ba8SAndrew Turner .endif 313*072a4ba8SAndrew Turner .else // !\push_ip 314*072a4ba8SAndrew Turner .if \push_lr 315*072a4ba8SAndrew Turner /* Case 11: pop lr register. */ 316*072a4ba8SAndrew Turner pop {lr} 317*072a4ba8SAndrew Turner .cfi_restore 14 318*072a4ba8SAndrew Turner .endif 319*072a4ba8SAndrew Turner .endif 320*072a4ba8SAndrew Turner .endif 321*072a4ba8SAndrew Turner #if HAVE_PAC_LEAF 322*072a4ba8SAndrew Turner aut ip, lr, sp 323*072a4ba8SAndrew Turner #endif /* HAVE_PAC_LEAF */ 324*072a4ba8SAndrew Turner bx lr 325*072a4ba8SAndrew Turner .endm 326*072a4ba8SAndrew Turner 327*072a4ba8SAndrew Turner /* Clean up expressions in 'last'. */ 328*072a4ba8SAndrew Turner .macro _preprocess_reglist1 first:req, last:req, push_ip:req, push_lr:req, reglist_op:req 329*072a4ba8SAndrew Turner .if \last == 0 330*072a4ba8SAndrew Turner \reglist_op \first, 0, \push_ip, \push_lr 331*072a4ba8SAndrew Turner .elseif \last == 1 332*072a4ba8SAndrew Turner \reglist_op \first, 1, \push_ip, \push_lr 333*072a4ba8SAndrew Turner .elseif \last == 2 334*072a4ba8SAndrew Turner \reglist_op \first, 2, \push_ip, \push_lr 335*072a4ba8SAndrew Turner .elseif \last == 3 336*072a4ba8SAndrew Turner \reglist_op \first, 3, \push_ip, \push_lr 337*072a4ba8SAndrew Turner .elseif \last == 4 338*072a4ba8SAndrew Turner \reglist_op \first, 4, \push_ip, \push_lr 339*072a4ba8SAndrew Turner .elseif \last == 5 340*072a4ba8SAndrew Turner \reglist_op \first, 5, \push_ip, \push_lr 341*072a4ba8SAndrew Turner .elseif \last == 6 342*072a4ba8SAndrew Turner \reglist_op \first, 6, \push_ip, \push_lr 343*072a4ba8SAndrew Turner .elseif \last == 7 344*072a4ba8SAndrew Turner \reglist_op \first, 7, \push_ip, \push_lr 345*072a4ba8SAndrew Turner .elseif \last == 8 346*072a4ba8SAndrew Turner \reglist_op \first, 8, \push_ip, \push_lr 347*072a4ba8SAndrew Turner .elseif \last == 9 348*072a4ba8SAndrew Turner \reglist_op \first, 9, \push_ip, \push_lr 349*072a4ba8SAndrew Turner .elseif \last == 10 350*072a4ba8SAndrew Turner \reglist_op \first, 10, \push_ip, \push_lr 351*072a4ba8SAndrew Turner .elseif \last == 11 352*072a4ba8SAndrew Turner \reglist_op \first, 11, \push_ip, \push_lr 353*072a4ba8SAndrew Turner .else 354*072a4ba8SAndrew Turner .error "last (\last) out of range" 355*072a4ba8SAndrew Turner .endif 356*072a4ba8SAndrew Turner .endm 357*072a4ba8SAndrew Turner 358*072a4ba8SAndrew Turner /* Clean up expressions in 'first'. */ 359*072a4ba8SAndrew Turner .macro _preprocess_reglist first:req, last, push_ip=0, push_lr=0, reglist_op:req 360*072a4ba8SAndrew Turner .ifb \last 361*072a4ba8SAndrew Turner _preprocess_reglist \first \first \push_ip \push_lr 362*072a4ba8SAndrew Turner .else 363*072a4ba8SAndrew Turner .if \first > \last 364*072a4ba8SAndrew Turner .error "last (\last) must be at least as great as first (\first)" 365*072a4ba8SAndrew Turner .endif 366*072a4ba8SAndrew Turner .if \first == 0 367*072a4ba8SAndrew Turner _preprocess_reglist1 0, \last, \push_ip, \push_lr, \reglist_op 368*072a4ba8SAndrew Turner .elseif \first == 1 369*072a4ba8SAndrew Turner _preprocess_reglist1 1, \last, \push_ip, \push_lr, \reglist_op 370*072a4ba8SAndrew Turner .elseif \first == 2 371*072a4ba8SAndrew Turner _preprocess_reglist1 2, \last, \push_ip, \push_lr, \reglist_op 372*072a4ba8SAndrew Turner .elseif \first == 3 373*072a4ba8SAndrew Turner _preprocess_reglist1 3, \last, \push_ip, \push_lr, \reglist_op 374*072a4ba8SAndrew Turner .elseif \first == 4 375*072a4ba8SAndrew Turner _preprocess_reglist1 4, \last, \push_ip, \push_lr, \reglist_op 376*072a4ba8SAndrew Turner .elseif \first == 5 377*072a4ba8SAndrew Turner _preprocess_reglist1 5, \last, \push_ip, \push_lr, \reglist_op 378*072a4ba8SAndrew Turner .elseif \first == 6 379*072a4ba8SAndrew Turner _preprocess_reglist1 6, \last, \push_ip, \push_lr, \reglist_op 380*072a4ba8SAndrew Turner .elseif \first == 7 381*072a4ba8SAndrew Turner _preprocess_reglist1 7, \last, \push_ip, \push_lr, \reglist_op 382*072a4ba8SAndrew Turner .elseif \first == 8 383*072a4ba8SAndrew Turner _preprocess_reglist1 8, \last, \push_ip, \push_lr, \reglist_op 384*072a4ba8SAndrew Turner .elseif \first == 9 385*072a4ba8SAndrew Turner _preprocess_reglist1 9, \last, \push_ip, \push_lr, \reglist_op 386*072a4ba8SAndrew Turner .elseif \first == 10 387*072a4ba8SAndrew Turner _preprocess_reglist1 10, \last, \push_ip, \push_lr, \reglist_op 388*072a4ba8SAndrew Turner .elseif \first == 11 389*072a4ba8SAndrew Turner _preprocess_reglist1 11, \last, \push_ip, \push_lr, \reglist_op 390*072a4ba8SAndrew Turner .else 391*072a4ba8SAndrew Turner .error "first (\first) out of range" 392*072a4ba8SAndrew Turner .endif 393*072a4ba8SAndrew Turner .endif 394*072a4ba8SAndrew Turner .endm 395*072a4ba8SAndrew Turner 396*072a4ba8SAndrew Turner .macro _align8 first, last, push_ip=0, push_lr=0, reglist_op=_prologue 397*072a4ba8SAndrew Turner .ifb \first 398*072a4ba8SAndrew Turner .ifnb \last 399*072a4ba8SAndrew Turner .error "can't have last (\last) without specifying first" 400*072a4ba8SAndrew Turner .else // \last not blank 401*072a4ba8SAndrew Turner .if ((\push_ip + \push_lr) % 2) == 0 402*072a4ba8SAndrew Turner \reglist_op first=-1, last=-1, push_ip=\push_ip, push_lr=\push_lr 403*072a4ba8SAndrew Turner .exitm 404*072a4ba8SAndrew Turner .else // ((\push_ip + \push_lr) % 2) odd 405*072a4ba8SAndrew Turner _align8 2, 2, \push_ip, \push_lr, \reglist_op 406*072a4ba8SAndrew Turner .exitm 407*072a4ba8SAndrew Turner .endif // ((\push_ip + \push_lr) % 2) == 0 408*072a4ba8SAndrew Turner .endif // .ifnb \last 409*072a4ba8SAndrew Turner .endif // .ifb \first 410*072a4ba8SAndrew Turner 411*072a4ba8SAndrew Turner .ifb \last 412*072a4ba8SAndrew Turner _align8 \first, \first, \push_ip, \push_lr, \reglist_op 413*072a4ba8SAndrew Turner .else 414*072a4ba8SAndrew Turner .if \push_ip & 1 <> \push_ip 415*072a4ba8SAndrew Turner .error "push_ip may be 0 or 1" 416*072a4ba8SAndrew Turner .endif 417*072a4ba8SAndrew Turner .if \push_lr & 1 <> \push_lr 418*072a4ba8SAndrew Turner .error "push_lr may be 0 or 1" 419*072a4ba8SAndrew Turner .endif 420*072a4ba8SAndrew Turner .ifeq (\last - \first + \push_ip + \push_lr) % 2 421*072a4ba8SAndrew Turner .if \first == 0 422*072a4ba8SAndrew Turner .error "Alignment required and first register is r0" 423*072a4ba8SAndrew Turner .exitm 424*072a4ba8SAndrew Turner .endif 425*072a4ba8SAndrew Turner _preprocess_reglist \first-1, \last, \push_ip, \push_lr, \reglist_op 426*072a4ba8SAndrew Turner .else 427*072a4ba8SAndrew Turner _preprocess_reglist \first \last, \push_ip, \push_lr, \reglist_op 428*072a4ba8SAndrew Turner .endif 429*072a4ba8SAndrew Turner .endif 430*072a4ba8SAndrew Turner .endm 431*072a4ba8SAndrew Turner 432*072a4ba8SAndrew Turner .macro prologue first, last, push_ip=PAC_LEAF_PUSH_IP, push_lr=0, align8=STACK_ALIGN_ENFORCE 433*072a4ba8SAndrew Turner .if \align8 434*072a4ba8SAndrew Turner _align8 \first, \last, \push_ip, \push_lr, _prologue 435*072a4ba8SAndrew Turner .else 436*072a4ba8SAndrew Turner _prologue first=\first, last=\last, push_ip=\push_ip, push_lr=\push_lr 437*072a4ba8SAndrew Turner .endif 438*072a4ba8SAndrew Turner .endm 439*072a4ba8SAndrew Turner 440*072a4ba8SAndrew Turner .macro epilogue first, last, push_ip=PAC_LEAF_PUSH_IP, push_lr=0, align8=STACK_ALIGN_ENFORCE 441*072a4ba8SAndrew Turner .if \align8 442*072a4ba8SAndrew Turner _align8 \first, \last, \push_ip, \push_lr, reglist_op=_epilogue 443*072a4ba8SAndrew Turner .else 444*072a4ba8SAndrew Turner _epilogue first=\first, last=\last, push_ip=\push_ip, push_lr=\push_lr 445*072a4ba8SAndrew Turner .endif 446*072a4ba8SAndrew Turner .endm 447*072a4ba8SAndrew Turner 448*072a4ba8SAndrew Turner #define ENTRY_ALIGN(name, alignment) \ 449*072a4ba8SAndrew Turner .global name; \ 450*072a4ba8SAndrew Turner .type name,%function; \ 451*072a4ba8SAndrew Turner .align alignment; \ 452*072a4ba8SAndrew Turner name: \ 453*072a4ba8SAndrew Turner .fnstart; \ 454*072a4ba8SAndrew Turner .cfi_startproc; 455*072a4ba8SAndrew Turner 456*072a4ba8SAndrew Turner #define ENTRY(name) ENTRY_ALIGN(name, 6) 457*072a4ba8SAndrew Turner 458*072a4ba8SAndrew Turner #define ENTRY_ALIAS(name) \ 459*072a4ba8SAndrew Turner .global name; \ 460*072a4ba8SAndrew Turner .type name,%function; \ 461*072a4ba8SAndrew Turner name: 462*072a4ba8SAndrew Turner 463*072a4ba8SAndrew Turner #if defined (IS_LEAF) 464*072a4ba8SAndrew Turner # define END_UNWIND .cantunwind; 465*072a4ba8SAndrew Turner #else 466*072a4ba8SAndrew Turner # define END_UNWIND 467*072a4ba8SAndrew Turner #endif 468*072a4ba8SAndrew Turner 469*072a4ba8SAndrew Turner #define END(name) \ 470*072a4ba8SAndrew Turner .cfi_endproc; \ 471*072a4ba8SAndrew Turner END_UNWIND \ 472*072a4ba8SAndrew Turner .fnend; \ 473*072a4ba8SAndrew Turner .size name, .-name; 474*072a4ba8SAndrew Turner 475*072a4ba8SAndrew Turner #define L(l) .L ## l 476*072a4ba8SAndrew Turner 477*072a4ba8SAndrew Turner #endif 478