src/hotspot/cpu/aarch64/cpustate_aarch64.hpp
changeset 57565 01bca26734bb
parent 57564 0a8436eda2fa
child 57566 ad84ae073248
--- a/src/hotspot/cpu/aarch64/cpustate_aarch64.hpp	Fri Jul 26 10:52:47 2019 +0200
+++ /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