diff options
Diffstat (limited to 'src/cmd/internal/obj')
| -rw-r--r-- | src/cmd/internal/obj/arm64/asm7.go | 42 | ||||
| -rw-r--r-- | src/cmd/internal/obj/arm64/list7.go | 56 | ||||
| -rw-r--r-- | src/cmd/internal/obj/util.go | 3 |
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) } |
