/* * Copyright (c) 2018 embedded brains GmbH * Copyright (c) 2015 Hesham Almatary * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #define OFFSET(i) ((i) * CPU_SIZEOF_POINTER) #define RA_OFFSET OFFSET(0) #define T0_OFFSET OFFSET(1) #define T1_OFFSET OFFSET(2) #define T2_OFFSET OFFSET(3) #define S0_OFFSET OFFSET(4) #define S1_OFFSET OFFSET(5) #define A0_OFFSET OFFSET(6) #define A1_OFFSET OFFSET(7) #define A2_OFFSET OFFSET(8) #define A3_OFFSET OFFSET(9) #define A4_OFFSET OFFSET(10) #define A5_OFFSET OFFSET(11) #define A6_OFFSET OFFSET(12) #define A7_OFFSET OFFSET(13) #define S2_OFFSET OFFSET(14) #define S3_OFFSET OFFSET(15) #define S4_OFFSET OFFSET(16) #define S5_OFFSET OFFSET(17) #define S6_OFFSET OFFSET(18) #define S7_OFFSET OFFSET(19) #define S8_OFFSET OFFSET(20) #define S9_OFFSET OFFSET(21) #define S10_OFFSET OFFSET(22) #define S11_OFFSET OFFSET(23) #define T3_OFFSET OFFSET(24) #define T4_OFFSET OFFSET(25) #define T5_OFFSET OFFSET(26) #define T6_OFFSET OFFSET(27) #define TMP_OFFSET OFFSET(28) #if __riscv_flen == 32 #define FOFFSET(i) (OFFSET(29) + (i) * 4) #elif __riscv_flen == 64 #define FOFFSET(i) (OFFSET(30) + (i) * 8) #else #define FOFFSET(i) OFFSET(29) #endif /* __riscv_flen */ #define FRAME_SIZE \ ((FOFFSET(32) + CPU_STACK_ALIGNMENT - 1) & ~(CPU_STACK_ALIGNMENT - 1)) .section .text, "ax", @progbits .align 2 PUBLIC(_CPU_Context_validate) SYM(_CPU_Context_validate): addi sp, sp, -FRAME_SIZE /* Save */ SREG ra, RA_OFFSET(sp) SREG t0, T0_OFFSET(sp) SREG t1, T1_OFFSET(sp) SREG t2, T2_OFFSET(sp) SREG s0, S0_OFFSET(sp) SREG s1, S1_OFFSET(sp) SREG a0, A0_OFFSET(sp) SREG a1, A1_OFFSET(sp) SREG a2, A2_OFFSET(sp) SREG a3, A3_OFFSET(sp) SREG a4, A4_OFFSET(sp) SREG a5, A5_OFFSET(sp) SREG a6, A6_OFFSET(sp) SREG a7, A7_OFFSET(sp) SREG s2, S2_OFFSET(sp) SREG s3, S3_OFFSET(sp) SREG s4, S4_OFFSET(sp) SREG s5, S5_OFFSET(sp) SREG s6, S6_OFFSET(sp) SREG s7, S7_OFFSET(sp) SREG s8, S8_OFFSET(sp) SREG s9, S9_OFFSET(sp) SREG s10, S10_OFFSET(sp) SREG s11, S11_OFFSET(sp) SREG t3, T3_OFFSET(sp) SREG t4, T4_OFFSET(sp) SREG t5, T5_OFFSET(sp) SREG t6, T6_OFFSET(sp) #if __riscv_flen > 0 FSREG f0, FOFFSET(0)(sp) FSREG f1, FOFFSET(1)(sp) FSREG f2, FOFFSET(2)(sp) FSREG f3, FOFFSET(3)(sp) FSREG f4, FOFFSET(4)(sp) FSREG f5, FOFFSET(5)(sp) FSREG f6, FOFFSET(6)(sp) FSREG f7, FOFFSET(7)(sp) FSREG f8, FOFFSET(8)(sp) FSREG f9, FOFFSET(9)(sp) FSREG f10, FOFFSET(10)(sp) FSREG f11, FOFFSET(11)(sp) FSREG f12, FOFFSET(12)(sp) FSREG f13, FOFFSET(13)(sp) FSREG f14, FOFFSET(14)(sp) FSREG f15, FOFFSET(15)(sp) FSREG f16, FOFFSET(16)(sp) FSREG f17, FOFFSET(17)(sp) FSREG f18, FOFFSET(18)(sp) FSREG f19, FOFFSET(19)(sp) FSREG f20, FOFFSET(20)(sp) FSREG f21, FOFFSET(21)(sp) FSREG f22, FOFFSET(22)(sp) FSREG f23, FOFFSET(23)(sp) FSREG f24, FOFFSET(24)(sp) FSREG f25, FOFFSET(25)(sp) FSREG f26, FOFFSET(26)(sp) FSREG f27, FOFFSET(27)(sp) FSREG f28, FOFFSET(28)(sp) FSREG f29, FOFFSET(29)(sp) FSREG f30, FOFFSET(30)(sp) FSREG f31, FOFFSET(31)(sp) #endif /* __riscv_flen */ /* Fill */ addi ra, a0, 1 /* sp must remain as is */ /* gp must remain as is */ /* tp must remain as is */ /* t0 is used for temporary values */ addi t1, a0, 2 addi t2, a0, 3 addi s0, a0, 4 addi s1, a0, 5 /* a0 is the pattern */ addi a1, a0, 6 addi a2, a0, 7 addi a3, a0, 8 addi a4, a0, 9 addi a5, a0, 10 addi a6, a0, 11 addi a7, a0, 12 addi s2, a0, 13 addi s3, a0, 14 addi s4, a0, 15 addi s5, a0, 16 addi s6, a0, 17 addi s7, a0, 18 addi s8, a0, 19 addi s9, a0, 20 addi s10, a0, 21 addi s11, a0, 22 addi t3, a0, 23 xor t4, sp, a0 xor t5, gp, a0 xor t6, tp, a0 #if __riscv_flen > 0 andi t0, a0, 0x1f fsflags t0 .macro fill_f reg, inc addi t0, a0, 24 + \inc FMVYX \reg, t0 .endm fill_f f0, 0 fill_f f1, 1 fill_f f2, 2 fill_f f3, 3 fill_f f4, 4 fill_f f5, 5 fill_f f6, 6 fill_f f7, 7 fill_f f8, 8 fill_f f9, 9 fill_f f10, 10 fill_f f11, 11 fill_f f12, 12 fill_f f13, 13 fill_f f14, 14 fill_f f15, 15 fill_f f16, 16 fill_f f17, 17 fill_f f18, 18 fill_f f19, 19 fill_f f20, 20 fill_f f21, 21 fill_f f22, 22 fill_f f23, 23 fill_f f24, 24 fill_f f25, 25 fill_f f26, 26 fill_f f27, 27 fill_f f28, 28 fill_f f29, 29 fill_f f30, 30 fill_f f31, 31 #endif /* __riscv_flen */ /* Check */ .Lcheck: .macro check_register reg, inc addi t0, a0, \inc bne \reg, t0, .Lrestore .endm check_register ra, 1 check_register t1, 2 check_register t2, 3 check_register s0, 4 check_register s1, 5 check_register a1, 6 check_register a2, 7 check_register a3, 8 check_register a4, 9 check_register a5, 10 check_register a6, 11 check_register a7, 12 check_register s2, 13 check_register s3, 14 check_register s4, 15 check_register s5, 16 check_register s6, 17 check_register s7, 18 check_register s8, 19 check_register s9, 20 check_register s10, 21 check_register s11, 22 check_register t3, 23 xor t0, sp, a0 bne t4, t0, .Lrestore xor t0, gp, a0 bne t5, t0, .Lrestore xor t0, tp, a0 bne t6, t0, .Lrestore #if __riscv_flen > 0 SREG t1, TMP_OFFSET(sp) frflags t0 andi t1, a0, 0x1f xor t0, t1, t0 LREG t1, TMP_OFFSET(sp) bnez t0, .Lrestore .macro check_f reg, inc FMVXY t0, \reg addi t0, t0, -24 - \inc bne t0, a0, .Lrestore .endm check_f f0, 0 check_f f1, 1 check_f f2, 2 check_f f3, 3 check_f f4, 4 check_f f5, 5 check_f f6, 6 check_f f7, 7 check_f f8, 8 check_f f9, 9 check_f f10, 10 check_f f11, 11 check_f f12, 12 check_f f13, 13 check_f f14, 14 check_f f15, 15 check_f f16, 16 check_f f17, 17 check_f f18, 18 check_f f19, 19 check_f f20, 20 check_f f21, 21 check_f f22, 22 check_f f23, 23 check_f f24, 24 check_f f25, 25 check_f f26, 26 check_f f27, 27 check_f f28, 28 check_f f29, 29 check_f f30, 30 check_f f31, 31 #endif /* __riscv_flen */ j .Lcheck /* Restore */ .Lrestore: LREG ra, RA_OFFSET(sp) LREG t0, T0_OFFSET(sp) LREG t1, T1_OFFSET(sp) LREG t2, T2_OFFSET(sp) LREG s0, S0_OFFSET(sp) LREG s1, S1_OFFSET(sp) LREG a0, A0_OFFSET(sp) LREG a1, A1_OFFSET(sp) LREG a2, A2_OFFSET(sp) LREG a3, A3_OFFSET(sp) LREG a4, A4_OFFSET(sp) LREG a5, A5_OFFSET(sp) LREG a6, A6_OFFSET(sp) LREG a7, A7_OFFSET(sp) LREG s2, S2_OFFSET(sp) LREG s3, S3_OFFSET(sp) LREG s4, S4_OFFSET(sp) LREG s5, S5_OFFSET(sp) LREG s6, S6_OFFSET(sp) LREG s7, S7_OFFSET(sp) LREG s8, S8_OFFSET(sp) LREG s9, S9_OFFSET(sp) LREG s10, S10_OFFSET(sp) LREG s11, S11_OFFSET(sp) LREG t3, T3_OFFSET(sp) LREG t4, T4_OFFSET(sp) LREG t5, T5_OFFSET(sp) LREG t6, T6_OFFSET(sp) #if __riscv_flen > 0 FLREG f0, FOFFSET(0)(sp) FLREG f1, FOFFSET(1)(sp) FLREG f2, FOFFSET(2)(sp) FLREG f3, FOFFSET(3)(sp) FLREG f4, FOFFSET(4)(sp) FLREG f5, FOFFSET(5)(sp) FLREG f6, FOFFSET(6)(sp) FLREG f7, FOFFSET(7)(sp) FLREG f8, FOFFSET(8)(sp) FLREG f9, FOFFSET(9)(sp) FLREG f10, FOFFSET(10)(sp) FLREG f11, FOFFSET(11)(sp) FLREG f12, FOFFSET(12)(sp) FLREG f13, FOFFSET(13)(sp) FLREG f14, FOFFSET(14)(sp) FLREG f15, FOFFSET(15)(sp) FLREG f16, FOFFSET(16)(sp) FLREG f17, FOFFSET(17)(sp) FLREG f18, FOFFSET(18)(sp) FLREG f19, FOFFSET(19)(sp) FLREG f20, FOFFSET(20)(sp) FLREG f21, FOFFSET(21)(sp) FLREG f22, FOFFSET(22)(sp) FLREG f23, FOFFSET(23)(sp) FLREG f24, FOFFSET(24)(sp) FLREG f25, FOFFSET(25)(sp) FLREG f26, FOFFSET(26)(sp) FLREG f27, FOFFSET(27)(sp) FLREG f28, FOFFSET(28)(sp) FLREG f29, FOFFSET(29)(sp) FLREG f30, FOFFSET(30)(sp) FLREG f31, FOFFSET(31)(sp) #endif /* __riscv_flen */ addi sp, sp, FRAME_SIZE ret