Home | History | Annotate | Line # | Download | only in aarch64
      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