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