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