diff --git a/core/rexcode/isa/riscv/tablegen/cpp-compiler/cpp-gen.odin b/core/rexcode/isa/riscv/tablegen/cpp-compiler/cpp-gen.odin index 3aba6c12b..8bc1026b3 100644 --- a/core/rexcode/isa/riscv/tablegen/cpp-compiler/cpp-gen.odin +++ b/core/rexcode/isa/riscv/tablegen/cpp-compiler/cpp-gen.odin @@ -260,8 +260,8 @@ main :: proc() { AliasSrc_ARG0, // user's 1st operand AliasSrc_ARG1, // user's 2nd operand AliasSrc_ARG2, // user's 3rd operand - AliasSrc_X0, // hardwired zero (x0) - AliasSrc_X1, // link register (ra / x1) + AliasSrc_ZERO, // hardwired zero (x0) + AliasSrc_LINK, // link register (ra / x1) AliasSrc_LIT, // the `lit` field below (immediate literal) AliasSrc_CSR_LIT, // the `csr` field below (fixed 12-bit CSR address) }; @@ -425,7 +425,7 @@ main :: proc() { string_map_set(&mnemonic_map, mnemonic_strings[m], cast(Mnemonic)m); } - string_map_init(&mnemonic_map, PSEUDO_MNEMONIC_COUNT*2); + string_map_init(&pseudo_mnemonic_map, PSEUDO_MNEMONIC_COUNT*2); for (u16 m = PM_INVALID+1; m < PSEUDO_MNEMONIC_COUNT; m++) { string_map_set(&pseudo_mnemonic_map, pseudo_mnemonic_strings[m], cast(PseudoMnemonic)m); } @@ -484,6 +484,10 @@ main :: proc() { } return 0; } + + bool integer_reg_width_is_exact() const { + return false; + } """) strings.write_string(&sb, "\n\n") diff --git a/core/rexcode/isa/x86/tablegen/cpp-compiler/cpp-gen.odin b/core/rexcode/isa/x86/tablegen/cpp-compiler/cpp-gen.odin index 56f505d4b..b665d97dd 100644 --- a/core/rexcode/isa/x86/tablegen/cpp-compiler/cpp-gen.odin +++ b/core/rexcode/isa/x86/tablegen/cpp-compiler/cpp-gen.odin @@ -341,7 +341,13 @@ main :: proc() { strings.write_string(&sb, "\n"); strings.write_string(&sb, """ enum AliasSrc : u8 { - AliasSrc_NONE, // slot unused + AliasSrc_NONE, // slot unused + AliasSrc_ARG0, // user's 1st operand + AliasSrc_ARG1, // user's 2nd operand + AliasSrc_ARG2, // user's 3rd operand + AliasSrc_ZERO, // hardwired zero + AliasSrc_LINK, // link register + AliasSrc_LIT, }; struct PseudoAlias { @@ -520,6 +526,10 @@ main :: proc() { } return 0; } + + bool integer_reg_width_is_exact() const { + return true; + } """) strings.write_string(&sb, "\n\n") diff --git a/src/asm_tables_amd64.cpp b/src/asm_tables_amd64.cpp index 609d87723..c2f013049 100644 --- a/src/asm_tables_amd64.cpp +++ b/src/asm_tables_amd64.cpp @@ -555,6 +555,10 @@ struct Asm_amd64 { return 0; } + bool integer_reg_width_is_exact() const { + return true; + } + AsmOperandKind kind_from_operand_type(OperandType type) const { switch (type) { case OP_R8: case OP_R16: case OP_R32: case OP_R64: diff --git a/src/asm_tables_riscv.cpp b/src/asm_tables_riscv.cpp index 550429635..e5045f622 100644 --- a/src/asm_tables_riscv.cpp +++ b/src/asm_tables_riscv.cpp @@ -455,6 +455,10 @@ struct Asm_riscv { return 0; } + bool integer_reg_width_is_exact() const { + return false; + } + AsmOperandKind kind_from_operand_type(OperandType type) const { switch (type) { case OP_NONE: diff --git a/src/check_asm.cpp b/src/check_asm.cpp index 584429b9c..74c4b07bb 100644 --- a/src/check_asm.cpp +++ b/src/check_asm.cpp @@ -312,15 +312,21 @@ gb_internal bool check_asm_operand_size_class(AsmCtx *asm_ctx, typename AsmCtx:: // Width check. if (want_w != 0 && got_w != 0) { if (want_class == AsmRegClass_Vector && !is_memory) { - // A scalar float uses only the low lane, so it is valid in any vector - // register slot as long as it fits; a #simd vector must match exactly. bool width_ok = (got_class == AsmRegClass_Float) ? (got_w <= want_w) : (got_w == want_w); if (!width_ok) { if (mismatch_) *mismatch_ = AsmMismatch_Size; return false; } + } else if (want_class == AsmRegClass_Integer && !is_memory && + !asm_ctx->integer_reg_width_is_exact()) { + // NOTE(bill): architectures such as RISC-V have registers which are + // always the architecture width + if (got_w > want_w) { + if (mismatch_) *mismatch_ = AsmMismatch_Size; + return false; + } } else { - // Integer/mask registers, and all memory operands: exact width. + // Integer/mask registers on exact-width targets, and all memory operands. if (want_w != got_w) { if (mismatch_) *mismatch_ = AsmMismatch_Size; return false; @@ -912,8 +918,9 @@ struct AsmMnemonicAccumulator { u16 explicitly_produced_regs; u16 stale_outputs; - // #align_stack relevance: any call/branch (CONTROL) or memory effect that could - // require the stack to be realigned. If none occurred, #align_stack is redundant. + // Related to #align_stack + // any call/branch (CONTROL) or memory effect that could require the stack + // to be realigned. If none occurred, #align_stack is redundant. bool saw_call_or_mem; }; @@ -990,6 +997,20 @@ gb_internal void check_mnemonic(AsmCtx *asm_ctx, CheckerContext *ctx, Entity *tm } + auto operand_slot_type = [&](typename AsmCtx::Encoding const &form, int user_index) -> typename AsmCtx::OperandType { + int raw_slot = -1; + if (is_pseudo) { + raw_slot = user_operand_target_index(user_index); + } else { + raw_slot = asm_ctx->form_explicit_slot(form, user_index); + } + if (0 <= raw_slot && raw_slot < cast(int)gb_count_of(form.ops)) { + return form.ops[raw_slot]; + } + return asm_ctx->OP_NONE; + }; + + auto valid_spots = slice_make(heap_allocator(), max_count); defer (slice_free(&valid_spots, heap_allocator())); @@ -1025,8 +1046,7 @@ gb_internal void check_mnemonic(AsmCtx *asm_ctx, CheckerContext *ctx, Entity *tm int width_pref = 0; for_array(i, operands) { - int slot = asm_ctx->form_explicit_slot(form, cast(int)i); - auto type = (slot >= 0) ? form.ops[slot] : asm_ctx->OP_NONE; + auto type = operand_slot_type(form, cast(int)i); Operand const *operand = &operands[i]; AsmOperandKind dst = asm_ctx->kind_from_operand_type(type); AsmOperandKind src = determine_asm_operand_kind(operand); @@ -1248,9 +1268,7 @@ gb_internal void check_mnemonic(AsmCtx *asm_ctx, CheckerContext *ctx, Entity *tm if (best_form >= 0) { auto &form = forms[best_form]; for_array(i, operands) { - int tei = user_operand_target_index(cast(int)i); - int slot = (tei >= 0) ? asm_ctx->form_explicit_slot(form, tei) : -1; - auto type = (slot >= 0) ? form.ops[slot] : asm_ctx->OP_NONE; + auto type = operand_slot_type(form, cast(int)i); AsmOperandKind dst = asm_ctx->kind_from_operand_type(type); AsmOperandKind src = determine_asm_operand_kind(&operands[i]); possible_kinds[i] = dst;