mirror of
https://github.com/golang/go.git
synced 2026-06-27 03:11:23 +00:00
cmd/internal/obj, cmd/compile: refactor encoding arm64 RegisterArrangement
Refactor cmd/internal/obj/arm64 and cmd/compile to use common helper function arm64.RegisterArrangement. Change-Id: I61201c6ff31cf146e5db33294319a927509b931a Reviewed-on: https://go-review.googlesource.com/c/go/+/714321 Reviewed-by: Junyang Shao <shaojunyang@google.com> Reviewed-by: Keith Randall <khr@google.com> LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@golang.org> Auto-Submit: Keith Randall <khr@golang.org>
This commit is contained in:
parent
5e45c1df65
commit
85f838f46c
2 changed files with 102 additions and 81 deletions
|
|
@ -162,6 +162,38 @@ func genIndexedOperand(op ssa.Op, base, idx int16) obj.Addr {
|
|||
return mop
|
||||
}
|
||||
|
||||
// simdRegArng encodes ssa value's register with specified simd arrangement
|
||||
func simdRegArng(reg int16, arng int16) int16 {
|
||||
if reg < arm64.REG_F0 || arm64.REG_F31 < reg {
|
||||
base.Fatalf("expected fp register: r%d", reg)
|
||||
}
|
||||
var err error
|
||||
if reg, err = arm64.RegisterArrangement(reg, arng, false); err != nil {
|
||||
base.Fatalf("bad simd register arrangement: %v", err)
|
||||
}
|
||||
return reg
|
||||
}
|
||||
|
||||
// simdV11 generates element-wise unary vector operations, e.g. VCNT V1.B8, V0.B8
|
||||
func simdV11(s *ssagen.State, v *ssa.Value, arrangement int16) *obj.Prog {
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = simdRegArng(v.Args[0].Reg(), arrangement)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = simdRegArng(v.Reg(), arrangement)
|
||||
return p
|
||||
}
|
||||
|
||||
// simdV11Scalar generates vector-to-scalar reduction operations, e.g. VUADDLV V1.B8, V0
|
||||
func simdV11Scalar(s *ssagen.State, v *ssa.Value, arrangement int16) *obj.Prog {
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = simdRegArng(v.Args[0].Reg(), arrangement)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = v.Reg() - arm64.REG_F0 + arm64.REG_V0
|
||||
return p
|
||||
}
|
||||
|
||||
func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
||||
switch v.Op {
|
||||
case ssa.OpCopy, ssa.OpARM64MOVDreg:
|
||||
|
|
@ -1018,17 +1050,9 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
|||
case ssa.OpARM64LoweredRound32F, ssa.OpARM64LoweredRound64F:
|
||||
// input is already rounded
|
||||
case ssa.OpARM64VCNT:
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = (v.Args[0].Reg()-arm64.REG_F0)&31 + arm64.REG_ARNG + ((arm64.ARNG_8B & 15) << 5)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = (v.Reg()-arm64.REG_F0)&31 + arm64.REG_ARNG + ((arm64.ARNG_8B & 15) << 5)
|
||||
simdV11(s, v, arm64.ARNG_8B)
|
||||
case ssa.OpARM64VUADDLV:
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = (v.Args[0].Reg()-arm64.REG_F0)&31 + arm64.REG_ARNG + ((arm64.ARNG_8B & 15) << 5)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = v.Reg() - arm64.REG_F0 + arm64.REG_V0
|
||||
simdV11Scalar(s, v, arm64.ARNG_8B)
|
||||
case ssa.OpARM64CSEL, ssa.OpARM64CSEL0:
|
||||
r1 := int16(arm64.REGZERO)
|
||||
if v.Op != ssa.OpARM64CSEL0 {
|
||||
|
|
|
|||
|
|
@ -8555,85 +8555,82 @@ func EncodeRegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount,
|
|||
}
|
||||
a.Reg = REG_PARNGZM + (reg & 31) + int16((arng&15)<<5)
|
||||
} else if reg <= REG_V31 && reg >= REG_V0 {
|
||||
switch ext {
|
||||
case "B8":
|
||||
if isIndex {
|
||||
return errors.New("invalid register extension")
|
||||
}
|
||||
a.Reg = REG_ARNG + (reg & 31) + ((ARNG_8B & 15) << 5)
|
||||
case "B16":
|
||||
if isIndex {
|
||||
return errors.New("invalid register extension")
|
||||
}
|
||||
a.Reg = REG_ARNG + (reg & 31) + ((ARNG_16B & 15) << 5)
|
||||
case "H4":
|
||||
if isIndex {
|
||||
return errors.New("invalid register extension")
|
||||
}
|
||||
a.Reg = REG_ARNG + (reg & 31) + ((ARNG_4H & 15) << 5)
|
||||
case "H8":
|
||||
if isIndex {
|
||||
return errors.New("invalid register extension")
|
||||
}
|
||||
a.Reg = REG_ARNG + (reg & 31) + ((ARNG_8H & 15) << 5)
|
||||
case "S2":
|
||||
if isIndex {
|
||||
return errors.New("invalid register extension")
|
||||
}
|
||||
a.Reg = REG_ARNG + (reg & 31) + ((ARNG_2S & 15) << 5)
|
||||
case "S4":
|
||||
if isIndex {
|
||||
return errors.New("invalid register extension")
|
||||
}
|
||||
a.Reg = REG_ARNG + (reg & 31) + ((ARNG_4S & 15) << 5)
|
||||
case "D1":
|
||||
if isIndex {
|
||||
return errors.New("invalid register extension")
|
||||
}
|
||||
a.Reg = REG_ARNG + (reg & 31) + ((ARNG_1D & 15) << 5)
|
||||
case "D2":
|
||||
if isIndex {
|
||||
return errors.New("invalid register extension")
|
||||
}
|
||||
a.Reg = REG_ARNG + (reg & 31) + ((ARNG_2D & 15) << 5)
|
||||
case "Q1":
|
||||
if isIndex {
|
||||
return errors.New("invalid register extension")
|
||||
}
|
||||
a.Reg = REG_ARNG + (reg & 31) + ((ARNG_1Q & 15) << 5)
|
||||
case "B":
|
||||
if !isIndex {
|
||||
return nil
|
||||
}
|
||||
a.Reg = REG_ELEM + (reg & 31) + ((ARNG_B & 15) << 5)
|
||||
a.Index = num
|
||||
case "H":
|
||||
if !isIndex {
|
||||
return nil
|
||||
}
|
||||
a.Reg = REG_ELEM + (reg & 31) + ((ARNG_H & 15) << 5)
|
||||
a.Index = num
|
||||
case "S":
|
||||
if !isIndex {
|
||||
return nil
|
||||
}
|
||||
a.Reg = REG_ELEM + (reg & 31) + ((ARNG_S & 15) << 5)
|
||||
a.Index = num
|
||||
case "D":
|
||||
if !isIndex {
|
||||
return nil
|
||||
}
|
||||
a.Reg = REG_ELEM + (reg & 31) + ((ARNG_D & 15) << 5)
|
||||
a.Index = num
|
||||
default:
|
||||
arng, elem := readArrangement(ext)
|
||||
if arng == -1 {
|
||||
return errors.New("unsupported simd register extension type: " + ext)
|
||||
}
|
||||
if elem && !isIndex {
|
||||
return nil
|
||||
}
|
||||
var err error
|
||||
if reg, err = RegisterArrangement(reg, arng, isIndex); err != nil {
|
||||
return err
|
||||
}
|
||||
a.Reg = reg
|
||||
if isIndex {
|
||||
a.Index = num
|
||||
}
|
||||
} else {
|
||||
return errors.New("invalid register and extension combination")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// readArrangement returns arrangement constant (or -1 for unknown arrangement)
|
||||
// and a boolean flag specifying whether it refers to a vector element.
|
||||
func readArrangement(name string) (arng int16, elem bool) {
|
||||
switch name {
|
||||
case "B8":
|
||||
return ARNG_8B, false
|
||||
case "B16":
|
||||
return ARNG_16B, false
|
||||
case "H4":
|
||||
return ARNG_4H, false
|
||||
case "H8":
|
||||
return ARNG_8H, false
|
||||
case "S2":
|
||||
return ARNG_2S, false
|
||||
case "S4":
|
||||
return ARNG_4S, false
|
||||
case "D1":
|
||||
return ARNG_1D, false
|
||||
case "D2":
|
||||
return ARNG_2D, false
|
||||
case "B":
|
||||
return ARNG_B, true
|
||||
case "H":
|
||||
return ARNG_H, true
|
||||
case "S":
|
||||
return ARNG_S, true
|
||||
case "D":
|
||||
return ARNG_D, true
|
||||
case "Q1":
|
||||
return ARNG_1Q, false
|
||||
default:
|
||||
return -1, false
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterArrangement encodes specified simd register number and arrangement.
|
||||
func RegisterArrangement(reg int16, arng int16, isIndex bool) (int16, error) {
|
||||
arng &= 15
|
||||
arrangement := arng << 5
|
||||
switch arng {
|
||||
case ARNG_B, ARNG_H, ARNG_S, ARNG_D:
|
||||
if !isIndex {
|
||||
return reg, nil
|
||||
}
|
||||
return REG_ELEM + (reg & 31) + arrangement, nil
|
||||
case ARNG_16B, ARNG_8H, ARNG_4S, ARNG_2D,
|
||||
ARNG_8B, ARNG_4H, ARNG_2S, ARNG_1D, ARNG_1Q:
|
||||
if isIndex {
|
||||
return 0, errors.New("invalid register extension")
|
||||
}
|
||||
return REG_ARNG + (reg & 31) + arrangement, nil
|
||||
}
|
||||
return 0, errors.New("unsupported simd register arrangement: " + fmt.Sprint(arng))
|
||||
}
|
||||
|
||||
// RegisterListOffset generates offset encoding according to AArch64 specification.
|
||||
func RegisterListOffset(firstReg, regCnt int, arrangement int64, scale int16) (int64, error) {
|
||||
offset := int64(firstReg)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue