--- a/src/hotspot/cpu/aarch64/cpustate_aarch64.hpp Mon Jul 29 18:31:18 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,595 +0,0 @@
-/*
- * Copyright (c) 2014, Red Hat Inc. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code 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
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef _CPU_STATE_H
-#define _CPU_STATE_H
-
-#include <sys/types.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.
- */
-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,
- // and now the aliases
- RSCRATCH1=R8,
- RSCRATCH2=R9,
- RMETHOD=R12,
- RESP=R20,
- RDISPATCH=R21,
- RBCP=R22,
- RLOCALS=R24,
- RMONITORS=R25,
- RCPOOL=R26,
- RHEAPBASE=R27,
- RTHREAD=R28,
- FP = R29,
- LR = R30,
- SP = R31,
- ZR = R31
-};
-
-/*
- * 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.
- */
-
-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,
-};
-
-/**
- * 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.
- *
- * n.b. the ARM spec says that when you write a 32 bit register you
- * are supposed to write the low 32 bits and zero the high 32
- * bits. But we don't actually have to care about this because Java
- * will only ever consume the 32 bits value as a 64 bit quantity after
- * an explicit extend.
- */
-union GRegisterValue
-{
- int8_t s8;
- int16_t s16;
- int32_t s32;
- int64_t s64;
- u_int8_t u8;
- u_int16_t u16;
- u_int32_t u32;
- u_int64_t u64;
-};
-
-class GRegister
-{
-public:
- GRegisterValue value;
-};
-
-/*
- * 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.
- */
-
-union FRegisterValue
-{
- float s;
- double d;
- long double q;
- // eventually we will need to be able to access the data as a vector
- // the integral array elements allow us to access the bits in s, d,
- // q, vs and vd at an appropriate level of granularity
- u_int8_t vb[16];
- u_int16_t vh[8];
- u_int32_t vw[4];
- u_int64_t vx[2];
- float vs[4];
- double vd[2];
-};
-
-class FRegister
-{
-public:
- FRegisterValue value;
-};
-
-/*
- * CPSR register -- this does not exist as a directly accessible
- * register but we need to store the flags so we can implement
- * flag-seting and flag testing operations
- *
- * we can possibly use injected x86 asm to report the outcome of flag
- * setting operations. if so we will need to grab the flags
- * immediately after the operation in order to ensure we don't lose
- * them because of the actions of the simulator. so we still need
- * somewhere to store the condition codes.
- */
-
-class CPSRRegister
-{
-public:
- u_int32_t value;
-
-/*
- * 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.
- */
-
- enum CPSRIdx {
- V_IDX,
- C_IDX,
- Z_IDX,
- N_IDX
- };
-
- enum CPSRMask {
- V = 1 << V_IDX,
- C = 1 << C_IDX,
- Z = 1 << Z_IDX,
- N = 1 << N_IDX
- };
-
- static const int CPSR_ALL_FLAGS = (V | C | Z | N);
-};
-
-// auxiliary function to assemble the relevant bits from
-// the x86 EFLAGS register into an ARM CPSR value
-
-#define X86_V_IDX 11
-#define X86_C_IDX 0
-#define X86_Z_IDX 6
-#define X86_N_IDX 7
-
-#define X86_V (1 << X86_V_IDX)
-#define X86_C (1 << X86_C_IDX)
-#define X86_Z (1 << X86_Z_IDX)
-#define X86_N (1 << X86_N_IDX)
-
-inline u_int32_t convertX86Flags(u_int32_t x86flags)
-{
- u_int32_t flags;
- // set N flag
- flags = ((x86flags & X86_N) >> X86_N_IDX);
- // shift then or in Z flag
- flags <<= 1;
- flags |= ((x86flags & X86_Z) >> X86_Z_IDX);
- // shift then or in C flag
- flags <<= 1;
- flags |= ((x86flags & X86_C) >> X86_C_IDX);
- // shift then or in V flag
- flags <<= 1;
- flags |= ((x86flags & X86_V) >> X86_V_IDX);
-
- return flags;
-}
-
-inline u_int32_t convertX86FlagsFP(u_int32_t x86flags)
-{
- // x86 flags set by fcomi(x,y) are ZF:PF:CF
- // (yes, that's PF for parity, WTF?)
- // where
- // 0) 0:0:0 means x > y
- // 1) 0:0:1 means x < y
- // 2) 1:0:0 means x = y
- // 3) 1:1:1 means x and y are unordered
- // note that we don't have to check PF so
- // we really have a simple 2-bit case switch
- // the corresponding ARM64 flags settings
- // in hi->lo bit order are
- // 0) --C-
- // 1) N---
- // 2) -ZC-
- // 3) --CV
-
- static u_int32_t armFlags[] = {
- 0b0010,
- 0b1000,
- 0b0110,
- 0b0011
- };
- // pick out the ZF and CF bits
- u_int32_t zc = ((x86flags & X86_Z) >> X86_Z_IDX);
- zc <<= 1;
- zc |= ((x86flags & X86_C) >> X86_C_IDX);
-
- return armFlags[zc];
-}
-
-/*
- * 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
- */
-
-class FPSRRegister
-{
-public:
- u_int32_t value;
- // indices for bits in the FPSR register value
- enum FPSRIdx {
- IO_IDX = 0,
- DZ_IDX = 1,
- OF_IDX = 2,
- UF_IDX = 3,
- IX_IDX = 4,
- ID_IDX = 7
- };
- // corresponding bits as numeric values
- 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)
- };
- static const int FPSR_ALL_FPSRS = (IO | DZ | OF | UF | IX | ID);
-};
-
-// debugger support
-
-enum PrintFormat
-{
- FMT_DECIMAL,
- FMT_HEX,
- FMT_SINGLE,
- FMT_DOUBLE,
- FMT_QUAD,
- FMT_MULTI
-};
-
-/*
- * model of the registers and other state associated with the cpu
- */
-class CPUState
-{
- friend class AArch64Simulator;
-private:
- // this is the PC of the instruction being executed
- u_int64_t pc;
- // this is the PC of the instruction to be executed next
- // it is defaulted to pc + 4 at instruction decode but
- // execute may reset it
-
- u_int64_t nextpc;
- GRegister gr[33]; // extra register at index 32 is used
- // to hold zero value
- FRegister fr[32];
- CPSRRegister cpsr;
- FPSRRegister fpsr;
-
-public:
-
- CPUState() {
- gr[20].value.u64 = 0; // establish initial condition for
- // checkAssertions()
- trace_counter = 0;
- }
-
- // General Register access macros
-
- // only xreg or xregs can be used as an lvalue in order to update a
- // register. this ensures that the top part of a register is always
- // assigned when it is written by the sim.
-
- inline u_int64_t &xreg(GReg reg, int r31_is_sp) {
- if (reg == R31 && !r31_is_sp) {
- return gr[32].value.u64;
- } else {
- return gr[reg].value.u64;
- }
- }
-
- inline int64_t &xregs(GReg reg, int r31_is_sp) {
- if (reg == R31 && !r31_is_sp) {
- return gr[32].value.s64;
- } else {
- return gr[reg].value.s64;
- }
- }
-
- inline u_int32_t wreg(GReg reg, int r31_is_sp) {
- if (reg == R31 && !r31_is_sp) {
- return gr[32].value.u32;
- } else {
- return gr[reg].value.u32;
- }
- }
-
- inline int32_t wregs(GReg reg, int r31_is_sp) {
- if (reg == R31 && !r31_is_sp) {
- return gr[32].value.s32;
- } else {
- return gr[reg].value.s32;
- }
- }
-
- inline u_int32_t hreg(GReg reg, int r31_is_sp) {
- if (reg == R31 && !r31_is_sp) {
- return gr[32].value.u16;
- } else {
- return gr[reg].value.u16;
- }
- }
-
- inline int32_t hregs(GReg reg, int r31_is_sp) {
- if (reg == R31 && !r31_is_sp) {
- return gr[32].value.s16;
- } else {
- return gr[reg].value.s16;
- }
- }
-
- inline u_int32_t breg(GReg reg, int r31_is_sp) {
- if (reg == R31 && !r31_is_sp) {
- return gr[32].value.u8;
- } else {
- return gr[reg].value.u8;
- }
- }
-
- inline int32_t bregs(GReg reg, int r31_is_sp) {
- if (reg == R31 && !r31_is_sp) {
- return gr[32].value.s8;
- } else {
- return gr[reg].value.s8;
- }
- }
-
- // FP Register access macros
-
- // all non-vector accessors return a reference so we can both read
- // and assign
-
- inline float &sreg(VReg reg) {
- return fr[reg].value.s;
- }
-
- inline double &dreg(VReg reg) {
- return fr[reg].value.d;
- }
-
- inline long double &qreg(VReg reg) {
- return fr[reg].value.q;
- }
-
- // all vector register accessors return a pointer
-
- inline float *vsreg(VReg reg) {
- return &fr[reg].value.vs[0];
- }
-
- inline double *vdreg(VReg reg) {
- return &fr[reg].value.vd[0];
- }
-
- inline u_int8_t *vbreg(VReg reg) {
- return &fr[reg].value.vb[0];
- }
-
- inline u_int16_t *vhreg(VReg reg) {
- return &fr[reg].value.vh[0];
- }
-
- inline u_int32_t *vwreg(VReg reg) {
- return &fr[reg].value.vw[0];
- }
-
- inline u_int64_t *vxreg(VReg reg) {
- return &fr[reg].value.vx[0];
- }
-
- union GRegisterValue prev_sp, prev_fp;
-
- static const int trace_size = 256;
- u_int64_t trace_buffer[trace_size];
- int trace_counter;
-
- bool checkAssertions()
- {
- // Make sure that SP is 16-aligned
- // Also make sure that ESP is above SP.
- // We don't care about checking ESP if it is null, i.e. it hasn't
- // been used yet.
- if (gr[31].value.u64 & 0x0f) {
- asm volatile("nop");
- return false;
- }
- return true;
- }
-
- // pc register accessors
-
- // this instruction can be used to fetch the current PC
- u_int64_t getPC();
- // instead of setting the current PC directly you can
- // first set the next PC (either absolute or PC-relative)
- // and later copy the next PC into the current PC
- // this supports a default increment by 4 at instruction
- // fetch with an optional reset by control instructions
- u_int64_t getNextPC();
- void setNextPC(u_int64_t next);
- void offsetNextPC(int64_t offset);
- // install nextpc as current pc
- void updatePC();
-
- // this instruction can be used to save the next PC to LR
- // just before installing a branch PC
- inline void saveLR() { gr[LR].value.u64 = nextpc; }
-
- // cpsr register accessors
- u_int32_t getCPSRRegister();
- void setCPSRRegister(u_int32_t flags);
- // read a specific subset of the flags as a bit pattern
- // mask should be composed using elements of enum FlagMask
- u_int32_t getCPSRBits(u_int32_t mask);
- // assign a specific subset of the flags as a bit pattern
- // mask and value should be composed using elements of enum FlagMask
- void setCPSRBits(u_int32_t mask, u_int32_t value);
- // test the value of a single flag returned as 1 or 0
- u_int32_t testCPSR(CPSRRegister::CPSRIdx idx);
- // set a single flag
- void setCPSR(CPSRRegister::CPSRIdx idx);
- // clear a single flag
- void clearCPSR(CPSRRegister::CPSRIdx idx);
- // utility method to set ARM CSPR flags from an x86 bit mask generated by integer arithmetic
- void setCPSRRegisterFromX86(u_int64_t x86Flags);
- // utility method to set ARM CSPR flags from an x86 bit mask generated by floating compare
- void setCPSRRegisterFromX86FP(u_int64_t x86Flags);
-
- // fpsr register accessors
- u_int32_t getFPSRRegister();
- void setFPSRRegister(u_int32_t flags);
- // read a specific subset of the fprs bits as a bit pattern
- // mask should be composed using elements of enum FPSRRegister::FlagMask
- u_int32_t getFPSRBits(u_int32_t mask);
- // assign a specific subset of the flags as a bit pattern
- // mask and value should be composed using elements of enum FPSRRegister::FlagMask
- void setFPSRBits(u_int32_t mask, u_int32_t value);
- // test the value of a single flag returned as 1 or 0
- u_int32_t testFPSR(FPSRRegister::FPSRIdx idx);
- // set a single flag
- void setFPSR(FPSRRegister::FPSRIdx idx);
- // clear a single flag
- void clearFPSR(FPSRRegister::FPSRIdx idx);
-
- // debugger support
- void printPC(int pending, const char *trailing = "\n");
- void printInstr(u_int32_t instr, void (*dasm)(u_int64_t), const char *trailing = "\n");
- void printGReg(GReg reg, PrintFormat format = FMT_HEX, const char *trailing = "\n");
- void printVReg(VReg reg, PrintFormat format = FMT_HEX, const char *trailing = "\n");
- void printCPSR(const char *trailing = "\n");
- void printFPSR(const char *trailing = "\n");
- void dumpState();
-};
-
-#endif // ifndef _CPU_STATE_H