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