Support riscv _aq _rl _aqrl suffixes for mnemonics

This commit is contained in:
gingerBill
2026-08-21 01:05:47 +01:00
parent acb6c1408f
commit d0fb380c20
6 changed files with 142 additions and 3 deletions

View File

@@ -437,6 +437,54 @@ main :: proc() {
return true;
}
enum MnemonicSuffix : u8 {
MnemonicSuffix_None = 0,
MnemonicSuffix_AQ = 1<<0, // Acquire
MnemonicSuffix_RL = 1<<1, // Release
};
bool mnemonic_accepts_suffix(u16 m) const {
auto forms = encoding_forms(m);
for (auto const &form : forms) {
for (auto const &enc : form.enc) {
if (enc == ENC_AQRL) {
return true;
}
}
}
auto clobbers = clobber_forms(m);
for (auto const &c : clobbers) {
if ((cast(u16)c.side_effects & (SideEffectFlag_ATOMIC | SideEffectFlag_RESERVATION)) != 0) {
return true;
}
}
return false;
}
Mnemonic mnemonic_lookup_ordered(String const &name, u8 *suffixes_) {
u8 suffixes = 0;
String base = {};
if (string_ends_with(name, str_lit(\"_aqrl\"))) {
suffixes = MnemonicSuffix_AQ | MnemonicSuffix_RL;
base = substring(name, 0, name.len - 5);
} else if (string_ends_with(name, str_lit(\"_aq\"))) {
suffixes = MnemonicSuffix_AQ;
base = substring(name, 0, name.len - 3);
} else if (string_ends_with(name, str_lit(\"_rl\"))) {
suffixes = MnemonicSuffix_RL;
base = substring(name, 0, name.len - 3);
} else {
return M_INVALID;
}
Mnemonic m = mnemonic_lookup(base);
if (m == M_INVALID || !mnemonic_accepts_suffix(cast(u16)m)) {
return M_INVALID;
}
if (suffixes_) *suffixes_ = suffixes;
return m;
}
Mnemonic mnemonic_lookup(String const &name) {
Mnemonic *found = string_map_get(&mnemonic_map, name);
return found ? *found : M_INVALID;

View File

@@ -480,6 +480,21 @@ main :: proc() {
return true;
}
enum MnemonicSuffix : u8 {
MnemonicSuffix_None = 0,
};
bool mnemonic_accepts_suffix(u16 m) const {
return false;
}
Mnemonic mnemonic_lookup_ordered(String const &name, u8 *suffixes_) {
// NOTE(bill): Do any instructions need a suffix idea?
return M_INVALID;
}
Mnemonic mnemonic_lookup(String const &name) {
Mnemonic *found = string_map_get(&mnemonic_map, name);
return found ? *found : M_INVALID;

View File

@@ -508,6 +508,21 @@ struct Asm_amd64 {
return true;
}
enum MnemonicSuffix : u8 {
MnemonicSuffix_None = 0,
};
bool mnemonic_accepts_suffix(u16 m) const {
return false;
}
Mnemonic mnemonic_lookup_ordered(String const &name, u8 *suffixes_) {
// NOTE(bill): Do any instructions need a suffix idea?
return M_INVALID;
}
Mnemonic mnemonic_lookup(String const &name) {
Mnemonic *found = string_map_get(&mnemonic_map, name);
return found ? *found : M_INVALID;

View File

@@ -407,6 +407,54 @@ struct Asm_riscv {
return true;
}
enum MnemonicSuffix : u8 {
MnemonicSuffix_None = 0,
MnemonicSuffix_AQ = 1<<0, // Acquire
MnemonicSuffix_RL = 1<<1, // Release
};
bool mnemonic_accepts_suffix(u16 m) const {
auto forms = encoding_forms(m);
for (auto const &form : forms) {
for (auto const &enc : form.enc) {
if (enc == ENC_AQRL) {
return true;
}
}
}
auto clobbers = clobber_forms(m);
for (auto const &c : clobbers) {
if ((cast(u16)c.side_effects & (SideEffectFlag_ATOMIC | SideEffectFlag_RESERVATION)) != 0) {
return true;
}
}
return false;
}
Mnemonic mnemonic_lookup_ordered(String const &name, u8 *suffixes_) {
u8 suffixes = 0;
String base = {};
if (string_ends_with(name, str_lit("_aqrl"))) {
suffixes = MnemonicSuffix_AQ | MnemonicSuffix_RL;
base = substring(name, 0, name.len - 5);
} else if (string_ends_with(name, str_lit("_aq"))) {
suffixes = MnemonicSuffix_AQ;
base = substring(name, 0, name.len - 3);
} else if (string_ends_with(name, str_lit("_rl"))) {
suffixes = MnemonicSuffix_RL;
base = substring(name, 0, name.len - 3);
} else {
return M_INVALID;
}
Mnemonic m = mnemonic_lookup(base);
if (m == M_INVALID || !mnemonic_accepts_suffix(cast(u16)m)) {
return M_INVALID;
}
if (suffixes_) *suffixes_ = suffixes;
return m;
}
Mnemonic mnemonic_lookup(String const &name) {
Mnemonic *found = string_map_get(&mnemonic_map, name);
return found ? *found : M_INVALID;

View File

@@ -855,7 +855,7 @@ enum CheckMnemomicResult {
};
template <typename AsmCtx>
gb_internal CheckMnemomicResult check_mnemonic_name(AsmCtx *asm_ctx, AstAsmInstruction *instr, u16 *mnemonic_) {
gb_internal CheckMnemomicResult check_mnemonic_name(AsmCtx *asm_ctx, AstAsmInstruction *instr, u16 *mnemonic_, u8 *suffix_flags_) {
Token token = instr->name->Ident.token;
GB_ASSERT_MSG(token.kind == Token_Ident || token_is_keyword(token.kind), "got %.*s of kind %.*s", LIT(token.string), LIT(token_strings[token.kind]));
String name = token.string;
@@ -875,6 +875,14 @@ gb_internal CheckMnemomicResult check_mnemonic_name(AsmCtx *asm_ctx, AstAsmInstr
return CheckMnemomic_PseudoMnemonic;
}
u8 suffix_flags = 0;
auto om = asm_ctx->mnemonic_lookup_ordered(name, &suffix_flags);
if (om) {
if (mnemonic_) *mnemonic_ = cast(u16)om;
if (suffix_flags_) *suffix_flags_ = suffix_flags;
return CheckMnemomic_Mnemonic;
}
ERROR_BLOCK();
if (instr->operands.count == 0) {
@@ -1924,8 +1932,9 @@ gb_internal void check_asm_template(AsmCtx *asm_ctx, CheckerContext *ctx, Entity
case_ast_node(instr, AsmInstruction, instruction_);
GB_ASSERT(instr->name->kind == Ast_Ident);
u16 mnemonic = 0;
CheckMnemomicResult res = check_mnemonic_name(asm_ctx, instr, &mnemonic);
u16 mnemonic = 0;
u8 suffix_flags = 0;
CheckMnemomicResult res = check_mnemonic_name(asm_ctx, instr, &mnemonic, &suffix_flags);
array_clear(&operands);
for (Ast *expr : instr->operands) {
@@ -1944,6 +1953,7 @@ gb_internal void check_asm_template(AsmCtx *asm_ctx, CheckerContext *ctx, Entity
previous_prefix = cast(u8)mnemonic;
previous_prefix_instr = instruction_;
} else if (res == CheckMnemomic_Mnemonic) {
instr->suffix_flags = suffix_flags;
check_mnemonic(asm_ctx, ctx, entity, instr, mnemonic, 0, slice_from_array(operands),
previous_prefix, previous_prefix_instr,
&asm_acc);
@@ -1953,6 +1963,8 @@ gb_internal void check_asm_template(AsmCtx *asm_ctx, CheckerContext *ctx, Entity
previous_prefix = 0;
previous_prefix_instr = nullptr;
} else if (res == CheckMnemomic_PseudoMnemonic) {
instr->suffix_flags = suffix_flags;
u16 pseudo_mnemonic = cast(u16)mnemonic;
auto alias = asm_ctx->pseudo_alias(cast(u16)pseudo_mnemonic);
u16 target_mnemonic = cast(u16)alias.target;

View File

@@ -507,6 +507,7 @@ struct AstSplitArgs {
Ast * name; \
Slice<Ast *> operands; \
u16 mnemonic; \
u8 suffix_flags; \
i32 valid_form_index; \
}) \
AST_KIND(AsmMemoryOperand, "asm memory operand", struct { \