feat(asm): assemble static symbols and the whole go-flac AVX2 kernel byte-identically
Assisted-by: Qwen 3.8 Max Preview
This commit is contained in:
+28
-1
@@ -19,7 +19,16 @@ func Encode(mnemonic string, ops ...Operand) ([]byte, error) {
|
||||
}
|
||||
|
||||
type enc struct {
|
||||
out []byte
|
||||
out []byte
|
||||
patches []encPatch // disp32 fields awaiting static-symbol resolution
|
||||
}
|
||||
|
||||
// encPatch marks a 4-byte displacement field in enc.out that must receive the
|
||||
// RIP-relative offset of a static symbol once the file layout is settled.
|
||||
type encPatch struct {
|
||||
off int
|
||||
name string
|
||||
addend int64
|
||||
}
|
||||
|
||||
func (e *enc) encode(mnem string, ops []Operand) error {
|
||||
@@ -120,6 +129,14 @@ type instr struct {
|
||||
sib int // -1 if absent
|
||||
disp []byte
|
||||
imm []byte
|
||||
sb *sbRef // static-symbol displacement in disp, awaiting resolution
|
||||
}
|
||||
|
||||
// sbRef records that an instruction's displacement refers to a static symbol
|
||||
// rather than holding a literal value.
|
||||
type sbRef struct {
|
||||
name string
|
||||
addend int64
|
||||
}
|
||||
|
||||
func (e *enc) emit(i *instr) error {
|
||||
@@ -152,6 +169,9 @@ func (e *enc) emit(i *instr) error {
|
||||
if i.sib >= 0 {
|
||||
e.out = append(e.out, byte(i.sib))
|
||||
}
|
||||
if i.sb != nil {
|
||||
e.patches = append(e.patches, encPatch{off: len(e.out), name: i.sb.name, addend: i.sb.addend})
|
||||
}
|
||||
e.out = append(e.out, i.disp...)
|
||||
e.out = append(e.out, i.imm...)
|
||||
return nil
|
||||
@@ -199,6 +219,13 @@ func setRMReg(i *instr, regField int, rexR, regForced bool, rm Operand, opSize i
|
||||
return nil
|
||||
case Mem:
|
||||
return setMem(i, regField, r)
|
||||
case sbMem:
|
||||
// RIP-relative reference; the displacement is patched once the static
|
||||
// symbol's address is known.
|
||||
i.modrm = regField<<3 | 0x05 // mod=00, rm=101 → (RIP)+disp32
|
||||
i.disp = le32(0)
|
||||
i.sb = &sbRef{name: r.name, addend: r.addend}
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("invalid r/m operand %T", rm)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user