fix(asm): encode the riscv64 FENCE predecessor and successor flags

Assisted-by: GLM 5.3
This commit is contained in:
petrbalvin committed 2026-10-07 13:51:02 +02:00
1 parent 36d1ac804a
commit e5aabf9801
1 file changed
+33
+33
View File
@@ -352,6 +352,26 @@ func riscvPadBytes(pad int) []byte {
return out return out
} }
// riscvFenceFlags carries the toolchain's sixteen FENCE flag spellings (its
// specialOperands table between SPOP_FENCE_BEGIN and SPOP_FENCE_END), each
// with the 4-bit encoding the predecessor and successor fields pack.
var riscvFenceFlags = map[string]uint32{
"W": 1, "R": 2, "RW": 3, "O": 4, "OW": 5, "OR": 6, "ORW": 7,
"I": 8, "IW": 9, "IR": 10, "IRW": 11, "IO": 12, "IOW": 13,
"IOR": 14, "IORW": 15,
}
// riscvFenceFlag resolves one FENCE flag operand (a bare name such as W or
// IORW) to its 4-bit encoding.
func riscvFenceFlag(op *ast.Operand) (uint32, bool) {
name := ""
if op.Addr.Sym != nil {
name = op.Addr.Sym.Name
}
v, ok := riscvFenceFlags[strings.ToUpper(name)]
return v, ok
}
// riscvInstrSize returns the encoded size in bytes of a RISC-V instruction. // riscvInstrSize returns the encoded size in bytes of a RISC-V instruction.
// Most instructions are 4 bytes; MOV with a large immediate and I-type // Most instructions are 4 bytes; MOV with a large immediate and I-type
// arithmetic with a large immediate expand to several (possibly compressed) // arithmetic with a large immediate expand to several (possibly compressed)
@@ -1322,6 +1342,19 @@ func encodeRISCVInstr(instr *ast.Instr, pc int, offsets map[string]int, fi riscv
if mnem == "PAUSE" { if mnem == "PAUSE" {
imm = 0x010 imm = 0x010
} }
// FENCE pred, succ spells both flags with the toolchain's sixteen
// IORW combinations, packed as pred<<4 | succ in the immediate.
if mnem == "FENCE" && len(ops) == 2 {
pred, ok := riscvFenceFlag(ops[0])
if !ok {
return nil, fmt.Errorf("FENCE: invalid predecessor operand %q", ops[0].Raw)
}
succ, ok := riscvFenceFlag(ops[1])
if !ok {
return nil, fmt.Errorf("FENCE: invalid successor operand %q", ops[1].Raw)
}
imm = int32(pred)<<4 | int32(succ)
}
word = riscvIType(enc, 0, 0, imm) word = riscvIType(enc, 0, 0, imm)
return []byte{byte(word), byte(word >> 8), byte(word >> 16), byte(word >> 24)}, nil return []byte{byte(word), byte(word >> 8), byte(word >> 16), byte(word >> 24)}, nil