aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/internal/obj')
-rw-r--r--src/cmd/internal/obj/arm64/asm7.go42
-rw-r--r--src/cmd/internal/obj/arm64/list7.go56
-rw-r--r--src/cmd/internal/obj/util.go3
3 files changed, 76 insertions, 25 deletions
diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go
index 3b7ad24493..7b940dd58c 100644
--- a/src/cmd/internal/obj/arm64/asm7.go
+++ b/src/cmd/internal/obj/arm64/asm7.go
@@ -2227,6 +2227,41 @@ func (c *ctxt7) checkindex(p *obj.Prog, index, maxindex int) {
}
}
+/* checkoffset checks whether the immediate offset is valid for VLD1.P and VST1.P*/
+func (c *ctxt7) checkoffset(p *obj.Prog, as obj.As) {
+ var offset, list, n int64
+ switch as {
+ case AVLD1:
+ offset = p.From.Offset
+ list = p.To.Offset
+ case AVST1:
+ offset = p.To.Offset
+ list = p.From.Offset
+ default:
+ c.ctxt.Diag("invalid operation on op %v", p.As)
+ }
+ opcode := (list >> 12) & 15
+ q := (list >> 30) & 1
+ if offset == 0 {
+ return
+ }
+ switch opcode {
+ case 0x7:
+ n = 1 // one register
+ case 0xa:
+ n = 2 // two registers
+ case 0x6:
+ n = 3 // three registers
+ case 0x2:
+ n = 4 // four registers
+ default:
+ c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
+ }
+ if !(q == 0 && offset == n*8) && !(q == 1 && offset == n*16) {
+ c.ctxt.Diag("invalid post-increment offset: %v", p)
+ }
+}
+
func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 := uint32(0)
o2 := uint32(0)
@@ -2278,6 +2313,11 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
case 3: /* op R<<n[,R],R (shifted register) */
o1 = c.oprrr(p, p.As)
+ amount := (p.From.Offset >> 10) & 63
+ is64bit := o1 & (1 << 31)
+ if is64bit == 0 && amount >= 32 {
+ c.ctxt.Diag("shift amount out of range 0 to 31: %v", p)
+ }
o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
rt := int(p.To.Reg)
if p.To.Type == obj.TYPE_NONE {
@@ -3634,6 +3674,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 |= 1 << 23
if p.From.Index == 0 {
// immediate offset variant
+ c.checkoffset(p, p.As)
o1 |= 0x1f << 16
} else {
// register offset variant
@@ -3722,6 +3763,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 |= 1 << 23
if p.To.Index == 0 {
// immediate offset variant
+ c.checkoffset(p, p.As)
o1 |= 0x1f << 16
} else {
// register offset variant
diff --git a/src/cmd/internal/obj/arm64/list7.go b/src/cmd/internal/obj/arm64/list7.go
index 37c61d2255..266e2baaee 100644
--- a/src/cmd/internal/obj/arm64/list7.go
+++ b/src/cmd/internal/obj/arm64/list7.go
@@ -92,6 +92,7 @@ func arrange(a int) string {
}
func rconv(r int) string {
+ ext := (r >> 5) & 7
if r == REGG {
return "g"
}
@@ -173,52 +174,52 @@ func rconv(r int) string {
case r == REG_PSTL3STRM:
return "PSTL3STRM"
case REG_UXTB <= r && r < REG_UXTH:
- if (r>>5)&7 != 0 {
- return fmt.Sprintf("R%d.UXTB<<%d", r&31, (r>>5)&7)
+ if ext != 0 {
+ return fmt.Sprintf("%s.UXTB<<%d", regname(r), ext)
} else {
- return fmt.Sprintf("R%d.UXTB", r&31)
+ return fmt.Sprintf("%s.UXTB", regname(r))
}
case REG_UXTH <= r && r < REG_UXTW:
- if (r>>5)&7 != 0 {
- return fmt.Sprintf("R%d.UXTH<<%d", r&31, (r>>5)&7)
+ if ext != 0 {
+ return fmt.Sprintf("%s.UXTH<<%d", regname(r), ext)
} else {
- return fmt.Sprintf("R%d.UXTH", r&31)
+ return fmt.Sprintf("%s.UXTH", regname(r))
}
case REG_UXTW <= r && r < REG_UXTX:
- if (r>>5)&7 != 0 {
- return fmt.Sprintf("R%d.UXTW<<%d", r&31, (r>>5)&7)
+ if ext != 0 {
+ return fmt.Sprintf("%s.UXTW<<%d", regname(r), ext)
} else {
- return fmt.Sprintf("R%d.UXTW", r&31)
+ return fmt.Sprintf("%s.UXTW", regname(r))
}
case REG_UXTX <= r && r < REG_SXTB:
- if (r>>5)&7 != 0 {
- return fmt.Sprintf("R%d.UXTX<<%d", r&31, (r>>5)&7)
+ if ext != 0 {
+ return fmt.Sprintf("%s.UXTX<<%d", regname(r), ext)
} else {
- return fmt.Sprintf("R%d.UXTX", r&31)
+ return fmt.Sprintf("%s.UXTX", regname(r))
}
case REG_SXTB <= r && r < REG_SXTH:
- if (r>>5)&7 != 0 {
- return fmt.Sprintf("R%d.SXTB<<%d", r&31, (r>>5)&7)
+ if ext != 0 {
+ return fmt.Sprintf("%s.SXTB<<%d", regname(r), ext)
} else {
- return fmt.Sprintf("R%d.SXTB", r&31)
+ return fmt.Sprintf("%s.SXTB", regname(r))
}
case REG_SXTH <= r && r < REG_SXTW:
- if (r>>5)&7 != 0 {
- return fmt.Sprintf("R%d.SXTH<<%d", r&31, (r>>5)&7)
+ if ext != 0 {
+ return fmt.Sprintf("%s.SXTH<<%d", regname(r), ext)
} else {
- return fmt.Sprintf("R%d.SXTH", r&31)
+ return fmt.Sprintf("%s.SXTH", regname(r))
}
case REG_SXTW <= r && r < REG_SXTX:
- if (r>>5)&7 != 0 {
- return fmt.Sprintf("R%d.SXTW<<%d", r&31, (r>>5)&7)
+ if ext != 0 {
+ return fmt.Sprintf("%s.SXTW<<%d", regname(r), ext)
} else {
- return fmt.Sprintf("R%d.SXTW", r&31)
+ return fmt.Sprintf("%s.SXTW", regname(r))
}
case REG_SXTX <= r && r < REG_SPECIAL:
- if (r>>5)&7 != 0 {
- return fmt.Sprintf("R%d.SXTX<<%d", r&31, (r>>5)&7)
+ if ext != 0 {
+ return fmt.Sprintf("%s.SXTX<<%d", regname(r), ext)
} else {
- return fmt.Sprintf("R%d.SXTX", r&31)
+ return fmt.Sprintf("%s.SXTX", regname(r))
}
case REG_ARNG <= r && r < REG_ELEM:
return fmt.Sprintf("V%d.%s", r&31, arrange((r>>5)&15))
@@ -291,3 +292,10 @@ func rlconv(list int64) string {
str += "]"
return str
}
+
+func regname(r int) string {
+ if r&31 == 31 {
+ return "ZR"
+ }
+ return fmt.Sprintf("R%d", r&31)
+}
diff --git a/src/cmd/internal/obj/util.go b/src/cmd/internal/obj/util.go
index 245e9e9e9b..9b25231bb4 100644
--- a/src/cmd/internal/obj/util.go
+++ b/src/cmd/internal/obj/util.go
@@ -263,7 +263,8 @@ func Dconv(p *Prog, a *Addr) string {
}
case "arm64":
op := ops[((v>>22)&3)<<1:]
- str = fmt.Sprintf("R%d%c%c%d", (v>>16)&31, op[0], op[1], (v>>10)&63)
+ r := (v >> 16) & 31
+ str = fmt.Sprintf("%s%c%c%d", Rconv(r+RBaseARM64), op[0], op[1], (v>>10)&63)
default:
panic("TYPE_SHIFT is not supported on " + objabi.GOARCH)
}