arm/armasm: rename VLDR/VSTR in plan9 syntax
Some load/store instructions are renamed in plan9 syntax, such as
LDR -> MOVW
STR -> MOVW
LDRB -> MOVBU
LDRSB -> MOVBS
STRB -> MOVB
LDRH -> MOVHU
LDRSH -> MOVSH
STRH -> MOVH
And VLDR/VSTR also need to be renamed.
VLDR.F32 -> MOVF (load from memory to single FP register)
VLDR.F64 -> MOVD (load from memory to double FP register)
VSTR.F32 -> MOVF (store single FP register to memory)
VSTR.F64 -> MOVD (store double FP register to memory)
This patch fixes this issue and adds corresponding tests.
fixes golang/go#20897
Change-Id: I03aaad6379fa6f7c9b808d6a4795a06299fb7a18
Reviewed-on: https://go-review.googlesource.com/47360
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/arm/armasm/plan9x.go b/arm/armasm/plan9x.go
index cbae803..321b081 100644
--- a/arm/armasm/plan9x.go
+++ b/arm/armasm/plan9x.go
@@ -9,6 +9,7 @@
"encoding/binary"
"fmt"
"io"
+ "math"
"strings"
)
@@ -37,7 +38,7 @@
op := inst.Op.String()
switch inst.Op &^ 15 {
- case LDR_EQ, LDRB_EQ, LDRH_EQ, LDRSB_EQ, LDRSH_EQ:
+ case LDR_EQ, LDRB_EQ, LDRH_EQ, LDRSB_EQ, LDRSH_EQ, VLDR_EQ:
// Check for RET
reg, _ := inst.Args[0].(Reg)
mem, _ := inst.Args[1].(Mem)
@@ -48,7 +49,7 @@
// Check for PC-relative load.
if mem.Base == PC && mem.Sign == 0 && mem.Mode == AddrOffset && text != nil {
addr := uint32(pc) + 8 + uint32(mem.Offset)
- buf := make([]byte, 4)
+ buf := make([]byte, 8)
switch inst.Op &^ 15 {
case LDRB_EQ, LDRSB_EQ:
if _, err := text.ReadAt(buf[:1], int64(addr)); err != nil {
@@ -63,7 +64,7 @@
args[1] = fmt.Sprintf("$%#x", binary.LittleEndian.Uint16(buf))
case LDR_EQ:
- if _, err := text.ReadAt(buf, int64(addr)); err != nil {
+ if _, err := text.ReadAt(buf[:4], int64(addr)); err != nil {
break
}
x := binary.LittleEndian.Uint32(buf)
@@ -72,6 +73,22 @@
} else {
args[1] = fmt.Sprintf("$%#x", x)
}
+
+ case VLDR_EQ:
+ switch {
+ case strings.HasPrefix(args[0], "D"): // VLDR.F64
+ if _, err := text.ReadAt(buf, int64(addr)); err != nil {
+ break
+ }
+ args[1] = fmt.Sprintf("$%f", math.Float64frombits(binary.LittleEndian.Uint64(buf)))
+ case strings.HasPrefix(args[0], "S"): // VLDR.F32
+ if _, err := text.ReadAt(buf[:4], int64(addr)); err != nil {
+ break
+ }
+ args[1] = fmt.Sprintf("$%f", math.Float32frombits(binary.LittleEndian.Uint32(buf)))
+ default:
+ panic(fmt.Sprintf("wrong FP register: %v", inst))
+ }
}
}
}
@@ -79,7 +96,7 @@
// Move addressing mode into opcode suffix.
suffix := ""
switch inst.Op &^ 15 {
- case LDR_EQ, LDRB_EQ, LDRSB_EQ, LDRH_EQ, LDRSH_EQ, STR_EQ, STRB_EQ, STRH_EQ:
+ case LDR_EQ, LDRB_EQ, LDRSB_EQ, LDRH_EQ, LDRSH_EQ, STR_EQ, STRB_EQ, STRH_EQ, VLDR_EQ, VSTR_EQ:
mem, _ := inst.Args[1].(Mem)
switch mem.Mode {
case AddrOffset, AddrLDM:
@@ -133,6 +150,19 @@
op = "MOVHU" + op[4:] + suffix
case LDRSH_EQ:
op = "MOVHS" + op[5:] + suffix
+ case VLDR_EQ:
+ switch {
+ case strings.HasPrefix(args[1], "D"): // VLDR.F64
+ op = "MOVD" + op[4:] + suffix
+ args[1] = "F" + args[1][1:] // Dx -> Fx
+ case strings.HasPrefix(args[1], "S"): // VLDR.F32
+ op = "MOVF" + op[4:] + suffix
+ if inst.Args[0].(Reg)&1 == 0 { // Sx -> Fy, y = x/2, if x is even
+ args[1] = fmt.Sprintf("F%d", (inst.Args[0].(Reg)-S0)/2)
+ }
+ default:
+ panic(fmt.Sprintf("wrong FP register: %v", inst))
+ }
case STR_EQ:
op = "MOVW" + op[3:] + suffix
@@ -143,6 +173,20 @@
case STRH_EQ:
op = "MOVH" + op[4:] + suffix
args[0], args[1] = args[1], args[0]
+ case VSTR_EQ:
+ switch {
+ case strings.HasPrefix(args[1], "D"): // VSTR.F64
+ op = "MOVD" + op[4:] + suffix
+ args[1] = "F" + args[1][1:] // Dx -> Fx
+ case strings.HasPrefix(args[1], "S"): // VSTR.F32
+ op = "MOVF" + op[4:] + suffix
+ if inst.Args[0].(Reg)&1 == 0 { // Sx -> Fy, y = x/2, if x is even
+ args[1] = fmt.Sprintf("F%d", (inst.Args[0].(Reg)-S0)/2)
+ }
+ default:
+ panic(fmt.Sprintf("wrong FP register: %v", inst))
+ }
+ args[0], args[1] = args[1], args[0]
}
if args != nil {
diff --git a/arm/armasm/testdata/decode.txt b/arm/armasm/testdata/decode.txt
index 24b6a93..413280c 100644
--- a/arm/armasm/testdata/decode.txt
+++ b/arm/armasm/testdata/decode.txt
@@ -1228,3 +1228,27 @@
58f07ff5| 1 plan9 DMB $8
49f07ff5| 1 plan9 DSB $9
62f07ff5| 1 plan9 ISB $2
+009a94ed| 1 plan9 MOVF (R4), F9
+009ad4ed| 1 plan9 MOVF (R4), S19
+009b940d| 1 plan9 MOVD.EQ (R4), F9
+003a9a1d| 1 plan9 MOVF.NE (R10), F3
+003ada1d| 1 plan9 MOVF.NE (R10), S7
+003b9aed| 1 plan9 MOVD (R10), F3
+089a93ed| 1 plan9 MOVF 0x20(R3), F9
+089ad3ed| 1 plan9 MOVF 0x20(R3), S19
+089b940d| 1 plan9 MOVD.EQ 0x20(R4), F9
+083a1a1d| 1 plan9 MOVF.NE -0x20(R10), F3
+083a5a1d| 1 plan9 MOVF.NE -0x20(R10), S7
+083b1aed| 1 plan9 MOVD -0x20(R10), F3
+009a84ed| 1 plan9 MOVF F9, (R4)
+009ac4ed| 1 plan9 MOVF S19, (R4)
+009b840d| 1 plan9 MOVD.EQ F9, (R4)
+003a8a1d| 1 plan9 MOVF.NE F3, (R10)
+003aca1d| 1 plan9 MOVF.NE S7, (R10)
+003b8aed| 1 plan9 MOVD F3, (R10)
+089a83ed| 1 plan9 MOVF F9, 0x20(R3)
+089ac3ed| 1 plan9 MOVF S19, 0x20(R3)
+089b840d| 1 plan9 MOVD.EQ F9, 0x20(R4)
+083a0a1d| 1 plan9 MOVF.NE F3, -0x20(R10)
+083a4a1d| 1 plan9 MOVF.NE S7, -0x20(R10)
+083b0aed| 1 plan9 MOVD F3, -0x20(R10)