Skip to content

Commit

Permalink
Implement Zacas extension.
Browse files Browse the repository at this point in the history
  • Loading branch information
glg-rv committed Jun 19, 2023
1 parent bfdc0f8 commit f71bda9
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 0 deletions.
6 changes: 6 additions & 0 deletions disasm/disasm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,12 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DEFINE_XAMO(sc_d)
}

if (isa->extension_enabled(EXT_ZACAS)) {
DEFINE_XAMO(amocas_w)
DEFINE_XAMO(amocas_d)
DEFINE_XAMO(amocas_q)
}

add_insn(new disasm_insn_t("j", match_jal, mask_jal | mask_rd, {&jump_target}));
add_insn(new disasm_insn_t("jal", match_jal | match_rd_ra, mask_jal | mask_rd, {&jump_target}));
add_insn(new disasm_insn_t("jal", match_jal, mask_jal, {&xrd, &jump_target}));
Expand Down
37 changes: 37 additions & 0 deletions riscv/insns/amocas_d.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
require_extension(EXT_ZACAS);

if (xlen == 32) {
// RV32: the spec defines two 32-bit comparisons. Since we're
// loading 64-bit for memory we have to adjust for endianness.
uint64_t comp, swap, res;

require_align(insn.rd(), 2);
require_align(insn.rs2(), 2);
if (insn.rd() == 0) {
comp = 0;
} else if (MMU.is_target_big_endian()) {
comp = (uint32_t)READ_REG(insn.rd() + 1) | (RD << 32);
} else {
comp = (uint32_t)RD | (READ_REG(insn.rd() + 1) << 32);
}
if (insn.rs2() == 0) {
swap = 0;
} else if (MMU.is_target_big_endian()) {
swap = (uint32_t)READ_REG(insn.rs2() + 1) | (RS2 << 32);
} else {
swap = (uint32_t)RS2 | (READ_REG(insn.rs2() + 1) << 32);
}
res = MMU.amo_compare_and_swap<uint64_t>(RS1, comp, swap);
if (insn.rd() != 0) {
if (MMU.is_target_big_endian()) {
WRITE_REG(insn.rd() + 1, sext32((uint32_t)res));
WRITE_REG(insn.rd(), sext32(res >> 32));
} else {
WRITE_REG(insn.rd(), sext32((uint32_t)res));
WRITE_REG(insn.rd() + 1, sext32(res >> 32));
}
}
} else {
// RV64
WRITE_RD(MMU.amo_compare_and_swap<uint64_t>(RS1, RD, RS2));
}
34 changes: 34 additions & 0 deletions riscv/insns/amocas_q.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
require_extension(EXT_ZACAS);
require_rv64;
require_align(insn.rd(), 2);
require_align(insn.rs2(), 2);

// The spec defines two 64-bit comparisons. Since we're loading
// 128-bit for memory we have to adjust for endianness.

uint128_t comp, swap, res;

if (insn.rd() == 0) {
comp = 0;
} else if (MMU.is_target_big_endian()) {
comp = READ_REG(insn.rd() + 1) | ((uint128_t)RD << 64);
} else {
comp = RD | ((uint128_t)READ_REG(insn.rd() + 1) << 64);
}
if (insn.rs2() == 0) {
swap = 0;
} else if (MMU.is_target_big_endian()) {
swap = READ_REG(insn.rs2() + 1) | ((uint128_t)RS2 << 64);
} else {
swap = RS2 | ((uint128_t)READ_REG(insn.rs2() + 1) << 64);
}
res = MMU.amo_compare_and_swap<uint128_t>(RS1, comp, swap);
if (insn.rd() != 0) {
if (MMU.is_target_big_endian()) {
WRITE_REG(insn.rd(), res >> 64);
WRITE_REG(insn.rd() + 1, res);
} else {
WRITE_REG(insn.rd(), res);
WRITE_REG(insn.rd() + 1, res >> 64);
}
}
2 changes: 2 additions & 0 deletions riscv/insns/amocas_w.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require_extension(EXT_ZACAS);
WRITE_RD(sext32(MMU.amo_compare_and_swap<uint32_t>(RS1, RD, RS2)));
6 changes: 6 additions & 0 deletions riscv/isa_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
// HINTs encoded in base-ISA instructions are always present.
} else if (ext_str == "zihintntl") {
// HINTs encoded in base-ISA instructions are always present.
} else if (ext_str == "zacas") {
extension_table[EXT_ZACAS] = true;
} else if (ext_str == "zmmul") {
extension_table[EXT_ZMMUL] = true;
} else if (ext_str == "zba") {
Expand Down Expand Up @@ -301,6 +303,10 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
bad_isa_string(str, "'Zcf/Zcd/Zcb/Zcmp/Zcmt' extensions require 'Zca' extension");
}

if (extension_table[EXT_ZACAS] && !extension_table['A']) {
bad_isa_string(str, "'Zacas' extension requires 'A' extension");
}

std::string lowercase = strtolower(priv);
bool user = false, supervisor = false;

Expand Down
1 change: 1 addition & 0 deletions riscv/isa_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ typedef enum {
EXT_ZVFBFMIN,
EXT_ZVFBFWMA,
EXT_SSTC,
EXT_ZACAS,
EXT_INTERNAL_ZFH_MOVE,
NUM_ISA_EXTENSIONS
} isa_extension_t;
Expand Down
11 changes: 11 additions & 0 deletions riscv/mmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,17 @@ class mmu_t
})
}

template<typename T>
T amo_compare_and_swap(reg_t addr, T comp, T swap) {
convert_load_traps_to_store_traps({
store_slow_path(addr, sizeof(T), nullptr, {false, false, false}, false, true);
auto lhs = load<T>(addr);
if (lhs == comp)
store<T>(addr, swap);
return lhs;
})
}

void store_float128(reg_t addr, float128_t val)
{
if (unlikely(addr & (sizeof(float128_t)-1)) && !is_misaligned_enabled()) {
Expand Down
5 changes: 5 additions & 0 deletions riscv/processor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ processor_t::processor_t(const isa_parser_t *isa, const cfg_t *cfg,
fprintf(stderr, "V extension is not supported on platforms without __int128 type\n");
abort();
}

if (isa->extension_enabled(EXT_ZACAS) && isa->get_max_xlen() == 64) {
fprintf(stderr, "Zacas extension is not supported on 64-bit platforms without __int128 type\n");
abort();
}
#endif

parse_varch_string(cfg->varch());
Expand Down
6 changes: 6 additions & 0 deletions riscv/riscv.mk.in
Original file line number Diff line number Diff line change
Expand Up @@ -1335,6 +1335,11 @@ riscv_insn_ext_bf16 = \
$(riscv_insn_ext_zvfbfmin) \
$(riscv_insn_ext_zvfbfwma) \

riscv_insn_ext_zacas = \
amocas_w \
amocas_d \
$(if $(HAVE_INT128),amocas_q)

riscv_insn_list = \
$(riscv_insn_ext_a) \
$(riscv_insn_ext_c) \
Expand All @@ -1360,6 +1365,7 @@ riscv_insn_list = \
$(riscv_insn_ext_cmo) \
$(riscv_insn_ext_zicond) \
$(riscv_insn_ext_bf16) \
$(riscv_insn_ext_zacas) \

riscv_gen_srcs = $(addsuffix .cc,$(riscv_insn_list))

Expand Down

0 comments on commit f71bda9

Please sign in to comment.