feat(asm): byte-identical go-flac AVX2 assembly with scalar families and jump relaxation
Assisted-by: Qwen 3.8 Max Preview
This commit is contained in:
+21
-14
@@ -400,22 +400,29 @@ func parseAddress(g []token.Token) ast.Address {
|
||||
}
|
||||
|
||||
i := 0
|
||||
// Optional leading displacement before a '(' base group.
|
||||
if isSignedNumber(g, i) && i+1 < len(g) && g[i+1].Kind == token.LParen {
|
||||
neg := false
|
||||
if g[i].Kind == token.Minus {
|
||||
neg = true
|
||||
i++
|
||||
} else if g[i].Kind == token.Plus {
|
||||
i++
|
||||
// Optional leading displacement before a '(' base group. A sign pushes
|
||||
// the parenthesis one token further out: -4(DX) has it at i+2.
|
||||
if isSignedNumber(g, i) {
|
||||
paren := i + 1
|
||||
if g[i].Kind == token.Minus || g[i].Kind == token.Plus {
|
||||
paren = i + 2
|
||||
}
|
||||
if i < len(g) && g[i].Kind == token.Number {
|
||||
addr.Offset = parseInt(g[i].Text)
|
||||
addr.HasOff = true
|
||||
if neg {
|
||||
addr.Offset = -addr.Offset
|
||||
if paren < len(g) && g[paren].Kind == token.LParen {
|
||||
neg := false
|
||||
if g[i].Kind == token.Minus {
|
||||
neg = true
|
||||
i++
|
||||
} else if g[i].Kind == token.Plus {
|
||||
i++
|
||||
}
|
||||
if i < len(g) && g[i].Kind == token.Number {
|
||||
addr.Offset = parseInt(g[i].Text)
|
||||
addr.HasOff = true
|
||||
if neg {
|
||||
addr.Offset = -addr.Offset
|
||||
}
|
||||
i++
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
// First parenthesised group: the base register.
|
||||
|
||||
@@ -34,6 +34,46 @@ func texts(f *ast.File) []*ast.Text {
|
||||
return out
|
||||
}
|
||||
|
||||
// TestNegativeDisplacement is a regression test for a leading negative
|
||||
// displacement with a base and index: the sign pushed the parenthesis one
|
||||
// token further out than the lookahead expected, and the whole address used
|
||||
// to parse empty.
|
||||
func TestNegativeDisplacement(t *testing.T) {
|
||||
f, errs := Parse("neg_amd64.s", `
|
||||
#include "textflag.h"
|
||||
TEXT ·f(SB), NOSPLIT, $0
|
||||
LEAQ -4(DX)(R9*4), R9
|
||||
MOVQ +8(AX), BX
|
||||
RET
|
||||
`)
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("parse: %v", errs)
|
||||
}
|
||||
fn := texts(f)[0]
|
||||
var leaq, movq *ast.Instr
|
||||
for _, s := range fn.Body {
|
||||
if in, ok := s.(*ast.Instr); ok {
|
||||
switch in.Mnemonic.Text {
|
||||
case "LEAQ":
|
||||
leaq = in
|
||||
case "MOVQ":
|
||||
movq = in
|
||||
}
|
||||
}
|
||||
}
|
||||
if leaq == nil || movq == nil {
|
||||
t.Fatalf("instructions not parsed: leaq=%v movq=%v", leaq, movq)
|
||||
}
|
||||
a := leaq.Operands[0].Addr
|
||||
if a.Base != "DX" || a.Index != "R9" || a.Scale != 4 || a.Offset != -4 || !a.HasOff {
|
||||
t.Errorf("LEAQ addr = %+v, want -4(DX)(R9*4)", a)
|
||||
}
|
||||
b := movq.Operands[0].Addr
|
||||
if b.Base != "AX" || b.Offset != 8 || !b.HasOff {
|
||||
t.Errorf("MOVQ addr = %+v, want +8(AX)", b)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseSample(t *testing.T) {
|
||||
f := mustParse(t, "../testdata/sample_amd64.s")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user