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