1 1.1 christos /* cpustate.h -- Prototypes for AArch64 simulator functions. 2 1.1 christos 3 1.1.1.6 christos Copyright (C) 2015-2024 Free Software Foundation, Inc. 4 1.1 christos 5 1.1 christos Contributed by Red Hat. 6 1.1 christos 7 1.1 christos This file is part of GDB. 8 1.1 christos 9 1.1 christos This program is free software; you can redistribute it and/or modify 10 1.1 christos it under the terms of the GNU General Public License as published by 11 1.1 christos the Free Software Foundation; either version 3 of the License, or 12 1.1 christos (at your option) any later version. 13 1.1 christos 14 1.1 christos This program is distributed in the hope that it will be useful, 15 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 16 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 1.1 christos GNU General Public License for more details. 18 1.1 christos 19 1.1 christos You should have received a copy of the GNU General Public License 20 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 21 1.1 christos 22 1.1.1.5 christos /* This must come before any other includes. */ 23 1.1.1.5 christos #include "defs.h" 24 1.1.1.5 christos 25 1.1 christos #include <stdio.h> 26 1.1.1.2 christos #include <math.h> 27 1.1 christos 28 1.1 christos #include "sim-main.h" 29 1.1.1.5 christos #include "sim-signal.h" 30 1.1 christos #include "cpustate.h" 31 1.1 christos #include "simulator.h" 32 1.1.1.4 christos #include "libiberty.h" 33 1.1 christos 34 1.1.1.6 christos #include "aarch64-sim.h" 35 1.1.1.6 christos 36 1.1 christos /* Some operands are allowed to access the stack pointer (reg 31). 37 1.1 christos For others a read from r31 always returns 0, and a write to r31 is ignored. */ 38 1.1 christos #define reg_num(reg) (((reg) == R31 && !r31_is_sp) ? 32 : (reg)) 39 1.1 christos 40 1.1 christos void 41 1.1 christos aarch64_set_reg_u64 (sim_cpu *cpu, GReg reg, int r31_is_sp, uint64_t val) 42 1.1 christos { 43 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 44 1.1.1.6 christos 45 1.1 christos if (reg == R31 && ! r31_is_sp) 46 1.1 christos { 47 1.1 christos TRACE_REGISTER (cpu, "GR[31] NOT CHANGED!"); 48 1.1 christos return; 49 1.1 christos } 50 1.1 christos 51 1.1.1.6 christos if (val != aarch64_cpu->gr[reg].u64) 52 1.1 christos TRACE_REGISTER (cpu, 53 1.1 christos "GR[%2d] changes from %16" PRIx64 " to %16" PRIx64, 54 1.1.1.6 christos reg, aarch64_cpu->gr[reg].u64, val); 55 1.1 christos 56 1.1.1.6 christos aarch64_cpu->gr[reg].u64 = val; 57 1.1 christos } 58 1.1 christos 59 1.1 christos void 60 1.1 christos aarch64_set_reg_s64 (sim_cpu *cpu, GReg reg, int r31_is_sp, int64_t val) 61 1.1 christos { 62 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 63 1.1.1.6 christos 64 1.1 christos if (reg == R31 && ! r31_is_sp) 65 1.1 christos { 66 1.1 christos TRACE_REGISTER (cpu, "GR[31] NOT CHANGED!"); 67 1.1 christos return; 68 1.1 christos } 69 1.1 christos 70 1.1.1.6 christos if (val != aarch64_cpu->gr[reg].s64) 71 1.1 christos TRACE_REGISTER (cpu, 72 1.1 christos "GR[%2d] changes from %16" PRIx64 " to %16" PRIx64, 73 1.1.1.6 christos reg, aarch64_cpu->gr[reg].s64, val); 74 1.1 christos 75 1.1.1.6 christos aarch64_cpu->gr[reg].s64 = val; 76 1.1 christos } 77 1.1 christos 78 1.1 christos uint64_t 79 1.1 christos aarch64_get_reg_u64 (sim_cpu *cpu, GReg reg, int r31_is_sp) 80 1.1 christos { 81 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->gr[reg_num(reg)].u64; 82 1.1 christos } 83 1.1 christos 84 1.1 christos int64_t 85 1.1 christos aarch64_get_reg_s64 (sim_cpu *cpu, GReg reg, int r31_is_sp) 86 1.1 christos { 87 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->gr[reg_num(reg)].s64; 88 1.1 christos } 89 1.1 christos 90 1.1 christos uint32_t 91 1.1 christos aarch64_get_reg_u32 (sim_cpu *cpu, GReg reg, int r31_is_sp) 92 1.1 christos { 93 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->gr[reg_num(reg)].u32; 94 1.1 christos } 95 1.1 christos 96 1.1 christos int32_t 97 1.1 christos aarch64_get_reg_s32 (sim_cpu *cpu, GReg reg, int r31_is_sp) 98 1.1 christos { 99 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->gr[reg_num(reg)].s32; 100 1.1 christos } 101 1.1 christos 102 1.1 christos void 103 1.1 christos aarch64_set_reg_s32 (sim_cpu *cpu, GReg reg, int r31_is_sp, int32_t val) 104 1.1 christos { 105 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 106 1.1.1.6 christos 107 1.1 christos if (reg == R31 && ! r31_is_sp) 108 1.1 christos { 109 1.1 christos TRACE_REGISTER (cpu, "GR[31] NOT CHANGED!"); 110 1.1 christos return; 111 1.1 christos } 112 1.1 christos 113 1.1.1.6 christos if (val != aarch64_cpu->gr[reg].s32) 114 1.1 christos TRACE_REGISTER (cpu, "GR[%2d] changes from %8x to %8x", 115 1.1.1.6 christos reg, aarch64_cpu->gr[reg].s32, val); 116 1.1 christos 117 1.1 christos /* The ARM ARM states that (C1.2.4): 118 1.1 christos When the data size is 32 bits, the lower 32 bits of the 119 1.1 christos register are used and the upper 32 bits are ignored on 120 1.1 christos a read and cleared to zero on a write. 121 1.1 christos We simulate this by first clearing the whole 64-bits and 122 1.1 christos then writing to the 32-bit value in the GRegister union. */ 123 1.1.1.6 christos aarch64_cpu->gr[reg].s64 = 0; 124 1.1.1.6 christos aarch64_cpu->gr[reg].s32 = val; 125 1.1 christos } 126 1.1 christos 127 1.1 christos void 128 1.1 christos aarch64_set_reg_u32 (sim_cpu *cpu, GReg reg, int r31_is_sp, uint32_t val) 129 1.1 christos { 130 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 131 1.1.1.6 christos 132 1.1 christos if (reg == R31 && ! r31_is_sp) 133 1.1 christos { 134 1.1 christos TRACE_REGISTER (cpu, "GR[31] NOT CHANGED!"); 135 1.1 christos return; 136 1.1 christos } 137 1.1 christos 138 1.1.1.6 christos if (val != aarch64_cpu->gr[reg].u32) 139 1.1 christos TRACE_REGISTER (cpu, "GR[%2d] changes from %8x to %8x", 140 1.1.1.6 christos reg, aarch64_cpu->gr[reg].u32, val); 141 1.1 christos 142 1.1.1.6 christos aarch64_cpu->gr[reg].u64 = 0; 143 1.1.1.6 christos aarch64_cpu->gr[reg].u32 = val; 144 1.1 christos } 145 1.1 christos 146 1.1 christos uint32_t 147 1.1 christos aarch64_get_reg_u16 (sim_cpu *cpu, GReg reg, int r31_is_sp) 148 1.1 christos { 149 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->gr[reg_num(reg)].u16; 150 1.1 christos } 151 1.1 christos 152 1.1 christos int32_t 153 1.1 christos aarch64_get_reg_s16 (sim_cpu *cpu, GReg reg, int r31_is_sp) 154 1.1 christos { 155 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->gr[reg_num(reg)].s16; 156 1.1 christos } 157 1.1 christos 158 1.1 christos uint32_t 159 1.1 christos aarch64_get_reg_u8 (sim_cpu *cpu, GReg reg, int r31_is_sp) 160 1.1 christos { 161 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->gr[reg_num(reg)].u8; 162 1.1 christos } 163 1.1 christos 164 1.1 christos int32_t 165 1.1 christos aarch64_get_reg_s8 (sim_cpu *cpu, GReg reg, int r31_is_sp) 166 1.1 christos { 167 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->gr[reg_num(reg)].s8; 168 1.1 christos } 169 1.1 christos 170 1.1 christos uint64_t 171 1.1 christos aarch64_get_PC (sim_cpu *cpu) 172 1.1 christos { 173 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->pc; 174 1.1 christos } 175 1.1 christos 176 1.1 christos uint64_t 177 1.1 christos aarch64_get_next_PC (sim_cpu *cpu) 178 1.1 christos { 179 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->nextpc; 180 1.1 christos } 181 1.1 christos 182 1.1 christos void 183 1.1 christos aarch64_set_next_PC (sim_cpu *cpu, uint64_t next) 184 1.1 christos { 185 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 186 1.1.1.6 christos 187 1.1.1.6 christos if (next != aarch64_cpu->nextpc + 4) 188 1.1 christos TRACE_REGISTER (cpu, 189 1.1 christos "NextPC changes from %16" PRIx64 " to %16" PRIx64, 190 1.1.1.6 christos aarch64_cpu->nextpc, next); 191 1.1 christos 192 1.1.1.6 christos aarch64_cpu->nextpc = next; 193 1.1 christos } 194 1.1 christos 195 1.1 christos void 196 1.1 christos aarch64_set_next_PC_by_offset (sim_cpu *cpu, int64_t offset) 197 1.1 christos { 198 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 199 1.1.1.6 christos 200 1.1.1.6 christos if (aarch64_cpu->pc + offset != aarch64_cpu->nextpc + 4) 201 1.1 christos TRACE_REGISTER (cpu, 202 1.1 christos "NextPC changes from %16" PRIx64 " to %16" PRIx64, 203 1.1.1.6 christos aarch64_cpu->nextpc, aarch64_cpu->pc + offset); 204 1.1 christos 205 1.1.1.6 christos aarch64_cpu->nextpc = aarch64_cpu->pc + offset; 206 1.1 christos } 207 1.1 christos 208 1.1 christos /* Install nextpc as current pc. */ 209 1.1 christos void 210 1.1 christos aarch64_update_PC (sim_cpu *cpu) 211 1.1 christos { 212 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 213 1.1.1.6 christos 214 1.1.1.6 christos aarch64_cpu->pc = aarch64_cpu->nextpc; 215 1.1 christos /* Rezero the register we hand out when asked for ZR just in case it 216 1.1 christos was used as the destination for a write by the previous 217 1.1 christos instruction. */ 218 1.1.1.6 christos aarch64_cpu->gr[32].u64 = 0UL; 219 1.1 christos } 220 1.1 christos 221 1.1 christos /* This instruction can be used to save the next PC to LR 222 1.1 christos just before installing a branch PC. */ 223 1.1 christos void 224 1.1 christos aarch64_save_LR (sim_cpu *cpu) 225 1.1 christos { 226 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 227 1.1.1.6 christos 228 1.1.1.6 christos if (aarch64_cpu->gr[LR].u64 != aarch64_cpu->nextpc) 229 1.1 christos TRACE_REGISTER (cpu, 230 1.1 christos "LR changes from %16" PRIx64 " to %16" PRIx64, 231 1.1.1.6 christos aarch64_cpu->gr[LR].u64, aarch64_cpu->nextpc); 232 1.1 christos 233 1.1.1.6 christos aarch64_cpu->gr[LR].u64 = aarch64_cpu->nextpc; 234 1.1 christos } 235 1.1 christos 236 1.1 christos static const char * 237 1.1 christos decode_cpsr (FlagMask flags) 238 1.1 christos { 239 1.1 christos switch (flags & CPSR_ALL_FLAGS) 240 1.1 christos { 241 1.1 christos default: 242 1.1 christos case 0: return "----"; 243 1.1 christos case 1: return "---V"; 244 1.1 christos case 2: return "--C-"; 245 1.1 christos case 3: return "--CV"; 246 1.1 christos case 4: return "-Z--"; 247 1.1 christos case 5: return "-Z-V"; 248 1.1 christos case 6: return "-ZC-"; 249 1.1 christos case 7: return "-ZCV"; 250 1.1 christos case 8: return "N---"; 251 1.1 christos case 9: return "N--V"; 252 1.1 christos case 10: return "N-C-"; 253 1.1 christos case 11: return "N-CV"; 254 1.1 christos case 12: return "NZ--"; 255 1.1 christos case 13: return "NZ-V"; 256 1.1 christos case 14: return "NZC-"; 257 1.1 christos case 15: return "NZCV"; 258 1.1 christos } 259 1.1 christos } 260 1.1 christos 261 1.1 christos /* Retrieve the CPSR register as an int. */ 262 1.1 christos uint32_t 263 1.1 christos aarch64_get_CPSR (sim_cpu *cpu) 264 1.1 christos { 265 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->CPSR; 266 1.1 christos } 267 1.1 christos 268 1.1 christos /* Set the CPSR register as an int. */ 269 1.1 christos void 270 1.1 christos aarch64_set_CPSR (sim_cpu *cpu, uint32_t new_flags) 271 1.1 christos { 272 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 273 1.1.1.6 christos 274 1.1 christos if (TRACE_REGISTER_P (cpu)) 275 1.1 christos { 276 1.1.1.6 christos if (aarch64_cpu->CPSR != new_flags) 277 1.1 christos TRACE_REGISTER (cpu, 278 1.1 christos "CPSR changes from %s to %s", 279 1.1.1.6 christos decode_cpsr (aarch64_cpu->CPSR), decode_cpsr (new_flags)); 280 1.1 christos else 281 1.1 christos TRACE_REGISTER (cpu, 282 1.1.1.6 christos "CPSR stays at %s", decode_cpsr (aarch64_cpu->CPSR)); 283 1.1 christos } 284 1.1 christos 285 1.1.1.6 christos aarch64_cpu->CPSR = new_flags & CPSR_ALL_FLAGS; 286 1.1 christos } 287 1.1 christos 288 1.1 christos /* Read a specific subset of the CPSR as a bit pattern. */ 289 1.1 christos uint32_t 290 1.1 christos aarch64_get_CPSR_bits (sim_cpu *cpu, FlagMask mask) 291 1.1 christos { 292 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->CPSR & mask; 293 1.1 christos } 294 1.1 christos 295 1.1 christos /* Assign a specific subset of the CPSR as a bit pattern. */ 296 1.1 christos void 297 1.1 christos aarch64_set_CPSR_bits (sim_cpu *cpu, uint32_t mask, uint32_t value) 298 1.1 christos { 299 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 300 1.1.1.6 christos uint32_t old_flags = aarch64_cpu->CPSR; 301 1.1 christos 302 1.1 christos mask &= CPSR_ALL_FLAGS; 303 1.1.1.6 christos aarch64_cpu->CPSR &= ~ mask; 304 1.1.1.6 christos aarch64_cpu->CPSR |= (value & mask); 305 1.1 christos 306 1.1.1.6 christos if (old_flags != aarch64_cpu->CPSR) 307 1.1 christos TRACE_REGISTER (cpu, 308 1.1 christos "CPSR changes from %s to %s", 309 1.1.1.6 christos decode_cpsr (old_flags), decode_cpsr (aarch64_cpu->CPSR)); 310 1.1 christos } 311 1.1 christos 312 1.1 christos /* Test the value of a single CPSR returned as non-zero or zero. */ 313 1.1 christos uint32_t 314 1.1 christos aarch64_test_CPSR_bit (sim_cpu *cpu, FlagMask bit) 315 1.1 christos { 316 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->CPSR & bit; 317 1.1 christos } 318 1.1 christos 319 1.1 christos /* Set a single flag in the CPSR. */ 320 1.1 christos void 321 1.1 christos aarch64_set_CPSR_bit (sim_cpu *cpu, FlagMask bit) 322 1.1 christos { 323 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 324 1.1.1.6 christos uint32_t old_flags = aarch64_cpu->CPSR; 325 1.1 christos 326 1.1.1.6 christos aarch64_cpu->CPSR |= (bit & CPSR_ALL_FLAGS); 327 1.1 christos 328 1.1.1.6 christos if (old_flags != aarch64_cpu->CPSR) 329 1.1 christos TRACE_REGISTER (cpu, 330 1.1 christos "CPSR changes from %s to %s", 331 1.1.1.6 christos decode_cpsr (old_flags), decode_cpsr (aarch64_cpu->CPSR)); 332 1.1 christos } 333 1.1 christos 334 1.1 christos /* Clear a single flag in the CPSR. */ 335 1.1 christos void 336 1.1 christos aarch64_clear_CPSR_bit (sim_cpu *cpu, FlagMask bit) 337 1.1 christos { 338 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 339 1.1.1.6 christos uint32_t old_flags = aarch64_cpu->CPSR; 340 1.1 christos 341 1.1.1.6 christos aarch64_cpu->CPSR &= ~(bit & CPSR_ALL_FLAGS); 342 1.1 christos 343 1.1.1.6 christos if (old_flags != aarch64_cpu->CPSR) 344 1.1 christos TRACE_REGISTER (cpu, 345 1.1 christos "CPSR changes from %s to %s", 346 1.1.1.6 christos decode_cpsr (old_flags), decode_cpsr (aarch64_cpu->CPSR)); 347 1.1 christos } 348 1.1 christos 349 1.1 christos float 350 1.1 christos aarch64_get_FP_half (sim_cpu *cpu, VReg reg) 351 1.1 christos { 352 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 353 1.1 christos union 354 1.1 christos { 355 1.1 christos uint16_t h[2]; 356 1.1 christos float f; 357 1.1 christos } u; 358 1.1 christos 359 1.1 christos u.h[0] = 0; 360 1.1.1.6 christos u.h[1] = aarch64_cpu->fr[reg].h[0]; 361 1.1 christos return u.f; 362 1.1 christos } 363 1.1 christos 364 1.1 christos 365 1.1 christos float 366 1.1 christos aarch64_get_FP_float (sim_cpu *cpu, VReg reg) 367 1.1 christos { 368 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->fr[reg].s; 369 1.1 christos } 370 1.1 christos 371 1.1 christos double 372 1.1 christos aarch64_get_FP_double (sim_cpu *cpu, VReg reg) 373 1.1 christos { 374 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->fr[reg].d; 375 1.1 christos } 376 1.1 christos 377 1.1 christos void 378 1.1 christos aarch64_get_FP_long_double (sim_cpu *cpu, VReg reg, FRegister *a) 379 1.1 christos { 380 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 381 1.1.1.6 christos 382 1.1.1.6 christos a->v[0] = aarch64_cpu->fr[reg].v[0]; 383 1.1.1.6 christos a->v[1] = aarch64_cpu->fr[reg].v[1]; 384 1.1 christos } 385 1.1 christos 386 1.1 christos void 387 1.1 christos aarch64_set_FP_half (sim_cpu *cpu, VReg reg, float val) 388 1.1 christos { 389 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 390 1.1 christos union 391 1.1 christos { 392 1.1 christos uint16_t h[2]; 393 1.1 christos float f; 394 1.1 christos } u; 395 1.1 christos 396 1.1 christos u.f = val; 397 1.1.1.6 christos aarch64_cpu->fr[reg].h[0] = u.h[1]; 398 1.1.1.6 christos aarch64_cpu->fr[reg].h[1] = 0; 399 1.1 christos } 400 1.1 christos 401 1.1 christos 402 1.1 christos void 403 1.1 christos aarch64_set_FP_float (sim_cpu *cpu, VReg reg, float val) 404 1.1 christos { 405 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 406 1.1.1.6 christos 407 1.1.1.6 christos if (val != aarch64_cpu->fr[reg].s 408 1.1.1.2 christos /* Handle +/- zero. */ 409 1.1.1.6 christos || signbit (val) != signbit (aarch64_cpu->fr[reg].s)) 410 1.1 christos { 411 1.1 christos FRegister v; 412 1.1 christos 413 1.1 christos v.s = val; 414 1.1 christos TRACE_REGISTER (cpu, 415 1.1.1.5 christos "FR[%d].s changes from %f to %f [hex: %0" PRIx64 "]", 416 1.1.1.6 christos reg, aarch64_cpu->fr[reg].s, val, v.v[0]); 417 1.1 christos } 418 1.1 christos 419 1.1.1.6 christos aarch64_cpu->fr[reg].s = val; 420 1.1 christos } 421 1.1 christos 422 1.1 christos void 423 1.1 christos aarch64_set_FP_double (sim_cpu *cpu, VReg reg, double val) 424 1.1 christos { 425 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 426 1.1.1.6 christos 427 1.1.1.6 christos if (val != aarch64_cpu->fr[reg].d 428 1.1.1.2 christos /* Handle +/- zero. */ 429 1.1.1.6 christos || signbit (val) != signbit (aarch64_cpu->fr[reg].d)) 430 1.1 christos { 431 1.1 christos FRegister v; 432 1.1 christos 433 1.1 christos v.d = val; 434 1.1 christos TRACE_REGISTER (cpu, 435 1.1.1.5 christos "FR[%d].d changes from %f to %f [hex: %0" PRIx64 "]", 436 1.1.1.6 christos reg, aarch64_cpu->fr[reg].d, val, v.v[0]); 437 1.1 christos } 438 1.1.1.6 christos aarch64_cpu->fr[reg].d = val; 439 1.1 christos } 440 1.1 christos 441 1.1 christos void 442 1.1 christos aarch64_set_FP_long_double (sim_cpu *cpu, VReg reg, FRegister a) 443 1.1 christos { 444 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 445 1.1.1.6 christos 446 1.1.1.6 christos if (aarch64_cpu->fr[reg].v[0] != a.v[0] 447 1.1.1.6 christos || aarch64_cpu->fr[reg].v[1] != a.v[1]) 448 1.1 christos TRACE_REGISTER (cpu, 449 1.1.1.5 christos "FR[%d].q changes from [%0" PRIx64 " %0" PRIx64 "] to [%0" 450 1.1.1.5 christos PRIx64 " %0" PRIx64 "] ", 451 1.1 christos reg, 452 1.1.1.6 christos aarch64_cpu->fr[reg].v[0], aarch64_cpu->fr[reg].v[1], 453 1.1 christos a.v[0], a.v[1]); 454 1.1 christos 455 1.1.1.6 christos aarch64_cpu->fr[reg].v[0] = a.v[0]; 456 1.1.1.6 christos aarch64_cpu->fr[reg].v[1] = a.v[1]; 457 1.1 christos } 458 1.1 christos 459 1.1.1.6 christos #define GET_VEC_ELEMENT(REG, ELEMENT, FIELD) \ 460 1.1.1.6 christos do \ 461 1.1.1.6 christos { \ 462 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); \ 463 1.1.1.6 christos \ 464 1.1.1.6 christos if (ELEMENT >= ARRAY_SIZE (aarch64_cpu->fr[0].FIELD)) \ 465 1.1 christos { \ 466 1.1.1.6 christos TRACE_REGISTER (cpu, \ 467 1.1 christos "Internal SIM error: invalid element number: %d ",\ 468 1.1 christos ELEMENT); \ 469 1.1 christos sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu), \ 470 1.1 christos sim_stopped, SIM_SIGBUS); \ 471 1.1 christos } \ 472 1.1.1.6 christos return aarch64_cpu->fr[REG].FIELD [ELEMENT]; \ 473 1.1 christos } \ 474 1.1 christos while (0) 475 1.1 christos 476 1.1 christos uint64_t 477 1.1 christos aarch64_get_vec_u64 (sim_cpu *cpu, VReg reg, unsigned element) 478 1.1 christos { 479 1.1 christos GET_VEC_ELEMENT (reg, element, v); 480 1.1 christos } 481 1.1 christos 482 1.1 christos uint32_t 483 1.1 christos aarch64_get_vec_u32 (sim_cpu *cpu, VReg reg, unsigned element) 484 1.1 christos { 485 1.1 christos GET_VEC_ELEMENT (reg, element, w); 486 1.1 christos } 487 1.1 christos 488 1.1 christos uint16_t 489 1.1 christos aarch64_get_vec_u16 (sim_cpu *cpu, VReg reg, unsigned element) 490 1.1 christos { 491 1.1 christos GET_VEC_ELEMENT (reg, element, h); 492 1.1 christos } 493 1.1 christos 494 1.1 christos uint8_t 495 1.1 christos aarch64_get_vec_u8 (sim_cpu *cpu, VReg reg, unsigned element) 496 1.1 christos { 497 1.1 christos GET_VEC_ELEMENT (reg, element, b); 498 1.1 christos } 499 1.1 christos 500 1.1 christos int64_t 501 1.1 christos aarch64_get_vec_s64 (sim_cpu *cpu, VReg reg, unsigned element) 502 1.1 christos { 503 1.1 christos GET_VEC_ELEMENT (reg, element, V); 504 1.1 christos } 505 1.1 christos 506 1.1 christos int32_t 507 1.1 christos aarch64_get_vec_s32 (sim_cpu *cpu, VReg reg, unsigned element) 508 1.1 christos { 509 1.1 christos GET_VEC_ELEMENT (reg, element, W); 510 1.1 christos } 511 1.1 christos 512 1.1 christos int16_t 513 1.1 christos aarch64_get_vec_s16 (sim_cpu *cpu, VReg reg, unsigned element) 514 1.1 christos { 515 1.1 christos GET_VEC_ELEMENT (reg, element, H); 516 1.1 christos } 517 1.1 christos 518 1.1 christos int8_t 519 1.1 christos aarch64_get_vec_s8 (sim_cpu *cpu, VReg reg, unsigned element) 520 1.1 christos { 521 1.1 christos GET_VEC_ELEMENT (reg, element, B); 522 1.1 christos } 523 1.1 christos 524 1.1 christos float 525 1.1 christos aarch64_get_vec_float (sim_cpu *cpu, VReg reg, unsigned element) 526 1.1 christos { 527 1.1 christos GET_VEC_ELEMENT (reg, element, S); 528 1.1 christos } 529 1.1 christos 530 1.1 christos double 531 1.1 christos aarch64_get_vec_double (sim_cpu *cpu, VReg reg, unsigned element) 532 1.1 christos { 533 1.1 christos GET_VEC_ELEMENT (reg, element, D); 534 1.1 christos } 535 1.1 christos 536 1.1 christos 537 1.1 christos #define SET_VEC_ELEMENT(REG, ELEMENT, VAL, FIELD, PRINTER) \ 538 1.1 christos do \ 539 1.1 christos { \ 540 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); \ 541 1.1.1.6 christos \ 542 1.1.1.6 christos if (ELEMENT >= ARRAY_SIZE (aarch64_cpu->fr[0].FIELD)) \ 543 1.1 christos { \ 544 1.1 christos TRACE_REGISTER (cpu, \ 545 1.1 christos "Internal SIM error: invalid element number: %d ",\ 546 1.1 christos ELEMENT); \ 547 1.1 christos sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu), \ 548 1.1 christos sim_stopped, SIM_SIGBUS); \ 549 1.1 christos } \ 550 1.1.1.6 christos if (VAL != aarch64_cpu->fr[REG].FIELD [ELEMENT]) \ 551 1.1 christos TRACE_REGISTER (cpu, \ 552 1.1 christos "VR[%2d]." #FIELD " [%d] changes from " PRINTER \ 553 1.1 christos " to " PRINTER , REG, \ 554 1.1.1.6 christos ELEMENT, aarch64_cpu->fr[REG].FIELD [ELEMENT], VAL); \ 555 1.1 christos \ 556 1.1.1.6 christos aarch64_cpu->fr[REG].FIELD [ELEMENT] = VAL; \ 557 1.1 christos } \ 558 1.1 christos while (0) 559 1.1 christos 560 1.1 christos void 561 1.1 christos aarch64_set_vec_u64 (sim_cpu *cpu, VReg reg, unsigned element, uint64_t val) 562 1.1 christos { 563 1.1.1.5 christos SET_VEC_ELEMENT (reg, element, val, v, "%16" PRIx64); 564 1.1 christos } 565 1.1 christos 566 1.1 christos void 567 1.1 christos aarch64_set_vec_u32 (sim_cpu *cpu, VReg reg, unsigned element, uint32_t val) 568 1.1 christos { 569 1.1 christos SET_VEC_ELEMENT (reg, element, val, w, "%8x"); 570 1.1 christos } 571 1.1 christos 572 1.1 christos void 573 1.1 christos aarch64_set_vec_u16 (sim_cpu *cpu, VReg reg, unsigned element, uint16_t val) 574 1.1 christos { 575 1.1 christos SET_VEC_ELEMENT (reg, element, val, h, "%4x"); 576 1.1 christos } 577 1.1 christos 578 1.1 christos void 579 1.1 christos aarch64_set_vec_u8 (sim_cpu *cpu, VReg reg, unsigned element, uint8_t val) 580 1.1 christos { 581 1.1 christos SET_VEC_ELEMENT (reg, element, val, b, "%x"); 582 1.1 christos } 583 1.1 christos 584 1.1 christos void 585 1.1 christos aarch64_set_vec_s64 (sim_cpu *cpu, VReg reg, unsigned element, int64_t val) 586 1.1 christos { 587 1.1.1.5 christos SET_VEC_ELEMENT (reg, element, val, V, "%16" PRIx64); 588 1.1 christos } 589 1.1 christos 590 1.1 christos void 591 1.1 christos aarch64_set_vec_s32 (sim_cpu *cpu, VReg reg, unsigned element, int32_t val) 592 1.1 christos { 593 1.1 christos SET_VEC_ELEMENT (reg, element, val, W, "%8x"); 594 1.1 christos } 595 1.1 christos 596 1.1 christos void 597 1.1 christos aarch64_set_vec_s16 (sim_cpu *cpu, VReg reg, unsigned element, int16_t val) 598 1.1 christos { 599 1.1 christos SET_VEC_ELEMENT (reg, element, val, H, "%4x"); 600 1.1 christos } 601 1.1 christos 602 1.1 christos void 603 1.1 christos aarch64_set_vec_s8 (sim_cpu *cpu, VReg reg, unsigned element, int8_t val) 604 1.1 christos { 605 1.1 christos SET_VEC_ELEMENT (reg, element, val, B, "%x"); 606 1.1 christos } 607 1.1 christos 608 1.1 christos void 609 1.1 christos aarch64_set_vec_float (sim_cpu *cpu, VReg reg, unsigned element, float val) 610 1.1 christos { 611 1.1 christos SET_VEC_ELEMENT (reg, element, val, S, "%f"); 612 1.1 christos } 613 1.1 christos 614 1.1 christos void 615 1.1 christos aarch64_set_vec_double (sim_cpu *cpu, VReg reg, unsigned element, double val) 616 1.1 christos { 617 1.1 christos SET_VEC_ELEMENT (reg, element, val, D, "%f"); 618 1.1 christos } 619 1.1 christos 620 1.1 christos void 621 1.1 christos aarch64_set_FPSR (sim_cpu *cpu, uint32_t value) 622 1.1 christos { 623 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 624 1.1.1.6 christos 625 1.1.1.6 christos if (aarch64_cpu->FPSR != value) 626 1.1 christos TRACE_REGISTER (cpu, 627 1.1.1.6 christos "FPSR changes from %x to %x", aarch64_cpu->FPSR, value); 628 1.1 christos 629 1.1.1.6 christos aarch64_cpu->FPSR = value & FPSR_ALL_FPSRS; 630 1.1 christos } 631 1.1 christos 632 1.1 christos uint32_t 633 1.1 christos aarch64_get_FPSR (sim_cpu *cpu) 634 1.1 christos { 635 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->FPSR; 636 1.1 christos } 637 1.1 christos 638 1.1 christos void 639 1.1 christos aarch64_set_FPSR_bits (sim_cpu *cpu, uint32_t mask, uint32_t value) 640 1.1 christos { 641 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 642 1.1.1.6 christos uint32_t old_FPSR = aarch64_cpu->FPSR; 643 1.1 christos 644 1.1 christos mask &= FPSR_ALL_FPSRS; 645 1.1.1.6 christos aarch64_cpu->FPSR &= ~mask; 646 1.1.1.6 christos aarch64_cpu->FPSR |= (value & mask); 647 1.1 christos 648 1.1.1.6 christos if (aarch64_cpu->FPSR != old_FPSR) 649 1.1 christos TRACE_REGISTER (cpu, 650 1.1.1.6 christos "FPSR changes from %x to %x", old_FPSR, aarch64_cpu->FPSR); 651 1.1 christos } 652 1.1 christos 653 1.1 christos uint32_t 654 1.1 christos aarch64_get_FPSR_bits (sim_cpu *cpu, uint32_t mask) 655 1.1 christos { 656 1.1 christos mask &= FPSR_ALL_FPSRS; 657 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->FPSR & mask; 658 1.1 christos } 659 1.1 christos 660 1.1 christos int 661 1.1 christos aarch64_test_FPSR_bit (sim_cpu *cpu, FPSRMask flag) 662 1.1 christos { 663 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->FPSR & flag; 664 1.1 christos } 665 1.1 christos 666 1.1 christos uint64_t 667 1.1 christos aarch64_get_thread_id (sim_cpu *cpu) 668 1.1 christos { 669 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->tpidr; 670 1.1 christos } 671 1.1 christos 672 1.1 christos uint32_t 673 1.1 christos aarch64_get_FPCR (sim_cpu *cpu) 674 1.1 christos { 675 1.1.1.6 christos return AARCH64_SIM_CPU (cpu)->FPCR; 676 1.1 christos } 677 1.1 christos 678 1.1 christos void 679 1.1 christos aarch64_set_FPCR (sim_cpu *cpu, uint32_t val) 680 1.1 christos { 681 1.1.1.6 christos struct aarch64_sim_cpu *aarch64_cpu = AARCH64_SIM_CPU (cpu); 682 1.1.1.6 christos 683 1.1.1.6 christos if (aarch64_cpu->FPCR != val) 684 1.1 christos TRACE_REGISTER (cpu, 685 1.1.1.6 christos "FPCR changes from %x to %x", aarch64_cpu->FPCR, val); 686 1.1.1.6 christos aarch64_cpu->FPCR = val; 687 1.1 christos } 688