mirror of
https://github.com/odin-lang/Odin.git
synced 2026-08-27 07:21:31 +00:00
Support riscv _aq _rl _aqrl suffixes for mnemonics
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 { \
|
||||
|
||||
Reference in New Issue
Block a user