aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShenghou Ma <minux@golang.org>2016-12-09 00:13:43 -0500
committerMinux Ma <minux@golang.org>2016-12-12 23:25:06 +0000
commit9fe2291efdfd6257b97a3271b1145b67a3e7089d (patch)
tree8a4c07802984842197bf187f05b3ac8c966e626b /src
parentbc61026c3f60d0d449e1cb292ef202daa1c2d019 (diff)
downloadgo-9fe2291efdfd6257b97a3271b1145b67a3e7089d.tar.xz
cmd/internal/obj/mips: replace MOVD with MOVF on 32-bit to avoid unaligned memory access
This is the simplest CL that I can make for Go 1.8. For Go 1.9, we can revisit it and optimize the redundant address generation instructions or just fix #599 instead. Fixes #18140. Change-Id: Ie4804ab0e00dc6bb318da2bece8035c7c71caac3 Reviewed-on: https://go-review.googlesource.com/34193 Run-TryBot: Minux Ma <minux@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/cmd/internal/obj/mips/obj0.go38
1 files changed, 38 insertions, 0 deletions
diff --git a/src/cmd/internal/obj/mips/obj0.go b/src/cmd/internal/obj/mips/obj0.go
index 221fd428a3..12cfb31377 100644
--- a/src/cmd/internal/obj/mips/obj0.go
+++ b/src/cmd/internal/obj/mips/obj0.go
@@ -32,6 +32,7 @@ package mips
import (
"cmd/internal/obj"
"cmd/internal/sys"
+ "encoding/binary"
"fmt"
"math"
)
@@ -533,6 +534,43 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
}
}
+ if ctxt.Mode&Mips32 != 0 {
+ // rewrite MOVD into two MOVF in 32-bit mode to avoid unaligned memory access
+ for p = cursym.Text; p != nil; p = p1 {
+ p1 = p.Link
+
+ if p.As != AMOVD {
+ continue
+ }
+ if p.From.Type != obj.TYPE_MEM && p.To.Type != obj.TYPE_MEM {
+ continue
+ }
+
+ p.As = AMOVF
+ q = ctxt.NewProg()
+ *q = *p
+ q.Link = p.Link
+ p.Link = q
+ p1 = q.Link
+
+ var regOff int16
+ if ctxt.Arch.ByteOrder == binary.BigEndian {
+ regOff = 1 // load odd register first
+ }
+ if p.From.Type == obj.TYPE_MEM {
+ reg := REG_F0 + (p.To.Reg-REG_F0)&^1
+ p.To.Reg = reg + regOff
+ q.To.Reg = reg + 1 - regOff
+ q.From.Offset += 4
+ } else if p.To.Type == obj.TYPE_MEM {
+ reg := REG_F0 + (p.From.Reg-REG_F0)&^1
+ p.From.Reg = reg + regOff
+ q.From.Reg = reg + 1 - regOff
+ q.To.Offset += 4
+ }
+ }
+ }
+
if nosched {
// if we don't do instruction scheduling, simply add
// NOP after each branch instruction.