feat(arch): the SVE multiple-structure loads and stores
Assisted-by: GLM 5.3 Flash
This commit is contained in:
1 parent
82dbf087a8
commit
cdc3a75c88
5 files changed
+244
-5
No files matched your search
+81
-3
@@ -52,6 +52,7 @@ func arm64ExtStatement(mnem string, ops []*ast.Operand) (extops []arch.ExtOperan
|
||||
if !arm64ExtPinned(mnem, ops) {
|
||||
return nil, false, nil
|
||||
}
|
||||
ops = arm64ExtMergeLists(ops)
|
||||
out := make([]arch.ExtOperand, 0, len(ops))
|
||||
for i, op := range ops {
|
||||
text := strings.Join(strings.Fields(op.Raw), "")
|
||||
@@ -79,10 +80,11 @@ func arm64ExtStatement(mnem string, ops []*ast.Operand) (extops []arch.ExtOperan
|
||||
out = append(out, ext)
|
||||
continue
|
||||
}
|
||||
// The gather/scatter destination list, [Z13.B]: one scalable vector
|
||||
// in brackets, its arrangement part of the instruction's identity.
|
||||
// The load and store destination list, [Z13.B] or the multi-register
|
||||
// [Z13.B, Z14.B, Z15.B] of the multiple-structure shapes, its
|
||||
// arrangement part of the instruction's identity.
|
||||
if strings.HasPrefix(text, "[") && strings.HasSuffix(text, "]") {
|
||||
if ext, ok := arm64ExtVector(strings.Trim(text, "[]")); ok {
|
||||
if ext, ok := arm64ExtVectorList(mnem, strings.Trim(text, "[]")); ok {
|
||||
out = append(out, ext)
|
||||
continue
|
||||
}
|
||||
@@ -221,6 +223,82 @@ func arm64ExtVector(text string) (arch.ExtOperand, bool) {
|
||||
return arch.ExtOperand{Kind: arch.ExtZReg, Reg: reg, Arr: arr}, true
|
||||
}
|
||||
|
||||
// arm64ExtMergeLists rejoins the bracketed vector lists the parser reads as
|
||||
// separate operands: the comma inside [Z13.B, Z14.B, Z15.B] is an operand
|
||||
// boundary to the parser, so the list arrives as two or more pieces and the
|
||||
// multiple-structure loads and stores need it whole. Pieces from an opening
|
||||
// bracket to the one carrying the closing bracket rejoin over their commas;
|
||||
// everything else passes through untouched.
|
||||
func arm64ExtMergeLists(ops []*ast.Operand) []*ast.Operand {
|
||||
closed := func(op *ast.Operand) bool {
|
||||
return strings.HasSuffix(strings.Join(strings.Fields(op.Raw), ""), "]")
|
||||
}
|
||||
merged := make([]*ast.Operand, 0, len(ops))
|
||||
for i := 0; i < len(ops); i++ {
|
||||
text := strings.Join(strings.Fields(ops[i].Raw), "")
|
||||
if !strings.HasPrefix(text, "[") || closed(ops[i]) {
|
||||
merged = append(merged, ops[i])
|
||||
continue
|
||||
}
|
||||
parts := []string{ops[i].Raw}
|
||||
kind := ops[i].Kind
|
||||
for i+1 < len(ops) {
|
||||
i++
|
||||
parts = append(parts, ops[i].Raw)
|
||||
if closed(ops[i]) {
|
||||
break
|
||||
}
|
||||
}
|
||||
merged = append(merged, &ast.Operand{Kind: kind, Raw: strings.Join(parts, ",")})
|
||||
}
|
||||
return merged
|
||||
}
|
||||
|
||||
// arm64ExtVectorList parses the bracketed vector list of the loads and
|
||||
// stores: a single register, [Z13.B], or the multi-register lists of the
|
||||
// LD2-LD4 and ST2-ST4 multiple-structure shapes, [Z13.B, Z14.B, Z15.B],
|
||||
// consecutive registers under one arrangement. The instruction's own digit
|
||||
// names the list's length where it carries one, so a two-register list
|
||||
// under ZLD3 fails here. The encoding carries the first register alone;
|
||||
// the length rides the operand for the encode side.
|
||||
func arm64ExtVectorList(mnem, body string) (arch.ExtOperand, bool) {
|
||||
regs := strings.Split(body, ",")
|
||||
first, ok := arm64ExtVector(regs[0])
|
||||
if !ok {
|
||||
return arch.ExtOperand{}, false
|
||||
}
|
||||
for i, reg := range regs[1:] {
|
||||
op, ok := arm64ExtVector(reg)
|
||||
if !ok || op.Arr != first.Arr || op.Reg != first.Reg+i+1 {
|
||||
return arch.ExtOperand{}, false
|
||||
}
|
||||
}
|
||||
if count := arm64ExtListCount(mnem); count != len(regs) {
|
||||
return arch.ExtOperand{}, false
|
||||
}
|
||||
if len(regs) > 1 {
|
||||
first.List = len(regs)
|
||||
}
|
||||
return first, true
|
||||
}
|
||||
|
||||
// arm64ExtListCount reads the list length a load or store mnemonic names,
|
||||
// the digit straight after its ZLD or ZST prefix; the loads and stores
|
||||
// without one carry a single register.
|
||||
func arm64ExtListCount(mnem string) int {
|
||||
rest, ok := strings.CutPrefix(mnem, "ZLD")
|
||||
if !ok {
|
||||
rest, ok = strings.CutPrefix(mnem, "ZST")
|
||||
}
|
||||
if !ok || rest == "" {
|
||||
return 1
|
||||
}
|
||||
if c := rest[0]; c >= '2' && c <= '4' {
|
||||
return int(c - '0')
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// arm64ExtPredicate parses a predicate register operand: P0..P15 with an
|
||||
// optional element-size suffix (P0.B) and an optional qualifier in either
|
||||
// spelling the corpus and the wired forms use, P0/M and P0.Z.
|
||||
|
||||
Reference in new issue
Block a user