aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj
diff options
context:
space:
mode:
authorVasily Leonenko <vasiliy.leonenko@gmail.com>2025-09-06 23:03:16 +0300
committerCherry Mui <cherryyz@google.com>2025-10-15 17:35:29 -0700
commit45eee553e29770a264c378bccbb80c44807609f4 (patch)
tree9e849dca72a08e78bb6f7b885f0e22d9f64b0b72 /src/cmd/internal/obj
parent27f9a6705c700d9075d4651cf9cff9cabbe4a47e (diff)
downloadgo-45eee553e29770a264c378bccbb80c44807609f4.tar.xz
cmd/internal/obj: move ARM64RegisterExtension from cmd/asm/internal/arch
Change-Id: Iab41674953655efa7be3d306dfb3f5be486be501 Reviewed-on: https://go-review.googlesource.com/c/go/+/701455 Reviewed-by: Cherry Mui <cherryyz@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@google.com>
Diffstat (limited to 'src/cmd/internal/obj')
-rw-r--r--src/cmd/internal/obj/arm64/asm7.go144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go
index cfb70cf08a..3cb4be436b 100644
--- a/src/cmd/internal/obj/arm64/asm7.go
+++ b/src/cmd/internal/obj/arm64/asm7.go
@@ -34,6 +34,7 @@ import (
"cmd/internal/obj"
"cmd/internal/objabi"
"encoding/binary"
+ "errors"
"fmt"
"log"
"math"
@@ -7855,3 +7856,146 @@ func (c *ctxt7) encRegShiftOrExt(p *obj.Prog, a *obj.Addr, r int16) uint32 {
func pack(q uint32, arngA, arngB uint8) uint32 {
return uint32(q)<<16 | uint32(arngA)<<8 | uint32(arngB)
}
+
+// ARM64RegisterExtension constructs an ARM64 register with extension or arrangement.
+func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, isIndex bool) error {
+ Rnum := (reg & 31) + int16(num<<5)
+ if isAmount {
+ if num < 0 || num > 7 {
+ return errors.New("index shift amount is out of range")
+ }
+ }
+ if reg <= REG_R31 && reg >= REG_R0 {
+ if !isAmount {
+ return errors.New("invalid register extension")
+ }
+ switch ext {
+ case "UXTB":
+ if a.Type == obj.TYPE_MEM {
+ return errors.New("invalid shift for the register offset addressing mode")
+ }
+ a.Reg = REG_UXTB + Rnum
+ case "UXTH":
+ if a.Type == obj.TYPE_MEM {
+ return errors.New("invalid shift for the register offset addressing mode")
+ }
+ a.Reg = REG_UXTH + Rnum
+ case "UXTW":
+ // effective address of memory is a base register value and an offset register value.
+ if a.Type == obj.TYPE_MEM {
+ a.Index = REG_UXTW + Rnum
+ } else {
+ a.Reg = REG_UXTW + Rnum
+ }
+ case "UXTX":
+ if a.Type == obj.TYPE_MEM {
+ return errors.New("invalid shift for the register offset addressing mode")
+ }
+ a.Reg = REG_UXTX + Rnum
+ case "SXTB":
+ if a.Type == obj.TYPE_MEM {
+ return errors.New("invalid shift for the register offset addressing mode")
+ }
+ a.Reg = REG_SXTB + Rnum
+ case "SXTH":
+ if a.Type == obj.TYPE_MEM {
+ return errors.New("invalid shift for the register offset addressing mode")
+ }
+ a.Reg = REG_SXTH + Rnum
+ case "SXTW":
+ if a.Type == obj.TYPE_MEM {
+ a.Index = REG_SXTW + Rnum
+ } else {
+ a.Reg = REG_SXTW + Rnum
+ }
+ case "SXTX":
+ if a.Type == obj.TYPE_MEM {
+ a.Index = REG_SXTX + Rnum
+ } else {
+ a.Reg = REG_SXTX + Rnum
+ }
+ case "LSL":
+ a.Index = REG_LSL + Rnum
+ default:
+ return errors.New("unsupported general register extension type: " + ext)
+
+ }
+ } 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:
+ return errors.New("unsupported simd register extension type: " + ext)
+ }
+ } else {
+ return errors.New("invalid register and extension combination")
+ }
+ return nil
+}