diff options
| author | fanzha02 <fannie.zhang@arm.com> | 2018-03-08 10:33:14 +0000 |
|---|---|---|
| committer | Cherry Zhang <cherryyz@google.com> | 2018-03-19 23:45:50 +0000 |
| commit | 910c3a9dfc4ff8ea4c25d725783bce4887d790f2 (patch) | |
| tree | 19d0954999c23541b920cd0055575475051f3d46 /src/cmd/internal/obj | |
| parent | 7974f0815e071448cd429d7c30c1d6c24b04a589 (diff) | |
| download | go-910c3a9dfc4ff8ea4c25d725783bce4887d790f2.tar.xz | |
cmd/asm: add ARM64 assembler check for incorrect input
Current ARM64 assembler has no check for the invalid value of both
shift amount and post-index immediate offset of LD1/ST1. This patch
adds the check.
This patch also fixes the printing error of register number equals
to 31, which should be printed as ZR instead of R31. Test cases
are also added.
Change-Id: I476235f3ab3a3fc91fe89c5a3149a4d4529c05c7
Reviewed-on: https://go-review.googlesource.com/100255
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
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) } |
