aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj/arm64/inst.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/internal/obj/arm64/inst.go')
-rw-r--r--src/cmd/internal/obj/arm64/inst.go138
1 files changed, 136 insertions, 2 deletions
diff --git a/src/cmd/internal/obj/arm64/inst.go b/src/cmd/internal/obj/arm64/inst.go
index 28ff139d66..dd9c802aab 100644
--- a/src/cmd/internal/obj/arm64/inst.go
+++ b/src/cmd/internal/obj/arm64/inst.go
@@ -98,9 +98,19 @@ func aclass(a *obj.Addr) AClass {
if a.Reg >= REG_ARNG && a.Reg < REG_ELEM {
return AC_ARNG
}
- if a.Reg >= REG_ZARNG && a.Reg < REG_PARNGZM {
+ if a.Reg >= REG_ZARNG && a.Reg < REG_ZARNGELEM {
return AC_ARNG
}
+ if a.Reg >= REG_ZARNGELEM && a.Reg < REG_PZELEM {
+ return AC_ARNGIDX
+ }
+ if a.Reg >= REG_PZELEM && a.Reg < REG_PARNGZM {
+ if a.Reg&(1<<5) == 0 {
+ return AC_ZREGIDX
+ } else {
+ return AC_PREGIDX
+ }
+ }
if a.Reg >= REG_PARNGZM && a.Reg < REG_PARNGZM_END {
switch (a.Reg >> 5) & 15 {
case PRED_M, PRED_Z:
@@ -149,6 +159,27 @@ func addrComponent(a *obj.Addr, acl AClass, index int) uint32 {
default:
panic(fmt.Errorf("unknown elm index at %d in AClass %d", index, acl))
}
+ // AClass: AC_ARNGIDX, AC_PREGIDX, AC_ZREGIDX
+ // GNU mnemonic: <reg>.<T>[<index>]
+ // Go mnemonic:
+ // reg.T[index]
+ // Encoding:
+ // Type = TYPE_REG
+ // Reg = reg | (arrangement << 5)
+ // Index = index
+ case AC_ARNGIDX, AC_PREGIDX, AC_ZREGIDX:
+ switch index {
+ case 0:
+ return uint32(a.Reg & 31)
+ case 1:
+ // Arrangement
+ return uint32((a.Reg >> 5) & 15)
+ case 2:
+ // Index
+ return uint32(a.Index)
+ default:
+ panic(fmt.Errorf("unknown elm index at %d in AClass %d", index, acl))
+ }
// AClass: AC_SPZGREG, AC_VREG
// GNU mnemonic: <width><reg>
// Go mnemonic:
@@ -171,6 +202,96 @@ func addrComponent(a *obj.Addr, acl AClass, index int) uint32 {
panic(fmt.Errorf("unknown AClass %d", acl))
}
+var codeI1Tsz uint32 = 0xffffffff
+var codeImm2Tsz uint32 = 0xfffffffe
+
+// encodeI1Tsz is the implementation of the following encoding logic:
+// Is the immediate index, in the range 0 to one less than the number of elements in 128 bits, encoded in "i1:tsz".
+// bit range mappings:
+// i1: [20:21)
+// tsz: [16:20)
+// Note:
+//
+// arr is the arrangement.
+// This encoding is aligned to the high bit of the box, according to the spec.
+func encodeI1Tsz(v, arr uint32) (uint32, bool) {
+ switch arr {
+ case ARNG_B:
+ if v > 15 {
+ return 0, false
+ }
+ return v << 17, true
+ case ARNG_H:
+ if v > 7 {
+ return 0, false
+ }
+ return v << 18, true
+ case ARNG_S:
+ if v > 3 {
+ return 0, false
+ }
+ return v << 19, true
+ case ARNG_D:
+ if v > 1 {
+ return 0, false
+ }
+ return v << 20, true
+ case ARNG_Q:
+ if v > 0 {
+ return 0, false
+ }
+ return 0, true
+ default:
+ return 0, false
+ }
+}
+
+// encodeImm2Tsz is the implementation of the following encoding logic:
+// Is the immediate index, in the range 0 to one less than the number of elements in 512 bits, encoded in "imm2:tsz".
+// bit range mappings:
+// imm2: [22:24)
+// tsz: [16:21)
+// Note:
+//
+// arr is the arrangement.
+// This encoding is aligned to the high bit of the box, according to the spec.
+func encodeImm2Tsz(v, arr uint32) (uint32, bool) {
+ switch arr {
+ case ARNG_B:
+ if v > 63 {
+ return 0, false
+ }
+ v <<= 1
+ return (v&31)<<16 | (v>>5)<<22, true
+ case ARNG_H:
+ if v > 31 {
+ return 0, false
+ }
+ v <<= 2
+ return (v&31)<<16 | (v>>5)<<22, true
+ case ARNG_S:
+ if v > 15 {
+ return 0, false
+ }
+ v <<= 3
+ return (v&31)<<16 | (v>>5)<<22, true
+ case ARNG_D:
+ if v > 7 {
+ return 0, false
+ }
+ v <<= 4
+ return (v&31)<<16 | (v>>5)<<22, true
+ case ARNG_Q:
+ if v > 3 {
+ return 0, false
+ }
+ v <<= 5
+ return (v&31)<<16 | (v>>5)<<22, true
+ default:
+ return 0, false
+ }
+}
+
// tryEncode tries to encode p with i, it returns the encoded binary and ok signal.
func (i *instEncoder) tryEncode(p *obj.Prog) (uint32, bool) {
bin := i.fixedBits
@@ -191,7 +312,20 @@ func (i *instEncoder) tryEncode(p *obj.Prog) (uint32, bool) {
}
for i, enc := range op.elemEncoders {
val := addrComponent(addr, acl, i)
- if b, ok := enc.fn(val); ok {
+ if b, ok := enc.fn(val); ok || b != 0 {
+ if !ok {
+ switch b {
+ case codeI1Tsz:
+ b, ok = encodeI1Tsz(val, addrComponent(addr, acl, i-1))
+ case codeImm2Tsz:
+ b, ok = encodeImm2Tsz(val, addrComponent(addr, acl, i-1))
+ default:
+ panic(fmt.Errorf("unknown encoding function code %d", b))
+ }
+ }
+ if !ok {
+ return 0, false
+ }
bin |= b
if _, ok := encoded[enc.comp]; ok && b != encoded[enc.comp] {
return 0, false