11bb92983SJerome Forissier/* SPDX-License-Identifier: BSD-3-Clause */ 20c81fcd6SJens Wiklander/* 30c81fcd6SJens Wiklander * Copyright (c) 1994-2009 Red Hat, Inc. 40c81fcd6SJens Wiklander * All rights reserved. 50c81fcd6SJens Wiklander * 60c81fcd6SJens Wiklander * Redistribution and use in source and binary forms, with or without 70c81fcd6SJens Wiklander * modification, are permitted provided that the following conditions are met: 80c81fcd6SJens Wiklander * 90c81fcd6SJens Wiklander * 1. Redistributions of source code must retain the above copyright notice, 100c81fcd6SJens Wiklander * this list of conditions and the following disclaimer. 110c81fcd6SJens Wiklander * 120c81fcd6SJens Wiklander * 2. Redistributions in binary form must reproduce the above copyright notice, 130c81fcd6SJens Wiklander * this list of conditions and the following disclaimer in the documentation 140c81fcd6SJens Wiklander * and/or other materials provided with the distribution. 150c81fcd6SJens Wiklander * 160c81fcd6SJens Wiklander * 3. Neither the name of the copyright holder nor the names of its 170c81fcd6SJens Wiklander * contributors may be used to endorse or promote products derived from this 180c81fcd6SJens Wiklander * software without specific prior written permission. 190c81fcd6SJens Wiklander * 200c81fcd6SJens Wiklander * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 210c81fcd6SJens Wiklander * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 220c81fcd6SJens Wiklander * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 230c81fcd6SJens Wiklander * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 240c81fcd6SJens Wiklander * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 250c81fcd6SJens Wiklander * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 260c81fcd6SJens Wiklander * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 270c81fcd6SJens Wiklander * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 280c81fcd6SJens Wiklander * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 290c81fcd6SJens Wiklander * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 300c81fcd6SJens Wiklander * POSSIBILITY OF SUCH DAMAGE. 310c81fcd6SJens Wiklander */ 320c81fcd6SJens Wiklander/* This is a simple version of setjmp and longjmp. 330c81fcd6SJens Wiklander 340c81fcd6SJens Wiklander Nick Clifton, Cygnus Solutions, 13 June 1997. */ 350c81fcd6SJens Wiklander 360c81fcd6SJens Wiklander/* ANSI concatenation macros. */ 370c81fcd6SJens Wiklander#define CONCAT(a, b) CONCAT2(a, b) 380c81fcd6SJens Wiklander#define CONCAT2(a, b) a##b 390c81fcd6SJens Wiklander 400c81fcd6SJens Wiklander#ifndef __USER_LABEL_PREFIX__ 410c81fcd6SJens Wiklander#error __USER_LABEL_PREFIX__ not defined 420c81fcd6SJens Wiklander#endif 430c81fcd6SJens Wiklander 440c81fcd6SJens Wiklander#define SYM(x) CONCAT (__USER_LABEL_PREFIX__, x) 450c81fcd6SJens Wiklander 460c81fcd6SJens Wiklander#ifdef __ELF__ 470c81fcd6SJens Wiklander#define TYPE(x) .type SYM(x),function 480c81fcd6SJens Wiklander#define SIZE(x) .size SYM(x), . - SYM(x) 490c81fcd6SJens Wiklander#else 500c81fcd6SJens Wiklander#define TYPE(x) 510c81fcd6SJens Wiklander#define SIZE(x) 520c81fcd6SJens Wiklander#endif 530c81fcd6SJens Wiklander 54d9925536SJerome Forissier .section .note.GNU-stack,"",%progbits 55d9925536SJerome Forissier 560c81fcd6SJens Wiklander/* Arm/Thumb interworking support: 570c81fcd6SJens Wiklander 580c81fcd6SJens Wiklander The interworking scheme expects functions to use a BX instruction 590c81fcd6SJens Wiklander to return control to their parent. Since we need this code to work 600c81fcd6SJens Wiklander in both interworked and non-interworked environments as well as with 610c81fcd6SJens Wiklander older processors which do not have the BX instruction we do the 620c81fcd6SJens Wiklander following: 630c81fcd6SJens Wiklander Test the return address. 640c81fcd6SJens Wiklander If the bottom bit is clear perform an "old style" function exit. 650c81fcd6SJens Wiklander (We know that we are in ARM mode and returning to an ARM mode caller). 660c81fcd6SJens Wiklander Otherwise use the BX instruction to perform the function exit. 670c81fcd6SJens Wiklander 680c81fcd6SJens Wiklander We know that we will never attempt to perform the BX instruction on 690c81fcd6SJens Wiklander an older processor, because that kind of processor will never be 700c81fcd6SJens Wiklander interworked, and a return address with the bottom bit set will never 710c81fcd6SJens Wiklander be generated. 720c81fcd6SJens Wiklander 730c81fcd6SJens Wiklander In addition, we do not actually assemble the BX instruction as this would 740c81fcd6SJens Wiklander require us to tell the assembler that the processor is an ARM7TDMI and 750c81fcd6SJens Wiklander it would store this information in the binary. We want this binary to be 760c81fcd6SJens Wiklander able to be linked with binaries compiled for older processors however, so 770c81fcd6SJens Wiklander we do not want such information stored there. 780c81fcd6SJens Wiklander 790c81fcd6SJens Wiklander If we are running using the APCS-26 convention however, then we never 800c81fcd6SJens Wiklander test the bottom bit, because this is part of the processor status. 810c81fcd6SJens Wiklander Instead we just do a normal return, since we know that we cannot be 820c81fcd6SJens Wiklander returning to a Thumb caller - the Thumb does not support APCS-26. 830c81fcd6SJens Wiklander 840c81fcd6SJens Wiklander Function entry is much simpler. If we are compiling for the Thumb we 850c81fcd6SJens Wiklander just switch into ARM mode and then drop through into the rest of the 860c81fcd6SJens Wiklander function. The function exit code will take care of the restore to 870c81fcd6SJens Wiklander Thumb mode. 880c81fcd6SJens Wiklander 890c81fcd6SJens Wiklander For Thumb-2 do everything in Thumb mode. */ 900c81fcd6SJens Wiklander 910c81fcd6SJens Wiklander#if defined(__ARM_ARCH_6M__) 920c81fcd6SJens Wiklander/* ARMv6-M has to be implemented in Thumb mode. */ 930c81fcd6SJens Wiklander 940c81fcd6SJens Wiklander.thumb 950c81fcd6SJens Wiklander.thumb_func 960c81fcd6SJens Wiklander .globl SYM (setjmp) 970c81fcd6SJens Wiklander TYPE (setjmp) 980c81fcd6SJens WiklanderSYM (setjmp): 990c81fcd6SJens Wiklander /* Save registers in jump buffer. */ 1000c81fcd6SJens Wiklander stmia r0!, {r4, r5, r6, r7} 1010c81fcd6SJens Wiklander mov r1, r8 1020c81fcd6SJens Wiklander mov r2, r9 1030c81fcd6SJens Wiklander mov r3, r10 1040c81fcd6SJens Wiklander mov r4, fp 1050c81fcd6SJens Wiklander mov r5, sp 1060c81fcd6SJens Wiklander mov r6, lr 1070c81fcd6SJens Wiklander stmia r0!, {r1, r2, r3, r4, r5, r6} 1080c81fcd6SJens Wiklander sub r0, r0, #40 1090c81fcd6SJens Wiklander /* Restore callee-saved low regs. */ 1100c81fcd6SJens Wiklander ldmia r0!, {r4, r5, r6, r7} 1110c81fcd6SJens Wiklander /* Return zero. */ 1120c81fcd6SJens Wiklander mov r0, #0 1130c81fcd6SJens Wiklander bx lr 1140c81fcd6SJens Wiklander 1150c81fcd6SJens Wiklander.thumb_func 1160c81fcd6SJens Wiklander .globl SYM (longjmp) 1170c81fcd6SJens Wiklander TYPE (longjmp) 1180c81fcd6SJens WiklanderSYM (longjmp): 1190c81fcd6SJens Wiklander /* Restore High regs. */ 1200c81fcd6SJens Wiklander add r0, r0, #16 1210c81fcd6SJens Wiklander ldmia r0!, {r2, r3, r4, r5, r6} 1220c81fcd6SJens Wiklander mov r8, r2 1230c81fcd6SJens Wiklander mov r9, r3 1240c81fcd6SJens Wiklander mov r10, r4 1250c81fcd6SJens Wiklander mov fp, r5 1260c81fcd6SJens Wiklander mov sp, r6 1270c81fcd6SJens Wiklander ldmia r0!, {r3} /* lr */ 1280c81fcd6SJens Wiklander /* Restore low regs. */ 1290c81fcd6SJens Wiklander sub r0, r0, #40 1300c81fcd6SJens Wiklander ldmia r0!, {r4, r5, r6, r7} 1310c81fcd6SJens Wiklander /* Return the result argument, or 1 if it is zero. */ 1320c81fcd6SJens Wiklander mov r0, r1 1330c81fcd6SJens Wiklander bne 1f 1340c81fcd6SJens Wiklander mov r0, #1 1350c81fcd6SJens Wiklander1: 1360c81fcd6SJens Wiklander bx r3 1370c81fcd6SJens Wiklander 1380c81fcd6SJens Wiklander#else 1390c81fcd6SJens Wiklander 1400c81fcd6SJens Wiklander#ifdef __APCS_26__ 1410c81fcd6SJens Wiklander#define RET movs pc, lr 1420c81fcd6SJens Wiklander#elif defined(__thumb2__) 1430c81fcd6SJens Wiklander#define RET bx lr 1440c81fcd6SJens Wiklander#else 1450c81fcd6SJens Wiklander#define RET tst lr, #1; \ 1460c81fcd6SJens Wiklander moveq pc, lr ; \ 1470c81fcd6SJens Wiklander.word 0xe12fff1e /* bx lr */ 1480c81fcd6SJens Wiklander#endif 1490c81fcd6SJens Wiklander 1500c81fcd6SJens Wiklander#ifdef __thumb2__ 1510c81fcd6SJens Wiklander.macro COND where when 1520c81fcd6SJens Wiklander i\where \when 1530c81fcd6SJens Wiklander.endm 1540c81fcd6SJens Wiklander#else 1550c81fcd6SJens Wiklander.macro COND where when 1560c81fcd6SJens Wiklander.endm 1570c81fcd6SJens Wiklander#endif 1580c81fcd6SJens Wiklander 1590c81fcd6SJens Wiklander#if defined(__thumb2__) 1600c81fcd6SJens Wiklander.syntax unified 1610c81fcd6SJens Wiklander.macro MODE 1620c81fcd6SJens Wiklander .thumb 1630c81fcd6SJens Wiklander .thumb_func 1640c81fcd6SJens Wiklander.endm 1650c81fcd6SJens Wiklander.macro PROLOGUE name 1660c81fcd6SJens Wiklander.endm 1670c81fcd6SJens Wiklander 1680c81fcd6SJens Wiklander#elif defined(__thumb__) 1690c81fcd6SJens Wiklander#define MODE .thumb_func 1700c81fcd6SJens Wiklander.macro PROLOGUE name 1710c81fcd6SJens Wiklander .code 16 1720c81fcd6SJens Wiklander bx pc 1730c81fcd6SJens Wiklander nop 1740c81fcd6SJens Wiklander .code 32 1750c81fcd6SJens WiklanderSYM (.arm_start_of.\name): 1760c81fcd6SJens Wiklander.endm 1770c81fcd6SJens Wiklander#else /* Arm */ 1780c81fcd6SJens Wiklander#define MODE .code 32 1790c81fcd6SJens Wiklander.macro PROLOGUE name 1800c81fcd6SJens Wiklander.endm 1810c81fcd6SJens Wiklander#endif 1820c81fcd6SJens Wiklander 1830c81fcd6SJens Wiklander.macro FUNC_START name 1840c81fcd6SJens Wiklander .text 1850c81fcd6SJens Wiklander .align 2 1860c81fcd6SJens Wiklander MODE 1870c81fcd6SJens Wiklander .globl SYM (\name) 1880c81fcd6SJens Wiklander TYPE (\name) 1890c81fcd6SJens WiklanderSYM (\name): 1900c81fcd6SJens Wiklander PROLOGUE \name 1910c81fcd6SJens Wiklander.endm 1920c81fcd6SJens Wiklander 1930c81fcd6SJens Wiklander.macro FUNC_END name 1940c81fcd6SJens Wiklander RET 1950c81fcd6SJens Wiklander SIZE (\name) 1960c81fcd6SJens Wiklander.endm 1970c81fcd6SJens Wiklander 1980c81fcd6SJens Wiklander/* -------------------------------------------------------------------- 1990c81fcd6SJens Wiklander int setjmp (jmp_buf); 2000c81fcd6SJens Wiklander -------------------------------------------------------------------- */ 2010c81fcd6SJens Wiklander 2020c81fcd6SJens Wiklander FUNC_START setjmp 2030c81fcd6SJens Wiklander 2040c81fcd6SJens Wiklander /* Save all the callee-preserved registers into the jump buffer. */ 2050c81fcd6SJens Wiklander#ifdef __thumb2__ 2060c81fcd6SJens Wiklander mov ip, sp 2070c81fcd6SJens Wiklander stmea a1!, { v1-v7, fp, ip, lr } 2080c81fcd6SJens Wiklander#else 2099de8272eSJerome Forissier stmea a1!, { v1-v7, fp, ip} 2109de8272eSJerome Forissier str sp, [a1], #4 2119de8272eSJerome Forissier str lr, [a1], #4 2120c81fcd6SJens Wiklander#endif 2130c81fcd6SJens Wiklander 2140c81fcd6SJens Wiklander#if 0 /* Simulator does not cope with FP instructions yet. */ 2150c81fcd6SJens Wiklander#ifndef __SOFTFP__ 2160c81fcd6SJens Wiklander /* Save the floating point registers. */ 2170c81fcd6SJens Wiklander sfmea f4, 4, [a1] 2180c81fcd6SJens Wiklander#endif 2190c81fcd6SJens Wiklander#endif 220c96d7091SSumit Garg 221099918f6SSumit Garg#ifdef CFG_FTRACE_SUPPORT 222c96d7091SSumit Garg stmdb sp!, { lr } 223c96d7091SSumit Garg /* 224c96d7091SSumit Garg * As ftrace is supported in ARM mode only, so hardcode jmp_buf 225c96d7091SSumit Garg * offset used to save ftrace return index. 226c96d7091SSumit Garg */ 227c96d7091SSumit Garg add a1, a1, #48 228c96d7091SSumit Garg bl ftrace_setjmp 229c96d7091SSumit Garg ldmia sp!, { lr } 230c96d7091SSumit Garg#endif 231c96d7091SSumit Garg 2320c81fcd6SJens Wiklander /* When setting up the jump buffer return 0. */ 2330c81fcd6SJens Wiklander mov a1, #0 2340c81fcd6SJens Wiklander 2350c81fcd6SJens Wiklander FUNC_END setjmp 2360c81fcd6SJens Wiklander 2370c81fcd6SJens Wiklander/* -------------------------------------------------------------------- 2380c81fcd6SJens Wiklander volatile void longjmp (jmp_buf, int); 2390c81fcd6SJens Wiklander -------------------------------------------------------------------- */ 2400c81fcd6SJens Wiklander 2410c81fcd6SJens Wiklander FUNC_START longjmp 2420c81fcd6SJens Wiklander 2430c81fcd6SJens Wiklander /* If we have stack extension code it ought to be handled here. */ 2440c81fcd6SJens Wiklander 245099918f6SSumit Garg#ifdef CFG_FTRACE_SUPPORT 246c96d7091SSumit Garg stmdb sp!, { a1, a2, lr } 247c96d7091SSumit Garg /* 248c96d7091SSumit Garg * As ftrace is supported in ARM mode only, so hardcode jmp_buf 249c96d7091SSumit Garg * offset used to restore ftrace return stack. 250c96d7091SSumit Garg */ 251c96d7091SSumit Garg add a1, a1, #92 252c96d7091SSumit Garg bl ftrace_longjmp 253c96d7091SSumit Garg ldmia sp!, { a1, a2, lr } 254c96d7091SSumit Garg#endif 255*7749dda2SAleksandr Iashchenko#if defined(__KERNEL__) && defined(CFG_CORE_SANITIZE_KADDRESS) && \ 256*7749dda2SAleksandr Iashchenko !defined(CFG_DYN_CONFIG) 257*7749dda2SAleksandr Iashchenko stmdb sp!, { a1, a2, a3, lr } 258*7749dda2SAleksandr Iashchenko 259*7749dda2SAleksandr Iashchenko#ifdef __thumb2__ 260*7749dda2SAleksandr Iashchenko ldr a1, [a1, #32] 261*7749dda2SAleksandr Iashchenko#else 262*7749dda2SAleksandr Iashchenko ldr a1, [a1, #36] 263*7749dda2SAleksandr Iashchenko#endif 264*7749dda2SAleksandr Iashchenko bl asan_handle_longjmp 265*7749dda2SAleksandr Iashchenko ldmia sp!, { a1, a2, a3, lr } 266*7749dda2SAleksandr Iashchenko#endif 267c96d7091SSumit Garg 2680c81fcd6SJens Wiklander /* Restore the registers, retrieving the state when setjmp() was called. */ 2690c81fcd6SJens Wiklander#ifdef __thumb2__ 2700c81fcd6SJens Wiklander ldmfd a1!, { v1-v7, fp, ip, lr } 2710c81fcd6SJens Wiklander mov sp, ip 2720c81fcd6SJens Wiklander#else 2739de8272eSJerome Forissier ldmfd a1!, { v1-v7, fp, ip } 2749de8272eSJerome Forissier ldr sp, [a1], #4 2759de8272eSJerome Forissier ldr lr, [a1], #4 2760c81fcd6SJens Wiklander#endif 2770c81fcd6SJens Wiklander 2780c81fcd6SJens Wiklander#if 0 /* Simulator does not cope with FP instructions yet. */ 2790c81fcd6SJens Wiklander#ifndef __SOFTFP__ 2800c81fcd6SJens Wiklander /* Restore floating point registers as well. */ 2810c81fcd6SJens Wiklander lfmfd f4, 4, [a1] 2820c81fcd6SJens Wiklander#endif 2830c81fcd6SJens Wiklander#endif 2840c81fcd6SJens Wiklander /* Put the return value into the integer result register. 2850c81fcd6SJens Wiklander But if it is zero then return 1 instead. */ 2860c81fcd6SJens Wiklander movs a1, a2 2870c81fcd6SJens Wiklander#ifdef __thumb2__ 2880c81fcd6SJens Wiklander it eq 2890c81fcd6SJens Wiklander#endif 2900c81fcd6SJens Wiklander moveq a1, #1 2910c81fcd6SJens Wiklander 2920c81fcd6SJens Wiklander FUNC_END longjmp 2930c81fcd6SJens Wiklander#endif 294