Shruti Gupta | 38133fa | 2023-04-19 17:00:38 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2023, Arm Limited. All rights reserved. |
| 3 | * |
| 4 | * SPDX-License-Identifier: BSD-3-Clause |
| 5 | */ |
Arunachalam Ganapathy | 7e514f6 | 2023-08-30 13:27:36 +0100 | [diff] [blame] | 6 | |
| 7 | #include <arch_helpers.h> |
Shruti Gupta | 38133fa | 2023-04-19 17:00:38 +0100 | [diff] [blame] | 8 | #include <stdbool.h> |
| 9 | #include <stdlib.h> |
| 10 | #include <string.h> |
| 11 | |
| 12 | #include <debug.h> |
| 13 | #include <lib/extensions/fpu.h> |
| 14 | |
| 15 | #define __STR(x) #x |
| 16 | #define STR(x) __STR(x) |
| 17 | |
| 18 | #define fill_simd_helper(num1, num2) "ldp q"#num1", q"#num2",\ |
| 19 | [%0], #"STR(2 * FPU_Q_SIZE)";" |
| 20 | #define read_simd_helper(num1, num2) "stp q"#num1", q"#num2",\ |
| 21 | [%0], #"STR(2 * FPU_Q_SIZE)";" |
| 22 | |
Arunachalam Ganapathy | 7e514f6 | 2023-08-30 13:27:36 +0100 | [diff] [blame] | 23 | /* Read FPU Q[0-31] and strore it in 'q_regs' */ |
| 24 | void fpu_q_regs_read(fpu_q_reg_t q_regs[FPU_Q_COUNT]) |
Shruti Gupta | 38133fa | 2023-04-19 17:00:38 +0100 | [diff] [blame] | 25 | { |
Shruti Gupta | 38133fa | 2023-04-19 17:00:38 +0100 | [diff] [blame] | 26 | __asm__ volatile( |
| 27 | read_simd_helper(0, 1) |
| 28 | read_simd_helper(2, 3) |
| 29 | read_simd_helper(4, 5) |
| 30 | read_simd_helper(6, 7) |
| 31 | read_simd_helper(8, 9) |
| 32 | read_simd_helper(10, 11) |
| 33 | read_simd_helper(12, 13) |
| 34 | read_simd_helper(14, 15) |
| 35 | read_simd_helper(16, 17) |
| 36 | read_simd_helper(18, 19) |
| 37 | read_simd_helper(20, 21) |
| 38 | read_simd_helper(22, 23) |
| 39 | read_simd_helper(24, 25) |
| 40 | read_simd_helper(26, 27) |
| 41 | read_simd_helper(28, 29) |
| 42 | read_simd_helper(30, 31) |
| 43 | "sub %0, %0, #" STR(FPU_Q_COUNT * FPU_Q_SIZE) ";" |
Arunachalam Ganapathy | 7e514f6 | 2023-08-30 13:27:36 +0100 | [diff] [blame] | 44 | : : "r" (q_regs)); |
Shruti Gupta | 38133fa | 2023-04-19 17:00:38 +0100 | [diff] [blame] | 45 | } |
| 46 | |
Arunachalam Ganapathy | 7e514f6 | 2023-08-30 13:27:36 +0100 | [diff] [blame] | 47 | /* Write FPU Q[0-31] registers passed in 'q_regs' */ |
| 48 | static void fpu_q_regs_write(const fpu_q_reg_t q_regs[FPU_Q_COUNT]) |
Shruti Gupta | 38133fa | 2023-04-19 17:00:38 +0100 | [diff] [blame] | 49 | { |
Shruti Gupta | 38133fa | 2023-04-19 17:00:38 +0100 | [diff] [blame] | 50 | __asm__ volatile( |
| 51 | fill_simd_helper(0, 1) |
| 52 | fill_simd_helper(2, 3) |
| 53 | fill_simd_helper(4, 5) |
| 54 | fill_simd_helper(6, 7) |
| 55 | fill_simd_helper(8, 9) |
| 56 | fill_simd_helper(10, 11) |
| 57 | fill_simd_helper(12, 13) |
| 58 | fill_simd_helper(14, 15) |
| 59 | fill_simd_helper(16, 17) |
| 60 | fill_simd_helper(18, 19) |
| 61 | fill_simd_helper(20, 21) |
| 62 | fill_simd_helper(22, 23) |
| 63 | fill_simd_helper(24, 25) |
| 64 | fill_simd_helper(26, 27) |
| 65 | fill_simd_helper(28, 29) |
| 66 | fill_simd_helper(30, 31) |
| 67 | "sub %0, %0, #" STR(FPU_Q_COUNT * FPU_Q_SIZE) ";" |
Arunachalam Ganapathy | 7e514f6 | 2023-08-30 13:27:36 +0100 | [diff] [blame] | 68 | : : "r" (q_regs)); |
Shruti Gupta | 38133fa | 2023-04-19 17:00:38 +0100 | [diff] [blame] | 69 | } |
| 70 | |
Arunachalam Ganapathy | 7e514f6 | 2023-08-30 13:27:36 +0100 | [diff] [blame] | 71 | /* Read FPCR and FPSR and store it in 'cs_regs' */ |
| 72 | void fpu_cs_regs_read(fpu_cs_regs_t *cs_regs) |
Shruti Gupta | 38133fa | 2023-04-19 17:00:38 +0100 | [diff] [blame] | 73 | { |
Arunachalam Ganapathy | 7e514f6 | 2023-08-30 13:27:36 +0100 | [diff] [blame] | 74 | cs_regs->fpcr = read_fpcr(); |
| 75 | cs_regs->fpsr = read_fpsr(); |
| 76 | } |
| 77 | |
| 78 | /* Write FPCR and FPSR passed in 'cs_regs' */ |
| 79 | void fpu_cs_regs_write(const fpu_cs_regs_t *cs_regs) |
| 80 | { |
| 81 | write_fpcr(cs_regs->fpcr); |
| 82 | write_fpsr(cs_regs->fpsr); |
| 83 | } |
| 84 | |
| 85 | /* |
| 86 | * Generate random values and write it to 'q_regs', then write it to FPU Q |
| 87 | * registers. |
| 88 | */ |
| 89 | void fpu_q_regs_write_rand(fpu_q_reg_t q_regs[FPU_Q_COUNT]) |
| 90 | { |
| 91 | uint32_t rval; |
| 92 | |
| 93 | rval = rand(); |
| 94 | |
| 95 | memset((void *)q_regs, 0, sizeof(fpu_q_reg_t) * FPU_Q_COUNT); |
Shruti Gupta | 38133fa | 2023-04-19 17:00:38 +0100 | [diff] [blame] | 96 | for (unsigned int num = 0U; num < FPU_Q_COUNT; num++) { |
Arunachalam Ganapathy | 7e514f6 | 2023-08-30 13:27:36 +0100 | [diff] [blame] | 97 | memset((uint8_t *)q_regs[num], rval * (num + 1), |
| 98 | sizeof(fpu_q_reg_t)); |
Shruti Gupta | 38133fa | 2023-04-19 17:00:38 +0100 | [diff] [blame] | 99 | } |
Arunachalam Ganapathy | 7e514f6 | 2023-08-30 13:27:36 +0100 | [diff] [blame] | 100 | fpu_q_regs_write(q_regs); |
Shruti Gupta | 38133fa | 2023-04-19 17:00:38 +0100 | [diff] [blame] | 101 | } |
| 102 | |
Arunachalam Ganapathy | 7e514f6 | 2023-08-30 13:27:36 +0100 | [diff] [blame] | 103 | /* |
| 104 | * Generate random values and write it to 'cs_regs', then write it to FPU FPCR |
| 105 | * and FPSR. |
| 106 | */ |
| 107 | void fpu_cs_regs_write_rand(fpu_cs_regs_t *cs_regs) |
Shruti Gupta | 38133fa | 2023-04-19 17:00:38 +0100 | [diff] [blame] | 108 | { |
Arunachalam Ganapathy | 7e514f6 | 2023-08-30 13:27:36 +0100 | [diff] [blame] | 109 | memset((void *)cs_regs, 0, sizeof(fpu_cs_regs_t)); |
Shruti Gupta | 38133fa | 2023-04-19 17:00:38 +0100 | [diff] [blame] | 110 | |
Arunachalam Ganapathy | 7e514f6 | 2023-08-30 13:27:36 +0100 | [diff] [blame] | 111 | cs_regs->fpcr = rand(); |
| 112 | cs_regs->fpsr = rand(); |
| 113 | |
| 114 | /* |
| 115 | * Write random value to FPCR FPSR. |
| 116 | * Note write will be ignored for reserved bits. |
| 117 | */ |
| 118 | fpu_cs_regs_write(cs_regs); |
| 119 | |
| 120 | /* Read back current FPCR and FPSR */ |
| 121 | fpu_cs_regs_read(cs_regs); |
| 122 | } |
| 123 | |
| 124 | /* |
| 125 | * Generate random values and write it to 'fpu_state', then write it to FPU Q |
| 126 | * registers, FPCR and FPSR. |
| 127 | */ |
| 128 | void fpu_state_write_rand(fpu_state_t *fpu_state) |
| 129 | { |
| 130 | fpu_q_regs_write_rand(fpu_state->q_regs); |
| 131 | fpu_cs_regs_write_rand(&fpu_state->cs_regs); |
| 132 | } |
| 133 | |
| 134 | /* Read FPU Q registers, FPCR and FPSR write it to 'fpu_state' */ |
| 135 | void fpu_state_read(fpu_state_t *fpu_state) |
| 136 | { |
| 137 | fpu_q_regs_read(fpu_state->q_regs); |
| 138 | fpu_cs_regs_read(&fpu_state->cs_regs); |
| 139 | } |
| 140 | |
| 141 | /* Return zero if FPU Q registers 's1', 's2' matches else nonzero */ |
| 142 | int fpu_q_regs_compare(const fpu_q_reg_t s1[FPU_Q_COUNT], |
| 143 | const fpu_q_reg_t s2[FPU_Q_COUNT]) |
| 144 | { |
| 145 | return memcmp(s1, s2, sizeof(fpu_q_reg_t) * FPU_Q_COUNT); |
| 146 | } |
| 147 | |
| 148 | /* |
| 149 | * Return zero if FPU control and status registers 's1', 's2' matches else |
| 150 | * nonzero |
| 151 | */ |
| 152 | int fpu_cs_regs_compare(const fpu_cs_regs_t *s1, const fpu_cs_regs_t *s2) |
| 153 | { |
| 154 | return memcmp(s1, s2, sizeof(fpu_cs_regs_t)); |
| 155 | } |
| 156 | |
| 157 | /* Returns 0, if FPU state 's1', 's2' matches else non-zero */ |
| 158 | int fpu_state_compare(const fpu_state_t *s1, const fpu_state_t *s2) |
| 159 | { |
| 160 | if (fpu_q_regs_compare(s1->q_regs, s2->q_regs) != 0) { |
| 161 | return 1; |
Shruti Gupta | 38133fa | 2023-04-19 17:00:38 +0100 | [diff] [blame] | 162 | } |
Arunachalam Ganapathy | 7e514f6 | 2023-08-30 13:27:36 +0100 | [diff] [blame] | 163 | |
| 164 | if (fpu_cs_regs_compare(&s1->cs_regs, &s2->cs_regs) != 0) { |
| 165 | return 1; |
| 166 | } |
| 167 | |
| 168 | return 0; |
Shruti Gupta | 38133fa | 2023-04-19 17:00:38 +0100 | [diff] [blame] | 169 | } |