Skip to content

Commit

Permalink
Attended PR comments.
Browse files Browse the repository at this point in the history
  • Loading branch information
FinnWilkinson committed Oct 31, 2024
1 parent 891b046 commit 98dab74
Show file tree
Hide file tree
Showing 18 changed files with 164 additions and 53 deletions.
7 changes: 1 addition & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ endif()
# we don't use git for LLVM here as it clones the entire LLVM repo which takes too long and we only need a relatively small part of it
FetchContent_Declare(
llvm
# URL https://github.com/llvm/llvm-project/releases/download/llvmorg-19.1.0/llvm-project-19.1.0.src.tar.xz
# URL_HASH MD5=cfecaf29f50dce67836d32ca6b927e1d
URL https://github.com/llvm/llvm-project/releases/download/llvmorg-18.1.8/llvm-project-18.1.8.src.tar.xz
URL_HASH MD5=81cd0be5ae6f1ad8961746116d426a96
)
Expand All @@ -43,9 +41,6 @@ FetchContent_Declare(
GIT_REPOSITORY https://github.com/UoB-HPC/capstone.git
GIT_TAG next-update # Branch for SimEng version 0.9.7
GIT_PROGRESS TRUE

# Old Git tag pre-Armv9.2
# GIT_TAG e7be7d99e718ef9741026b80fc6f5e100fdf4f94 # trunk
)

cmake_policy(SET CMP0048 NEW)
Expand Down Expand Up @@ -155,7 +150,7 @@ if(SIMENG_ENABLE_TESTS)

# Check LLVM version
if ((${LLVM_PACKAGE_VERSION} VERSION_LESS "8.0") OR (${LLVM_PACKAGE_VERSION} VERSION_GREATER_EQUAL "18.2"))
message(FATAL_ERROR "LLVM version must be >= 8.0 and <= 18.2")
message(FATAL_ERROR "LLVM version must be >= 8.0 and < 18.2")
endif()

# Print message containing if the full test suite will run
Expand Down
4 changes: 2 additions & 2 deletions configs/a64fx_SME.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ Register-Set:
FloatingPoint/SVE-Count: 128
Predicate-Count: 48
Conditional-Count: 128
Matrix-Count: 2
Table-Count: 8
SME-Matrix-Count: 2
SME-Lookup-Table-Count: 8
Pipeline-Widths:
Commit: 4
FrontEnd: 4
Expand Down
2 changes: 1 addition & 1 deletion docs/sphinx/developer/arch/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ SimEng architecture definitions are responsible for describing the features and

To achieve this, SimEng defines a set of abstract architecture-related classes. Discrete implementations of these classes are provided for each of the ISAs SimEng supports by default, and must also be implemented for adding support for new or custom ISAs.

ISA support is achieved through the use of the `Capstone <https://github.com/aquynh/capstone/>`_ disassembly framework, which disassembles a binary instruction into a C/C++ object that include operand registers, access types, and immediate values to name a few. In order to update SimEng's AArch64 support from Armv8.4-a to Armv9.2-a, we undertook a Capstone update to allow for disassembly of the Armv9.2-a ISA. The work done for this can be found `here <https://github.com/capstone-engine/capstone/pull/1907>`_. Extensive work continues to be done to Capstone by its community in order to allow for easier updating of ISA versions. This facilitated the recent update of SimEng's AArch64 ISA support to Armv9.4-a.
ISA support is achieved through the use of an in-house fork of the `Capstone <https://github.com/aquynh/capstone/>`_ disassembly framework, which disassembles a binary instruction into a C/C++ object that includes operand registers, access types, and immediate values to name a few. In order to update SimEng's AArch64 support from Armv8.4-a to Armv9.2-a, we undertook a Capstone update to allow for disassembly of the Armv9.2-a ISA. The work done for this can be found `here <https://github.com/capstone-engine/capstone/pull/1907>`_. Extensive work continues to be done to Capstone by its community in order to allow for easier updating of ISA versions. This facilitated the recent update of SimEng's AArch64 ISA support to Armv9.4-a.

Below provides more information on the abstract structure of a SimEng architecture and currently supported ISAs.

Expand Down
4 changes: 2 additions & 2 deletions docs/sphinx/developer/arch/supported/aarch64.rst
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ There are several useful variables that execution behaviours have access to:
This is the output vector, into which ``RegisterValue`` instances containing the results should be placed. Each entry in the vector corresponds to a destination register.

Some instructions have "implicit" destination registers: in these cases, the implicit destinations are added to the **start** of the results vector. For example, ``subs w0, w1, #1`` writes explicitly to ``w0``, but also implicitly sets the "NZCV" comparison flags. In this case, ``results[0]`` is expected to be the updated NZCV flags, while ``results[1]`` is expected to be the new value of ``w0``.
Some Load and Store instructions update the base memory address register (pre- or post-indexing). These registers are also classes as implicit destination registers and thus will be added to the start of the results vector. For example, ``ldr x1, [x0], #8`` writes explicitly to ``x1`` but also writes implicitly to ``x0``. In this case, ``results[0]`` is expected to be the updated ``x0`` value (``x0 + 8``) and ``results[1]`` is expected to be the new value of ``x1``.
Some Load and Store instructions update the base memory address register (pre- or post-indexing). These registers are also classed as implicit destination registers and thus will be added to the start of the results vector. For example, ``ldr x1, [x0], #8`` writes explicitly to ``x1`` but also writes implicitly to ``x0``. In this case, ``results[0]`` is expected to be the updated ``x0`` value (``x0 + 8``) and ``results[1]`` is expected to be the new value of ``x1``.

Memory instructions may have a "writeback" variant, where the register containing the address is updated by an offset during execution. In these cases, the address register is added as a destination *after* the other registers, corresponding with the textual representation of the registers. E.g., the instruction ``ldr x1, [x2, #8]!`` will expect the value of ``x1`` in ``results[0]``, while the updated address ``x2`` should be placed in ``results[1]``.

Expand Down Expand Up @@ -226,7 +226,7 @@ Concerning SVE & SME loads and stores, an effort should be made to merge contigu
Instruction aliases
*******************

Although Capstone has been configured to produce the disassembly information for the "real" instruction rather than that of its (preferred) alias, the instruction's mnemonic and operand string will still be that of its alias. Hence, if an exception occurs the printed instruction informtion may not match the internal opcode used.
Although Capstone has been configured to produce the disassembly information for the "real" instruction rather than that of its (preferred) alias, the instruction's mnemonic and operand string will still be that of its alias. Hence, if an exception occurs the printed instruction information may not match the internal opcode used.

Common Instruction Execution behaviour issues
*********************************************
Expand Down
2 changes: 1 addition & 1 deletion docs/sphinx/user/building_simeng.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ With this configuration, the build files will be generated in a directory called
More information about the LLVM_DIR value can be found `here <https://llvm.org/docs/CMake.html#embedding-llvm-in-your-project>`_.

.. Note::
LLVM versions greater than 18 or less than 8 are not supported. We'd recommend using LLVM 18.1.8 where possible as this has been verified by us to work correctly for the most recent version of SimEng.
LLVM versions greater than 18.2 or less than 8 are not supported. We'd recommend using LLVM 18.1.8 where possible as this has been verified by us to work correctly for the most recent version of SimEng. LLVM versions less than 14 will likely not support AArch64 SVE2, SME, or SME2 instructions.

b. Two additional flags are available when building SimEng. Firstly is ``-DSIMENG_SANITIZE={ON, OFF}`` which adds a selection of sanitisation compilation flags (primarily used during the development of the framework). Secondly is ``-SIMENG_OPTIMIZE={ON, OFF}`` which attempts to optimise the framework's compilation for the host machine through a set of compiler flags and options.

Expand Down
4 changes: 2 additions & 2 deletions docs/sphinx/user/configuring_simeng.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,10 @@ AArch64
- Conditional-Count
The number of physical status/flag/conditional-code registers.

- Matrix-Count (Optional)
- SME-Matrix-Count (Optional)
The number of physical ``za`` Arm SME registers.

- Table-Count (Optional)
- SME-Lookup-Table-Count (Optional)
The number of physical SME Lookup Table registers (``zt0``).

RISC-V
Expand Down
10 changes: 5 additions & 5 deletions src/include/simeng/arch/aarch64/ArchInfo.hh
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ class ArchInfo : public simeng::arch::ArchInfo {
uint16_t fpCount = regConfig["FloatingPoint/SVE-Count"].as<uint16_t>();
uint16_t predCount = regConfig["Predicate-Count"].as<uint16_t>();
uint16_t condCount = regConfig["Conditional-Count"].as<uint16_t>();
uint16_t matCount = regConfig["Matrix-Count"].as<uint16_t>();
uint16_t tabCount = regConfig["Table-Count"].as<uint16_t>();
// Matrix-Count multiplied by (SVL/8) as internal representation of ZA is a
// block of row-vector-registers. Therefore, we need to convert physical
// counts from whole-ZA to rows-in-ZA.
uint16_t matCount = regConfig["SME-Matrix-Count"].as<uint16_t>();
uint16_t tabCount = regConfig["SME-Lookup-Table-Count"].as<uint16_t>();
// SME-Matrix-Count multiplied by (SVL/8) as internal representation of ZA
// is a block of row-vector-registers. Therefore, we need to convert
// physical counts from whole-ZA to rows-in-ZA.
matCount *= zaSize_;
physRegStruct_ = {{8, gpCount},
{256, fpCount},
Expand Down
15 changes: 8 additions & 7 deletions src/include/simeng/arch/aarch64/Instruction.hh
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ struct MicroOpInfo {
int microOpIndex = 0;
};

// TODO: Handle multi-register aarch64_reg operands
/** Get the size of the data to be accessed from/to memory. */
inline uint8_t getDataSize(cs_aarch64_op op) {
// No V-register enum identifiers exist. Instead, depending on whether a full
Expand Down Expand Up @@ -118,7 +117,11 @@ inline uint8_t getDataSize(cs_aarch64_op op) {
case AARCH64LAYOUT_VL_B:
return 1;
default:
assert(false && "Unknown VAS type");
std::cerr << "[SimEng] Cannot determine size of Arm V vector register "
"elements with `reg` value "
<< op.reg << " and `vas` value of " << vas << ". Exiting..."
<< std::endl;
exit(1);
break;
}
}
Expand Down Expand Up @@ -168,16 +171,14 @@ inline uint8_t getDataSize(cs_aarch64_op op) {
return 16;
}

// ARCH64_REG_PN0 -> +15 are scalable predicate registers
// ARCH64_REG_PN0 -> +15 are 256-bit (P) registers
if (op.reg >= AARCH64_REG_PN0) {
/** TODO: Check functionality is correct when multi-vector operands + SME2
* has been supported. */
return 1;
return 32;
}

// AARCH64_REG_P0 -> +15 are 256-bit (P) registers
if (op.reg >= AARCH64_REG_P0) {
return 1;
return 32;
}

// AARCH64_REG_H0 -> +31 are 16-bit arranged (H) neon registers
Expand Down
2 changes: 1 addition & 1 deletion src/include/simeng/arch/aarch64/MicroDecoder.hh
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class MicroDecoder {

// Default objects
/** Default capstone instruction structure. */
cs_aarch64 default_info = {AArch64CC_Invalid, false, false, 0, {}};
cs_aarch64 default_info = {AArch64CC_Invalid, false, false, false, 0, {}};

/** Default register. */
cs_aarch64_op default_op = {0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ bitfieldManipulate(T value, T dest, uint8_t rotateBy, uint8_t sourceBits,

/** Function to check if NZCV conditions hold. */
inline bool conditionHolds(uint8_t cond, uint8_t nzcv) {
// Due to Capstone enum changes, need to add 1 to cond
bool inverse = cond & 1;
uint8_t upper = cond >> 1;
bool n = (nzcv >> 3) & 1;
Expand Down
2 changes: 1 addition & 1 deletion src/include/simeng/arch/aarch64/helpers/sve.hh
Original file line number Diff line number Diff line change
Expand Up @@ -1046,7 +1046,7 @@ RegisterValue sveMax_vecImm(
return {out, 256};
}

/** Helper function for SVE instructions with the format `max zdn, pg/m zdn,
/** Helper function for SVE instructions with the format `max zdn, pg/m, zdn,
* zm`.
* T represents the type of sourceValues (e.g. for zdn.d, T = uint64_t).
* Returns correctly formatted RegisterValue. */
Expand Down
2 changes: 2 additions & 0 deletions src/lib/arch/aarch64/Architecture.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config)
}

cs_option(capstoneHandle_, CS_OPT_DETAIL, CS_OPT_ON);
// This second Capstone option reverses instruction aliases, and instead
// means all operand information is that of the "real" underlying instruction.
cs_option(capstoneHandle_, CS_OPT_DETAIL, CS_OPT_DETAIL_REAL);

// Generate zero-indexed system register map
Expand Down
78 changes: 76 additions & 2 deletions src/lib/arch/aarch64/InstructionMetadata.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,19 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn)
operands[0].access = CS_AC_WRITE;
break;
case Opcode::AArch64_ADR_LSL_ZZZ_D_0: // example bytecode = c8a0e704
[[fallthrough]];
case Opcode::AArch64_ADR_LSL_ZZZ_D_1:
[[fallthrough]];
case Opcode::AArch64_ADR_LSL_ZZZ_D_2:
[[fallthrough]];
case Opcode::AArch64_ADR_LSL_ZZZ_D_3:
[[fallthrough]];
case Opcode::AArch64_ADR_LSL_ZZZ_S_0:
[[fallthrough]];
case Opcode::AArch64_ADR_LSL_ZZZ_S_1:
[[fallthrough]];
case Opcode::AArch64_ADR_LSL_ZZZ_S_2:
[[fallthrough]];
case Opcode::AArch64_ADR_LSL_ZZZ_S_3: {
// Change the last 2 Z-regs from one MEM operand to two REG operands
operandCount = 3;
Expand All @@ -63,36 +70,52 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn)
break;
}
case Opcode::AArch64_CASALW: // Example bytecode - 02fce188
[[fallthrough]];
case Opcode::AArch64_CASALX:
// Remove implicit destination (MEM base reg)
implicitDestinationCount = 0;
break;
case Opcode::AArch64_ADD_ZI_B: // Example bytecode - 00c12025
[[fallthrough]];
case Opcode::AArch64_ADD_ZI_D:
[[fallthrough]];
case Opcode::AArch64_ADD_ZI_H:
[[fallthrough]];
case Opcode::AArch64_ADD_ZI_S: {
// Incorrect access types
operands[0].access = CS_AC_WRITE;
operands[1].access = CS_AC_READ;
break;
}
case Opcode::AArch64_SMAX_ZI_B:
[[fallthrough]];
case Opcode::AArch64_SMAX_ZI_D:
[[fallthrough]];
case Opcode::AArch64_SMAX_ZI_H:
[[fallthrough]];
case Opcode::AArch64_SMAX_ZI_S: // Example bytecode - 03c0a825
case Opcode::AArch64_AND_ZI: // Example bytecode - 00068005
[[fallthrough]];
case Opcode::AArch64_AND_ZI: // Example bytecode - 00068005
// Incorrect access types
operands[0].access = CS_AC_WRITE;
operands[1].access = CS_AC_READ;
break;
case Opcode::AArch64_FSUB_ZPmI_D:
[[fallthrough]];
case Opcode::AArch64_FSUB_ZPmI_H:
[[fallthrough]];
case Opcode::AArch64_FSUB_ZPmI_S: // Example bytecode - 00849965
[[fallthrough]];
case Opcode::AArch64_FMUL_ZPmI_D:
[[fallthrough]];
case Opcode::AArch64_FMUL_ZPmI_H:
[[fallthrough]];
case Opcode::AArch64_FMUL_ZPmI_S: // Example bytecode - 00809a65
[[fallthrough]];
case Opcode::AArch64_FADD_ZPmI_D: // Example bytecode - 0584d865
[[fallthrough]];
case Opcode::AArch64_FADD_ZPmI_H:
[[fallthrough]];
case Opcode::AArch64_FADD_ZPmI_S: {
// Incorrect access types
operands[0].access = CS_AC_WRITE;
Expand All @@ -101,56 +124,107 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn)
break;
}
case Opcode::AArch64_AND_ZPmZ_D: // Example bytecode - 4901da04
[[fallthrough]];
case Opcode::AArch64_AND_ZPmZ_H:
[[fallthrough]];
case Opcode::AArch64_AND_ZPmZ_S:
[[fallthrough]];
case Opcode::AArch64_AND_ZPmZ_B:
[[fallthrough]];
case Opcode::AArch64_SMULH_ZPmZ_B: // Example bytecode - 20001204
[[fallthrough]];
case Opcode::AArch64_SMULH_ZPmZ_D:
[[fallthrough]];
case Opcode::AArch64_SMULH_ZPmZ_H:
[[fallthrough]];
case Opcode::AArch64_SMULH_ZPmZ_S:
[[fallthrough]];
case Opcode::AArch64_SMIN_ZPmZ_B:
[[fallthrough]];
case Opcode::AArch64_SMIN_ZPmZ_D:
[[fallthrough]];
case Opcode::AArch64_SMIN_ZPmZ_H:
[[fallthrough]];
case Opcode::AArch64_SMIN_ZPmZ_S: // Example bytecode - 01008a04
[[fallthrough]];
case Opcode::AArch64_SMAX_ZPmZ_B:
[[fallthrough]];
case Opcode::AArch64_SMAX_ZPmZ_D:
[[fallthrough]];
case Opcode::AArch64_SMAX_ZPmZ_H:
[[fallthrough]];
case Opcode::AArch64_SMAX_ZPmZ_S: // Example bytecode - 01008804
case Opcode::AArch64_MUL_ZPmZ_B: // Example bytecode - 40001004
[[fallthrough]];
case Opcode::AArch64_MUL_ZPmZ_B: // Example bytecode - 40001004
[[fallthrough]];
case Opcode::AArch64_MUL_ZPmZ_D:
[[fallthrough]];
case Opcode::AArch64_MUL_ZPmZ_H:
[[fallthrough]];
case Opcode::AArch64_MUL_ZPmZ_S:
[[fallthrough]];
case Opcode::AArch64_FSUBR_ZPmZ_D:
[[fallthrough]];
case Opcode::AArch64_FSUBR_ZPmZ_H:
[[fallthrough]];
case Opcode::AArch64_FSUBR_ZPmZ_S: // Example bytecode - 24808365
[[fallthrough]];
case Opcode::AArch64_FSUB_ZPmZ_D:
[[fallthrough]];
case Opcode::AArch64_FSUB_ZPmZ_H:
[[fallthrough]];
case Opcode::AArch64_FSUB_ZPmZ_S: // Example bytecode - 24808165
[[fallthrough]];
case Opcode::AArch64_FMUL_ZPmZ_D:
[[fallthrough]];
case Opcode::AArch64_FMUL_ZPmZ_H:
[[fallthrough]];
case Opcode::AArch64_FMUL_ZPmZ_S: // Example bytecode - 83808265
[[fallthrough]];
case Opcode::AArch64_FDIV_ZPmZ_D: // Example bytecode - 0184cd65
[[fallthrough]];
case Opcode::AArch64_FDIV_ZPmZ_H:
[[fallthrough]];
case Opcode::AArch64_FDIV_ZPmZ_S:
[[fallthrough]];
case Opcode::AArch64_FDIVR_ZPmZ_D: // Example bytecode - 0184cc65
[[fallthrough]];
case Opcode::AArch64_FDIVR_ZPmZ_H:
[[fallthrough]];
case Opcode::AArch64_FDIVR_ZPmZ_S:
[[fallthrough]];
case Opcode::AArch64_FADDA_VPZ_D:
[[fallthrough]];
case Opcode::AArch64_FADDA_VPZ_H:
[[fallthrough]];
case Opcode::AArch64_FADDA_VPZ_S: // Example bytecode - 01249865
[[fallthrough]];
case Opcode::AArch64_FADD_ZPmZ_D: // Example bytecode - 6480c065
[[fallthrough]];
case Opcode::AArch64_FADD_ZPmZ_H:
[[fallthrough]];
case Opcode::AArch64_FADD_ZPmZ_S:
[[fallthrough]];
case Opcode::AArch64_FCADD_ZPmZ_D: // Example bytecode - 2080c064
[[fallthrough]];
case Opcode::AArch64_FCADD_ZPmZ_H:
[[fallthrough]];
case Opcode::AArch64_FCADD_ZPmZ_S:
[[fallthrough]];
case Opcode::AArch64_ADD_ZPmZ_B: // Example bytecode - 00000004
[[fallthrough]];
case Opcode::AArch64_ADD_ZPmZ_D:
[[fallthrough]];
case Opcode::AArch64_ADD_ZPmZ_H:
[[fallthrough]];
case Opcode::AArch64_ADD_ZPmZ_S:
[[fallthrough]];
case Opcode::AArch64_EOR_ZPmZ_B: // Example bytecode - 20001904
[[fallthrough]];
case Opcode::AArch64_EOR_ZPmZ_D:
[[fallthrough]];
case Opcode::AArch64_EOR_ZPmZ_H:
[[fallthrough]];
case Opcode::AArch64_EOR_ZPmZ_S:
// Incorrect access types
operands[0].access = CS_AC_WRITE;
Expand Down
Loading

0 comments on commit 98dab74

Please sign in to comment.