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