fix(asm): encode the riscv64 FENCE predecessor and successor flags
Assisted-by: GLM 5.3
This commit is contained in:
1 parent
36d1ac804a
commit
e5aabf9801
1 file changed
+33
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user