mirror of
https://github.com/odin-lang/Odin.git
synced 2026-09-05 03:30:21 +00:00
Handle status snapshot style instructions
This commit is contained in:
@@ -354,6 +354,11 @@ main :: proc() {
|
||||
bool is_atomic = (cast(u16)side_effects & SideEffectFlag_ATOMIC) != 0;
|
||||
return (implicit & ClobberReg_SP) != 0 || is_atomic;
|
||||
}
|
||||
|
||||
bool is_status_snapshot() const {
|
||||
u16 flags = cast(u16)this->flags_rd_call();
|
||||
return gb_count_set_bits(flags & CLOBBER_FLAGS_COND) >= 4;
|
||||
}
|
||||
};
|
||||
|
||||
void clobber_implicit_regs(StringSet *clobber_registers_set, u16 implicit_regs) {
|
||||
|
||||
@@ -289,6 +289,19 @@ main :: proc() {
|
||||
bool is_atomic = false; // TODO(bill): Add ATOMIC flag to SideEffectFlags in the original INSTRUCTION_TABLE
|
||||
return (implicit & (ClobberReg_SP)) != 0 || is_atomic;
|
||||
}
|
||||
bool is_status_snapshot() const {
|
||||
// RiscV64 has no architectural condition flags: branches compare two GPRs
|
||||
// directly (beq/bltu/…) and slt/sltu materialise a 0/1 into a GPR, so nothing
|
||||
// ever consumes status as an implicit condition — flags_rd_call() is always
|
||||
// empty and the flag read-before-write check is already vacuous here.
|
||||
//
|
||||
// The only status that exists — the accrued fcsr exception flags (fflags[4:0])
|
||||
// and the frm rounding field — is read solely through an explicit CSR access
|
||||
// (csrr* / frflags / frrm), which pulls the register out as an opaque value
|
||||
// into a GPR. That is a snapshot by construction and must never require a
|
||||
// producer, so every status read that RV64 can express qualifies.
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void clobber_implicit_regs(StringSet *clobber_registers_set, u16 implicit_regs) {
|
||||
|
||||
@@ -153,6 +153,7 @@ main :: proc() {
|
||||
case ClobberFlag_CF: return \"c\"; case ClobberFlag_PF: return \"p\";
|
||||
case ClobberFlag_AF: return \"a\"; case ClobberFlag_ZF: return \"z\";
|
||||
case ClobberFlag_SF: return \"s\"; case ClobberFlag_OF: return \"o\";
|
||||
case ClobberFlag_DF: return \"d\"; case ClobberFlag_IF: return \"i\";
|
||||
}
|
||||
return \"?\";
|
||||
}
|
||||
@@ -363,6 +364,14 @@ main :: proc() {
|
||||
u16 implicit = cast(u16)implicit_rd | cast(u16)implicit_wr;
|
||||
return (implicit & (ClobberReg_RSP|ClobberReg_RSI|ClobberReg_RDI|ClobberReg_RBX)) != 0;
|
||||
}
|
||||
|
||||
bool is_status_snapshot() const {
|
||||
u16 flags = cast(u16)this->flags_rd_call();
|
||||
u16 const STATUS_FLAGS = ClobberFlag_CF | ClobberFlag_PF | ClobberFlag_AF |
|
||||
ClobberFlag_ZF | ClobberFlag_SF | ClobberFlag_OF;
|
||||
return ((flags & ClobberFlag_IF) != 0) ||
|
||||
(gb_count_set_bits(flags & STATUS_FLAGS) >= 4);
|
||||
}
|
||||
};
|
||||
|
||||
void clobber_implicit_regs(StringSet *clobber_registers_set, u16 implicit_regs) {
|
||||
|
||||
@@ -156,6 +156,7 @@ struct Asm_amd64 {
|
||||
case ClobberFlag_CF: return "c"; case ClobberFlag_PF: return "p";
|
||||
case ClobberFlag_AF: return "a"; case ClobberFlag_ZF: return "z";
|
||||
case ClobberFlag_SF: return "s"; case ClobberFlag_OF: return "o";
|
||||
case ClobberFlag_DF: return "d"; case ClobberFlag_IF: return "i";
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
@@ -366,6 +367,14 @@ struct Asm_amd64 {
|
||||
u16 implicit = cast(u16)implicit_rd | cast(u16)implicit_wr;
|
||||
return (implicit & (ClobberReg_RSP|ClobberReg_RSI|ClobberReg_RDI|ClobberReg_RBX)) != 0;
|
||||
}
|
||||
|
||||
bool is_status_snapshot() const {
|
||||
u16 flags = cast(u16)this->flags_rd_call();
|
||||
u16 const STATUS_FLAGS = ClobberFlag_CF | ClobberFlag_PF | ClobberFlag_AF |
|
||||
ClobberFlag_ZF | ClobberFlag_SF | ClobberFlag_OF;
|
||||
return ((flags & ClobberFlag_IF) != 0) ||
|
||||
(gb_count_set_bits(flags & STATUS_FLAGS) >= 4);
|
||||
}
|
||||
};
|
||||
|
||||
void clobber_implicit_regs(StringSet *clobber_registers_set, u16 implicit_regs) {
|
||||
|
||||
@@ -341,6 +341,11 @@ struct Asm_arm64 {
|
||||
bool is_atomic = (cast(u16)side_effects & SideEffectFlag_ATOMIC) != 0;
|
||||
return (implicit & ClobberReg_SP) != 0 || is_atomic;
|
||||
}
|
||||
|
||||
bool is_status_snapshot() const {
|
||||
u16 flags = cast(u16)this->flags_rd_call();
|
||||
return gb_count_set_bits(flags & CLOBBER_FLAGS_COND) >= 4;
|
||||
}
|
||||
};
|
||||
|
||||
void clobber_implicit_regs(StringSet *clobber_registers_set, u16 implicit_regs) {
|
||||
|
||||
@@ -237,6 +237,19 @@ struct Asm_riscv {
|
||||
bool is_atomic = false; // TODO(bill): Add ATOMIC flag to SideEffectFlags in the original INSTRUCTION_TABLE
|
||||
return (implicit & (ClobberReg_SP)) != 0 || is_atomic;
|
||||
}
|
||||
bool is_status_snapshot() const {
|
||||
// RiscV64 has no architectural condition flags: branches compare two GPRs
|
||||
// directly (beq/bltu/…) and slt/sltu materialise a 0/1 into a GPR, so nothing
|
||||
// ever consumes status as an implicit condition — flags_rd_call() is always
|
||||
// empty and the flag read-before-write check is already vacuous here.
|
||||
//
|
||||
// The only status that exists — the accrued fcsr exception flags (fflags[4:0])
|
||||
// and the frm rounding field — is read solely through an explicit CSR access
|
||||
// (csrr* / frflags / frrm), which pulls the register out as an opaque value
|
||||
// into a GPR. That is a snapshot by construction and must never require a
|
||||
// producer, so every status read that RV64 can express qualifies.
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void clobber_implicit_regs(StringSet *clobber_registers_set, u16 implicit_regs) {
|
||||
|
||||
@@ -692,7 +692,19 @@ gb_internal void check_asm_cfg_analyse(AsmCtx *asm_ctx, AsmCfg *cfg, CheckerCont
|
||||
check_asm_cfg_report_undef_reg(asm_ctx, cfg, entity, instr, f->name, bit);
|
||||
}
|
||||
|
||||
bool is_status_snapshot = false;
|
||||
if (instr->mnemonic && instr->valid_form_index >= 0) {
|
||||
auto clobber_forms = asm_ctx->clobber_forms(instr->mnemonic);
|
||||
if (clobber_forms.count > 0 && instr->valid_form_index < clobber_forms.count) {
|
||||
auto &clobber = clobber_forms[instr->valid_form_index];
|
||||
is_status_snapshot = clobber.is_status_snapshot();
|
||||
}
|
||||
}
|
||||
|
||||
u16 undef_flags = f->read_flags & ~run_flags & ~reported_flags;
|
||||
if (is_status_snapshot) {
|
||||
undef_flags = 0;
|
||||
}
|
||||
if (undef_flags != 0) {
|
||||
reported_flags |= undef_flags;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user