Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New aarch64 insn support #335

Merged
merged 20 commits into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/include/simeng/Instruction.hh
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ class Instruction {

/** Override the specified source register with a renamed physical register.
*/
virtual void renameSource(uint8_t i, Register renamed) = 0;
virtual void renameSource(uint16_t i, Register renamed) = 0;
dANW34V3R marked this conversation as resolved.
Show resolved Hide resolved

/** Override the specified destination register with a renamed physical
* register. */
virtual void renameDestination(uint8_t i, Register renamed) = 0;
virtual void renameDestination(uint16_t i, Register renamed) = 0;
dANW34V3R marked this conversation as resolved.
Show resolved Hide resolved

/** Provide a value for the operand at the specified index. */
virtual void supplyOperand(uint8_t i, const RegisterValue& value) = 0;
virtual void supplyOperand(uint16_t i, const RegisterValue& value) = 0;

/** Check whether the operand at index `i` has had a value supplied. */
virtual bool isOperandReady(int i) const = 0;
Expand Down
41 changes: 36 additions & 5 deletions src/include/simeng/arch/aarch64/Instruction.hh
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,39 @@ inline uint8_t getDataSize(cs_arm64_op op) {

// ARM64_REG_V0 -> {end} are vector registers
if (op.reg >= ARM64_REG_V0) {
// Data size for vector registers relies on opcode thus return 0
return 0;
// Data size for vector registers relies on opcode, get vector access
dANW34V3R marked this conversation as resolved.
Show resolved Hide resolved
// specifier
arm64_vas vas = op.vas;
assert(vas != ARM64_VAS_INVALID && "Invalid VAS type");
switch (vas) {
case ARM64_VAS_16B:
case ARM64_VAS_8H:
case ARM64_VAS_4S:
case ARM64_VAS_2D:
case ARM64_VAS_1Q: {
return 16;
}
case ARM64_VAS_8B:
case ARM64_VAS_4H:
case ARM64_VAS_2S:
case ARM64_VAS_1D: {
return 8;
}
case ARM64_VAS_4B:
case ARM64_VAS_2H:
case ARM64_VAS_1S: {
return 4;
}
case ARM64_VAS_1H: {
return 2;
}
case ARM64_VAS_1B: {
return 1;
}
default: {
assert(false && "Unknown VAS type");
}
}
}

// ARM64_REG_ZAB0 -> +31 are tiles of the matrix register (ZA)
Expand Down Expand Up @@ -258,14 +289,14 @@ class Instruction : public simeng::Instruction {

/** Override the specified source register with a renamed physical register.
*/
void renameSource(uint8_t i, Register renamed) override;
void renameSource(uint16_t i, Register renamed) override;

/** Override the specified destination register with a renamed physical
* register. */
void renameDestination(uint8_t i, Register renamed) override;
void renameDestination(uint16_t i, Register renamed) override;

/** Provide a value for the operand at the specified index. */
virtual void supplyOperand(uint8_t i, const RegisterValue& value) override;
virtual void supplyOperand(uint16_t i, const RegisterValue& value) override;

/** Check whether all operand values have been supplied, and the instruction
* is ready to execute. */
Expand Down
6 changes: 6 additions & 0 deletions src/include/simeng/arch/aarch64/MicroDecoder.hh
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ class MicroDecoder {
csh capstoneHandle, bool lastMicroOp = false,
int microOpIndex = 0);

/** Create an address offset uop from a base register and a register. */
Instruction createRegOffsetUop(const Architecture& architecture,
arm64_reg base, arm64_reg offset,
csh capstoneHandle, bool lastMicroOp = false,
int microOpIndex = 0);

/** Create a load uop from a destination register and a capstone memory
* operand. */
Instruction createLdrUop(const Architecture& architecture, arm64_reg dest,
Expand Down
65 changes: 65 additions & 0 deletions src/include/simeng/arch/aarch64/helpers/neon.hh
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,23 @@ class neonHelp {
return {out, 256};
}

/** Helper function for NEON instructions with the format `fabd vd.T, vn.T,
* vm.T`.
* T represents the type of operands (e.g. for vn.2d, T = double).
* I represents the number of elements in the output array to be updated (e.g.
* for vd.8b I = 8).
* Returns correctly formatted RegisterValue. */
template <typename T, int I>
static RegisterValue vecFabd(std::vector<RegisterValue>& operands) {
const T* n = operands[0].getAsVector<T>();
const T* m = operands[1].getAsVector<T>();
T out[16 / sizeof(T)] = {0};
for (int i = 0; i < I; i++) {
out[i] = std::fabs(n[i] - m[i]);
}
return {out, 256};
}

/** Helper function for NEON instructions with the format `fabs vd, vn`.
* T represents the type of operands (e.g. for vn.2d, T = double).
* I represents the number of elements in the output array to be updated (e.g.
Expand Down Expand Up @@ -690,6 +707,31 @@ class neonHelp {
return {out, 256};
}

/** Helper function for NEON instructions with the format `shrn vd, vn, #imm`.
* Ta represents the type of source operand (e.g. for vn.2d, Ta = uint64_t).
* Tb represents the type of destination operand (e.g. for vd.2s, Tb =
* uint32_t).
* I represents the number of elements in the output array to be
* updated (e.g. for vd.8b I = 8).
* Returns correctly formatted RegisterValue.
*/
template <typename Ta, typename Tb, int I>
static RegisterValue vecShrnShift_imm(
std::vector<RegisterValue>& operands,
const simeng::arch::aarch64::InstructionMetadata& metadata,
bool shrn2 = false) {
const Ta* n = operands[0].getAsVector<Ta>();

uint64_t shift = metadata.operands[2].imm;

Tb out[16 / sizeof(Tb)] = {0};
int index = shrn2 ? I : 0;
for (int i = 0; i < I; i++) {
out[index + i] = static_cast<Tb>(std::trunc(n[i] >> shift));
}
return {out, 256};
}

/** Helper function for NEON instructions with the format `sshr vd, vn, #imm`.
* T represents the type of operands (e.g. for vn.2d, T = uint64_t).
* I represents the number of elements in the output array to be updated (e.g.
Expand Down Expand Up @@ -889,6 +931,29 @@ class neonHelp {

return {out, 256};
}

/** Helper function for NEON instructions with the format `zip<1,2> vd.T,
* vn.T, vm.T`.
* T represents the type of operands (e.g. for vn.d, T = uint64_t).
* I represents the number of elements in the output array to be updated (e.g.
* for vn.8b, I = 8).
* Returns formatted Register Value. */
template <typename T, int I>
static RegisterValue vecZip(std::vector<RegisterValue>& operands,
bool isZip2) {
const T* n = operands[0].getAsVector<T>();
const T* m = operands[1].getAsVector<T>();

T out[16 / sizeof(T)] = {0};
int index = isZip2 ? (I / 2) : 0;
for (int i = 0; i < I / 2; i++) {
out[2 * i] = n[index];
out[(2 * i) + 1] = m[index];
index++;
}

return {out, 256};
}
};
} // namespace aarch64
} // namespace arch
Expand Down
45 changes: 43 additions & 2 deletions src/include/simeng/arch/aarch64/helpers/sve.hh
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,25 @@ class sveHelp {
return {out, 256};
}

/** Helper function for SVE instructions with the format `add zd, zn, #imm`.
* T represents the type of operands (e.g. for zn.d, T = uint64_t).
* Returns correctly formatted RegisterValue. */
template <typename T>
static RegisterValue sveAdd_imm(
std::vector<RegisterValue>& operands,
const simeng::arch::aarch64::InstructionMetadata& metadata,
const uint16_t VL_bits) {
const T* n = operands[0].getAsVector<T>();
const T imm = static_cast<T>(metadata.operands[2].imm);

const uint16_t partition_num = VL_bits / (sizeof(T) * 8);
T out[256 / sizeof(T)] = {0};
for (int i = 0; i < partition_num; i++) {
out[i] = n[i] + imm;
}
return {out, 256};
}

/** Helper function for SVE instructions with the format `add zdn, pg/m, zdn,
* const`.
* T represents the type of operands (e.g. for zn.d, T = uint64_t).
Expand Down Expand Up @@ -911,6 +930,25 @@ class sveHelp {
return {out, 256};
}

/** Helper function for SVE instructions with the format `<AND, EOR, ...>
* zd, zn, zm`.
* T represents the type of operands (e.g. for zn.d, T = uint64_t).
* Returns correctly formatted RegisterValue. */
template <typename T>
static RegisterValue sveLogicOpUnPredicated_3vecs(
std::vector<RegisterValue>& operands, const uint16_t VL_bits,
std::function<T(T, T)> func) {
const T* n = operands[0].getAsVector<T>();
const T* m = operands[1].getAsVector<T>();

const uint16_t partition_num = VL_bits / (sizeof(T) * 8);
T out[256 / sizeof(T)] = {0};
for (int i = 0; i < partition_num; i++) {
out[i] = func(n[i], m[i]);
}
return {out, 256};
}

/** Helper function for SVE instructions with the format `lsl sz, zn, #imm`.
* T represents the type of operands (e.g. for zn.d, T = uint64_t).
* Returns correctly formatted RegisterValue. */
Expand Down Expand Up @@ -1179,13 +1217,16 @@ class sveHelp {
template <typename T>
static std::array<uint64_t, 4> svePsel(
std::vector<RegisterValue>& operands,
const simeng::arch::aarch64::InstructionMetadata& metadata) {
const simeng::arch::aarch64::InstructionMetadata& metadata,
const uint16_t VL_bits) {
const uint64_t* pn = operands[0].getAsVector<uint64_t>();
const uint64_t* pm = operands[1].getAsVector<uint64_t>();
const uint32_t wa = operands[2].get<uint32_t>();
const uint32_t imm = metadata.operands[2].sme_index.disp;

uint32_t index = wa + imm;
const uint16_t partition_num = VL_bits / (sizeof(T) * 8);

uint32_t index = (wa + imm) % partition_num;
uint64_t shifted_active = 1ull << ((index % (64 / sizeof(T))) * sizeof(T));

std::array<uint64_t, 4> out = {0, 0, 0, 0};
Expand Down
6 changes: 3 additions & 3 deletions src/include/simeng/arch/riscv/Instruction.hh
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,14 @@ class Instruction : public simeng::Instruction {

/** Override the specified source register with a renamed physical register.
*/
void renameSource(uint8_t i, Register renamed) override;
void renameSource(uint16_t i, Register renamed) override;

/** Override the specified destination register with a renamed physical
* register. */
void renameDestination(uint8_t i, Register renamed) override;
void renameDestination(uint16_t i, Register renamed) override;

/** Provide a value for the operand at the specified index. */
virtual void supplyOperand(uint8_t i, const RegisterValue& value) override;
virtual void supplyOperand(uint16_t i, const RegisterValue& value) override;

/** Check whether all operand values have been supplied, and the instruction
* is ready to execute. */
Expand Down
6 changes: 3 additions & 3 deletions src/lib/arch/aarch64/Instruction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ bool Instruction::isOperandReady(int index) const {
return static_cast<bool>(operands[index]);
}

void Instruction::renameSource(uint8_t i, Register renamed) {
void Instruction::renameSource(uint16_t i, Register renamed) {
sourceRegisters[i] = renamed;
}
void Instruction::renameDestination(uint8_t i, Register renamed) {
void Instruction::renameDestination(uint16_t i, Register renamed) {
destinationRegisters[i] = renamed;
}

void Instruction::supplyOperand(uint8_t i, const RegisterValue& value) {
void Instruction::supplyOperand(uint16_t i, const RegisterValue& value) {
assert(!canExecute() &&
"Attempted to provide an operand to a ready-to-execute instruction");
assert(value.size() > 0 &&
Expand Down
Loading