xref: /netbsd-src/external/gpl3/gdb/dist/sim/aarch64/cpustate.c (revision 4d1eaf9104083d3c1d72a17f5c414777b18c6935)
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