blob: da887b33a458328611a213b309a80cf76996a07f [file] [log] [blame]
Shruti Gupta38133fa2023-04-19 17:00:38 +01001/*
2 * Copyright (c) 2023, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#include <stdbool.h>
7#include <stdlib.h>
8#include <string.h>
9
10#include <debug.h>
11#include <lib/extensions/fpu.h>
12
13#define __STR(x) #x
14#define STR(x) __STR(x)
15
16#define fill_simd_helper(num1, num2) "ldp q"#num1", q"#num2",\
17 [%0], #"STR(2 * FPU_Q_SIZE)";"
18#define read_simd_helper(num1, num2) "stp q"#num1", q"#num2",\
19 [%0], #"STR(2 * FPU_Q_SIZE)";"
20
21static fpu_reg_state_t g_fpu_read;
22
23static void read_fpu_state_registers(fpu_reg_state_t *fpu_template_in)
24{
25#ifdef __aarch64__
26
27 u_register_t fpsr;
28 u_register_t fpcr;
29
30 /* Read current FPCR FPSR and write to template. */
31 __asm__ volatile ("mrs %0, fpsr\n" : "=r" (fpsr));
32 __asm__ volatile ("mrs %0, fpcr\n" : "=r" (fpcr));
33 fpu_template_in->fpsr = fpsr;
34 fpu_template_in->fpcr = fpcr;
35
36 __asm__ volatile(
37 read_simd_helper(0, 1)
38 read_simd_helper(2, 3)
39 read_simd_helper(4, 5)
40 read_simd_helper(6, 7)
41 read_simd_helper(8, 9)
42 read_simd_helper(10, 11)
43 read_simd_helper(12, 13)
44 read_simd_helper(14, 15)
45 read_simd_helper(16, 17)
46 read_simd_helper(18, 19)
47 read_simd_helper(20, 21)
48 read_simd_helper(22, 23)
49 read_simd_helper(24, 25)
50 read_simd_helper(26, 27)
51 read_simd_helper(28, 29)
52 read_simd_helper(30, 31)
53 "sub %0, %0, #" STR(FPU_Q_COUNT * FPU_Q_SIZE) ";"
54 : : "r" (fpu_template_in->q));
55#endif
56}
57
58void fpu_state_fill_regs_and_template(fpu_reg_state_t *fpu_template_in)
59{
60 u_register_t fpsr;
61 u_register_t fpcr;
62 u_register_t temp;
63
64 temp = rand();
65 (void)memset((void *)fpu_template_in, 0, sizeof(fpu_reg_state_t));
66
67 /*
68 * Write random value to FPCR FPSR.
69 * Note write will be ignored for reserved bits.
70 */
71 __asm__ volatile ("mrs %0, fpsr\n" : "=r" (temp));
72 __asm__ volatile ("mrs %0, fpcr\n" : "=r" (temp));
73
74 /*
75 * Read back current FPCR FPSR and write to template,
76 */
77 __asm__ volatile ("mrs %0, fpsr\n" : "=r" (fpsr));
78 __asm__ volatile ("mrs %0, fpcr\n" : "=r" (fpcr));
79 fpu_template_in->fpsr = fpsr;
80 fpu_template_in->fpcr = fpcr;
81
82 for (unsigned int num = 0U; num < FPU_Q_COUNT; num++) {
83 memset((uint8_t *)fpu_template_in->q[num], temp * num,
84 sizeof(fpu_template_in->q[0]));
85 }
86 __asm__ volatile(
87 fill_simd_helper(0, 1)
88 fill_simd_helper(2, 3)
89 fill_simd_helper(4, 5)
90 fill_simd_helper(6, 7)
91 fill_simd_helper(8, 9)
92 fill_simd_helper(10, 11)
93 fill_simd_helper(12, 13)
94 fill_simd_helper(14, 15)
95 fill_simd_helper(16, 17)
96 fill_simd_helper(18, 19)
97 fill_simd_helper(20, 21)
98 fill_simd_helper(22, 23)
99 fill_simd_helper(24, 25)
100 fill_simd_helper(26, 27)
101 fill_simd_helper(28, 29)
102 fill_simd_helper(30, 31)
103 "sub %0, %0, #" STR(FPU_Q_COUNT * FPU_Q_SIZE) ";"
104 : : "r" (fpu_template_in->q));
105}
106
107void fpu_state_print(fpu_reg_state_t *vec)
108{
109 INFO("dumping FPU registers :\n");
110 for (unsigned int num = 0U; num < FPU_Q_COUNT; num++) {
111 INFO("Q[%u]=0x%llx%llx\n", num, (uint64_t)vec->q[num * FPU_Q_SIZE],
112 (uint64_t)(vec->q[num * FPU_Q_SIZE + 1]));
113 }
114 INFO("FPCR=0x%lx FPSR=0x%lx\n", vec->fpcr, vec->fpsr);
115}
116
117bool fpu_state_compare_template(fpu_reg_state_t *fpu_template_in)
118{
119 (void)memset((void *)&g_fpu_read, 0, sizeof(fpu_reg_state_t));
120 read_fpu_state_registers(&g_fpu_read);
121
122 if (memcmp((uint8_t *)fpu_template_in,
123 (uint8_t *)&g_fpu_read,
124 sizeof(fpu_reg_state_t)) != 0U) {
125 ERROR("%s failed\n", __func__);
126 ERROR("Read values\n");
127 fpu_state_print(&g_fpu_read);
128 ERROR("Template values\n");
129 fpu_state_print(fpu_template_in);
130 return false;
131 } else {
132 return true;
133 }
134}