Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:23

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreCPUAArch64
0007  *
0008  * @brief Implementation of _CPU_Context_validate
0009  *
0010  * This file implements _CPU_Context_validate for use in spcontext01.
0011  */
0012 
0013 /*
0014  * Copyright (C) 2020 On-Line Applications Research Corporation (OAR)
0015  * Written by Kinsey Moore <kinsey.moore@oarcorp.com>
0016  *
0017  * Redistribution and use in source and binary forms, with or without
0018  * modification, are permitted provided that the following conditions
0019  * are met:
0020  * 1. Redistributions of source code must retain the above copyright
0021  *    notice, this list of conditions and the following disclaimer.
0022  * 2. Redistributions in binary form must reproduce the above copyright
0023  *    notice, this list of conditions and the following disclaimer in the
0024  *    documentation and/or other materials provided with the distribution.
0025  *
0026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0036  * POSSIBILITY OF SUCH DAMAGE.
0037  */
0038 
0039 #ifdef HAVE_CONFIG_H
0040 #include "config.h"
0041 #endif
0042 
0043 #include <rtems/asm.h>
0044 #include <rtems/score/cpu.h>
0045 #include <rtems/score/basedefs.h>
0046 
0047 /*
0048  * This register size applies to X (integer) registers as well as the D (lower
0049  * half floating point) registers. It does not apply to V (full size floating
0050  * point) registers or W (lower half integer) registers.
0051  */
0052 #define AARCH64_REGISTER_SIZE 8
0053 
0054 /* According to the AAPCS64, X19-X28 are callee-saved registers */
0055 #define FRAME_OFFSET_X19  0x00
0056 #define FRAME_OFFSET_X20  0x08
0057 #define FRAME_OFFSET_X21  0x10
0058 #define FRAME_OFFSET_X22  0x18
0059 #define FRAME_OFFSET_X23  0x20
0060 #define FRAME_OFFSET_X24  0x28
0061 #define FRAME_OFFSET_X25  0x30
0062 #define FRAME_OFFSET_X26  0x38
0063 #define FRAME_OFFSET_X27  0x40
0064 #define FRAME_OFFSET_X28  0x48
0065 #define FRAME_OFFSET_LR   0x50
0066 
0067 #ifdef AARCH64_MULTILIB_VFP
0068   /*
0069    * According to the AAPCS64, V8-V15 are callee-saved registers, but only the
0070    * bottom 8 bytes are required to be saved which correspond to D8-D15.
0071    */
0072   #define FRAME_OFFSET_D8  0x58
0073   #define FRAME_OFFSET_D9  0x60
0074   #define FRAME_OFFSET_D10 0x68
0075   #define FRAME_OFFSET_D11 0x70
0076   #define FRAME_OFFSET_D12 0x78
0077   #define FRAME_OFFSET_D13 0x80
0078   #define FRAME_OFFSET_D14 0x88
0079   #define FRAME_OFFSET_D15 0x90
0080 
0081   /*
0082    * Force 16 byte alignment of the frame size to avoid stack pointer alignment
0083    * exceptions.
0084    */
0085   #define FRAME_SIZE RTEMS_ALIGN_UP( FRAME_OFFSET_D15 + AARCH64_REGISTER_SIZE, 16 )
0086 #else
0087   #define FRAME_SIZE RTEMS_ALIGN_UP( FRAME_OFFSET_LR + AARCH64_REGISTER_SIZE, 16 )
0088 #endif
0089 
0090     .section    .text
0091 
0092 FUNCTION_ENTRY(_CPU_Context_validate)
0093 
0094     /* Save */
0095 
0096     sub sp, sp, #FRAME_SIZE
0097 
0098     str x19, [sp, #FRAME_OFFSET_X19]
0099     str x20, [sp, #FRAME_OFFSET_X20]
0100     str x21, [sp, #FRAME_OFFSET_X21]
0101     str x22, [sp, #FRAME_OFFSET_X22]
0102     str x23, [sp, #FRAME_OFFSET_X23]
0103     str x24, [sp, #FRAME_OFFSET_X24]
0104     str x25, [sp, #FRAME_OFFSET_X25]
0105     str x26, [sp, #FRAME_OFFSET_X26]
0106     str x27, [sp, #FRAME_OFFSET_X27]
0107     str x28, [sp, #FRAME_OFFSET_X28]
0108     str lr, [sp, #FRAME_OFFSET_LR]
0109 
0110 #ifdef AARCH64_MULTILIB_VFP
0111     str d8, [sp, #FRAME_OFFSET_D8]
0112     str d9, [sp, #FRAME_OFFSET_D9]
0113     str d10, [sp, #FRAME_OFFSET_D10]
0114     str d11, [sp, #FRAME_OFFSET_D11]
0115     str d12, [sp, #FRAME_OFFSET_D12]
0116     str d13, [sp, #FRAME_OFFSET_D13]
0117     str d14, [sp, #FRAME_OFFSET_D14]
0118     str d15, [sp, #FRAME_OFFSET_D15]
0119 #endif
0120 
0121     /* Fill */
0122 
0123     /* R1 is used for temporary values */
0124     mov x1, x0
0125 
0126     /* R2 contains the stack pointer */
0127     mov x2, sp
0128 
0129 .macro fill_register reg
0130     add x1, x1, #1
0131     mov \reg, x1
0132 .endm
0133 
0134 
0135 #ifdef AARCH64_MULTILIB_VFP
0136     /* X3 contains the FPSR */
0137     mrs x3, FPSR
0138     ldr x4, =0xf000001f
0139     bic x3, x3, x4
0140     and x4, x4, x0
0141     orr x3, x3, x4
0142     msr FPSR, x3
0143 #else
0144     fill_register   x3
0145 #endif
0146 
0147     fill_register   x4
0148     fill_register   x5
0149     fill_register   x6
0150     fill_register   x7
0151     fill_register   x8
0152     fill_register   x9
0153     fill_register   x10
0154     fill_register   x11
0155     fill_register   x12
0156     fill_register   x13
0157     fill_register   x14
0158     fill_register   x15
0159     fill_register   x16
0160     fill_register   x17
0161     fill_register   x18
0162     fill_register   x19
0163     fill_register   x20
0164     fill_register   x21
0165     fill_register   x22
0166     fill_register   x23
0167     fill_register   x24
0168     fill_register   x25
0169     fill_register   x26
0170     fill_register   x27
0171     fill_register   x28
0172     fill_register   x29
0173     fill_register   lr
0174 
0175 #ifdef AARCH64_MULTILIB_VFP
0176 .macro fill_vfp_register regnum
0177     add x1, x1, #1
0178     fmov    d\regnum\(), x1
0179     fmov    v\regnum\().D[1], x1
0180 .endm
0181 
0182     fill_vfp_register   0
0183     fill_vfp_register   1
0184     fill_vfp_register   2
0185     fill_vfp_register   3
0186     fill_vfp_register   4
0187     fill_vfp_register   5
0188     fill_vfp_register   6
0189     fill_vfp_register   7
0190     fill_vfp_register   8
0191     fill_vfp_register   9
0192     fill_vfp_register   10
0193     fill_vfp_register   11
0194     fill_vfp_register   12
0195     fill_vfp_register   13
0196     fill_vfp_register   14
0197     fill_vfp_register   15
0198     fill_vfp_register   16
0199     fill_vfp_register   17
0200     fill_vfp_register   18
0201     fill_vfp_register   19
0202     fill_vfp_register   20
0203     fill_vfp_register   21
0204     fill_vfp_register   22
0205     fill_vfp_register   23
0206     fill_vfp_register   24
0207     fill_vfp_register   25
0208     fill_vfp_register   26
0209     fill_vfp_register   27
0210     fill_vfp_register   28
0211     fill_vfp_register   29
0212     fill_vfp_register   30
0213     fill_vfp_register   31
0214 #endif /* AARCH64_MULTILIB_VFP */
0215 
0216     /* Check */
0217 check:
0218 
0219 .macro check_register reg
0220     add x1, x1, #1
0221     cmp \reg, x1
0222     bne restore
0223 .endm
0224 
0225     mov x1, sp
0226     cmp x2, x1
0227     bne restore
0228 
0229     mov x1, x0
0230 
0231 #ifndef AARCH64_MULTILIB_VFP
0232     check_register  x3
0233 #endif
0234 
0235     check_register  x4
0236     check_register  x5
0237     check_register  x6
0238     check_register  x7
0239     check_register  x8
0240     check_register  x9
0241     check_register  x10
0242     check_register  x11
0243     check_register  x12
0244     check_register  x13
0245     check_register  x14
0246     check_register  x15
0247     check_register  x16
0248     check_register  x17
0249     check_register  x18
0250     check_register  x19
0251     check_register  x20
0252     check_register  x21
0253     check_register  x22
0254     check_register  x23
0255     check_register  x24
0256     check_register  x25
0257     check_register  x26
0258     check_register  x27
0259     check_register  x28
0260     check_register  x29
0261     check_register  lr
0262 
0263 #ifdef AARCH64_MULTILIB_VFP
0264     b   check_vfp
0265 #endif
0266 
0267     b   check
0268 
0269     /* Restore */
0270 restore:
0271 
0272     ldr x19, [sp, #FRAME_OFFSET_X19]
0273     ldr x20, [sp, #FRAME_OFFSET_X20]
0274     ldr x21, [sp, #FRAME_OFFSET_X21]
0275     ldr x22, [sp, #FRAME_OFFSET_X22]
0276     ldr x23, [sp, #FRAME_OFFSET_X23]
0277     ldr x24, [sp, #FRAME_OFFSET_X24]
0278     ldr x25, [sp, #FRAME_OFFSET_X25]
0279     ldr x26, [sp, #FRAME_OFFSET_X26]
0280     ldr x27, [sp, #FRAME_OFFSET_X27]
0281     ldr x28, [sp, #FRAME_OFFSET_X28]
0282     ldr lr, [sp, #FRAME_OFFSET_LR]
0283 
0284 #ifdef AARCH64_MULTILIB_VFP
0285     ldr d8, [sp, #FRAME_OFFSET_D8]
0286     ldr d9, [sp, #FRAME_OFFSET_D9]
0287     ldr d10, [sp, #FRAME_OFFSET_D10]
0288     ldr d11, [sp, #FRAME_OFFSET_D11]
0289     ldr d12, [sp, #FRAME_OFFSET_D12]
0290     ldr d13, [sp, #FRAME_OFFSET_D13]
0291     ldr d14, [sp, #FRAME_OFFSET_D14]
0292     ldr d15, [sp, #FRAME_OFFSET_D15]
0293 #endif
0294 
0295     add sp, sp, #FRAME_SIZE
0296 
0297     ret
0298 
0299 FUNCTION_END(_CPU_Context_validate)
0300 
0301 #ifdef AARCH64_MULTILIB_VFP
0302 check_vfp:
0303 
0304 .macro check_vfp_register regnum
0305     add x1, x1, #1
0306     fmov    x4, d\regnum
0307     fmov    x5, v\regnum\().D[1]
0308     cmp x5, x4
0309     bne 1f
0310     cmp x1, x4
0311     bne 1f
0312     b   2f
0313 1:
0314     b   restore
0315 2:
0316 .endm
0317 
0318     mrs x4, FPSR
0319     cmp x4, x3
0320     bne restore
0321 
0322     check_vfp_register  0
0323     check_vfp_register  1
0324     check_vfp_register  2
0325     check_vfp_register  3
0326     check_vfp_register  4
0327     check_vfp_register  5
0328     check_vfp_register  6
0329     check_vfp_register  7
0330     check_vfp_register  8
0331     check_vfp_register  9
0332     check_vfp_register  10
0333     check_vfp_register  11
0334     check_vfp_register  12
0335     check_vfp_register  13
0336     check_vfp_register  14
0337     check_vfp_register  15
0338     check_vfp_register  16
0339     check_vfp_register  17
0340     check_vfp_register  18
0341     check_vfp_register  19
0342     check_vfp_register  20
0343     check_vfp_register  21
0344     check_vfp_register  22
0345     check_vfp_register  23
0346     check_vfp_register  24
0347     check_vfp_register  25
0348     check_vfp_register  26
0349     check_vfp_register  27
0350     check_vfp_register  28
0351     check_vfp_register  29
0352     check_vfp_register  30
0353     check_vfp_register  31
0354 
0355     /* Restore x4 and x5 */
0356     mov x1, x0
0357     fill_register   x4
0358     fill_register   x5
0359 
0360     b   check
0361 #endif /* AARCH64_MULTILIB_VFP */