mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-21 04:42:53 +08:00
6df01ab8ab
The defs.h header will take care of including the various config.h headers. For now, it's just config.h, but we'll add more when we integrate gnulib in. This header should be used instead of config.h, and should be the first include in every .c file. We won't rely on the old behavior where we expected files to include the port's sim-main.h which then includes the common sim-basics.h which then includes config.h. We have a ton of code that includes things before sim-main.h, and it sometimes needs to be that way. Creating a dedicated header avoids the ordering mess and implicit inclusion that shows up otherwise.
352 lines
10 KiB
C
352 lines
10 KiB
C
/* cpustate.h -- Prototypes for AArch64 cpu state functions.
|
|
|
|
Copyright (C) 2015-2021 Free Software Foundation, Inc.
|
|
|
|
Contributed by Red Hat.
|
|
|
|
This file is part of GDB.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef _CPU_STATE_H
|
|
#define _CPU_STATE_H
|
|
|
|
#include <sys/types.h>
|
|
#include <stdint.h>
|
|
#include <inttypes.h>
|
|
|
|
#include "sim/sim.h"
|
|
|
|
/* Symbolic names used to identify general registers which also match
|
|
the registers indices in machine code.
|
|
|
|
We have 32 general registers which can be read/written as 32 bit or
|
|
64 bit sources/sinks and are appropriately referred to as Wn or Xn
|
|
in the assembly code. Some instructions mix these access modes
|
|
(e.g. ADD X0, X1, W2) so the implementation of the instruction
|
|
needs to *know* which type of read or write access is required. */
|
|
typedef enum GReg
|
|
{
|
|
R0,
|
|
R1,
|
|
R2,
|
|
R3,
|
|
R4,
|
|
R5,
|
|
R6,
|
|
R7,
|
|
R8,
|
|
R9,
|
|
R10,
|
|
R11,
|
|
R12,
|
|
R13,
|
|
R14,
|
|
R15,
|
|
R16,
|
|
R17,
|
|
R18,
|
|
R19,
|
|
R20,
|
|
R21,
|
|
R22,
|
|
R23,
|
|
R24,
|
|
R25,
|
|
R26,
|
|
R27,
|
|
R28,
|
|
R29,
|
|
R30,
|
|
R31,
|
|
FP = R29,
|
|
LR = R30,
|
|
SP = R31,
|
|
ZR = R31
|
|
} GReg;
|
|
|
|
/* Symbolic names used to refer to floating point registers which also
|
|
match the registers indices in machine code.
|
|
|
|
We have 32 FP registers which can be read/written as 8, 16, 32, 64
|
|
and 128 bit sources/sinks and are appropriately referred to as Bn,
|
|
Hn, Sn, Dn and Qn in the assembly code. Some instructions mix these
|
|
access modes (e.g. FCVT S0, D0) so the implementation of the
|
|
instruction needs to *know* which type of read or write access is
|
|
required. */
|
|
|
|
typedef enum VReg
|
|
{
|
|
V0,
|
|
V1,
|
|
V2,
|
|
V3,
|
|
V4,
|
|
V5,
|
|
V6,
|
|
V7,
|
|
V8,
|
|
V9,
|
|
V10,
|
|
V11,
|
|
V12,
|
|
V13,
|
|
V14,
|
|
V15,
|
|
V16,
|
|
V17,
|
|
V18,
|
|
V19,
|
|
V20,
|
|
V21,
|
|
V22,
|
|
V23,
|
|
V24,
|
|
V25,
|
|
V26,
|
|
V27,
|
|
V28,
|
|
V29,
|
|
V30,
|
|
V31,
|
|
} VReg;
|
|
|
|
/* All the different integer bit patterns for the components of a
|
|
general register are overlaid here using a union so as to allow
|
|
all reading and writing of the desired bits. Note that we have
|
|
to take care when emulating a big-endian AArch64 as we are
|
|
running on a little endian host. */
|
|
|
|
typedef union GRegisterValue
|
|
{
|
|
#if !WORDS_BIGENDIAN
|
|
int8_t s8;
|
|
int16_t s16;
|
|
int32_t s32;
|
|
int64_t s64;
|
|
uint8_t u8;
|
|
uint16_t u16;
|
|
uint32_t u32;
|
|
uint64_t u64;
|
|
#else
|
|
struct { int64_t :56; int8_t s8; };
|
|
struct { int64_t :48; int16_t s16; };
|
|
struct { int64_t :32; int32_t s32; };
|
|
int64_t s64;
|
|
struct { uint64_t :56; uint8_t u8; };
|
|
struct { uint64_t :48; uint16_t u16; };
|
|
struct { uint64_t :32; uint32_t u32; };
|
|
uint64_t u64;
|
|
#endif
|
|
} GRegister;
|
|
|
|
/* Float registers provide for storage of a single, double or quad
|
|
word format float in the same register. Single floats are not
|
|
paired within each double register as per 32 bit arm. Instead each
|
|
128 bit register Vn embeds the bits for Sn, and Dn in the lower
|
|
quarter and half, respectively, of the bits for Qn.
|
|
|
|
The upper bits can also be accessed as single or double floats by
|
|
the float vector operations using indexing e.g. V1.D[1], V1.S[3]
|
|
etc and, for SIMD operations using a horrible index range notation.
|
|
|
|
The spec also talks about accessing float registers as half words
|
|
and bytes with Hn and Bn providing access to the low 16 and 8 bits
|
|
of Vn but it is not really clear what these bits represent. We can
|
|
probably ignore this for Java anyway. However, we do need to access
|
|
the raw bits at 32 and 64 bit resolution to load to/from integer
|
|
registers.
|
|
|
|
Note - we do not use the long double type. Aliasing issues between
|
|
integer and float values mean that it is unreliable to use them. */
|
|
|
|
typedef union FRegisterValue
|
|
{
|
|
float s;
|
|
double d;
|
|
|
|
uint64_t v[2];
|
|
uint32_t w[4];
|
|
uint16_t h[8];
|
|
uint8_t b[16];
|
|
|
|
int64_t V[2];
|
|
int32_t W[4];
|
|
int16_t H[8];
|
|
int8_t B[16];
|
|
|
|
float S[4];
|
|
double D[2];
|
|
|
|
} FRegister;
|
|
|
|
/* Condition register bit select values.
|
|
|
|
The order of bits here is important because some of
|
|
the flag setting conditional instructions employ a
|
|
bit field to populate the flags when a false condition
|
|
bypasses execution of the operation and we want to
|
|
be able to assign the flags register using the
|
|
supplied value. */
|
|
|
|
typedef enum FlagIdx
|
|
{
|
|
V_IDX = 0,
|
|
C_IDX = 1,
|
|
Z_IDX = 2,
|
|
N_IDX = 3
|
|
} FlagIdx;
|
|
|
|
typedef enum FlagMask
|
|
{
|
|
V = 1 << V_IDX,
|
|
C = 1 << C_IDX,
|
|
Z = 1 << Z_IDX,
|
|
N = 1 << N_IDX
|
|
} FlagMask;
|
|
|
|
#define CPSR_ALL_FLAGS (V | C | Z | N)
|
|
|
|
typedef uint32_t FlagsRegister;
|
|
|
|
/* FPSR register -- floating point status register
|
|
|
|
This register includes IDC, IXC, UFC, OFC, DZC, IOC and QC bits,
|
|
and the floating point N, Z, C, V bits but the latter are unused in
|
|
aarch64 mode. The sim ignores QC for now.
|
|
|
|
Bit positions are as per the ARMv7 FPSCR register
|
|
|
|
IDC : 7 ==> Input Denormal (cumulative exception bit)
|
|
IXC : 4 ==> Inexact
|
|
UFC : 3 ==> Underflow
|
|
OFC : 2 ==> Overflow
|
|
DZC : 1 ==> Division by Zero
|
|
IOC : 0 ==> Invalid Operation
|
|
|
|
The rounding mode is held in bits [23,22] defined as follows:
|
|
|
|
0b00 Round to Nearest (RN) mode
|
|
0b01 Round towards Plus Infinity (RP) mode
|
|
0b10 Round towards Minus Infinity (RM) mode
|
|
0b11 Round towards Zero (RZ) mode. */
|
|
|
|
/* Indices for bits in the FPSR register value. */
|
|
typedef enum FPSRIdx
|
|
{
|
|
IO_IDX = 0,
|
|
DZ_IDX = 1,
|
|
OF_IDX = 2,
|
|
UF_IDX = 3,
|
|
IX_IDX = 4,
|
|
ID_IDX = 7
|
|
} FPSRIdx;
|
|
|
|
/* Corresponding bits as numeric values. */
|
|
typedef enum FPSRMask
|
|
{
|
|
IO = (1 << IO_IDX),
|
|
DZ = (1 << DZ_IDX),
|
|
OF = (1 << OF_IDX),
|
|
UF = (1 << UF_IDX),
|
|
IX = (1 << IX_IDX),
|
|
ID = (1 << ID_IDX)
|
|
} FPSRMask;
|
|
|
|
#define FPSR_ALL_FPSRS (IO | DZ | OF | UF | IX | ID)
|
|
|
|
/* General Register access functions. */
|
|
extern uint64_t aarch64_get_reg_u64 (sim_cpu *, GReg, int);
|
|
extern int64_t aarch64_get_reg_s64 (sim_cpu *, GReg, int);
|
|
extern uint32_t aarch64_get_reg_u32 (sim_cpu *, GReg, int);
|
|
extern int32_t aarch64_get_reg_s32 (sim_cpu *, GReg, int);
|
|
extern uint32_t aarch64_get_reg_u16 (sim_cpu *, GReg, int);
|
|
extern int32_t aarch64_get_reg_s16 (sim_cpu *, GReg, int);
|
|
extern uint32_t aarch64_get_reg_u8 (sim_cpu *, GReg, int);
|
|
extern int32_t aarch64_get_reg_s8 (sim_cpu *, GReg, int);
|
|
|
|
extern void aarch64_set_reg_u64 (sim_cpu *, GReg, int, uint64_t);
|
|
extern void aarch64_set_reg_u32 (sim_cpu *, GReg, int, uint32_t);
|
|
extern void aarch64_set_reg_s64 (sim_cpu *, GReg, int, int64_t);
|
|
extern void aarch64_set_reg_s32 (sim_cpu *, GReg, int, int32_t);
|
|
|
|
/* FP Register access functions. */
|
|
extern float aarch64_get_FP_half (sim_cpu *, VReg);
|
|
extern float aarch64_get_FP_float (sim_cpu *, VReg);
|
|
extern double aarch64_get_FP_double (sim_cpu *, VReg);
|
|
extern void aarch64_get_FP_long_double (sim_cpu *, VReg, FRegister *);
|
|
|
|
extern void aarch64_set_FP_half (sim_cpu *, VReg, float);
|
|
extern void aarch64_set_FP_float (sim_cpu *, VReg, float);
|
|
extern void aarch64_set_FP_double (sim_cpu *, VReg, double);
|
|
extern void aarch64_set_FP_long_double (sim_cpu *, VReg, FRegister);
|
|
|
|
/* PC register accessors. */
|
|
extern uint64_t aarch64_get_PC (sim_cpu *);
|
|
extern uint64_t aarch64_get_next_PC (sim_cpu *);
|
|
extern void aarch64_set_next_PC (sim_cpu *, uint64_t);
|
|
extern void aarch64_set_next_PC_by_offset (sim_cpu *, int64_t);
|
|
extern void aarch64_update_PC (sim_cpu *);
|
|
extern void aarch64_save_LR (sim_cpu *);
|
|
|
|
/* Instruction accessor - implemented as a
|
|
macro as we do not need to annotate it. */
|
|
#define aarch64_get_instr(cpu) ((cpu)->instr)
|
|
|
|
/* Flag register accessors. */
|
|
extern uint32_t aarch64_get_CPSR (sim_cpu *);
|
|
extern void aarch64_set_CPSR (sim_cpu *, uint32_t);
|
|
extern uint32_t aarch64_get_CPSR_bits (sim_cpu *, uint32_t);
|
|
extern void aarch64_set_CPSR_bits (sim_cpu *, uint32_t, uint32_t);
|
|
extern uint32_t aarch64_test_CPSR_bit (sim_cpu *, FlagMask);
|
|
extern void aarch64_set_CPSR_bit (sim_cpu *, FlagMask);
|
|
extern void aarch64_clear_CPSR_bit (sim_cpu *, FlagMask);
|
|
|
|
extern void aarch64_set_FPSR (sim_cpu *, uint32_t);
|
|
extern uint32_t aarch64_get_FPSR (sim_cpu *);
|
|
extern void aarch64_set_FPSR_bits (sim_cpu *, uint32_t, uint32_t);
|
|
extern uint32_t aarch64_get_FPSR_bits (sim_cpu *, uint32_t);
|
|
extern int aarch64_test_FPSR_bit (sim_cpu *, FPSRMask);
|
|
|
|
/* Vector register accessors. */
|
|
extern uint64_t aarch64_get_vec_u64 (sim_cpu *, VReg, unsigned);
|
|
extern uint32_t aarch64_get_vec_u32 (sim_cpu *, VReg, unsigned);
|
|
extern uint16_t aarch64_get_vec_u16 (sim_cpu *, VReg, unsigned);
|
|
extern uint8_t aarch64_get_vec_u8 (sim_cpu *, VReg, unsigned);
|
|
extern void aarch64_set_vec_u64 (sim_cpu *, VReg, unsigned, uint64_t);
|
|
extern void aarch64_set_vec_u32 (sim_cpu *, VReg, unsigned, uint32_t);
|
|
extern void aarch64_set_vec_u16 (sim_cpu *, VReg, unsigned, uint16_t);
|
|
extern void aarch64_set_vec_u8 (sim_cpu *, VReg, unsigned, uint8_t);
|
|
|
|
extern int64_t aarch64_get_vec_s64 (sim_cpu *, VReg, unsigned);
|
|
extern int32_t aarch64_get_vec_s32 (sim_cpu *, VReg, unsigned);
|
|
extern int16_t aarch64_get_vec_s16 (sim_cpu *, VReg, unsigned);
|
|
extern int8_t aarch64_get_vec_s8 (sim_cpu *, VReg, unsigned);
|
|
extern void aarch64_set_vec_s64 (sim_cpu *, VReg, unsigned, int64_t);
|
|
extern void aarch64_set_vec_s32 (sim_cpu *, VReg, unsigned, int32_t);
|
|
extern void aarch64_set_vec_s16 (sim_cpu *, VReg, unsigned, int16_t);
|
|
extern void aarch64_set_vec_s8 (sim_cpu *, VReg, unsigned, int8_t);
|
|
|
|
extern float aarch64_get_vec_float (sim_cpu *, VReg, unsigned);
|
|
extern double aarch64_get_vec_double (sim_cpu *, VReg, unsigned);
|
|
extern void aarch64_set_vec_float (sim_cpu *, VReg, unsigned, float);
|
|
extern void aarch64_set_vec_double (sim_cpu *, VReg, unsigned, double);
|
|
|
|
/* System register accessors. */
|
|
extern uint64_t aarch64_get_thread_id (sim_cpu *);
|
|
extern uint32_t aarch64_get_FPCR (sim_cpu *);
|
|
extern void aarch64_set_FPCR (sim_cpu *, uint32_t);
|
|
|
|
#endif /* _CPU_STATE_H */
|